@gajae-code/coding-agent 0.12.5 → 0.12.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/README.md +4 -1
- package/dist/types/async/job-manager.d.ts +36 -1
- package/dist/types/extensibility/extensions/runner.d.ts +9 -7
- package/dist/types/gjc-runtime/launch-tmux.d.ts +22 -3
- package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
- package/dist/types/gjc-runtime/team-launch.d.ts +3 -1
- package/dist/types/gjc-runtime/team-runtime.d.ts +14 -2
- package/dist/types/gjc-runtime/team-store.d.ts +0 -4
- package/dist/types/gjc-runtime/team-workers.d.ts +5 -0
- package/dist/types/gjc-runtime/tmux-common.d.ts +1 -0
- package/dist/types/gjc-runtime/tmux-provider-context.d.ts +57 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +8 -1
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +3 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +21 -4
- package/dist/types/modes/components/gjc-bundle-settings.d.ts +1 -0
- package/dist/types/modes/components/plugin-settings.d.ts +2 -0
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/sdk/broker/broker.d.ts +18 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +13 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +1 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -3
- package/dist/types/sdk/bus/index.d.ts +4 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +2 -2
- package/dist/types/sdk/bus/telegram-daemon.d.ts +25 -3
- package/dist/types/sdk/bus/topic-registry.d.ts +63 -3
- package/dist/types/session/agent-session.d.ts +5 -4
- package/dist/types/session/attempt-record-store.d.ts +19 -0
- package/dist/types/session/session-manager.d.ts +1 -0
- package/dist/types/session/session-storage.d.ts +8 -0
- package/dist/types/task/receipt.d.ts +1 -0
- package/dist/types/task/types.d.ts +43 -0
- package/dist/types/tools/subagent.d.ts +15 -0
- package/dist/types/tools/todo-write.d.ts +3 -0
- package/package.json +8 -8
- package/scripts/capture-sticky-viewport-showcase.ts +131 -5
- package/scripts/verify-gjc-sdk-canonicalization.ts +128 -183
- package/scripts/verify-sticky-viewport-showcase.ts +620 -93
- package/src/async/job-manager.ts +430 -46
- package/src/config/model-profiles.ts +8 -0
- package/src/config/settings-schema.ts +17 -3
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +2 -0
- package/src/extensibility/extensions/runner.ts +80 -6
- package/src/extensibility/extensions/wrapper.ts +22 -15
- package/src/extensibility/runtime-skill-discovery.ts +4 -6
- package/src/gjc-runtime/launch-tmux.ts +309 -293
- package/src/gjc-runtime/managed-owner-supervisor.ts +6 -2
- package/src/gjc-runtime/psmux-detect.ts +52 -6
- package/src/gjc-runtime/team-launch.ts +50 -2
- package/src/gjc-runtime/team-runtime.ts +716 -251
- package/src/gjc-runtime/team-store.ts +25 -7
- package/src/gjc-runtime/team-workers.ts +161 -1
- package/src/gjc-runtime/tmux-common.ts +16 -4
- package/src/gjc-runtime/tmux-gc.ts +37 -5
- package/src/gjc-runtime/tmux-owner-isolation.ts +2 -0
- package/src/gjc-runtime/tmux-provider-context.ts +451 -0
- package/src/gjc-runtime/tmux-sessions.ts +409 -156
- package/src/gjc-runtime/ultragoal-change-set.ts +90 -44
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +7 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +360 -156
- package/src/internal-urls/docs-index.generated.ts +4 -4
- package/src/internal-urls/local-protocol.ts +39 -18
- package/src/modes/acp/acp-agent.ts +27 -13
- package/src/modes/components/gjc-bundle-settings.ts +2 -0
- package/src/modes/components/plugin-settings.ts +5 -0
- package/src/modes/components/settings-selector.ts +4 -0
- package/src/modes/controllers/selector-controller.ts +1 -0
- package/src/prompts/tools/monitor.md +4 -4
- package/src/sdk/broker/broker.ts +93 -10
- package/src/sdk/broker/lifecycle-ledger.ts +227 -11
- package/src/sdk/broker/lifecycle.ts +691 -92
- package/src/sdk/bus/chat-daemon-control.ts +30 -6
- package/src/sdk/bus/index.ts +23 -6
- package/src/sdk/bus/telegram-daemon-contract.ts +2 -2
- package/src/sdk/bus/telegram-daemon.ts +283 -44
- package/src/sdk/bus/topic-registry.ts +133 -10
- package/src/sdk/session.ts +7 -6
- package/src/session/agent-session.ts +752 -339
- package/src/session/attempt-record-store.ts +106 -0
- package/src/session/internal/managed-session-scope.ts +252 -67
- package/src/session/internal/managed-session-storage.ts +1 -0
- package/src/session/session-manager.ts +7 -0
- package/src/session/session-storage.ts +146 -24
- package/src/task/index.ts +230 -19
- package/src/task/provider-retry-status.ts +4 -1
- package/src/task/receipt.ts +2 -0
- package/src/task/types.ts +10 -0
- package/src/tools/monitor.ts +7 -1
- package/src/tools/output-meta.ts +10 -2
- package/src/tools/subagent.ts +97 -75
- package/src/tools/todo-write.ts +47 -0
|
@@ -23,6 +23,7 @@ export type BrokerErrorCode = "idempotency_conflict" | "terminal_uncertain" | "b
|
|
|
23
23
|
export type BrokerCleanupIdentity = {
|
|
24
24
|
dev: string;
|
|
25
25
|
ino: string;
|
|
26
|
+
nlink?: string;
|
|
26
27
|
size: number;
|
|
27
28
|
mtimeNs: string;
|
|
28
29
|
sha256: string;
|
|
@@ -51,6 +52,7 @@ export type BrokerArtifactTree = {
|
|
|
51
52
|
};
|
|
52
53
|
export type BrokerCleanupEvidence = {
|
|
53
54
|
phase: "artifacts" | "transcript" | "metadata" | "lifecycle";
|
|
55
|
+
cleanupReceiptVersion?: 1;
|
|
54
56
|
/** Ledger-bound deletion target; never reconstructed from a retry request. */
|
|
55
57
|
sessionsRoot?: string;
|
|
56
58
|
transcriptPath?: string;
|
|
@@ -59,6 +61,10 @@ export type BrokerCleanupEvidence = {
|
|
|
59
61
|
sessionId?: string;
|
|
60
62
|
artifactsIdentity?: BrokerCleanupIdentity;
|
|
61
63
|
transcriptIdentity?: BrokerCleanupIdentity;
|
|
64
|
+
transcriptParentIdentity?: {
|
|
65
|
+
dev: string;
|
|
66
|
+
ino: string;
|
|
67
|
+
};
|
|
62
68
|
/** Identity-bound lifecycle metadata marker retained when exact cleanup is deferred. */
|
|
63
69
|
metadataIdentity?: BrokerCleanupIdentity;
|
|
64
70
|
metadataPath?: string;
|
|
@@ -71,9 +77,17 @@ export type BrokerCleanupEvidence = {
|
|
|
71
77
|
/** Append-only terminal proof for lifecycle metadata cleanup. */
|
|
72
78
|
metadataCompleted?: true;
|
|
73
79
|
detachedArtifactsPath?: string;
|
|
80
|
+
retainedArtifactsSuccessorPath?: string;
|
|
81
|
+
retainedArtifactsPlaceholderPath?: string;
|
|
82
|
+
retainedArtifactsUnknownPath?: string;
|
|
83
|
+
retainedArtifactsSideAuthority?: "none" | "retained";
|
|
74
84
|
detachedTranscriptPath?: string;
|
|
85
|
+
retainedTranscriptSuccessorPath?: string;
|
|
86
|
+
retainedTranscriptPlaceholderPath?: string;
|
|
87
|
+
retainedTranscriptUnknownPath?: string;
|
|
75
88
|
/** Durable proof that artifact cleanup completed before transcript mutation. */
|
|
76
89
|
artifactsRemoved?: boolean;
|
|
90
|
+
artifactsAbsentAtAuthorization?: true;
|
|
77
91
|
/** Preauthorized no-replace artifact quarantine path persisted before detach. */
|
|
78
92
|
plannedArtifactsPath?: string;
|
|
79
93
|
/** Identity-bound artifact tree authority persisted before broker detach and replayed exactly. */
|
|
@@ -82,6 +96,10 @@ export type BrokerCleanupEvidence = {
|
|
|
82
96
|
plannedTranscriptPath?: string;
|
|
83
97
|
/** Fully identity-bound startup-failure cleanup plan, persisted before any detach. */
|
|
84
98
|
lifecycleFiles?: BrokerLifecycleCleanupFile[];
|
|
99
|
+
lifecycleParentIdentity?: {
|
|
100
|
+
dev: string;
|
|
101
|
+
ino: string;
|
|
102
|
+
};
|
|
85
103
|
/** Delete metadata receipts authorize only the canonical marker/ready sibling pair. */
|
|
86
104
|
lifecycleDeleteMetadata?: true;
|
|
87
105
|
};
|
|
@@ -66,6 +66,11 @@ export interface LifecycleLedgerEntry {
|
|
|
66
66
|
endpointGeneration?: number;
|
|
67
67
|
responseDigest?: string;
|
|
68
68
|
response?: unknown;
|
|
69
|
+
unresolvedCleanupResponse?: unknown;
|
|
70
|
+
unresolvedCleanupResponseDigest?: string;
|
|
71
|
+
uncertainCleanupSessionId?: string;
|
|
72
|
+
uncertainCleanupSessionIds?: string[];
|
|
73
|
+
uncertainCleanupAllSessions?: true;
|
|
69
74
|
ts: number;
|
|
70
75
|
}
|
|
71
76
|
export type BeginResult = {
|
|
@@ -105,5 +110,13 @@ export declare class LifecycleLedger {
|
|
|
105
110
|
begin(identity: string, requestHash: string): Promise<BeginResult>;
|
|
106
111
|
transition(identity: string, state: LifecycleState, fields?: Omit<Partial<LifecycleLedgerEntry>, "identity" | "requestHash" | "state" | "ts">): Promise<LifecycleLedgerEntry>;
|
|
107
112
|
assertSupportedStateVersions(): Promise<void>;
|
|
113
|
+
findCleanupPendingByDeleteTarget(target: {
|
|
114
|
+
sessionId: string;
|
|
115
|
+
sessionsRoot?: string;
|
|
116
|
+
transcriptPath: string;
|
|
117
|
+
cwd: string;
|
|
118
|
+
}, excludingIdentity: string): LifecycleLedgerEntry | undefined;
|
|
119
|
+
findCleanupPendingBySessionId(sessionId: string, excludingIdentity: string): LifecycleLedgerEntry | undefined;
|
|
120
|
+
hasUncertainCleanupForSession(sessionId: string, excludingIdentity: string): boolean;
|
|
108
121
|
get(identity: string): LifecycleLedgerEntry | undefined;
|
|
109
122
|
}
|
|
@@ -92,6 +92,7 @@ export declare function readSessionLifecycleFailureForTest(root: string, id: str
|
|
|
92
92
|
effectMarker: string;
|
|
93
93
|
incarnation: string;
|
|
94
94
|
}): Promise<SdkStartupFailure | undefined>;
|
|
95
|
+
export declare function canonicalDeleteLocatorPath(pathname: string): string;
|
|
95
96
|
export interface LifecycleExecutionOutcome {
|
|
96
97
|
response: BrokerResponse;
|
|
97
98
|
durableEffects?: LifecycleDurableEffectsReceipt;
|
|
@@ -20,9 +20,8 @@ export type ChatDaemonAction = "stop" | "reload";
|
|
|
20
20
|
* applies the current notification configuration directly when starting chat
|
|
21
21
|
* daemon transports. Generation 16 applies Telegram sound-policy configuration
|
|
22
22
|
* through shared notification parsing. Generation 17 bound managed-session
|
|
23
|
-
* replacement to exact native filesystem authority; generation 18
|
|
24
|
-
* binding
|
|
25
|
-
* the lifecycle contract moving strictly forward.
|
|
23
|
+
* replacement to exact native filesystem authority; generation 18 retired that
|
|
24
|
+
* binding, and generation 19 binds exact cleanup to parent/link-count authority.
|
|
26
25
|
*/
|
|
27
26
|
export declare const CHAT_DAEMON_GENERATIONS: Readonly<Record<ChatDaemonKind, number>>;
|
|
28
27
|
export declare function chatDaemonGeneration(kind: ChatDaemonKind): number;
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* Enable with Settings notifications config, `GJC_NOTIFICATIONS=1` (a token is
|
|
18
18
|
* generated), or `GJC_NOTIFICATIONS_TOKEN`.
|
|
19
19
|
*/
|
|
20
|
+
import { type RunSettlementProof } from "@gajae-code/agent-core";
|
|
20
21
|
import type { Tool } from "@gajae-code/ai";
|
|
21
22
|
import { NotificationServer } from "@gajae-code/natives";
|
|
22
23
|
import { Settings } from "../../config/settings";
|
|
@@ -33,6 +34,9 @@ import { NotificationSessionController } from "./session-control";
|
|
|
33
34
|
import { type EnsureDaemonResult, type RegisterNotificationRootResult } from "./telegram-daemon";
|
|
34
35
|
export type { IdentityControlSuccessPathInput, IdentityControlTerminalPathInput, TerminalSendOutcome, } from "./control-drain-lease";
|
|
35
36
|
export { isNativeControlDrainAvailable, runIdentityControlSuccessPath, runIdentityControlTerminalPath, } from "./control-drain-lease";
|
|
37
|
+
export declare function formatPromptSettlementDiagnostic(proof: Extract<RunSettlementProof, {
|
|
38
|
+
status: "unfenced";
|
|
39
|
+
}>, now?: number): string;
|
|
36
40
|
/** Where a `session_create` should run. Discriminated by `kind`. */
|
|
37
41
|
export type SessionCreateTarget = {
|
|
38
42
|
kind: "existing_path";
|
|
@@ -47,9 +47,9 @@ export declare const NOTIFICATION_PROTOCOL_VERSION = 3;
|
|
|
47
47
|
* user-created topic adoption (forum-topic folder picker). Generation 36 bound
|
|
48
48
|
* managed-session replacement to exact native filesystem authority; generation
|
|
49
49
|
* 37 retires that binding (revert of #3489, which stalled POSIX artifact
|
|
50
|
-
* cleanup)
|
|
50
|
+
* cleanup); generation 38 binds exact cleanup to parent and link-count authority.
|
|
51
51
|
*/
|
|
52
|
-
export declare const DAEMON_GENERATION =
|
|
52
|
+
export declare const DAEMON_GENERATION = 38;
|
|
53
53
|
/**
|
|
54
54
|
* Serving-compatibility boundary for daemon lifecycle requests. Epoch 1 covers
|
|
55
55
|
* all builds published before this field existed; epoch 2 covered generation 29;
|
|
@@ -61,11 +61,13 @@ export interface TelegramDaemonFs {
|
|
|
61
61
|
size?: number;
|
|
62
62
|
dev?: number;
|
|
63
63
|
ino?: number;
|
|
64
|
+
/** Hard-link count; required to prove a staging temp has no second name. */
|
|
65
|
+
nlink?: number;
|
|
64
66
|
ctimeMs?: number;
|
|
65
67
|
isDirectory?: () => boolean;
|
|
66
68
|
}>;
|
|
67
69
|
readEndpointFile?(path: string): Promise<NotificationEndpointFile>;
|
|
68
|
-
exactUnlink?(path: string, identity: NotificationEndpointFileIdentity): Promise<NotificationExactUnlinkResult>;
|
|
70
|
+
exactUnlink?(path: string, identity: NotificationEndpointFileIdentity, quarantineName?: string): Promise<NotificationExactUnlinkResult>;
|
|
69
71
|
}
|
|
70
72
|
export interface SpawnResult {
|
|
71
73
|
pid?: number;
|
|
@@ -281,11 +283,26 @@ export declare function withNotificationRootRegistryFence(input: {
|
|
|
281
283
|
* (#2956). Nothing previously reaped these; they accumulate in the notifications
|
|
282
284
|
* directory across ownership transitions.
|
|
283
285
|
*/
|
|
284
|
-
export declare const NOTIFICATION_LEAK_ARTIFACT_PREFIXES: readonly [".gjc-delete-daemon-transition-", ".gjc-exact-unlink-placeholder-", ".gjc-delete-notification-endpoint-"];
|
|
286
|
+
export declare const NOTIFICATION_LEAK_ARTIFACT_PREFIXES: readonly [".gjc-delete-daemon-transition-", ".gjc-exact-unlink-placeholder-", ".gjc-delete-notification-endpoint-", ".gjc-delete-notification-staging-temp-"];
|
|
285
287
|
/** Grace window before a leak artifact is reaped (covers in-flight unlinks). */
|
|
286
288
|
export declare const NOTIFICATION_LEAK_ARTIFACT_GRACE_MS: number;
|
|
287
289
|
/** True when a path is permanently gone (not a transient I/O blip). */
|
|
288
290
|
export declare function isPermanentMissingPathError(error: unknown): boolean;
|
|
291
|
+
/** A publication staging claim recovered from an abandoned temp's name. */
|
|
292
|
+
export interface NotificationStagingTempClaim {
|
|
293
|
+
/** Published sibling this temp was staged for. */
|
|
294
|
+
destination: string;
|
|
295
|
+
/** PID of the process that staged it. */
|
|
296
|
+
pid: number;
|
|
297
|
+
/** Wall-clock ms the publisher recorded when it staged the temp. */
|
|
298
|
+
stagedAtMs: number;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Recover the publication claim encoded in a staging temp's name, or
|
|
302
|
+
* `undefined` when `name` is not a staging temp or its PID/timestamp fields are
|
|
303
|
+
* not usable integers. An unparseable claim is never reaped.
|
|
304
|
+
*/
|
|
305
|
+
export declare function parseNotificationStagingTemp(name: string): NotificationStagingTempClaim | undefined;
|
|
289
306
|
export declare function isNotificationLeakArtifactName(name: string): boolean;
|
|
290
307
|
/**
|
|
291
308
|
* Drop permanently missing scan roots from the durable registry under the roots
|
|
@@ -302,13 +319,16 @@ export declare function pruneMissingNotificationRoots(input: {
|
|
|
302
319
|
}>;
|
|
303
320
|
/**
|
|
304
321
|
* Reap retained exact-unlink / ownership-transition quarantine files older than
|
|
305
|
-
* the grace window from the notifications directory
|
|
322
|
+
* the grace window from the notifications directory, plus publication staging
|
|
323
|
+
* temps whose publisher is provably dead.
|
|
306
324
|
*/
|
|
307
325
|
export declare function reapStaleNotificationArtifacts(input: {
|
|
308
326
|
settings: Settings;
|
|
309
327
|
fs?: TelegramDaemonFs;
|
|
310
328
|
now?: () => number;
|
|
311
329
|
graceMs?: number;
|
|
330
|
+
/** Liveness seam used to prove a staging temp's publisher is dead. */
|
|
331
|
+
pidAlive?: (pid: number) => boolean;
|
|
312
332
|
}): Promise<{
|
|
313
333
|
removed: string[];
|
|
314
334
|
skipped: number;
|
|
@@ -322,6 +342,8 @@ export declare function healTelegramDaemonNotificationState(input: {
|
|
|
322
342
|
fs?: TelegramDaemonFs;
|
|
323
343
|
now?: () => number;
|
|
324
344
|
graceMs?: number;
|
|
345
|
+
/** Liveness seam used to prove a staging temp's publisher is dead. */
|
|
346
|
+
pidAlive?: (pid: number) => boolean;
|
|
325
347
|
}): Promise<{
|
|
326
348
|
prunedRoots: string[];
|
|
327
349
|
removedArtifacts: string[];
|
|
@@ -92,6 +92,17 @@ export interface TopicDeleteAuthoritySnapshot {
|
|
|
92
92
|
/** Exact fenced record, retained to restore an in-memory tombstone after a failed clear publication. */
|
|
93
93
|
record?: TopicRecord;
|
|
94
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Proof that a definite delete was settled in memory and still owes its durable
|
|
97
|
+
* commit. Handed back only by a settlement that actually happened, so a refused
|
|
98
|
+
* settlement structurally cannot be followed by a rollback.
|
|
99
|
+
*/
|
|
100
|
+
export interface TopicSettledDelete {
|
|
101
|
+
sessionId: string;
|
|
102
|
+
topicId: string;
|
|
103
|
+
/** Authority epoch proven current when the record was removed. */
|
|
104
|
+
settledEpoch: number;
|
|
105
|
+
}
|
|
95
106
|
export declare function emptyTopicRegistryState(): TopicRegistryState;
|
|
96
107
|
/**
|
|
97
108
|
* In-memory registry over a serialisable state. Topic creation is injected via
|
|
@@ -199,7 +210,14 @@ export declare class TopicRegistry {
|
|
|
199
210
|
captureDeleteAuthority(sessionId: string): TopicDeleteAuthoritySnapshot;
|
|
200
211
|
/** Restore a failed delete fence only while its exact authority mutation remains current. */
|
|
201
212
|
restoreDeleteAuthority(snapshot: TopicDeleteAuthoritySnapshot): boolean;
|
|
202
|
-
/**
|
|
213
|
+
/**
|
|
214
|
+
* Restore the exact delete fence after a failed compensation publication.
|
|
215
|
+
*
|
|
216
|
+
* Settlement rebuilds derived routes, which can make a surviving colliding
|
|
217
|
+
* record routable. Rebuild again on successful restoration so the reinstated
|
|
218
|
+
* fence re-quarantines the topic id instead of leaving inbound routing open to
|
|
219
|
+
* the collision partner despite the restored fence.
|
|
220
|
+
*/
|
|
203
221
|
restoreDeleteFence(snapshot: TopicDeleteAuthoritySnapshot): boolean;
|
|
204
222
|
/** Fence new work before the remote delete starts, including an absent in-flight create. */
|
|
205
223
|
beginDelete(sessionId: string): TopicRecord | undefined;
|
|
@@ -209,8 +227,50 @@ export declare class TopicRegistry {
|
|
|
209
227
|
fenceAcceptedCreateForLease(sessionId: string, topicId: string, creationLeaseEpoch: number, now?: () => number, name?: string, binding?: TopicEndpointBinding): TopicRecord | undefined;
|
|
210
228
|
/** Wait for a revoked create to settle before admitting a later lifecycle epoch. */
|
|
211
229
|
awaitInflight(sessionId: string): Promise<void>;
|
|
212
|
-
/**
|
|
213
|
-
|
|
230
|
+
/**
|
|
231
|
+
* Phase 1 of settling a definite remote delete: remove the record while
|
|
232
|
+
* deliberately RETAINING its topic-id quarantine.
|
|
233
|
+
*
|
|
234
|
+
* `dispatchedAuthorityEpoch` is the authority epoch the caller held when it
|
|
235
|
+
* dispatched the remote delete. Settlement requires that epoch to still equal
|
|
236
|
+
* both the record's own authority epoch and the registry's current epoch for
|
|
237
|
+
* the session, so a held earlier delete can never settle a newer fence: if a
|
|
238
|
+
* scan or close-started delete re-fenced the same session/topic after this
|
|
239
|
+
* delete was dispatched, the stale definite result is refused and the newer
|
|
240
|
+
* `delete_pending` record plus its topic-id quarantine stay intact.
|
|
241
|
+
*
|
|
242
|
+
* An epoch outside the safe-integer range cannot identify a generation, and at
|
|
243
|
+
* `Number.MAX_SAFE_INTEGER` epoch advancement has saturated so distinct
|
|
244
|
+
* generations are no longer distinguishable. Both fail closed: settlement can
|
|
245
|
+
* no longer be proven fresh, so the fence is kept.
|
|
246
|
+
*
|
|
247
|
+
* Derived routing tables are deliberately NOT rebuilt here. Until the cleared
|
|
248
|
+
* snapshot is durably persisted the clear is not authoritative, so publishing
|
|
249
|
+
* routes now would make a colliding survivor routable (and the settled id
|
|
250
|
+
* adoptable) during the held write, and a failed persist would re-quarantine
|
|
251
|
+
* too late. Publish with {@link commitSettledDelete} once the persist
|
|
252
|
+
* succeeds, or undo with {@link rollbackSettledDelete} when it fails.
|
|
253
|
+
*/
|
|
254
|
+
settleDelete(sessionId: string, topicId: string, dispatchedAuthorityEpoch: number): TopicSettledDelete | undefined;
|
|
255
|
+
/**
|
|
256
|
+
* Phase 2: publish derived routing tables once the cleared state is durable.
|
|
257
|
+
*
|
|
258
|
+
* Only here does the settled topic id lose its quarantine, so a surviving
|
|
259
|
+
* colliding record becomes routable and a settled id becomes adoptable without
|
|
260
|
+
* waiting for a daemon restart.
|
|
261
|
+
*/
|
|
262
|
+
commitSettledDelete(settled: TopicSettledDelete): boolean;
|
|
263
|
+
/**
|
|
264
|
+
* Compare-and-swap undo for a settlement whose durable clear failed.
|
|
265
|
+
*
|
|
266
|
+
* Restoration applies only while the registry still holds exactly the state
|
|
267
|
+
* that this settlement produced: the settlement is still awaiting commit, the
|
|
268
|
+
* session still has no record, and the session epoch is still the settled
|
|
269
|
+
* epoch. Any mismatch means a newer generation intervened, so the restore is
|
|
270
|
+
* refused and the newer state is left untouched. A refused settlement produced
|
|
271
|
+
* no token, so it can never reach this path.
|
|
272
|
+
*/
|
|
273
|
+
rollbackSettledDelete(settled: TopicSettledDelete): boolean;
|
|
214
274
|
/** Remove a topic record immediately for local/test cleanup compatibility. */
|
|
215
275
|
delete(sessionId: string): boolean;
|
|
216
276
|
/** Serialise active records plus unpublished staged creates for atomic commit. */
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
* Modes use this class and add their own I/O layer on top.
|
|
14
14
|
*/
|
|
15
15
|
import { type Agent, type AgentContext, type AgentEvent, type AgentLoopConfig, type AgentMessage, type AgentState, type AgentTool, type MidRunMaintenanceOutcome, type RunSettlementProof, type StablePrefixSnapshot, ThinkingLevel } from "@gajae-code/agent-core";
|
|
16
|
+
import type { AttemptScope } from "@gajae-code/agent-core/attempt-scope";
|
|
16
17
|
import { type CompactionResult, type EmergencyCompactionSample } from "@gajae-code/agent-core/compaction";
|
|
17
|
-
import type { AssistantMessage, Effort, ImageContent, Message, MessageAttribution, Model, ProviderSessionState, ServiceTier, SimpleStreamOptions, TextContent, ToolCall, ToolChoice, Usage, UsageReport } from "@gajae-code/ai";
|
|
18
|
+
import type { AssistantMessage, AttemptScopeRef, Effort, ImageContent, Message, MessageAttribution, Model, ProviderSessionState, ServiceTier, SimpleStreamOptions, TextContent, ToolCall, ToolChoice, Usage, UsageReport } from "@gajae-code/ai";
|
|
18
19
|
import { type BtwTextExchange } from "./btw-contract";
|
|
19
20
|
export interface ForkContextSeedMetadata {
|
|
20
21
|
sourceSessionId: string;
|
|
@@ -231,7 +232,7 @@ export interface AgentSessionConfig {
|
|
|
231
232
|
/** Tool-session factory context used to lazily attach workflow-gate-only tools. */
|
|
232
233
|
workflowGateToolSession?: ToolSession;
|
|
233
234
|
/** Current session pre-LLM message transform pipeline */
|
|
234
|
-
transformContext?: (messages: AgentMessage[], signal?: AbortSignal) => AgentMessage[] | Promise<AgentMessage[]>;
|
|
235
|
+
transformContext?: (messages: AgentMessage[], signal?: AbortSignal, scope?: AttemptScopeRef) => AgentMessage[] | Promise<AgentMessage[]>;
|
|
235
236
|
/** Provider payload hook used by the active session request path */
|
|
236
237
|
onPayload?: SimpleStreamOptions["onPayload"];
|
|
237
238
|
/** Provider response hook used by the active session request path */
|
|
@@ -815,9 +816,9 @@ export declare class AgentSession {
|
|
|
815
816
|
/** Build display context from an unpublished successor without changing active session state. @internal */
|
|
816
817
|
buildPreparedDisplaySessionContext(prepared: PreparedNewSession): SessionContext;
|
|
817
818
|
/** Convert session messages using the same pre-LLM pipeline as the active session. */
|
|
818
|
-
convertMessagesToLlm(messages: AgentMessage[], signal?: AbortSignal): Promise<Message[]>;
|
|
819
|
+
convertMessagesToLlm(messages: AgentMessage[], signal?: AbortSignal, scope?: AttemptScope): Promise<Message[]>;
|
|
819
820
|
/** Apply session-level stream hooks to a direct side request. */
|
|
820
|
-
prepareSimpleStreamOptions(options: SimpleStreamOptions, provider?: string): SimpleStreamOptions;
|
|
821
|
+
prepareSimpleStreamOptions(options: SimpleStreamOptions, provider?: string, scope?: AttemptScope): SimpleStreamOptions;
|
|
821
822
|
/** Current steering mode */
|
|
822
823
|
get steeringMode(): "all" | "one-at-a-time";
|
|
823
824
|
/** Current follow-up mode */
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AttemptScope, AttemptScopeAuthority } from "@gajae-code/agent-core/attempt-scope";
|
|
2
|
+
export type AttemptExecutionState = "unknown" | "clean" | "executed";
|
|
3
|
+
/**
|
|
4
|
+
* Tracks whether an attempt has had an extension handler delivered to it.
|
|
5
|
+
*
|
|
6
|
+
* Records are deliberately established in two phases: allocation registers an
|
|
7
|
+
* `unknown` record, then the session marks it `clean` immediately before the
|
|
8
|
+
* first handler-capable delivery can occur. The runner changes a clean record
|
|
9
|
+
* to `executed` immediately before invoking its first handler.
|
|
10
|
+
*/
|
|
11
|
+
export declare class AttemptRecordStore {
|
|
12
|
+
#private;
|
|
13
|
+
constructor(authority: AttemptScopeAuthority);
|
|
14
|
+
register(scope: AttemptScope): boolean;
|
|
15
|
+
establishClean(scope: AttemptScope): boolean;
|
|
16
|
+
markExecuted(scope: AttemptScope): boolean;
|
|
17
|
+
isClean(scope: AttemptScope): boolean;
|
|
18
|
+
retire(scope: AttemptScope): boolean;
|
|
19
|
+
}
|
|
@@ -3,6 +3,7 @@ import { type ManagedDirectoryRoot } from "./internal/managed-session-storage";
|
|
|
3
3
|
export interface SessionStorageStat {
|
|
4
4
|
dev: bigint;
|
|
5
5
|
ino: bigint;
|
|
6
|
+
nlink?: bigint;
|
|
6
7
|
size: number;
|
|
7
8
|
mtimeMs: number;
|
|
8
9
|
mtimeNs: bigint;
|
|
@@ -148,6 +149,7 @@ export interface SessionStorage {
|
|
|
148
149
|
export interface SessionStorageFileIdentity {
|
|
149
150
|
dev: bigint;
|
|
150
151
|
ino: bigint;
|
|
152
|
+
nlink?: bigint;
|
|
151
153
|
size: number;
|
|
152
154
|
mtimeNs: bigint;
|
|
153
155
|
sha256: string;
|
|
@@ -181,12 +183,17 @@ export interface VerifiedSessionDeleteTarget {
|
|
|
181
183
|
cwd: string;
|
|
182
184
|
/** Expected transcript file `(dev, ino)` captured at authorization. */
|
|
183
185
|
transcriptIdentity: SessionStorageFileIdentity;
|
|
186
|
+
transcriptParentIdentity?: {
|
|
187
|
+
dev: bigint;
|
|
188
|
+
ino: bigint;
|
|
189
|
+
};
|
|
184
190
|
/**
|
|
185
191
|
* For retry after an `artifacts` `cleanup_pending`: the recorded artifact
|
|
186
192
|
* directory identity to re-accept. A replacement/different artifact directory
|
|
187
193
|
* fails closed. Omit on first attempt or to accept recorded absence.
|
|
188
194
|
*/
|
|
189
195
|
expectedArtifactsIdentity?: SessionStorageFileIdentity;
|
|
196
|
+
artifactsAbsentAtAuthorization?: true;
|
|
190
197
|
/** Stable native recursive-tree evidence captured before artifact detachment. */
|
|
191
198
|
expectedArtifactsTree?: NativeDirectoryTreeSnapshot;
|
|
192
199
|
/** Identity-bound quarantine path retained when recursive artifact cleanup failed. */
|
|
@@ -256,6 +263,7 @@ type NativeDirectoryTreeEntry = {
|
|
|
256
263
|
kind: string;
|
|
257
264
|
dev: string;
|
|
258
265
|
ino: string;
|
|
266
|
+
nlink: string;
|
|
259
267
|
size: string;
|
|
260
268
|
mtimeNs: string;
|
|
261
269
|
ctimeNs: string;
|
|
@@ -65,6 +65,10 @@ export declare const taskItemSchema: z.ZodObject<{
|
|
|
65
65
|
head: z.ZodOptional<z.ZodString>;
|
|
66
66
|
branch: z.ZodOptional<z.ZodString>;
|
|
67
67
|
}, z.core.$strict>>;
|
|
68
|
+
duplicate_policy: z.ZodOptional<z.ZodEnum<{
|
|
69
|
+
supersede: "supersede";
|
|
70
|
+
warn: "warn";
|
|
71
|
+
}>>;
|
|
68
72
|
}, z.core.$strip>;
|
|
69
73
|
export type TaskItem = z.infer<typeof taskItemSchema>;
|
|
70
74
|
export declare const taskSchema: z.ZodObject<{
|
|
@@ -93,6 +97,10 @@ export declare const taskSchema: z.ZodObject<{
|
|
|
93
97
|
head: z.ZodOptional<z.ZodString>;
|
|
94
98
|
branch: z.ZodOptional<z.ZodString>;
|
|
95
99
|
}, z.core.$strict>>;
|
|
100
|
+
duplicate_policy: z.ZodOptional<z.ZodEnum<{
|
|
101
|
+
supersede: "supersede";
|
|
102
|
+
warn: "warn";
|
|
103
|
+
}>>;
|
|
96
104
|
}, z.core.$strip>>;
|
|
97
105
|
spawnPlan: z.ZodOptional<z.ZodObject<{
|
|
98
106
|
whyParallel: z.ZodString;
|
|
@@ -128,6 +136,10 @@ export declare const taskSchemaNoIsolation: z.ZodObject<{
|
|
|
128
136
|
head: z.ZodOptional<z.ZodString>;
|
|
129
137
|
branch: z.ZodOptional<z.ZodString>;
|
|
130
138
|
}, z.core.$strict>>;
|
|
139
|
+
duplicate_policy: z.ZodOptional<z.ZodEnum<{
|
|
140
|
+
supersede: "supersede";
|
|
141
|
+
warn: "warn";
|
|
142
|
+
}>>;
|
|
131
143
|
}, z.core.$strip>>;
|
|
132
144
|
spawnPlan: z.ZodOptional<z.ZodObject<{
|
|
133
145
|
whyParallel: z.ZodString;
|
|
@@ -163,6 +175,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
|
|
|
163
175
|
head: z.ZodOptional<z.ZodString>;
|
|
164
176
|
branch: z.ZodOptional<z.ZodString>;
|
|
165
177
|
}, z.core.$strict>>;
|
|
178
|
+
duplicate_policy: z.ZodOptional<z.ZodEnum<{
|
|
179
|
+
supersede: "supersede";
|
|
180
|
+
warn: "warn";
|
|
181
|
+
}>>;
|
|
166
182
|
}, z.core.$strip>>;
|
|
167
183
|
spawnPlan: z.ZodOptional<z.ZodObject<{
|
|
168
184
|
whyParallel: z.ZodString;
|
|
@@ -197,6 +213,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
|
|
|
197
213
|
head: z.ZodOptional<z.ZodString>;
|
|
198
214
|
branch: z.ZodOptional<z.ZodString>;
|
|
199
215
|
}, z.core.$strict>>;
|
|
216
|
+
duplicate_policy: z.ZodOptional<z.ZodEnum<{
|
|
217
|
+
supersede: "supersede";
|
|
218
|
+
warn: "warn";
|
|
219
|
+
}>>;
|
|
200
220
|
}, z.core.$strip>>;
|
|
201
221
|
spawnPlan: z.ZodOptional<z.ZodObject<{
|
|
202
222
|
whyParallel: z.ZodString;
|
|
@@ -231,6 +251,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
|
|
|
231
251
|
head: z.ZodOptional<z.ZodString>;
|
|
232
252
|
branch: z.ZodOptional<z.ZodString>;
|
|
233
253
|
}, z.core.$strict>>;
|
|
254
|
+
duplicate_policy: z.ZodOptional<z.ZodEnum<{
|
|
255
|
+
supersede: "supersede";
|
|
256
|
+
warn: "warn";
|
|
257
|
+
}>>;
|
|
234
258
|
}, z.core.$strip>>;
|
|
235
259
|
spawnPlan: z.ZodOptional<z.ZodObject<{
|
|
236
260
|
whyParallel: z.ZodString;
|
|
@@ -265,6 +289,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
|
|
|
265
289
|
head: z.ZodOptional<z.ZodString>;
|
|
266
290
|
branch: z.ZodOptional<z.ZodString>;
|
|
267
291
|
}, z.core.$strict>>;
|
|
292
|
+
duplicate_policy: z.ZodOptional<z.ZodEnum<{
|
|
293
|
+
supersede: "supersede";
|
|
294
|
+
warn: "warn";
|
|
295
|
+
}>>;
|
|
268
296
|
}, z.core.$strip>>;
|
|
269
297
|
spawnPlan: z.ZodOptional<z.ZodObject<{
|
|
270
298
|
whyParallel: z.ZodString;
|
|
@@ -299,6 +327,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
|
|
|
299
327
|
head: z.ZodOptional<z.ZodString>;
|
|
300
328
|
branch: z.ZodOptional<z.ZodString>;
|
|
301
329
|
}, z.core.$strict>>;
|
|
330
|
+
duplicate_policy: z.ZodOptional<z.ZodEnum<{
|
|
331
|
+
supersede: "supersede";
|
|
332
|
+
warn: "warn";
|
|
333
|
+
}>>;
|
|
302
334
|
}, z.core.$strip>>;
|
|
303
335
|
spawnPlan: z.ZodOptional<z.ZodObject<{
|
|
304
336
|
whyParallel: z.ZodString;
|
|
@@ -333,6 +365,10 @@ declare const ALL_TASK_SCHEMAS: readonly [z.ZodObject<{
|
|
|
333
365
|
head: z.ZodOptional<z.ZodString>;
|
|
334
366
|
branch: z.ZodOptional<z.ZodString>;
|
|
335
367
|
}, z.core.$strict>>;
|
|
368
|
+
duplicate_policy: z.ZodOptional<z.ZodEnum<{
|
|
369
|
+
supersede: "supersede";
|
|
370
|
+
warn: "warn";
|
|
371
|
+
}>>;
|
|
336
372
|
}, z.core.$strip>>;
|
|
337
373
|
spawnPlan: z.ZodOptional<z.ZodObject<{
|
|
338
374
|
whyParallel: z.ZodString;
|
|
@@ -357,6 +393,7 @@ export interface TaskParams {
|
|
|
357
393
|
spawnPlan?: SpawnPlanReceipt;
|
|
358
394
|
tasks: TaskItem[];
|
|
359
395
|
isolated?: boolean;
|
|
396
|
+
duplicate_policy?: "warn" | "supersede";
|
|
360
397
|
}
|
|
361
398
|
/** A code review finding reported by the reviewer agent */
|
|
362
399
|
export interface ReviewFinding {
|
|
@@ -502,6 +539,11 @@ export interface TaskRecoveryArtifactRef {
|
|
|
502
539
|
/** Recovery artifacts remain readable for the parent session lifetime. */
|
|
503
540
|
durability: "session";
|
|
504
541
|
}
|
|
542
|
+
/** Bounded duplicate-launch disposition carried into task receipts. */
|
|
543
|
+
export interface DuplicateDisposition {
|
|
544
|
+
action: "warned" | "superseded";
|
|
545
|
+
predecessorIds: string[];
|
|
546
|
+
}
|
|
505
547
|
export interface TaskPersistenceResult {
|
|
506
548
|
outcome: "applied" | "no_changes" | "recovery_available";
|
|
507
549
|
ownerWorktreeApplied: boolean;
|
|
@@ -537,6 +579,7 @@ export interface SingleResult {
|
|
|
537
579
|
setupFailure?: SetupFailureSummary;
|
|
538
580
|
aborted?: boolean;
|
|
539
581
|
abortReason?: string;
|
|
582
|
+
duplicateDisposition?: DuplicateDisposition;
|
|
540
583
|
paused?: boolean;
|
|
541
584
|
/** Aggregated usage from the subprocess, accumulated incrementally from message_end events. */
|
|
542
585
|
usage?: Usage;
|
|
@@ -16,6 +16,11 @@ declare const subagentSchema: z.ZodObject<{
|
|
|
16
16
|
id: z.ZodOptional<z.ZodString>;
|
|
17
17
|
message: z.ZodOptional<z.ZodString>;
|
|
18
18
|
pause: z.ZodOptional<z.ZodBoolean>;
|
|
19
|
+
condition: z.ZodOptional<z.ZodEnum<{
|
|
20
|
+
all_terminal: "all_terminal";
|
|
21
|
+
any_terminal: "any_terminal";
|
|
22
|
+
}>>;
|
|
23
|
+
heartbeat_ms: z.ZodOptional<z.ZodNumber>;
|
|
19
24
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
20
25
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
21
26
|
verbosity: z.ZodOptional<z.ZodEnum<{
|
|
@@ -65,6 +70,11 @@ export interface SubagentToolDetails {
|
|
|
65
70
|
subagents: SubagentSnapshot[];
|
|
66
71
|
/** Await outcome for a live await receipt; omitted when no wait was started. */
|
|
67
72
|
awaitOutcome?: SubagentAwaitOutcome;
|
|
73
|
+
waitOutcome?: "completed" | "timed_out_wait" | "interrupted";
|
|
74
|
+
condition?: "all_terminal" | "any_terminal";
|
|
75
|
+
heartbeatMs?: number;
|
|
76
|
+
terminalIds?: string[];
|
|
77
|
+
acknowledgedTerminalIds?: string[];
|
|
68
78
|
/** True only when the parent await was interrupted; the child was not cancelled. */
|
|
69
79
|
interrupted?: true;
|
|
70
80
|
}
|
|
@@ -89,6 +99,11 @@ export declare class SubagentTool implements AgentTool<typeof subagentSchema, Su
|
|
|
89
99
|
id: z.ZodOptional<z.ZodString>;
|
|
90
100
|
message: z.ZodOptional<z.ZodString>;
|
|
91
101
|
pause: z.ZodOptional<z.ZodBoolean>;
|
|
102
|
+
condition: z.ZodOptional<z.ZodEnum<{
|
|
103
|
+
all_terminal: "all_terminal";
|
|
104
|
+
any_terminal: "any_terminal";
|
|
105
|
+
}>>;
|
|
106
|
+
heartbeat_ms: z.ZodOptional<z.ZodNumber>;
|
|
92
107
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
93
108
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
94
109
|
verbosity: z.ZodOptional<z.ZodEnum<{
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@gajae-code/agent-core";
|
|
2
|
+
import type { RawArgumentValidationResult } from "@gajae-code/ai/types";
|
|
2
3
|
import type { Component } from "@gajae-code/tui";
|
|
3
4
|
import * as z from "zod/v4";
|
|
4
5
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
@@ -25,6 +26,7 @@ export interface TodoWriteToolDetails {
|
|
|
25
26
|
phases: TodoPhase[];
|
|
26
27
|
storage: "session" | "memory";
|
|
27
28
|
}
|
|
29
|
+
declare function validateRawTodoArguments(arguments_: Record<string, unknown>): RawArgumentValidationResult;
|
|
28
30
|
declare const todoWriteSchema: z.ZodObject<{
|
|
29
31
|
ops: z.ZodArray<z.ZodObject<{
|
|
30
32
|
op: z.ZodEnum<{
|
|
@@ -88,6 +90,7 @@ export declare class TodoWriteTool implements AgentTool<typeof todoWriteSchema,
|
|
|
88
90
|
text: z.ZodOptional<z.ZodString>;
|
|
89
91
|
}, z.core.$strip>>;
|
|
90
92
|
}, z.core.$strip>;
|
|
93
|
+
readonly rawArgumentValidation: typeof validateRawTodoArguments;
|
|
91
94
|
readonly concurrency = "exclusive";
|
|
92
95
|
readonly strict = true;
|
|
93
96
|
readonly loadMode = "discoverable";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/coding-agent",
|
|
4
|
-
"version": "0.12.
|
|
4
|
+
"version": "0.12.7",
|
|
5
5
|
"description": "Gajae Code CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://gajae-code.com",
|
|
7
7
|
"author": "Yeachan-Heo and Gajae Code Contributors",
|
|
@@ -53,13 +53,13 @@
|
|
|
53
53
|
"@agentclientprotocol/sdk": "1.3.0",
|
|
54
54
|
"@babel/parser": "^7.29.3",
|
|
55
55
|
"@mozilla/readability": "^0.6.0",
|
|
56
|
-
"@gajae-code/stats": "0.12.
|
|
57
|
-
"@gajae-code/agent-core": "0.12.
|
|
58
|
-
"@gajae-code/ai": "0.12.
|
|
59
|
-
"@gajae-code/bridge-client": "0.12.
|
|
60
|
-
"@gajae-code/natives": "0.12.
|
|
61
|
-
"@gajae-code/tui": "0.12.
|
|
62
|
-
"@gajae-code/utils": "0.12.
|
|
56
|
+
"@gajae-code/stats": "0.12.7",
|
|
57
|
+
"@gajae-code/agent-core": "0.12.7",
|
|
58
|
+
"@gajae-code/ai": "0.12.7",
|
|
59
|
+
"@gajae-code/bridge-client": "0.12.7",
|
|
60
|
+
"@gajae-code/natives": "0.12.7",
|
|
61
|
+
"@gajae-code/tui": "0.12.7",
|
|
62
|
+
"@gajae-code/utils": "0.12.7",
|
|
63
63
|
"@puppeteer/browsers": "^2.13.0",
|
|
64
64
|
"@types/turndown": "5.0.6",
|
|
65
65
|
"@xterm/headless": "^6.0.0",
|