Skip to content

fix: handle OpenAI tool content and stable secret ids#1374

Merged
chhoumann merged 2 commits into
masterfrom
fix/ai-tool-content-secret-ids
Jun 17, 2026
Merged

fix: handle OpenAI tool content and stable secret ids#1374
chhoumann merged 2 commits into
masterfrom
fix/ai-tool-content-secret-ids

Conversation

@chhoumann

@chhoumann chhoumann commented Jun 17, 2026

Copy link
Copy Markdown
Owner

Fix two related runtime issues from the latest user-script secret work.

The first commit fixes the reported OpenAI 400 response:

Invalid value for 'content': expected a string, got null.

OpenAI assistant messages with tool calls still need string content, so the OpenAI provider mapping now sends an empty string when normalized assistant content is absent instead of null.

The second commit adds optional id support for user-script secret options. Script authors can keep SecretStorage references stable across visible label changes, while existing scripts continue to fall back to the option label. The migration path also reattaches an existing id-backed secret under a renamed option label.

Verification:

  • pnpm run test -- src/ai/tools/providerToolMapping.test.ts src/utils/userScriptSecrets.test.ts src/gui/MacroGUIs/UserScriptSettingsModal.test.ts src/engine/MacroChoiceEngine.entry.test.ts src/engine/SingleMacroEngine.member-access.test.ts (ran full Vitest suite: 225 passed, 5 skipped)
  • pnpm run build-with-lint
  • git diff --check master...HEAD
  • Obsidian dev-vault smoke before committing: plugin reload, stable secret-id migration, option-label rename reattach, no captured runtime errors

Summary by CodeRabbit

  • Documentation

    • Updated documentation for secret settings to explain the optional id field, which keeps stored secrets stable when renaming user-visible setting labels.
  • Tests

    • Added comprehensive test coverage for secret ID handling, migration scenarios, and label renaming without data loss.

OpenAI rejects assistant messages whose content is null, including tool-call messages. Preserve an empty string when the normalized message has no content so the request body stays valid.
Allow user-script secret options to provide an optional id for SecretStorage references. This keeps saved secrets stable across visible setting label changes while retaining generated IDs as the fallback.
@chhoumann chhoumann marked this pull request as ready for review June 17, 2026 08:55
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying quickadd with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0b26d76
Status: ✅  Deploy successful!
Preview URL: https://414b91fa.quickadd.pages.dev
Branch Preview URL: https://fix-ai-tool-content-secret-i.quickadd.pages.dev

View logs

@chhoumann chhoumann merged commit 54582b3 into master Jun 17, 2026
8 checks passed
@chhoumann chhoumann deleted the fix/ai-tool-content-secret-ids branch June 17, 2026 08:58

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0b26d7655e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

for (const settingName of secretOptionNames) {
for (const [settingName, option] of secretOptionEntries) {
const value = command.settings?.[settingName];
if (isUserScriptSecretRef(value)) continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Migrate existing refs when an option id is added

When a script adds a non-label id to a secret option that users have already saved, value is already a UserScriptSecretRef pointing at the old label-derived key, so this early continue prevents it from ever being moved to the option-derived stable key. The modal save path also preserves that existing ref, so a later label rename using the documented id will not find the user's saved secret and will require re-entry. Consider migrating/copying refs whose secretRef differs from buildUserScriptSecretId(command, settingName, option) when the old secret can be read.

Useful? React with 👍 / 👎.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6423a12f-d326-462d-9459-592ea43656a6

📥 Commits

Reviewing files that changed from the base of the PR and between 288a1b5 and 0b26d76.

📒 Files selected for processing (8)
  • docs/docs/Advanced/scriptsWithSettings.md
  • docs/docs/UserScripts.md
  • src/ai/tools/providerToolMapping.test.ts
  • src/ai/tools/providerToolMapping.ts
  • src/gui/MacroGUIs/UserScriptSettingsModal.test.ts
  • src/gui/MacroGUIs/UserScriptSettingsModal.ts
  • src/utils/userScriptSecrets.test.ts
  • src/utils/userScriptSecrets.ts

📝 Walkthrough

Walkthrough

Adds an optional id field to user-script secret options for stable SecretStorage keys independent of visible label changes. Rewrites secret ID generation with hashing/truncation helpers, updates buildUserScriptSecretId and storeUserScriptSecret signatures, reworks migrateUserScriptSecretSettings, wires the option through the settings modal, and adds documentation. Also fixes OpenAI assistant message content to always be a string ("") instead of null.

Changes

Stable Secret Option ID Support

Layer / File(s) Summary
Secret ID type, constants, hashing, and fitSecretId
src/utils/userScriptSecrets.ts
Adds MAX_SECRET_ID_LENGTH/SECRET_ID_HASH_LENGTH constants, extends UserScriptOptionDefinition with optional id, replaces simple concatenation with hashing/truncation helpers and fitSecretId that compresses IDs into a fixed-length budget, and adds getSecretSettingId/hasStableSecretId internal helpers.
Updated public API and migration loop
src/utils/userScriptSecrets.ts, src/utils/userScriptSecrets.test.ts
Updates buildAvailableSecretRef and storeUserScriptSecret to accept an optional option parameter. Refactors migrateUserScriptSecretSettings to iterate [settingName, option] entries, conditionally migrate empty values only when a stable ID exists, remove duplicate secret refs, and pass option through for non-empty plaintext migrations. New tests cover stable ID generation, 64-char limit enforcement, collision fallback, and migration reattachment when labels change.
Modal Option type and storeUserScriptSecret wiring
src/gui/MacroGUIs/UserScriptSettingsModal.ts, src/gui/MacroGUIs/UserScriptSettingsModal.test.ts
Adds optional id to the Option type, passes this.settings.options?.[name] to storeUserScriptSecret when saving a secret, and adds a modal test verifying the stable secret option ID is used as the storage key.
Docs for the optional id field
docs/docs/UserScripts.md, docs/docs/Advanced/scriptsWithSettings.md
Updates secret option examples to show the id field and explains stable-key semantics and fallback behavior.

OpenAI Assistant Message Content Normalization

Layer / File(s) Summary
content ?? "" fix and test assertion
src/ai/tools/providerToolMapping.ts, src/ai/tools/providerToolMapping.test.ts
Changes m.content || null to m.content ?? "" so assistant message content is always a string; adds a test assertion that it is "" when a tool call is present.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • chhoumann/quickadd#1373: Modifies the same src/utils/userScriptSecrets.ts pipeline—secret ID generation, migration, and storeUserScriptSecret/secret refs—which this PR extends with the optional stable option.id support.

Suggested labels

released

🐇 A rabbit hops with joy today,
Secret keys shall never stray!
Give your option a stable id,
And renaming labels? Nothing to fear did.
The hash fits snug, the ref holds tight —
Sixty-four chars, perfectly right! 🔑✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ai-tool-content-secret-ids

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant