@gajae-code/coding-agent 0.2.3 → 0.2.5
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 +34 -8600
- package/README.md +1 -1
- package/dist/types/async/job-manager.d.ts +61 -0
- package/dist/types/cli/update-cli.d.ts +3 -0
- package/dist/types/config/settings-schema.d.ts +27 -3
- package/dist/types/config/settings.d.ts +1 -1
- package/dist/types/defaults/gjc-defaults.d.ts +19 -6
- package/dist/types/discovery/helpers.d.ts +1 -0
- package/dist/types/exec/bash-executor.d.ts +8 -1
- package/dist/types/gjc-runtime/restricted-role-agent-bash.d.ts +2 -0
- package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -1
- package/dist/types/modes/components/settings-selector.d.ts +4 -0
- package/dist/types/modes/components/skill-hud/render.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +2 -0
- package/dist/types/modes/theme/defaults/index.d.ts +45 -9351
- package/dist/types/modes/theme/theme.d.ts +6 -5
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/session/streaming-output.d.ts +11 -0
- package/dist/types/skill-state/active-state.d.ts +1 -0
- package/dist/types/task/types.d.ts +1 -0
- package/dist/types/tools/bash-allowed-prefixes.d.ts +5 -0
- package/dist/types/tools/bash.d.ts +24 -0
- package/dist/types/tools/cron.d.ts +110 -0
- package/dist/types/tools/index.d.ts +4 -0
- package/dist/types/tools/monitor.d.ts +54 -0
- package/dist/types/web/search/index.d.ts +1 -0
- package/dist/types/web/search/provider.d.ts +11 -4
- package/dist/types/web/search/providers/duckduckgo.d.ts +57 -0
- package/dist/types/web/search/types.d.ts +1 -1
- package/package.json +7 -7
- package/src/async/job-manager.ts +224 -0
- package/src/cli/agents-cli.ts +3 -0
- package/src/cli/update-cli.ts +67 -16
- package/src/config/settings-schema.ts +30 -2
- package/src/config/settings.ts +44 -7
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +48 -6
- package/src/defaults/gjc/skills/deep-interview/auto-answer-uncertain.md +37 -0
- package/src/defaults/gjc/skills/deep-interview/auto-research-greenfield.md +42 -0
- package/src/defaults/gjc/skills/ralplan/SKILL.md +8 -4
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +9 -6
- package/src/defaults/gjc-defaults.ts +68 -16
- package/src/discovery/helpers.ts +5 -0
- package/src/eval/js/shared/rewrite-imports.ts +1 -2
- package/src/exec/bash-executor.ts +20 -9
- package/src/gjc-runtime/deep-interview-runtime.ts +44 -0
- package/src/gjc-runtime/ralplan-runtime.ts +2 -0
- package/src/gjc-runtime/restricted-role-agent-bash.ts +5 -0
- package/src/gjc-runtime/state-runtime.ts +3 -2
- package/src/goals/tools/goal-tool.ts +5 -1
- package/src/hooks/skill-state.ts +1 -1
- package/src/internal-urls/docs-index.generated.ts +8 -4
- package/src/lsp/render.ts +1 -1
- package/src/memories/index.ts +5 -4
- package/src/modes/acp/acp-agent.ts +1 -1
- package/src/modes/acp/acp-client-bridge.ts +1 -1
- package/src/modes/components/agent-dashboard.ts +1 -1
- package/src/modes/components/diff.ts +2 -2
- package/src/modes/components/settings-selector.ts +25 -14
- package/src/modes/components/skill-hud/render.ts +7 -2
- package/src/modes/controllers/command-controller.ts +1 -1
- package/src/modes/controllers/input-controller.ts +10 -2
- package/src/modes/controllers/selector-controller.ts +67 -0
- package/src/modes/interactive-mode.ts +34 -3
- package/src/modes/theme/defaults/blue-crab.json +126 -0
- package/src/modes/theme/defaults/index.ts +2 -196
- package/src/modes/theme/theme.ts +75 -36
- package/src/modes/types.ts +2 -0
- package/src/prompts/agents/architect.md +5 -1
- package/src/prompts/agents/critic.md +5 -1
- package/src/prompts/agents/frontmatter.md +1 -0
- package/src/prompts/agents/planner.md +5 -1
- package/src/prompts/memories/unavailable.md +9 -0
- package/src/prompts/tools/bash.md +9 -0
- package/src/prompts/tools/cron.md +25 -0
- package/src/prompts/tools/monitor.md +30 -0
- package/src/runtime-mcp/oauth-flow.ts +4 -2
- package/src/sdk.ts +7 -0
- package/src/session/agent-session.ts +16 -5
- package/src/session/streaming-output.ts +21 -0
- package/src/skill-state/active-state.ts +163 -12
- package/src/slash-commands/builtin-registry.ts +11 -1
- package/src/task/agents.ts +1 -0
- package/src/task/executor.ts +1 -0
- package/src/task/types.ts +1 -0
- package/src/tools/bash-allowed-prefixes.ts +169 -0
- package/src/tools/bash.ts +190 -29
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/cron.ts +665 -0
- package/src/tools/index.ts +20 -2
- package/src/tools/monitor.ts +136 -0
- package/src/vim/engine.ts +3 -3
- package/src/web/search/index.ts +31 -18
- package/src/web/search/provider.ts +57 -12
- package/src/web/search/providers/duckduckgo.ts +279 -0
- package/src/web/search/types.ts +2 -0
- package/src/modes/theme/dark.json +0 -95
- package/src/modes/theme/defaults/alabaster.json +0 -93
- package/src/modes/theme/defaults/amethyst.json +0 -96
- package/src/modes/theme/defaults/anthracite.json +0 -93
- package/src/modes/theme/defaults/basalt.json +0 -91
- package/src/modes/theme/defaults/birch.json +0 -95
- package/src/modes/theme/defaults/dark-abyss.json +0 -91
- package/src/modes/theme/defaults/dark-arctic.json +0 -104
- package/src/modes/theme/defaults/dark-aurora.json +0 -95
- package/src/modes/theme/defaults/dark-catppuccin.json +0 -107
- package/src/modes/theme/defaults/dark-cavern.json +0 -91
- package/src/modes/theme/defaults/dark-copper.json +0 -95
- package/src/modes/theme/defaults/dark-cosmos.json +0 -90
- package/src/modes/theme/defaults/dark-cyberpunk.json +0 -102
- package/src/modes/theme/defaults/dark-dracula.json +0 -98
- package/src/modes/theme/defaults/dark-eclipse.json +0 -91
- package/src/modes/theme/defaults/dark-ember.json +0 -95
- package/src/modes/theme/defaults/dark-equinox.json +0 -90
- package/src/modes/theme/defaults/dark-forest.json +0 -96
- package/src/modes/theme/defaults/dark-github.json +0 -105
- package/src/modes/theme/defaults/dark-gruvbox.json +0 -112
- package/src/modes/theme/defaults/dark-lavender.json +0 -95
- package/src/modes/theme/defaults/dark-lunar.json +0 -89
- package/src/modes/theme/defaults/dark-midnight.json +0 -95
- package/src/modes/theme/defaults/dark-monochrome.json +0 -94
- package/src/modes/theme/defaults/dark-monokai.json +0 -98
- package/src/modes/theme/defaults/dark-nebula.json +0 -90
- package/src/modes/theme/defaults/dark-nord.json +0 -97
- package/src/modes/theme/defaults/dark-ocean.json +0 -101
- package/src/modes/theme/defaults/dark-one.json +0 -100
- package/src/modes/theme/defaults/dark-poimandres.json +0 -141
- package/src/modes/theme/defaults/dark-rainforest.json +0 -91
- package/src/modes/theme/defaults/dark-reef.json +0 -91
- package/src/modes/theme/defaults/dark-retro.json +0 -92
- package/src/modes/theme/defaults/dark-rose-pine.json +0 -96
- package/src/modes/theme/defaults/dark-sakura.json +0 -95
- package/src/modes/theme/defaults/dark-slate.json +0 -95
- package/src/modes/theme/defaults/dark-solarized.json +0 -97
- package/src/modes/theme/defaults/dark-solstice.json +0 -90
- package/src/modes/theme/defaults/dark-starfall.json +0 -91
- package/src/modes/theme/defaults/dark-sunset.json +0 -99
- package/src/modes/theme/defaults/dark-swamp.json +0 -90
- package/src/modes/theme/defaults/dark-synthwave.json +0 -103
- package/src/modes/theme/defaults/dark-taiga.json +0 -91
- package/src/modes/theme/defaults/dark-terminal.json +0 -95
- package/src/modes/theme/defaults/dark-tokyo-night.json +0 -101
- package/src/modes/theme/defaults/dark-tundra.json +0 -91
- package/src/modes/theme/defaults/dark-twilight.json +0 -91
- package/src/modes/theme/defaults/dark-volcanic.json +0 -91
- package/src/modes/theme/defaults/graphite.json +0 -92
- package/src/modes/theme/defaults/light-arctic.json +0 -107
- package/src/modes/theme/defaults/light-aurora-day.json +0 -91
- package/src/modes/theme/defaults/light-canyon.json +0 -91
- package/src/modes/theme/defaults/light-catppuccin.json +0 -106
- package/src/modes/theme/defaults/light-cirrus.json +0 -90
- package/src/modes/theme/defaults/light-coral.json +0 -95
- package/src/modes/theme/defaults/light-cyberpunk.json +0 -96
- package/src/modes/theme/defaults/light-dawn.json +0 -90
- package/src/modes/theme/defaults/light-dunes.json +0 -91
- package/src/modes/theme/defaults/light-eucalyptus.json +0 -95
- package/src/modes/theme/defaults/light-forest.json +0 -100
- package/src/modes/theme/defaults/light-frost.json +0 -95
- package/src/modes/theme/defaults/light-github.json +0 -115
- package/src/modes/theme/defaults/light-glacier.json +0 -91
- package/src/modes/theme/defaults/light-gruvbox.json +0 -108
- package/src/modes/theme/defaults/light-haze.json +0 -90
- package/src/modes/theme/defaults/light-honeycomb.json +0 -95
- package/src/modes/theme/defaults/light-lagoon.json +0 -91
- package/src/modes/theme/defaults/light-lavender.json +0 -95
- package/src/modes/theme/defaults/light-meadow.json +0 -91
- package/src/modes/theme/defaults/light-mint.json +0 -95
- package/src/modes/theme/defaults/light-monochrome.json +0 -101
- package/src/modes/theme/defaults/light-ocean.json +0 -99
- package/src/modes/theme/defaults/light-one.json +0 -99
- package/src/modes/theme/defaults/light-opal.json +0 -91
- package/src/modes/theme/defaults/light-orchard.json +0 -91
- package/src/modes/theme/defaults/light-paper.json +0 -95
- package/src/modes/theme/defaults/light-poimandres.json +0 -141
- package/src/modes/theme/defaults/light-prism.json +0 -90
- package/src/modes/theme/defaults/light-retro.json +0 -98
- package/src/modes/theme/defaults/light-sand.json +0 -95
- package/src/modes/theme/defaults/light-savanna.json +0 -91
- package/src/modes/theme/defaults/light-solarized.json +0 -102
- package/src/modes/theme/defaults/light-soleil.json +0 -90
- package/src/modes/theme/defaults/light-sunset.json +0 -99
- package/src/modes/theme/defaults/light-synthwave.json +0 -98
- package/src/modes/theme/defaults/light-tokyo-night.json +0 -111
- package/src/modes/theme/defaults/light-wetland.json +0 -91
- package/src/modes/theme/defaults/light-zenith.json +0 -89
- package/src/modes/theme/defaults/limestone.json +0 -94
- package/src/modes/theme/defaults/mahogany.json +0 -97
- package/src/modes/theme/defaults/marble.json +0 -93
- package/src/modes/theme/defaults/obsidian.json +0 -91
- package/src/modes/theme/defaults/onyx.json +0 -91
- package/src/modes/theme/defaults/pearl.json +0 -93
- package/src/modes/theme/defaults/porcelain.json +0 -91
- package/src/modes/theme/defaults/quartz.json +0 -96
- package/src/modes/theme/defaults/sandstone.json +0 -95
- package/src/modes/theme/defaults/titanium.json +0 -90
- package/src/modes/theme/light.json +0 -93
package/src/lsp/render.ts
CHANGED
|
@@ -103,7 +103,7 @@ export function renderResult(
|
|
|
103
103
|
args?: LspParams,
|
|
104
104
|
): Component {
|
|
105
105
|
const content = result.content?.[0];
|
|
106
|
-
if (
|
|
106
|
+
if (content?.type !== "text" || !("text" in content) || !content.text) {
|
|
107
107
|
const icon = formatStatusIcon("warning", theme, options.spinnerFrame);
|
|
108
108
|
const header = `${icon} LSP`;
|
|
109
109
|
return new Text([header, theme.fg("dim", "No result")].join("\n"), 0, 0);
|
package/src/memories/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ import consolidationTemplate from "../prompts/memories/consolidation.md" with {
|
|
|
12
12
|
import readPathTemplate from "../prompts/memories/read-path.md" with { type: "text" };
|
|
13
13
|
import stageOneInputTemplate from "../prompts/memories/stage_one_input.md" with { type: "text" };
|
|
14
14
|
import stageOneSystemTemplate from "../prompts/memories/stage_one_system.md" with { type: "text" };
|
|
15
|
+
import unavailableTemplate from "../prompts/memories/unavailable.md" with { type: "text" };
|
|
15
16
|
import type { AgentSession } from "../session/agent-session";
|
|
16
17
|
import {
|
|
17
18
|
claimStage1Jobs,
|
|
@@ -153,20 +154,20 @@ export async function buildMemoryToolDeveloperInstructions(
|
|
|
153
154
|
): Promise<string | undefined> {
|
|
154
155
|
const cfg = loadMemoryConfig(settings);
|
|
155
156
|
if (!cfg.enabled) return undefined;
|
|
156
|
-
const memoryRoot = getMemoryRoot(agentDir, session?.sessionManager
|
|
157
|
+
const memoryRoot = getMemoryRoot(agentDir, session?.sessionManager?.getCwd() ?? settings.getCwd());
|
|
157
158
|
const summaryPath = path.join(memoryRoot, "memory_summary.md");
|
|
158
159
|
|
|
159
160
|
let text: string;
|
|
160
161
|
try {
|
|
161
162
|
text = await Bun.file(summaryPath).text();
|
|
162
163
|
} catch {
|
|
163
|
-
return
|
|
164
|
+
return unavailableTemplate;
|
|
164
165
|
}
|
|
165
166
|
|
|
166
167
|
const summary = text.trim();
|
|
167
|
-
if (!summary) return
|
|
168
|
+
if (!summary) return unavailableTemplate;
|
|
168
169
|
const truncated = truncateByApproxTokens(summary, cfg.summaryInjectionTokenLimit);
|
|
169
|
-
if (!truncated.trim()) return
|
|
170
|
+
if (!truncated.trim()) return unavailableTemplate;
|
|
170
171
|
|
|
171
172
|
return prompt.render(readPathTemplate, {
|
|
172
173
|
memory_summary: truncated,
|
|
@@ -272,7 +272,7 @@ async function elicitFromAcpClient(
|
|
|
272
272
|
finish(undefined);
|
|
273
273
|
});
|
|
274
274
|
const response = await promise;
|
|
275
|
-
if (
|
|
275
|
+
if (response?.action !== "accept" || !response.content) {
|
|
276
276
|
return undefined;
|
|
277
277
|
}
|
|
278
278
|
return response.content.value;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ACP-side `ClientBridge` implementation. Wraps `AgentSideConnection` so the
|
|
3
|
-
* `read`/`write`/`bash`/`edit` tools (and the permission gate in
|
|
3
|
+
* `read`/`write`/`bash`/`monitor`/`edit` tools (and the permission gate in
|
|
4
4
|
* `AgentSession`) can route through the client when it advertises the
|
|
5
5
|
* relevant capabilities at `initialize` time.
|
|
6
6
|
*/
|
|
@@ -121,7 +121,7 @@ function matchAgent(agent: DashboardAgent, query: string): boolean {
|
|
|
121
121
|
function extractAssistantText(messages: AgentMessage[]): string | null {
|
|
122
122
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
123
123
|
const message = messages[i];
|
|
124
|
-
if (
|
|
124
|
+
if (message?.role !== "assistant") continue;
|
|
125
125
|
const blocks = message.content;
|
|
126
126
|
if (!Array.isArray(blocks)) continue;
|
|
127
127
|
const text = blocks
|
|
@@ -151,7 +151,7 @@ export function renderDiff(diffText: string, options: RenderDiffOptions = {}): s
|
|
|
151
151
|
const removedLines: { lineNum: string; content: string }[] = [];
|
|
152
152
|
while (i < lines.length) {
|
|
153
153
|
const p = parseDiffLine(lines[i]);
|
|
154
|
-
if (
|
|
154
|
+
if (p?.prefix !== "-") break;
|
|
155
155
|
removedLines.push({ lineNum: p.lineNum, content: p.content });
|
|
156
156
|
i++;
|
|
157
157
|
}
|
|
@@ -159,7 +159,7 @@ export function renderDiff(diffText: string, options: RenderDiffOptions = {}): s
|
|
|
159
159
|
const addedLines: { lineNum: string; content: string }[] = [];
|
|
160
160
|
while (i < lines.length) {
|
|
161
161
|
const p = parseDiffLine(lines[i]);
|
|
162
|
-
if (
|
|
162
|
+
if (p?.prefix !== "+") break;
|
|
163
163
|
addedLines.push({ lineNum: p.lineNum, content: p.content });
|
|
164
164
|
i++;
|
|
165
165
|
}
|
|
@@ -21,7 +21,7 @@ import type {
|
|
|
21
21
|
StatusLineSeparatorStyle,
|
|
22
22
|
} from "../../config/settings-schema";
|
|
23
23
|
import { SETTING_TABS, TAB_METADATA } from "../../config/settings-schema";
|
|
24
|
-
import { getSelectListTheme, getSettingsListTheme, theme } from "../../modes/theme/theme";
|
|
24
|
+
import { getCurrentThemeName, getSelectListTheme, getSettingsListTheme, theme } from "../../modes/theme/theme";
|
|
25
25
|
import { matchesAppInterrupt } from "../../modes/utils/keybinding-matchers";
|
|
26
26
|
import { getTabBarTheme } from "../shared";
|
|
27
27
|
import { DynamicBorder } from "./dynamic-border";
|
|
@@ -200,6 +200,10 @@ export interface StatusLinePreviewSettings {
|
|
|
200
200
|
export interface SettingsCallbacks {
|
|
201
201
|
/** Called when any setting value changes */
|
|
202
202
|
onChange: (path: SettingPath, newValue: unknown) => void;
|
|
203
|
+
/** Called for theme preview while browsing theme settings */
|
|
204
|
+
onThemePreview?: (theme: string) => void | Promise<void>;
|
|
205
|
+
/** Called to restore the rendered theme when theme settings preview is cancelled */
|
|
206
|
+
onThemePreviewCancel?: (theme: string) => void | Promise<void>;
|
|
203
207
|
/** Called for status line preview while configuring */
|
|
204
208
|
onStatusLinePreview?: (settings: StatusLinePreviewSettings) => void;
|
|
205
209
|
/** Get current rendered status line for inline preview */
|
|
@@ -217,7 +221,6 @@ export interface SettingsCallbacks {
|
|
|
217
221
|
export class SettingsSelectorComponent extends Container {
|
|
218
222
|
#tabBar: TabBar;
|
|
219
223
|
#currentList: SettingsList | null = null;
|
|
220
|
-
#currentSubmenu: Container | null = null;
|
|
221
224
|
#pluginComponent: PluginSettingsComponent | null = null;
|
|
222
225
|
#statusPreviewContainer: Container | null = null;
|
|
223
226
|
#statusPreviewText: Text | null = null;
|
|
@@ -374,10 +377,15 @@ export class SettingsSelectorComponent extends Container {
|
|
|
374
377
|
let onPreview: ((value: string) => void | Promise<void>) | undefined;
|
|
375
378
|
let onPreviewCancel: (() => void) | undefined;
|
|
376
379
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
380
|
+
if (def.path === "theme.dark" || def.path === "theme.light") {
|
|
381
|
+
const activeThemeBeforePreview = getCurrentThemeName() ?? currentValue;
|
|
382
|
+
onPreview = value => {
|
|
383
|
+
return this.callbacks.onThemePreview?.(value);
|
|
384
|
+
};
|
|
385
|
+
onPreviewCancel = () => {
|
|
386
|
+
return this.callbacks.onThemePreviewCancel?.(activeThemeBeforePreview);
|
|
387
|
+
};
|
|
388
|
+
} else if (def.path === "statusLine.preset") {
|
|
381
389
|
onPreview = value => {
|
|
382
390
|
const presetDef = getPreset(
|
|
383
391
|
value as "default" | "minimal" | "compact" | "full" | "nerd" | "ascii" | "custom",
|
|
@@ -612,17 +620,20 @@ export class SettingsSelectorComponent extends Container {
|
|
|
612
620
|
return;
|
|
613
621
|
}
|
|
614
622
|
|
|
615
|
-
// Escape
|
|
616
|
-
|
|
617
|
-
this.callbacks.onCancel();
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
// Pass to current content
|
|
623
|
+
// Pass to current content. SettingsList owns Escape routing so open
|
|
624
|
+
// submenus can run their cancel/restore callbacks before closing.
|
|
622
625
|
if (this.#currentList) {
|
|
623
626
|
this.#currentList.handleInput(data);
|
|
624
|
-
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
if (this.#pluginComponent) {
|
|
625
630
|
this.#pluginComponent.handleInput(data);
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Fallback for future top-level content that does not own cancellation.
|
|
635
|
+
if (matchesAppInterrupt(data)) {
|
|
636
|
+
this.callbacks.onCancel();
|
|
626
637
|
}
|
|
627
638
|
}
|
|
628
639
|
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
collapsePlanningPipeline,
|
|
3
|
+
type SkillActiveEntry,
|
|
4
|
+
type WorkflowHudChip,
|
|
5
|
+
} from "../../../skill-state/active-state";
|
|
2
6
|
import { workflowReceiptStatus } from "../../../skill-state/workflow-state-contract";
|
|
3
7
|
|
|
4
8
|
const ANSI_RESET_FG = "\x1b[39m";
|
|
@@ -69,7 +73,8 @@ function formatEntry(entry: SkillActiveEntry): string {
|
|
|
69
73
|
}
|
|
70
74
|
|
|
71
75
|
export function renderSkillHudBar(entries: readonly SkillActiveEntry[], width: number): string | null {
|
|
72
|
-
const
|
|
76
|
+
const visible = collapsePlanningPipeline(entries.filter(entry => entry.active !== false));
|
|
77
|
+
const active = visible.filter(entry => sanitizeHudPart(entry.skill)).sort(compareEntries);
|
|
73
78
|
if (active.length === 0 || width <= 0) return null;
|
|
74
79
|
const body = active.map(formatEntry).join(" + ");
|
|
75
80
|
const prefix = `${ANSI_BORDER}◆${ANSI_RESET_FG} ${ANSI_BOLD}${ANSI_ACCENT}hud${ANSI_RESET_FG}${ANSI_RESET_BOLD} `;
|
|
@@ -585,7 +585,7 @@ export class CommandController {
|
|
|
585
585
|
if (action === "view") {
|
|
586
586
|
const payload = await backend.buildDeveloperInstructions(agentDir, this.ctx.settings, this.ctx.session);
|
|
587
587
|
if (!payload) {
|
|
588
|
-
this.ctx.showWarning("Memory payload is empty
|
|
588
|
+
this.ctx.showWarning("Memory payload is empty; durable memory is unavailable or unconfirmed.");
|
|
589
589
|
return;
|
|
590
590
|
}
|
|
591
591
|
this.ctx.chatContainer.addChild(new Spacer(1));
|
|
@@ -64,6 +64,7 @@ export class InputController {
|
|
|
64
64
|
} else if (this.ctx.isBashMode) {
|
|
65
65
|
this.ctx.editor.setText("");
|
|
66
66
|
this.ctx.isBashMode = false;
|
|
67
|
+
this.ctx.isBashNoContext = false;
|
|
67
68
|
this.ctx.updateEditorBorderColor();
|
|
68
69
|
} else if (this.ctx.session.isEvalRunning) {
|
|
69
70
|
this.ctx.session.abortEval();
|
|
@@ -172,11 +173,17 @@ export class InputController {
|
|
|
172
173
|
|
|
173
174
|
this.ctx.editor.onChange = (text: string) => {
|
|
174
175
|
const wasBashMode = this.ctx.isBashMode;
|
|
176
|
+
const wasBashNoContext = this.ctx.isBashNoContext;
|
|
175
177
|
const wasPythonMode = this.ctx.isPythonMode;
|
|
176
178
|
const trimmed = text.trimStart();
|
|
177
|
-
this.ctx.isBashMode =
|
|
179
|
+
this.ctx.isBashMode = trimmed.startsWith("!");
|
|
180
|
+
this.ctx.isBashNoContext = trimmed.startsWith("!!");
|
|
178
181
|
this.ctx.isPythonMode = trimmed.startsWith("$") && !trimmed.startsWith("${");
|
|
179
|
-
if (
|
|
182
|
+
if (
|
|
183
|
+
wasBashMode !== this.ctx.isBashMode ||
|
|
184
|
+
wasBashNoContext !== this.ctx.isBashNoContext ||
|
|
185
|
+
wasPythonMode !== this.ctx.isPythonMode
|
|
186
|
+
) {
|
|
180
187
|
this.ctx.updateEditorBorderColor();
|
|
181
188
|
}
|
|
182
189
|
};
|
|
@@ -260,6 +267,7 @@ export class InputController {
|
|
|
260
267
|
this.ctx.editor.addToHistory(text);
|
|
261
268
|
await this.ctx.handleBashCommand(command, isExcluded);
|
|
262
269
|
this.ctx.isBashMode = false;
|
|
270
|
+
this.ctx.isBashNoContext = false;
|
|
263
271
|
this.ctx.updateEditorBorderColor();
|
|
264
272
|
return;
|
|
265
273
|
}
|
|
@@ -17,7 +17,11 @@ import {
|
|
|
17
17
|
} from "../../extensibility/plugins/marketplace";
|
|
18
18
|
import {
|
|
19
19
|
getAvailableThemes,
|
|
20
|
+
getCurrentThemeName,
|
|
21
|
+
getDetectedThemeSettingsPath,
|
|
20
22
|
getSymbolTheme,
|
|
23
|
+
previewTheme,
|
|
24
|
+
restoreThemePreview,
|
|
21
25
|
setColorBlindMode,
|
|
22
26
|
setSymbolPreset,
|
|
23
27
|
setTheme,
|
|
@@ -47,6 +51,7 @@ import {
|
|
|
47
51
|
import { SessionObserverOverlayComponent } from "../components/session-observer-overlay";
|
|
48
52
|
import { SessionSelectorComponent } from "../components/session-selector";
|
|
49
53
|
import { SettingsSelectorComponent } from "../components/settings-selector";
|
|
54
|
+
import { ThemeSelectorComponent } from "../components/theme-selector";
|
|
50
55
|
import { ToolExecutionComponent } from "../components/tool-execution";
|
|
51
56
|
import { TreeSelectorComponent } from "../components/tree-selector";
|
|
52
57
|
import { UserMessageSelectorComponent } from "../components/user-message-selector";
|
|
@@ -62,6 +67,10 @@ const CALLBACK_SERVER_PROVIDERS = new Set<OAuthProvider>([
|
|
|
62
67
|
|
|
63
68
|
const MANUAL_LOGIN_TIP = "Tip: You can complete pairing with /login <redirect URL>.";
|
|
64
69
|
|
|
70
|
+
function isThemePreviewSuperseded(result: { success: boolean; error?: string }): boolean {
|
|
71
|
+
return !result.success && result.error?.includes("superseded by a newer request") === true;
|
|
72
|
+
}
|
|
73
|
+
|
|
65
74
|
function formatProviderOnboardingCommandGuide(): string {
|
|
66
75
|
return [
|
|
67
76
|
"Provider preset setup:",
|
|
@@ -134,6 +143,22 @@ export class SelectorController {
|
|
|
134
143
|
},
|
|
135
144
|
{
|
|
136
145
|
onChange: (id, value) => this.handleSettingChange(id, value),
|
|
146
|
+
onThemePreview: themeName => {
|
|
147
|
+
return previewTheme(themeName).then(result => {
|
|
148
|
+
if (!result.success && result.error && !isThemePreviewSuperseded(result)) {
|
|
149
|
+
this.ctx.showError(`Failed to preview theme: ${result.error}`);
|
|
150
|
+
}
|
|
151
|
+
this.#refreshThemeUi();
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
onThemePreviewCancel: themeName => {
|
|
155
|
+
return restoreThemePreview(themeName).then(result => {
|
|
156
|
+
if (!result.success && result.error && !isThemePreviewSuperseded(result)) {
|
|
157
|
+
this.ctx.showError(`Failed to restore theme preview: ${result.error}`);
|
|
158
|
+
}
|
|
159
|
+
this.#refreshThemeUi();
|
|
160
|
+
});
|
|
161
|
+
},
|
|
137
162
|
onStatusLinePreview: previewSettings => {
|
|
138
163
|
// Update status line with preview settings
|
|
139
164
|
this.ctx.statusLine.updateSettings({
|
|
@@ -177,6 +202,48 @@ export class SelectorController {
|
|
|
177
202
|
});
|
|
178
203
|
}
|
|
179
204
|
|
|
205
|
+
#refreshThemeUi(): void {
|
|
206
|
+
this.ctx.statusLine.invalidate();
|
|
207
|
+
this.ctx.updateEditorTopBorder();
|
|
208
|
+
this.ctx.ui.requestRender();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
showThemeSelector(): void {
|
|
212
|
+
getAvailableThemes().then(availableThemes => {
|
|
213
|
+
const initialTheme = getCurrentThemeName() ?? "red-claw";
|
|
214
|
+
this.showSelector(done => {
|
|
215
|
+
const selector = new ThemeSelectorComponent(
|
|
216
|
+
initialTheme,
|
|
217
|
+
availableThemes,
|
|
218
|
+
themeName => {
|
|
219
|
+
const settingPath = getDetectedThemeSettingsPath();
|
|
220
|
+
settings.set(settingPath, themeName);
|
|
221
|
+
this.#refreshThemeUi();
|
|
222
|
+
done();
|
|
223
|
+
},
|
|
224
|
+
() => {
|
|
225
|
+
void restoreThemePreview(initialTheme).then(result => {
|
|
226
|
+
if (!result.success && result.error) {
|
|
227
|
+
this.ctx.showError(`Failed to restore theme preview: ${result.error}`);
|
|
228
|
+
}
|
|
229
|
+
this.#refreshThemeUi();
|
|
230
|
+
});
|
|
231
|
+
done();
|
|
232
|
+
},
|
|
233
|
+
themeName => {
|
|
234
|
+
void previewTheme(themeName).then(result => {
|
|
235
|
+
if (!result.success && result.error) {
|
|
236
|
+
this.ctx.showError(`Failed to preview theme: ${result.error}`);
|
|
237
|
+
}
|
|
238
|
+
this.#refreshThemeUi();
|
|
239
|
+
});
|
|
240
|
+
},
|
|
241
|
+
);
|
|
242
|
+
return { component: selector, focus: selector.getSelectList() };
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
180
247
|
showHistorySearch(): void {
|
|
181
248
|
const historyStorage = this.ctx.historyStorage;
|
|
182
249
|
if (!historyStorage) return;
|
|
@@ -112,12 +112,23 @@ const HINT_SHIMMER_PALETTE: ShimmerPalette = {
|
|
|
112
112
|
high: "borderAccent",
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
+
function getDefaultInputPrefix(): string {
|
|
116
|
+
return `${theme.fg("accent", ">")} `;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function getShellInputPrefix(isNoContext: boolean): string {
|
|
120
|
+
const shellLabel = isNoContext
|
|
121
|
+
? theme.fg("warning", theme.bold("shell no-context"))
|
|
122
|
+
: theme.fg("bashMode", theme.bold("shell"));
|
|
123
|
+
return `${shellLabel} ${getDefaultInputPrefix()}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
115
126
|
function configureDefaultComposerChrome(editor: CustomEditor): void {
|
|
116
127
|
editor.setBorderVisible(true);
|
|
117
128
|
editor.setBorderStyle("sharp");
|
|
118
129
|
editor.setClosedBorderBox(true);
|
|
119
130
|
editor.setPromptGutter(undefined);
|
|
120
|
-
editor.setInputPrefix(
|
|
131
|
+
editor.setInputPrefix(getDefaultInputPrefix());
|
|
121
132
|
editor.setPlaceholder("Type your message...");
|
|
122
133
|
editor.setPaddingX(1);
|
|
123
134
|
editor.setTopBorder(undefined);
|
|
@@ -236,6 +247,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
236
247
|
isInitialized = false;
|
|
237
248
|
isBackgrounded = false;
|
|
238
249
|
isBashMode = false;
|
|
250
|
+
isBashNoContext = false;
|
|
239
251
|
toolOutputExpanded = false;
|
|
240
252
|
todoExpanded = false;
|
|
241
253
|
planModeEnabled = false;
|
|
@@ -808,7 +820,10 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
808
820
|
|
|
809
821
|
updateEditorChrome(): void {
|
|
810
822
|
if (this.isBashMode) {
|
|
811
|
-
this.editor.borderColor =
|
|
823
|
+
this.editor.borderColor = this.isBashNoContext
|
|
824
|
+
? (str: string) => theme.fg("warning", str)
|
|
825
|
+
: theme.getBashModeBorderColor();
|
|
826
|
+
this.editor.setInputPrefix(getShellInputPrefix(this.isBashNoContext));
|
|
812
827
|
} else if (this.isPythonMode) {
|
|
813
828
|
this.editor.borderColor = theme.getPythonModeBorderColor();
|
|
814
829
|
} else {
|
|
@@ -823,6 +838,9 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
823
838
|
this.editor.borderColor = theme.getThinkingBorderColor(level);
|
|
824
839
|
}
|
|
825
840
|
}
|
|
841
|
+
if (!this.isBashMode) {
|
|
842
|
+
this.editor.setInputPrefix(getDefaultInputPrefix());
|
|
843
|
+
}
|
|
826
844
|
this.#setComposerTopBorder();
|
|
827
845
|
this.ui.requestRender();
|
|
828
846
|
}
|
|
@@ -1281,7 +1299,16 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1281
1299
|
reason?: "completed" | "paused" | "dropped";
|
|
1282
1300
|
}): Promise<void> {
|
|
1283
1301
|
const previousTools = this.#goalModePreviousTools;
|
|
1284
|
-
|
|
1302
|
+
// Drop keeps the `goal` tool callable so the agent can immediately create a new
|
|
1303
|
+
// goal in the same session without a leader-side cleanup. Complete (and pause)
|
|
1304
|
+
// exit goal mode and restore the pre-goal tool set even when the goal_updated
|
|
1305
|
+
// event has already cleared goalModeEnabled (see #completeGoalFromTool emitting
|
|
1306
|
+
// state.enabled = false before #exitGoalMode runs). Spec: deep-interview-ultragoal-goal-tool-wiring AC1+AC2.
|
|
1307
|
+
const shouldRestoreTools =
|
|
1308
|
+
previousTools &&
|
|
1309
|
+
options?.reason !== "dropped" &&
|
|
1310
|
+
(this.goalModeEnabled || options?.reason === "completed" || options?.paused === true);
|
|
1311
|
+
if (shouldRestoreTools) {
|
|
1285
1312
|
await this.session.setActiveToolsByName(previousTools);
|
|
1286
1313
|
}
|
|
1287
1314
|
const currentState = this.session.getGoalModeState();
|
|
@@ -2339,6 +2366,10 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
2339
2366
|
this.#selectorController.showSettingsSelector();
|
|
2340
2367
|
}
|
|
2341
2368
|
|
|
2369
|
+
showThemeSelector(): void {
|
|
2370
|
+
this.#selectorController.showThemeSelector();
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2342
2373
|
showHistorySearch(): void {
|
|
2343
2374
|
this.#selectorController.showHistorySearch();
|
|
2344
2375
|
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/can1357/gajae-code/main/packages/coding-agent/theme-schema.json",
|
|
3
|
+
"name": "blue-crab",
|
|
4
|
+
"vars": {
|
|
5
|
+
"cyan": "#66e8ff",
|
|
6
|
+
"blue": "#4ea1ff",
|
|
7
|
+
"green": "#72e6b8",
|
|
8
|
+
"red": "#ff6b7a",
|
|
9
|
+
"yellow": "#f3c76d",
|
|
10
|
+
"gray": "#b8c7d9",
|
|
11
|
+
"dimGray": "#5d7288",
|
|
12
|
+
"darkGray": "#344456",
|
|
13
|
+
"accent": "#2f9bff",
|
|
14
|
+
"selectedBg": "#12314a",
|
|
15
|
+
"userMsgBg": "#081b2a",
|
|
16
|
+
"toolPendingBg": "#0a2235",
|
|
17
|
+
"toolSuccessBg": "#0b2b25",
|
|
18
|
+
"toolErrorBg": "#321923",
|
|
19
|
+
"customMsgBg": "#0c1a2c",
|
|
20
|
+
"abyss": "#020812",
|
|
21
|
+
"deepNavy": "#061321",
|
|
22
|
+
"crabShell": "#2f9bff",
|
|
23
|
+
"claw": "#5ec8ff",
|
|
24
|
+
"ocean": "#0b4f8a",
|
|
25
|
+
"azure": "#7dd3fc",
|
|
26
|
+
"seafoam": "#80f2d3",
|
|
27
|
+
"kelp": "#62d9a8",
|
|
28
|
+
"sand": "#f4d6a0",
|
|
29
|
+
"coral": "#ff8a7a",
|
|
30
|
+
"ink": "#020812",
|
|
31
|
+
"mantle": "#061321",
|
|
32
|
+
"surface": "#0a1d31",
|
|
33
|
+
"surfaceBright": "#12314a",
|
|
34
|
+
"foam": "#e6f7ff",
|
|
35
|
+
"mutedShell": "#9db5c9",
|
|
36
|
+
"dimShell": "#55708a",
|
|
37
|
+
"brandBlue": "#2f9bff",
|
|
38
|
+
"shell": "#e6f7ff",
|
|
39
|
+
"dangerRed": "#ff5f75",
|
|
40
|
+
"warningAmber": "#f5bd58",
|
|
41
|
+
"diffRemovalRed": "#df5b61"
|
|
42
|
+
},
|
|
43
|
+
"colors": {
|
|
44
|
+
"accent": "claw",
|
|
45
|
+
"border": "ocean",
|
|
46
|
+
"borderAccent": "brandBlue",
|
|
47
|
+
"borderMuted": "dimShell",
|
|
48
|
+
"success": "kelp",
|
|
49
|
+
"error": "dangerRed",
|
|
50
|
+
"warning": "warningAmber",
|
|
51
|
+
"muted": "mutedShell",
|
|
52
|
+
"dim": "dimShell",
|
|
53
|
+
"text": "shell",
|
|
54
|
+
"thinkingText": "mutedShell",
|
|
55
|
+
"selectedBg": "surfaceBright",
|
|
56
|
+
"userMessageBg": "surface",
|
|
57
|
+
"userMessageText": "shell",
|
|
58
|
+
"customMessageBg": "mantle",
|
|
59
|
+
"customMessageText": "shell",
|
|
60
|
+
"customMessageLabel": "claw",
|
|
61
|
+
"toolPendingBg": "mantle",
|
|
62
|
+
"toolSuccessBg": "#0b2b25",
|
|
63
|
+
"toolErrorBg": "#321923",
|
|
64
|
+
"toolTitle": "shell",
|
|
65
|
+
"toolOutput": "mutedShell",
|
|
66
|
+
"mdHeading": "brandBlue",
|
|
67
|
+
"mdLink": "azure",
|
|
68
|
+
"mdLinkUrl": "dimShell",
|
|
69
|
+
"mdCode": "sand",
|
|
70
|
+
"mdCodeBlock": "seafoam",
|
|
71
|
+
"mdCodeBlockBorder": "ocean",
|
|
72
|
+
"mdQuote": "mutedShell",
|
|
73
|
+
"mdQuoteBorder": "ocean",
|
|
74
|
+
"mdHr": "dimShell",
|
|
75
|
+
"mdListBullet": "claw",
|
|
76
|
+
"toolDiffAdded": "kelp",
|
|
77
|
+
"toolDiffRemoved": "diffRemovalRed",
|
|
78
|
+
"toolDiffContext": "mutedShell",
|
|
79
|
+
"link": "azure",
|
|
80
|
+
"syntaxComment": "dimShell",
|
|
81
|
+
"syntaxKeyword": "brandBlue",
|
|
82
|
+
"syntaxFunction": "sand",
|
|
83
|
+
"syntaxVariable": "foam",
|
|
84
|
+
"syntaxString": "seafoam",
|
|
85
|
+
"syntaxNumber": "azure",
|
|
86
|
+
"syntaxType": "claw",
|
|
87
|
+
"syntaxOperator": "mutedShell",
|
|
88
|
+
"syntaxPunctuation": "dimShell",
|
|
89
|
+
"thinkingOff": "dimShell",
|
|
90
|
+
"thinkingMinimal": "mutedShell",
|
|
91
|
+
"thinkingLow": "azure",
|
|
92
|
+
"thinkingMedium": "claw",
|
|
93
|
+
"thinkingHigh": "brandBlue",
|
|
94
|
+
"thinkingXhigh": "coral",
|
|
95
|
+
"bashMode": "claw",
|
|
96
|
+
"statusLineBg": "ocean",
|
|
97
|
+
"statusLineSep": "dimShell",
|
|
98
|
+
"statusLineModel": "claw",
|
|
99
|
+
"statusLinePath": "azure",
|
|
100
|
+
"statusLineGitClean": "kelp",
|
|
101
|
+
"statusLineGitDirty": "sand",
|
|
102
|
+
"statusLineContext": "seafoam",
|
|
103
|
+
"statusLineSpend": "sand",
|
|
104
|
+
"statusLineStaged": "kelp",
|
|
105
|
+
"statusLineDirty": "sand",
|
|
106
|
+
"statusLineUntracked": "diffRemovalRed",
|
|
107
|
+
"statusLineOutput": "foam",
|
|
108
|
+
"statusLineCost": "claw",
|
|
109
|
+
"statusLineSubagents": "brandBlue",
|
|
110
|
+
"pythonMode": "sand"
|
|
111
|
+
},
|
|
112
|
+
"export": {
|
|
113
|
+
"pageBg": "#020812",
|
|
114
|
+
"cardBg": "#061321",
|
|
115
|
+
"infoBg": "#0a1d31"
|
|
116
|
+
},
|
|
117
|
+
"symbols": {
|
|
118
|
+
"preset": "unicode",
|
|
119
|
+
"overrides": {
|
|
120
|
+
"icon.pi": "🦀",
|
|
121
|
+
"icon.agents": "🦞",
|
|
122
|
+
"status.running": "🌊",
|
|
123
|
+
"md.bullet": "▸"
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|