@gajae-code/coding-agent 0.2.5 → 0.3.1
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 +28 -0
- package/dist/types/async/job-manager.d.ts +91 -2
- package/dist/types/cli/args.d.ts +1 -1
- package/dist/types/commands/deep-interview.d.ts +3 -0
- package/dist/types/commands/harness.d.ts +37 -0
- package/dist/types/config/keybindings.d.ts +5 -0
- package/dist/types/config/settings-schema.d.ts +10 -4
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/debug/crash-diagnostics.d.ts +45 -0
- package/dist/types/debug/runtime-gauges.d.ts +6 -0
- package/dist/types/deep-interview/render-middleware.d.ts +6 -0
- package/dist/types/eval/py/executor.d.ts +2 -0
- package/dist/types/eval/py/kernel.d.ts +2 -0
- package/dist/types/exec/bash-executor.d.ts +10 -0
- package/dist/types/extensibility/custom-tools/types.d.ts +1 -0
- package/dist/types/extensibility/extensions/types.d.ts +6 -0
- package/dist/types/extensibility/shared-events.d.ts +1 -0
- package/dist/types/gjc-runtime/cli-write-receipt.d.ts +24 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +1 -0
- package/dist/types/gjc-runtime/state-graph.d.ts +4 -0
- package/dist/types/gjc-runtime/state-migrations.d.ts +33 -0
- package/dist/types/gjc-runtime/state-renderer.d.ts +65 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +2 -0
- package/dist/types/gjc-runtime/state-schema.d.ts +317 -0
- package/dist/types/gjc-runtime/state-validation.d.ts +6 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +147 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +81 -7
- package/dist/types/gjc-runtime/workflow-command-ref.d.ts +43 -0
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +54 -0
- package/dist/types/harness-control-plane/classifier.d.ts +13 -0
- package/dist/types/harness-control-plane/control-endpoint.d.ts +31 -0
- package/dist/types/harness-control-plane/finalize.d.ts +47 -0
- package/dist/types/harness-control-plane/frame-mapper.d.ts +29 -0
- package/dist/types/harness-control-plane/operate.d.ts +35 -0
- package/dist/types/harness-control-plane/owner.d.ts +46 -0
- package/dist/types/harness-control-plane/preserve.d.ts +19 -0
- package/dist/types/harness-control-plane/receipts.d.ts +88 -0
- package/dist/types/harness-control-plane/rpc-adapter.d.ts +66 -0
- package/dist/types/harness-control-plane/seams.d.ts +21 -0
- package/dist/types/harness-control-plane/session-lease.d.ts +65 -0
- package/dist/types/harness-control-plane/state-machine.d.ts +19 -0
- package/dist/types/harness-control-plane/storage.d.ts +53 -0
- package/dist/types/harness-control-plane/types.d.ts +162 -0
- package/dist/types/hooks/skill-keywords.d.ts +2 -1
- package/dist/types/hooks/skill-state.d.ts +23 -29
- package/dist/types/internal-urls/agent-protocol.d.ts +2 -2
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
- package/dist/types/internal-urls/registry-helpers.d.ts +8 -7
- package/dist/types/internal-urls/types.d.ts +4 -0
- package/dist/types/lsp/index.d.ts +10 -10
- package/dist/types/modes/bridge/auth.d.ts +12 -0
- package/dist/types/modes/bridge/bridge-client-bridge.d.ts +9 -0
- package/dist/types/modes/bridge/bridge-mode.d.ts +44 -0
- package/dist/types/modes/bridge/bridge-ui-context.d.ts +88 -0
- package/dist/types/modes/bridge/event-stream.d.ts +8 -0
- package/dist/types/modes/components/custom-editor.d.ts +6 -0
- package/dist/types/modes/components/hook-selector.d.ts +1 -0
- package/dist/types/modes/components/jobs-overlay-model.d.ts +31 -0
- package/dist/types/modes/components/jobs-overlay.d.ts +30 -0
- package/dist/types/modes/components/status-line/types.d.ts +2 -0
- package/dist/types/modes/components/status-line.d.ts +2 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +8 -0
- package/dist/types/modes/index.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +2 -0
- package/dist/types/modes/jobs-observer.d.ts +57 -0
- package/dist/types/modes/rpc/host-tools.d.ts +1 -16
- package/dist/types/modes/rpc/host-uris.d.ts +1 -38
- package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +20 -0
- package/dist/types/modes/shared/agent-wire/command-validation.d.ts +2 -0
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +24 -0
- package/dist/types/modes/shared/agent-wire/handshake.d.ts +46 -0
- package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +16 -0
- package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +17 -0
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +44 -0
- package/dist/types/modes/shared/agent-wire/responses.d.ts +4 -0
- package/dist/types/modes/shared/agent-wire/scopes.d.ts +18 -0
- package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +42 -0
- package/dist/types/modes/shared/agent-wire/ui-result.d.ts +27 -0
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/sdk.d.ts +4 -0
- package/dist/types/session/agent-session.d.ts +19 -1
- package/dist/types/skill-state/active-state.d.ts +2 -0
- package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +1 -1
- package/dist/types/skill-state/workflow-state-contract.d.ts +25 -2
- package/dist/types/skill-state/workflow-state-version.d.ts +3 -0
- package/dist/types/task/executor.d.ts +3 -0
- package/dist/types/task/id.d.ts +7 -0
- package/dist/types/task/index.d.ts +5 -0
- package/dist/types/task/receipt.d.ts +85 -0
- package/dist/types/task/spawn-gate.d.ts +38 -0
- package/dist/types/task/types.d.ts +198 -14
- package/dist/types/tools/cron.d.ts +6 -0
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/path-utils.d.ts +1 -0
- package/dist/types/tools/subagent.d.ts +26 -1
- package/package.json +7 -7
- package/scripts/build-binary.ts +7 -0
- package/src/async/job-manager.ts +334 -6
- package/src/cli/args.ts +9 -2
- package/src/cli/auth-broker-cli.ts +1 -0
- package/src/cli/config-cli.ts +10 -2
- package/src/cli.ts +2 -0
- package/src/commands/deep-interview.ts +1 -0
- package/src/commands/harness.ts +862 -0
- package/src/commands/launch.ts +2 -2
- package/src/commands/state.ts +2 -1
- package/src/commands/team.ts +54 -39
- package/src/config/keybindings.ts +6 -0
- package/src/config/settings-schema.ts +13 -3
- package/src/config/settings.ts +5 -0
- package/src/dap/client.ts +17 -3
- package/src/debug/crash-diagnostics.ts +223 -0
- package/src/debug/runtime-gauges.ts +20 -0
- package/src/deep-interview/render-middleware.ts +372 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -1
- package/src/defaults/gjc/skills/ralplan/SKILL.md +31 -2
- package/src/defaults/gjc/skills/team/SKILL.md +47 -21
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +106 -13
- package/src/eval/py/executor.ts +21 -1
- package/src/eval/py/kernel.ts +15 -0
- package/src/exec/bash-executor.ts +41 -0
- package/src/extensibility/custom-tools/types.ts +1 -0
- package/src/extensibility/extensions/types.ts +6 -0
- package/src/extensibility/shared-events.ts +1 -0
- package/src/gjc-runtime/cli-write-receipt.ts +31 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +98 -42
- package/src/gjc-runtime/goal-mode-request.ts +11 -3
- package/src/gjc-runtime/ralplan-runtime.ts +235 -43
- package/src/gjc-runtime/state-graph.ts +86 -0
- package/src/gjc-runtime/state-migrations.ts +179 -0
- package/src/gjc-runtime/state-renderer.ts +345 -0
- package/src/gjc-runtime/state-runtime.ts +1155 -46
- package/src/gjc-runtime/state-schema.ts +192 -0
- package/src/gjc-runtime/state-validation.ts +49 -0
- package/src/gjc-runtime/state-writer.ts +749 -0
- package/src/gjc-runtime/team-runtime.ts +1255 -189
- package/src/gjc-runtime/ultragoal-runtime.ts +460 -43
- package/src/gjc-runtime/workflow-command-ref.ts +239 -0
- package/src/gjc-runtime/workflow-manifest.generated.json +1601 -0
- package/src/gjc-runtime/workflow-manifest.ts +427 -0
- package/src/harness-control-plane/classifier.ts +128 -0
- package/src/harness-control-plane/control-endpoint.ts +148 -0
- package/src/harness-control-plane/finalize.ts +222 -0
- package/src/harness-control-plane/frame-mapper.ts +286 -0
- package/src/harness-control-plane/operate.ts +225 -0
- package/src/harness-control-plane/owner.ts +600 -0
- package/src/harness-control-plane/preserve.ts +102 -0
- package/src/harness-control-plane/receipts.ts +216 -0
- package/src/harness-control-plane/rpc-adapter.ts +276 -0
- package/src/harness-control-plane/seams.ts +39 -0
- package/src/harness-control-plane/session-lease.ts +388 -0
- package/src/harness-control-plane/state-machine.ts +98 -0
- package/src/harness-control-plane/storage.ts +257 -0
- package/src/harness-control-plane/types.ts +214 -0
- package/src/hooks/skill-keywords.ts +4 -2
- package/src/hooks/skill-state.ts +197 -64
- package/src/internal-urls/agent-protocol.ts +68 -21
- package/src/internal-urls/artifact-protocol.ts +12 -17
- package/src/internal-urls/docs-index.generated.ts +3 -2
- package/src/internal-urls/registry-helpers.ts +19 -16
- package/src/internal-urls/types.ts +4 -0
- package/src/lsp/client.ts +18 -2
- package/src/main.ts +21 -5
- package/src/modes/bridge/auth.ts +41 -0
- package/src/modes/bridge/bridge-client-bridge.ts +47 -0
- package/src/modes/bridge/bridge-mode.ts +520 -0
- package/src/modes/bridge/bridge-ui-context.ts +200 -0
- package/src/modes/bridge/event-stream.ts +70 -0
- package/src/modes/components/assistant-message.ts +5 -1
- package/src/modes/components/custom-editor.ts +101 -0
- package/src/modes/components/hook-selector.ts +133 -20
- package/src/modes/components/jobs-overlay-model.ts +109 -0
- package/src/modes/components/jobs-overlay.ts +172 -0
- package/src/modes/components/status-line/presets.ts +7 -5
- package/src/modes/components/status-line/segments.ts +25 -0
- package/src/modes/components/status-line/types.ts +2 -0
- package/src/modes/components/status-line.ts +9 -1
- package/src/modes/controllers/event-controller.ts +71 -6
- package/src/modes/controllers/extension-ui-controller.ts +43 -1
- package/src/modes/controllers/input-controller.ts +105 -9
- package/src/modes/controllers/selector-controller.ts +31 -1
- package/src/modes/index.ts +1 -0
- package/src/modes/interactive-mode.ts +28 -0
- package/src/modes/jobs-observer.ts +204 -0
- package/src/modes/rpc/host-tools.ts +1 -186
- package/src/modes/rpc/host-uris.ts +1 -235
- package/src/modes/rpc/rpc-client.ts +25 -10
- package/src/modes/rpc/rpc-mode.ts +12 -381
- package/src/modes/shared/agent-wire/command-dispatch.ts +341 -0
- package/src/modes/shared/agent-wire/command-validation.ts +131 -0
- package/src/modes/shared/agent-wire/event-envelope.ts +108 -0
- package/src/modes/shared/agent-wire/handshake.ts +117 -0
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +194 -0
- package/src/modes/shared/agent-wire/host-uri-bridge.ts +236 -0
- package/src/modes/shared/agent-wire/protocol.ts +96 -0
- package/src/modes/shared/agent-wire/responses.ts +17 -0
- package/src/modes/shared/agent-wire/scopes.ts +89 -0
- package/src/modes/shared/agent-wire/ui-request-broker.ts +150 -0
- package/src/modes/shared/agent-wire/ui-result.ts +48 -0
- package/src/modes/types.ts +2 -0
- package/src/prompts/agents/executor.md +13 -0
- package/src/prompts/tools/subagent.md +39 -4
- package/src/prompts/tools/task-summary.md +3 -9
- package/src/prompts/tools/task.md +5 -1
- package/src/sdk.ts +8 -0
- package/src/session/agent-session.ts +445 -71
- package/src/session/session-manager.ts +13 -1
- package/src/skill-state/active-state.ts +58 -65
- package/src/skill-state/deep-interview-mutation-guard.ts +114 -17
- package/src/skill-state/initial-phase.ts +2 -0
- package/src/skill-state/workflow-state-contract.ts +33 -4
- package/src/skill-state/workflow-state-version.ts +3 -0
- package/src/slash-commands/builtin-registry.ts +8 -0
- package/src/task/executor.ts +79 -13
- package/src/task/id.ts +33 -0
- package/src/task/index.ts +376 -74
- package/src/task/output-manager.ts +5 -4
- package/src/task/receipt.ts +297 -0
- package/src/task/render.ts +54 -134
- package/src/task/spawn-gate.ts +132 -0
- package/src/task/types.ts +104 -10
- package/src/tools/ask.ts +88 -27
- package/src/tools/ast-edit.ts +1 -0
- package/src/tools/ast-grep.ts +1 -0
- package/src/tools/bash.ts +1 -1
- package/src/tools/cron.ts +48 -0
- package/src/tools/find.ts +4 -1
- package/src/tools/index.ts +2 -0
- package/src/tools/path-utils.ts +3 -2
- package/src/tools/read.ts +1 -0
- package/src/tools/search.ts +1 -0
- package/src/tools/skill.ts +6 -1
- package/src/tools/subagent.ts +423 -79
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/** The hard, locked batch threshold enforced by the runtime gate. */
|
|
2
|
+
export const DEFAULT_SPAWN_THRESHOLD = 4;
|
|
3
|
+
|
|
4
|
+
/** The justification a large batch or reviewer-spawned explorer must supply to pass the hard gate. */
|
|
5
|
+
export interface SpawnPlanReceipt {
|
|
6
|
+
whyParallel: string;
|
|
7
|
+
whyNotLocal: string;
|
|
8
|
+
independence: string;
|
|
9
|
+
expectedReceiptShape: string;
|
|
10
|
+
maxInlineTokens: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface SpawnGateRequest {
|
|
14
|
+
/** Number of children the batch wants to spawn. */
|
|
15
|
+
childCount: number;
|
|
16
|
+
/** The spawn-plan receipt, when provided. */
|
|
17
|
+
plan?: SpawnPlanReceipt;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ReviewerExploreGateRequest {
|
|
21
|
+
/** Agent type/name doing the spawning, when known. */
|
|
22
|
+
spawningAgentType?: string | null;
|
|
23
|
+
/** Target agent type/name requested by the task call. */
|
|
24
|
+
targetAgent: string;
|
|
25
|
+
/** The spawn-plan receipt, when provided. */
|
|
26
|
+
plan?: SpawnPlanReceipt;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type SpawnGateOutcome = "allowed" | "rejected";
|
|
30
|
+
|
|
31
|
+
export interface SpawnGateDecision {
|
|
32
|
+
outcome: SpawnGateOutcome;
|
|
33
|
+
/** Human-readable reason, suitable for a blocked-result message. */
|
|
34
|
+
reason: string;
|
|
35
|
+
/** Whether a plan was required for this request. */
|
|
36
|
+
planRequired: boolean;
|
|
37
|
+
/** Missing plan field names when rejected for an incomplete plan. */
|
|
38
|
+
missingFields: readonly string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const REQUIRED_STRING_FIELDS = ["whyParallel", "whyNotLocal", "independence", "expectedReceiptShape"] as const;
|
|
42
|
+
|
|
43
|
+
export function findMissingPlanFields(plan: SpawnPlanReceipt | undefined): string[] {
|
|
44
|
+
if (plan === undefined) {
|
|
45
|
+
return [...REQUIRED_STRING_FIELDS, "maxInlineTokens"];
|
|
46
|
+
}
|
|
47
|
+
const missing: string[] = [];
|
|
48
|
+
for (const field of REQUIRED_STRING_FIELDS) {
|
|
49
|
+
const value = plan[field];
|
|
50
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
51
|
+
missing.push(field);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (
|
|
55
|
+
typeof plan.maxInlineTokens !== "number" ||
|
|
56
|
+
!Number.isFinite(plan.maxInlineTokens) ||
|
|
57
|
+
plan.maxInlineTokens <= 0
|
|
58
|
+
) {
|
|
59
|
+
missing.push("maxInlineTokens");
|
|
60
|
+
}
|
|
61
|
+
return missing;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function decide(childCount: number, threshold: number, plan: SpawnPlanReceipt | undefined): SpawnGateDecision {
|
|
65
|
+
if (!Number.isInteger(childCount) || childCount < 0) {
|
|
66
|
+
throw new RangeError("childCount must be a non-negative integer");
|
|
67
|
+
}
|
|
68
|
+
if (!Number.isInteger(threshold) || threshold < 1) {
|
|
69
|
+
throw new RangeError("threshold must be a positive integer");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const planRequired = childCount > threshold;
|
|
73
|
+
if (!planRequired) {
|
|
74
|
+
return {
|
|
75
|
+
outcome: "allowed",
|
|
76
|
+
reason: `batch of ${childCount} is at or below threshold ${threshold}`,
|
|
77
|
+
planRequired: false,
|
|
78
|
+
missingFields: [],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const missingFields = findMissingPlanFields(plan);
|
|
83
|
+
if (missingFields.length > 0) {
|
|
84
|
+
return {
|
|
85
|
+
outcome: "rejected",
|
|
86
|
+
reason: `batch of ${childCount} exceeds threshold ${threshold} and the spawn-plan receipt is ${
|
|
87
|
+
plan === undefined ? "missing" : `incomplete (${missingFields.join(", ")})`
|
|
88
|
+
}`,
|
|
89
|
+
planRequired: true,
|
|
90
|
+
missingFields,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
outcome: "allowed",
|
|
96
|
+
reason: `batch of ${childCount} exceeds threshold ${threshold} and a complete spawn-plan receipt was provided`,
|
|
97
|
+
planRequired: true,
|
|
98
|
+
missingFields: [],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function evaluateSpawnGate(request: SpawnGateRequest): SpawnGateDecision {
|
|
103
|
+
return decide(request.childCount, DEFAULT_SPAWN_THRESHOLD, request.plan);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function evaluateReviewerExploreGate(request: ReviewerExploreGateRequest): SpawnGateDecision {
|
|
107
|
+
if (request.spawningAgentType !== "reviewer" || request.targetAgent !== "explore") {
|
|
108
|
+
return {
|
|
109
|
+
outcome: "allowed",
|
|
110
|
+
reason: "reviewer->explore gate does not apply",
|
|
111
|
+
planRequired: false,
|
|
112
|
+
missingFields: [],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const missingFields = findMissingPlanFields(request.plan);
|
|
117
|
+
if (missingFields.length > 0) {
|
|
118
|
+
return {
|
|
119
|
+
outcome: "rejected",
|
|
120
|
+
reason: `reviewer->explore spawn requires a complete spawn-plan receipt (${missingFields.join(", ")})`,
|
|
121
|
+
planRequired: true,
|
|
122
|
+
missingFields,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
outcome: "allowed",
|
|
128
|
+
reason: "reviewer->explore spawn has a complete spawn-plan receipt",
|
|
129
|
+
planRequired: true,
|
|
130
|
+
missingFields: [],
|
|
131
|
+
};
|
|
132
|
+
}
|
package/src/task/types.ts
CHANGED
|
@@ -2,12 +2,16 @@ import type { ThinkingLevel } from "@gajae-code/agent-core";
|
|
|
2
2
|
import type { Usage } from "@gajae-code/ai";
|
|
3
3
|
import { $env } from "@gajae-code/utils";
|
|
4
4
|
import * as z from "zod/v4";
|
|
5
|
+
import { isValidTaskId, TASK_ID_DESCRIPTION } from "./id";
|
|
6
|
+
import type { TaskResultReceipt } from "./receipt";
|
|
5
7
|
import { getTaskSimpleModeCapabilities, type TaskSimpleMode } from "./simple-mode";
|
|
8
|
+
import type { SpawnPlanReceipt } from "./spawn-gate";
|
|
6
9
|
import type { NestedRepoPatch } from "./worktree";
|
|
7
10
|
|
|
8
11
|
/** Source of an agent definition */
|
|
9
12
|
export type AgentSource = "bundled" | "user" | "project";
|
|
10
13
|
export type ForkContextPolicy = "forbidden" | "allowed";
|
|
14
|
+
export type ForkContextMode = "none" | "receipt" | "last-turn" | "bounded" | "full";
|
|
11
15
|
|
|
12
16
|
const parseNumber = (value: string | undefined, defaultValue: number): number => {
|
|
13
17
|
if (value) {
|
|
@@ -53,22 +57,33 @@ export interface SubagentLifecyclePayload {
|
|
|
53
57
|
agent: string;
|
|
54
58
|
agentSource: AgentSource;
|
|
55
59
|
description?: string;
|
|
56
|
-
status: "started" | "completed" | "failed" | "aborted";
|
|
60
|
+
status: "started" | "completed" | "failed" | "aborted" | "paused";
|
|
57
61
|
sessionFile?: string;
|
|
58
62
|
index: number;
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
const assignmentDescription = "per-task instructions; self-contained";
|
|
66
|
+
const spawnPlanSchema = z
|
|
67
|
+
.object({
|
|
68
|
+
whyParallel: z.string(),
|
|
69
|
+
whyNotLocal: z.string(),
|
|
70
|
+
independence: z.string(),
|
|
71
|
+
expectedReceiptShape: z.string(),
|
|
72
|
+
maxInlineTokens: z.number(),
|
|
73
|
+
})
|
|
74
|
+
.describe("justification required before spawning more than four tasks or reviewer-spawned explore tasks");
|
|
62
75
|
|
|
63
76
|
const createTaskItemSchema = (_contextEnabled: boolean) =>
|
|
64
77
|
z.object({
|
|
65
|
-
id: z.string().max(48).describe("
|
|
78
|
+
id: z.string().max(48).refine(isValidTaskId, TASK_ID_DESCRIPTION).describe("filesystem-safe task identifier"),
|
|
66
79
|
description: z.string().describe("ui label, not seen by subagent"),
|
|
67
80
|
assignment: z.string().describe(assignmentDescription),
|
|
68
81
|
inheritContext: z
|
|
69
|
-
.
|
|
82
|
+
.enum(["none", "receipt", "last-turn", "bounded", "full"])
|
|
70
83
|
.optional()
|
|
71
|
-
.describe(
|
|
84
|
+
.describe(
|
|
85
|
+
"fork-context mode: none/omitted copies no parent context; receipt copies a minimal receipt-sized snapshot; last-turn copies only the latest exchange; bounded copies the bounded default snapshot; full copies a larger sanitized snapshot up to the configured/model token cap",
|
|
86
|
+
),
|
|
72
87
|
});
|
|
73
88
|
|
|
74
89
|
/** Single task item for parallel execution (default shape with context enabled). */
|
|
@@ -77,11 +92,23 @@ export type TaskItem = z.infer<typeof taskItemSchema>;
|
|
|
77
92
|
|
|
78
93
|
const createTaskSchema = (options: { isolationEnabled: boolean; simpleMode: TaskSimpleMode }) => {
|
|
79
94
|
const { contextEnabled, customSchemaEnabled } = getTaskSimpleModeCapabilities(options.simpleMode);
|
|
80
|
-
|
|
95
|
+
let itemSchema = createTaskItemSchema(contextEnabled);
|
|
96
|
+
if (!contextEnabled) {
|
|
97
|
+
itemSchema = itemSchema.superRefine((item, ctx) => {
|
|
98
|
+
if (item.inheritContext !== undefined && item.inheritContext !== "none") {
|
|
99
|
+
ctx.addIssue({
|
|
100
|
+
code: "custom",
|
|
101
|
+
path: ["inheritContext"],
|
|
102
|
+
message: "Independent tasks cannot inherit parent context; omit inheritContext or set it to none.",
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
81
107
|
|
|
82
108
|
let schema = z.object({
|
|
83
109
|
agent: z.string().describe("agent type"),
|
|
84
110
|
tasks: z.array(itemSchema).describe("tasks to execute in parallel"),
|
|
111
|
+
spawnPlan: spawnPlanSchema.optional(),
|
|
85
112
|
});
|
|
86
113
|
if (contextEnabled) {
|
|
87
114
|
schema = schema.extend({
|
|
@@ -139,6 +166,7 @@ export interface TaskParams {
|
|
|
139
166
|
agent: string;
|
|
140
167
|
context?: string;
|
|
141
168
|
schema?: string;
|
|
169
|
+
spawnPlan?: SpawnPlanReceipt;
|
|
142
170
|
tasks: TaskItem[];
|
|
143
171
|
isolated?: boolean;
|
|
144
172
|
}
|
|
@@ -192,7 +220,7 @@ export interface AgentProgress {
|
|
|
192
220
|
id: string;
|
|
193
221
|
agent: string;
|
|
194
222
|
agentSource: AgentSource;
|
|
195
|
-
status: "pending" | "running" | "completed" | "failed" | "aborted";
|
|
223
|
+
status: "pending" | "running" | "completed" | "failed" | "aborted" | "paused";
|
|
196
224
|
task: string;
|
|
197
225
|
assignment?: string;
|
|
198
226
|
description?: string;
|
|
@@ -230,6 +258,7 @@ export interface AgentProgress {
|
|
|
230
258
|
retryState?: {
|
|
231
259
|
attempt: number;
|
|
232
260
|
maxAttempts: number;
|
|
261
|
+
unbounded?: boolean;
|
|
233
262
|
delayMs: number;
|
|
234
263
|
errorMessage: string;
|
|
235
264
|
startedAtMs: number;
|
|
@@ -279,6 +308,7 @@ export interface SingleResult {
|
|
|
279
308
|
error?: string;
|
|
280
309
|
aborted?: boolean;
|
|
281
310
|
abortReason?: string;
|
|
311
|
+
paused?: boolean;
|
|
282
312
|
/** Aggregated usage from the subprocess, accumulated incrementally from message_end events. */
|
|
283
313
|
usage?: Usage;
|
|
284
314
|
/** Output path for the task result */
|
|
@@ -289,6 +319,8 @@ export interface SingleResult {
|
|
|
289
319
|
branchName?: string;
|
|
290
320
|
/** Nested repo patches to apply after parent merge */
|
|
291
321
|
nestedPatches?: NestedRepoPatch[];
|
|
322
|
+
/** Whether isolated execution produced a non-empty root or nested patch. */
|
|
323
|
+
producedChanges?: boolean;
|
|
292
324
|
/** Data extracted by registered subprocess tool handlers (keyed by tool name) */
|
|
293
325
|
extractedToolData?: Record<string, unknown[]>;
|
|
294
326
|
/**
|
|
@@ -302,21 +334,83 @@ export interface SingleResult {
|
|
|
302
334
|
errorMessage: string;
|
|
303
335
|
};
|
|
304
336
|
/** Output metadata for agent:// URL integration */
|
|
305
|
-
outputMeta?: { lineCount: number; charCount: number };
|
|
337
|
+
outputMeta?: { lineCount: number; charCount: number; byteSize?: number; sha256?: string };
|
|
338
|
+
/** Fork-context seed accounting for this subagent, when inherited parent context was cloned. */
|
|
339
|
+
forkContext?: { mode: ForkContextMode; clonedTokens: number };
|
|
306
340
|
}
|
|
307
341
|
|
|
308
342
|
/** Tool details for TUI rendering */
|
|
309
343
|
export interface TaskToolDetails {
|
|
310
344
|
projectAgentsDir: string | null;
|
|
311
|
-
results:
|
|
345
|
+
results: TaskResultReceipt[];
|
|
312
346
|
totalDurationMs: number;
|
|
313
347
|
/** Aggregated usage across all subagents. */
|
|
314
348
|
usage?: Usage;
|
|
315
|
-
|
|
349
|
+
/** Aggregate cloned tokens copied into fork-context seeds across subagents. */
|
|
350
|
+
forkContextClonedTokens?: number;
|
|
351
|
+
roiSummary?: {
|
|
352
|
+
childCount: number;
|
|
353
|
+
totalTokens: number;
|
|
354
|
+
totalCostTotal?: number;
|
|
355
|
+
totalClonedTokens?: number;
|
|
356
|
+
/** Advisory ids for terminal children that spent tokens without detectable output/review/changes. */
|
|
357
|
+
lowRoiChildIds: string[];
|
|
358
|
+
};
|
|
316
359
|
progress?: AgentProgress[];
|
|
317
360
|
async?: {
|
|
318
|
-
state: "running" | "completed" | "failed";
|
|
361
|
+
state: "running" | "paused" | "queued" | "completed" | "failed";
|
|
319
362
|
jobId: string;
|
|
320
363
|
type: "task";
|
|
321
364
|
};
|
|
322
365
|
}
|
|
366
|
+
/**
|
|
367
|
+
* Persisted per-turn / per-subagent token record (Phase 0 instrumentation).
|
|
368
|
+
*
|
|
369
|
+
* Additive: this does not alter any existing task result shape. It is the
|
|
370
|
+
* durable, model-independent unit the deterministic orchestration-token
|
|
371
|
+
* benchmark (`@gajae-code/orchestration-token-benchmark`) consumes to measure
|
|
372
|
+
* token efficiency without any live-model calls.
|
|
373
|
+
*/
|
|
374
|
+
export interface TaskTokenLog {
|
|
375
|
+
/** Subagent id, or "root" for the orchestrator's own turn. */
|
|
376
|
+
subagentId: string;
|
|
377
|
+
/** Agent name for attribution, when known. */
|
|
378
|
+
agent?: string;
|
|
379
|
+
/** 1-based turn index within the subagent's session. */
|
|
380
|
+
turn: number;
|
|
381
|
+
/** ISO-8601 timestamp the turn completed. */
|
|
382
|
+
at: string;
|
|
383
|
+
/** Cost-bearing input tokens (excludes cache reads), mirrors `Usage.input`. */
|
|
384
|
+
input: number;
|
|
385
|
+
/** Total output tokens for the turn, mirrors `Usage.output`. */
|
|
386
|
+
output: number;
|
|
387
|
+
/** Tokens read from the prompt cache, mirrors `Usage.cacheRead`. */
|
|
388
|
+
cacheRead: number;
|
|
389
|
+
/** Tokens written to the prompt cache, mirrors `Usage.cacheWrite`. */
|
|
390
|
+
cacheWrite: number;
|
|
391
|
+
/** input + output + cacheRead + cacheWrite. */
|
|
392
|
+
totalTokens: number;
|
|
393
|
+
/** Latest per-turn context-window occupancy, when known. */
|
|
394
|
+
contextTokens?: number;
|
|
395
|
+
/** Estimated USD cost for the turn, when known. */
|
|
396
|
+
cost?: number;
|
|
397
|
+
/** Model id used for the turn, when known. */
|
|
398
|
+
model?: string;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Deterministic aggregate token metrics computed from a set of `TaskTokenLog`
|
|
403
|
+
* entries. The cache-hit-rate field is the primary prompt-cache signal called
|
|
404
|
+
* out by the prefix-stability invariant (see the approved plan).
|
|
405
|
+
*/
|
|
406
|
+
export interface TaskTokenMetrics {
|
|
407
|
+
/** Number of token-log entries aggregated. */
|
|
408
|
+
turns: number;
|
|
409
|
+
inputTokens: number;
|
|
410
|
+
outputTokens: number;
|
|
411
|
+
cacheReadTokens: number;
|
|
412
|
+
cacheWriteTokens: number;
|
|
413
|
+
totalTokens: number;
|
|
414
|
+
/** cacheRead / (input + cacheRead); 0 when there is no input-class traffic. */
|
|
415
|
+
cacheHitRate: number;
|
|
416
|
+
}
|
package/src/tools/ask.ts
CHANGED
|
@@ -28,6 +28,11 @@ import {
|
|
|
28
28
|
} from "@gajae-code/tui";
|
|
29
29
|
import { prompt, untilAborted } from "@gajae-code/utils";
|
|
30
30
|
import * as z from "zod/v4";
|
|
31
|
+
import {
|
|
32
|
+
formatDeepInterviewSelectorPrompt,
|
|
33
|
+
isDeepInterviewAskQuestion,
|
|
34
|
+
renderDeepInterviewAskQuestion,
|
|
35
|
+
} from "../deep-interview/render-middleware";
|
|
31
36
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
32
37
|
import { getMarkdownTheme, type Theme, theme } from "../modes/theme/theme";
|
|
33
38
|
import askDescription from "../prompts/tools/ask.md" with { type: "text" };
|
|
@@ -84,6 +89,7 @@ export interface AskToolDetails {
|
|
|
84
89
|
|
|
85
90
|
const OTHER_OPTION = "Other (type your own)";
|
|
86
91
|
const RECOMMENDED_SUFFIX = " (Recommended)";
|
|
92
|
+
const DEEP_INTERVIEW_SELECTOR_SCROLL_TITLE_ROWS = Number.MAX_SAFE_INTEGER;
|
|
87
93
|
|
|
88
94
|
function getDoneOptionLabel(): string {
|
|
89
95
|
return `${theme.status.success} Done selecting`;
|
|
@@ -115,6 +121,17 @@ function stripRecommendedSuffix(label: string): string {
|
|
|
115
121
|
return label.endsWith(RECOMMENDED_SUFFIX) ? label.slice(0, -RECOMMENDED_SUFFIX.length) : label;
|
|
116
122
|
}
|
|
117
123
|
|
|
124
|
+
function formatNumberedOptionLabel(label: string, index: number): string {
|
|
125
|
+
if (/^\s*\d+[.)]\s+/.test(label)) {
|
|
126
|
+
return label;
|
|
127
|
+
}
|
|
128
|
+
return `${index + 1}. ${label}`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function numberOptionLabels(labels: string[]): string[] {
|
|
132
|
+
return labels.map(formatNumberedOptionLabel);
|
|
133
|
+
}
|
|
134
|
+
|
|
118
135
|
// =============================================================================
|
|
119
136
|
// Question Selection Logic
|
|
120
137
|
// =============================================================================
|
|
@@ -138,6 +155,8 @@ interface AskSingleQuestionOptions {
|
|
|
138
155
|
signal?: AbortSignal;
|
|
139
156
|
initialSelection?: Pick<SelectionResult, "selectedOptions" | "customInput">;
|
|
140
157
|
navigation?: NavigationControls;
|
|
158
|
+
scrollTitleRows?: number;
|
|
159
|
+
otherOptionLabel?: string;
|
|
141
160
|
}
|
|
142
161
|
|
|
143
162
|
interface UIContext {
|
|
@@ -150,6 +169,7 @@ interface UIContext {
|
|
|
150
169
|
signal?: AbortSignal;
|
|
151
170
|
outline?: boolean;
|
|
152
171
|
wrapFocused?: boolean;
|
|
172
|
+
scrollTitleRows?: number;
|
|
153
173
|
onTimeout?: () => void;
|
|
154
174
|
onLeft?: () => void;
|
|
155
175
|
onRight?: () => void;
|
|
@@ -171,7 +191,7 @@ async function askSingleQuestion(
|
|
|
171
191
|
multi: boolean,
|
|
172
192
|
options: AskSingleQuestionOptions = {},
|
|
173
193
|
): Promise<SelectionResult> {
|
|
174
|
-
const { recommended, timeout, signal, initialSelection, navigation } = options;
|
|
194
|
+
const { recommended, timeout, signal, initialSelection, navigation, scrollTitleRows } = options;
|
|
175
195
|
const doneLabel = getDoneOptionLabel();
|
|
176
196
|
let selectedOptions = [...(initialSelection?.selectedOptions ?? [])];
|
|
177
197
|
let customInput = initialSelection?.customInput;
|
|
@@ -187,15 +207,18 @@ async function askSingleQuestion(
|
|
|
187
207
|
timeoutTriggered = true;
|
|
188
208
|
};
|
|
189
209
|
let navigationAction: "back" | "forward" | undefined;
|
|
190
|
-
const
|
|
210
|
+
const baseHelpText = navigation
|
|
191
211
|
? "up/down navigate enter select ←/→ question esc cancel"
|
|
192
212
|
: "up/down navigate enter select esc cancel";
|
|
213
|
+
const helpText =
|
|
214
|
+
scrollTitleRows === undefined ? baseHelpText : `${baseHelpText} wheel/PgUp/PgDn scroll question`;
|
|
193
215
|
const dialogOptions = {
|
|
194
216
|
initialIndex,
|
|
195
217
|
timeout,
|
|
196
218
|
signal,
|
|
197
219
|
outline: true,
|
|
198
220
|
wrapFocused: true,
|
|
221
|
+
scrollTitleRows,
|
|
199
222
|
onTimeout,
|
|
200
223
|
helpText,
|
|
201
224
|
onLeft: navigation?.allowBack
|
|
@@ -225,6 +248,7 @@ async function askSingleQuestion(
|
|
|
225
248
|
const input = signal ? await untilAborted(signal, showCustomInput) : await showCustomInput();
|
|
226
249
|
return { input };
|
|
227
250
|
};
|
|
251
|
+
const otherOptionLabel = options.otherOptionLabel ?? OTHER_OPTION;
|
|
228
252
|
|
|
229
253
|
const promptWithProgress = navigation?.progressText ? `${question} (${navigation.progressText})` : question;
|
|
230
254
|
if (multi) {
|
|
@@ -246,7 +270,7 @@ async function askSingleQuestion(
|
|
|
246
270
|
if (!navigation?.allowForward && selected.size > 0) {
|
|
247
271
|
opts.push(doneLabel);
|
|
248
272
|
}
|
|
249
|
-
opts.push(
|
|
273
|
+
opts.push(otherOptionLabel);
|
|
250
274
|
|
|
251
275
|
const prefix = selected.size > 0 ? `(${selected.size} selected) ` : "";
|
|
252
276
|
const {
|
|
@@ -267,7 +291,7 @@ async function askSingleQuestion(
|
|
|
267
291
|
}
|
|
268
292
|
if (choice === doneLabel) break;
|
|
269
293
|
|
|
270
|
-
if (choice ===
|
|
294
|
+
if (choice === otherOptionLabel) {
|
|
271
295
|
if (selectTimedOut) {
|
|
272
296
|
timedOut = true;
|
|
273
297
|
break;
|
|
@@ -309,7 +333,7 @@ async function askSingleQuestion(
|
|
|
309
333
|
selectedOptions = Array.from(selected);
|
|
310
334
|
} else {
|
|
311
335
|
const displayLabels = addRecommendedSuffix(optionLabels, recommended);
|
|
312
|
-
const optionsWithNavigation = [...displayLabels,
|
|
336
|
+
const optionsWithNavigation = [...displayLabels, otherOptionLabel];
|
|
313
337
|
|
|
314
338
|
let initialIndex = recommended;
|
|
315
339
|
const previouslySelected = selectedOptions[0];
|
|
@@ -338,7 +362,7 @@ async function askSingleQuestion(
|
|
|
338
362
|
if (!timedOut) {
|
|
339
363
|
return { selectedOptions, customInput, timedOut, cancelled: true };
|
|
340
364
|
}
|
|
341
|
-
} else if (choice ===
|
|
365
|
+
} else if (choice === otherOptionLabel) {
|
|
342
366
|
if (!selectTimedOut) {
|
|
343
367
|
const customResult = await promptForCustomInput();
|
|
344
368
|
if (customResult.input !== undefined) {
|
|
@@ -452,22 +476,46 @@ export class AskTool implements AgentTool<typeof askSchema, AskToolDetails> {
|
|
|
452
476
|
q: AskParams["questions"][number],
|
|
453
477
|
options?: { previous?: QuestionResult; navigation?: NavigationControls },
|
|
454
478
|
) => {
|
|
455
|
-
const
|
|
479
|
+
const rawOptionLabels = q.options.map(o => o.label);
|
|
456
480
|
try {
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
481
|
+
const deepInterviewPrompt = formatDeepInterviewSelectorPrompt(q.question);
|
|
482
|
+
const displayQuestion = deepInterviewPrompt ?? q.question;
|
|
483
|
+
const shouldNumberOptions = isDeepInterviewAskQuestion(q.question);
|
|
484
|
+
const optionLabels = shouldNumberOptions ? numberOptionLabels(rawOptionLabels) : rawOptionLabels;
|
|
485
|
+
const initialSelection =
|
|
486
|
+
shouldNumberOptions && options?.previous
|
|
487
|
+
? {
|
|
488
|
+
...options.previous,
|
|
489
|
+
selectedOptions: options.previous.selectedOptions.map(selected => {
|
|
490
|
+
const rawIndex = rawOptionLabels.indexOf(selected);
|
|
491
|
+
return rawIndex >= 0 ? (optionLabels[rawIndex] ?? selected) : selected;
|
|
492
|
+
}),
|
|
493
|
+
}
|
|
494
|
+
: options?.previous;
|
|
495
|
+
const {
|
|
496
|
+
selectedOptions: displaySelectedOptions,
|
|
497
|
+
customInput,
|
|
498
|
+
navigation,
|
|
499
|
+
cancelled,
|
|
500
|
+
timedOut,
|
|
501
|
+
} = await askSingleQuestion(ui, displayQuestion, optionLabels, q.multi ?? false, {
|
|
502
|
+
recommended: q.recommended,
|
|
503
|
+
timeout: timeout ?? undefined,
|
|
504
|
+
signal,
|
|
505
|
+
initialSelection,
|
|
506
|
+
navigation: options?.navigation,
|
|
507
|
+
scrollTitleRows: deepInterviewPrompt === null ? undefined : DEEP_INTERVIEW_SELECTOR_SCROLL_TITLE_ROWS,
|
|
508
|
+
otherOptionLabel: shouldNumberOptions
|
|
509
|
+
? formatNumberedOptionLabel(OTHER_OPTION, optionLabels.length)
|
|
510
|
+
: undefined,
|
|
511
|
+
});
|
|
512
|
+
const selectedOptions = shouldNumberOptions
|
|
513
|
+
? displaySelectedOptions.map(selected => {
|
|
514
|
+
const displayIndex = optionLabels.indexOf(selected);
|
|
515
|
+
return displayIndex >= 0 ? (rawOptionLabels[displayIndex] ?? selected) : selected;
|
|
516
|
+
})
|
|
517
|
+
: displaySelectedOptions;
|
|
518
|
+
return { optionLabels: rawOptionLabels, selectedOptions, customInput, navigation, cancelled, timedOut };
|
|
471
519
|
} catch (error) {
|
|
472
520
|
if (error instanceof Error && error.name === "AbortError") {
|
|
473
521
|
throw new ToolAbortError("Ask input was cancelled");
|
|
@@ -659,14 +707,17 @@ export const askToolRenderer = {
|
|
|
659
707
|
container.addChild(
|
|
660
708
|
new Text(` ${uiTheme.fg("dim", qBranch)} ${uiTheme.fg("dim", `[${q.id}]`)}${metaStr}`, 0, 0),
|
|
661
709
|
);
|
|
662
|
-
|
|
710
|
+
const deepInterviewQuestion = renderDeepInterviewAskQuestion(q.question, uiTheme);
|
|
711
|
+
container.addChild(deepInterviewQuestion ?? new Markdown(q.question, 3, 0, mdTheme, accentStyle));
|
|
663
712
|
|
|
664
713
|
const qOptions = q.options;
|
|
665
714
|
if (qOptions?.length) {
|
|
666
715
|
const entries = qOptions.map((opt, j) => {
|
|
667
716
|
const isLastOpt = j === qOptions.length - 1;
|
|
668
717
|
const optBranch = isLastOpt ? uiTheme.tree.last : uiTheme.tree.branch;
|
|
669
|
-
const
|
|
718
|
+
const shouldNumberOption = deepInterviewQuestion !== null || isDeepInterviewAskQuestion(q.question);
|
|
719
|
+
const displayLabel = shouldNumberOption ? formatNumberedOptionLabel(opt.label, j) : opt.label;
|
|
720
|
+
const optLabel = renderInlineMarkdown(displayLabel, mdTheme, t => uiTheme.fg("muted", t));
|
|
670
721
|
return {
|
|
671
722
|
prefix: ` ${uiTheme.fg("dim", continuation)} ${uiTheme.fg("dim", optBranch)} ${uiTheme.fg("dim", uiTheme.checkbox.unchecked)} `,
|
|
672
723
|
label: optLabel,
|
|
@@ -682,20 +733,24 @@ export const askToolRenderer = {
|
|
|
682
733
|
if (!args.question) {
|
|
683
734
|
return new Text(formatErrorMessage("No question provided", uiTheme), 0, 0);
|
|
684
735
|
}
|
|
736
|
+
const question = args.question;
|
|
685
737
|
|
|
686
738
|
const container = new Container();
|
|
687
739
|
const meta: string[] = [];
|
|
688
740
|
if (args.multi) meta.push("multi");
|
|
689
741
|
if (args.options?.length) meta.push(`options:${args.options.length}`);
|
|
690
742
|
container.addChild(new Text(`${label}${formatMeta(meta, uiTheme)}`, 0, 0));
|
|
691
|
-
|
|
743
|
+
const deepInterviewQuestion = renderDeepInterviewAskQuestion(question, uiTheme);
|
|
744
|
+
container.addChild(deepInterviewQuestion ?? new Markdown(question, 1, 0, mdTheme, accentStyle));
|
|
692
745
|
|
|
693
746
|
const options = args.options;
|
|
694
747
|
if (options?.length) {
|
|
695
748
|
const entries = options.map((opt, i) => {
|
|
696
749
|
const isLast = i === options.length - 1;
|
|
697
750
|
const branch = isLast ? uiTheme.tree.last : uiTheme.tree.branch;
|
|
698
|
-
const
|
|
751
|
+
const shouldNumberOption = deepInterviewQuestion !== null || isDeepInterviewAskQuestion(question);
|
|
752
|
+
const displayLabel = shouldNumberOption ? formatNumberedOptionLabel(opt.label, i) : opt.label;
|
|
753
|
+
const optLabel = renderInlineMarkdown(displayLabel, mdTheme, t => uiTheme.fg("muted", t));
|
|
699
754
|
return {
|
|
700
755
|
prefix: ` ${uiTheme.fg("dim", branch)} ${uiTheme.fg("dim", uiTheme.checkbox.unchecked)} `,
|
|
701
756
|
label: optLabel,
|
|
@@ -752,7 +807,10 @@ export const askToolRenderer = {
|
|
|
752
807
|
container.addChild(
|
|
753
808
|
new Text(` ${uiTheme.fg("dim", branch)} ${statusIcon} ${uiTheme.fg("dim", `[${r.id}]`)}`, 0, 0),
|
|
754
809
|
);
|
|
755
|
-
container.addChild(
|
|
810
|
+
container.addChild(
|
|
811
|
+
renderDeepInterviewAskQuestion(r.question, uiTheme) ??
|
|
812
|
+
new Markdown(r.question, 3, 0, mdTheme, accentStyle),
|
|
813
|
+
);
|
|
756
814
|
|
|
757
815
|
const answerLines: string[] = [];
|
|
758
816
|
for (let j = 0; j < r.selectedOptions.length; j++) {
|
|
@@ -795,7 +853,10 @@ export const askToolRenderer = {
|
|
|
795
853
|
const header = renderStatusLine({ icon: hasSelection ? "success" : "warning", title: "Ask" }, uiTheme);
|
|
796
854
|
const container = new Container();
|
|
797
855
|
container.addChild(new Text(header, 0, 0));
|
|
798
|
-
container.addChild(
|
|
856
|
+
container.addChild(
|
|
857
|
+
renderDeepInterviewAskQuestion(details.question, uiTheme) ??
|
|
858
|
+
new Markdown(details.question, 1, 0, mdTheme, accentStyle),
|
|
859
|
+
);
|
|
799
860
|
|
|
800
861
|
const answerLines: string[] = [];
|
|
801
862
|
if (details.selectedOptions && details.selectedOptions.length > 0) {
|
package/src/tools/ast-edit.ts
CHANGED
|
@@ -204,6 +204,7 @@ export class AstEditTool implements AgentTool<typeof astEditSchema, AstEditToolD
|
|
|
204
204
|
const scope = await resolveToolSearchScope({
|
|
205
205
|
rawPaths: params.paths,
|
|
206
206
|
cwd: this.session.cwd,
|
|
207
|
+
getArtifactsDir: this.session.getArtifactsDir,
|
|
207
208
|
internalUrlAction: "rewrite",
|
|
208
209
|
});
|
|
209
210
|
const { searchPath: resolvedSearchPath, scopePath, isDirectory, multiTargets, globFilter } = scope;
|
package/src/tools/ast-grep.ts
CHANGED
|
@@ -151,6 +151,7 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
151
151
|
const scope = await resolveToolSearchScope({
|
|
152
152
|
rawPaths: params.paths,
|
|
153
153
|
cwd: this.session.cwd,
|
|
154
|
+
getArtifactsDir: this.session.getArtifactsDir,
|
|
154
155
|
internalUrlAction: "search",
|
|
155
156
|
});
|
|
156
157
|
const { searchPath: resolvedSearchPath, scopePath, isDirectory, multiTargets, globFilter } = scope;
|
package/src/tools/bash.ts
CHANGED
|
@@ -693,7 +693,7 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
693
693
|
throw error instanceof Error ? error : new Error(String(error));
|
|
694
694
|
}
|
|
695
695
|
},
|
|
696
|
-
{ ownerId },
|
|
696
|
+
{ ownerId, metadata: { monitor: true } },
|
|
697
697
|
);
|
|
698
698
|
currentJobId = jobId;
|
|
699
699
|
return { jobId, label, commandCwd: prepared.commandCwd };
|