@oh-my-pi/pi-coding-agent 15.5.15 → 15.7.0
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 +81 -0
- package/dist/types/capability/rule-buckets.d.ts +30 -0
- package/dist/types/capability/rule.d.ts +7 -0
- package/dist/types/cli/classify-install-target.d.ts +0 -10
- package/dist/types/cli/completion-gen.d.ts +80 -0
- package/dist/types/cli/initial-message.d.ts +1 -1
- package/dist/types/cli/tiny-models-cli.d.ts +9 -0
- package/dist/types/commands/complete.d.ts +6 -0
- package/dist/types/commands/completions.d.ts +13 -0
- package/dist/types/commands/setup.d.ts +10 -1
- package/dist/types/commands/tiny-models.d.ts +22 -0
- package/dist/types/commit/analysis/conventional.d.ts +1 -1
- package/dist/types/commit/analysis/summary.d.ts +1 -1
- package/dist/types/commit/changelog/generate.d.ts +1 -1
- package/dist/types/commit/changelog/index.d.ts +2 -2
- package/dist/types/commit/map-reduce/map-phase.d.ts +1 -1
- package/dist/types/commit/map-reduce/reduce-phase.d.ts +1 -1
- package/dist/types/config/model-id-affixes.d.ts +10 -0
- package/dist/types/config/settings-schema.d.ts +402 -17
- package/dist/types/discovery/builtin-defaults.d.ts +1 -0
- package/dist/types/discovery/builtin-rules/index.d.ts +7 -0
- package/dist/types/discovery/helpers.d.ts +1 -1
- package/dist/types/discovery/index.d.ts +1 -0
- package/dist/types/discovery/substitute-plugin-root.d.ts +0 -4
- package/dist/types/edit/hashline/block-resolver.d.ts +9 -0
- package/dist/types/edit/hashline/index.d.ts +1 -0
- package/dist/types/eval/js/shared/rewrite-imports.d.ts +16 -1
- package/dist/types/eval/py/kernel.d.ts +3 -0
- package/dist/types/eval/py/runtime.d.ts +11 -1
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/internal-urls/agent-protocol.d.ts +2 -1
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -1
- package/dist/types/internal-urls/local-protocol.d.ts +2 -1
- package/dist/types/internal-urls/memory-protocol.d.ts +2 -1
- package/dist/types/internal-urls/omp-protocol.d.ts +2 -1
- package/dist/types/internal-urls/router.d.ts +8 -1
- package/dist/types/internal-urls/rule-protocol.d.ts +2 -1
- package/dist/types/internal-urls/skill-protocol.d.ts +2 -1
- package/dist/types/internal-urls/types.d.ts +26 -0
- package/dist/types/main.d.ts +1 -0
- package/dist/types/memory-backend/index.d.ts +1 -0
- package/dist/types/memory-backend/resolve.d.ts +2 -1
- package/dist/types/memory-backend/types.d.ts +7 -1
- package/dist/types/mnemosyne/backend.d.ts +4 -0
- package/dist/types/mnemosyne/config.d.ts +29 -0
- package/dist/types/mnemosyne/index.d.ts +3 -0
- package/dist/types/mnemosyne/state.d.ts +72 -0
- package/dist/types/modes/components/custom-editor.d.ts +2 -3
- package/dist/types/modes/components/hook-selector.d.ts +27 -0
- package/dist/types/modes/components/index.d.ts +2 -0
- package/dist/types/modes/components/segment-track.d.ts +22 -0
- package/dist/types/modes/components/status-line/context-thresholds.d.ts +6 -0
- package/dist/types/modes/components/tiny-title-download-progress.d.ts +11 -0
- package/dist/types/modes/components/welcome.d.ts +22 -0
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +4 -1
- package/dist/types/modes/gradient-highlight.d.ts +23 -0
- package/dist/types/modes/interactive-mode.d.ts +7 -4
- package/dist/types/modes/internal-url-autocomplete.d.ts +43 -0
- package/dist/types/modes/orchestrate.d.ts +10 -0
- package/dist/types/modes/setup-wizard/index.d.ts +16 -0
- package/dist/types/modes/setup-wizard/scenes/glyph.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/outro.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/providers.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +19 -0
- package/dist/types/modes/setup-wizard/scenes/splash.d.ts +11 -0
- package/dist/types/modes/setup-wizard/scenes/theme.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/types.d.ts +43 -0
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +19 -0
- package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +14 -0
- package/dist/types/modes/theme/defaults/index.d.ts +8406 -8406
- package/dist/types/modes/theme/shimmer.d.ts +2 -0
- package/dist/types/modes/theme/theme.d.ts +11 -0
- package/dist/types/modes/types.d.ts +5 -1
- package/dist/types/modes/ultrathink.d.ts +3 -3
- package/dist/types/modes/utils/keybinding-matchers.d.ts +5 -0
- package/dist/types/sdk.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +33 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +2 -0
- package/dist/types/task/render.d.ts +5 -1
- package/dist/types/tiny/device.d.ts +78 -0
- package/dist/types/tiny/dtype.d.ts +85 -0
- package/dist/types/tiny/models.d.ts +185 -0
- package/dist/types/tiny/text.d.ts +19 -0
- package/dist/types/tiny/title-client.d.ts +32 -0
- package/dist/types/tiny/title-protocol.d.ts +74 -0
- package/dist/types/tiny/worker.d.ts +2 -0
- package/dist/types/tools/bash.d.ts +3 -2
- package/dist/types/tools/eval.d.ts +1 -1
- package/dist/types/tools/index.d.ts +7 -4
- package/dist/types/tools/memory-edit.d.ts +40 -0
- package/dist/types/tools/{hindsight-recall.d.ts → memory-recall.d.ts} +6 -6
- package/dist/types/tools/{hindsight-reflect.d.ts → memory-reflect.d.ts} +6 -6
- package/dist/types/tools/memory-render.d.ts +60 -0
- package/dist/types/tools/{hindsight-retain.d.ts → memory-retain.d.ts} +6 -6
- package/dist/types/tools/todo-write.d.ts +8 -0
- package/dist/types/tools/tool-result.d.ts +2 -0
- package/dist/types/tui/code-cell.d.ts +2 -0
- package/dist/types/tui/output-block.d.ts +17 -0
- package/dist/types/utils/title-generator.d.ts +3 -0
- package/package.json +18 -14
- package/scripts/build-binary.ts +1 -0
- package/src/capability/rule-buckets.ts +64 -0
- package/src/capability/rule.ts +8 -0
- package/src/cli/completion-gen.ts +550 -0
- package/src/cli/setup-cli.ts +5 -3
- package/src/cli/tiny-models-cli.ts +127 -0
- package/src/cli-commands.ts +3 -0
- package/src/cli.ts +9 -15
- package/src/commands/complete.ts +66 -0
- package/src/commands/completions.ts +60 -0
- package/src/commands/setup.ts +29 -4
- package/src/commands/tiny-models.ts +36 -0
- package/src/config/model-equivalence.ts +43 -2
- package/src/config/model-id-affixes.ts +64 -0
- package/src/config/model-registry.ts +84 -10
- package/src/config/settings-schema.ts +275 -15
- package/src/discovery/builtin-defaults.ts +39 -0
- package/src/discovery/builtin-rules/index.ts +48 -0
- package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
- package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
- package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
- package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
- package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
- package/src/discovery/builtin-rules/rs-result-type.md +19 -0
- package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
- package/src/discovery/builtin-rules/ts-import-type.md +42 -0
- package/src/discovery/builtin-rules/ts-no-any.md +56 -0
- package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
- package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
- package/src/discovery/builtin-rules/ts-no-tiny-functions.md +50 -0
- package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
- package/src/discovery/builtin-rules/ts-set-map.md +28 -0
- package/src/discovery/index.ts +1 -0
- package/src/edit/hashline/block-resolver.ts +14 -0
- package/src/edit/hashline/diff.ts +9 -8
- package/src/edit/hashline/execute.ts +2 -1
- package/src/edit/hashline/index.ts +1 -0
- package/src/eval/__tests__/shared-executors.test.ts +36 -0
- package/src/eval/js/shared/local-module-loader.ts +13 -1
- package/src/eval/js/shared/rewrite-imports.ts +31 -26
- package/src/eval/py/kernel.ts +37 -15
- package/src/eval/py/runtime.ts +57 -28
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +0 -12
- package/src/export/ttsr.ts +2 -0
- package/src/internal-urls/agent-protocol.ts +18 -1
- package/src/internal-urls/artifact-protocol.ts +19 -1
- package/src/internal-urls/docs-index.generated.ts +8 -7
- package/src/internal-urls/local-protocol.ts +14 -1
- package/src/internal-urls/memory-protocol.ts +6 -1
- package/src/internal-urls/omp-protocol.ts +5 -1
- package/src/internal-urls/router.ts +20 -1
- package/src/internal-urls/rule-protocol.ts +8 -1
- package/src/internal-urls/skill-protocol.ts +8 -1
- package/src/internal-urls/types.ts +27 -0
- package/src/lsp/render.ts +1 -1
- package/src/main.ts +18 -1
- package/src/mcp/oauth-flow.ts +2 -2
- package/src/memory-backend/index.ts +1 -0
- package/src/memory-backend/resolve.ts +4 -1
- package/src/memory-backend/types.ts +8 -1
- package/src/mnemosyne/backend.ts +374 -0
- package/src/mnemosyne/config.ts +160 -0
- package/src/mnemosyne/index.ts +3 -0
- package/src/mnemosyne/state.ts +548 -0
- package/src/modes/acp/acp-agent.ts +11 -6
- package/src/modes/components/agent-dashboard.ts +4 -4
- package/src/modes/components/custom-editor.ts +3 -2
- package/src/modes/components/diff.ts +2 -2
- package/src/modes/components/extensions/extension-list.ts +3 -2
- package/src/modes/components/footer.ts +5 -6
- package/src/modes/components/history-search.ts +3 -3
- package/src/modes/components/hook-selector.ts +92 -8
- package/src/modes/components/index.ts +2 -0
- package/src/modes/components/mcp-add-wizard.ts +3 -3
- package/src/modes/components/model-selector.ts +5 -4
- package/src/modes/components/oauth-selector.ts +3 -3
- package/src/modes/components/segment-track.ts +52 -0
- package/src/modes/components/session-observer-overlay.ts +19 -13
- package/src/modes/components/session-selector.ts +3 -3
- package/src/modes/components/settings-defs.ts +7 -0
- package/src/modes/components/status-line/context-thresholds.ts +11 -0
- package/src/modes/components/status-line/segments.ts +2 -2
- package/src/modes/components/tiny-title-download-progress.ts +90 -0
- package/src/modes/components/tips.txt +13 -0
- package/src/modes/components/tool-execution.ts +72 -4
- package/src/modes/components/tree-selector.ts +3 -3
- package/src/modes/components/user-message-selector.ts +3 -3
- package/src/modes/components/welcome.ts +102 -43
- package/src/modes/controllers/command-controller.ts +16 -1
- package/src/modes/controllers/extension-ui-controller.ts +3 -1
- package/src/modes/controllers/input-controller.ts +69 -21
- package/src/modes/gradient-highlight.ts +70 -0
- package/src/modes/interactive-mode.ts +75 -114
- package/src/modes/internal-url-autocomplete.ts +143 -0
- package/src/modes/orchestrate.ts +36 -0
- package/src/modes/prompt-action-autocomplete.ts +12 -0
- package/src/modes/setup-wizard/index.ts +88 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +96 -0
- package/src/modes/setup-wizard/scenes/outro.ts +35 -0
- package/src/modes/setup-wizard/scenes/providers.ts +69 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +193 -0
- package/src/modes/setup-wizard/scenes/splash.ts +201 -0
- package/src/modes/setup-wizard/scenes/theme.ts +299 -0
- package/src/modes/setup-wizard/scenes/types.ts +48 -0
- package/src/modes/setup-wizard/scenes/web-search.ts +128 -0
- package/src/modes/setup-wizard/wizard-overlay.ts +275 -0
- package/src/modes/theme/shimmer.ts +5 -0
- package/src/modes/theme/theme.ts +44 -20
- package/src/modes/types.ts +6 -1
- package/src/modes/ultrathink.ts +9 -53
- package/src/modes/utils/keybinding-matchers.ts +11 -0
- package/src/prompts/system/memory-consolidation-system.md +8 -0
- package/src/prompts/system/memory-extraction-system.md +26 -0
- package/src/prompts/{commands/orchestrate.md → system/orchestrate-notice.md} +6 -17
- package/src/prompts/system/system-prompt.md +2 -0
- package/src/prompts/system/tiny-title-system.md +8 -0
- package/src/prompts/tools/memory-edit.md +8 -0
- package/src/prompts/tools/read.md +4 -0
- package/src/prompts/tools/task.md +4 -7
- package/src/sdk.ts +13 -21
- package/src/session/agent-session.ts +128 -44
- package/src/slash-commands/builtin-registry.ts +18 -1
- package/src/system-prompt.ts +4 -0
- package/src/task/commands.ts +1 -5
- package/src/task/executor.ts +8 -0
- package/src/task/index.ts +2 -0
- package/src/task/render.ts +69 -26
- package/src/tiny/device.ts +117 -0
- package/src/tiny/dtype.ts +101 -0
- package/src/tiny/models.ts +218 -0
- package/src/tiny/text.ts +54 -0
- package/src/tiny/title-client.ts +395 -0
- package/src/tiny/title-protocol.ts +51 -0
- package/src/tiny/worker.ts +587 -0
- package/src/tools/bash.ts +74 -29
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/eval.ts +9 -4
- package/src/tools/index.ts +17 -22
- package/src/tools/memory-edit.ts +59 -0
- package/src/tools/memory-recall.ts +100 -0
- package/src/tools/memory-reflect.ts +88 -0
- package/src/tools/memory-render.ts +185 -0
- package/src/tools/memory-retain.ts +91 -0
- package/src/tools/read.ts +1 -0
- package/src/tools/renderers.ts +4 -2
- package/src/tools/todo-write.ts +128 -29
- package/src/tools/tool-result.ts +8 -0
- package/src/tui/code-cell.ts +6 -1
- package/src/tui/output-block.ts +199 -38
- package/src/utils/title-generator.ts +115 -13
- package/dist/types/tools/recipe/index.d.ts +0 -46
- package/dist/types/tools/recipe/render.d.ts +0 -36
- package/dist/types/tools/recipe/runner.d.ts +0 -60
- package/dist/types/tools/recipe/runners/cargo.d.ts +0 -16
- package/dist/types/tools/recipe/runners/index.d.ts +0 -2
- package/dist/types/tools/recipe/runners/just.d.ts +0 -2
- package/dist/types/tools/recipe/runners/make.d.ts +0 -2
- package/dist/types/tools/recipe/runners/pkg.d.ts +0 -2
- package/dist/types/tools/recipe/runners/task.d.ts +0 -2
- package/src/prompts/tools/recipe.md +0 -16
- package/src/tools/hindsight-recall.ts +0 -69
- package/src/tools/hindsight-reflect.ts +0 -58
- package/src/tools/hindsight-retain.ts +0 -57
- package/src/tools/recipe/index.ts +0 -81
- package/src/tools/recipe/render.ts +0 -19
- package/src/tools/recipe/runner.ts +0 -219
- package/src/tools/recipe/runners/cargo.ts +0 -131
- package/src/tools/recipe/runners/index.ts +0 -8
- package/src/tools/recipe/runners/just.ts +0 -73
- package/src/tools/recipe/runners/make.ts +0 -101
- package/src/tools/recipe/runners/pkg.ts +0 -167
- package/src/tools/recipe/runners/task.ts +0 -72
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { type Component, matchesKey, padding, truncateToWidth, visibleWidth } from "@oh-my-pi/pi-tui";
|
|
2
|
+
import { APP_NAME } from "@oh-my-pi/pi-utils";
|
|
3
|
+
import { gradientLogo, PI_LOGO } from "../components/welcome";
|
|
4
|
+
import { theme } from "../theme/theme";
|
|
5
|
+
import type { InteractiveModeContext } from "../types";
|
|
6
|
+
import { renderSetupOutro, SETUP_OUTRO_MS } from "./scenes/outro";
|
|
7
|
+
import { renderSetupSplash, SETUP_SPLASH_MS, SETUP_TICK_MS } from "./scenes/splash";
|
|
8
|
+
import type { SetupScene, SetupSceneController, SetupSceneHost, SetupSceneResult } from "./scenes/types";
|
|
9
|
+
|
|
10
|
+
type WizardPhase = "splash" | "transition" | "scene" | "outro" | "done";
|
|
11
|
+
|
|
12
|
+
const SCENE_MARGIN_X = 4;
|
|
13
|
+
const MIN_CONTENT_WIDTH = 20;
|
|
14
|
+
/** Cross-dissolve duration from the splash into the first scene. */
|
|
15
|
+
const SCENE_TRANSITION_MS = 420;
|
|
16
|
+
|
|
17
|
+
function centerLine(line: string, width: number): string {
|
|
18
|
+
const lineWidth = visibleWidth(line);
|
|
19
|
+
if (lineWidth >= width) return truncateToWidth(line, width);
|
|
20
|
+
const left = Math.floor((width - lineWidth) / 2);
|
|
21
|
+
return padding(left) + line + padding(width - left - lineWidth);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function clampLine(line: string, width: number): string {
|
|
25
|
+
const truncated = truncateToWidth(line, width);
|
|
26
|
+
return truncated + padding(Math.max(0, width - visibleWidth(truncated)));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function indentLine(line: string, width: number, indent: number): string {
|
|
30
|
+
const prefix = padding(Math.min(indent, Math.max(0, width - 1)));
|
|
31
|
+
return clampLine(prefix + line, width);
|
|
32
|
+
}
|
|
33
|
+
/** Stable per-row jitter in [0,1) for the dissolve reveal order. */
|
|
34
|
+
function rowNoise(y: number): number {
|
|
35
|
+
const h = Math.imul(y ^ 0x9e3779b9, 2654435761);
|
|
36
|
+
return ((h ^ (h >>> 15)) >>> 0) / 4294967296;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Top-biased cross-dissolve between two equal-height frames. As `progress`
|
|
41
|
+
* (0..1) advances, each row flips from `from` to `to` once it crosses a per-row
|
|
42
|
+
* threshold — top rows reveal first (so the scene's mark/header materializes
|
|
43
|
+
* before the splash water below it), with a little jitter for an organic edge.
|
|
44
|
+
*/
|
|
45
|
+
function dissolveFrames(from: string[], to: string[], progress: number, height: number): string[] {
|
|
46
|
+
const eased = progress * progress * (3 - 2 * progress);
|
|
47
|
+
const denom = Math.max(1, height - 1);
|
|
48
|
+
const out: string[] = [];
|
|
49
|
+
for (let y = 0; y < height; y++) {
|
|
50
|
+
const threshold = 0.78 * (y / denom) + 0.22 * rowNoise(y);
|
|
51
|
+
out.push((eased >= threshold ? to[y] : from[y]) ?? "");
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export class SetupWizardComponent implements Component {
|
|
57
|
+
#phase: WizardPhase = "splash";
|
|
58
|
+
#phaseStartedAt = performance.now();
|
|
59
|
+
#sceneIndex = 0;
|
|
60
|
+
#activeScene: SetupSceneController | undefined;
|
|
61
|
+
#timer: NodeJS.Timeout | undefined;
|
|
62
|
+
#done = Promise.withResolvers<void>();
|
|
63
|
+
#disposed = false;
|
|
64
|
+
|
|
65
|
+
constructor(
|
|
66
|
+
readonly ctx: InteractiveModeContext,
|
|
67
|
+
readonly scenes: readonly SetupScene[],
|
|
68
|
+
) {}
|
|
69
|
+
|
|
70
|
+
run(): Promise<void> {
|
|
71
|
+
this.#phase = this.scenes.length === 0 ? "outro" : "splash";
|
|
72
|
+
this.#phaseStartedAt = performance.now();
|
|
73
|
+
this.#startTimer();
|
|
74
|
+
this.ctx.ui.requestRender();
|
|
75
|
+
return this.#done.promise;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
dispose(): void {
|
|
79
|
+
this.#disposed = true;
|
|
80
|
+
this.#stopTimer();
|
|
81
|
+
this.#unmountActiveScene();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
invalidate(): void {
|
|
85
|
+
this.#activeScene?.invalidate();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
handleInput(data: string): void {
|
|
89
|
+
if (this.#phase === "done") return;
|
|
90
|
+
if (matchesKey(data, "ctrl+c")) {
|
|
91
|
+
this.#beginOutro();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (this.#phase === "splash") {
|
|
95
|
+
if (
|
|
96
|
+
matchesKey(data, "enter") ||
|
|
97
|
+
matchesKey(data, "return") ||
|
|
98
|
+
matchesKey(data, "space") ||
|
|
99
|
+
matchesKey(data, "escape")
|
|
100
|
+
) {
|
|
101
|
+
this.#beginScene();
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (this.#phase === "outro") {
|
|
106
|
+
if (
|
|
107
|
+
matchesKey(data, "enter") ||
|
|
108
|
+
matchesKey(data, "return") ||
|
|
109
|
+
matchesKey(data, "space") ||
|
|
110
|
+
matchesKey(data, "escape")
|
|
111
|
+
) {
|
|
112
|
+
this.#complete();
|
|
113
|
+
}
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
this.#activeScene?.handleInput?.(data);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
render(width: number): string[] {
|
|
120
|
+
const safeWidth = Math.max(1, width);
|
|
121
|
+
const height = Math.max(1, this.ctx.ui.terminal.rows);
|
|
122
|
+
let lines: string[];
|
|
123
|
+
switch (this.#phase) {
|
|
124
|
+
case "splash":
|
|
125
|
+
lines = renderSetupSplash(safeWidth, height, performance.now() - this.#phaseStartedAt);
|
|
126
|
+
break;
|
|
127
|
+
case "transition": {
|
|
128
|
+
const elapsed = performance.now() - this.#phaseStartedAt;
|
|
129
|
+
const progress = Math.min(1, elapsed / SCENE_TRANSITION_MS);
|
|
130
|
+
const splash = renderSetupSplash(safeWidth, height, SETUP_SPLASH_MS + elapsed);
|
|
131
|
+
const scene = this.#renderScene(safeWidth, height);
|
|
132
|
+
lines = dissolveFrames(splash, scene, progress, height);
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
case "outro":
|
|
136
|
+
lines = renderSetupOutro(safeWidth, height, performance.now() - this.#phaseStartedAt);
|
|
137
|
+
break;
|
|
138
|
+
case "scene":
|
|
139
|
+
lines = this.#renderScene(safeWidth, height);
|
|
140
|
+
break;
|
|
141
|
+
case "done":
|
|
142
|
+
lines = [];
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
return this.#fitToScreen(lines, safeWidth, height);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
#renderScene(width: number, height: number): string[] {
|
|
149
|
+
const scene = this.scenes[this.#sceneIndex];
|
|
150
|
+
const title = this.#activeScene?.title ?? scene?.title ?? "Setup";
|
|
151
|
+
const subtitle = this.#activeScene?.subtitle;
|
|
152
|
+
const contentWidth = Math.max(MIN_CONTENT_WIDTH, width - SCENE_MARGIN_X * 2);
|
|
153
|
+
const logo = gradientLogo(PI_LOGO, 0);
|
|
154
|
+
const header = [
|
|
155
|
+
"",
|
|
156
|
+
...logo.map(line => centerLine(line, width)),
|
|
157
|
+
centerLine(theme.bold(theme.fg("accent", APP_NAME)), width),
|
|
158
|
+
centerLine(theme.fg("muted", `Setup step ${this.#sceneIndex + 1} of ${this.scenes.length}`), width),
|
|
159
|
+
"",
|
|
160
|
+
indentLine(theme.bold(title), width, SCENE_MARGIN_X),
|
|
161
|
+
];
|
|
162
|
+
if (subtitle) {
|
|
163
|
+
header.push(indentLine(theme.fg("muted", subtitle), width, SCENE_MARGIN_X));
|
|
164
|
+
}
|
|
165
|
+
header.push("");
|
|
166
|
+
|
|
167
|
+
const footer = [
|
|
168
|
+
"",
|
|
169
|
+
centerLine(theme.fg("dim", "↑/↓ select · enter confirm · esc skip · ctrl+c exit setup"), width),
|
|
170
|
+
];
|
|
171
|
+
const maxBodyLines = Math.max(0, height - header.length - footer.length);
|
|
172
|
+
const body = this.#activeScene?.render(contentWidth).slice(0, maxBodyLines) ?? [];
|
|
173
|
+
const lines = [...header, ...body.map(line => indentLine(line, width, SCENE_MARGIN_X))];
|
|
174
|
+
while (lines.length + footer.length < height) {
|
|
175
|
+
lines.push("");
|
|
176
|
+
}
|
|
177
|
+
lines.push(...footer);
|
|
178
|
+
return lines;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
#fitToScreen(lines: string[], width: number, height: number): string[] {
|
|
182
|
+
const fitted = lines.slice(0, height).map(line => clampLine(line, width));
|
|
183
|
+
while (fitted.length < height) {
|
|
184
|
+
fitted.push(padding(width));
|
|
185
|
+
}
|
|
186
|
+
return fitted;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
#startTimer(): void {
|
|
190
|
+
if (this.#timer) return;
|
|
191
|
+
this.#timer = setInterval(() => {
|
|
192
|
+
if (this.#disposed) return;
|
|
193
|
+
const elapsed = performance.now() - this.#phaseStartedAt;
|
|
194
|
+
if (this.#phase === "splash" && elapsed >= SETUP_SPLASH_MS) {
|
|
195
|
+
this.#beginScene();
|
|
196
|
+
} else if (this.#phase === "transition" && elapsed >= SCENE_TRANSITION_MS) {
|
|
197
|
+
this.#phase = "scene";
|
|
198
|
+
this.#phaseStartedAt = performance.now();
|
|
199
|
+
this.ctx.ui.requestRender();
|
|
200
|
+
} else if (this.#phase === "outro" && elapsed >= SETUP_OUTRO_MS) {
|
|
201
|
+
this.#complete();
|
|
202
|
+
} else {
|
|
203
|
+
this.ctx.ui.requestRender();
|
|
204
|
+
}
|
|
205
|
+
}, SETUP_TICK_MS);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
#stopTimer(): void {
|
|
209
|
+
if (!this.#timer) return;
|
|
210
|
+
clearInterval(this.#timer);
|
|
211
|
+
this.#timer = undefined;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
#mountSceneController(targetPhase: "scene" | "transition"): void {
|
|
215
|
+
if (this.#disposed) return;
|
|
216
|
+
this.#unmountActiveScene();
|
|
217
|
+
if (this.#sceneIndex >= this.scenes.length) {
|
|
218
|
+
this.#beginOutro();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
const scene = this.scenes[this.#sceneIndex];
|
|
222
|
+
const host: SetupSceneHost = {
|
|
223
|
+
ctx: this.ctx,
|
|
224
|
+
requestRender: () => this.ctx.ui.requestRender(),
|
|
225
|
+
finish: (_result: SetupSceneResult) => this.#finishScene(),
|
|
226
|
+
setFocus: component => this.ctx.ui.setFocus(component),
|
|
227
|
+
restoreFocus: () => this.ctx.ui.setFocus(this),
|
|
228
|
+
};
|
|
229
|
+
this.#activeScene = scene.mount(host);
|
|
230
|
+
this.#phase = targetPhase;
|
|
231
|
+
this.#phaseStartedAt = performance.now();
|
|
232
|
+
this.ctx.ui.setFocus(this);
|
|
233
|
+
void this.#activeScene.onMount?.();
|
|
234
|
+
this.ctx.ui.requestRender();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Enter the first scene through a dissolve from the splash. */
|
|
238
|
+
#beginScene(): void {
|
|
239
|
+
this.#mountSceneController("transition");
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
#mountCurrentScene(): void {
|
|
243
|
+
this.#mountSceneController("scene");
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
#finishScene(): void {
|
|
247
|
+
if (this.#phase !== "scene" && this.#phase !== "transition") return;
|
|
248
|
+
this.#unmountActiveScene();
|
|
249
|
+
this.#sceneIndex += 1;
|
|
250
|
+
this.#mountCurrentScene();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
#unmountActiveScene(): void {
|
|
254
|
+
this.#activeScene?.onUnmount?.();
|
|
255
|
+
this.#activeScene?.dispose?.();
|
|
256
|
+
this.#activeScene = undefined;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
#beginOutro(): void {
|
|
260
|
+
if (this.#phase === "done") return;
|
|
261
|
+
this.#unmountActiveScene();
|
|
262
|
+
this.#phase = "outro";
|
|
263
|
+
this.#phaseStartedAt = performance.now();
|
|
264
|
+
this.ctx.ui.setFocus(this);
|
|
265
|
+
this.#startTimer();
|
|
266
|
+
this.ctx.ui.requestRender();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
#complete(): void {
|
|
270
|
+
if (this.#phase === "done") return;
|
|
271
|
+
this.#phase = "done";
|
|
272
|
+
this.#stopTimer();
|
|
273
|
+
this.#done.resolve();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
@@ -147,6 +147,11 @@ function resolveMode(): ShimmerMode {
|
|
|
147
147
|
return settings.get("display.shimmer");
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
/** Whether shimmer animations are active (any mode other than `disabled`). */
|
|
151
|
+
export function shimmerEnabled(): boolean {
|
|
152
|
+
return resolveMode() !== "disabled";
|
|
153
|
+
}
|
|
154
|
+
|
|
150
155
|
/**
|
|
151
156
|
* Apply a shimmer sweep across one or more segments, treating them as a
|
|
152
157
|
* single continuous string for band positioning. Each segment can supply
|
package/src/modes/theme/theme.ts
CHANGED
|
@@ -1310,6 +1310,24 @@ export class Theme {
|
|
|
1310
1310
|
return ansi;
|
|
1311
1311
|
}
|
|
1312
1312
|
|
|
1313
|
+
/**
|
|
1314
|
+
* Foreground ANSI for text drawn **on top of** `fillColor` used as a solid
|
|
1315
|
+
* background (e.g. a powerline chip). Picks near-black or near-white by the
|
|
1316
|
+
* fill's perceived luminance (Rec. 601 luma) so the label stays legible on
|
|
1317
|
+
* both bright and dark fills, across light and dark themes.
|
|
1318
|
+
*
|
|
1319
|
+
* Reads the RGB out of the already-resolved truecolor escape; when the fill
|
|
1320
|
+
* is encoded as a 256-palette index (limited terminals) the RGB is
|
|
1321
|
+
* unavailable, so it falls back to the theme `text` color.
|
|
1322
|
+
*/
|
|
1323
|
+
getContrastFgAnsi(fillColor: ThemeColor): string {
|
|
1324
|
+
const ansi = this.#fgColors[fillColor];
|
|
1325
|
+
const match = ansi ? /38;2;(\d+);(\d+);(\d+)/.exec(ansi) : null;
|
|
1326
|
+
if (!match) return this.#fgColors.text;
|
|
1327
|
+
const luma = 0.299 * Number(match[1]) + 0.587 * Number(match[2]) + 0.114 * Number(match[3]);
|
|
1328
|
+
return luma > 140 ? "\x1b[38;2;0;0;0m" : "\x1b[38;2;255;255;255m";
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1313
1331
|
getColorMode(): ColorMode {
|
|
1314
1332
|
return this.mode;
|
|
1315
1333
|
}
|
|
@@ -1929,17 +1947,20 @@ export function setThemeInstance(themeInstance: Theme): void {
|
|
|
1929
1947
|
*/
|
|
1930
1948
|
export async function setSymbolPreset(preset: SymbolPreset): Promise<void> {
|
|
1931
1949
|
currentSymbolPresetOverride = preset;
|
|
1932
|
-
if (currentThemeName)
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1950
|
+
if (!currentThemeName) return;
|
|
1951
|
+
|
|
1952
|
+
const requestId = ++themeLoadRequestId;
|
|
1953
|
+
try {
|
|
1954
|
+
const loadedTheme = await loadTheme(currentThemeName, getCurrentThemeOptions());
|
|
1955
|
+
if (requestId !== themeLoadRequestId) return;
|
|
1956
|
+
theme = loadedTheme;
|
|
1957
|
+
} catch {
|
|
1958
|
+
if (requestId !== themeLoadRequestId) return;
|
|
1959
|
+
// Fall back to dark theme with new preset
|
|
1960
|
+
theme = await loadTheme("dark", getCurrentThemeOptions());
|
|
1961
|
+
if (requestId !== themeLoadRequestId) return;
|
|
1942
1962
|
}
|
|
1963
|
+
onThemeChangeCallback?.();
|
|
1943
1964
|
}
|
|
1944
1965
|
|
|
1945
1966
|
/**
|
|
@@ -1955,17 +1976,20 @@ export function getSymbolPresetOverride(): SymbolPreset | undefined {
|
|
|
1955
1976
|
*/
|
|
1956
1977
|
export async function setColorBlindMode(enabled: boolean): Promise<void> {
|
|
1957
1978
|
currentColorBlindMode = enabled;
|
|
1958
|
-
if (currentThemeName)
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1979
|
+
if (!currentThemeName) return;
|
|
1980
|
+
|
|
1981
|
+
const requestId = ++themeLoadRequestId;
|
|
1982
|
+
try {
|
|
1983
|
+
const loadedTheme = await loadTheme(currentThemeName, getCurrentThemeOptions());
|
|
1984
|
+
if (requestId !== themeLoadRequestId) return;
|
|
1985
|
+
theme = loadedTheme;
|
|
1986
|
+
} catch {
|
|
1987
|
+
if (requestId !== themeLoadRequestId) return;
|
|
1988
|
+
// Fall back to dark theme
|
|
1989
|
+
theme = await loadTheme("dark", getCurrentThemeOptions());
|
|
1990
|
+
if (requestId !== themeLoadRequestId) return;
|
|
1968
1991
|
}
|
|
1992
|
+
onThemeChangeCallback?.();
|
|
1969
1993
|
}
|
|
1970
1994
|
|
|
1971
1995
|
/**
|
package/src/modes/types.ts
CHANGED
|
@@ -58,6 +58,10 @@ export type TodoPhase = {
|
|
|
58
58
|
tasks: TodoItem[];
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
+
export interface InteractiveModeInitOptions {
|
|
62
|
+
suppressWelcomeIntro?: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
61
65
|
export interface InteractiveModeContext {
|
|
62
66
|
// UI access
|
|
63
67
|
ui: TUI;
|
|
@@ -129,7 +133,8 @@ export interface InteractiveModeContext {
|
|
|
129
133
|
todoPhases: TodoPhase[];
|
|
130
134
|
|
|
131
135
|
// Lifecycle
|
|
132
|
-
init(): Promise<void>;
|
|
136
|
+
init(options?: InteractiveModeInitOptions): Promise<void>;
|
|
137
|
+
playWelcomeIntro(): void;
|
|
133
138
|
shutdown(): Promise<void>;
|
|
134
139
|
checkShutdownRequested(): Promise<void>;
|
|
135
140
|
|
package/src/modes/ultrathink.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ultrathinkNotice from "../prompts/system/ultrathink-notice.md" with { type: "text" };
|
|
2
|
-
import {
|
|
2
|
+
import { createGradientHighlighter } from "./gradient-highlight";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* "ultrathink" keyword support, mirroring Claude Code's affordance.
|
|
@@ -11,12 +11,8 @@ import { theme } from "./theme/theme";
|
|
|
11
11
|
* "ultrathinking"/"ultrathinks" never trigger either behavior.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
// Cheap, stateless presence probe used to skip the boundary regex on most lines.
|
|
15
|
-
const ULTRATHINK_PROBE = /ultrathink/i;
|
|
16
14
|
// Detection: standalone keyword, any case. Non-global so `.test` stays stateless.
|
|
17
15
|
const ULTRATHINK_WORD = /\bultrathink\b/i;
|
|
18
|
-
// Highlight: global so `.replace` walks every occurrence.
|
|
19
|
-
const ULTRATHINK_HIGHLIGHT = /\bultrathink\b/gi;
|
|
20
16
|
|
|
21
17
|
/** Hidden system notice appended after a user message that mentions "ultrathink". */
|
|
22
18
|
export const ULTRATHINK_NOTICE: string = ultrathinkNotice.trim();
|
|
@@ -26,54 +22,14 @@ export function containsUltrathink(text: string): boolean {
|
|
|
26
22
|
return ULTRATHINK_WORD.test(text);
|
|
27
23
|
}
|
|
28
24
|
|
|
29
|
-
const FG_RESET = "\x1b[39m";
|
|
30
|
-
// Hue stops swept across the visible spectrum. More stops than the keyword has
|
|
31
|
-
// letters so the gradient resolves smoothly regardless of casing/match length.
|
|
32
|
-
const RAINBOW_STOPS = 14;
|
|
33
|
-
|
|
34
|
-
let cachedMode: string | undefined;
|
|
35
|
-
let cachedPalette: readonly string[] | undefined;
|
|
36
|
-
|
|
37
|
-
/** Rainbow foreground escapes for the active color mode, compiled once per mode. */
|
|
38
|
-
function rainbowPalette(): readonly string[] {
|
|
39
|
-
const mode = theme.getColorMode();
|
|
40
|
-
if (cachedPalette && cachedMode === mode) return cachedPalette;
|
|
41
|
-
const format = mode === "truecolor" ? "ansi-16m" : "ansi-256";
|
|
42
|
-
const palette: string[] = [];
|
|
43
|
-
for (let i = 0; i < RAINBOW_STOPS; i++) {
|
|
44
|
-
// Sweep red→violet (0..330°), stopping short of the wrap back to red.
|
|
45
|
-
const hue = Math.round((i / RAINBOW_STOPS) * 330);
|
|
46
|
-
palette.push(Bun.color(`hsl(${hue}, 90%, 62%)`, format) ?? "");
|
|
47
|
-
}
|
|
48
|
-
cachedMode = mode;
|
|
49
|
-
cachedPalette = palette;
|
|
50
|
-
return palette;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** Paint each character of `word` with the next rainbow stop, resetting fg after. */
|
|
54
|
-
function rainbow(word: string): string {
|
|
55
|
-
const palette = rainbowPalette();
|
|
56
|
-
const n = word.length;
|
|
57
|
-
let out = "";
|
|
58
|
-
let prev = "";
|
|
59
|
-
for (let i = 0; i < n; i++) {
|
|
60
|
-
const color = palette[Math.floor((i / n) * palette.length)] ?? palette[0] ?? "";
|
|
61
|
-
// Coalesce consecutive characters that resolve to the same stop.
|
|
62
|
-
if (color !== prev) {
|
|
63
|
-
out += color;
|
|
64
|
-
prev = color;
|
|
65
|
-
}
|
|
66
|
-
out += word[i];
|
|
67
|
-
}
|
|
68
|
-
return `${out}${FG_RESET}`;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
25
|
/**
|
|
72
26
|
* Rainbow-highlight every standalone "ultrathink" in `text` for editor display.
|
|
73
|
-
*
|
|
74
|
-
*
|
|
27
|
+
* Sweeps red→violet (hue 0..330), stopping short of the wrap back to red so the
|
|
28
|
+
* gradient resolves smoothly regardless of casing or match length.
|
|
75
29
|
*/
|
|
76
|
-
export
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
30
|
+
export const highlightUltrathink: (text: string) => string = createGradientHighlighter({
|
|
31
|
+
probe: /ultrathink/i,
|
|
32
|
+
highlight: /\bultrathink\b/gi,
|
|
33
|
+
stops: 14,
|
|
34
|
+
hue: t => t * 330,
|
|
35
|
+
});
|
|
@@ -16,10 +16,21 @@ export function matchesAppInterrupt(data: string): boolean {
|
|
|
16
16
|
return matchesKey(data, "escape") || matchesKey(data, "esc");
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/** Match the generic selector cancel keybinding. */
|
|
19
20
|
export function matchesSelectCancel(data: string): boolean {
|
|
20
21
|
return getKeybindings().matches(data, "tui.select.cancel");
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
/** Match the generic selector up-navigation keybinding. */
|
|
25
|
+
export function matchesSelectUp(data: string): boolean {
|
|
26
|
+
return getKeybindings().matches(data, "tui.select.up");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Match the generic selector down-navigation keybinding. */
|
|
30
|
+
export function matchesSelectDown(data: string): boolean {
|
|
31
|
+
return getKeybindings().matches(data, "tui.select.down");
|
|
32
|
+
}
|
|
33
|
+
|
|
23
34
|
export function matchesAppExternalEditor(data: string): boolean {
|
|
24
35
|
const keybindings = getKeybindings();
|
|
25
36
|
const externalEditorKeys = keybindings.getKeys("app.editor.external");
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Summarize the memories below into 1-3 concise sentences.
|
|
2
|
+
|
|
3
|
+
Preserve every fact, name, number, version, date, and decision exactly. Merge duplicates and near-duplicates; never repeat the same point. When memories conflict, state only the most recent as current. Do not invent, infer, or add anything that is not present in the memories. Output only the summary sentences, nothing else.
|
|
4
|
+
|
|
5
|
+
Memories:
|
|
6
|
+
{memories}
|
|
7
|
+
|
|
8
|
+
Summary:
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Extract durable, long-term memory items from the user message below.
|
|
2
|
+
|
|
3
|
+
Output ONE item per line as a short plain-text statement: no JSON, no bullets, no numbering, no field labels.
|
|
4
|
+
Capture only persistent, reusable information:
|
|
5
|
+
- facts (name, role, employer, config, ports, versions, numbers)
|
|
6
|
+
- explicit instructions to the assistant
|
|
7
|
+
- stable preferences
|
|
8
|
+
- dated events or deadlines
|
|
9
|
+
|
|
10
|
+
Keep names, numbers, versions, and dates exact, in the message's original language. When a value is updated, output only the latest value. Ignore greetings, acknowledgements, small talk, weather, and one-off remarks.
|
|
11
|
+
If nothing qualifies, output exactly: NO_FACTS
|
|
12
|
+
|
|
13
|
+
Example
|
|
14
|
+
Message: My name is Sam, I work at Globex, and I always use 2-space indents.
|
|
15
|
+
Items:
|
|
16
|
+
name is Sam
|
|
17
|
+
works at Globex
|
|
18
|
+
prefers 2-space indents
|
|
19
|
+
|
|
20
|
+
Example
|
|
21
|
+
Message: lol nice weather today, might grab a coffee later
|
|
22
|
+
Items:
|
|
23
|
+
NO_FACTS
|
|
24
|
+
|
|
25
|
+
Message: {text}
|
|
26
|
+
Items:
|
|
@@ -1,29 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
description: Drive a multi-phase task to completion via parallel subagents
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Task
|
|
7
|
-
|
|
8
|
-
$@
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Orchestration Contract
|
|
13
|
-
|
|
14
|
-
You are the **orchestrator** for the task above. Read it once, then execute under the rules below. The contract overrides any default tendency to yield early, narrate, or do work yourself.
|
|
1
|
+
<system-notice>
|
|
2
|
+
The user's message above is an **orchestration request**. Execute it as the orchestrator under the contract below. This contract overrides any default tendency to yield early, narrate, or do the work yourself.
|
|
15
3
|
|
|
16
4
|
<role>
|
|
17
|
-
You decompose, dispatch, verify, and iterate. You do **not** edit code. Every file mutation goes through a `task` subagent. Your tool budget is: reading for planning, `task` for dispatch, verification (`bun check`, `bun test`, `
|
|
5
|
+
You decompose, dispatch, verify, and iterate. You do **not** edit code. Every file mutation goes through a `task` subagent. Your tool budget is: reading for planning, `task` for dispatch, verification (`bun check`, `bun test`, `lsp diagnostics`), git via `bash`, and `todo_write` for tracking.
|
|
18
6
|
</role>
|
|
19
7
|
|
|
20
8
|
<rules>
|
|
21
9
|
1. **Do not yield until everything is closed.** A phase finishing is *not* a yield point — launch the next phase in the same turn. Stop only when every requested item is verifiably done, or you hit a concrete [blocked] state that genuinely requires the user.
|
|
22
|
-
2. **Enumerate the full surface before dispatching.** If the
|
|
10
|
+
2. **Enumerate the full surface before dispatching.** If the request references audits, plans, checklists, phase lists, or file lists, expand them into a flat set of items in `todo_write`. "Most of them" or "the important ones" is failure. Re-read the source documents — do not work from memory.
|
|
23
11
|
3. **Parallelize maximally.** Every set of edits with disjoint file scope MUST ship as one `task` batch. Serialize only when one subagent produces a contract (types, schema, shared module) the next consumes — and state the dependency when you do.
|
|
24
12
|
4. **Each `task` assignment is self-contained.** Subagents have no shared context. Spell out: target files (≤3–5 explicit paths, no globs), the change with APIs and patterns, edge cases, and observable acceptance criteria. Do not assume they read the same plan you did.
|
|
25
13
|
5. **Verify after every phase before launching the next.** Run the appropriate gate: `bun check` for types, package-scoped `bun test` for behavior, `lsp diagnostics` for changed files. If a phase introduced breakage, dispatch fix-up subagents *before* moving on. Never declare a phase done on a red tree.
|
|
26
|
-
6. **Commit policy.** If the
|
|
14
|
+
6. **Commit policy.** If the request asks for commits or the repo workflow expects them, commit after each green phase with a focused message. Never commit a red tree. Never commit work the user did not ask to commit.
|
|
27
15
|
7. **Respawn, do not absorb.** If a subagent returns incomplete or wrong work, spawn a corrective subagent with the specific gap — do not silently fix it yourself.
|
|
28
16
|
8. **No scope creep, no scope shrink.** Do not add work the user did not ask for. Do not relabel unfinished items as "follow-up", "v1", or "MVP" to imply completion.
|
|
29
17
|
9. **Subagents do not verify, lint, or format.** Every `task` assignment MUST instruct the subagent to skip all gates and formatters. Their job is the edit only. You — the orchestrator — run verification and formatting **once** at the end of the phase across the union of changed files. Avoids redundant runs and racing formatter passes.
|
|
@@ -47,3 +35,4 @@ You decompose, dispatch, verify, and iterate. You do **not** edit code. Every fi
|
|
|
47
35
|
- Marking todos done based on subagent self-reports without verifying the gate.
|
|
48
36
|
- Summarizing progress in chat instead of advancing to the next phase.
|
|
49
37
|
</anti-patterns>
|
|
38
|
+
</system-notice>
|
|
@@ -54,7 +54,9 @@ With most FS/bash-like tools, static references to them will automatically resol
|
|
|
54
54
|
- `skill://<name>`: Skill instructions
|
|
55
55
|
- `/<path>`: File within a skill
|
|
56
56
|
- `rule://<name>`: Rule details
|
|
57
|
+
{{#if hasMemoryRoot}}
|
|
57
58
|
- `memory://root`: Project memory summary
|
|
59
|
+
{{/if}}
|
|
58
60
|
- `agent://<id>`: Full agent output artifact
|
|
59
61
|
- `/<path>`: JSON field extraction
|
|
60
62
|
- `artifact://<id>`: Artifact content
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
You generate concise terminal session titles.
|
|
2
|
+
|
|
3
|
+
Input is one user message inside `<user-message>` tags.
|
|
4
|
+
|
|
5
|
+
Return one specific 3-6 word title.
|
|
6
|
+
Continue the assistant response after `<title>` and close it with `</title>`.
|
|
7
|
+
|
|
8
|
+
NEVER include quotes, punctuation, markdown, commentary, or a second line.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Edit Mnemosyne long-term memories by id.
|
|
2
|
+
|
|
3
|
+
Use only with ids returned by the `recall` tool. Operations:
|
|
4
|
+
- `update`: replace content and/or importance for a working memory.
|
|
5
|
+
- `forget`: permanently delete a working memory.
|
|
6
|
+
- `invalidate`: softly supersede a working or episodic memory, optionally pointing at `replacement_id`.
|
|
7
|
+
|
|
8
|
+
Prefer `invalidate` when a memory became stale but its history may still be useful. Use `forget` only for content that should be hard-deleted.
|
|
@@ -46,7 +46,11 @@ Extracts text from PDF, Word, PowerPoint, Excel, RTF, and EPUB. Notebooks (`.ipy
|
|
|
46
46
|
|
|
47
47
|
# Images
|
|
48
48
|
|
|
49
|
+
{{#if INSPECT_IMAGE_ENABLED}}
|
|
49
50
|
Reading an image path returns metadata (mime, bytes, dimensions, channels, alpha). For actual visual analysis, call `inspect_image` with the path and a question describing what to inspect.
|
|
51
|
+
{{else}}
|
|
52
|
+
Reading an image path returns the decoded image inline (PNG, JPEG, GIF, WEBP) for direct visual analysis.
|
|
53
|
+
{{/if}}
|
|
50
54
|
|
|
51
55
|
# Archives
|
|
52
56
|
|
|
@@ -30,15 +30,12 @@ Subagents have no conversation history. Every fact, file path, and direction the
|
|
|
30
30
|
</parameters>
|
|
31
31
|
|
|
32
32
|
<rules>
|
|
33
|
+
- **Maximize batch width.** Spawn the widest parallel set the work decomposes into. NEVER spawn a single-task batch for divisible work, or defer work that could have been concurrent.
|
|
33
34
|
- NEVER assign tasks to run project-wide build/test/lint. Caller verifies after the batch.
|
|
34
35
|
- **Subagents do not verify, lint, or format.** Every assignment MUST instruct the subagent to skip all gates and formatters. You run them once at the end across the union of changed files — avoids redundant runs and racing formatter passes.
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
{{else}}
|
|
39
|
-
- Each task: ≤3–5 explicit files. No globs, no "update all", no package-wide scope. Fan out to a cluster instead.
|
|
40
|
-
{{/if}}
|
|
41
|
-
- Pass large payloads via `local://<path>` URIs, not inline.
|
|
36
|
+
- No globs, no "update all", no package-wide scope. Fan out.
|
|
37
|
+
- Do not concern yourself with how agents might overlap on certain actions. Never use it as an excuse to go slower: they can resolve collisions in real-time with the harness facilities.
|
|
38
|
+
- Pass large payloads via `local://<path>` URIs, not inline. {{#if contextEnabled}} (other than the context){{/if}}
|
|
42
39
|
{{#if contextEnabled}}- Put shared constraints in `context` once; do not duplicate across assignments.{{/if}}
|
|
43
40
|
- Prefer agents that investigate **and** edit in one pass; only spin a read-only discovery step when affected files are genuinely unknown.
|
|
44
41
|
</rules>
|