@gajae-code/coding-agent 0.2.5 → 0.3.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 +10 -0
- package/dist/types/async/job-manager.d.ts +84 -2
- package/dist/types/commands/harness.d.ts +37 -0
- package/dist/types/config/settings-schema.d.ts +6 -0
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/deep-interview/render-middleware.d.ts +5 -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/state-graph.d.ts +4 -0
- package/dist/types/gjc-runtime/state-migrations.d.ts +24 -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-validation.d.ts +6 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +137 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +81 -7
- 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 +30 -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 +2 -29
- package/dist/types/modes/components/hook-selector.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/types.d.ts +1 -0
- package/dist/types/sdk.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +8 -0
- 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 +24 -0
- package/dist/types/task/executor.d.ts +3 -0
- package/dist/types/task/types.d.ts +55 -3
- package/dist/types/tools/subagent.d.ts +11 -1
- package/package.json +7 -7
- package/src/async/job-manager.ts +298 -6
- 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/harness.ts +592 -0
- package/src/commands/team.ts +36 -39
- package/src/config/settings-schema.ts +7 -0
- package/src/config/settings.ts +5 -0
- package/src/deep-interview/render-middleware.ts +366 -0
- package/src/defaults/gjc/skills/team/SKILL.md +47 -21
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +78 -11
- 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/deep-interview-runtime.ts +40 -21
- package/src/gjc-runtime/goal-mode-request.ts +11 -3
- package/src/gjc-runtime/ralplan-runtime.ts +25 -10
- package/src/gjc-runtime/state-graph.ts +86 -0
- package/src/gjc-runtime/state-migrations.ts +132 -0
- package/src/gjc-runtime/state-renderer.ts +345 -0
- package/src/gjc-runtime/state-runtime.ts +733 -21
- package/src/gjc-runtime/state-validation.ts +49 -0
- package/src/gjc-runtime/state-writer.ts +718 -0
- package/src/gjc-runtime/team-runtime.ts +1083 -89
- package/src/gjc-runtime/ultragoal-runtime.ts +348 -19
- package/src/gjc-runtime/workflow-manifest.generated.json +1497 -0
- package/src/gjc-runtime/workflow-manifest.ts +425 -0
- package/src/harness-control-plane/classifier.ts +128 -0
- package/src/harness-control-plane/control-endpoint.ts +137 -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 +553 -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 +97 -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 +24 -41
- package/src/internal-urls/docs-index.generated.ts +1 -1
- package/src/modes/components/assistant-message.ts +5 -1
- package/src/modes/components/hook-selector.ts +72 -2
- package/src/modes/controllers/event-controller.ts +71 -6
- package/src/modes/controllers/extension-ui-controller.ts +6 -0
- package/src/modes/controllers/input-controller.ts +9 -1
- package/src/modes/controllers/selector-controller.ts +2 -1
- package/src/modes/interactive-mode.ts +1 -0
- package/src/modes/types.ts +1 -0
- package/src/prompts/agents/executor.md +13 -0
- package/src/prompts/tools/subagent.md +33 -3
- package/src/sdk.ts +4 -0
- package/src/session/agent-session.ts +231 -33
- 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 +91 -13
- package/src/skill-state/initial-phase.ts +2 -0
- package/src/skill-state/workflow-state-contract.ts +26 -0
- package/src/task/executor.ts +50 -8
- package/src/task/index.ts +120 -8
- package/src/task/render.ts +6 -3
- package/src/task/types.ts +56 -3
- package/src/tools/ask.ts +28 -7
- package/src/tools/subagent.ts +255 -64
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export interface SessionLease {
|
|
2
|
+
ownerId: string;
|
|
3
|
+
sessionId: string;
|
|
4
|
+
pid: number;
|
|
5
|
+
leaseTokenHash: string;
|
|
6
|
+
endpoint: {
|
|
7
|
+
kind: "unix-socket" | "fifo";
|
|
8
|
+
path: string;
|
|
9
|
+
} | null;
|
|
10
|
+
eventsPath: string;
|
|
11
|
+
heartbeatAt: string;
|
|
12
|
+
expiresAt: string;
|
|
13
|
+
leaseEpoch: number;
|
|
14
|
+
writer: {
|
|
15
|
+
ownerId: string;
|
|
16
|
+
leaseEpoch: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export declare class LeaseError extends Error {
|
|
20
|
+
readonly code: string;
|
|
21
|
+
constructor(message: string, code: string);
|
|
22
|
+
}
|
|
23
|
+
export type LeaseStatus = "missing" | "live" | "expiredAlive" | "dead" | "epermAlive";
|
|
24
|
+
type PidStatus = "alive" | "dead" | "eperm";
|
|
25
|
+
export declare function readLease(root: string, sessionId: string): Promise<SessionLease | null>;
|
|
26
|
+
export declare function isExpired(lease: SessionLease, clock?: () => number): boolean;
|
|
27
|
+
export declare function classifyLeaseStatus(lease: SessionLease | null, opts?: {
|
|
28
|
+
clock?: () => number;
|
|
29
|
+
probe?: (pid: number) => PidStatus;
|
|
30
|
+
}): LeaseStatus;
|
|
31
|
+
/** Liveness probe via signal 0. Defaults to the real process table; injectable for tests. */
|
|
32
|
+
export declare function isOwnerAlive(pid: number, probe?: (pid: number) => boolean): boolean;
|
|
33
|
+
export declare function isStale(lease: SessionLease, opts?: {
|
|
34
|
+
clock?: () => number;
|
|
35
|
+
probe?: (pid: number) => boolean;
|
|
36
|
+
}): boolean;
|
|
37
|
+
export interface AcquireOptions {
|
|
38
|
+
ownerId: string;
|
|
39
|
+
pid: number;
|
|
40
|
+
endpoint?: SessionLease["endpoint"];
|
|
41
|
+
eventsPath: string;
|
|
42
|
+
ttlMs: number;
|
|
43
|
+
clock?: () => number;
|
|
44
|
+
probe?: (pid: number) => boolean | PidStatus;
|
|
45
|
+
}
|
|
46
|
+
export interface AcquiredLease {
|
|
47
|
+
lease: SessionLease;
|
|
48
|
+
token: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Acquire (or take over a stale) lease. Fails closed with `lease_held` when a live,
|
|
52
|
+
* unexpired lease is held by a different owner. Re-acquiring as the current owner refreshes.
|
|
53
|
+
*/
|
|
54
|
+
export declare function acquireLease(root: string, sessionId: string, opts: AcquireOptions): Promise<AcquiredLease>;
|
|
55
|
+
/** Refresh the lease expiry. Only the recorded owner may heartbeat (single-writer). */
|
|
56
|
+
export declare function heartbeat(root: string, sessionId: string, ownerId: string, ttlMs: number, clock?: () => number): Promise<SessionLease>;
|
|
57
|
+
/** Whether `ownerId` is the live, unexpired single writer permitted to append events. */
|
|
58
|
+
export declare function canWriteEvents(lease: SessionLease, ownerId: string, clock?: () => number): boolean;
|
|
59
|
+
/** Release the lease (owner shutdown). Only the holder may release. */
|
|
60
|
+
export declare function releaseLease(root: string, sessionId: string, ownerId: string): Promise<void>;
|
|
61
|
+
export declare function reapDeadOwnerArtifacts(root: string, sessionId: string, expectedOwnerId: string, expectedEpoch: number, opts?: {
|
|
62
|
+
clock?: () => number;
|
|
63
|
+
probe?: (pid: number) => PidStatus;
|
|
64
|
+
}): Promise<boolean>;
|
|
65
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle state machine + the universal `{state, evidence, nextAllowedActions}` contract.
|
|
3
|
+
*
|
|
4
|
+
* `nextAllowedActions` is the forcing function: it tells the caller exactly which
|
|
5
|
+
* primitives are currently permitted and, when not, why. Owner-routed verbs
|
|
6
|
+
* (`submit`) report `owner-not-live` when no `RuntimeOwner` holds the session lease.
|
|
7
|
+
*/
|
|
8
|
+
import type { HarnessLifecycle, NextAllowedAction, PrimitiveResponse, SessionState, SessionStateView } from "./types";
|
|
9
|
+
export declare function isTerminal(lifecycle: HarnessLifecycle): boolean;
|
|
10
|
+
export declare function canTransition(from: HarnessLifecycle, to: HarnessLifecycle): boolean;
|
|
11
|
+
export declare function assertTransition(from: HarnessLifecycle, to: HarnessLifecycle): void;
|
|
12
|
+
/**
|
|
13
|
+
* Derive the permitted next actions for a session given its lifecycle and whether
|
|
14
|
+
* a live owner currently holds the lease.
|
|
15
|
+
*/
|
|
16
|
+
export declare function nextAllowedActions(lifecycle: HarnessLifecycle, ownerLive: boolean): NextAllowedAction[];
|
|
17
|
+
export declare function buildStateView(state: SessionState, ownerLive: boolean): SessionStateView;
|
|
18
|
+
/** Build the universal contract response carried by every primitive. */
|
|
19
|
+
export declare function buildResponse<E extends Record<string, unknown>>(state: SessionState, ownerLive: boolean, evidence: E, ok?: boolean): PrimitiveResponse<E>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { EventEnvelope, ReceiptFamily, SessionState } from "./types";
|
|
2
|
+
export declare const MAX_UNIX_SOCKET_PATH_BYTES = 100;
|
|
3
|
+
export declare function controlSocketPath(root: string, sessionId: string, env?: NodeJS.ProcessEnv): string;
|
|
4
|
+
export declare class StorageError extends Error {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
constructor(message: string, code: string);
|
|
7
|
+
}
|
|
8
|
+
/** Resolve the harness state root from explicit value, env, or cwd default. */
|
|
9
|
+
export declare function resolveHarnessRoot(opts?: {
|
|
10
|
+
root?: string;
|
|
11
|
+
cwd?: string;
|
|
12
|
+
env?: NodeJS.ProcessEnv;
|
|
13
|
+
}): string;
|
|
14
|
+
export declare function assertSafeSessionId(id: string): void;
|
|
15
|
+
export declare function generateSessionId(prefix?: string): string;
|
|
16
|
+
export interface SessionPaths {
|
|
17
|
+
dir: string;
|
|
18
|
+
state: string;
|
|
19
|
+
lease: string;
|
|
20
|
+
events: string;
|
|
21
|
+
receiptsIndex: string;
|
|
22
|
+
receiptsDir: string;
|
|
23
|
+
artifactsDir: string;
|
|
24
|
+
controlSock: string;
|
|
25
|
+
controlFifo: string;
|
|
26
|
+
gjcSessionDir: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function sessionPaths(root: string, sessionId: string): SessionPaths;
|
|
29
|
+
export declare function readSessionState(root: string, sessionId: string): Promise<SessionState | null>;
|
|
30
|
+
export declare function writeSessionState(root: string, state: SessionState): Promise<void>;
|
|
31
|
+
export declare function sessionExists(root: string, sessionId: string): Promise<boolean>;
|
|
32
|
+
/** Append a single severity envelope to events.jsonl. Single-writer discipline is the owner's job (M3). */
|
|
33
|
+
export declare function appendEvent(root: string, sessionId: string, envelope: EventEnvelope): Promise<void>;
|
|
34
|
+
/** Read events from cursor (exclusive). Tail-only: never mutates the log. */
|
|
35
|
+
export declare function readEvents(root: string, sessionId: string, fromCursor?: number): Promise<EventEnvelope[]>;
|
|
36
|
+
export interface ReceiptIndexEntry {
|
|
37
|
+
receiptId: string;
|
|
38
|
+
family: ReceiptFamily;
|
|
39
|
+
valid: boolean;
|
|
40
|
+
createdAt: string;
|
|
41
|
+
path: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Persist a receipt immutably. Fails closed if the receipt id already exists,
|
|
45
|
+
* then appends an index entry to receipts.jsonl.
|
|
46
|
+
*/
|
|
47
|
+
export declare function writeReceiptImmutable(root: string, sessionId: string, family: ReceiptFamily, receiptId: string, value: {
|
|
48
|
+
receiptId: string;
|
|
49
|
+
family: ReceiptFamily;
|
|
50
|
+
valid: boolean;
|
|
51
|
+
createdAt: string;
|
|
52
|
+
}): Promise<ReceiptIndexEntry>;
|
|
53
|
+
export declare function readReceiptIndex(root: string, sessionId: string, family?: ReceiptFamily): Promise<ReceiptIndexEntry[]>;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for the gajae-code-native coding-harness operations control plane (v1).
|
|
3
|
+
*
|
|
4
|
+
* See the approved consensus plan at
|
|
5
|
+
* `.gjc/plans/ralplan/2026-06-02-0853-3e33/stage-02-revision.md` and the spec at
|
|
6
|
+
* `.gjc/specs/deep-interview-harness-control-plane.md`.
|
|
7
|
+
*
|
|
8
|
+
* v1 implements the gajae-code adapter only. omx/codex/remote/auth are deferred seams.
|
|
9
|
+
*/
|
|
10
|
+
/** Harnesses the control plane can operate. v1 implements `gajae-code` only. */
|
|
11
|
+
export type Harness = "gajae-code" | "codex" | "omx";
|
|
12
|
+
/** Lifecycle states of an operated session. */
|
|
13
|
+
export type HarnessLifecycle = "new" | "started" | "submitted" | "observing" | "recovering" | "validating" | "finalizing" | "completed" | "blocked" | "retired";
|
|
14
|
+
/** Event severities emitted by the owner. */
|
|
15
|
+
export type Severity = "info" | "warn" | "critical";
|
|
16
|
+
/** Bounded git delta classification surfaced by `observe`. */
|
|
17
|
+
export type GitDelta = "clean" | "dirty" | "zero-delta" | "unknown";
|
|
18
|
+
/** Risk classification surfaced by `observe`. */
|
|
19
|
+
export type RiskKind = "normal" | "prompt-not-accepted" | "deleted-worktree" | "vanished-dirty";
|
|
20
|
+
/** Deterministic recovery classifications. */
|
|
21
|
+
export type RecoveryClassification = "continue" | "send-enter" | "reinject-prompt" | "restart-clean" | "restart-preserve-delta" | "fallback-codex-exec" | "human-check";
|
|
22
|
+
/** Receipt families persisted under the session storage dir. */
|
|
23
|
+
export type ReceiptFamily = "vanish" | "prompt-acceptance" | "validation" | "completion";
|
|
24
|
+
/** The CLI verbs / primitives exposed by `gjc harness <verb>`. */
|
|
25
|
+
export type HarnessVerb = "start" | "submit" | "observe" | "classify" | "recover" | "validate" | "finalize" | "retire" | "events" | "monitor" | "operate";
|
|
26
|
+
/** Submission transports. */
|
|
27
|
+
export type SubmitMode = "paste-buffer" | "stdin" | "file";
|
|
28
|
+
/** A single entry in the forcing-function `nextAllowedActions` list. */
|
|
29
|
+
export interface NextAllowedAction {
|
|
30
|
+
verb: HarnessVerb;
|
|
31
|
+
available: boolean;
|
|
32
|
+
/** Present when `available` is false; explains why the verb is currently disallowed. */
|
|
33
|
+
reason?: string;
|
|
34
|
+
}
|
|
35
|
+
/** Compact, model-facing view of session state included in every response. */
|
|
36
|
+
export interface SessionStateView {
|
|
37
|
+
sessionId: string;
|
|
38
|
+
lifecycle: HarnessLifecycle;
|
|
39
|
+
harness: Harness;
|
|
40
|
+
ownerLive: boolean;
|
|
41
|
+
blockers: string[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The universal contract: EVERY primitive response carries `{state, evidence, nextAllowedActions}`.
|
|
45
|
+
* `ok` is a transport-level convenience; semantic blocking is expressed via state + nextAllowedActions.
|
|
46
|
+
*/
|
|
47
|
+
export interface PrimitiveResponse<E = Record<string, unknown>> {
|
|
48
|
+
ok: boolean;
|
|
49
|
+
state: SessionStateView;
|
|
50
|
+
evidence: E;
|
|
51
|
+
nextAllowedActions: NextAllowedAction[];
|
|
52
|
+
}
|
|
53
|
+
/** Re-grabbable session handle returned by `start` / `operate`. */
|
|
54
|
+
export interface SessionHandle {
|
|
55
|
+
sessionId: string;
|
|
56
|
+
harness: Harness;
|
|
57
|
+
repo: string | null;
|
|
58
|
+
workspace: string;
|
|
59
|
+
branch: string | null;
|
|
60
|
+
base: string | null;
|
|
61
|
+
issueOrPr: string | null;
|
|
62
|
+
processHandle: {
|
|
63
|
+
kind: "runtime-owner";
|
|
64
|
+
ownerId: string | null;
|
|
65
|
+
pid: number | null;
|
|
66
|
+
};
|
|
67
|
+
rpcHandle: {
|
|
68
|
+
kind: "rpc-subprocess";
|
|
69
|
+
pid: number | null;
|
|
70
|
+
sessionDir: string;
|
|
71
|
+
};
|
|
72
|
+
ownerHandle: {
|
|
73
|
+
leasePath: string;
|
|
74
|
+
endpoint: string | null;
|
|
75
|
+
heartbeatAt: string | null;
|
|
76
|
+
};
|
|
77
|
+
routerHandle: {
|
|
78
|
+
kind: "default-in-owner";
|
|
79
|
+
policy: string;
|
|
80
|
+
eventsPath: string;
|
|
81
|
+
};
|
|
82
|
+
viewportHandle: {
|
|
83
|
+
kind: "event-monitor";
|
|
84
|
+
tmuxSessionName: string | null;
|
|
85
|
+
viewOnly: true;
|
|
86
|
+
};
|
|
87
|
+
startedAt: string;
|
|
88
|
+
updatedAt: string;
|
|
89
|
+
}
|
|
90
|
+
/** Persisted per-session record (state.json). */
|
|
91
|
+
export interface SessionState {
|
|
92
|
+
schemaVersion: number;
|
|
93
|
+
sessionId: string;
|
|
94
|
+
lifecycle: HarnessLifecycle;
|
|
95
|
+
harness: Harness;
|
|
96
|
+
handle: SessionHandle;
|
|
97
|
+
/** Per-classification retry counters consumed by the recovery policy. */
|
|
98
|
+
retries: Record<string, number>;
|
|
99
|
+
blockers: string[];
|
|
100
|
+
createdAt: string;
|
|
101
|
+
updatedAt: string;
|
|
102
|
+
}
|
|
103
|
+
/** Bounded observed-signal vocabulary surfaced by `observe` (the owner only ever emits these). */
|
|
104
|
+
export type ObservedSignal = "SessionStart" | "prompt-accepted" | "tool-call" | "test-running" | "commit-created" | "completed" | "error" | "streaming" | "idle";
|
|
105
|
+
export declare const OBSERVED_SIGNALS: readonly ObservedSignal[];
|
|
106
|
+
/** Bounded observation surfaced by `observe` — never a raw pane/transcript dump. */
|
|
107
|
+
export interface Observation {
|
|
108
|
+
lifecycle: HarnessLifecycle;
|
|
109
|
+
ownerLive: boolean;
|
|
110
|
+
cwd: string;
|
|
111
|
+
branch: string | null;
|
|
112
|
+
gitDelta: GitDelta;
|
|
113
|
+
lastActivityAt: string | null;
|
|
114
|
+
observedSignals: string[];
|
|
115
|
+
risk: RiskKind;
|
|
116
|
+
/** RPC subprocess liveness, distinct from owner-process/lease liveness. Optional for back-compat. */
|
|
117
|
+
rpcLive?: boolean;
|
|
118
|
+
/** ISO timestamp of the most recent RPC frame the owner observed, if any. */
|
|
119
|
+
rpcLastFrameAt?: string | null;
|
|
120
|
+
}
|
|
121
|
+
/** Input to the deterministic recovery classifier. */
|
|
122
|
+
export interface ClassifyInput {
|
|
123
|
+
observation: Observation;
|
|
124
|
+
/** Remaining retry budget per classification family. */
|
|
125
|
+
retryBudget: RetryBudget;
|
|
126
|
+
/** Whether an accepted prompt was in flight when the owner/RPC was last seen. */
|
|
127
|
+
acceptedPromptActive?: boolean;
|
|
128
|
+
}
|
|
129
|
+
/** Default and supplied retry budgets. */
|
|
130
|
+
export interface RetryBudget {
|
|
131
|
+
reinjectPrompt: number;
|
|
132
|
+
zeroDeltaVanish: number;
|
|
133
|
+
dirtyVanishPreserve: number;
|
|
134
|
+
validationRepair: number;
|
|
135
|
+
}
|
|
136
|
+
/** Result of the deterministic recovery classifier. */
|
|
137
|
+
export interface RecoveryDecision {
|
|
138
|
+
classification: RecoveryClassification;
|
|
139
|
+
reason: string;
|
|
140
|
+
severity: Severity;
|
|
141
|
+
/** Whether executing the recommended action requires a live owner. */
|
|
142
|
+
ownerRequired: boolean;
|
|
143
|
+
/** Receipt family that MUST be valid before the action may proceed (e.g. `vanish`). */
|
|
144
|
+
requiredReceiptFamily: ReceiptFamily | null;
|
|
145
|
+
}
|
|
146
|
+
/** Severity-tagged event envelope written exclusively by the owner. */
|
|
147
|
+
export interface EventEnvelope<E = Record<string, unknown>> {
|
|
148
|
+
eventId: string;
|
|
149
|
+
cursor: number;
|
|
150
|
+
createdAt: string;
|
|
151
|
+
severity: Severity;
|
|
152
|
+
kind: string;
|
|
153
|
+
state: SessionStateView;
|
|
154
|
+
evidence: E;
|
|
155
|
+
nextAllowedActions: NextAllowedAction[];
|
|
156
|
+
writer: {
|
|
157
|
+
ownerId: string;
|
|
158
|
+
leaseEpoch: number;
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
export declare const SESSION_SCHEMA_VERSION: 1;
|
|
162
|
+
export declare const DEFAULT_RETRY_BUDGET: RetryBudget;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CanonicalGjcWorkflowSkill } from "../skill-state/active-state";
|
|
1
2
|
export interface SkillKeywordDefinition {
|
|
2
3
|
keyword: string;
|
|
3
4
|
skill: GjcWorkflowSkill;
|
|
@@ -5,7 +6,7 @@ export interface SkillKeywordDefinition {
|
|
|
5
6
|
guidance: string;
|
|
6
7
|
}
|
|
7
8
|
export declare const GJC_WORKFLOW_SKILLS: readonly ["deep-interview", "ralplan", "ultragoal", "team"];
|
|
8
|
-
export type GjcWorkflowSkill =
|
|
9
|
+
export type GjcWorkflowSkill = CanonicalGjcWorkflowSkill;
|
|
9
10
|
export declare const GJC_SKILL_KEYWORD_DEFINITIONS: readonly SkillKeywordDefinition[];
|
|
10
11
|
export declare function isGjcWorkflowSkill(value: string): value is GjcWorkflowSkill;
|
|
11
12
|
export declare function compareSkillKeywordMatches(a: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SkillDiscoverySettings } from "../config/skill-settings-defaults";
|
|
2
|
-
import
|
|
2
|
+
import { type SkillActiveState } from "../skill-state/active-state";
|
|
3
3
|
import { type GjcWorkflowSkill } from "./skill-keywords";
|
|
4
4
|
export declare const GJC_STATE_DIR = ".gjc/state";
|
|
5
5
|
export declare const SKILL_ACTIVE_STATE_FILE = "skill-active-state.json";
|
|
@@ -14,34 +14,7 @@ export interface SkillKeywordMatch {
|
|
|
14
14
|
skill: GjcWorkflowSkill;
|
|
15
15
|
priority: number;
|
|
16
16
|
}
|
|
17
|
-
export
|
|
18
|
-
skill: GjcWorkflowSkill;
|
|
19
|
-
phase?: string;
|
|
20
|
-
active?: boolean;
|
|
21
|
-
activated_at?: string;
|
|
22
|
-
updated_at?: string;
|
|
23
|
-
session_id?: string;
|
|
24
|
-
thread_id?: string;
|
|
25
|
-
turn_id?: string;
|
|
26
|
-
hud?: WorkflowHudSummary;
|
|
27
|
-
stale?: boolean;
|
|
28
|
-
}
|
|
29
|
-
export interface SkillActiveState {
|
|
30
|
-
version: number;
|
|
31
|
-
active: boolean;
|
|
32
|
-
skill: GjcWorkflowSkill;
|
|
33
|
-
keyword: string;
|
|
34
|
-
phase: string;
|
|
35
|
-
activated_at: string;
|
|
36
|
-
updated_at: string;
|
|
37
|
-
source: "gjc-skill-state-hook";
|
|
38
|
-
session_id?: string;
|
|
39
|
-
thread_id?: string;
|
|
40
|
-
turn_id?: string;
|
|
41
|
-
initialized_mode?: GjcWorkflowSkill;
|
|
42
|
-
initialized_state_path?: string;
|
|
43
|
-
active_skills: SkillActiveEntry[];
|
|
44
|
-
}
|
|
17
|
+
export type { SkillActiveEntry, SkillActiveState } from "../skill-state/active-state";
|
|
45
18
|
export interface ModeState {
|
|
46
19
|
active?: boolean;
|
|
47
20
|
current_phase?: string;
|
|
@@ -86,6 +86,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
|
|
|
86
86
|
retryLoader: Loader | undefined;
|
|
87
87
|
autoCompactionEscapeHandler?: () => void;
|
|
88
88
|
retryEscapeHandler?: () => void;
|
|
89
|
+
retryCountdownTimer?: ReturnType<typeof setInterval>;
|
|
89
90
|
unsubscribe?: () => void;
|
|
90
91
|
onInputCallback?: (input: SubmittedUserInput) => void;
|
|
91
92
|
optimisticUserMessageSignature: string | undefined;
|
|
@@ -93,6 +93,7 @@ export interface InteractiveModeContext {
|
|
|
93
93
|
retryLoader: Loader | undefined;
|
|
94
94
|
autoCompactionEscapeHandler?: () => void;
|
|
95
95
|
retryEscapeHandler?: () => void;
|
|
96
|
+
retryCountdownTimer?: ReturnType<typeof setInterval>;
|
|
96
97
|
unsubscribe?: () => void;
|
|
97
98
|
onInputCallback?: (input: SubmittedUserInput) => void;
|
|
98
99
|
optimisticUserMessageSignature: string | undefined;
|
package/dist/types/sdk.d.ts
CHANGED
|
@@ -127,6 +127,8 @@ export interface CreateAgentSessionOptions {
|
|
|
127
127
|
forkContextSeed?: ForkContextSeed;
|
|
128
128
|
/** Optional provider state override. Fork-context children should omit this by default. */
|
|
129
129
|
providerSessionState?: Map<string, ProviderSessionState>;
|
|
130
|
+
/** Cooperative pause checkpoint passed through to Agent. */
|
|
131
|
+
shouldPause?: () => boolean;
|
|
130
132
|
}
|
|
131
133
|
/** Result from createAgentSession */
|
|
132
134
|
export interface CreateAgentSessionResult {
|
|
@@ -90,6 +90,7 @@ export type AgentSessionEvent = AgentEvent | {
|
|
|
90
90
|
maxAttempts: number;
|
|
91
91
|
delayMs: number;
|
|
92
92
|
errorMessage: string;
|
|
93
|
+
unbounded?: boolean;
|
|
93
94
|
} | {
|
|
94
95
|
type: "auto_retry_end";
|
|
95
96
|
success: boolean;
|
|
@@ -604,6 +605,7 @@ export declare class AgentSession {
|
|
|
604
605
|
abort(options?: {
|
|
605
606
|
goalReason?: "interrupted" | "internal";
|
|
606
607
|
timeoutMs?: number;
|
|
608
|
+
cause?: "user_interrupt" | "new_session" | "session_switch" | "compaction" | "handoff" | "tool_abort" | "internal";
|
|
607
609
|
}): Promise<void>;
|
|
608
610
|
/**
|
|
609
611
|
* Start a new session, optionally with initial messages and parent tracking.
|
|
@@ -752,6 +754,12 @@ export declare class AgentSession {
|
|
|
752
754
|
* Cancel in-progress retry.
|
|
753
755
|
*/
|
|
754
756
|
abortRetry(): void;
|
|
757
|
+
/**
|
|
758
|
+
* Skip the current retry backoff and re-attempt immediately. Distinct from
|
|
759
|
+
* abortRetry(), which cancels the retry and returns to idle. No-op when no
|
|
760
|
+
* retry backoff is active.
|
|
761
|
+
*/
|
|
762
|
+
retryNow(): void;
|
|
755
763
|
/** Whether auto-retry is currently in progress */
|
|
756
764
|
get isRetrying(): boolean;
|
|
757
765
|
/** Whether auto-retry is enabled */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentTool } from "@gajae-code/agent-core";
|
|
2
2
|
export declare const DEEP_INTERVIEW_MUTATION_BLOCK_MESSAGE = "Deep-interview phase boundary: continue gathering context/questions/risks and emit a handoff/spec before code edits. Mutation tools and patch execution are blocked while deep-interview is active; finalize specs through `gjc deep-interview --write --stage final` or hand off to an execution phase.";
|
|
3
|
-
export declare const WORKFLOW_STATE_MUTATION_BLOCK_MESSAGE = "
|
|
3
|
+
export declare const WORKFLOW_STATE_MUTATION_BLOCK_MESSAGE = ".gjc workflow state and artifacts are runtime-owned. Agent mutation tools cannot edit `.gjc/**`; use the sanctioned `gjc` CLI instead.";
|
|
4
4
|
type ToolWithEditMode = AgentTool & {
|
|
5
5
|
mode?: unknown;
|
|
6
6
|
customWireName?: unknown;
|
|
@@ -4,6 +4,12 @@ export declare const WORKFLOW_STATE_RECEIPT_VERSION = 1;
|
|
|
4
4
|
export declare const WORKFLOW_STATE_RECEIPT_FRESH_MS: number;
|
|
5
5
|
export type WorkflowStateMutationOwner = "gjc-state-cli" | "gjc-runtime" | "gjc-hook";
|
|
6
6
|
export type WorkflowStateReceiptStatus = "fresh" | "stale";
|
|
7
|
+
export interface WorkflowStateContentChecksum {
|
|
8
|
+
algorithm: "sha256";
|
|
9
|
+
value: string;
|
|
10
|
+
covered_path: string;
|
|
11
|
+
computed_at: string;
|
|
12
|
+
}
|
|
7
13
|
export interface WorkflowStateReceipt {
|
|
8
14
|
version: 1;
|
|
9
15
|
skill: CanonicalGjcWorkflowSkill;
|
|
@@ -15,6 +21,24 @@ export interface WorkflowStateReceipt {
|
|
|
15
21
|
fresh_until: string;
|
|
16
22
|
status: WorkflowStateReceiptStatus;
|
|
17
23
|
mutation_id: string;
|
|
24
|
+
verb?: string;
|
|
25
|
+
from_phase?: string;
|
|
26
|
+
to_phase?: string;
|
|
27
|
+
forced?: boolean;
|
|
28
|
+
paths?: string[];
|
|
29
|
+
content_sha256?: WorkflowStateContentChecksum;
|
|
30
|
+
}
|
|
31
|
+
export interface AuditEntry {
|
|
32
|
+
ts: string;
|
|
33
|
+
skill?: string;
|
|
34
|
+
category: string;
|
|
35
|
+
verb: string;
|
|
36
|
+
owner: WorkflowStateMutationOwner;
|
|
37
|
+
mutation_id: string;
|
|
38
|
+
from_phase?: string;
|
|
39
|
+
to_phase?: string;
|
|
40
|
+
forced: boolean;
|
|
41
|
+
paths: string[];
|
|
18
42
|
}
|
|
19
43
|
export declare function workflowModeStateFileName(skill: CanonicalGjcWorkflowSkill): string;
|
|
20
44
|
export declare function workflowStateStoragePath(cwd: string, skill: CanonicalGjcWorkflowSkill, sessionId?: string): string;
|
|
@@ -29,6 +29,9 @@ export interface ExecutorOptions {
|
|
|
29
29
|
index: number;
|
|
30
30
|
id: string;
|
|
31
31
|
modelOverride?: string | string[];
|
|
32
|
+
runMode?: "initial" | "resume" | "message";
|
|
33
|
+
resumeMessage?: string;
|
|
34
|
+
subagentId?: string;
|
|
32
35
|
/**
|
|
33
36
|
* Active model selector of the parent session, used as an auth-aware fallback
|
|
34
37
|
* if the resolved subagent model has no working credentials. See #985.
|
|
@@ -32,7 +32,7 @@ export interface SubagentLifecyclePayload {
|
|
|
32
32
|
agent: string;
|
|
33
33
|
agentSource: AgentSource;
|
|
34
34
|
description?: string;
|
|
35
|
-
status: "started" | "completed" | "failed" | "aborted";
|
|
35
|
+
status: "started" | "completed" | "failed" | "aborted" | "paused";
|
|
36
36
|
sessionFile?: string;
|
|
37
37
|
index: number;
|
|
38
38
|
}
|
|
@@ -171,7 +171,7 @@ export interface AgentProgress {
|
|
|
171
171
|
id: string;
|
|
172
172
|
agent: string;
|
|
173
173
|
agentSource: AgentSource;
|
|
174
|
-
status: "pending" | "running" | "completed" | "failed" | "aborted";
|
|
174
|
+
status: "pending" | "running" | "completed" | "failed" | "aborted" | "paused";
|
|
175
175
|
task: string;
|
|
176
176
|
assignment?: string;
|
|
177
177
|
description?: string;
|
|
@@ -213,6 +213,7 @@ export interface AgentProgress {
|
|
|
213
213
|
retryState?: {
|
|
214
214
|
attempt: number;
|
|
215
215
|
maxAttempts: number;
|
|
216
|
+
unbounded?: boolean;
|
|
216
217
|
delayMs: number;
|
|
217
218
|
errorMessage: string;
|
|
218
219
|
startedAtMs: number;
|
|
@@ -261,6 +262,7 @@ export interface SingleResult {
|
|
|
261
262
|
error?: string;
|
|
262
263
|
aborted?: boolean;
|
|
263
264
|
abortReason?: string;
|
|
265
|
+
paused?: boolean;
|
|
264
266
|
/** Aggregated usage from the subprocess, accumulated incrementally from message_end events. */
|
|
265
267
|
usage?: Usage;
|
|
266
268
|
/** Output path for the task result */
|
|
@@ -299,9 +301,59 @@ export interface TaskToolDetails {
|
|
|
299
301
|
outputPaths?: string[];
|
|
300
302
|
progress?: AgentProgress[];
|
|
301
303
|
async?: {
|
|
302
|
-
state: "running" | "completed" | "failed";
|
|
304
|
+
state: "running" | "paused" | "queued" | "completed" | "failed";
|
|
303
305
|
jobId: string;
|
|
304
306
|
type: "task";
|
|
305
307
|
};
|
|
306
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* Persisted per-turn / per-subagent token record (Phase 0 instrumentation).
|
|
311
|
+
*
|
|
312
|
+
* Additive: this does not alter any existing task result shape. It is the
|
|
313
|
+
* durable, model-independent unit the deterministic orchestration-token
|
|
314
|
+
* benchmark (`@gajae-code/orchestration-token-benchmark`) consumes to measure
|
|
315
|
+
* token efficiency without any live-model calls.
|
|
316
|
+
*/
|
|
317
|
+
export interface TaskTokenLog {
|
|
318
|
+
/** Subagent id, or "root" for the orchestrator's own turn. */
|
|
319
|
+
subagentId: string;
|
|
320
|
+
/** Agent name for attribution, when known. */
|
|
321
|
+
agent?: string;
|
|
322
|
+
/** 1-based turn index within the subagent's session. */
|
|
323
|
+
turn: number;
|
|
324
|
+
/** ISO-8601 timestamp the turn completed. */
|
|
325
|
+
at: string;
|
|
326
|
+
/** Cost-bearing input tokens (excludes cache reads), mirrors `Usage.input`. */
|
|
327
|
+
input: number;
|
|
328
|
+
/** Total output tokens for the turn, mirrors `Usage.output`. */
|
|
329
|
+
output: number;
|
|
330
|
+
/** Tokens read from the prompt cache, mirrors `Usage.cacheRead`. */
|
|
331
|
+
cacheRead: number;
|
|
332
|
+
/** Tokens written to the prompt cache, mirrors `Usage.cacheWrite`. */
|
|
333
|
+
cacheWrite: number;
|
|
334
|
+
/** input + output + cacheRead + cacheWrite. */
|
|
335
|
+
totalTokens: number;
|
|
336
|
+
/** Latest per-turn context-window occupancy, when known. */
|
|
337
|
+
contextTokens?: number;
|
|
338
|
+
/** Estimated USD cost for the turn, when known. */
|
|
339
|
+
cost?: number;
|
|
340
|
+
/** Model id used for the turn, when known. */
|
|
341
|
+
model?: string;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Deterministic aggregate token metrics computed from a set of `TaskTokenLog`
|
|
345
|
+
* entries. The cache-hit-rate field is the primary prompt-cache signal called
|
|
346
|
+
* out by the prefix-stability invariant (see the approved plan).
|
|
347
|
+
*/
|
|
348
|
+
export interface TaskTokenMetrics {
|
|
349
|
+
/** Number of token-log entries aggregated. */
|
|
350
|
+
turns: number;
|
|
351
|
+
inputTokens: number;
|
|
352
|
+
outputTokens: number;
|
|
353
|
+
cacheReadTokens: number;
|
|
354
|
+
cacheWriteTokens: number;
|
|
355
|
+
totalTokens: number;
|
|
356
|
+
/** cacheRead / (input + cacheRead); 0 when there is no input-class traffic. */
|
|
357
|
+
cacheHitRate: number;
|
|
358
|
+
}
|
|
307
359
|
export {};
|
|
@@ -8,13 +8,18 @@ declare const subagentSchema: z.ZodObject<{
|
|
|
8
8
|
cancel: "cancel";
|
|
9
9
|
inspect: "inspect";
|
|
10
10
|
list: "list";
|
|
11
|
+
pause: "pause";
|
|
12
|
+
resume: "resume";
|
|
13
|
+
steer: "steer";
|
|
11
14
|
}>;
|
|
12
15
|
ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
16
|
+
message: z.ZodOptional<z.ZodString>;
|
|
17
|
+
pause: z.ZodOptional<z.ZodBoolean>;
|
|
13
18
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
14
19
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
15
20
|
}, z.core.$strip>;
|
|
16
21
|
type SubagentParams = z.infer<typeof subagentSchema>;
|
|
17
|
-
type SubagentStatus = "running" | "completed" | "failed" | "cancelled" | "not_found" | "already_completed";
|
|
22
|
+
type SubagentStatus = "running" | "paused" | "queued" | "completed" | "failed" | "cancelled" | "not_found" | "already_completed";
|
|
18
23
|
export interface SubagentSnapshot {
|
|
19
24
|
id: string;
|
|
20
25
|
jobId: string;
|
|
@@ -45,8 +50,13 @@ export declare class SubagentTool implements AgentTool<typeof subagentSchema, Su
|
|
|
45
50
|
cancel: "cancel";
|
|
46
51
|
inspect: "inspect";
|
|
47
52
|
list: "list";
|
|
53
|
+
pause: "pause";
|
|
54
|
+
resume: "resume";
|
|
55
|
+
steer: "steer";
|
|
48
56
|
}>;
|
|
49
57
|
ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
58
|
+
message: z.ZodOptional<z.ZodString>;
|
|
59
|
+
pause: z.ZodOptional<z.ZodBoolean>;
|
|
50
60
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
51
61
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
52
62
|
}, z.core.$strip>;
|
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
|
+
"version": "0.3.0",
|
|
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",
|
|
@@ -48,12 +48,12 @@
|
|
|
48
48
|
"@agentclientprotocol/sdk": "0.21.0",
|
|
49
49
|
"@babel/parser": "^7.29.3",
|
|
50
50
|
"@mozilla/readability": "^0.6.0",
|
|
51
|
-
"@gajae-code/stats": "0.
|
|
52
|
-
"@gajae-code/agent-core": "0.
|
|
53
|
-
"@gajae-code/ai": "0.
|
|
54
|
-
"@gajae-code/natives": "0.
|
|
55
|
-
"@gajae-code/tui": "0.
|
|
56
|
-
"@gajae-code/utils": "0.
|
|
51
|
+
"@gajae-code/stats": "0.3.0",
|
|
52
|
+
"@gajae-code/agent-core": "0.3.0",
|
|
53
|
+
"@gajae-code/ai": "0.3.0",
|
|
54
|
+
"@gajae-code/natives": "0.3.0",
|
|
55
|
+
"@gajae-code/tui": "0.3.0",
|
|
56
|
+
"@gajae-code/utils": "0.3.0",
|
|
57
57
|
"@puppeteer/browsers": "^2.13.0",
|
|
58
58
|
"@types/turndown": "5.0.6",
|
|
59
59
|
"@xterm/headless": "^6.0.0",
|