Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6b51428
feat: add prompt shortcut storage and settings [risk:high]
Leeeon233 Sep 5, 2026
092c559
feat: rework Prompt Shortcut settings and local-first publication [ri…
Leeeon233 Sep 6, 2026
f893905
fix: tighten the Prompt Shortcut editor layout [risk:medium]
Leeeon233 Sep 6, 2026
b1aa3d1
fix: grow a variable default from one row [risk:low]
Leeeon233 Sep 6, 2026
49e4ae4
feat: add Prompt Shortcut invocation and sending [risk:high]
Leeeon233 Sep 6, 2026
e1ee4ff
fix: keep mention menus interactive inside dialogs [risk:medium]
Leeeon233 Sep 6, 2026
d204be5
feat: rework the Shortcut parameter tray and drop expand-and-edit [ri…
Leeeon233 Sep 6, 2026
e128e02
fix: give the Shortcut list and parameter tray a right column [risk:low]
Leeeon233 Sep 6, 2026
201b9ba
feat: give a Prompt Shortcut its own emoji [risk:medium]
Leeeon233 Sep 6, 2026
88dadb4
feat: carry filled values in a Shortcut chip and stay optimistic [ris…
Leeeon233 Sep 7, 2026
df8e150
feat!: remove Prompt Shortcut variables [risk:high]
Sep 10, 2026
24c04c4
feat: gate Prompt Shortcuts behind a developer beta switch [risk:medium]
Leeeon233 Sep 10, 2026
665a216
fix: clear only the accepted landing Shortcut draft [risk:high]
Leeeon233 Sep 10, 2026
e2d7a21
chore: merge main into Prompt Shortcut branch [risk:high]
Leeeon233 Sep 10, 2026
362a08f
chore: format merged landing composer [risk:low]
Leeeon233 Sep 10, 2026
a4e4e11
refactor: remove obsolete Prompt Shortcut paths [risk:high]
Leeeon233 Sep 10, 2026
3aca38b
chore: trim temporary Prompt Shortcut test and story coverage [risk:m…
Leeeon233 Sep 10, 2026
9e33cf4
fix: hide Prompt Shortcut publication warning [risk:low]
Leeeon233 Sep 11, 2026
5d9e150
fix: hide Prompt Shortcut retry button [risk:low]
Leeeon233 Sep 11, 2026
85ef06d
fix: remove Prompt Shortcut author display [risk:low]
Leeeon233 Sep 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions .agents/docs/ui-mentions.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ lives in its `README.md`.
expensive one, which is why `getCandidates` must stay lazy and a bare `@` calls
none of them.
3. **Commit.** The candidate's `insertText` is what the user sees in the prompt;
the committed *range* is what carries structured identity (a session id, a Role
the committed _range_ is what carries structured identity (a session id, a Role
id) that no text form could.
4. **Draft persistence and hydration.** Ranges are stored beside the draft, and
rebuilding them from text is only a fallback.
Expand Down Expand Up @@ -52,7 +52,7 @@ every return looking like plain text — and never came back at all if the sourc
never loaded. Hence persistence of the narrow `PersistedMentionRange`: the live
range carries callbacks, which `JSON.stringify` writes as `{}`.

`mergeHydratedMentions` rejects an *overlapping* range, not just an exact
`mergeHydratedMentions` rejects an _overlapping_ range, not just an exact
duplicate, because a session and a path are now the same shape: two sources can
each claim `@fix-ci` at different ends, and only rejecting overlaps keeps the
restored range authoritative.
Expand All @@ -71,8 +71,6 @@ default and reads storage in `onMount`, so latching at mount latches `''` and th

A session mention commits as a plain `@<title-slug>`: the old `session:` marker
was only ever an anchor for the before-send rewrite, and the user had to read it.
It is still the only type whose displayed text differs from what the agent
receives.

Dropping the marker is why hydration has to break a tie:
`hydrateSessionMentionsFromText` skips any token the file source already knows.
Expand Down Expand Up @@ -133,3 +131,16 @@ instruction — so the neutral rows were a second description that had already
drifted (printing stored ids raw, labelling the permission mode "Reasoning"). That
pane is desktop-only: the docked mobile strip is too narrow and has no hover to
preview with.

## Prompt Shortcuts

The Slash menu has separate ACP-command and Shortcut sources. Shortcut discovery
reads the index; selecting a result loads and freezes its body before committing
an inline range. Opaque payload history preserves that snapshot through Undo.
`compileShortcutPrompt` combines ordinary rewrites with `expandShortcut` output
in original coordinates, producing the final text and spans together.

Template editors reuse these primitives with explicit author-selected scope and
exclude Sessions, recursive Shortcuts and ACP commands. Product constraints live
in the [mention rules](../../packages/components/src/components/mentions/AGENTS.md)
and [settings rules](../../packages/components/src/components/settings/AGENTS.md).
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Prompt Shortcut composer integration

Status: implemented
Translation: pending
PR: https://github.com/LodyAI/Lody/pull/575

## Abstract

Prompt Shortcuts add frozen inline invocations to the composer while the main
branch introduces submission ownership and stable textarea hydration. Their
integration keeps the existing submission lifecycle and window owner behavior,
and preserves Shortcut preparation cancellation and identity-scoped recovery.
Accepted submissions must clear only their own Shortcut checkpoint, including
when completion arrives after switching composers. Live dependency resolution
and gateway end-to-end behavior remain unverified.

## Decisions

- `MainLayout` retains workspace window ownership for singleton background work
and mounts one readiness- and developer-gated Shortcut provider.
- Session submission uses `useComposerSubmission`; Shortcut compilation runs
before the existing accepted-message boundary. Ordinary draft owners remain
responsible for text and ordinary mention persistence.
- Mention preparation keeps a generation ticket, independent of query text.
Main's stable textarea and hydration reset coexist with identity changes that
retire pending Shortcut preparation. Unavailable Role candidates and exact
unavailable Shortcut matches remain disabled with reasons.
- Clearing only the ordinary draft after a retired submission leaves an old
Shortcut checkpoint eligible for empty-composer recovery. Cleanup therefore
needs the submitted checkpoint's ownership, not text equality or an
unconditional deletion that can erase a replacement invocation.

## Cleanup and coverage scope

Ablation removed the obsolete prototype, unused editable annotations/replacement
API, test-only composer compiler and publication helper. Negative controls showed
that disabling semantic history loses snapshots and accepting stale preparation
inserts late chips; those protections remain.

The feature is temporary. Its dedicated tests, Storybook stories and additions to
shared test fixtures were subsequently removed to reduce maintenance scope.
General mention preparation/modal and existing composer tests remain. Earlier
ablation results are historical evidence, not a claim of retained feature coverage.

## Verification limits

Checks use the outer dependency installation with test environment variables
isolated. Its affected-check wrapper remains blocked by the existing indexed OSS
revision mismatch; the standalone public E2E package is not in that dependency
graph. Production mobile bundling previously exhausted the Node heap. Live
dependency resolution, full production builds and gateway E2E remain unverified.
70 changes: 66 additions & 4 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3821,7 +3821,7 @@
"mention.category.issue.label": "Issues",
"mention.category.pr.label": "Pull Requests",
"mention.category.skill.label": "Skills",
"mention.category.command.label": "Commands",
"mention.category.command.label": "Agent Commands",
"mention.menu.back": "Back",
"mention.menu.noResults": "No results",
"mention.menu.loading": "Loading…",
Expand Down Expand Up @@ -3927,11 +3927,9 @@
"settings.agentRoles.issues.modelUnsupported": "model “{{value}}”",
"settings.agentRoles.issues.optionUnsupported": "option “{{option}}”",
"settings.agentRoles.issues.optionValueUnsupported": "option “{{option}}” value “{{value}}”",
"settings.agentRoles.form.emoji": "Emoji",
"settings.agentRoles.errors.nameTaken": "Another role already uses this name.",
"emojiPicker.empty": "No emoji found.",
"emojiPicker.placeholder": "Select an emoji…",
"settings.agentRoles.form.emojiReset": "Reset to {{emoji}}",
"settings.agentRoles.form.memory": "Memory",
"settings.agentRoles.form.memoryHint": "Not supported yet. Every session this role creates starts fresh — it remembers nothing from earlier ones.",
"sessions.fileViewer.pathCopyFailed": "Failed to copy file path",
Expand Down Expand Up @@ -3963,5 +3961,69 @@
"sessions.fileViewer.pageUnavailable": "File changed or is unavailable. Reopen the preview.",
"sessions.copyContextMarkdown": "Copy context as Markdown",
"sessions.copyContextMarkdownHint": "Copy the conversation through this message",
"sessions.copyContextIncomplete": "The last response was still generating when copied."
"sessions.copyContextIncomplete": "The last response was still generating when copied.",
"settings.promptShortcuts.intro": "Saved Prompts you can call with a slash command. Each one says where it applies; a Shortcut with nothing set works anywhere in this workspace. Private until you share it.",
"settings.promptShortcuts.new": "New Prompt Shortcut",
"settings.promptShortcuts.empty": "No Prompt Shortcuts yet. Save a Prompt you retype often and call it with /.",
"settings.promptShortcuts.private": "Private",
"settings.promptShortcuts.shared": "Shared",
"settings.promptShortcuts.readOnly": "Read-only",
"settings.promptShortcuts.workspaceScope": "Workspace",
"settings.promptShortcuts.needsAttention": "A reference is outside this scope",
"settings.promptShortcuts.delete": "Delete shortcut",
"settings.promptShortcuts.deleteTitle": "Delete Prompt Shortcut",
"settings.promptShortcuts.deleteHelp": "Delete “{{name}}”? Prompts already inserted into drafts or sent messages are unchanged.",
"settings.promptShortcuts.edit": "Edit Prompt Shortcut",
"settings.promptShortcuts.view": "Prompt Shortcut",
"settings.promptShortcuts.editorHelp": "Saved to this workspace and sent as one message.",
"settings.promptShortcuts.readOnlyHelp": "Shared by another member. Only its author can change it.",
"settings.promptShortcuts.name": "Name",
"settings.promptShortcuts.command": "Slash command",
"settings.promptShortcuts.commandPlaceholder": "review-pr",
"settings.promptShortcuts.description": "Description (optional)",
"settings.promptShortcuts.descriptionPlaceholder": "Description — shown in the / menu",
"settings.promptShortcuts.scope": "Applies to",
"settings.promptShortcuts.project": "Project",
"settings.promptShortcuts.machine": "Machine",
"settings.promptShortcuts.agent": "Agent",
"settings.promptShortcuts.none": "None",
"settings.promptShortcuts.thisMachine": "Limit to this machine",
"settings.promptShortcuts.mentionScope": "Not available for the scope set in “Applies to”.",
"settings.promptShortcuts.mentionScopeMissing": "Set {{axes}} in “Applies to” first.",
"settings.promptShortcuts.prompt": "Prompt",
"settings.promptShortcuts.promptHelp": "One message. @ mentions a file or Role, $ a skill, # an issue. The selectors below say where this Shortcut can be called and what @ completes against — None on every axis means anywhere in this workspace.",
"settings.promptShortcuts.promptPlaceholder": "Write the prompt you would otherwise retype.",
"settings.promptShortcuts.repairScope": "Restore the matching scope or remove these mentions before saving.",
"settings.promptShortcuts.requiredAxes": "Requires matching {{axes}}",
"settings.promptShortcuts.share": "Share with workspace",
"settings.promptShortcuts.shareHint": "Off by default. Sharing is separate from where the Shortcut applies.",
"settings.promptShortcuts.shareWarning": "Workspace members can read and copy this Prompt and its reference labels. Making it private later cannot remove copies they already received.",
"settings.promptShortcuts.create": "Create",
"settings.promptShortcuts.invalid": "Could not save. Check the name, command, mention scope and size limits, then try again.",
"settings.tabs.promptShortcuts": "Prompt Shortcuts",
"settings.categories.promptShortcuts.description": "Reusable Prompts and mentions",
"settings.emoji.label": "Emoji",
"settings.emoji.reset": "Reset to {{emoji}}",
"mention.category.promptShortcut.label": "Prompt Shortcuts",
"promptShortcut.unverified": "Dependencies cannot be verified yet.",
"promptShortcut.checking": "Checking availability…",
"promptShortcut.projectMismatch": "Requires a different project.",
"promptShortcut.machineMismatch": "Requires a different machine.",
"promptShortcut.providerMismatch": "Requires a different agent.",
"promptShortcut.machineOffline": "Required machine is offline.",
"promptShortcut.missingScope": "A reference requires an explicit scope.",
"promptShortcut.scopeMismatch": "A reference does not match the saved scope.",
"promptShortcut.permissionDenied": "A required reference is no longer accessible.",
"promptShortcut.dependencyMissing": "A required reference is unavailable.",
"promptShortcut.private": "Private",
"promptShortcut.shared": "Shared",
"promptShortcut.loadingBody": "Loading Shortcut…",
"promptShortcut.versionChanged": "Shortcut changed. Select it again to retry.",
"promptShortcut.bodyOffline": "Body is not available offline. Reconnect and select again.",
"promptShortcut.loadFailed": "Could not load Shortcut. Select it again to retry.",
"promptShortcut.draftSaveFailed": "Could not save this Shortcut draft locally. Keep this composer open and retry your edit.",
"promptShortcut.promptTooLarge": "Expanded prompt exceeds the size limit.",
"promptShortcut.invalidDraft": "This Shortcut draft is incomplete. Remove the affected chip and insert it again.",
"settings.beta.promptShortcutsHelper": "Create reusable prompts and insert them with /. In development — expect rough edges.",
"settings.promptShortcuts.disabled": "Enable Prompt Shortcuts under Developer mode in Settings → About to use this feature."
}
70 changes: 66 additions & 4 deletions locales/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -3821,7 +3821,7 @@
"mention.category.issue.label": "Issues",
"mention.category.pr.label": "Pull Requests",
"mention.category.skill.label": "Skills",
"mention.category.command.label": "命令",
"mention.category.command.label": "Agent 命令",
"mention.menu.back": "返回",
"mention.menu.noResults": "没有结果",
"mention.menu.loading": "加载中…",
Expand Down Expand Up @@ -3927,11 +3927,9 @@
"settings.agentRoles.issues.modelUnsupported": "模型“{{value}}”",
"settings.agentRoles.issues.optionUnsupported": "选项“{{option}}”",
"settings.agentRoles.issues.optionValueUnsupported": "选项“{{option}}”的值“{{value}}”",
"settings.agentRoles.form.emoji": "Emoji",
"settings.agentRoles.errors.nameTaken": "另一个角色已经使用了这个名称。",
"emojiPicker.empty": "没有找到 Emoji。",
"emojiPicker.placeholder": "选择一个 Emoji…",
"settings.agentRoles.form.emojiReset": "恢复为 {{emoji}}",
"settings.agentRoles.form.memory": "记忆",
"settings.agentRoles.form.memoryHint": "暂不支持。该角色创建的每个会话都从零开始,不会记住此前会话中的任何内容。",
"sessions.fileViewer.pathCopyFailed": "复制文件路径失败",
Expand Down Expand Up @@ -3963,5 +3961,69 @@
"sessions.fileViewer.pageUnavailable": "文件已更改或无法读取,请重新打开预览。",
"sessions.copyContextMarkdown": "复制上下文为 Markdown",
"sessions.copyContextMarkdownHint": "复制截至此条的对话",
"sessions.copyContextIncomplete": "复制时,最后一条回复仍在生成。"
"sessions.copyContextIncomplete": "复制时,最后一条回复仍在生成。",
"settings.promptShortcuts.intro": "保存可以用斜杠命令调用的 Prompt。每条都会写明适用范围;三项都不设置就表示在本工作区内任何地方都能用。默认私有,除非你选择共享。",
"settings.promptShortcuts.new": "新建 Prompt Shortcut",
"settings.promptShortcuts.empty": "还没有 Prompt Shortcut。把常写的 Prompt 存下来,用 / 调用。",
"settings.promptShortcuts.private": "私有",
"settings.promptShortcuts.shared": "已共享",
"settings.promptShortcuts.readOnly": "只读",
"settings.promptShortcuts.workspaceScope": "整个工作区",
"settings.promptShortcuts.needsAttention": "有引用超出适用范围",
"settings.promptShortcuts.delete": "删除 Shortcut",
"settings.promptShortcuts.deleteTitle": "删除 Prompt Shortcut",
"settings.promptShortcuts.deleteHelp": "确定删除“{{name}}”吗?已经插入草稿或已发送消息中的内容不会改变。",
"settings.promptShortcuts.edit": "编辑 Prompt Shortcut",
"settings.promptShortcuts.view": "Prompt Shortcut",
"settings.promptShortcuts.editorHelp": "保存在本工作区,调用时作为一条消息发送。",
"settings.promptShortcuts.readOnlyHelp": "由其他成员共享,只有作者本人可以修改。",
"settings.promptShortcuts.name": "名称",
"settings.promptShortcuts.command": "斜杠命令",
"settings.promptShortcuts.commandPlaceholder": "review-pr",
"settings.promptShortcuts.description": "描述(可选)",
"settings.promptShortcuts.descriptionPlaceholder": "描述 - 显示在 / 菜单中",
"settings.promptShortcuts.scope": "适用范围",
"settings.promptShortcuts.project": "项目",
"settings.promptShortcuts.machine": "机器",
"settings.promptShortcuts.agent": "Agent",
"settings.promptShortcuts.none": "None",
"settings.promptShortcuts.thisMachine": "仅限本机",
"settings.promptShortcuts.mentionScope": "当前“适用范围”下无法使用这种引用。",
"settings.promptShortcuts.mentionScopeMissing": "请先在“适用范围”里设置{{axes}}。",
"settings.promptShortcuts.prompt": "Prompt",
"settings.promptShortcuts.promptHelp": "只发送一条消息。@ 引用文件或 Role,$ 引用 Skill,# 引用 Issue。下面三个选择器决定它能在哪里调用,也决定 @ 从哪里补全;三项都为 None 表示本工作区内任意位置。",
"settings.promptShortcuts.promptPlaceholder": "写下你平时会反复输入的 Prompt。",
"settings.promptShortcuts.repairScope": "保存前请恢复匹配的适用范围,或移除以下引用。",
"settings.promptShortcuts.requiredAxes": "需要匹配的{{axes}}范围",
"settings.promptShortcuts.share": "共享给工作区",
"settings.promptShortcuts.shareHint": "默认关闭。共享与适用范围是两件独立的事。",
"settings.promptShortcuts.shareWarning": "工作区成员可以阅读和复制此 Prompt 及其引用标签。之后改为私有也无法撤回他们已经收到的副本。",
"settings.promptShortcuts.create": "创建",
"settings.promptShortcuts.invalid": "无法保存。请检查名称、命令、引用范围和大小限制后重试。",
"settings.tabs.promptShortcuts": "Prompt Shortcuts",
"settings.categories.promptShortcuts.description": "可复用的 Prompt 与提及",
"settings.emoji.label": "Emoji",
"settings.emoji.reset": "恢复为 {{emoji}}",
"mention.category.promptShortcut.label": "提示词快捷方式",
"promptShortcut.unverified": "暂时无法验证依赖。",
"promptShortcut.checking": "正在检查可用性…",
"promptShortcut.projectMismatch": "需要切换到指定项目。",
"promptShortcut.machineMismatch": "需要切换到指定机器。",
"promptShortcut.providerMismatch": "需要切换到指定 Agent。",
"promptShortcut.machineOffline": "所需机器已离线。",
"promptShortcut.missingScope": "引用缺少明确的适用范围。",
"promptShortcut.scopeMismatch": "引用与已保存的适用范围不匹配。",
"promptShortcut.permissionDenied": "已无权访问所需引用。",
"promptShortcut.dependencyMissing": "所需引用不可用。",
"promptShortcut.private": "私有",
"promptShortcut.shared": "共享",
"promptShortcut.loadingBody": "正在加载快捷方式…",
"promptShortcut.versionChanged": "快捷方式版本已变化,请重新选择以重试。",
"promptShortcut.bodyOffline": "离线时无法读取正文,请联网后重新选择。",
"promptShortcut.loadFailed": "无法加载快捷方式,请重新选择以重试。",
"promptShortcut.draftSaveFailed": "无法在本地保存此 Shortcut 草稿。请保持输入框打开并重试编辑。",
"promptShortcut.promptTooLarge": "展开后的 Prompt 超过大小限制。",
"promptShortcut.invalidDraft": "此 Shortcut 草稿不完整。请删除有问题的 chip 后重新插入。",
"settings.beta.promptShortcutsHelper": "创建可复用的提示词,通过 / 插入。功能开发中,体验可能不完善。",
"settings.promptShortcuts.disabled": "请在设置 → 关于的开发者模式下开启 Prompt Shortcuts。"
}
Loading
Loading