@gajae-code/coding-agent 0.3.1 → 0.4.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 +46 -0
- package/README.md +1 -1
- package/dist/types/cli/args.d.ts +2 -0
- package/dist/types/commands/launch.d.ts +6 -0
- package/dist/types/config/model-profile-activation.d.ts +30 -0
- package/dist/types/config/model-profiles.d.ts +19 -0
- package/dist/types/config/model-registry.d.ts +25 -10
- package/dist/types/config/model-resolver.d.ts +1 -1
- package/dist/types/config/models-config-schema.d.ts +84 -0
- package/dist/types/config/settings-schema.d.ts +15 -0
- package/dist/types/edit/diff.d.ts +16 -0
- package/dist/types/edit/modes/replace.d.ts +7 -0
- package/dist/types/extensibility/gjc-plugins/activation.d.ts +14 -0
- package/dist/types/extensibility/gjc-plugins/index.d.ts +9 -0
- package/dist/types/extensibility/gjc-plugins/injection.d.ts +31 -0
- package/dist/types/extensibility/gjc-plugins/loader.d.ts +3 -0
- package/dist/types/extensibility/gjc-plugins/paths.d.ts +8 -0
- package/dist/types/extensibility/gjc-plugins/schema.d.ts +3 -0
- package/dist/types/extensibility/gjc-plugins/state.d.ts +9 -0
- package/dist/types/extensibility/gjc-plugins/tools.d.ts +8 -0
- package/dist/types/extensibility/gjc-plugins/types.d.ts +64 -0
- package/dist/types/extensibility/gjc-plugins/validation.d.ts +4 -0
- package/dist/types/extensibility/skills.d.ts +9 -1
- package/dist/types/gjc-runtime/state-runtime.d.ts +22 -0
- package/dist/types/harness-control-plane/storage.d.ts +7 -0
- package/dist/types/lsp/client.d.ts +1 -0
- package/dist/types/main.d.ts +10 -1
- package/dist/types/modes/bridge/bridge-mode.d.ts +2 -0
- package/dist/types/modes/components/custom-provider-wizard.d.ts +10 -0
- package/dist/types/modes/components/model-selector.d.ts +6 -1
- package/dist/types/modes/components/provider-onboarding-selector.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
- package/dist/types/modes/prompt-action-autocomplete.d.ts +2 -2
- package/dist/types/modes/rpc/rpc-client.d.ts +9 -1
- package/dist/types/modes/rpc/rpc-types.d.ts +179 -2
- package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +57 -0
- package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +16 -1
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +47 -0
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +7 -0
- package/dist/types/modes/shared/agent-wire/handshake.d.ts +11 -1
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +3 -1
- package/dist/types/modes/shared/agent-wire/responses.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +27 -0
- package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +68 -0
- package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +161 -0
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +61 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +114 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +39 -0
- package/dist/types/modes/theme/theme.d.ts +2 -1
- package/dist/types/modes/types.d.ts +1 -0
- package/dist/types/runtime-mcp/transports/stdio.d.ts +0 -4
- package/dist/types/sdk.d.ts +8 -1
- package/dist/types/session/agent-session.d.ts +10 -0
- package/dist/types/session/blob-store.d.ts +17 -0
- package/dist/types/session/messages.d.ts +3 -0
- package/dist/types/session/session-storage.d.ts +6 -0
- package/dist/types/skill-state/active-state.d.ts +13 -0
- package/dist/types/task/executor.d.ts +1 -0
- package/dist/types/thinking.d.ts +3 -2
- package/dist/types/tools/hindsight-recall.d.ts +0 -2
- package/dist/types/tools/hindsight-reflect.d.ts +0 -2
- package/dist/types/tools/hindsight-retain.d.ts +0 -2
- package/dist/types/tools/index.d.ts +7 -4
- package/package.json +9 -7
- package/src/cli/args.ts +10 -0
- package/src/cli.ts +14 -0
- package/src/commands/harness.ts +192 -7
- package/src/commands/launch.ts +8 -0
- package/src/commands/ultragoal.ts +1 -21
- package/src/config/model-equivalence.ts +1 -1
- package/src/config/model-profile-activation.ts +157 -0
- package/src/config/model-profiles.ts +155 -0
- package/src/config/model-registry.ts +51 -5
- package/src/config/model-resolver.ts +3 -2
- package/src/config/models-config-schema.ts +42 -1
- package/src/config/settings-schema.ts +14 -1
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +11 -1
- package/src/defaults/gjc/skills/ultragoal/ai-slop-cleaner.md +61 -0
- package/src/defaults/gjc-defaults.ts +7 -0
- package/src/discovery/claude-plugins.ts +25 -5
- package/src/edit/diff.ts +64 -1
- package/src/edit/modes/replace.ts +60 -2
- package/src/extensibility/gjc-plugins/activation.ts +87 -0
- package/src/extensibility/gjc-plugins/index.ts +9 -0
- package/src/extensibility/gjc-plugins/injection.ts +114 -0
- package/src/extensibility/gjc-plugins/loader.ts +131 -0
- package/src/extensibility/gjc-plugins/paths.ts +66 -0
- package/src/extensibility/gjc-plugins/schema.ts +79 -0
- package/src/extensibility/gjc-plugins/state.ts +29 -0
- package/src/extensibility/gjc-plugins/tools.ts +47 -0
- package/src/extensibility/gjc-plugins/types.ts +97 -0
- package/src/extensibility/gjc-plugins/validation.ts +76 -0
- package/src/extensibility/skills.ts +39 -7
- package/src/gjc-runtime/state-runtime.ts +93 -2
- package/src/gjc-runtime/state-writer.ts +17 -1
- package/src/gjc-runtime/ultragoal-runtime.ts +62 -2
- package/src/gjc-runtime/workflow-manifest.generated.json +5 -0
- package/src/gjc-runtime/workflow-manifest.ts +2 -2
- package/src/harness-control-plane/storage.ts +144 -2
- package/src/hashline/hash.ts +23 -0
- package/src/hooks/skill-state.ts +2 -0
- package/src/internal-urls/docs-index.generated.ts +8 -11
- package/src/lsp/client.ts +7 -0
- package/src/main.ts +67 -1
- package/src/modes/acp/acp-agent.ts +25 -2
- package/src/modes/bridge/bridge-mode.ts +124 -2
- package/src/modes/components/custom-provider-wizard.ts +318 -0
- package/src/modes/components/model-selector.ts +108 -18
- package/src/modes/components/provider-onboarding-selector.ts +6 -1
- package/src/modes/controllers/input-controller.ts +14 -2
- package/src/modes/controllers/selector-controller.ts +57 -1
- package/src/modes/prompt-action-autocomplete.ts +49 -10
- package/src/modes/rpc/rpc-client.ts +57 -3
- package/src/modes/rpc/rpc-mode.ts +67 -0
- package/src/modes/rpc/rpc-types.ts +224 -2
- package/src/modes/shared/agent-wire/approval-gate.ts +151 -0
- package/src/modes/shared/agent-wire/command-dispatch.ts +97 -4
- package/src/modes/shared/agent-wire/command-validation.ts +25 -1
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +222 -0
- package/src/modes/shared/agent-wire/event-envelope.ts +13 -0
- package/src/modes/shared/agent-wire/handshake.ts +43 -3
- package/src/modes/shared/agent-wire/protocol.ts +7 -0
- package/src/modes/shared/agent-wire/responses.ts +2 -2
- package/src/modes/shared/agent-wire/scopes.ts +2 -0
- package/src/modes/shared/agent-wire/unattended-action-policy.ts +341 -0
- package/src/modes/shared/agent-wire/unattended-audit.ts +175 -0
- package/src/modes/shared/agent-wire/unattended-run-controller.ts +406 -0
- package/src/modes/shared/agent-wire/unattended-session.ts +180 -0
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +324 -0
- package/src/modes/shared/agent-wire/workflow-gate-schema.ts +331 -0
- package/src/modes/theme/theme.ts +6 -0
- package/src/modes/types.ts +1 -0
- package/src/prompts/memories/consolidation.md +1 -1
- package/src/prompts/memories/read-path.md +6 -7
- package/src/prompts/memories/unavailable.md +2 -2
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/irc.md +1 -1
- package/src/prompts/tools/read.md +2 -2
- package/src/prompts/tools/recall.md +1 -0
- package/src/prompts/tools/reflect.md +1 -0
- package/src/prompts/tools/retain.md +1 -0
- package/src/runtime-mcp/client.ts +7 -4
- package/src/runtime-mcp/manager.ts +45 -13
- package/src/runtime-mcp/transports/http.ts +40 -14
- package/src/runtime-mcp/transports/stdio.ts +11 -10
- package/src/sdk.ts +48 -1
- package/src/session/agent-session.ts +211 -2
- package/src/session/blob-store.ts +84 -0
- package/src/session/messages.ts +3 -0
- package/src/session/session-manager.ts +390 -33
- package/src/session/session-storage.ts +26 -0
- package/src/setup/provider-onboarding.ts +2 -2
- package/src/skill-state/active-state.ts +89 -1
- package/src/slash-commands/builtin-registry.ts +1 -1
- package/src/task/discovery.ts +7 -1
- package/src/task/executor.ts +18 -2
- package/src/task/index.ts +2 -0
- package/src/thinking.ts +8 -2
- package/src/tools/ask.ts +39 -9
- package/src/tools/hindsight-recall.ts +0 -2
- package/src/tools/hindsight-reflect.ts +0 -2
- package/src/tools/hindsight-retain.ts +0 -2
- package/src/tools/index.ts +7 -18
- package/src/tools/read.ts +3 -3
- package/src/tools/skill.ts +15 -3
- package/src/utils/edit-mode.ts +1 -1
|
@@ -40,7 +40,9 @@ export interface SessionStorage {
|
|
|
40
40
|
readTextPrefix(path: string, maxBytes: number): Promise<string>;
|
|
41
41
|
writeText(path: string, content: string): Promise<void>;
|
|
42
42
|
rename(path: string, nextPath: string): Promise<void>;
|
|
43
|
+
renameSync(path: string, nextPath: string): void;
|
|
43
44
|
unlink(path: string): Promise<void>;
|
|
45
|
+
unlinkSync(path: string): void;
|
|
44
46
|
deleteSessionWithArtifacts(sessionPath: string): Promise<void>;
|
|
45
47
|
openWriter(path: string, options?: { flags?: "a" | "w"; onError?: (err: Error) => void }): SessionStorageWriter;
|
|
46
48
|
}
|
|
@@ -198,10 +200,22 @@ export class FileSessionStorage implements SessionStorage {
|
|
|
198
200
|
}
|
|
199
201
|
}
|
|
200
202
|
|
|
203
|
+
renameSync(path: string, nextPath: string): void {
|
|
204
|
+
try {
|
|
205
|
+
fs.renameSync(path, nextPath);
|
|
206
|
+
} catch (err) {
|
|
207
|
+
throw toError(err);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
201
211
|
unlink(path: string): Promise<void> {
|
|
202
212
|
return fs.promises.unlink(path);
|
|
203
213
|
}
|
|
204
214
|
|
|
215
|
+
unlinkSync(path: string): void {
|
|
216
|
+
fs.unlinkSync(path);
|
|
217
|
+
}
|
|
218
|
+
|
|
205
219
|
openWriter(path: string, options?: { flags?: "a" | "w"; onError?: (err: Error) => void }): SessionStorageWriter {
|
|
206
220
|
return new FileSessionStorageWriter(path, options);
|
|
207
221
|
}
|
|
@@ -375,10 +389,22 @@ export class MemorySessionStorage implements SessionStorage {
|
|
|
375
389
|
return Promise.resolve();
|
|
376
390
|
}
|
|
377
391
|
|
|
392
|
+
renameSync(path: string, nextPath: string): void {
|
|
393
|
+
const entry = this.#files.get(path);
|
|
394
|
+
if (!entry) throw new Error(`File not found: ${path}`);
|
|
395
|
+
this.#files.set(nextPath, entry);
|
|
396
|
+
this.#files.delete(path);
|
|
397
|
+
}
|
|
398
|
+
|
|
378
399
|
unlink(path: string): Promise<void> {
|
|
379
400
|
this.#files.delete(path);
|
|
380
401
|
return Promise.resolve();
|
|
381
402
|
}
|
|
403
|
+
|
|
404
|
+
unlinkSync(path: string): void {
|
|
405
|
+
this.#files.delete(path);
|
|
406
|
+
}
|
|
407
|
+
|
|
382
408
|
deleteSessionWithArtifacts(_sessionPath: string): Promise<void> {
|
|
383
409
|
return Promise.resolve();
|
|
384
410
|
}
|
|
@@ -79,7 +79,7 @@ export const PROVIDER_PRESETS: readonly ProviderPreset[] = [
|
|
|
79
79
|
providerId: "minimax-code",
|
|
80
80
|
baseUrl: "https://api.minimax.io/v1",
|
|
81
81
|
apiKeyEnv: "MINIMAX_CODE_API_KEY",
|
|
82
|
-
models: ["
|
|
82
|
+
models: ["minimax-m3"],
|
|
83
83
|
compat: MINIMAX_OPENAI_COMPAT,
|
|
84
84
|
},
|
|
85
85
|
{
|
|
@@ -92,7 +92,7 @@ export const PROVIDER_PRESETS: readonly ProviderPreset[] = [
|
|
|
92
92
|
providerId: "minimax-code-cn",
|
|
93
93
|
baseUrl: "https://api.minimaxi.com/v1",
|
|
94
94
|
apiKeyEnv: "MINIMAX_CODE_CN_API_KEY",
|
|
95
|
-
models: ["
|
|
95
|
+
models: ["minimax-m3"],
|
|
96
96
|
compat: MINIMAX_OPENAI_COMPAT,
|
|
97
97
|
},
|
|
98
98
|
{
|
|
@@ -32,6 +32,17 @@ export interface WorkflowHudSummary {
|
|
|
32
32
|
|
|
33
33
|
export type { WorkflowStateReceipt } from "./workflow-state-contract";
|
|
34
34
|
|
|
35
|
+
export interface ActiveSubskillEntry {
|
|
36
|
+
plugin: string;
|
|
37
|
+
subskillName: string;
|
|
38
|
+
parent: string;
|
|
39
|
+
bindsTo: string;
|
|
40
|
+
phase: string;
|
|
41
|
+
activationArg: string;
|
|
42
|
+
filePath: string;
|
|
43
|
+
toolPaths: string[];
|
|
44
|
+
}
|
|
45
|
+
|
|
35
46
|
export interface SkillActiveEntry {
|
|
36
47
|
skill: string;
|
|
37
48
|
phase?: string;
|
|
@@ -47,6 +58,7 @@ export interface SkillActiveEntry {
|
|
|
47
58
|
handoff_from?: string;
|
|
48
59
|
handoff_to?: string;
|
|
49
60
|
handoff_at?: string;
|
|
61
|
+
active_subskills?: ActiveSubskillEntry[];
|
|
50
62
|
}
|
|
51
63
|
|
|
52
64
|
export interface SkillActiveState {
|
|
@@ -64,6 +76,7 @@ export interface SkillActiveState {
|
|
|
64
76
|
initialized_mode?: CanonicalGjcWorkflowSkill;
|
|
65
77
|
initialized_state_path?: string;
|
|
66
78
|
active_skills?: SkillActiveEntry[];
|
|
79
|
+
active_subskills?: ActiveSubskillEntry[];
|
|
67
80
|
[key: string]: unknown;
|
|
68
81
|
}
|
|
69
82
|
|
|
@@ -87,6 +100,7 @@ export interface SyncSkillActiveStateOptions {
|
|
|
87
100
|
handoff_from?: string;
|
|
88
101
|
handoff_to?: string;
|
|
89
102
|
handoff_at?: string;
|
|
103
|
+
active_subskills?: ActiveSubskillEntry[];
|
|
90
104
|
}
|
|
91
105
|
|
|
92
106
|
const HUD_TEXT_LIMIT = 80;
|
|
@@ -188,6 +202,48 @@ function normalizeWorkflowStateReceipt(raw: unknown): WorkflowStateReceipt | und
|
|
|
188
202
|
mutation_id: mutationId,
|
|
189
203
|
};
|
|
190
204
|
}
|
|
205
|
+
function normalizeActiveSubskillEntry(raw: unknown): ActiveSubskillEntry | null {
|
|
206
|
+
if (!raw || typeof raw !== "object") return null;
|
|
207
|
+
const record = raw as Record<string, unknown>;
|
|
208
|
+
const plugin = safeString(record.plugin).trim();
|
|
209
|
+
const subskillName = safeString(record.subskillName).trim();
|
|
210
|
+
const parent = safeString(record.parent).trim();
|
|
211
|
+
const bindsTo = safeString(record.bindsTo).trim();
|
|
212
|
+
const phase = safeString(record.phase).trim();
|
|
213
|
+
const activationArg = safeString(record.activationArg).trim();
|
|
214
|
+
const filePath = safeString(record.filePath).trim();
|
|
215
|
+
const toolPaths = Array.isArray(record.toolPaths)
|
|
216
|
+
? record.toolPaths.map(item => safeString(item).trim()).filter(Boolean)
|
|
217
|
+
: [];
|
|
218
|
+
if (!plugin || !subskillName || !parent || !bindsTo || !phase || !activationArg || !filePath) return null;
|
|
219
|
+
return { plugin, subskillName, parent, bindsTo, phase, activationArg, filePath, toolPaths };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function normalizeActiveSubskillEntries(raw: unknown): ActiveSubskillEntry[] | undefined {
|
|
223
|
+
if (!Array.isArray(raw)) return undefined;
|
|
224
|
+
const entries = raw
|
|
225
|
+
.map(normalizeActiveSubskillEntry)
|
|
226
|
+
.filter((entry): entry is ActiveSubskillEntry => entry !== null);
|
|
227
|
+
return entries.length > 0 ? entries : undefined;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function activeSubskillEntryKey(entry: ActiveSubskillEntry): string {
|
|
231
|
+
return [entry.plugin, entry.parent, entry.phase, entry.activationArg].join("\0");
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function unionActiveSubskillEntries(...entrySets: Array<ActiveSubskillEntry[] | undefined>): ActiveSubskillEntry[] {
|
|
235
|
+
const merged: ActiveSubskillEntry[] = [];
|
|
236
|
+
const seen = new Set<string>();
|
|
237
|
+
for (const entries of entrySets) {
|
|
238
|
+
for (const entry of entries ?? []) {
|
|
239
|
+
const key = activeSubskillEntryKey(entry);
|
|
240
|
+
if (seen.has(key)) continue;
|
|
241
|
+
seen.add(key);
|
|
242
|
+
merged.push(entry);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return merged;
|
|
246
|
+
}
|
|
191
247
|
|
|
192
248
|
function encodePathSegment(value: string): string {
|
|
193
249
|
return encodeURIComponent(value).replaceAll(".", "%2E");
|
|
@@ -204,6 +260,7 @@ function normalizeEntry(raw: unknown): SkillActiveEntry | null {
|
|
|
204
260
|
if (!skill) return null;
|
|
205
261
|
const hud = normalizeWorkflowHudSummary(record.hud);
|
|
206
262
|
const receipt = normalizeWorkflowStateReceipt(record.receipt);
|
|
263
|
+
const activeSubskills = normalizeActiveSubskillEntries(record.active_subskills);
|
|
207
264
|
return {
|
|
208
265
|
...record,
|
|
209
266
|
skill,
|
|
@@ -219,6 +276,7 @@ function normalizeEntry(raw: unknown): SkillActiveEntry | null {
|
|
|
219
276
|
handoff_at: safeString(record.handoff_at).trim() || undefined,
|
|
220
277
|
...(hud ? { hud } : {}),
|
|
221
278
|
...(receipt ? { receipt } : {}),
|
|
279
|
+
...(activeSubskills ? { active_subskills: activeSubskills } : {}),
|
|
222
280
|
stale: undefined,
|
|
223
281
|
};
|
|
224
282
|
}
|
|
@@ -278,6 +336,7 @@ export function normalizeSkillActiveState(raw: unknown): SkillActiveState | null
|
|
|
278
336
|
session_id: safeString(state.session_id).trim() || primary?.session_id || undefined,
|
|
279
337
|
thread_id: safeString(state.thread_id).trim() || primary?.thread_id || undefined,
|
|
280
338
|
turn_id: safeString(state.turn_id).trim() || primary?.turn_id || undefined,
|
|
339
|
+
active_subskills: activeSkills.flatMap(entry => entry.active_subskills ?? []),
|
|
281
340
|
active_skills: activeSkills.length > 0 ? activeSkills : [],
|
|
282
341
|
};
|
|
283
342
|
}
|
|
@@ -512,6 +571,7 @@ export async function readVisibleSkillActiveState(cwd: string, sessionId?: strin
|
|
|
512
571
|
phase: primary?.phase ?? "",
|
|
513
572
|
session_id: safeString(sessionId).trim() || primary?.session_id,
|
|
514
573
|
active_skills: activeSkills,
|
|
574
|
+
active_subskills: activeSkills.flatMap(entry => entry.active_subskills ?? []),
|
|
515
575
|
};
|
|
516
576
|
}
|
|
517
577
|
|
|
@@ -552,7 +612,25 @@ async function rebuildActiveState(cwd: string, sessionScope?: ActiveSessionScope
|
|
|
552
612
|
await rebuildActiveSnapshot(cwd, sessionScope, { cwd, audit: activeStateWriterAudit("rebuild-active-snapshot") });
|
|
553
613
|
}
|
|
554
614
|
|
|
615
|
+
async function activeSubskillsForExistingEntry(
|
|
616
|
+
cwd: string,
|
|
617
|
+
sessionId: string | undefined,
|
|
618
|
+
skill: string,
|
|
619
|
+
): Promise<ActiveSubskillEntry[] | undefined> {
|
|
620
|
+
const { rootPath, sessionPath } = getSkillActiveStatePaths(cwd, sessionId);
|
|
621
|
+
const [rootState, sessionState] = await Promise.all([
|
|
622
|
+
readRawActiveStateForHandoff(rootPath, false),
|
|
623
|
+
sessionPath ? readRawActiveStateForHandoff(sessionPath, false) : Promise.resolve(null),
|
|
624
|
+
]);
|
|
625
|
+
const existing = mergeVisibleEntries(sessionState, rootState, sessionId).find(entry => entry.skill === skill);
|
|
626
|
+
return existing?.active_subskills;
|
|
627
|
+
}
|
|
628
|
+
|
|
555
629
|
export async function syncSkillActiveState(options: SyncSkillActiveStateOptions): Promise<void> {
|
|
630
|
+
const preservedActiveSubskills =
|
|
631
|
+
options.active_subskills === undefined
|
|
632
|
+
? await activeSubskillsForExistingEntry(options.cwd, options.sessionId, options.skill)
|
|
633
|
+
: undefined;
|
|
556
634
|
const nowIso = options.nowIso ?? new Date().toISOString();
|
|
557
635
|
const hud = normalizeWorkflowHudSummary(options.hud);
|
|
558
636
|
const entry: SkillActiveEntry = {
|
|
@@ -569,6 +647,11 @@ export async function syncSkillActiveState(options: SyncSkillActiveStateOptions)
|
|
|
569
647
|
...(options.handoff_at ? { handoff_at: options.handoff_at } : {}),
|
|
570
648
|
...(hud ? { hud } : {}),
|
|
571
649
|
...(options.receipt ? { receipt: options.receipt } : {}),
|
|
650
|
+
...(options.active_subskills !== undefined
|
|
651
|
+
? { active_subskills: options.active_subskills }
|
|
652
|
+
: preservedActiveSubskills
|
|
653
|
+
? { active_subskills: preservedActiveSubskills }
|
|
654
|
+
: {}),
|
|
572
655
|
};
|
|
573
656
|
await persistActiveEntry(options.cwd, undefined, entry);
|
|
574
657
|
await rebuildActiveState(options.cwd);
|
|
@@ -636,9 +719,13 @@ export async function applyHandoffToActiveState(options: ApplyHandoffOptions): P
|
|
|
636
719
|
...(priorCaller.handoff_from && !callerEntry.handoff_from
|
|
637
720
|
? { handoff_from: priorCaller.handoff_from }
|
|
638
721
|
: {}),
|
|
722
|
+
...(priorCaller.active_subskills ? { active_subskills: priorCaller.active_subskills } : {}),
|
|
639
723
|
}
|
|
640
724
|
: callerEntry;
|
|
641
|
-
|
|
725
|
+
const activeSubskills = unionActiveSubskillEntries(priorCaller?.active_subskills, calleeEntry.active_subskills);
|
|
726
|
+
const mergedCallee: SkillActiveEntry =
|
|
727
|
+
activeSubskills.length > 0 ? { ...calleeEntry, active_subskills: activeSubskills } : calleeEntry;
|
|
728
|
+
return [...kept, mergedCaller, mergedCallee];
|
|
642
729
|
};
|
|
643
730
|
const writeEntries = async (
|
|
644
731
|
sessionScope: ActiveSessionScope | undefined,
|
|
@@ -675,5 +762,6 @@ function buildSyncEntry(options: SyncSkillActiveStateOptions, nowIso: string): S
|
|
|
675
762
|
...(options.handoff_at ? { handoff_at: options.handoff_at } : {}),
|
|
676
763
|
...(hud ? { hud } : {}),
|
|
677
764
|
...(options.receipt ? { receipt: options.receipt } : {}),
|
|
765
|
+
...(options.active_subskills ? { active_subskills: options.active_subskills } : {}),
|
|
678
766
|
};
|
|
679
767
|
}
|
package/src/task/discovery.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { logger } from "@gajae-code/utils";
|
|
|
15
15
|
import { isProviderEnabled } from "../capability";
|
|
16
16
|
import { findAllNearestProjectConfigDirs, getConfigDirs } from "../config";
|
|
17
17
|
import { listClaudePluginRoots } from "../discovery/helpers";
|
|
18
|
+
import { rootContainsGjcManifest } from "../extensibility/gjc-plugins/paths";
|
|
18
19
|
import { loadBundledAgents, parseAgent } from "./agents";
|
|
19
20
|
import type { AgentDefinition, AgentSource } from "./types";
|
|
20
21
|
|
|
@@ -93,7 +94,12 @@ export async function discoverAgents(cwd: string, home: string = os.homedir()):
|
|
|
93
94
|
const { roots: pluginRoots } = isProviderEnabled("claude-plugins")
|
|
94
95
|
? await listClaudePluginRoots(home, resolvedCwd)
|
|
95
96
|
: { roots: [] };
|
|
96
|
-
const
|
|
97
|
+
const nonGjcPluginRoots = [];
|
|
98
|
+
for (const plugin of pluginRoots) {
|
|
99
|
+
if (await rootContainsGjcManifest(plugin.path)) continue;
|
|
100
|
+
nonGjcPluginRoots.push(plugin);
|
|
101
|
+
}
|
|
102
|
+
const sortedPluginRoots = nonGjcPluginRoots.sort((a, b) => {
|
|
97
103
|
if (a.scope === b.scope) return 0;
|
|
98
104
|
return a.scope === "project" ? -1 : 1;
|
|
99
105
|
});
|
package/src/task/executor.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { Settings } from "../config/settings";
|
|
|
19
19
|
import { SETTINGS_SCHEMA, type SettingPath } from "../config/settings-schema";
|
|
20
20
|
import { runExtensionCompact, runExtensionSetModel } from "../extensibility/extensions/compact-handler";
|
|
21
21
|
import { getSessionSlashCommands } from "../extensibility/extensions/get-commands-handler";
|
|
22
|
+
import { buildAgentSubskillInjection } from "../extensibility/gjc-plugins";
|
|
22
23
|
import { buildSkillPromptMessage, type Skill } from "../extensibility/skills";
|
|
23
24
|
import type { HindsightSessionState } from "../hindsight/state";
|
|
24
25
|
import type { LocalProtocolOptions } from "../internal-urls";
|
|
@@ -123,6 +124,7 @@ export interface ExecutorOptions {
|
|
|
123
124
|
* if the resolved subagent model has no working credentials. See #985.
|
|
124
125
|
*/
|
|
125
126
|
parentActiveModelPattern?: string;
|
|
127
|
+
parentSessionId?: string;
|
|
126
128
|
thinkingLevel?: ThinkingLevel;
|
|
127
129
|
outputSchema?: unknown;
|
|
128
130
|
/** Parent task recursion depth (0 = top-level, 1 = first child, etc.) */
|
|
@@ -1094,6 +1096,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1094
1096
|
options.parentActiveModelPattern,
|
|
1095
1097
|
modelRegistry,
|
|
1096
1098
|
settings,
|
|
1099
|
+
options.parentSessionId,
|
|
1097
1100
|
),
|
|
1098
1101
|
);
|
|
1099
1102
|
if (authFallbackUsed && model) {
|
|
@@ -1157,6 +1160,12 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1157
1160
|
? `This subagent was started with a forked snapshot of the parent conversation. Included ${options.forkContextSeed.metadata.includedMessages} message(s), skipped ${options.forkContextSeed.metadata.skippedMessages}, approximately ${options.forkContextSeed.metadata.approximateTokens} tokens. The snapshot is not live; use IRC for live coordination when enabled.`
|
|
1158
1161
|
: "";
|
|
1159
1162
|
|
|
1163
|
+
const agentSubskillBlock = await buildAgentSubskillInjection({
|
|
1164
|
+
cwd,
|
|
1165
|
+
sessionId: options.parentSessionId,
|
|
1166
|
+
agentName: agent.name,
|
|
1167
|
+
});
|
|
1168
|
+
|
|
1160
1169
|
const { session } = await awaitAbortable(
|
|
1161
1170
|
createAgentSession({
|
|
1162
1171
|
cwd: worktree ?? cwd,
|
|
@@ -1183,15 +1192,22 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1183
1192
|
ircSelfId: ircEnabled ? id : "",
|
|
1184
1193
|
forkContext: forkContextNotice,
|
|
1185
1194
|
});
|
|
1195
|
+
const promptWithSubskills = `${subagentPrompt}${agentSubskillBlock}`;
|
|
1186
1196
|
return defaultPrompt.length === 0
|
|
1187
|
-
? [
|
|
1188
|
-
: [...defaultPrompt.slice(0, -1),
|
|
1197
|
+
? [promptWithSubskills]
|
|
1198
|
+
: [...defaultPrompt.slice(0, -1), promptWithSubskills, defaultPrompt[defaultPrompt.length - 1]];
|
|
1189
1199
|
},
|
|
1190
1200
|
sessionManager,
|
|
1191
1201
|
hasUI: false,
|
|
1192
1202
|
spawns: spawnsEnv,
|
|
1193
1203
|
taskDepth: childDepth,
|
|
1194
1204
|
currentAgentType: agent.name,
|
|
1205
|
+
gjcSubskillToolContext: {
|
|
1206
|
+
cwd,
|
|
1207
|
+
sessionId: options.parentSessionId,
|
|
1208
|
+
parent: agent.name,
|
|
1209
|
+
phase: "prompt",
|
|
1210
|
+
},
|
|
1195
1211
|
parentHindsightSessionState: options.parentHindsightSessionState,
|
|
1196
1212
|
parentTaskPrefix: id,
|
|
1197
1213
|
agentId: id,
|
package/src/task/index.ts
CHANGED
|
@@ -1310,6 +1310,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1310
1310
|
taskDepth,
|
|
1311
1311
|
modelOverride,
|
|
1312
1312
|
parentActiveModelPattern,
|
|
1313
|
+
parentSessionId: this.session.getSessionId?.() ?? undefined,
|
|
1313
1314
|
thinkingLevel: thinkingLevelOverride,
|
|
1314
1315
|
outputSchema: effectiveOutputSchema,
|
|
1315
1316
|
sessionFile: taskSessionFile,
|
|
@@ -1369,6 +1370,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1369
1370
|
taskDepth,
|
|
1370
1371
|
modelOverride,
|
|
1371
1372
|
parentActiveModelPattern,
|
|
1373
|
+
parentSessionId: this.session.getSessionId?.() ?? undefined,
|
|
1372
1374
|
thinkingLevel: thinkingLevelOverride,
|
|
1373
1375
|
outputSchema: effectiveOutputSchema,
|
|
1374
1376
|
sessionFile: taskSessionFile,
|
package/src/thinking.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type ResolvedThinkingLevel, ThinkingLevel } from "@gajae-code/agent-core";
|
|
2
|
-
import { clampThinkingLevelForModel, type Effort,
|
|
1
|
+
import { type ResolvedThinkingLevel, ThinkingLevel } from "@gajae-code/agent-core/thinking";
|
|
2
|
+
import { clampThinkingLevelForModel, type Effort, THINKING_EFFORTS } from "@gajae-code/ai/model-thinking";
|
|
3
|
+
import type { Model } from "@gajae-code/ai/types";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Metadata used to render thinking selector values in the coding-agent UI.
|
|
@@ -34,6 +35,11 @@ const THINKING_LEVEL_METADATA: Record<ThinkingLevel, ThinkingLevelMetadata> = {
|
|
|
34
35
|
label: "xhigh",
|
|
35
36
|
description: "Maximum reasoning (~32k tokens)",
|
|
36
37
|
},
|
|
38
|
+
[ThinkingLevel.Max]: {
|
|
39
|
+
value: ThinkingLevel.Max,
|
|
40
|
+
label: "max",
|
|
41
|
+
description: "Opus maximum reasoning",
|
|
42
|
+
},
|
|
37
43
|
};
|
|
38
44
|
|
|
39
45
|
const THINKING_LEVELS = new Set<string>([ThinkingLevel.Inherit, ThinkingLevel.Off, ...THINKING_EFFORTS]);
|
package/src/tools/ask.ts
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
renderDeepInterviewAskQuestion,
|
|
35
35
|
} from "../deep-interview/render-middleware";
|
|
36
36
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
37
|
+
import { gateAnswerToResult, questionToGate } from "../modes/shared/agent-wire/deep-interview-gate";
|
|
37
38
|
import { getMarkdownTheme, type Theme, theme } from "../modes/theme/theme";
|
|
38
39
|
import askDescription from "../prompts/tools/ask.md" with { type: "text" };
|
|
39
40
|
import { renderStatusLine } from "../tui";
|
|
@@ -425,7 +426,7 @@ export class AskTool implements AgentTool<typeof askSchema, AskToolDetails> {
|
|
|
425
426
|
}
|
|
426
427
|
|
|
427
428
|
static createIf(session: ToolSession): AskTool | null {
|
|
428
|
-
return session.hasUI ? new AskTool(session) : null;
|
|
429
|
+
return session.hasUI || session.getWorkflowGateEmitter?.() ? new AskTool(session) : null;
|
|
429
430
|
}
|
|
430
431
|
|
|
431
432
|
/** Send terminal notification when ask tool is waiting for input */
|
|
@@ -442,17 +443,25 @@ export class AskTool implements AgentTool<typeof askSchema, AskToolDetails> {
|
|
|
442
443
|
_onUpdate?: AgentToolUpdateCallback<AskToolDetails>,
|
|
443
444
|
context?: AgentToolContext,
|
|
444
445
|
): Promise<AgentToolResult<AskToolDetails>> {
|
|
445
|
-
|
|
446
|
-
|
|
446
|
+
const gateEmitter = this.session.getWorkflowGateEmitter?.();
|
|
447
|
+
const canUseWorkflowGate = gateEmitter?.isUnattended() === true;
|
|
448
|
+
|
|
449
|
+
// Headless fallback: unattended workflow gates are the non-TUI answer path.
|
|
450
|
+
if (!canUseWorkflowGate && (!context?.hasUI || !context.ui)) {
|
|
447
451
|
context?.abort();
|
|
448
452
|
throw new ToolAbortError("Ask tool requires interactive mode");
|
|
449
453
|
}
|
|
450
454
|
|
|
451
|
-
const extensionUi = context
|
|
455
|
+
const extensionUi = context?.ui;
|
|
452
456
|
const ui: UIContext = {
|
|
453
|
-
select: (prompt, options, dialogOptions) =>
|
|
454
|
-
|
|
455
|
-
extensionUi.
|
|
457
|
+
select: (prompt, options, dialogOptions) => {
|
|
458
|
+
if (!extensionUi) throw new ToolAbortError("Ask tool requires interactive mode");
|
|
459
|
+
return extensionUi.select(prompt, options, dialogOptions);
|
|
460
|
+
},
|
|
461
|
+
editor: (title, prefill, dialogOptions, editorOptions) => {
|
|
462
|
+
if (!extensionUi) throw new ToolAbortError("Ask tool requires interactive mode");
|
|
463
|
+
return extensionUi.editor(title, prefill, dialogOptions, editorOptions);
|
|
464
|
+
},
|
|
456
465
|
};
|
|
457
466
|
|
|
458
467
|
// Determine timeout based on settings and plan mode
|
|
@@ -477,6 +486,27 @@ export class AskTool implements AgentTool<typeof askSchema, AskToolDetails> {
|
|
|
477
486
|
options?: { previous?: QuestionResult; navigation?: NavigationControls },
|
|
478
487
|
) => {
|
|
479
488
|
const rawOptionLabels = q.options.map(o => o.label);
|
|
489
|
+
// Unattended (#316/#323/G011): route the question through the workflow-gate
|
|
490
|
+
// emitter instead of the interactive UI; the external agent answers over RPC.
|
|
491
|
+
if (gateEmitter && canUseWorkflowGate) {
|
|
492
|
+
const gateQuestion = {
|
|
493
|
+
id: q.id,
|
|
494
|
+
question: q.question,
|
|
495
|
+
options: q.options,
|
|
496
|
+
multi: q.multi,
|
|
497
|
+
recommended: q.recommended,
|
|
498
|
+
};
|
|
499
|
+
const answer = await gateEmitter.emitGate(questionToGate(gateQuestion));
|
|
500
|
+
const decoded = gateAnswerToResult(gateQuestion, answer);
|
|
501
|
+
return {
|
|
502
|
+
optionLabels: rawOptionLabels,
|
|
503
|
+
selectedOptions: decoded.selectedOptions,
|
|
504
|
+
customInput: decoded.customInput,
|
|
505
|
+
navigation: undefined as NavigationControls | undefined,
|
|
506
|
+
cancelled: false,
|
|
507
|
+
timedOut: false,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
480
510
|
try {
|
|
481
511
|
const deepInterviewPrompt = formatDeepInterviewSelectorPrompt(q.question);
|
|
482
512
|
const displayQuestion = deepInterviewPrompt ?? q.question;
|
|
@@ -529,7 +559,7 @@ export class AskTool implements AgentTool<typeof askSchema, AskToolDetails> {
|
|
|
529
559
|
const { optionLabels, selectedOptions, customInput, cancelled, timedOut } = await askQuestion(q);
|
|
530
560
|
|
|
531
561
|
if (!timedOut && (cancelled || (selectedOptions.length === 0 && customInput === undefined))) {
|
|
532
|
-
context
|
|
562
|
+
context?.abort();
|
|
533
563
|
throw new ToolAbortError("Ask tool was cancelled by the user");
|
|
534
564
|
}
|
|
535
565
|
const details: AskToolDetails = {
|
|
@@ -581,7 +611,7 @@ export class AskTool implements AgentTool<typeof askSchema, AskToolDetails> {
|
|
|
581
611
|
} = await askQuestion(q, { previous, navigation });
|
|
582
612
|
|
|
583
613
|
if (cancelled && !timedOut) {
|
|
584
|
-
context
|
|
614
|
+
context?.abort();
|
|
585
615
|
throw new ToolAbortError("Ask tool was cancelled by the user");
|
|
586
616
|
}
|
|
587
617
|
|
|
@@ -17,8 +17,6 @@ export class HindsightRecallTool implements AgentTool<typeof hindsightRecallSche
|
|
|
17
17
|
readonly description = recallDescription;
|
|
18
18
|
readonly parameters = hindsightRecallSchema;
|
|
19
19
|
readonly strict = true;
|
|
20
|
-
readonly loadMode = "discoverable";
|
|
21
|
-
readonly summary = "Search hindsight memory for relevant prior context";
|
|
22
20
|
|
|
23
21
|
constructor(private readonly session: ToolSession) {}
|
|
24
22
|
|
|
@@ -18,8 +18,6 @@ export class HindsightReflectTool implements AgentTool<typeof hindsightReflectSc
|
|
|
18
18
|
readonly description = reflectDescription;
|
|
19
19
|
readonly parameters = hindsightReflectSchema;
|
|
20
20
|
readonly strict = true;
|
|
21
|
-
readonly loadMode = "discoverable";
|
|
22
|
-
readonly summary = "Reflect on recent work and write hindsight memory";
|
|
23
21
|
|
|
24
22
|
constructor(private readonly session: ToolSession) {}
|
|
25
23
|
|
|
@@ -22,8 +22,6 @@ export class HindsightRetainTool implements AgentTool<typeof hindsightRetainSche
|
|
|
22
22
|
readonly description = retainDescription;
|
|
23
23
|
readonly parameters = hindsightRetainSchema;
|
|
24
24
|
readonly strict = true;
|
|
25
|
-
readonly loadMode = "discoverable";
|
|
26
|
-
readonly summary = "Store important facts in hindsight memory";
|
|
27
25
|
|
|
28
26
|
constructor(private readonly session: ToolSession) {}
|
|
29
27
|
|
package/src/tools/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type { GoalModeState, GoalRuntime } from "../goals";
|
|
|
10
10
|
import { GoalTool } from "../goals/tools/goal-tool";
|
|
11
11
|
import type { HindsightSessionState } from "../hindsight/state";
|
|
12
12
|
import { LspTool } from "../lsp";
|
|
13
|
+
import type { WorkflowGateEmitter } from "../modes/shared/agent-wire/unattended-session";
|
|
13
14
|
import type { PlanModeState } from "../plan-mode/state";
|
|
14
15
|
import type { AgentRegistry } from "../registry/agent-registry";
|
|
15
16
|
import type { ForkContextSeed, ForkContextSeedOptions } from "../session/agent-session";
|
|
@@ -36,9 +37,6 @@ import { DebugTool } from "./debug";
|
|
|
36
37
|
import { EvalTool } from "./eval";
|
|
37
38
|
import { FindTool } from "./find";
|
|
38
39
|
import { GithubTool } from "./gh";
|
|
39
|
-
import { HindsightRecallTool } from "./hindsight-recall";
|
|
40
|
-
import { HindsightReflectTool } from "./hindsight-reflect";
|
|
41
|
-
import { HindsightRetainTool } from "./hindsight-retain";
|
|
42
40
|
import { InspectImageTool } from "./inspect-image";
|
|
43
41
|
import { IrcTool } from "./irc";
|
|
44
42
|
import { JobTool } from "./job";
|
|
@@ -76,9 +74,6 @@ export * from "./debug";
|
|
|
76
74
|
export * from "./eval";
|
|
77
75
|
export * from "./find";
|
|
78
76
|
export * from "./gh";
|
|
79
|
-
export * from "./hindsight-recall";
|
|
80
|
-
export * from "./hindsight-reflect";
|
|
81
|
-
export * from "./hindsight-retain";
|
|
82
77
|
export * from "./image-gen";
|
|
83
78
|
export * from "./inspect-image";
|
|
84
79
|
export * from "./irc";
|
|
@@ -198,6 +193,8 @@ export interface ToolSession {
|
|
|
198
193
|
getPlanModeState?: () => PlanModeState | undefined;
|
|
199
194
|
/** Goal mode state (if active or paused) */
|
|
200
195
|
getGoalModeState?: () => GoalModeState | undefined;
|
|
196
|
+
/** Unattended workflow-gate emitter (present only when unattended mode is negotiated). */
|
|
197
|
+
getWorkflowGateEmitter?: () => WorkflowGateEmitter | undefined;
|
|
201
198
|
/** Goal runtime for the active agent session. */
|
|
202
199
|
getGoalRuntime?: () => GoalRuntime | undefined;
|
|
203
200
|
/** Bridge to the connected client (e.g. ACP editor host). Tools should route fs/terminal/permission requests through this when available. */
|
|
@@ -302,7 +299,10 @@ export function computeEssentialBuiltinNames(settings: Settings): string[] {
|
|
|
302
299
|
|
|
303
300
|
/**
|
|
304
301
|
* Public callable factory map. External callers may invoke `BUILTIN_TOOLS.read(session)` or
|
|
305
|
-
* `BUILTIN_TOOLS[name](session)` to construct a tool directly.
|
|
302
|
+
* `BUILTIN_TOOLS[name](session)` to construct a public coding-harness tool directly.
|
|
303
|
+
*
|
|
304
|
+
* Hindsight memory helpers are intentionally excluded: memory is a private backend
|
|
305
|
+
* integration, not a public gajae-code tool surface.
|
|
306
306
|
*/
|
|
307
307
|
export const BUILTIN_TOOLS: Record<string, ToolFactory> = {
|
|
308
308
|
read: s => new ReadTool(s),
|
|
@@ -337,9 +337,6 @@ export const BUILTIN_TOOLS: Record<string, ToolFactory> = {
|
|
|
337
337
|
web_search: s => new WebSearchTool(s),
|
|
338
338
|
search_tool_bm25: SearchToolBm25Tool.createIf,
|
|
339
339
|
write: s => new WriteTool(s),
|
|
340
|
-
retain: HindsightRetainTool.createIf,
|
|
341
|
-
recall: HindsightRecallTool.createIf,
|
|
342
|
-
reflect: HindsightReflectTool.createIf,
|
|
343
340
|
skill: SkillTool.createIf,
|
|
344
341
|
goal: s => new GoalTool(s),
|
|
345
342
|
};
|
|
@@ -460,11 +457,6 @@ export async function createTools(session: ToolSession, toolNames?: string[]): P
|
|
|
460
457
|
) {
|
|
461
458
|
requestedTools.push("recipe");
|
|
462
459
|
}
|
|
463
|
-
if (session.settings.get("memory.backend") === "hindsight") {
|
|
464
|
-
for (const name of ["recall", "retain", "reflect"]) {
|
|
465
|
-
if (!requestedTools.includes(name)) requestedTools.push(name);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
460
|
}
|
|
469
461
|
// Resolve effective tool discovery mode.
|
|
470
462
|
// tools.discoveryMode takes precedence; mcp.discoveryMode is a back-compat alias for "mcp-only".
|
|
@@ -512,9 +504,6 @@ export async function createTools(session: ToolSession, toolNames?: string[]): P
|
|
|
512
504
|
return true;
|
|
513
505
|
}
|
|
514
506
|
if (name === "recipe") return session.settings.get("recipe.enabled");
|
|
515
|
-
if (name === "retain" || name === "recall" || name === "reflect") {
|
|
516
|
-
return session.settings.get("memory.backend") === "hindsight";
|
|
517
|
-
}
|
|
518
507
|
if (name === "task") {
|
|
519
508
|
const maxDepth = session.settings.get("task.maxRecursionDepth") ?? 2;
|
|
520
509
|
const currentDepth = session.taskDepth ?? 0;
|
package/src/tools/read.ts
CHANGED
|
@@ -1031,7 +1031,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1031
1031
|
}
|
|
1032
1032
|
|
|
1033
1033
|
const collectedLines = streamResult.lines;
|
|
1034
|
-
if (!rawSelector && maxColumns > 0) {
|
|
1034
|
+
if (!rawSelector && !shouldAddHashLines && maxColumns > 0) {
|
|
1035
1035
|
for (let i = 0; i < collectedLines.length; i++) {
|
|
1036
1036
|
const { text, wasTruncated } = truncateLine(collectedLines[i], maxColumns);
|
|
1037
1037
|
if (wasTruncated) {
|
|
@@ -1789,8 +1789,9 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1789
1789
|
// counts in `truncation` keep reflecting the source, not the trimmed
|
|
1790
1790
|
// view — column truncation surfaces separately via `.limits()`.
|
|
1791
1791
|
const rawSelector = isRawSelector(parsed);
|
|
1792
|
+
const shouldAddHashLines = !rawSelector && displayMode.hashLines;
|
|
1792
1793
|
const maxColumns = resolveOutputMaxColumns(this.session.settings);
|
|
1793
|
-
if (!rawSelector && maxColumns > 0) {
|
|
1794
|
+
if (!rawSelector && !shouldAddHashLines && maxColumns > 0) {
|
|
1794
1795
|
for (let i = 0; i < collectedLines.length; i++) {
|
|
1795
1796
|
const { text, wasTruncated } = truncateLine(collectedLines[i], maxColumns);
|
|
1796
1797
|
if (wasTruncated) {
|
|
@@ -1824,7 +1825,6 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
|
|
|
1824
1825
|
getFileReadCache(this.session).recordContiguous(absolutePath, startLineDisplay, collectedLines);
|
|
1825
1826
|
}
|
|
1826
1827
|
|
|
1827
|
-
const shouldAddHashLines = !rawSelector && displayMode.hashLines;
|
|
1828
1828
|
const shouldAddLineNumbers = rawSelector ? false : shouldAddHashLines ? false : displayMode.lineNumbers;
|
|
1829
1829
|
let capturedDisplayContent: { text: string; startLine: number } | undefined;
|
|
1830
1830
|
const formatText = (text: string, startNum: number): string => {
|
package/src/tools/skill.ts
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import type { AgentTool, AgentToolResult } from "@gajae-code/agent-core";
|
|
19
19
|
import { prompt, untilAborted } from "@gajae-code/utils";
|
|
20
20
|
import * as z from "zod/v4";
|
|
21
|
+
import { resolveSubskillActivationForSkillInvocation } from "../extensibility/gjc-plugins";
|
|
21
22
|
import { buildSkillPromptMessage } from "../extensibility/skills";
|
|
22
23
|
import { runNativeStateCommand } from "../gjc-runtime/state-runtime";
|
|
23
24
|
import skillDescription from "../prompts/tools/skill.md" with { type: "text" };
|
|
@@ -125,7 +126,18 @@ export class SkillTool implements AgentTool<typeof skillSchema, SkillToolDetails
|
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
const args = (input.args ?? "").trim();
|
|
128
|
-
const
|
|
129
|
+
const activationResult = await resolveSubskillActivationForSkillInvocation({
|
|
130
|
+
cwd: this.#session.cwd,
|
|
131
|
+
sessionId: this.#session.getSessionId?.() ?? activeState?.session_id?.trim() ?? undefined,
|
|
132
|
+
skillName: skill.name,
|
|
133
|
+
args,
|
|
134
|
+
});
|
|
135
|
+
const built = await buildSkillPromptMessage(skill, activationResult.cleanedArgs, {
|
|
136
|
+
subskillActivation: activationResult.activation,
|
|
137
|
+
subskillActivationSet: activationResult.activeSubskillsToPersist,
|
|
138
|
+
cwd: this.#session.cwd,
|
|
139
|
+
sessionId: this.#session.getSessionId?.() ?? activeState?.session_id?.trim() ?? undefined,
|
|
140
|
+
});
|
|
129
141
|
|
|
130
142
|
await sendCustomMessage(
|
|
131
143
|
{
|
|
@@ -141,7 +153,7 @@ export class SkillTool implements AgentTool<typeof skillSchema, SkillToolDetails
|
|
|
141
153
|
const summary = JSON.stringify({
|
|
142
154
|
callee: skill.name,
|
|
143
155
|
path: skill.filePath,
|
|
144
|
-
args:
|
|
156
|
+
args: activationResult.cleanedArgs || undefined,
|
|
145
157
|
lineCount: built.details.lineCount,
|
|
146
158
|
});
|
|
147
159
|
return {
|
|
@@ -149,7 +161,7 @@ export class SkillTool implements AgentTool<typeof skillSchema, SkillToolDetails
|
|
|
149
161
|
details: {
|
|
150
162
|
name: skill.name,
|
|
151
163
|
path: skill.filePath,
|
|
152
|
-
args:
|
|
164
|
+
args: activationResult.cleanedArgs || undefined,
|
|
153
165
|
lineCount: built.details.lineCount,
|
|
154
166
|
},
|
|
155
167
|
};
|
package/src/utils/edit-mode.ts
CHANGED