@oh-my-pi/pi-coding-agent 16.0.4 → 16.0.6
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 +94 -0
- package/dist/cli.js +2027 -1396
- package/dist/types/advisor/advise-tool.d.ts +31 -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/args.d.ts +1 -0
- package/dist/types/cli/bench-cli.d.ts +6 -0
- package/dist/types/cli/ttsr-cli.d.ts +39 -0
- package/dist/types/commands/launch.d.ts +3 -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 +144 -25
- 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/runner.d.ts +5 -2
- package/dist/types/extensibility/extensions/types.d.ts +14 -10
- 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/shared-events.d.ts +22 -1
- 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/main.d.ts +1 -0
- 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/components/status-line/component.d.ts +1 -1
- package/dist/types/modes/components/status-line/context-thresholds.d.ts +0 -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/rpc/rpc-types.d.ts +1 -1
- 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/modes/utils/context-usage.d.ts +12 -0
- package/dist/types/sdk.d.ts +8 -1
- package/dist/types/session/agent-session.d.ts +24 -0
- package/dist/types/session/session-persistence.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 +8 -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/code-cell.d.ts +2 -0
- package/dist/types/tui/index.d.ts +1 -0
- package/dist/types/tui/width-aware-text.d.ts +23 -0
- package/dist/types/utils/image-vision-fallback.d.ts +28 -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/base.d.ts +1 -0
- package/dist/types/web/search/providers/gemini.d.ts +1 -0
- 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 +103 -1
- package/src/advisor/advise-tool.ts +47 -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/args.ts +1 -0
- package/src/cli/bench-cli.ts +30 -7
- package/src/cli/flag-tables.ts +8 -0
- package/src/cli/ttsr-cli.ts +995 -0
- package/src/cli-commands.ts +1 -0
- package/src/cli.ts +7 -1
- package/src/collab/host.ts +2 -2
- package/src/commands/launch.ts +3 -0
- 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 +118 -2
- 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/eval/py/runner.py +44 -0
- 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/runner.ts +20 -2
- package/src/extensibility/extensions/types.ts +22 -8
- 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/shared-events.ts +24 -0
- 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 +15 -13
- package/src/lsp/types.ts +13 -27
- package/src/main.ts +29 -21
- 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/branch-summary-message.ts +1 -0
- package/src/modes/components/btw-panel.ts +5 -1
- package/src/modes/components/collab-prompt-message.ts +9 -7
- package/src/modes/components/compaction-summary-message.ts +1 -0
- package/src/modes/components/custom-editor.ts +18 -0
- package/src/modes/components/custom-message.ts +1 -0
- package/src/modes/components/footer.ts +6 -5
- package/src/modes/components/hook-message.ts +1 -0
- package/src/modes/components/read-tool-group.ts +9 -3
- package/src/modes/components/skill-message.ts +1 -0
- package/src/modes/components/status-line/component.ts +139 -15
- package/src/modes/components/status-line/context-thresholds.ts +0 -1
- package/src/modes/components/todo-reminder.ts +1 -0
- package/src/modes/components/tool-execution.ts +17 -10
- package/src/modes/components/ttsr-notification.ts +1 -0
- package/src/modes/components/user-message.ts +6 -6
- package/src/modes/controllers/btw-controller.ts +69 -1
- package/src/modes/controllers/event-controller.ts +2 -7
- package/src/modes/controllers/input-controller.ts +29 -0
- package/src/modes/controllers/selector-controller.ts +10 -3
- package/src/modes/interactive-mode.ts +42 -10
- package/src/modes/rpc/rpc-types.ts +1 -1
- 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 +37 -20
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/prompts/system/system-prompt.md +1 -0
- package/src/prompts/tools/image-attachment-describe-system.md +8 -0
- package/src/prompts/tools/image-attachment-describe.md +10 -0
- package/src/sdk.ts +35 -22
- package/src/session/agent-session.ts +715 -255
- package/src/session/session-history-format.ts +11 -2
- package/src/session/session-loader.ts +19 -32
- package/src/session/session-persistence.ts +27 -11
- package/src/session/snapcompact-inline.ts +1 -1
- package/src/slash-commands/builtin-registry.ts +4 -11
- package/src/ssh/connection-manager.ts +3 -2
- package/src/startup-splash.ts +19 -0
- package/src/task/executor.ts +12 -7
- 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 +94 -57
- 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 +197 -19
- 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/code-cell.ts +44 -3
- package/src/tui/index.ts +1 -0
- package/src/tui/width-aware-text.ts +58 -0
- package/src/utils/image-vision-fallback.ts +197 -0
- package/src/utils/markit.ts +17 -2
- package/src/web/search/index.ts +21 -9
- package/src/web/search/providers/base.ts +1 -0
- package/src/web/search/providers/gemini.ts +56 -18
- 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();
|
package/src/collab/host.ts
CHANGED
|
@@ -415,7 +415,7 @@ export class CollabHost {
|
|
|
415
415
|
// render exactly the same anchored, provider-real count the host's own
|
|
416
416
|
// status line shows.
|
|
417
417
|
const breakdown = this.#ctx.statusLine.getCachedContextBreakdown();
|
|
418
|
-
const tokens = breakdown.usedTokens;
|
|
418
|
+
const tokens = breakdown.usedTokens ?? 0;
|
|
419
419
|
return {
|
|
420
420
|
isStreaming: session.isStreaming,
|
|
421
421
|
isAborting: session.isAborting,
|
|
@@ -427,7 +427,7 @@ export class CollabHost {
|
|
|
427
427
|
contextUsage: {
|
|
428
428
|
tokens,
|
|
429
429
|
contextWindow: breakdown.contextWindow,
|
|
430
|
-
percent:
|
|
430
|
+
percent: breakdown.contextWindow > 0 ? (tokens / breakdown.contextWindow) * 100 : 0,
|
|
431
431
|
},
|
|
432
432
|
participants: this.participants,
|
|
433
433
|
};
|
package/src/commands/launch.ts
CHANGED
|
@@ -136,6 +136,9 @@ export default class Index extends Command {
|
|
|
136
136
|
"no-title": Flags.boolean({
|
|
137
137
|
description: "Disable title auto-generation",
|
|
138
138
|
}),
|
|
139
|
+
"max-time": Flags.string({
|
|
140
|
+
description: "Stop the session after this many seconds",
|
|
141
|
+
}),
|
|
139
142
|
// `--auto-approve` / `--yolo`: declared here so oclif's auto-generated `--help` lists it.
|
|
140
143
|
// Runtime parsing happens in `cli/args.ts parseArgs` (line 176 in that file) — `runRootCommand`
|
|
141
144
|
// consumes the manual-parser output, not these oclif flag values. If you rename or remove
|
|
@@ -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);
|