@gajae-code/coding-agent 0.12.1 → 0.12.4
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 +39 -0
- package/dist/types/config/settings-schema.d.ts +2 -2
- package/dist/types/gjc-runtime/ralplan-review-conflicts.d.ts +114 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +5 -3
- package/dist/types/gjc-runtime/ultragoal-evidence.d.ts +5 -1
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -2
- package/dist/types/modes/components/irc-sidebar.d.ts +16 -0
- package/dist/types/modes/controllers/command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/event-controller.d.ts +1 -1
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +2 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
- package/dist/types/modes/interactive-mode.d.ts +9 -0
- package/dist/types/modes/theme/theme.d.ts +3 -1
- package/dist/types/modes/types.d.ts +32 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +2 -1
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -2
- package/dist/types/session/agent-session.d.ts +2 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +22 -3
- package/dist/types/task/index.d.ts +4 -0
- package/dist/types/task/output-manager.d.ts +1 -0
- package/dist/types/task/receipt.d.ts +2 -0
- package/dist/types/tools/index.d.ts +2 -0
- package/package.json +8 -8
- package/scripts/dogfood-ralplan-review-conflicts.ts +272 -0
- package/scripts/generate-sdk-operation-inventory.ts +2 -0
- package/scripts/run-acp-conformance.ts +5 -0
- package/src/async/job-manager.ts +22 -20
- package/src/config/provider-ranking.ts +1 -0
- package/src/config/settings-schema.ts +2 -2
- package/src/debug/index.ts +42 -17
- package/src/defaults/gjc/skills/ralplan/SKILL.md +9 -7
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +22 -5
- package/src/defaults/gjc/skills/ultragoal/validation-batch-contracts.md +2 -1
- package/src/gjc-runtime/launch-worktree.ts +103 -1
- package/src/gjc-runtime/ledger-event-renderer.ts +1 -0
- package/src/gjc-runtime/ralplan-review-conflicts.ts +472 -0
- package/src/gjc-runtime/ralplan-runtime.ts +80 -10
- package/src/gjc-runtime/ultragoal-evidence.ts +110 -49
- package/src/gjc-runtime/ultragoal-runtime.ts +467 -22
- package/src/gjc-runtime/workflow-manifest.generated.json +29 -0
- package/src/gjc-runtime/workflow-manifest.ts +17 -2
- package/src/internal-urls/docs-index.generated.ts +2 -2
- package/src/modes/DESIGN.md +53 -0
- package/src/modes/components/irc-sidebar.ts +30 -1
- package/src/modes/components/tool-status-header.ts +0 -1
- package/src/modes/controllers/command-controller.ts +38 -34
- package/src/modes/controllers/event-controller.ts +27 -16
- package/src/modes/controllers/extension-ui-controller.ts +186 -34
- package/src/modes/controllers/selector-controller.ts +115 -22
- package/src/modes/interactive-mode.ts +189 -62
- package/src/modes/jobs-observer.ts +1 -1
- package/src/modes/theme/theme.ts +11 -9
- package/src/modes/types.ts +88 -0
- package/src/sdk/broker/lifecycle.ts +18 -13
- package/src/sdk/bus/chat-daemon-control.ts +4 -3
- package/src/sdk/bus/telegram-daemon-contract.ts +3 -2
- package/src/sdk/protocol/operation-inventory.generated.json +11 -0
- package/src/sdk/session.ts +1 -0
- package/src/session/agent-session.ts +22 -1
- package/src/session/internal/managed-session-scope.ts +158 -107
- package/src/session/internal/managed-session-storage.ts +445 -57
- package/src/session/session-storage.ts +29 -44
- package/src/task/index.ts +257 -31
- package/src/task/output-manager.ts +24 -14
- package/src/task/receipt.ts +11 -1
- package/src/tools/index.ts +2 -0
package/src/modes/types.ts
CHANGED
|
@@ -63,6 +63,88 @@ export function canApplyComposerSubmission(
|
|
|
63
63
|
): boolean {
|
|
64
64
|
return options === undefined || (options.ownsComposer && editor === options.editor);
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
type PartialActivityStatusContainer = Partial<Pick<Container, "children" | "clear" | "detachChild" | "addChild">>;
|
|
68
|
+
|
|
69
|
+
export function stopInteractiveActivityIndicator(
|
|
70
|
+
ctx: {
|
|
71
|
+
loadingAnimation?: Loader;
|
|
72
|
+
statusContainer?: PartialActivityStatusContainer;
|
|
73
|
+
stopLoadingAnimation?: (options?: { restoreBackground?: boolean }) => void;
|
|
74
|
+
},
|
|
75
|
+
options?: { restoreBackground?: boolean },
|
|
76
|
+
): void {
|
|
77
|
+
if (ctx.stopLoadingAnimation) {
|
|
78
|
+
ctx.stopLoadingAnimation(options);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
ctx.loadingAnimation?.stop();
|
|
82
|
+
ctx.loadingAnimation = undefined;
|
|
83
|
+
ctx.statusContainer?.clear?.();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function clearInteractiveActivityLoaders(
|
|
87
|
+
ctx: Pick<
|
|
88
|
+
InteractiveModeContext,
|
|
89
|
+
| "autoCompactionLoader"
|
|
90
|
+
| "autoCompactionEscapeHandler"
|
|
91
|
+
| "retryLoader"
|
|
92
|
+
| "retryCountdownTimer"
|
|
93
|
+
| "retryEscapeHandler"
|
|
94
|
+
| "retryEscapePrimed"
|
|
95
|
+
| "editor"
|
|
96
|
+
>,
|
|
97
|
+
): void {
|
|
98
|
+
ctx.autoCompactionLoader?.stop();
|
|
99
|
+
ctx.autoCompactionLoader = undefined;
|
|
100
|
+
if (ctx.autoCompactionEscapeHandler) ctx.editor.onEscape = ctx.autoCompactionEscapeHandler;
|
|
101
|
+
ctx.autoCompactionEscapeHandler = undefined;
|
|
102
|
+
ctx.retryLoader?.stop();
|
|
103
|
+
ctx.retryLoader = undefined;
|
|
104
|
+
if (ctx.retryCountdownTimer) clearInterval(ctx.retryCountdownTimer);
|
|
105
|
+
ctx.retryCountdownTimer = undefined;
|
|
106
|
+
if (ctx.retryEscapeHandler) ctx.editor.onEscape = ctx.retryEscapeHandler;
|
|
107
|
+
ctx.retryEscapeHandler = undefined;
|
|
108
|
+
ctx.retryEscapePrimed = false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function suspendInteractiveActivityIndicator(ctx: {
|
|
112
|
+
loadingAnimation?: Loader;
|
|
113
|
+
statusContainer?: PartialActivityStatusContainer;
|
|
114
|
+
stopLoadingAnimation?: (options?: { restoreBackground?: boolean }) => void;
|
|
115
|
+
syncActivityIndicator?: () => void;
|
|
116
|
+
suspendActivityIndicator?: () => () => void;
|
|
117
|
+
}): () => void {
|
|
118
|
+
if (ctx.suspendActivityIndicator) return ctx.suspendActivityIndicator();
|
|
119
|
+
const suspendedLoader = ctx.loadingAnimation;
|
|
120
|
+
const statusContainer = ctx.statusContainer;
|
|
121
|
+
const canTransferMountedLoader =
|
|
122
|
+
Array.isArray(statusContainer?.children) &&
|
|
123
|
+
typeof statusContainer.detachChild === "function" &&
|
|
124
|
+
typeof statusContainer.addChild === "function";
|
|
125
|
+
const wasMounted =
|
|
126
|
+
canTransferMountedLoader && suspendedLoader !== undefined && statusContainer.children?.includes(suspendedLoader);
|
|
127
|
+
if (suspendedLoader && wasMounted) statusContainer.detachChild?.(suspendedLoader);
|
|
128
|
+
let released = false;
|
|
129
|
+
return () => {
|
|
130
|
+
if (released) return;
|
|
131
|
+
released = true;
|
|
132
|
+
if (
|
|
133
|
+
wasMounted &&
|
|
134
|
+
suspendedLoader &&
|
|
135
|
+
ctx.loadingAnimation === suspendedLoader &&
|
|
136
|
+
Array.isArray(statusContainer?.children) &&
|
|
137
|
+
!statusContainer.children.includes(suspendedLoader)
|
|
138
|
+
) {
|
|
139
|
+
statusContainer.addChild?.(suspendedLoader);
|
|
140
|
+
}
|
|
141
|
+
syncInteractiveActivityIndicator(ctx);
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function syncInteractiveActivityIndicator(ctx: { syncActivityIndicator?: () => void }): void {
|
|
146
|
+
ctx.syncActivityIndicator?.();
|
|
147
|
+
}
|
|
66
148
|
export type TodoStatus = "pending" | "in_progress" | "completed" | "abandoned";
|
|
67
149
|
|
|
68
150
|
export type TodoItem = {
|
|
@@ -164,6 +246,8 @@ export interface InteractiveModeContext {
|
|
|
164
246
|
init(): Promise<void>;
|
|
165
247
|
shutdown(): Promise<void>;
|
|
166
248
|
checkShutdownRequested(): Promise<void>;
|
|
249
|
+
isStopped?(): boolean;
|
|
250
|
+
onStop(callback: () => void): () => void;
|
|
167
251
|
|
|
168
252
|
// Extension UI integration
|
|
169
253
|
setToolUIContext(uiContext: ExtensionUIContext, hasUI: boolean): void;
|
|
@@ -190,6 +274,9 @@ export interface InteractiveModeContext {
|
|
|
190
274
|
setWorkingMessage(message?: string): void;
|
|
191
275
|
applyPendingWorkingMessage(): void;
|
|
192
276
|
ensureLoadingAnimation(): void;
|
|
277
|
+
syncActivityIndicator(): void;
|
|
278
|
+
suspendActivityIndicator(): () => void;
|
|
279
|
+
stopLoadingAnimation(options?: { restoreBackground?: boolean }): void;
|
|
193
280
|
/**
|
|
194
281
|
* Commit a pet mode through the shared result-returning policy: capability
|
|
195
282
|
* is rechecked immediately before mutation and the preference persists only
|
|
@@ -253,6 +340,7 @@ export interface InteractiveModeContext {
|
|
|
253
340
|
updateEditorTopBorder(): void;
|
|
254
341
|
updateEditorBorderColor(): void;
|
|
255
342
|
rebuildChatFromMessages(policy: TranscriptRebuildPolicy): void;
|
|
343
|
+
updateEditorChrome(): void;
|
|
256
344
|
setTodos(todos: TodoItem[] | TodoPhase[]): void;
|
|
257
345
|
reloadTodos(): Promise<void>;
|
|
258
346
|
toggleTodoExpansion(): void;
|
|
@@ -3260,26 +3260,31 @@ async function executeLifecycleResponse(
|
|
|
3260
3260
|
`Unable to delete saved session artifacts: ${error instanceof Error ? error.message : String(error)}`,
|
|
3261
3261
|
);
|
|
3262
3262
|
}
|
|
3263
|
-
const
|
|
3263
|
+
const retainedArtifactsRootOnly =
|
|
3264
3264
|
deleted.kind === "cleanup_pending" &&
|
|
3265
3265
|
deleted.phase === "artifacts" &&
|
|
3266
3266
|
deleted.detachedArtifactsPath !== undefined &&
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3267
|
+
(() => {
|
|
3268
|
+
const snapshot = native.snapshotDirectoryTree(deleted.detachedArtifactsPath);
|
|
3269
|
+
if (!snapshot.ok || !snapshot.snapshot) return false;
|
|
3270
|
+
const entries = snapshot.snapshot.entries;
|
|
3271
|
+
return entries.length === 1 && entries[0]?.relativePath === "" && entries[0].kind === "directory";
|
|
3272
|
+
})();
|
|
3273
|
+
const retainedArtifactsEvidence =
|
|
3274
|
+
retainedArtifactsRootOnly && deleted.kind === "cleanup_pending" && deleted.phase === "artifacts"
|
|
3275
|
+
? {
|
|
3276
|
+
detachedArtifactsPath: deleted.detachedArtifactsPath,
|
|
3277
|
+
...(deleted.artifactsIdentity
|
|
3278
|
+
? { artifactsIdentity: serializeCleanupIdentity(deleted.artifactsIdentity) }
|
|
3279
|
+
: {}),
|
|
3280
|
+
}
|
|
3281
|
+
: {};
|
|
3282
|
+
if (deleted.kind === "artifacts_removed" || retainedArtifactsRootOnly) {
|
|
3271
3283
|
const transcriptPhaseCleanup = {
|
|
3272
3284
|
...preauthorizedCleanup,
|
|
3273
3285
|
phase: "transcript" as const,
|
|
3274
3286
|
artifactsRemoved: true,
|
|
3275
|
-
...(
|
|
3276
|
-
? {
|
|
3277
|
-
detachedArtifactsPath: deleted.detachedArtifactsPath,
|
|
3278
|
-
...(deleted.artifactsIdentity
|
|
3279
|
-
? { artifactsIdentity: serializeCleanupIdentity(deleted.artifactsIdentity) }
|
|
3280
|
-
: {}),
|
|
3281
|
-
}
|
|
3282
|
-
: {}),
|
|
3287
|
+
...(retainedArtifactsRootOnly ? retainedArtifactsEvidence : {}),
|
|
3283
3288
|
...(preauthorizedCleanup.artifactTree
|
|
3284
3289
|
? { artifactTree: { ...preauthorizedCleanup.artifactTree, completed: true as const } }
|
|
3285
3290
|
: {}),
|
|
@@ -38,11 +38,12 @@ export type ChatDaemonAction = "stop" | "reload";
|
|
|
38
38
|
* chat daemons after notification configuration parsing changes. Generation 15
|
|
39
39
|
* applies the current notification configuration directly when starting chat
|
|
40
40
|
* daemon transports. Generation 16 applies Telegram sound-policy configuration
|
|
41
|
-
* through shared notification parsing.
|
|
41
|
+
* through shared notification parsing. Generation 17 binds managed-session
|
|
42
|
+
* replacement to exact native filesystem authority.
|
|
42
43
|
*/
|
|
43
44
|
export const CHAT_DAEMON_GENERATIONS: Readonly<Record<ChatDaemonKind, number>> = {
|
|
44
|
-
discord:
|
|
45
|
-
slack:
|
|
45
|
+
discord: 17,
|
|
46
|
+
slack: 17,
|
|
46
47
|
};
|
|
47
48
|
|
|
48
49
|
export function chatDaemonGeneration(kind: ChatDaemonKind): number {
|
|
@@ -46,9 +46,10 @@ export const NOTIFICATION_PROTOCOL_VERSION = 3;
|
|
|
46
46
|
* 33 adds action-bound multi-select state rendering and replay-safe option
|
|
47
47
|
* snapshots. Generation 34 converts non-photo image formats (including WebP)
|
|
48
48
|
* into Telegram-compatible photo uploads when possible. Generation 35 adds
|
|
49
|
-
* user-created topic adoption (forum-topic folder picker).
|
|
49
|
+
* user-created topic adoption (forum-topic folder picker). Generation 36 binds
|
|
50
|
+
* managed-session replacement to exact native filesystem authority.
|
|
50
51
|
*/
|
|
51
|
-
export const DAEMON_GENERATION =
|
|
52
|
+
export const DAEMON_GENERATION = 36;
|
|
52
53
|
|
|
53
54
|
/**
|
|
54
55
|
* Serving-compatibility boundary for daemon lifecycle requests. Epoch 1 covers
|
|
@@ -2531,6 +2531,17 @@
|
|
|
2531
2531
|
"testIds": "not_applicable"
|
|
2532
2532
|
}
|
|
2533
2533
|
},
|
|
2534
|
+
{
|
|
2535
|
+
"sourceId": "agent_session:registerToolSessionCleanup",
|
|
2536
|
+
"sourceFile": "packages/coding-agent/src/session/agent-session.ts",
|
|
2537
|
+
"sourceKind": "agent_session",
|
|
2538
|
+
"decision": "exclude",
|
|
2539
|
+
"rationale": "internal tool lifecycle cleanup registration, not a user-facing SDK control seam",
|
|
2540
|
+
"exclusionMetadata": {
|
|
2541
|
+
"adapterMappings": "not_applicable",
|
|
2542
|
+
"testIds": "not_applicable"
|
|
2543
|
+
}
|
|
2544
|
+
},
|
|
2534
2545
|
{
|
|
2535
2546
|
"sourceId": "agent_session:getAsyncJobSnapshot",
|
|
2536
2547
|
"sourceFile": "packages/coding-agent/src/session/agent-session.ts",
|
package/src/sdk/session.ts
CHANGED
|
@@ -1623,6 +1623,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1623
1623
|
}
|
|
1624
1624
|
},
|
|
1625
1625
|
getArtifactManager: () => sessionManager.getArtifactManager(),
|
|
1626
|
+
registerSessionCleanup: cleanup => session?.registerToolSessionCleanup(cleanup) ?? (() => {}),
|
|
1626
1627
|
settings,
|
|
1627
1628
|
authStorage,
|
|
1628
1629
|
modelRegistry,
|
|
@@ -1884,6 +1884,7 @@ export class AgentSession {
|
|
|
1884
1884
|
#providerCacheSessionId: string | undefined;
|
|
1885
1885
|
#isDisposed = false;
|
|
1886
1886
|
#disposePromise: Promise<void> | undefined;
|
|
1887
|
+
readonly #toolSessionCleanups = new Set<() => Promise<void> | void>();
|
|
1887
1888
|
#newSessionTransition: Promise<boolean> | undefined;
|
|
1888
1889
|
// Extension system
|
|
1889
1890
|
#extensionRunner: ExtensionRunner | undefined = undefined;
|
|
@@ -3233,6 +3234,21 @@ export class AgentSession {
|
|
|
3233
3234
|
return this.#agentId;
|
|
3234
3235
|
}
|
|
3235
3236
|
|
|
3237
|
+
registerToolSessionCleanup(cleanup: () => Promise<void> | void): () => void {
|
|
3238
|
+
if (this.#isDisposed) throw new Error("Cannot register tool cleanup after session disposal has started.");
|
|
3239
|
+
this.#toolSessionCleanups.add(cleanup);
|
|
3240
|
+
return () => this.#toolSessionCleanups.delete(cleanup);
|
|
3241
|
+
}
|
|
3242
|
+
|
|
3243
|
+
async #runToolSessionCleanups(): Promise<void> {
|
|
3244
|
+
const cleanups = Array.from(this.#toolSessionCleanups);
|
|
3245
|
+
this.#toolSessionCleanups.clear();
|
|
3246
|
+
const results = await Promise.allSettled(cleanups.map(async cleanup => await cleanup()));
|
|
3247
|
+
for (const result of results) {
|
|
3248
|
+
if (result.status === "rejected") logger.warn("Tool session cleanup failed", { error: String(result.reason) });
|
|
3249
|
+
}
|
|
3250
|
+
}
|
|
3251
|
+
|
|
3236
3252
|
getAsyncJobSnapshot(options?: { recentLimit?: number }): AsyncJobSnapshot | null {
|
|
3237
3253
|
const manager = AsyncJobManager.instance();
|
|
3238
3254
|
if (!manager) return null;
|
|
@@ -5565,6 +5581,7 @@ export class AgentSession {
|
|
|
5565
5581
|
AsyncJobManager.setInstance(undefined);
|
|
5566
5582
|
}
|
|
5567
5583
|
}
|
|
5584
|
+
await this.#runToolSessionCleanups();
|
|
5568
5585
|
// Only disconnect the MCP manager THIS session owns (top-level sessions that
|
|
5569
5586
|
// connected plugin-bundle MCP servers). Subagents and callers that merely
|
|
5570
5587
|
// observe the process-global manager must never tear down a manager they do
|
|
@@ -15703,7 +15720,10 @@ export class AgentSession {
|
|
|
15703
15720
|
*/
|
|
15704
15721
|
async switchSession(
|
|
15705
15722
|
sessionPath: string,
|
|
15706
|
-
options?: {
|
|
15723
|
+
options?: {
|
|
15724
|
+
transition?: SessionSwitchEvent["transition"];
|
|
15725
|
+
onTransitionMutationStarted?: () => void;
|
|
15726
|
+
},
|
|
15707
15727
|
): Promise<boolean> {
|
|
15708
15728
|
this.#beginSessionTransition("switch-session");
|
|
15709
15729
|
try {
|
|
@@ -15723,6 +15743,7 @@ export class AgentSession {
|
|
|
15723
15743
|
return false;
|
|
15724
15744
|
}
|
|
15725
15745
|
}
|
|
15746
|
+
options?.onTransitionMutationStarted?.();
|
|
15726
15747
|
|
|
15727
15748
|
this.#disconnectFromAgent();
|
|
15728
15749
|
await this.abort();
|