@oh-my-pi/pi-coding-agent 16.0.5 → 16.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +60 -0
- package/dist/cli.js +1945 -1386
- package/dist/types/advisor/advise-tool.d.ts +22 -19
- package/dist/types/autoresearch/tools/init-experiment.d.ts +13 -17
- package/dist/types/autoresearch/tools/log-experiment.d.ts +17 -19
- package/dist/types/autoresearch/tools/run-experiment.d.ts +3 -4
- package/dist/types/autoresearch/tools/update-notes.d.ts +4 -5
- package/dist/types/cli/ttsr-cli.d.ts +39 -0
- package/dist/types/commands/ttsr.d.ts +57 -0
- package/dist/types/commit/agentic/tools/analyze-file.d.ts +4 -5
- package/dist/types/commit/agentic/tools/git-file-diff.d.ts +4 -5
- package/dist/types/commit/agentic/tools/git-hunk.d.ts +5 -6
- package/dist/types/commit/agentic/tools/git-overview.d.ts +4 -5
- package/dist/types/commit/agentic/tools/propose-changelog.d.ts +23 -24
- package/dist/types/commit/agentic/tools/propose-commit.d.ts +11 -32
- package/dist/types/commit/agentic/tools/recent-commits.d.ts +3 -4
- package/dist/types/commit/agentic/tools/schemas.d.ts +6 -27
- package/dist/types/commit/agentic/tools/split-commit.d.ts +28 -49
- package/dist/types/commit/changelog/generate.d.ts +12 -13
- package/dist/types/commit/shared-llm.d.ts +10 -37
- package/dist/types/config/config-file.d.ts +4 -4
- package/dist/types/config/keybindings.d.ts +5 -0
- package/dist/types/config/models-config-schema.d.ts +625 -990
- package/dist/types/config/models-config.d.ts +229 -217
- package/dist/types/config/settings-schema.d.ts +53 -23
- package/dist/types/edit/hashline/params.d.ts +7 -11
- package/dist/types/edit/index.d.ts +2 -1
- package/dist/types/edit/modes/apply-patch.d.ts +4 -5
- package/dist/types/edit/modes/patch.d.ts +15 -24
- package/dist/types/edit/modes/replace.d.ts +16 -17
- package/dist/types/eval/js/index.d.ts +1 -0
- package/dist/types/extensibility/custom-commands/types.d.ts +6 -3
- package/dist/types/extensibility/custom-tools/types.d.ts +8 -5
- package/dist/types/extensibility/extensions/types.d.ts +6 -3
- package/dist/types/extensibility/hooks/types.d.ts +7 -4
- package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +13 -5
- package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +17 -0
- package/dist/types/extensibility/typebox.d.ts +80 -58
- package/dist/types/goals/tools/goal-tool.d.ts +11 -24
- package/dist/types/index.d.ts +2 -0
- package/dist/types/lsp/index.d.ts +11 -26
- package/dist/types/lsp/types.d.ts +12 -28
- package/dist/types/mcp/client.d.ts +8 -0
- package/dist/types/modes/components/btw-panel.d.ts +1 -0
- package/dist/types/modes/components/custom-editor.d.ts +3 -1
- package/dist/types/modes/controllers/btw-controller.d.ts +2 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +3 -0
- package/dist/types/modes/setup-wizard/index.d.ts +1 -0
- package/dist/types/modes/setup-wizard/startup-splash.d.ts +7 -0
- package/dist/types/modes/theme/theme.d.ts +1 -1
- package/dist/types/modes/types.d.ts +3 -0
- package/dist/types/sdk.d.ts +5 -0
- package/dist/types/session/agent-session.d.ts +4 -0
- package/dist/types/startup-splash.d.ts +12 -0
- package/dist/types/task/types.d.ts +47 -48
- package/dist/types/tools/ask.d.ts +26 -27
- package/dist/types/tools/ast-edit.d.ts +17 -17
- package/dist/types/tools/ast-grep.d.ts +12 -13
- package/dist/types/tools/bash.d.ts +20 -17
- package/dist/types/tools/browser.d.ts +46 -71
- package/dist/types/tools/checkpoint.d.ts +14 -15
- package/dist/types/tools/debug.d.ts +82 -145
- package/dist/types/tools/eval.d.ts +30 -40
- package/dist/types/tools/find.d.ts +17 -18
- package/dist/types/tools/gh.d.ts +49 -78
- package/dist/types/tools/image-gen.d.ts +20 -36
- package/dist/types/tools/inspect-image.d.ts +10 -11
- package/dist/types/tools/irc.d.ts +22 -33
- package/dist/types/tools/job.d.ts +11 -12
- package/dist/types/tools/learn.d.ts +21 -28
- package/dist/types/tools/manage-skill.d.ts +13 -22
- package/dist/types/tools/memory-edit.d.ts +15 -24
- package/dist/types/tools/memory-recall.d.ts +7 -8
- package/dist/types/tools/memory-reflect.d.ts +9 -10
- package/dist/types/tools/memory-retain.d.ts +13 -14
- package/dist/types/tools/read.d.ts +7 -8
- package/dist/types/tools/resolve.d.ts +11 -18
- package/dist/types/tools/review.d.ts +9 -15
- package/dist/types/tools/search-tool-bm25.d.ts +9 -10
- package/dist/types/tools/search.d.ts +16 -17
- package/dist/types/tools/ssh.d.ts +14 -15
- package/dist/types/tools/todo.d.ts +27 -43
- package/dist/types/tools/tts.d.ts +8 -9
- package/dist/types/tools/write.d.ts +9 -10
- package/dist/types/tui/index.d.ts +1 -0
- package/dist/types/tui/width-aware-text.d.ts +23 -0
- package/dist/types/utils/markit.d.ts +10 -1
- package/dist/types/web/search/index.d.ts +17 -28
- package/dist/types/web/search/providers/perplexity.d.ts +0 -2
- package/dist/types/web/search/types.d.ts +32 -26
- package/package.json +14 -13
- package/scripts/omp +1 -1
- package/src/advisor/__tests__/advisor.test.ts +44 -1
- package/src/advisor/advise-tool.ts +34 -11
- package/src/autoresearch/tools/init-experiment.ts +13 -16
- package/src/autoresearch/tools/log-experiment.ts +15 -18
- package/src/autoresearch/tools/run-experiment.ts +3 -3
- package/src/autoresearch/tools/update-notes.ts +4 -4
- package/src/cli/ttsr-cli.ts +995 -0
- package/src/cli-commands.ts +1 -0
- package/src/cli.ts +7 -1
- package/src/commands/ttsr.ts +125 -0
- package/src/commit/agentic/tools/analyze-file.ts +4 -4
- package/src/commit/agentic/tools/git-file-diff.ts +4 -4
- package/src/commit/agentic/tools/git-hunk.ts +7 -5
- package/src/commit/agentic/tools/git-overview.ts +4 -4
- package/src/commit/agentic/tools/propose-changelog.ts +18 -15
- package/src/commit/agentic/tools/propose-commit.ts +6 -6
- package/src/commit/agentic/tools/recent-commits.ts +3 -3
- package/src/commit/agentic/tools/schemas.ts +8 -20
- package/src/commit/agentic/tools/split-commit.ts +19 -23
- package/src/commit/analysis/summary.ts +7 -5
- package/src/commit/changelog/generate.ts +15 -11
- package/src/commit/shared-llm.ts +17 -24
- package/src/config/config-file.ts +13 -15
- package/src/config/keybindings.ts +6 -0
- package/src/config/models-config-schema.ts +206 -179
- package/src/config/settings-schema.ts +34 -0
- package/src/discovery/builtin-rules/index.ts +2 -0
- package/src/discovery/builtin-rules/ts-import-type.md +2 -2
- package/src/discovery/builtin-rules/ts-no-any.md +11 -2
- package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
- package/src/edit/hashline/params.ts +12 -11
- package/src/edit/index.ts +5 -4
- package/src/edit/modes/apply-patch.ts +4 -4
- package/src/edit/modes/patch.ts +15 -18
- package/src/edit/modes/replace.ts +13 -17
- package/src/edit/renderer.ts +0 -1
- package/src/eval/agent-bridge.ts +11 -13
- package/src/eval/completion-bridge.ts +25 -17
- package/src/eval/js/context-manager.ts +17 -2
- package/src/eval/js/index.ts +1 -1
- package/src/eval/py/executor.ts +2 -2
- package/src/extensibility/custom-commands/loader.ts +5 -3
- package/src/extensibility/custom-commands/types.ts +6 -3
- package/src/extensibility/custom-tools/loader.ts +4 -2
- package/src/extensibility/custom-tools/types.ts +8 -5
- package/src/extensibility/extensions/loader.ts +4 -2
- package/src/extensibility/extensions/types.ts +6 -3
- package/src/extensibility/hooks/loader.ts +5 -2
- package/src/extensibility/hooks/types.ts +7 -4
- package/src/extensibility/legacy-pi-ai-shim.ts +42 -5
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +113 -0
- package/src/extensibility/plugins/legacy-pi-compat.ts +13 -13
- package/src/extensibility/tool-proxy.ts +4 -1
- package/src/extensibility/typebox.ts +778 -251
- package/src/goals/guided-setup.ts +12 -3
- package/src/goals/tools/goal-tool.ts +6 -6
- package/src/index.ts +2 -0
- package/src/internal-urls/docs-index.generated.ts +11 -9
- package/src/lsp/types.ts +13 -27
- package/src/main.ts +19 -18
- package/src/mcp/client.ts +38 -13
- package/src/mcp/render.ts +102 -89
- package/src/modes/components/agent-hub.ts +11 -4
- package/src/modes/components/btw-panel.ts +5 -1
- package/src/modes/components/custom-editor.ts +18 -0
- package/src/modes/components/status-line/component.ts +8 -1
- package/src/modes/components/tool-execution.ts +17 -10
- package/src/modes/controllers/btw-controller.ts +69 -1
- package/src/modes/controllers/input-controller.ts +29 -0
- package/src/modes/interactive-mode.ts +38 -8
- package/src/modes/setup-wizard/index.ts +1 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +77 -5
- package/src/modes/setup-wizard/startup-splash.ts +107 -0
- package/src/modes/theme/theme.ts +133 -143
- package/src/modes/types.ts +3 -0
- package/src/modes/utils/context-usage.ts +9 -5
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/prompts/system/system-prompt.md +1 -0
- package/src/sdk.ts +21 -4
- package/src/session/agent-session.ts +173 -33
- package/src/session/session-history-format.ts +11 -2
- package/src/session/snapcompact-inline.ts +1 -1
- package/src/slash-commands/builtin-registry.ts +3 -10
- package/src/startup-splash.ts +19 -0
- package/src/task/executor.ts +11 -6
- package/src/task/types.ts +44 -41
- package/src/tool-discovery/tool-index.ts +17 -4
- package/src/tools/ask.ts +14 -14
- package/src/tools/ast-edit.ts +17 -14
- package/src/tools/ast-grep.ts +10 -9
- package/src/tools/bash.ts +15 -10
- package/src/tools/browser/launch.ts +13 -0
- package/src/tools/browser.ts +26 -32
- package/src/tools/checkpoint.ts +7 -7
- package/src/tools/debug.ts +72 -69
- package/src/tools/eval.ts +18 -19
- package/src/tools/find.ts +20 -13
- package/src/tools/gh.ts +29 -49
- package/src/tools/image-gen.ts +27 -32
- package/src/tools/inspect-image.ts +8 -9
- package/src/tools/irc.ts +12 -12
- package/src/tools/job.ts +6 -6
- package/src/tools/learn.ts +11 -14
- package/src/tools/manage-skill.ts +19 -23
- package/src/tools/memory-edit.ts +8 -8
- package/src/tools/memory-recall.ts +4 -4
- package/src/tools/memory-reflect.ts +5 -5
- package/src/tools/memory-retain.ts +9 -11
- package/src/tools/puppeteer/02_stealth_hairline.txt +1 -1
- package/src/tools/puppeteer/04_stealth_iframe.txt +4 -4
- package/src/tools/puppeteer/05_stealth_webgl.txt +1 -1
- package/src/tools/puppeteer/10_stealth_plugins.txt +6 -4
- package/src/tools/puppeteer/12_stealth_codecs.txt +2 -2
- package/src/tools/puppeteer/13_stealth_worker.txt +1 -1
- package/src/tools/read.ts +169 -13
- package/src/tools/report-tool-issue.ts +6 -6
- package/src/tools/resolve.ts +6 -6
- package/src/tools/review.ts +10 -12
- package/src/tools/search-tool-bm25.ts +5 -5
- package/src/tools/search.ts +20 -29
- package/src/tools/ssh.ts +8 -8
- package/src/tools/todo.ts +16 -19
- package/src/tools/tts.ts +16 -15
- package/src/tools/write.ts +5 -5
- package/src/tui/index.ts +1 -0
- package/src/tui/width-aware-text.ts +58 -0
- package/src/utils/markit.ts +17 -2
- package/src/web/search/index.ts +9 -9
- package/src/web/search/providers/perplexity.ts +373 -126
- package/src/web/search/types.ts +28 -48
package/src/cli-commands.ts
CHANGED
|
@@ -39,6 +39,7 @@ export const commands: CommandEntry[] = [
|
|
|
39
39
|
{ name: "usage", load: () => import("./commands/usage").then(m => m.default) },
|
|
40
40
|
{ name: "tiny-models", load: () => import("./commands/tiny-models").then(m => m.default) },
|
|
41
41
|
{ name: "token", load: () => import("./commands/token").then(m => m.default) },
|
|
42
|
+
{ name: "ttsr", load: () => import("./commands/ttsr").then(m => m.default) },
|
|
42
43
|
{ name: "worktree", load: () => import("./commands/worktree").then(m => m.default), aliases: ["wt"] },
|
|
43
44
|
{ name: "search", load: () => import("./commands/web-search").then(m => m.default), aliases: ["q"] },
|
|
44
45
|
];
|
package/src/cli.ts
CHANGED
|
@@ -275,7 +275,13 @@ export async function runCli(argv: string[]): Promise<void> {
|
|
|
275
275
|
// Declare this module as the worker-host entry now that the active profile
|
|
276
276
|
// is resolved. The worker-host module is side-effect-free; importing
|
|
277
277
|
// `@oh-my-pi/pi-utils/env` here would snapshot the wrong agent `.env`.
|
|
278
|
-
|
|
278
|
+
// Gated on `import.meta.main`: only the real CLI process entry is a valid
|
|
279
|
+
// worker host. Worker-thread re-entry already returned above at the
|
|
280
|
+
// `__omp_worker_` dispatch, and importers (`runCli` in profile-CLI tests,
|
|
281
|
+
// SDK embedding) have `import.meta.main === false` — declaring there would
|
|
282
|
+
// poison `workerHostEntry()` for the whole test process, forcing eval/stats/
|
|
283
|
+
// browser workers onto the same-realm inline fallback.
|
|
284
|
+
if (import.meta.main) declareWorkerHostEntry();
|
|
279
285
|
|
|
280
286
|
if (resolvedArgv[0] === "--smoke-test") {
|
|
281
287
|
await runSmokeTest();
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* `omp ttsr` — inspect and test Time-Traveling Stream Rules.
|
|
5
|
+
*
|
|
6
|
+
* `omp ttsr test` feeds a snippet (inline, --file, or stdin) through the real
|
|
7
|
+
* TTSR matching pipeline and reports which rules would trigger. `omp ttsr list`
|
|
8
|
+
* shows every TTSR-registered rule the current project/user config would load.
|
|
9
|
+
*/
|
|
10
|
+
import { Args, Command, Flags } from "@oh-my-pi/pi-utils/cli";
|
|
11
|
+
import {
|
|
12
|
+
runTtsrCommand,
|
|
13
|
+
TTSR_ACTIONS,
|
|
14
|
+
TTSR_SOURCES,
|
|
15
|
+
type TtsrCommandArgs,
|
|
16
|
+
type TtsrScanArgs,
|
|
17
|
+
type TtsrTestArgs,
|
|
18
|
+
} from "../cli/ttsr-cli";
|
|
19
|
+
import type { TtsrMatchSource } from "../export/ttsr";
|
|
20
|
+
|
|
21
|
+
export default class Ttsr extends Command {
|
|
22
|
+
static description = "Inspect and test Time-Traveling Stream Rules (TTSR)";
|
|
23
|
+
|
|
24
|
+
static args = {
|
|
25
|
+
action: Args.string({
|
|
26
|
+
description: "TTSR action",
|
|
27
|
+
required: false,
|
|
28
|
+
options: TTSR_ACTIONS,
|
|
29
|
+
}),
|
|
30
|
+
snippet: Args.string({
|
|
31
|
+
description: "Inline snippet text to test (ttsr test) or directory to scan (ttsr scan)",
|
|
32
|
+
required: false,
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
static flags = {
|
|
37
|
+
file: Flags.string({ description: "Snippet file path, or - for stdin (ttsr test)" }),
|
|
38
|
+
rule: Flags.string({
|
|
39
|
+
char: "r",
|
|
40
|
+
description: "Rule markdown file to test in isolation (skips project rule loading)",
|
|
41
|
+
}),
|
|
42
|
+
source: Flags.string({
|
|
43
|
+
description: "Match source: text, thinking, or tool (inferred from --file when omitted)",
|
|
44
|
+
options: TTSR_SOURCES,
|
|
45
|
+
}),
|
|
46
|
+
tool: Flags.string({
|
|
47
|
+
description: "Tool name when source is tool (e.g. edit, write); defaults to edit",
|
|
48
|
+
}),
|
|
49
|
+
path: Flags.string({
|
|
50
|
+
char: "p",
|
|
51
|
+
description: "Candidate file path for scope/glob matching and AST language inference",
|
|
52
|
+
}),
|
|
53
|
+
verbose: Flags.boolean({ char: "v", description: "Show every evaluated rule, not just triggered ones" }),
|
|
54
|
+
json: Flags.boolean({ description: "Output JSON" }),
|
|
55
|
+
"no-gitignore": Flags.boolean({ description: "Include files excluded by .gitignore (ttsr scan)" }),
|
|
56
|
+
"max-bytes": Flags.integer({
|
|
57
|
+
description: "Maximum file size to scan in bytes; 0 disables the limit (ttsr scan)",
|
|
58
|
+
}),
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
static examples = [
|
|
62
|
+
"omp ttsr list",
|
|
63
|
+
"omp ttsr test 'const x: any = 1'",
|
|
64
|
+
"omp ttsr test src/foo.ts",
|
|
65
|
+
"omp ttsr test --file src/foo.ts",
|
|
66
|
+
"omp ttsr test --file src/foo.ts --source text",
|
|
67
|
+
"omp ttsr test --rule .omp/rules/no-any.md --source tool --path src/foo.ts 'const x: any = 1'",
|
|
68
|
+
"echo 'Box::leak(&mut v)' | omp ttsr test --file - --path src/lib.rs",
|
|
69
|
+
"omp ttsr test --source tool --tool edit --path src/foo.ts 'const x: any = 1'",
|
|
70
|
+
"omp ttsr scan",
|
|
71
|
+
"omp ttsr scan src/",
|
|
72
|
+
"omp ttsr scan -r .omp/rules/no-any.md src/",
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
async run(): Promise<void> {
|
|
76
|
+
const { args, flags } = await this.parse(Ttsr);
|
|
77
|
+
const action = (args.action ?? "list") as (typeof TTSR_ACTIONS)[number];
|
|
78
|
+
|
|
79
|
+
// A positional that resolves to an existing file is a snippet file, not
|
|
80
|
+
// inline text — so `omp ttsr test src/foo.ts` works without --file.
|
|
81
|
+
// --file always wins over the positional.
|
|
82
|
+
let file = flags.file;
|
|
83
|
+
let snippet = args.snippet;
|
|
84
|
+
if (action === "test" && snippet && !file) {
|
|
85
|
+
const resolved = path.resolve(snippet);
|
|
86
|
+
if (existsSync(resolved)) {
|
|
87
|
+
file = resolved;
|
|
88
|
+
snippet = undefined;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const test: TtsrTestArgs | undefined =
|
|
93
|
+
action === "test"
|
|
94
|
+
? {
|
|
95
|
+
snippet,
|
|
96
|
+
file,
|
|
97
|
+
rule: flags.rule,
|
|
98
|
+
source: flags.source as TtsrMatchSource | undefined,
|
|
99
|
+
tool: flags.tool,
|
|
100
|
+
filePath: flags.path,
|
|
101
|
+
verbose: flags.verbose,
|
|
102
|
+
}
|
|
103
|
+
: undefined;
|
|
104
|
+
|
|
105
|
+
const scan: TtsrScanArgs | undefined =
|
|
106
|
+
action === "scan"
|
|
107
|
+
? {
|
|
108
|
+
directory: args.snippet,
|
|
109
|
+
rule: flags.rule,
|
|
110
|
+
gitignore: !flags["no-gitignore"],
|
|
111
|
+
maxBytes: flags["max-bytes"],
|
|
112
|
+
verbose: flags.verbose,
|
|
113
|
+
}
|
|
114
|
+
: undefined;
|
|
115
|
+
|
|
116
|
+
const cmd: TtsrCommandArgs = {
|
|
117
|
+
action,
|
|
118
|
+
test,
|
|
119
|
+
scan,
|
|
120
|
+
json: flags.json,
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
await runTtsrCommand(cmd);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { prompt } from "@oh-my-pi/pi-utils";
|
|
2
|
-
import {
|
|
2
|
+
import { type } from "arktype";
|
|
3
3
|
import analyzeFilePrompt from "../../../commit/agentic/prompts/analyze-file.md" with { type: "text" };
|
|
4
4
|
import type { CommitAgentState } from "../../../commit/agentic/state";
|
|
5
5
|
import type { NumstatEntry } from "../../../commit/types";
|
|
@@ -12,9 +12,9 @@ import type { TaskParams } from "../../../task/types";
|
|
|
12
12
|
import type { ToolSession } from "../../../tools";
|
|
13
13
|
import { getFilePriority } from "./git-file-diff";
|
|
14
14
|
|
|
15
|
-
const analyzeFileSchema =
|
|
16
|
-
files:
|
|
17
|
-
goal:
|
|
15
|
+
const analyzeFileSchema = type({
|
|
16
|
+
files: type("string").describe("file path").array().atLeastLength(1),
|
|
17
|
+
"goal?": type("string").describe("analysis focus"),
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
const analyzeFileOutputSchema = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type } from "arktype";
|
|
2
2
|
import type { CommitAgentState } from "../../../commit/agentic/state";
|
|
3
3
|
import type { CustomTool } from "../../../extensibility/custom-tools/types";
|
|
4
4
|
import * as git from "../../../utils/git";
|
|
@@ -131,9 +131,9 @@ function processDiffs(files: string[], diffs: Map<string, string>): { result: st
|
|
|
131
131
|
return { result: parts.join("\n\n"), truncatedFiles };
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
const gitFileDiffSchema =
|
|
135
|
-
files:
|
|
136
|
-
staged:
|
|
134
|
+
const gitFileDiffSchema = type({
|
|
135
|
+
files: type("string").describe("file to diff").array().atLeastLength(1).atMostLength(10),
|
|
136
|
+
"staged?": type("boolean").describe("use staged changes (default true)"),
|
|
137
137
|
});
|
|
138
138
|
|
|
139
139
|
export function createGitFileDiffTool(cwd: string, state: CommitAgentState): CustomTool<typeof gitFileDiffSchema> {
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type } from "arktype";
|
|
2
2
|
import type { DiffHunk, FileHunks } from "../../../commit/types";
|
|
3
3
|
import type { CustomTool } from "../../../extensibility/custom-tools/types";
|
|
4
4
|
import * as git from "../../../utils/git";
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
const hunkIndexType = type("number").describe("1-based hunk index");
|
|
7
|
+
|
|
8
|
+
const gitHunkSchema = type({
|
|
9
|
+
file: type("string").describe("file path"),
|
|
10
|
+
"hunks?": hunkIndexType.array().atLeastLength(1),
|
|
11
|
+
"staged?": type("boolean").describe("use staged changes (default true)"),
|
|
10
12
|
});
|
|
11
13
|
|
|
12
14
|
function selectHunks(fileHunks: FileHunks, requested?: number[]): DiffHunk[] {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type } from "arktype";
|
|
2
2
|
import type { CommitAgentState, GitOverviewSnapshot } from "../../../commit/agentic/state";
|
|
3
3
|
import { extractScopeCandidates } from "../../../commit/analysis/scope";
|
|
4
4
|
import type { CustomTool } from "../../../extensibility/custom-tools/types";
|
|
@@ -42,9 +42,9 @@ function filterExcludedFiles(files: string[]): { filtered: string[]; excluded: s
|
|
|
42
42
|
return { filtered, excluded };
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
const gitOverviewSchema =
|
|
46
|
-
staged:
|
|
47
|
-
include_untracked:
|
|
45
|
+
const gitOverviewSchema = type({
|
|
46
|
+
"staged?": type("boolean").describe("use staged changes (default true)"),
|
|
47
|
+
"include_untracked?": type("boolean").describe("include untracked when unstaged"),
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
export function createGitOverviewTool(cwd: string, state: CommitAgentState): CustomTool<typeof gitOverviewSchema> {
|
|
@@ -1,27 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type } from "arktype";
|
|
2
2
|
import type { CommitAgentState } from "../../../commit/agentic/state";
|
|
3
3
|
import { CHANGELOG_CATEGORIES, type ChangelogCategory } from "../../../commit/types";
|
|
4
4
|
import type { CustomTool } from "../../../extensibility/custom-tools/types";
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
const changelogCategoryProperties = {
|
|
7
|
+
"Breaking Changes?": "string[]",
|
|
8
|
+
"Added?": "string[]",
|
|
9
|
+
"Changed?": "string[]",
|
|
10
|
+
"Deprecated?": "string[]",
|
|
11
|
+
"Removed?": "string[]",
|
|
12
|
+
"Fixed?": "string[]",
|
|
13
|
+
"Security?": "string[]",
|
|
14
|
+
} as const;
|
|
13
15
|
|
|
14
|
-
const changelogEntriesSchema =
|
|
15
|
-
|
|
16
|
+
const changelogEntriesSchema = type({
|
|
17
|
+
...changelogCategoryProperties,
|
|
18
|
+
});
|
|
16
19
|
|
|
17
|
-
const changelogEntrySchema =
|
|
18
|
-
path:
|
|
20
|
+
const changelogEntrySchema = type({
|
|
21
|
+
path: "string",
|
|
19
22
|
entries: changelogEntriesSchema,
|
|
20
|
-
deletions:
|
|
23
|
+
"deletions?": changelogEntriesSchema.describe("entries to remove"),
|
|
21
24
|
});
|
|
22
25
|
|
|
23
|
-
const proposeChangelogSchema =
|
|
24
|
-
entries:
|
|
26
|
+
const proposeChangelogSchema = type({
|
|
27
|
+
entries: changelogEntrySchema.array(),
|
|
25
28
|
});
|
|
26
29
|
|
|
27
30
|
interface ChangelogResponse {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type } from "arktype";
|
|
2
2
|
import type { CommitAgentState } from "../../../commit/agentic/state";
|
|
3
3
|
import {
|
|
4
4
|
capDetails,
|
|
@@ -15,12 +15,12 @@ import type { CustomTool } from "../../../extensibility/custom-tools/types";
|
|
|
15
15
|
import * as git from "../../../utils/git";
|
|
16
16
|
import { commitTypeSchema, detailSchema } from "./schemas.js";
|
|
17
17
|
|
|
18
|
-
const proposeCommitSchema =
|
|
18
|
+
const proposeCommitSchema = type({
|
|
19
19
|
type: commitTypeSchema,
|
|
20
|
-
scope:
|
|
21
|
-
summary:
|
|
22
|
-
details:
|
|
23
|
-
issue_refs:
|
|
20
|
+
scope: type("string").or("null"),
|
|
21
|
+
summary: "string",
|
|
22
|
+
details: detailSchema.array(),
|
|
23
|
+
issue_refs: "string[]",
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
interface ProposalResponse {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type } from "arktype";
|
|
2
2
|
import type { CustomTool } from "../../../extensibility/custom-tools/types";
|
|
3
3
|
import * as git from "../../../utils/git";
|
|
4
4
|
|
|
5
|
-
const recentCommitsSchema =
|
|
6
|
-
count:
|
|
5
|
+
const recentCommitsSchema = type({
|
|
6
|
+
"count?": type("1 <= number <= 50").describe("commit count"),
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
interface RecentCommitStats {
|
|
@@ -1,23 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type } from "arktype";
|
|
2
2
|
|
|
3
|
-
export const commitTypeSchema =
|
|
4
|
-
"feat",
|
|
5
|
-
|
|
6
|
-
"refactor",
|
|
7
|
-
"perf",
|
|
8
|
-
"docs",
|
|
9
|
-
"test",
|
|
10
|
-
"build",
|
|
11
|
-
"ci",
|
|
12
|
-
"chore",
|
|
13
|
-
"style",
|
|
14
|
-
"revert",
|
|
15
|
-
] as const);
|
|
3
|
+
export const commitTypeSchema = type(
|
|
4
|
+
"'feat' | 'fix' | 'refactor' | 'perf' | 'docs' | 'test' | 'build' | 'ci' | 'chore' | 'style' | 'revert'",
|
|
5
|
+
);
|
|
16
6
|
|
|
17
|
-
export const detailSchema =
|
|
18
|
-
text:
|
|
19
|
-
changelog_category:
|
|
20
|
-
|
|
21
|
-
.optional(),
|
|
22
|
-
user_visible: z.boolean().optional(),
|
|
7
|
+
export const detailSchema = type({
|
|
8
|
+
text: "string",
|
|
9
|
+
"changelog_category?": "'Added' | 'Changed' | 'Fixed' | 'Deprecated' | 'Removed' | 'Security' | 'Breaking Changes'",
|
|
10
|
+
"user_visible?": "boolean",
|
|
23
11
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type } from "arktype";
|
|
2
2
|
import type { CommitAgentState, SplitCommitGroup, SplitCommitPlan } from "../../../commit/agentic/state";
|
|
3
3
|
import { computeDependencyOrder } from "../../../commit/agentic/topo-sort";
|
|
4
4
|
import {
|
|
@@ -15,32 +15,28 @@ import type { CustomTool } from "../../../extensibility/custom-tools/types";
|
|
|
15
15
|
import * as git from "../../../utils/git";
|
|
16
16
|
import { commitTypeSchema, detailSchema } from "./schemas.js";
|
|
17
17
|
|
|
18
|
-
const hunkSelectorSchema =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
z.object({ type: z.literal("lines"), start: z.number(), end: z.number() }),
|
|
22
|
-
]);
|
|
18
|
+
const hunkSelectorSchema = type({ type: "'all'" })
|
|
19
|
+
.or({ type: "'indices'", indices: "number[]" })
|
|
20
|
+
.or({ type: "'lines'", start: "number", end: "number" });
|
|
23
21
|
|
|
24
|
-
const fileChangeSchema =
|
|
25
|
-
path:
|
|
22
|
+
const fileChangeSchema = type({
|
|
23
|
+
path: "string",
|
|
26
24
|
hunks: hunkSelectorSchema,
|
|
27
25
|
});
|
|
28
26
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
)
|
|
43
|
-
.min(2),
|
|
27
|
+
const commitItemSchema = type({
|
|
28
|
+
changes: fileChangeSchema.array(),
|
|
29
|
+
type: commitTypeSchema,
|
|
30
|
+
scope: type("string").or("null"),
|
|
31
|
+
summary: "string",
|
|
32
|
+
"details?": detailSchema.array(),
|
|
33
|
+
"issue_refs?": "string[]",
|
|
34
|
+
"rationale?": "string",
|
|
35
|
+
"dependencies?": "number[]",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const splitCommitSchema = type({
|
|
39
|
+
commits: commitItemSchema.array(),
|
|
44
40
|
});
|
|
45
41
|
|
|
46
42
|
interface SplitCommitResponse {
|
|
@@ -2,19 +2,21 @@ import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
|
2
2
|
import type { Api, ApiKey, AssistantMessage, Model } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import { completeSimple, validateToolCall } from "@oh-my-pi/pi-ai";
|
|
4
4
|
import { prompt } from "@oh-my-pi/pi-utils";
|
|
5
|
-
import {
|
|
5
|
+
import { type } from "arktype";
|
|
6
6
|
import summarySystemPrompt from "../../commit/prompts/summary-system.md" with { type: "text" };
|
|
7
7
|
import summaryUserPrompt from "../../commit/prompts/summary-user.md" with { type: "text" };
|
|
8
8
|
import type { CommitSummary } from "../../commit/types";
|
|
9
9
|
import { toReasoningEffort } from "../../thinking";
|
|
10
10
|
import { extractTextContent, extractToolCall } from "../utils";
|
|
11
11
|
|
|
12
|
+
const SummaryToolSchema = type({
|
|
13
|
+
summary: "string",
|
|
14
|
+
});
|
|
15
|
+
|
|
12
16
|
const SummaryTool = {
|
|
13
17
|
name: "create_commit_summary",
|
|
14
18
|
description: "Generate the summary line for a conventional commit message.",
|
|
15
|
-
parameters:
|
|
16
|
-
summary: z.string(),
|
|
17
|
-
}),
|
|
19
|
+
parameters: SummaryToolSchema,
|
|
18
20
|
};
|
|
19
21
|
|
|
20
22
|
export interface SummaryInput {
|
|
@@ -83,7 +85,7 @@ function renderSummaryPrompt({
|
|
|
83
85
|
function parseSummaryFromResponse(message: AssistantMessage, commitType: string, scope: string | null): CommitSummary {
|
|
84
86
|
const toolCall = extractToolCall(message, "create_commit_summary");
|
|
85
87
|
if (toolCall) {
|
|
86
|
-
const parsed = validateToolCall([SummaryTool], toolCall) as
|
|
88
|
+
const parsed = validateToolCall([SummaryTool], toolCall) as (typeof SummaryToolSchema)["infer"];
|
|
87
89
|
return { summary: stripTypePrefix(parsed.summary, commitType, scope) };
|
|
88
90
|
}
|
|
89
91
|
const text = extractTextContent(message);
|
|
@@ -2,25 +2,29 @@ import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
|
2
2
|
import type { Api, ApiKey, AssistantMessage, Model } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import { completeSimple, validateToolCall } from "@oh-my-pi/pi-ai";
|
|
4
4
|
import { prompt } from "@oh-my-pi/pi-utils";
|
|
5
|
-
import {
|
|
5
|
+
import { type } from "arktype";
|
|
6
6
|
import changelogSystemPrompt from "../../commit/prompts/changelog-system.md" with { type: "text" };
|
|
7
7
|
import changelogUserPrompt from "../../commit/prompts/changelog-user.md" with { type: "text" };
|
|
8
|
-
import
|
|
8
|
+
import type { ChangelogGenerationResult } from "../../commit/types";
|
|
9
9
|
import { toReasoningEffort } from "../../thinking";
|
|
10
10
|
import { extractTextContent, extractToolCall, parseJsonPayload } from "../utils";
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
// Build the changelog entry schema with arktype
|
|
13
|
+
// Each category maps to an optional array of strings
|
|
14
|
+
const changelogEntriesSchema = type({
|
|
15
|
+
"Breaking Changes?": "string[]",
|
|
16
|
+
"Added?": "string[]",
|
|
17
|
+
"Changed?": "string[]",
|
|
18
|
+
"Deprecated?": "string[]",
|
|
19
|
+
"Removed?": "string[]",
|
|
20
|
+
"Fixed?": "string[]",
|
|
21
|
+
"Security?": "string[]",
|
|
22
|
+
});
|
|
17
23
|
|
|
18
24
|
export const changelogTool = {
|
|
19
25
|
name: "create_changelog_entries",
|
|
20
26
|
description: "Generate changelog entries grouped by Keep a Changelog categories.",
|
|
21
|
-
parameters:
|
|
22
|
-
entries: changelogEntriesSchema,
|
|
23
|
-
}),
|
|
27
|
+
parameters: type({ entries: changelogEntriesSchema }),
|
|
24
28
|
};
|
|
25
29
|
|
|
26
30
|
export interface ChangelogPromptInput {
|
|
@@ -68,7 +72,7 @@ export async function generateChangelogEntries({
|
|
|
68
72
|
function parseChangelogResponse(message: AssistantMessage): ChangelogGenerationResult {
|
|
69
73
|
const toolCall = extractToolCall(message, "create_changelog_entries");
|
|
70
74
|
if (toolCall) {
|
|
71
|
-
const parsed = validateToolCall([changelogTool], toolCall) as
|
|
75
|
+
const parsed = validateToolCall([changelogTool], toolCall) as typeof changelogTool.parameters.infer;
|
|
72
76
|
return { entries: parsed.entries ?? {} };
|
|
73
77
|
}
|
|
74
78
|
|
package/src/commit/shared-llm.ts
CHANGED
|
@@ -1,36 +1,29 @@
|
|
|
1
1
|
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
|
|
2
|
-
import { validateToolCall } from "@oh-my-pi/pi-ai";
|
|
3
|
-
import { z } from "zod/v4";
|
|
2
|
+
import { type as t, validateToolCall } from "@oh-my-pi/pi-ai";
|
|
4
3
|
import type { ChangelogCategory, ConventionalAnalysis } from "./types";
|
|
5
4
|
import { extractTextContent, extractToolCall, normalizeAnalysis, parseJsonPayload } from "./utils";
|
|
6
5
|
|
|
7
|
-
const changelogCategoryLiteral =
|
|
8
|
-
"Added",
|
|
9
|
-
|
|
10
|
-
"Fixed",
|
|
11
|
-
"Deprecated",
|
|
12
|
-
"Removed",
|
|
13
|
-
"Security",
|
|
14
|
-
"Breaking Changes",
|
|
15
|
-
]);
|
|
6
|
+
const changelogCategoryLiteral = t(
|
|
7
|
+
"'Added' | 'Changed' | 'Fixed' | 'Deprecated' | 'Removed' | 'Security' | 'Breaking Changes'",
|
|
8
|
+
);
|
|
16
9
|
|
|
17
10
|
/**
|
|
18
|
-
* Shared
|
|
11
|
+
* Shared arktype schema for the `create_conventional_analysis` tool used by
|
|
19
12
|
* both the single-pass analysis call and the map-reduce reduce phase. Schemas
|
|
20
13
|
* are identical across phases — only the surrounding tool `description`
|
|
21
14
|
* differs to reflect the input the phase is summarizing.
|
|
22
15
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
),
|
|
33
|
-
issue_refs:
|
|
16
|
+
const detailItem = t({
|
|
17
|
+
text: "string",
|
|
18
|
+
"changelog_category?": changelogCategoryLiteral,
|
|
19
|
+
"user_visible?": "boolean",
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const conventionalAnalysisParameters = t({
|
|
23
|
+
type: "'feat' | 'fix' | 'refactor' | 'docs' | 'test' | 'chore' | 'style' | 'perf' | 'build' | 'ci' | 'revert'",
|
|
24
|
+
scope: t("string").or("null"),
|
|
25
|
+
details: detailItem.array(),
|
|
26
|
+
issue_refs: "string[]",
|
|
34
27
|
});
|
|
35
28
|
|
|
36
29
|
export interface ConventionalAnalysisTool {
|
|
@@ -68,7 +61,7 @@ export function parseConventionalAnalysisResponse(
|
|
|
68
61
|
): ConventionalAnalysis {
|
|
69
62
|
const toolCall = extractToolCall(message, tool.name);
|
|
70
63
|
if (toolCall) {
|
|
71
|
-
const parsed = validateToolCall([tool], toolCall) as
|
|
64
|
+
const parsed = validateToolCall([tool], toolCall) as any;
|
|
72
65
|
return normalizeAnalysis(parsed);
|
|
73
66
|
}
|
|
74
67
|
const text = extractTextContent(message);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { getAgentDir, isEnoent, logger } from "@oh-my-pi/pi-utils";
|
|
4
|
+
import type { Type } from "arktype";
|
|
4
5
|
import { JSONC, YAML } from "bun";
|
|
5
|
-
import type { ZodType } from "zod/v4";
|
|
6
6
|
|
|
7
7
|
/** Minimal subset of the AJV ConfigSchemaError shape this module actually relies on. */
|
|
8
8
|
interface ConfigSchemaError {
|
|
@@ -55,7 +55,7 @@ function migrateJsonToYml(jsonPath: string, ymlPath: string) {
|
|
|
55
55
|
|
|
56
56
|
export interface IConfigFile<T> {
|
|
57
57
|
readonly id: string;
|
|
58
|
-
readonly schema:
|
|
58
|
+
readonly schema: Type;
|
|
59
59
|
path?(): string;
|
|
60
60
|
load(): T | null;
|
|
61
61
|
invalidate?(): void;
|
|
@@ -129,7 +129,7 @@ export class ConfigFile<T> implements IConfigFile<T> {
|
|
|
129
129
|
|
|
130
130
|
constructor(
|
|
131
131
|
readonly id: string,
|
|
132
|
-
readonly schema:
|
|
132
|
+
readonly schema: Type,
|
|
133
133
|
configPath: string = path.join(getAgentDir(), `${id}.yml`),
|
|
134
134
|
) {
|
|
135
135
|
this.#basePath = configPath;
|
|
@@ -193,10 +193,10 @@ export class ConfigFile<T> implements IConfigFile<T> {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
createDefault(): T {
|
|
196
|
-
const parsed = this.schema
|
|
197
|
-
if (parsed
|
|
198
|
-
const fallback = this.schema
|
|
199
|
-
if (fallback
|
|
196
|
+
const parsed = this.schema({});
|
|
197
|
+
if (!(parsed instanceof Error)) return parsed as T;
|
|
198
|
+
const fallback = this.schema(undefined);
|
|
199
|
+
if (!(fallback instanceof Error)) return fallback as T;
|
|
200
200
|
throw new ConfigError(this.id, undefined, {
|
|
201
201
|
err: new Error("Schema produced no default value"),
|
|
202
202
|
stage: "createDefault",
|
|
@@ -219,19 +219,17 @@ export class ConfigFile<T> implements IConfigFile<T> {
|
|
|
219
219
|
throw new Error(`Invalid config file path: ${this.#basePath}`);
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
const checked = this.schema
|
|
223
|
-
if (
|
|
222
|
+
const checked = this.schema(parsed);
|
|
223
|
+
if (checked instanceof Error) {
|
|
224
224
|
const schemaErrors: ConfigSchemaError[] = [];
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if (schemaErrors.length >= 50) break;
|
|
229
|
-
}
|
|
225
|
+
// arktype errors are Error instances with a message property
|
|
226
|
+
// Extract the error message as a single schema error
|
|
227
|
+
schemaErrors.push({ instancePath: "root", message: checked.message });
|
|
230
228
|
const error = new ConfigError(this.id, schemaErrors);
|
|
231
229
|
logger.warn("Failed to parse config file", { path: this.path(), error });
|
|
232
230
|
return this.#storeCache({ error, status: "error" });
|
|
233
231
|
}
|
|
234
|
-
const value = checked
|
|
232
|
+
const value = checked as T;
|
|
235
233
|
try {
|
|
236
234
|
this.#auxValidate?.(value);
|
|
237
235
|
} catch (error) {
|
|
@@ -31,6 +31,7 @@ interface AppKeybindings {
|
|
|
31
31
|
"app.tools.expand": true;
|
|
32
32
|
"app.editor.external": true;
|
|
33
33
|
"app.message.followUp": true;
|
|
34
|
+
"app.retry": true;
|
|
34
35
|
"app.message.dequeue": true;
|
|
35
36
|
"app.clipboard.pasteImage": true;
|
|
36
37
|
"app.clipboard.pasteTextRaw": true;
|
|
@@ -131,6 +132,10 @@ export const KEYBINDINGS = {
|
|
|
131
132
|
defaultKeys: ["ctrl+q", "ctrl+enter"],
|
|
132
133
|
description: "Send follow-up message",
|
|
133
134
|
},
|
|
135
|
+
"app.retry": {
|
|
136
|
+
defaultKeys: "alt+r",
|
|
137
|
+
description: "Retry last failed assistant turn",
|
|
138
|
+
},
|
|
134
139
|
"app.message.dequeue": {
|
|
135
140
|
defaultKeys: "alt+up",
|
|
136
141
|
description: "Dequeue message",
|
|
@@ -238,6 +243,7 @@ const KEYBINDING_NAME_MIGRATIONS = {
|
|
|
238
243
|
toggleThinking: "app.thinking.toggle",
|
|
239
244
|
externalEditor: "app.editor.external",
|
|
240
245
|
followUp: "app.message.followUp",
|
|
246
|
+
retry: "app.retry",
|
|
241
247
|
dequeue: "app.message.dequeue",
|
|
242
248
|
pasteImage: "app.clipboard.pasteImage",
|
|
243
249
|
pasteTextRaw: "app.clipboard.pasteTextRaw",
|