Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 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
54a9cdf
chore: remove PR tests and documentation [risk:low]
Leeeon233 Sep 11, 2026
9cc11cc
chore: merge latest main into Prompt Shortcuts [risk:medium]
Leeeon233 Sep 11, 2026
e8a24f8
refactor: insert Shortcut text directly into composer [risk:medium]
Leeeon233 Sep 11, 2026
95dfd48
chore: merge main and preserve both cloud APIs [risk:medium]
Leeeon233 Sep 11, 2026
cf07f3f
fix: keep mention selection callback void [risk:medium]
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
70 changes: 66 additions & 4 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3851,7 +3851,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 @@ -3957,11 +3957,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 @@ -3993,5 +3991,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 @@ -3851,7 +3851,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 @@ -3957,11 +3957,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 @@ -3993,5 +3991,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。"
}
63 changes: 63 additions & 0 deletions packages/cloud-api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,69 @@ type SeatInvitePreview =
};

export type CloudApi = {
promptShortcuts: {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add the required Spec and Agent Note

This introduces a public cloud protocol and new durable persistence, publication, access, and deletion guarantees, but the changed-file list contains neither an owning draft Spec nor an Agent Note. Without those records, the intended cross-client and cloud contracts are not reviewable or traceable; add both in this change as required by the repository’s governance rules.

AGENTS.md reference: AGENTS.md:L15-L21

Useful? React with 👍 / 👎.

stageDocument: Mutation<
{
workspaceId: string;
ownerUserId: string;
shortcutId: string;
bodyDocId: string;
visibility: 'private' | 'workspace';
},
{ bodyDocId: string; status: 'staged' | 'active' }
>;
activateDocument: Mutation<
{
workspaceId: string;
bodyDocId: string;
previousBodyDocId: string | null;
previousRevision: string | null;
revision: string;
slug: string;
indexBytes: number;
},
null
>;
settleDocument: Mutation<
{
workspaceId: string;
shortcutId: string;
bodyDocId: string;
visibility: 'private' | 'workspace';
},
'active' | 'cancelled'
>;
revokeShortcut: Mutation<
{
workspaceId: string;
shortcutId: string;
bodyDocId: string;
visibility: 'private' | 'workspace';
},
null
>;
listAccessibleDocuments: Query<
{ workspaceId: string },
Array<{
shortcutId: string;
bodyDocId: string;
ownerUserId: string;
visibility: 'private' | 'workspace';
revision: string | null;
deleted?: boolean;
}>
>;
getStreamToken: Action<
{
workspaceId: string;
target:
| { kind: 'index'; ownerUserId: string; visibility: 'private' | 'workspace' }
| { kind: 'body'; bodyDocId: string };
write: boolean;
},
{ token: string; expiresIn: number; gatewayBaseUrl: string; streamId: string }
>;
};
activity: {
recordMyWorkspaceDailyActiveUser: Mutation<
{ workspaceId: string },
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/atoms/local-storage-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export const setWorkspaceReposCacheAtom = atom(

export interface ChatLandingSessionState {
prompt: string;
/** Ownership only for Shortcut checkpoints; ordinary drafts retain their existing behavior. */
shortcutWorkspaceId?: string;
pastedTextDrafts?: PastedTextDraft[];
/**
* Mention ranges for `prompt`. Stored so a returning draft shows its mentions
Expand Down
27 changes: 16 additions & 11 deletions packages/components/src/atoms/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import { atomWithStorage } from 'jotai/utils';
import type { MachineId, SupportedLanguage } from '@lody/shared';
import type { MobileKeyboardAction } from '@/lib/mobile-keyboard-action';
import { isSymbolFontFamily } from '@/lib/local-fonts';
import {
SETTINGS_DEFAULT_TAB,
type SettingsTabId,
} from '@/components/settings/settings-tabs';
import { SETTINGS_DEFAULT_TAB, type SettingsTabId } from '@/components/settings/settings-tabs';

export const languageAtom = atomWithStorage<SupportedLanguage>('lody-language', 'en');

Expand Down Expand Up @@ -131,10 +128,7 @@ export const electronSessionCompletionNotificationsEnabledAtom = atomWithStorage
// (e.g. an unwrapped Markdown paragraph) stays readable without horizontal
// scrolling — especially on mobile. Shared by every SessionMonacoTextViewer
// mount via the viewer reading this atom directly.
export const fileViewerWordWrapAtom = atomWithStorage<boolean>(
'lody-file-viewer-word-wrap',
true
);
export const fileViewerWordWrapAtom = atomWithStorage<boolean>('lody-file-viewer-word-wrap', true);

// Mobile composer keyboard return key behavior.
export const mobileKeyboardActionAtom = atomWithStorage<MobileKeyboardAction>(
Expand Down Expand Up @@ -201,9 +195,7 @@ export function readTasksFeatureEnabledFromStorage(): boolean {
return false;
}
try {
const developerMode = JSON.parse(
localStorage.getItem(DEVELOPER_MODE_STORAGE_KEY) ?? 'false'
);
const developerMode = JSON.parse(localStorage.getItem(DEVELOPER_MODE_STORAGE_KEY) ?? 'false');
const tasksBeta = JSON.parse(localStorage.getItem(TASKS_BETA_STORAGE_KEY) ?? 'false');
return developerMode === true && tasksBeta === true;
} catch {
Expand Down Expand Up @@ -257,6 +249,19 @@ export const inboxFeatureEnabledAtom = atom(
(get) => get(developerModeEnabledAtom) && get(inboxBetaEnabledAtom)
);

// Developer-only opt-in. Turning Developer mode off retains the local choice.
export const promptShortcutsBetaEnabledAtom = atomWithStorage<boolean>(
'lody-prompt-shortcuts-beta-enabled',
false,
undefined,
{ getOnInit: true }
);

/** Shared gate for Shortcut settings, discovery and the workspace runtime. */
export const promptShortcutsFeatureEnabledAtom = atom(
(get) => get(developerModeEnabledAtom) && get(promptShortcutsBetaEnabledAtom)
);

/** localStorage keys for the experimental features gate. */
export const EXPERIMENTAL_FEATURES_STORAGE_KEY = 'lody-experimental-features-enabled';
export const REVIEW_AGENT_EXPERIMENT_STORAGE_KEY = 'lody-review-agent-enabled';
Expand Down
Loading
Loading