@gajae-code/coding-agent 0.4.4 → 0.4.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 +40 -0
- package/dist/types/cli/fast-help.d.ts +1 -0
- package/dist/types/cli/setup-cli.d.ts +2 -0
- package/dist/types/commands/harness.d.ts +3 -0
- package/dist/types/commands/setup.d.ts +6 -0
- package/dist/types/config/model-registry.d.ts +3 -0
- package/dist/types/config/models-config-schema.d.ts +5 -0
- package/dist/types/coordinator/contract.d.ts +1 -1
- package/dist/types/coordinator-mcp/server.d.ts +8 -2
- package/dist/types/harness-control-plane/finalize.d.ts +5 -0
- package/dist/types/harness-control-plane/phase-rollup.d.ts +23 -0
- package/dist/types/harness-control-plane/receipt-ingest.d.ts +19 -0
- package/dist/types/harness-control-plane/receipts.d.ts +46 -0
- package/dist/types/harness-control-plane/rpc-adapter.d.ts +3 -0
- package/dist/types/harness-control-plane/types.d.ts +9 -1
- package/dist/types/main.d.ts +2 -2
- package/dist/types/modes/utils/abort-message.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +8 -0
- package/dist/types/setup/hermes-setup.d.ts +7 -0
- package/dist/types/task/fork-context-advisory.d.ts +13 -0
- package/dist/types/task/receipt.d.ts +1 -0
- package/dist/types/task/roi-reconciliation.d.ts +27 -0
- package/dist/types/task/types.d.ts +10 -0
- package/package.json +8 -7
- package/scripts/build-binary.ts +4 -0
- package/src/cli/fast-help.ts +80 -0
- package/src/cli/setup-cli.ts +12 -3
- package/src/cli.ts +107 -16
- package/src/commands/coordinator.ts +44 -1
- package/src/commands/harness.ts +92 -9
- package/src/commands/mcp-serve.ts +3 -2
- package/src/commands/setup.ts +4 -0
- package/src/config/models-config-schema.ts +1 -0
- package/src/coordinator/contract.ts +1 -0
- package/src/coordinator-mcp/server.ts +385 -182
- package/src/cursor.ts +30 -2
- package/src/gjc-runtime/launch-worktree.ts +12 -1
- package/src/gjc-runtime/session-state-sidecar.ts +38 -0
- package/src/harness-control-plane/finalize.ts +39 -5
- package/src/harness-control-plane/owner.ts +9 -1
- package/src/harness-control-plane/phase-rollup.ts +96 -0
- package/src/harness-control-plane/receipt-ingest.ts +127 -0
- package/src/harness-control-plane/receipts.ts +229 -1
- package/src/harness-control-plane/rpc-adapter.ts +8 -0
- package/src/harness-control-plane/types.ts +29 -1
- package/src/internal-urls/docs-index.generated.ts +6 -5
- package/src/main.ts +7 -3
- package/src/modes/components/status-line.ts +6 -6
- package/src/modes/controllers/event-controller.ts +5 -4
- package/src/modes/interactive-mode.ts +4 -5
- package/src/modes/print-mode.ts +1 -1
- package/src/modes/theme/theme.ts +2 -2
- package/src/modes/utils/abort-message.ts +41 -0
- package/src/modes/utils/context-usage.ts +15 -8
- package/src/modes/utils/ui-helpers.ts +5 -6
- package/src/sdk.ts +9 -4
- package/src/session/agent-session.ts +16 -5
- package/src/session/session-manager.ts +20 -0
- package/src/setup/hermes/templates/operator-instructions.v1.md +3 -2
- package/src/setup/hermes-setup.ts +63 -8
- package/src/task/fork-context-advisory.ts +99 -0
- package/src/task/index.ts +31 -2
- package/src/task/receipt.ts +2 -0
- package/src/task/roi-reconciliation.ts +90 -0
- package/src/task/types.ts +7 -0
- package/src/tools/index.ts +2 -2
- package/src/tools/subagent-render.ts +10 -1
- package/src/utils/title-generator.ts +16 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.4.5] - 2026-06-12
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added a dim `(ctrl+s to observe sessions)` discoverability hint under the `subagent` await panel header while any awaited subagent is still running, pointing to the full session observer overlay; the hint shows in both collapsed and expanded states and disappears once no subagent is running.
|
|
10
|
+
- Added a `phase-rollup` receipt family (receipt-of-receipts) to the harness control plane: a hash-sealed rollup that supersedes N child task receipts at a lifecycle boundary, preserving per-child `{id, status, outputUri, outputSha256, receiptSha256, tokens, costTotal, clonedTokens, lowRoi}` pointers plus aggregate ROI totals, with a pure deterministic builder (`buildPhaseRollupReceipt`) and fail-closed semantic validation.
|
|
11
|
+
- Added a pure receipt-ingestion fast path (`ingestReceipts`): fail-closed batch validation + lifecycle transition computation via the existing state machine, plus a deterministic model-facing digest hard-capped at 280 chars — groundwork for LLM-free receipt routing.
|
|
12
|
+
- Added advisory spawn-ROI reconciliation (`reconcileSpawnRoi`) and deterministic fork-context mode advice (`adviseForkContextMode`) surfaced in task receipts without changing task success semantics.
|
|
13
|
+
- Added the Grok Build provider contract design document.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Reduced compiled CLI startup and native bundle pressure with default-small grammar loading, tokenizer tiering, and compiled fast-help paths.
|
|
18
|
+
- Preserved dev/main release metadata and changelog consistency for the 0.4.5 lockstep release.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- Kept the unified `goal` tool registered and active by default whenever `goal.enabled` is true, including explicit tool subsets and `gjc ultragoal create-goals` arming flows.
|
|
23
|
+
- Restored no-argument `gjc` interactive startup instead of launching help.
|
|
24
|
+
- Rendered and executed Cursor-native tool calls, including detached/native handler paths and empty-pattern composer grep guards.
|
|
25
|
+
- Tool-output pruning no longer rewrites already-sent provider-facing history mid prompt-cache epoch and now persists pruned message updates back into canonical session storage.
|
|
26
|
+
- Preserved provider abort root causes in the final TUI abort label, kept replay rendering idempotent, and added a `PI_STREAM_IDLE_TIMEOUT_MS` remediation hint when stream idle watchdogs fire.
|
|
27
|
+
- Hardened harness owner recovery/finalize paths and submit-prompt-file handling.
|
|
28
|
+
|
|
29
|
+
## [0.4.4] - 2026-06-10
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- Made coordinator turns event-backed, adding an MCP coordinator server and the `gjc coordinator` / `gjc mcp-serve` commands backed by durable turn/session state (#479).
|
|
34
|
+
- Surfaced awaited sub-agent live streaming status in the await panel (#475).
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- Refreshed the README brand images (#477).
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- Persisted ralplan role-agent artifacts via the CLI, returning receipt-only output to the caller (#474).
|
|
43
|
+
- Collected the `ask` tool "Other" custom input inline below the option list (#476).
|
|
44
|
+
|
|
5
45
|
## [0.4.3] - 2026-06-10
|
|
6
46
|
|
|
7
47
|
### Added
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getExtraHelpText(): string;
|
|
@@ -14,6 +14,9 @@ export default class Harness extends Command {
|
|
|
14
14
|
description: string;
|
|
15
15
|
default: string;
|
|
16
16
|
};
|
|
17
|
+
"prompt-file": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
18
|
+
description: string;
|
|
19
|
+
};
|
|
17
20
|
session: import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
18
21
|
char: string;
|
|
19
22
|
description: string;
|
|
@@ -43,6 +43,12 @@ export default class Setup extends Command {
|
|
|
43
43
|
"session-command": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
44
44
|
description: string;
|
|
45
45
|
};
|
|
46
|
+
"no-worktree": import("@gajae-code/utils/cli").FlagDescriptor<"boolean"> & {
|
|
47
|
+
description: string;
|
|
48
|
+
};
|
|
49
|
+
"worktree-name": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
50
|
+
description: string;
|
|
51
|
+
};
|
|
46
52
|
"state-root": import("@gajae-code/utils/cli").FlagDescriptor<"string"> & {
|
|
47
53
|
description: string;
|
|
48
54
|
};
|
|
@@ -70,6 +70,7 @@ export declare const ModelsConfigFile: ConfigFile<{
|
|
|
70
70
|
allowsSyntheticReasoningContentForToolCalls?: boolean | undefined;
|
|
71
71
|
requiresAssistantContentForToolCalls?: boolean | undefined;
|
|
72
72
|
supportsToolChoice?: boolean | undefined;
|
|
73
|
+
supportsForcedToolChoice?: boolean | undefined;
|
|
73
74
|
disableReasoningOnForcedToolChoice?: boolean | undefined;
|
|
74
75
|
disableReasoningOnToolChoice?: boolean | undefined;
|
|
75
76
|
thinkingFormat?: "openai" | "openrouter" | "qwen" | "qwen-chat-template" | "zai" | undefined;
|
|
@@ -145,6 +146,7 @@ export declare const ModelsConfigFile: ConfigFile<{
|
|
|
145
146
|
allowsSyntheticReasoningContentForToolCalls?: boolean | undefined;
|
|
146
147
|
requiresAssistantContentForToolCalls?: boolean | undefined;
|
|
147
148
|
supportsToolChoice?: boolean | undefined;
|
|
149
|
+
supportsForcedToolChoice?: boolean | undefined;
|
|
148
150
|
disableReasoningOnForcedToolChoice?: boolean | undefined;
|
|
149
151
|
disableReasoningOnToolChoice?: boolean | undefined;
|
|
150
152
|
thinkingFormat?: "openai" | "openrouter" | "qwen" | "qwen-chat-template" | "zai" | undefined;
|
|
@@ -216,6 +218,7 @@ export declare const ModelsConfigFile: ConfigFile<{
|
|
|
216
218
|
allowsSyntheticReasoningContentForToolCalls?: boolean | undefined;
|
|
217
219
|
requiresAssistantContentForToolCalls?: boolean | undefined;
|
|
218
220
|
supportsToolChoice?: boolean | undefined;
|
|
221
|
+
supportsForcedToolChoice?: boolean | undefined;
|
|
219
222
|
disableReasoningOnForcedToolChoice?: boolean | undefined;
|
|
220
223
|
disableReasoningOnToolChoice?: boolean | undefined;
|
|
221
224
|
thinkingFormat?: "openai" | "openrouter" | "qwen" | "qwen-chat-template" | "zai" | undefined;
|
|
@@ -30,6 +30,7 @@ export declare const OpenAICompatSchema: z.ZodObject<{
|
|
|
30
30
|
allowsSyntheticReasoningContentForToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
31
31
|
requiresAssistantContentForToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
32
32
|
supportsToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
33
|
+
supportsForcedToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
33
34
|
disableReasoningOnForcedToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
34
35
|
disableReasoningOnToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
35
36
|
thinkingFormat: z.ZodOptional<z.ZodEnum<{
|
|
@@ -182,6 +183,7 @@ export declare const ModelOverrideSchema: z.ZodObject<{
|
|
|
182
183
|
allowsSyntheticReasoningContentForToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
183
184
|
requiresAssistantContentForToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
184
185
|
supportsToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
186
|
+
supportsForcedToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
185
187
|
disableReasoningOnForcedToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
186
188
|
disableReasoningOnToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
187
189
|
thinkingFormat: z.ZodOptional<z.ZodEnum<{
|
|
@@ -288,6 +290,7 @@ export declare const ModelsConfigSchema: z.ZodObject<{
|
|
|
288
290
|
allowsSyntheticReasoningContentForToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
289
291
|
requiresAssistantContentForToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
290
292
|
supportsToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
293
|
+
supportsForcedToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
291
294
|
disableReasoningOnForcedToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
292
295
|
disableReasoningOnToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
293
296
|
thinkingFormat: z.ZodOptional<z.ZodEnum<{
|
|
@@ -442,6 +445,7 @@ export declare const ModelsConfigSchema: z.ZodObject<{
|
|
|
442
445
|
allowsSyntheticReasoningContentForToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
443
446
|
requiresAssistantContentForToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
444
447
|
supportsToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
448
|
+
supportsForcedToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
445
449
|
disableReasoningOnForcedToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
446
450
|
disableReasoningOnToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
447
451
|
thinkingFormat: z.ZodOptional<z.ZodEnum<{
|
|
@@ -575,6 +579,7 @@ export declare const ModelsConfigSchema: z.ZodObject<{
|
|
|
575
579
|
allowsSyntheticReasoningContentForToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
576
580
|
requiresAssistantContentForToolCalls: z.ZodOptional<z.ZodBoolean>;
|
|
577
581
|
supportsToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
582
|
+
supportsForcedToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
578
583
|
disableReasoningOnForcedToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
579
584
|
disableReasoningOnToolChoice: z.ZodOptional<z.ZodBoolean>;
|
|
580
585
|
thinkingFormat: z.ZodOptional<z.ZodEnum<{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const COORDINATOR_MCP_PROTOCOL_VERSION = "2024-11-05";
|
|
2
2
|
export declare const COORDINATOR_MCP_SERVER_NAME = "gjc-coordinator-mcp";
|
|
3
|
-
export declare const COORDINATOR_MCP_TOOL_NAMES: readonly ["gjc_coordinator_list_sessions", "gjc_coordinator_read_status", "gjc_coordinator_read_tail", "gjc_coordinator_list_questions", "gjc_coordinator_list_artifacts", "gjc_coordinator_read_artifact", "gjc_coordinator_read_coordination_status", "gjc_coordinator_start_session", "gjc_coordinator_send_prompt", "gjc_coordinator_submit_question_answer", "gjc_coordinator_read_turn", "gjc_coordinator_await_turn", "gjc_coordinator_report_status"];
|
|
3
|
+
export declare const COORDINATOR_MCP_TOOL_NAMES: readonly ["gjc_coordinator_list_sessions", "gjc_coordinator_read_status", "gjc_coordinator_read_tail", "gjc_coordinator_list_questions", "gjc_coordinator_list_artifacts", "gjc_coordinator_read_artifact", "gjc_coordinator_read_coordination_status", "gjc_coordinator_register_session", "gjc_coordinator_start_session", "gjc_coordinator_send_prompt", "gjc_coordinator_submit_question_answer", "gjc_coordinator_read_turn", "gjc_coordinator_await_turn", "gjc_coordinator_report_status"];
|
|
4
4
|
export type CoordinatorToolName = (typeof COORDINATOR_MCP_TOOL_NAMES)[number];
|
|
@@ -8,10 +8,11 @@ interface JsonRpcRequest {
|
|
|
8
8
|
method: string;
|
|
9
9
|
params?: unknown;
|
|
10
10
|
}
|
|
11
|
+
type JsonRpcResult = any;
|
|
11
12
|
interface JsonRpcResponse {
|
|
12
13
|
jsonrpc: "2.0";
|
|
13
14
|
id: string | number | null;
|
|
14
|
-
result?:
|
|
15
|
+
result?: JsonRpcResult;
|
|
15
16
|
error?: {
|
|
16
17
|
code: number;
|
|
17
18
|
message: string;
|
|
@@ -30,6 +31,11 @@ interface SessionStartInput {
|
|
|
30
31
|
interface CoordinatorServices {
|
|
31
32
|
listSessions?: () => unknown[] | Promise<unknown[]>;
|
|
32
33
|
startSession?: (input: SessionStartInput) => unknown | Promise<unknown>;
|
|
34
|
+
commandRunner?: (command: string[]) => Promise<{
|
|
35
|
+
exitCode: number;
|
|
36
|
+
stdout: string;
|
|
37
|
+
stderr: string;
|
|
38
|
+
}>;
|
|
33
39
|
}
|
|
34
40
|
interface CoordinatorMcpServerOptions {
|
|
35
41
|
env?: NodeJS.ProcessEnv;
|
|
@@ -48,5 +54,5 @@ export declare function createCoordinatorMcpServer(options?: CoordinatorMcpServe
|
|
|
48
54
|
handleJsonRpc: (request: JsonRpcRequest) => Promise<JsonRpcResponse>;
|
|
49
55
|
handle: (request: JsonRpcRequest) => Promise<JsonRpcResponse>;
|
|
50
56
|
};
|
|
51
|
-
export declare function handleCoordinatorMcpRequest(request: JsonRpcRequest, options?: LegacyHandlerOptions): Promise<
|
|
57
|
+
export declare function handleCoordinatorMcpRequest(request: JsonRpcRequest, options?: LegacyHandlerOptions): Promise<JsonRpcResponse>;
|
|
52
58
|
export declare function runCoordinatorMcpStdio(options?: CoordinatorMcpServerOptions): Promise<void>;
|
|
@@ -30,6 +30,11 @@ export interface FinalizeOptions {
|
|
|
30
30
|
reviewOnly?: boolean;
|
|
31
31
|
/** Operator/loop-supplied terminal review verdict (closed vocabulary). */
|
|
32
32
|
verdict?: string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Final assistant text from the live RPC owner, used to extract a closed-vocabulary verdict
|
|
35
|
+
* for review-only sessions when no explicit {@link verdict} is supplied. Never persisted raw.
|
|
36
|
+
*/
|
|
37
|
+
assistantText?: string | null;
|
|
33
38
|
/** Bounded PR/issue reference for the review target (e.g. "PR-414"). Never resolved from the live repo. */
|
|
34
39
|
prTarget?: string | null;
|
|
35
40
|
validationCommands?: ValidationCommandSpec[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase-boundary receipt rollup builder (receipt-of-receipts).
|
|
3
|
+
*
|
|
4
|
+
* At a harness lifecycle boundary, N child task receipts can be superseded by a
|
|
5
|
+
* single `phase-rollup` receipt that preserves per-child pointers (id, status,
|
|
6
|
+
* outputRef, sha256) plus aggregate ROI totals. The rollup is hash-sealed via
|
|
7
|
+
* the standard receipt envelope and validated fail-closed like every other
|
|
8
|
+
* family (see `validatePhaseRollup` in receipts.ts). Pure builder — no runtime
|
|
9
|
+
* injection behavior is changed here.
|
|
10
|
+
*/
|
|
11
|
+
import type { TaskResultReceipt } from "../task/receipt";
|
|
12
|
+
import { type BuildReceiptInput, type PhaseRollupEvidence, type ReceiptEnvelope } from "./receipts";
|
|
13
|
+
export interface BuildPhaseRollupInput {
|
|
14
|
+
receiptId: string;
|
|
15
|
+
sessionId: string;
|
|
16
|
+
source: string;
|
|
17
|
+
subject: BuildReceiptInput<PhaseRollupEvidence>["subject"];
|
|
18
|
+
phase: string;
|
|
19
|
+
children: readonly TaskResultReceipt[];
|
|
20
|
+
/** Supply for deterministic output; defaults to now. */
|
|
21
|
+
createdAt?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function buildPhaseRollupReceipt(input: BuildPhaseRollupInput): ReceiptEnvelope<PhaseRollupEvidence>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ReceiptEnvelope } from "./receipts";
|
|
2
|
+
import type { HarnessLifecycle, ReceiptFamily, SessionState } from "./types";
|
|
3
|
+
export declare const RECEIPT_DIGEST_MAX_CHARS = 280;
|
|
4
|
+
export declare const RECEIPT_FAMILY_LIFECYCLE_TARGETS: Partial<Record<ReceiptFamily, HarnessLifecycle>>;
|
|
5
|
+
export interface ReceiptIngestResult {
|
|
6
|
+
accepted: ReceiptEnvelope<unknown>[];
|
|
7
|
+
rejected: {
|
|
8
|
+
receipt: ReceiptEnvelope<unknown>;
|
|
9
|
+
reasons: string[];
|
|
10
|
+
}[];
|
|
11
|
+
transitions: {
|
|
12
|
+
from: HarnessLifecycle;
|
|
13
|
+
to: HarnessLifecycle;
|
|
14
|
+
receiptId: string;
|
|
15
|
+
}[];
|
|
16
|
+
finalLifecycle: HarnessLifecycle;
|
|
17
|
+
digest: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function ingestReceipts(state: SessionState, receipts: readonly ReceiptEnvelope<unknown>[]): ReceiptIngestResult;
|
|
@@ -20,6 +20,8 @@ export interface ReceiptEnvelope<E = Record<string, unknown>> {
|
|
|
20
20
|
sha256: string;
|
|
21
21
|
}
|
|
22
22
|
export declare const RECEIPT_SCHEMA_VERSION: 1;
|
|
23
|
+
/** Deterministic stringify with sorted keys (stable hash basis). */
|
|
24
|
+
export declare function canonicalJson(value: unknown): string;
|
|
23
25
|
export declare function sha256Hex(input: string): string;
|
|
24
26
|
export interface BuildReceiptInput<E> {
|
|
25
27
|
receiptId: string;
|
|
@@ -90,6 +92,10 @@ export interface ReviewVerdictEvidence {
|
|
|
90
92
|
finalizedAt: string;
|
|
91
93
|
/** Bounded summary code/reference for the verdict; never raw assistant text. */
|
|
92
94
|
summaryRef: string | null;
|
|
95
|
+
/** Where the verdict came from: explicit operator input or extracted from final assistant text. */
|
|
96
|
+
verdictSource?: "input" | "assistant";
|
|
97
|
+
/** sha256 of the assistant text the verdict was extracted from, when sourced from the agent. */
|
|
98
|
+
assistantDigest?: string | null;
|
|
93
99
|
}
|
|
94
100
|
export interface ReviewFailureEvidence {
|
|
95
101
|
/** Machine-actionable reason the review produced no terminal verdict. */
|
|
@@ -98,6 +104,46 @@ export interface ReviewFailureEvidence {
|
|
|
98
104
|
failedAt: string;
|
|
99
105
|
/** Routing hint for the operator/fallback path. */
|
|
100
106
|
fallback: string;
|
|
107
|
+
/** sha256 of the assistant text examined for a verdict, when one was available. */
|
|
108
|
+
assistantDigest?: string | null;
|
|
109
|
+
/** Bounded, whitespace-collapsed assistant summary (never an unbounded transcript dump). */
|
|
110
|
+
assistantSummary?: string | null;
|
|
101
111
|
}
|
|
112
|
+
/** Pointer back to one superseded child task receipt. */
|
|
113
|
+
export interface PhaseRollupChildPointer {
|
|
114
|
+
id: string;
|
|
115
|
+
status: "completed" | "failed" | "aborted" | "merge_failed" | "paused";
|
|
116
|
+
/** Artifact URI holding the child's full output, when available. */
|
|
117
|
+
outputUri: string | null;
|
|
118
|
+
/** Content hash of the child's output artifact, when available. */
|
|
119
|
+
outputSha256: string | null;
|
|
120
|
+
/** Hash of the child receipt itself (canonical JSON), for staleness checks. */
|
|
121
|
+
receiptSha256: string;
|
|
122
|
+
/**
|
|
123
|
+
* Per-child ROI accounting carried into the rollup so the aggregate totals
|
|
124
|
+
* below are recomputable/verifiable from child evidence (not self-reported).
|
|
125
|
+
* `tokens` is the child's effective token count; cost/cloned are null when
|
|
126
|
+
* the child reported no such accounting.
|
|
127
|
+
*/
|
|
128
|
+
tokens: number;
|
|
129
|
+
costTotal: number | null;
|
|
130
|
+
clonedTokens: number | null;
|
|
131
|
+
lowRoi: boolean;
|
|
132
|
+
}
|
|
133
|
+
export interface PhaseRollupEvidence {
|
|
134
|
+
/** Harness lifecycle boundary this rollup was emitted at. */
|
|
135
|
+
phase: string;
|
|
136
|
+
children: PhaseRollupChildPointer[];
|
|
137
|
+
aggregate: {
|
|
138
|
+
childCount: number;
|
|
139
|
+
completed: number;
|
|
140
|
+
failed: number;
|
|
141
|
+
totalTokens: number;
|
|
142
|
+
totalCostTotal: number | null;
|
|
143
|
+
totalClonedTokens: number | null;
|
|
144
|
+
lowRoiChildIds: string[];
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
export declare function validatePhaseRollup(e: PhaseRollupEvidence): string[];
|
|
102
148
|
/** Classifications that MUST have a valid `vanish` receipt before the action proceeds. */
|
|
103
149
|
export declare function requiresVanishBeforeAction(classification: RecoveryClassification): boolean;
|
|
@@ -24,6 +24,8 @@ export interface HarnessRpc {
|
|
|
24
24
|
isLive?(): boolean;
|
|
25
25
|
/** ISO timestamp of the last observed event frame, or null. */
|
|
26
26
|
lastFrameAt?(): string | null;
|
|
27
|
+
/** Final assistant text from the live session (for review-verdict extraction); null when unavailable. */
|
|
28
|
+
getLastAssistantText?(): Promise<string | null>;
|
|
27
29
|
}
|
|
28
30
|
export interface AcceptanceResult {
|
|
29
31
|
accepted: boolean;
|
|
@@ -54,6 +56,7 @@ export declare class GajaeCodeRpc implements HarnessRpc {
|
|
|
54
56
|
isLive(): boolean;
|
|
55
57
|
lastFrameAt(): string | null;
|
|
56
58
|
getState(): Promise<RpcStateSnapshot>;
|
|
59
|
+
getLastAssistantText(): Promise<string | null>;
|
|
57
60
|
sendPrompt(prompt: string): Promise<{
|
|
58
61
|
commandId: string;
|
|
59
62
|
ack: boolean;
|
|
@@ -16,6 +16,14 @@ export type SessionMode = "implement" | "review";
|
|
|
16
16
|
export type ReviewVerdict = "APPROVE_MERGE_READY" | "REQUEST_CHANGES" | "OWNER_CONFIRMATION_REQUIRED";
|
|
17
17
|
export declare const REVIEW_VERDICTS: readonly ReviewVerdict[];
|
|
18
18
|
export declare function isReviewVerdict(value: unknown): value is ReviewVerdict;
|
|
19
|
+
/**
|
|
20
|
+
* Extract a single closed-vocabulary review verdict from free-form assistant text.
|
|
21
|
+
*
|
|
22
|
+
* Scans for canonical verdict tokens (and accepted aliases) as whole words and returns the
|
|
23
|
+
* LAST occurrence — the agent's final stated decision wins over any earlier mention. Returns
|
|
24
|
+
* null when no allowed token is present, so the finalizer fails closed on a missing verdict.
|
|
25
|
+
*/
|
|
26
|
+
export declare function extractReviewVerdict(text: string | null | undefined): ReviewVerdict | null;
|
|
19
27
|
/** Lifecycle states of an operated session. */
|
|
20
28
|
export type HarnessLifecycle = "new" | "started" | "submitted" | "observing" | "recovering" | "validating" | "finalizing" | "completed" | "blocked" | "retired";
|
|
21
29
|
/** Event severities emitted by the owner. */
|
|
@@ -27,7 +35,7 @@ export type RiskKind = "normal" | "prompt-not-accepted" | "deleted-worktree" | "
|
|
|
27
35
|
/** Deterministic recovery classifications. */
|
|
28
36
|
export type RecoveryClassification = "continue" | "send-enter" | "reinject-prompt" | "restart-clean" | "restart-preserve-delta" | "fallback-codex-exec" | "human-check";
|
|
29
37
|
/** Receipt families persisted under the session storage dir. */
|
|
30
|
-
export type ReceiptFamily = "vanish" | "prompt-acceptance" | "validation" | "completion" | "review-verdict" | "review-failure";
|
|
38
|
+
export type ReceiptFamily = "vanish" | "prompt-acceptance" | "validation" | "completion" | "review-verdict" | "review-failure" | "phase-rollup";
|
|
31
39
|
/** The CLI verbs / primitives exposed by `gjc harness <verb>`. */
|
|
32
40
|
export type HarnessVerb = "start" | "submit" | "observe" | "classify" | "recover" | "validate" | "finalize" | "retire" | "events" | "monitor" | "operate";
|
|
33
41
|
/** Submission transports. */
|
package/dist/types/main.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import type { Args } from "./cli/args";
|
|
8
8
|
import { ModelRegistry } from "./config/model-registry";
|
|
9
9
|
import { Settings } from "./config/settings";
|
|
10
|
-
import { InteractiveMode
|
|
10
|
+
import type { InteractiveMode } from "./modes/interactive-mode";
|
|
11
11
|
import type { SubmittedUserInput } from "./modes/types";
|
|
12
12
|
import { type CreateAgentSessionOptions, type CreateAgentSessionResult, createAgentSession, discoverAuthStorage } from "./sdk";
|
|
13
13
|
import type { AgentSession } from "./session/agent-session";
|
|
@@ -51,7 +51,7 @@ export declare function createAcpSessionFactory(args: AcpSessionFactoryOptions):
|
|
|
51
51
|
interface RunRootCommandDependencies {
|
|
52
52
|
createAgentSession?: typeof createAgentSession;
|
|
53
53
|
discoverAuthStorage?: typeof discoverAuthStorage;
|
|
54
|
-
runAcpMode?:
|
|
54
|
+
runAcpMode?: (createSession: AcpSessionFactory) => Promise<void>;
|
|
55
55
|
settings?: Settings;
|
|
56
56
|
}
|
|
57
57
|
export declare function runRootCommand(parsed: Args, rawArgs: string[], deps?: RunRootCommandDependencies): Promise<void>;
|
|
@@ -401,6 +401,14 @@ export declare class SessionManager {
|
|
|
401
401
|
appendCompaction<T = unknown>(summary: string, shortSummary: string | undefined, firstKeptEntryId: string, tokensBefore: number, details?: T, fromExtension?: boolean, preserveData?: Record<string, unknown>): string;
|
|
402
402
|
/** Append a custom entry (for extensions) as child of current leaf, then advance leaf. Returns entry id. */
|
|
403
403
|
appendCustomEntry(customType: string, data?: unknown): string;
|
|
404
|
+
/**
|
|
405
|
+
* Write mutated message entries back into the canonical entry store by id.
|
|
406
|
+
*
|
|
407
|
+
* `getBranch()` materializes resident-blob entries into copies, so in-place
|
|
408
|
+
* mutation of returned entries (e.g. pruning tool outputs) does not affect
|
|
409
|
+
* the canonical store. This applies such mutations for real.
|
|
410
|
+
*/
|
|
411
|
+
applyEntryMessageUpdates(entries: readonly SessionMessageEntry[]): void;
|
|
404
412
|
/**
|
|
405
413
|
* Rewrite the session file after in-place entry updates.
|
|
406
414
|
* Use sparingly (e.g., pruning old tool outputs).
|
|
@@ -11,6 +11,8 @@ export interface HermesSetupFlags {
|
|
|
11
11
|
repo?: string;
|
|
12
12
|
profile?: string;
|
|
13
13
|
sessionCommand?: string;
|
|
14
|
+
noWorktree?: boolean;
|
|
15
|
+
worktreeName?: string;
|
|
14
16
|
stateRoot?: string;
|
|
15
17
|
mutation?: string[];
|
|
16
18
|
artifactByteCap?: string;
|
|
@@ -33,6 +35,11 @@ export interface CoordinatorSetupSpec {
|
|
|
33
35
|
repo?: string;
|
|
34
36
|
};
|
|
35
37
|
sessionCommand?: string;
|
|
38
|
+
sessionCommandSource: "default" | "explicit";
|
|
39
|
+
worktree: {
|
|
40
|
+
enabled: boolean;
|
|
41
|
+
name?: string;
|
|
42
|
+
};
|
|
36
43
|
stateRoot?: string;
|
|
37
44
|
mutationPolicy: {
|
|
38
45
|
classes: HermesMutationClass[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ForkContextMode } from "./types";
|
|
2
|
+
export interface ForkContextAdvisory {
|
|
3
|
+
recommendedMode: ForkContextMode;
|
|
4
|
+
reasons: string[];
|
|
5
|
+
estimatedClonedTokens: Record<ForkContextMode, number>;
|
|
6
|
+
callerModeRespected: true;
|
|
7
|
+
}
|
|
8
|
+
export declare function adviseForkContextMode(input: {
|
|
9
|
+
assignment: string;
|
|
10
|
+
context?: string;
|
|
11
|
+
explicitMode?: ForkContextMode;
|
|
12
|
+
parentContextTokens?: number;
|
|
13
|
+
}): ForkContextAdvisory;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { TaskResultReceipt } from "./receipt";
|
|
2
|
+
import type { SpawnPlanReceipt } from "./spawn-gate";
|
|
3
|
+
/**
|
|
4
|
+
* Pure, advisory-only reconciliation between a spawn plan's inline-token promise
|
|
5
|
+
* and receipt-safe child outputs. These signals never change task success/failure
|
|
6
|
+
* semantics or runtime behavior; they only describe budget/ROI observations for
|
|
7
|
+
* model-facing summaries.
|
|
8
|
+
*/
|
|
9
|
+
export interface SpawnRoiChildReconciliation {
|
|
10
|
+
id: string;
|
|
11
|
+
inlineTokens: number;
|
|
12
|
+
maxInlineTokens: number;
|
|
13
|
+
overBudget: boolean;
|
|
14
|
+
overageTokens: number;
|
|
15
|
+
lowRoi: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface SpawnRoiReconciliation {
|
|
18
|
+
childCount: number;
|
|
19
|
+
promisedMaxInlineTokens: number;
|
|
20
|
+
children: SpawnRoiChildReconciliation[];
|
|
21
|
+
overBudgetChildIds: string[];
|
|
22
|
+
lowRoiChildIds: string[];
|
|
23
|
+
totalInlineTokens: number;
|
|
24
|
+
totalOverageTokens: number;
|
|
25
|
+
advisoryFlags: string[];
|
|
26
|
+
}
|
|
27
|
+
export declare function reconcileSpawnRoi(plan: SpawnPlanReceipt | undefined, receipts: readonly TaskResultReceipt[]): SpawnRoiReconciliation | undefined;
|
|
@@ -2,6 +2,7 @@ import type { ThinkingLevel } from "@gajae-code/agent-core";
|
|
|
2
2
|
import type { Usage } from "@gajae-code/ai";
|
|
3
3
|
import * as z from "zod/v4";
|
|
4
4
|
import type { TaskResultReceipt } from "./receipt";
|
|
5
|
+
import type { SpawnRoiReconciliation } from "./roi-reconciliation";
|
|
5
6
|
import { type TaskSimpleMode } from "./simple-mode";
|
|
6
7
|
import type { SpawnPlanReceipt } from "./spawn-gate";
|
|
7
8
|
import type { NestedRepoPatch } from "./worktree";
|
|
@@ -413,6 +414,14 @@ export interface SingleResult {
|
|
|
413
414
|
mode: ForkContextMode;
|
|
414
415
|
clonedTokens: number;
|
|
415
416
|
};
|
|
417
|
+
/**
|
|
418
|
+
* Advisory fork-context mode recommendation for this task (logged only;
|
|
419
|
+
* never changes the actual mode selection).
|
|
420
|
+
*/
|
|
421
|
+
forkContextAdvisory?: {
|
|
422
|
+
recommendedMode: ForkContextMode;
|
|
423
|
+
reasons: string[];
|
|
424
|
+
};
|
|
416
425
|
}
|
|
417
426
|
/** Tool details for TUI rendering */
|
|
418
427
|
export interface TaskToolDetails {
|
|
@@ -431,6 +440,7 @@ export interface TaskToolDetails {
|
|
|
431
440
|
/** Advisory ids for terminal children that spent tokens without detectable output/review/changes. */
|
|
432
441
|
lowRoiChildIds: string[];
|
|
433
442
|
};
|
|
443
|
+
roiReconciliation?: SpawnRoiReconciliation;
|
|
434
444
|
progress?: AgentProgress[];
|
|
435
445
|
async?: {
|
|
436
446
|
state: "running" | "paused" | "queued" | "completed" | "failed";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/coding-agent",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.5",
|
|
5
5
|
"description": "Gajae Code CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://gaebal-gajae.dev",
|
|
7
7
|
"author": "Yeachan-Heo",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"check:types": "tsgo -p tsconfig.json --noEmit",
|
|
37
37
|
"lint": "biome lint .",
|
|
38
38
|
"test": "bun test",
|
|
39
|
+
"bench:context": "bun run bench/context-optimization.bench.ts",
|
|
39
40
|
"generate-schemas": "bun ../../scripts/generate-json-schemas.ts",
|
|
40
41
|
"check:schemas": "bun ../../scripts/generate-json-schemas.ts --check",
|
|
41
42
|
"fix": "biome check --write --unsafe . && bun run format-prompts && bun run generate-docs-index",
|
|
@@ -50,12 +51,12 @@
|
|
|
50
51
|
"@agentclientprotocol/sdk": "0.21.0",
|
|
51
52
|
"@babel/parser": "^7.29.3",
|
|
52
53
|
"@mozilla/readability": "^0.6.0",
|
|
53
|
-
"@gajae-code/stats": "0.4.
|
|
54
|
-
"@gajae-code/agent-core": "0.4.
|
|
55
|
-
"@gajae-code/ai": "0.4.
|
|
56
|
-
"@gajae-code/natives": "0.4.
|
|
57
|
-
"@gajae-code/tui": "0.4.
|
|
58
|
-
"@gajae-code/utils": "0.4.
|
|
54
|
+
"@gajae-code/stats": "0.4.5",
|
|
55
|
+
"@gajae-code/agent-core": "0.4.5",
|
|
56
|
+
"@gajae-code/ai": "0.4.5",
|
|
57
|
+
"@gajae-code/natives": "0.4.5",
|
|
58
|
+
"@gajae-code/tui": "0.4.5",
|
|
59
|
+
"@gajae-code/utils": "0.4.5",
|
|
59
60
|
"@puppeteer/browsers": "^2.13.0",
|
|
60
61
|
"@types/turndown": "5.0.6",
|
|
61
62
|
"@xterm/headless": "^6.0.0",
|
package/scripts/build-binary.ts
CHANGED
|
@@ -39,6 +39,10 @@ async function main(): Promise<void> {
|
|
|
39
39
|
"bun",
|
|
40
40
|
"build",
|
|
41
41
|
"--compile",
|
|
42
|
+
// Minify shrinks the bundled JS the compiled binary must parse at
|
|
43
|
+
// startup (302MB → ~114MB --help RSS measured on darwin-arm64).
|
|
44
|
+
// --keep-names below preserves identifiers for error reports.
|
|
45
|
+
"--minify",
|
|
42
46
|
"--no-compile-autoload-bunfig",
|
|
43
47
|
"--no-compile-autoload-dotenv",
|
|
44
48
|
"--no-compile-autoload-tsconfig",
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { APP_NAME, CONFIG_DIR_NAME } from "@gajae-code/utils/dirs";
|
|
2
|
+
|
|
3
|
+
export function getExtraHelpText(): string {
|
|
4
|
+
return `Environment Variables:
|
|
5
|
+
# Core Providers
|
|
6
|
+
ANTHROPIC_API_KEY - Anthropic Claude models
|
|
7
|
+
ANTHROPIC_OAUTH_TOKEN - Anthropic OAuth (takes precedence over API key)
|
|
8
|
+
CLAUDE_CODE_USE_FOUNDRY - Enable Anthropic Foundry mode (uses Foundry endpoint + mTLS)
|
|
9
|
+
FOUNDRY_BASE_URL - Anthropic Foundry base URL (e.g., https://<foundry-host>)
|
|
10
|
+
ANTHROPIC_FOUNDRY_API_KEY - Anthropic token used as Authorization: Bearer <token> in Foundry mode
|
|
11
|
+
ANTHROPIC_CUSTOM_HEADERS - Extra Foundry headers (e.g., "user-id: USERNAME")
|
|
12
|
+
CLAUDE_CODE_CLIENT_CERT - Client certificate (PEM path or inline PEM) for mTLS
|
|
13
|
+
CLAUDE_CODE_CLIENT_KEY - Client private key (PEM path or inline PEM) for mTLS
|
|
14
|
+
NODE_EXTRA_CA_CERTS - CA bundle path (or inline PEM) for server certificate validation
|
|
15
|
+
OPENAI_API_KEY - OpenAI GPT models
|
|
16
|
+
GEMINI_API_KEY - Google Gemini models
|
|
17
|
+
GITHUB_TOKEN - GitHub Copilot (or GH_TOKEN, COPILOT_GITHUB_TOKEN)
|
|
18
|
+
|
|
19
|
+
# Additional LLM Providers
|
|
20
|
+
AZURE_OPENAI_API_KEY - Azure OpenAI models
|
|
21
|
+
GROQ_API_KEY - Groq models
|
|
22
|
+
CEREBRAS_API_KEY - Cerebras models
|
|
23
|
+
XAI_API_KEY - xAI Grok models
|
|
24
|
+
OPENROUTER_API_KEY - OpenRouter aggregated models
|
|
25
|
+
KILO_API_KEY - Kilo Gateway models
|
|
26
|
+
MISTRAL_API_KEY - Mistral models
|
|
27
|
+
ZAI_API_KEY - z.ai models (ZhipuAI/GLM)
|
|
28
|
+
MINIMAX_API_KEY - MiniMax models
|
|
29
|
+
OPENCODE_API_KEY - OpenCode Zen/OpenCode Go models
|
|
30
|
+
CURSOR_ACCESS_TOKEN - Cursor AI models
|
|
31
|
+
AI_GATEWAY_API_KEY - Vercel AI Gateway
|
|
32
|
+
|
|
33
|
+
# Cloud Providers
|
|
34
|
+
AWS_PROFILE - AWS Bedrock (or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY)
|
|
35
|
+
GOOGLE_CLOUD_PROJECT - Google Vertex AI (requires GOOGLE_CLOUD_LOCATION)
|
|
36
|
+
GOOGLE_APPLICATION_CREDENTIALS - Service account for Vertex AI
|
|
37
|
+
|
|
38
|
+
# Search & Tools
|
|
39
|
+
EXA_API_KEY - Exa web search
|
|
40
|
+
BRAVE_API_KEY - Brave web search
|
|
41
|
+
PERPLEXITY_API_KEY - Perplexity web search (API)
|
|
42
|
+
PERPLEXITY_COOKIES - Perplexity web search (session cookie)
|
|
43
|
+
TAVILY_API_KEY - Tavily web search
|
|
44
|
+
ANTHROPIC_SEARCH_API_KEY - Anthropic search provider
|
|
45
|
+
|
|
46
|
+
# Configuration
|
|
47
|
+
GJC_CODING_AGENT_DIR - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)
|
|
48
|
+
GJC_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)
|
|
49
|
+
GJC_SMOL_MODEL - Override smol/fast model (see --smol)
|
|
50
|
+
GJC_SLOW_MODEL - Override slow/reasoning model (see --slow)
|
|
51
|
+
GJC_PLAN_MODEL - Override planning model (see --plan)
|
|
52
|
+
GJC_NO_PTY - Disable PTY-based interactive bash execution
|
|
53
|
+
--tmux - Launch interactive startup inside a new tmux session
|
|
54
|
+
gjc session - List, inspect, create, remove, or attach tagged GJC-managed tmux sessions
|
|
55
|
+
GJC_LAUNCH_POLICY - Launch policy for --tmux startup: tmux or direct
|
|
56
|
+
GJC_TMUX_SESSION - Explicit tmux session name override for --tmux startup
|
|
57
|
+
|
|
58
|
+
For complete environment variable reference, see:
|
|
59
|
+
docs/environment-variables.md
|
|
60
|
+
Available Tools (default-enabled unless noted):
|
|
61
|
+
read - Read file contents
|
|
62
|
+
bash - Execute bash commands
|
|
63
|
+
edit - Edit files with find/replace
|
|
64
|
+
write - Write files (creates/overwrites)
|
|
65
|
+
grep - Search file contents
|
|
66
|
+
find - Find files by glob pattern
|
|
67
|
+
lsp - Language server protocol (code intelligence)
|
|
68
|
+
python - Execute Python code (requires: ${APP_NAME} setup python)
|
|
69
|
+
notebook - Edit Jupyter notebooks
|
|
70
|
+
inspect_image - Analyze images with a vision model
|
|
71
|
+
browser - Browser automation (Puppeteer)
|
|
72
|
+
task - Launch sub-agents for parallel tasks
|
|
73
|
+
todo_write - Manage todo/task lists
|
|
74
|
+
web_search - Search the web
|
|
75
|
+
ask - Ask user questions (interactive mode only)
|
|
76
|
+
|
|
77
|
+
Useful Commands:
|
|
78
|
+
${APP_NAME} --list-models - List configured provider models
|
|
79
|
+
${APP_NAME} --help - Show this help`;
|
|
80
|
+
}
|