@cjhyy/code-shell-core 0.6.0-rc.9 → 0.7.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/THIRD_PARTY_NOTICES.md +206 -0
- package/dist/automation/scheduler.d.ts +13 -7
- package/dist/automation/scheduler.js +116 -37
- package/dist/capability-control/service.d.ts +2 -0
- package/dist/capability-control/service.js +4 -2
- package/dist/cc-orchestrator/agent-adapter.d.ts +4 -0
- package/dist/cc-orchestrator/agent-adapter.js +11 -1
- package/dist/cc-orchestrator/codex-session-history.d.ts +14 -1
- package/dist/cc-orchestrator/codex-session-history.js +65 -5
- package/dist/cc-orchestrator/cwd-normalize.d.ts +2 -0
- package/dist/cc-orchestrator/cwd-normalize.js +19 -0
- package/dist/cc-orchestrator/external-agent-bindings.d.ts +27 -0
- package/dist/cc-orchestrator/external-agent-bindings.js +150 -0
- package/dist/cc-orchestrator/external-agent-changes.js +22 -5
- package/dist/cc-orchestrator/external-agent-driver.d.ts +1 -0
- package/dist/cc-orchestrator/external-agent-driver.js +265 -50
- package/dist/cc-orchestrator/external-agent-session-store.d.ts +23 -0
- package/dist/cc-orchestrator/external-agent-session-store.js +146 -0
- package/dist/cc-orchestrator/session-history.d.ts +35 -0
- package/dist/cc-orchestrator/session-history.js +98 -15
- package/dist/cli/agent-server-stdio.js +9 -2
- package/dist/context/compaction.d.ts +8 -1
- package/dist/context/compaction.js +49 -4
- package/dist/context/manager.d.ts +16 -2
- package/dist/context/manager.js +103 -19
- package/dist/credentials/access.d.ts +57 -0
- package/dist/credentials/access.js +185 -0
- package/dist/credentials/index.d.ts +3 -1
- package/dist/credentials/index.js +2 -0
- package/dist/credentials/inject-credential-tool.d.ts +3 -1
- package/dist/credentials/inject-credential-tool.js +30 -11
- package/dist/credentials/oauth.d.ts +20 -0
- package/dist/credentials/oauth.js +114 -0
- package/dist/credentials/store.d.ts +1 -0
- package/dist/credentials/store.js +3 -1
- package/dist/credentials/types.d.ts +49 -3
- package/dist/credentials/use-credential-tool.d.ts +9 -1
- package/dist/credentials/use-credential-tool.js +58 -45
- package/dist/engine/engine.d.ts +23 -3
- package/dist/engine/engine.js +380 -255
- package/dist/engine/goal.d.ts +17 -0
- package/dist/engine/goal.js +16 -6
- package/dist/engine/image-policy.d.ts +6 -0
- package/dist/engine/image-policy.js +17 -6
- package/dist/engine/input-attachments.d.ts +13 -0
- package/dist/engine/input-attachments.js +398 -0
- package/dist/engine/model-facade.d.ts +5 -2
- package/dist/engine/model-facade.js +4 -4
- package/dist/engine/parse-task.d.ts +10 -0
- package/dist/engine/parse-task.js +5 -0
- package/dist/engine/run-image-input.d.ts +22 -0
- package/dist/engine/run-image-input.js +195 -0
- package/dist/engine/steer-queue.d.ts +3 -1
- package/dist/engine/steer-queue.js +10 -2
- package/dist/engine/streaming-tool-queue.d.ts +11 -7
- package/dist/engine/streaming-tool-queue.js +11 -7
- package/dist/engine/turn-loop.d.ts +37 -2
- package/dist/engine/turn-loop.js +228 -43
- package/dist/engine/types.d.ts +8 -0
- package/dist/git/worktree/crud.d.ts +69 -0
- package/dist/git/worktree/crud.js +206 -0
- package/dist/git/worktree/diff.d.ts +14 -0
- package/dist/git/worktree/diff.js +82 -0
- package/dist/git/worktree/git-exec.d.ts +7 -0
- package/dist/git/worktree/git-exec.js +51 -0
- package/dist/git/worktree/index.d.ts +5 -0
- package/dist/git/worktree/index.js +5 -0
- package/dist/git/worktree/query.d.ts +42 -0
- package/dist/git/worktree/query.js +121 -0
- package/dist/git/worktree/slug.d.ts +11 -0
- package/dist/git/worktree/slug.js +58 -0
- package/dist/git/worktree.d.ts +1 -84
- package/dist/git/worktree.js +5 -230
- package/dist/hooks/goal-stop-hook.d.ts +33 -1
- package/dist/hooks/goal-stop-hook.js +202 -34
- package/dist/index.d.ts +31 -28
- package/dist/index.js +27 -25
- package/dist/logging/logger.js +6 -6
- package/dist/logging/sanitize-messages.d.ts +10 -2
- package/dist/logging/sanitize-messages.js +21 -6
- package/dist/plugins/installer/checkUpdate.d.ts +4 -1
- package/dist/plugins/installer/checkUpdate.js +4 -2
- package/dist/plugins/installer/install.js +2 -0
- package/dist/plugins/installer/installFromSource.js +9 -1
- package/dist/plugins/installer/parseSource.d.ts +4 -1
- package/dist/plugins/installer/parseSource.js +28 -10
- package/dist/plugins/installer/sourcePath.d.ts +9 -0
- package/dist/plugins/installer/sourcePath.js +50 -0
- package/dist/plugins/installer/update.d.ts +4 -1
- package/dist/plugins/installer/update.js +5 -3
- package/dist/plugins/parseMarketplaceInput.d.ts +4 -1
- package/dist/plugins/parseMarketplaceInput.js +4 -3
- package/dist/plugins/pluginInstaller.js +24 -22
- package/dist/preset/index.d.ts +1 -0
- package/dist/preset/index.js +30 -13
- package/dist/prompt/sections/base.md +1 -1
- package/dist/protocol/chat-session-manager.d.ts +2 -0
- package/dist/protocol/chat-session-manager.js +38 -2
- package/dist/protocol/chat-session.d.ts +3 -0
- package/dist/protocol/chat-session.js +1 -0
- package/dist/protocol/client.d.ts +9 -4
- package/dist/protocol/client.js +18 -1
- package/dist/protocol/server.d.ts +30 -0
- package/dist/protocol/server.js +247 -47
- package/dist/protocol/types.d.ts +49 -0
- package/dist/protocol/types.js +6 -0
- package/dist/run/FileRunStore.js +10 -1
- package/dist/run/Heartbeat.js +12 -0
- package/dist/run/RunApprovalBackend.d.ts +3 -0
- package/dist/run/RunApprovalBackend.js +41 -6
- package/dist/run/RunLock.js +2 -0
- package/dist/run/RunManager.d.ts +2 -0
- package/dist/run/RunManager.js +64 -24
- package/dist/run/ids.d.ts +2 -0
- package/dist/run/ids.js +23 -0
- package/dist/runtime/background-shell.d.ts +1 -0
- package/dist/runtime/background-shell.js +23 -13
- package/dist/runtime/spawn-common.js +10 -0
- package/dist/services/auto-dream.d.ts +15 -4
- package/dist/services/auto-dream.js +20 -20
- package/dist/services/dream-consolidation.d.ts +2 -3
- package/dist/services/dream-consolidation.js +65 -15
- package/dist/services/extract-memories.d.ts +14 -5
- package/dist/services/extract-memories.js +20 -3
- package/dist/services/global-dream-promotion.d.ts +23 -0
- package/dist/services/global-dream-promotion.js +112 -0
- package/dist/services/memory-orchestrator.js +347 -34
- package/dist/session/memory.d.ts +61 -18
- package/dist/session/memory.js +342 -79
- package/dist/session/session-manager.d.ts +35 -1
- package/dist/session/session-manager.js +224 -4
- package/dist/session/transcript.d.ts +1 -1
- package/dist/session/transcript.js +17 -5
- package/dist/settings/manager.d.ts +1 -0
- package/dist/settings/manager.js +87 -37
- package/dist/settings/schema-export.d.ts +2 -3
- package/dist/settings/schema-export.js +2 -3
- package/dist/settings/schema.d.ts +21 -0
- package/dist/settings/schema.js +12 -0
- package/dist/skills/scanner.d.ts +3 -2
- package/dist/skills/scanner.js +12 -9
- package/dist/tool-system/builtin/agent-notifications.d.ts +11 -4
- package/dist/tool-system/builtin/agent-notifications.js +19 -7
- package/dist/tool-system/builtin/background-jobs.d.ts +35 -6
- package/dist/tool-system/builtin/background-jobs.js +116 -7
- package/dist/tool-system/builtin/background-work.d.ts +17 -18
- package/dist/tool-system/builtin/background-work.js +51 -5
- package/dist/tool-system/builtin/config.d.ts +2 -1
- package/dist/tool-system/builtin/config.js +16 -11
- package/dist/tool-system/builtin/cron-list.definition.d.ts +3 -0
- package/dist/tool-system/builtin/cron-list.definition.js +6 -0
- package/dist/tool-system/builtin/cron.d.ts +1 -2
- package/dist/tool-system/builtin/cron.js +9 -7
- package/dist/tool-system/builtin/drive-claude-code.d.ts +23 -2
- package/dist/tool-system/builtin/drive-claude-code.js +589 -48
- package/dist/tool-system/builtin/edit.js +5 -2
- package/dist/tool-system/builtin/generate-video.d.ts +1 -0
- package/dist/tool-system/builtin/generate-video.js +13 -4
- package/dist/tool-system/builtin/index.d.ts +8 -3
- package/dist/tool-system/builtin/index.js +50 -22
- package/dist/tool-system/builtin/lsp.d.ts +2 -1
- package/dist/tool-system/builtin/lsp.js +6 -3
- package/dist/tool-system/builtin/memory.js +40 -8
- package/dist/tool-system/builtin/notebook-edit.js +5 -2
- package/dist/tool-system/builtin/powershell.d.ts +5 -2
- package/dist/tool-system/builtin/powershell.js +11 -7
- package/dist/tool-system/builtin/read.js +118 -6
- package/dist/tool-system/builtin/sleep.d.ts +1 -2
- package/dist/tool-system/builtin/sleep.definition.d.ts +8 -0
- package/dist/tool-system/builtin/sleep.definition.js +28 -0
- package/dist/tool-system/builtin/sleep.js +1 -22
- package/dist/tool-system/builtin/view-image.d.ts +2 -2
- package/dist/tool-system/builtin/view-image.js +109 -19
- package/dist/tool-system/builtin/worktree.d.ts +4 -4
- package/dist/tool-system/builtin/worktree.js +297 -74
- package/dist/tool-system/builtin/write.js +5 -3
- package/dist/tool-system/context.d.ts +41 -1
- package/dist/tool-system/executor.d.ts +1 -5
- package/dist/tool-system/executor.js +94 -115
- package/dist/tool-system/mcp-manager.d.ts +31 -6
- package/dist/tool-system/mcp-manager.js +193 -78
- package/dist/tool-system/path-policy.d.ts +2 -0
- package/dist/tool-system/path-policy.js +41 -12
- package/dist/tool-system/permission.d.ts +28 -7
- package/dist/tool-system/permission.js +130 -49
- package/dist/tool-system/registry.js +11 -4
- package/dist/tool-system/tool-result-redaction.d.ts +7 -0
- package/dist/tool-system/tool-result-redaction.js +48 -0
- package/dist/tool-system/workspace-bridge.d.ts +11 -0
- package/dist/tool-system/workspace-bridge.js +1 -0
- package/dist/types.d.ts +78 -11
- package/dist/utils/toolDisplay.js +1 -1
- package/package.json +4 -3
package/dist/skills/scanner.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Skill scanner — discovers <base>/<name>/SKILL.md files from project
|
|
3
|
-
*
|
|
2
|
+
* Skill scanner — discovers <base>/<name>/SKILL.md files from project
|
|
3
|
+
* `.code-shell/skills`, project `.agents/skills`, user `.code-shell/skills`,
|
|
4
|
+
* and installed plugins. Mirrors Claude Code's
|
|
4
5
|
* `loadSkillsFromSkillsDir` (skills/loadSkillsDir.ts:407) plus plugin
|
|
5
6
|
* integration (utils/plugins/pluginLoader.ts).
|
|
6
7
|
*/
|
package/dist/skills/scanner.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Skill scanner — discovers <base>/<name>/SKILL.md files from project
|
|
3
|
-
*
|
|
2
|
+
* Skill scanner — discovers <base>/<name>/SKILL.md files from project
|
|
3
|
+
* `.code-shell/skills`, project `.agents/skills`, user `.code-shell/skills`,
|
|
4
|
+
* and installed plugins. Mirrors Claude Code's
|
|
4
5
|
* `loadSkillsFromSkillsDir` (skills/loadSkillsDir.ts:407) plus plugin
|
|
5
6
|
* integration (utils/plugins/pluginLoader.ts).
|
|
6
7
|
*/
|
|
@@ -20,6 +21,7 @@ function userHome() {
|
|
|
20
21
|
function bases(cwd) {
|
|
21
22
|
return [
|
|
22
23
|
{ dir: join(cwd, ".code-shell", "skills"), source: "project" },
|
|
24
|
+
{ dir: join(cwd, ".agents", "skills"), source: "project" },
|
|
23
25
|
{ dir: join(userHome(), ".code-shell", "skills"), source: "user" },
|
|
24
26
|
];
|
|
25
27
|
}
|
|
@@ -158,13 +160,14 @@ function installedPluginsMtime() {
|
|
|
158
160
|
}
|
|
159
161
|
}
|
|
160
162
|
/**
|
|
161
|
-
* mtime of each local skills base dir (project + user). A
|
|
162
|
-
* changes when a child entry is added/removed, so installing
|
|
163
|
-
* `<cwd>/.code-shell/skills
|
|
164
|
-
* next scan — the just-installed
|
|
165
|
-
* without a restart. (Editing an
|
|
166
|
-
* dir mtime; install paths
|
|
167
|
-
* that, so this is the
|
|
163
|
+
* mtime of each local skills base dir (project .code-shell/.agents + user). A
|
|
164
|
+
* directory's mtime changes when a child entry is added/removed, so installing
|
|
165
|
+
* a new skill into `<cwd>/.code-shell/skills`, `<cwd>/.agents/skills`, or
|
|
166
|
+
* `~/.code-shell/skills` busts the cache on the next scan — the just-installed
|
|
167
|
+
* skill becomes visible to the running session without a restart. (Editing an
|
|
168
|
+
* existing skill's *contents* does not bump the dir mtime; install paths
|
|
169
|
+
* additionally call invalidateSkillCache() to cover that, so this is the
|
|
170
|
+
* passive half of a two-part guard.)
|
|
168
171
|
*/
|
|
169
172
|
function skillsDirsMtime(cwd) {
|
|
170
173
|
return bases(cwd)
|
|
@@ -6,8 +6,9 @@ import type { BackgroundAgentCompletedEvent, StreamEvent } from "../../types.js"
|
|
|
6
6
|
* background sub-agent that finishes (completed | failed) enqueues an item
|
|
7
7
|
* here; the UI layer subscribes and, when the main agent is idle, drains
|
|
8
8
|
* the queue and submits the formatted XML as a new user turn so the LLM
|
|
9
|
-
* sees the result.
|
|
10
|
-
* the agent; no follow-up needed).
|
|
9
|
+
* sees the result. Sub-agent cancellation does NOT enqueue (user explicitly
|
|
10
|
+
* stopped the agent; no follow-up needed). DriveAgent cancellation does enqueue
|
|
11
|
+
* so a detached external CLI job never leaves the waiting session hanging.
|
|
11
12
|
*
|
|
12
13
|
* The result text lives only in this queue + the eventual user message —
|
|
13
14
|
* not in `asyncAgentRegistry`. Registry stays metadata-only.
|
|
@@ -29,7 +30,7 @@ export type NotificationItem = {
|
|
|
29
30
|
agentId: string;
|
|
30
31
|
name?: string;
|
|
31
32
|
description: string;
|
|
32
|
-
status: "completed" | "failed";
|
|
33
|
+
status: "completed" | "failed" | "cancelled";
|
|
33
34
|
/** What kind of background work this was (lets UIs localize the toast). */
|
|
34
35
|
workKind?: "agent" | "shell" | "video" | "cc";
|
|
35
36
|
/** For workKind === "shell": the command that ran. */
|
|
@@ -41,8 +42,14 @@ export type NotificationItem = {
|
|
|
41
42
|
* if this notification is lost, and the user sees a real session id (not just
|
|
42
43
|
* an opaque background jobId). */
|
|
43
44
|
ccSessionId?: string;
|
|
44
|
-
/** Error message (failed only). */
|
|
45
|
+
/** Error message (failed/cancelled only). */
|
|
45
46
|
error?: string;
|
|
47
|
+
/** Files attributed to an external DriveAgent transcript. */
|
|
48
|
+
changedFiles?: string[];
|
|
49
|
+
/** DriveAgent cwd used to canonicalize path aliases in clients. */
|
|
50
|
+
cwd?: string;
|
|
51
|
+
/** Client id of the real user turn that launched this background work. */
|
|
52
|
+
originClientMessageId?: string;
|
|
46
53
|
enqueuedAt: number;
|
|
47
54
|
};
|
|
48
55
|
type Listener = () => void;
|
|
@@ -139,6 +139,15 @@ export function notificationItemToStreamEvent(item) {
|
|
|
139
139
|
event.finalText = item.finalText;
|
|
140
140
|
if (item.error !== undefined)
|
|
141
141
|
event.error = item.error;
|
|
142
|
+
if (item.ccSessionId !== undefined)
|
|
143
|
+
event.ccSessionId = item.ccSessionId;
|
|
144
|
+
if (item.changedFiles !== undefined)
|
|
145
|
+
event.changedFiles = item.changedFiles;
|
|
146
|
+
if (item.cwd !== undefined)
|
|
147
|
+
event.cwd = item.cwd;
|
|
148
|
+
if (item.originClientMessageId !== undefined) {
|
|
149
|
+
event.originClientMessageId = item.originClientMessageId;
|
|
150
|
+
}
|
|
142
151
|
return event;
|
|
143
152
|
}
|
|
144
153
|
/**
|
|
@@ -147,10 +156,7 @@ export function notificationItemToStreamEvent(item) {
|
|
|
147
156
|
* values get the quote escape too; element bodies don't need it.
|
|
148
157
|
*/
|
|
149
158
|
function escapeXmlText(s) {
|
|
150
|
-
return s
|
|
151
|
-
.replace(/&/g, "&")
|
|
152
|
-
.replace(/</g, "<")
|
|
153
|
-
.replace(/>/g, ">");
|
|
159
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
154
160
|
}
|
|
155
161
|
function escapeXmlAttr(s) {
|
|
156
162
|
return escapeXmlText(s).replace(/"/g, """);
|
|
@@ -173,7 +179,9 @@ export function buildNotificationMessage(items) {
|
|
|
173
179
|
const desc = ` <description>${escapeXmlText(item.description)}</description>`;
|
|
174
180
|
const body = item.status === "completed"
|
|
175
181
|
? ` <result>\n${escapeXmlText(item.finalText ?? "")}\n </result>`
|
|
176
|
-
:
|
|
182
|
+
: item.status === "cancelled"
|
|
183
|
+
? ` <cancelled>${escapeXmlText(item.error ?? "cancelled")}</cancelled>`
|
|
184
|
+
: ` <error>${escapeXmlText(item.error ?? "")}</error>`;
|
|
177
185
|
return [opening, desc, body, " </agent>"].join("\n");
|
|
178
186
|
})
|
|
179
187
|
.join("\n");
|
|
@@ -194,9 +202,13 @@ export function buildNotificationMessage(items) {
|
|
|
194
202
|
export function buildNotificationSummary(items) {
|
|
195
203
|
const header = "📨 background agents completed";
|
|
196
204
|
const rows = items.map((item) => {
|
|
197
|
-
const badge = item.status === "completed" ? "✓" : "✗";
|
|
205
|
+
const badge = item.status === "completed" ? "✓" : item.status === "cancelled" ? "cancelled" : "✗";
|
|
198
206
|
const namePart = item.name ? `${item.name} · ` : "";
|
|
199
|
-
const statusPart = item.status === "failed"
|
|
207
|
+
const statusPart = item.status === "failed"
|
|
208
|
+
? ` · failed: ${item.error ?? "unknown"}`
|
|
209
|
+
: item.status === "cancelled"
|
|
210
|
+
? ` · cancelled`
|
|
211
|
+
: "";
|
|
200
212
|
return ` └─ ${namePart}${item.description} · ${badge}${statusPart}`;
|
|
201
213
|
});
|
|
202
214
|
return [header, ...rows].join("\n");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Registry of NON-agent background jobs (GenerateVideo poll loops, DriveAgent
|
|
3
3
|
* external CLI runs). Mirrors the role `asyncAgentRegistry` plays for background
|
|
4
|
-
* sub-agents, but a job is not an agent — it has no transcript
|
|
5
|
-
*
|
|
4
|
+
* sub-agents, but a job is not an agent — it has no transcript and must NOT
|
|
5
|
+
* show up in AgentStatus.
|
|
6
6
|
*
|
|
7
7
|
* The engine's wait-for-background loop parks the turn until a session has no
|
|
8
8
|
* more RUNNING jobs, so the goal-stop-hook doesn't force the model to busy-loop
|
|
@@ -21,11 +21,14 @@
|
|
|
21
21
|
* loop observe the same instance.
|
|
22
22
|
*/
|
|
23
23
|
type Listener = () => void;
|
|
24
|
-
export type BackgroundJobStatus = "running" | "completed" | "failed";
|
|
24
|
+
export type BackgroundJobStatus = "running" | "cancelling" | "completed" | "failed" | "cancelled";
|
|
25
|
+
export type BackgroundJobKind = "drive-agent" | "video" | "job";
|
|
25
26
|
/** A background job, running or finished. */
|
|
26
27
|
export interface BackgroundJobEntry {
|
|
27
28
|
jobId: string;
|
|
28
29
|
sessionId: string;
|
|
30
|
+
/** Machine-readable kind for tools that need to target a subset of jobs. */
|
|
31
|
+
kind?: BackgroundJobKind;
|
|
29
32
|
/** Human description (e.g. "Generating video: <prompt>"). Shown to the goal
|
|
30
33
|
* judge (running) and in the background panel (all). */
|
|
31
34
|
description: string;
|
|
@@ -40,28 +43,54 @@ export interface BackgroundJobEntry {
|
|
|
40
43
|
ccSessionId?: string;
|
|
41
44
|
/** Files the external agent changed (parsed from its transcript, #6). */
|
|
42
45
|
changedFiles?: string[];
|
|
46
|
+
/** Working directory for jobs that operate on the filesystem, e.g. DriveAgent. */
|
|
47
|
+
cwd?: string;
|
|
48
|
+
/** DriveAgent prompt summary, separate from the UI-oriented description. */
|
|
49
|
+
promptSummary?: string;
|
|
50
|
+
/** External CLI kind for DriveAgent jobs. */
|
|
51
|
+
cli?: string;
|
|
52
|
+
/** Client message that launched this external job. */
|
|
53
|
+
originClientMessageId?: string;
|
|
54
|
+
/** Optional cancellation hook for jobs backed by a live process. */
|
|
55
|
+
abort?: () => void | Promise<void>;
|
|
43
56
|
}
|
|
44
57
|
/** Outcome passed to finish() to record how a job ended. */
|
|
45
58
|
export interface BackgroundJobOutcome {
|
|
46
|
-
status?: "completed" | "failed";
|
|
59
|
+
status?: "completed" | "failed" | "cancelled";
|
|
47
60
|
finalText?: string;
|
|
48
61
|
ccSessionId?: string;
|
|
49
62
|
changedFiles?: string[];
|
|
50
63
|
}
|
|
64
|
+
export interface BackgroundJobStartOptions {
|
|
65
|
+
kind?: BackgroundJobKind;
|
|
66
|
+
cwd?: string;
|
|
67
|
+
promptSummary?: string;
|
|
68
|
+
cli?: string;
|
|
69
|
+
originClientMessageId?: string;
|
|
70
|
+
abort?: () => void | Promise<void>;
|
|
71
|
+
}
|
|
51
72
|
declare class BackgroundJobRegistry {
|
|
52
73
|
private jobs;
|
|
53
74
|
private listeners;
|
|
54
75
|
/** Register a running job. Invalid sessionId is ignored (cannot be waited on). */
|
|
55
|
-
start(jobId: string, sessionId: string, description?: string): void;
|
|
76
|
+
start(jobId: string, sessionId: string, description?: string, options?: BackgroundJobStartOptions): void;
|
|
56
77
|
/** Mark a job terminal (retained, not deleted). Unknown id is a no-op (no
|
|
57
78
|
* notify) so a double-finish or a finish after reset stays quiet. */
|
|
58
79
|
finish(jobId: string, outcome?: BackgroundJobOutcome): void;
|
|
59
|
-
|
|
80
|
+
get(jobId: string): BackgroundJobEntry | undefined;
|
|
81
|
+
/** Persist artifacts discovered while a running job is winding down. */
|
|
82
|
+
recordArtifacts(jobId: string, artifacts: Pick<BackgroundJobOutcome, "ccSessionId" | "changedFiles">): void;
|
|
83
|
+
cancel(jobId: string, outcome?: Omit<BackgroundJobOutcome, "status">): Promise<boolean>;
|
|
84
|
+
/** True while any running/cancelling job spawned by `sessionId` remains. */
|
|
60
85
|
hasRunningForSession(sessionId: string): boolean;
|
|
61
86
|
/** Running jobs spawned by `sessionId`. Feeds the goal judge's task list. */
|
|
62
87
|
listRunningForSession(sessionId: string): BackgroundJobEntry[];
|
|
88
|
+
/** Running jobs, across all sessions, that are operating in the same cwd. */
|
|
89
|
+
listRunningByCwd(cwd: string): BackgroundJobEntry[];
|
|
63
90
|
/** All jobs (running + retained terminal) for `sessionId`. Feeds the panel. */
|
|
64
91
|
listForSession(sessionId: string): BackgroundJobEntry[];
|
|
92
|
+
/** All jobs (running + retained terminal) across sessions. Feeds all-scope UI. */
|
|
93
|
+
list(): BackgroundJobEntry[];
|
|
65
94
|
/** Drop every job of a session — called when the session is deleted/closed. */
|
|
66
95
|
dropForSession(sessionId: string): void;
|
|
67
96
|
subscribe: (cb: Listener) => (() => void);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Registry of NON-agent background jobs (GenerateVideo poll loops, DriveAgent
|
|
3
3
|
* external CLI runs). Mirrors the role `asyncAgentRegistry` plays for background
|
|
4
|
-
* sub-agents, but a job is not an agent — it has no transcript
|
|
5
|
-
*
|
|
4
|
+
* sub-agents, but a job is not an agent — it has no transcript and must NOT
|
|
5
|
+
* show up in AgentStatus.
|
|
6
6
|
*
|
|
7
7
|
* The engine's wait-for-background loop parks the turn until a session has no
|
|
8
8
|
* more RUNNING jobs, so the goal-stop-hook doesn't force the model to busy-loop
|
|
@@ -20,25 +20,57 @@
|
|
|
20
20
|
* loops run in the main engine process, so start/finish and the engine's wait
|
|
21
21
|
* loop observe the same instance.
|
|
22
22
|
*/
|
|
23
|
+
import { normalizeCwdPath } from "../../cc-orchestrator/cwd-normalize.js";
|
|
23
24
|
function isValidSessionId(sid) {
|
|
24
25
|
return typeof sid === "string" && sid.length > 0;
|
|
25
26
|
}
|
|
26
27
|
/** Generous per-session cap on retained terminal jobs — a leak backstop, not a
|
|
27
28
|
* UX limit; a human never spawns this many background jobs in one session. */
|
|
28
29
|
const MAX_TERMINAL_JOBS_PER_SESSION = 50;
|
|
30
|
+
const CANCEL_WAIT_TIMEOUT_MS = 5_000;
|
|
31
|
+
function isActiveStatus(status) {
|
|
32
|
+
return status === "running" || status === "cancelling";
|
|
33
|
+
}
|
|
34
|
+
async function waitForAbort(abort) {
|
|
35
|
+
let timer;
|
|
36
|
+
try {
|
|
37
|
+
await Promise.race([
|
|
38
|
+
Promise.resolve().then(abort),
|
|
39
|
+
new Promise((resolve) => {
|
|
40
|
+
timer = setTimeout(resolve, CANCEL_WAIT_TIMEOUT_MS);
|
|
41
|
+
}),
|
|
42
|
+
]);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Cancellation is best-effort; the terminal state still closes after the
|
|
46
|
+
// abort hook settles or the hard deadline expires.
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
if (timer)
|
|
50
|
+
clearTimeout(timer);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
29
53
|
class BackgroundJobRegistry {
|
|
30
54
|
jobs = new Map(); // jobId -> entry (insertion-ordered)
|
|
31
55
|
listeners = new Set();
|
|
32
56
|
/** Register a running job. Invalid sessionId is ignored (cannot be waited on). */
|
|
33
|
-
start(jobId, sessionId, description = "") {
|
|
57
|
+
start(jobId, sessionId, description = "", options) {
|
|
34
58
|
if (!isValidSessionId(sessionId))
|
|
35
59
|
return;
|
|
36
60
|
this.jobs.set(jobId, {
|
|
37
61
|
jobId,
|
|
38
62
|
sessionId,
|
|
63
|
+
...(options?.kind ? { kind: options.kind } : {}),
|
|
39
64
|
description,
|
|
40
65
|
status: "running",
|
|
41
66
|
startedAt: Date.now(),
|
|
67
|
+
...(options?.cwd ? { cwd: normalizeCwdPath(options.cwd) } : {}),
|
|
68
|
+
...(options?.promptSummary ? { promptSummary: options.promptSummary } : {}),
|
|
69
|
+
...(options?.cli ? { cli: options.cli } : {}),
|
|
70
|
+
...(options?.originClientMessageId
|
|
71
|
+
? { originClientMessageId: options.originClientMessageId }
|
|
72
|
+
: {}),
|
|
73
|
+
...(options?.abort ? { abort: options.abort } : {}),
|
|
42
74
|
});
|
|
43
75
|
this.notify();
|
|
44
76
|
}
|
|
@@ -48,6 +80,8 @@ class BackgroundJobRegistry {
|
|
|
48
80
|
const entry = this.jobs.get(jobId);
|
|
49
81
|
if (!entry)
|
|
50
82
|
return;
|
|
83
|
+
if (entry.status !== "running")
|
|
84
|
+
return;
|
|
51
85
|
entry.status = outcome?.status ?? "completed";
|
|
52
86
|
entry.finishedAt = Date.now();
|
|
53
87
|
if (outcome?.finalText !== undefined)
|
|
@@ -59,31 +93,97 @@ class BackgroundJobRegistry {
|
|
|
59
93
|
this.evictTerminalOverCap(entry.sessionId);
|
|
60
94
|
this.notify();
|
|
61
95
|
}
|
|
62
|
-
|
|
96
|
+
get(jobId) {
|
|
97
|
+
return this.jobs.get(jobId);
|
|
98
|
+
}
|
|
99
|
+
/** Persist artifacts discovered while a running job is winding down. */
|
|
100
|
+
recordArtifacts(jobId, artifacts) {
|
|
101
|
+
const entry = this.jobs.get(jobId);
|
|
102
|
+
if (!entry || !isActiveStatus(entry.status))
|
|
103
|
+
return;
|
|
104
|
+
if (artifacts.ccSessionId !== undefined)
|
|
105
|
+
entry.ccSessionId = artifacts.ccSessionId;
|
|
106
|
+
if (artifacts.changedFiles !== undefined)
|
|
107
|
+
entry.changedFiles = artifacts.changedFiles;
|
|
108
|
+
}
|
|
109
|
+
async cancel(jobId, outcome) {
|
|
110
|
+
const entry = this.jobs.get(jobId);
|
|
111
|
+
if (!entry)
|
|
112
|
+
return false;
|
|
113
|
+
if (entry.status !== "running")
|
|
114
|
+
return false;
|
|
115
|
+
// Publish a non-terminal guard before invoking external code. A completion
|
|
116
|
+
// callback may synchronously re-enter finish(); it must not publish
|
|
117
|
+
// completed/failed, while cwd/session conflict checks must still see the
|
|
118
|
+
// process as active until the abort hook confirms exit.
|
|
119
|
+
entry.status = "cancelling";
|
|
120
|
+
this.notify();
|
|
121
|
+
if (entry.abort)
|
|
122
|
+
await waitForAbort(entry.abort);
|
|
123
|
+
// Session teardown/reset may have removed the entry while termination was
|
|
124
|
+
// in flight. Do not resurrect or notify for a closed session.
|
|
125
|
+
if (this.jobs.get(jobId) !== entry || entry.status !== "cancelling")
|
|
126
|
+
return false;
|
|
127
|
+
entry.status = "cancelled";
|
|
128
|
+
entry.finishedAt = Date.now();
|
|
129
|
+
if (outcome?.finalText !== undefined)
|
|
130
|
+
entry.finalText = outcome.finalText;
|
|
131
|
+
if (outcome?.ccSessionId !== undefined)
|
|
132
|
+
entry.ccSessionId = outcome.ccSessionId;
|
|
133
|
+
if (outcome?.changedFiles !== undefined)
|
|
134
|
+
entry.changedFiles = outcome.changedFiles;
|
|
135
|
+
this.evictTerminalOverCap(entry.sessionId);
|
|
136
|
+
this.notify();
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
/** True while any running/cancelling job spawned by `sessionId` remains. */
|
|
63
140
|
hasRunningForSession(sessionId) {
|
|
64
141
|
for (const e of this.jobs.values()) {
|
|
65
|
-
if (e.sessionId === sessionId && e.status
|
|
142
|
+
if (e.sessionId === sessionId && isActiveStatus(e.status))
|
|
66
143
|
return true;
|
|
67
144
|
}
|
|
68
145
|
return false;
|
|
69
146
|
}
|
|
70
147
|
/** Running jobs spawned by `sessionId`. Feeds the goal judge's task list. */
|
|
71
148
|
listRunningForSession(sessionId) {
|
|
72
|
-
return [...this.jobs.values()].filter((e) => e.sessionId === sessionId && e.status
|
|
149
|
+
return [...this.jobs.values()].filter((e) => e.sessionId === sessionId && isActiveStatus(e.status));
|
|
150
|
+
}
|
|
151
|
+
/** Running jobs, across all sessions, that are operating in the same cwd. */
|
|
152
|
+
listRunningByCwd(cwd) {
|
|
153
|
+
const normalized = normalizeCwdPath(cwd);
|
|
154
|
+
return [...this.jobs.values()].filter((e) => isActiveStatus(e.status) && e.cwd === normalized);
|
|
73
155
|
}
|
|
74
156
|
/** All jobs (running + retained terminal) for `sessionId`. Feeds the panel. */
|
|
75
157
|
listForSession(sessionId) {
|
|
76
158
|
return [...this.jobs.values()].filter((e) => e.sessionId === sessionId);
|
|
77
159
|
}
|
|
160
|
+
/** All jobs (running + retained terminal) across sessions. Feeds all-scope UI. */
|
|
161
|
+
list() {
|
|
162
|
+
return [...this.jobs.values()];
|
|
163
|
+
}
|
|
78
164
|
/** Drop every job of a session — called when the session is deleted/closed. */
|
|
79
165
|
dropForSession(sessionId) {
|
|
80
166
|
let removed = false;
|
|
167
|
+
const aborts = [];
|
|
81
168
|
for (const [id, e] of this.jobs) {
|
|
82
169
|
if (e.sessionId === sessionId) {
|
|
170
|
+
// Delete first so a synchronous/queued completion caused by abort sees
|
|
171
|
+
// no live registry entry and cannot publish a late result for a closed
|
|
172
|
+
// session. Terminal jobs have nothing left to stop.
|
|
83
173
|
this.jobs.delete(id);
|
|
174
|
+
if (isActiveStatus(e.status) && e.abort)
|
|
175
|
+
aborts.push(e.abort);
|
|
84
176
|
removed = true;
|
|
85
177
|
}
|
|
86
178
|
}
|
|
179
|
+
for (const abort of aborts) {
|
|
180
|
+
try {
|
|
181
|
+
void Promise.resolve(abort()).catch(() => undefined);
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
// teardown is best-effort across jobs; continue reaping the rest
|
|
185
|
+
}
|
|
186
|
+
}
|
|
87
187
|
if (removed)
|
|
88
188
|
this.notify();
|
|
89
189
|
}
|
|
@@ -95,12 +195,21 @@ class BackgroundJobRegistry {
|
|
|
95
195
|
};
|
|
96
196
|
/** Test helper: drop all tracked jobs. */
|
|
97
197
|
reset() {
|
|
198
|
+
const aborts = [...this.jobs.values()].flatMap((entry) => isActiveStatus(entry.status) && entry.abort ? [entry.abort] : []);
|
|
98
199
|
this.jobs.clear();
|
|
200
|
+
for (const abort of aborts) {
|
|
201
|
+
try {
|
|
202
|
+
void Promise.resolve(abort()).catch(() => undefined);
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
// ignore
|
|
206
|
+
}
|
|
207
|
+
}
|
|
99
208
|
}
|
|
100
209
|
/** Backstop: keep at most MAX_TERMINAL_JOBS_PER_SESSION terminal jobs per
|
|
101
210
|
* session, evicting the oldest (insertion order). Running jobs never evicted. */
|
|
102
211
|
evictTerminalOverCap(sessionId) {
|
|
103
|
-
const terminal = [...this.jobs.values()].filter((e) => e.sessionId === sessionId && e.status
|
|
212
|
+
const terminal = [...this.jobs.values()].filter((e) => e.sessionId === sessionId && !isActiveStatus(e.status));
|
|
104
213
|
const over = terminal.length - MAX_TERMINAL_JOBS_PER_SESSION;
|
|
105
214
|
if (over <= 0)
|
|
106
215
|
return;
|
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unified view over the THREE kinds of async background work — background
|
|
3
|
-
* sub-agents (asyncAgentRegistry), background jobs / video polls
|
|
4
|
-
* (backgroundJobRegistry), and background shells (backgroundShellManager).
|
|
5
|
-
*
|
|
6
|
-
* Used by the goal-stop-hook to show the judge LLM what's still running, so it
|
|
7
|
-
* can tell "the goal is done except for a finite task that will wake me" (a
|
|
8
|
-
* download / video render → allow stop, wait for the wakeup) from "a long-lived
|
|
9
|
-
* service that the goal doesn't depend on" (a dev server → judge the goal
|
|
10
|
-
* normally). Replacing the old mechanical `hasRunningForSession` short-circuit:
|
|
11
|
-
* a boolean can't distinguish a finite download from a never-ending dev server,
|
|
12
|
-
* but the judge — given each task's kind + command — can.
|
|
13
|
-
*/
|
|
14
1
|
import { type AsyncAgentStatus } from "./agent-registry.js";
|
|
15
2
|
import { type BackgroundJobStatus } from "./background-jobs.js";
|
|
16
3
|
import { type BgShell } from "../../runtime/background-shell.js";
|
|
@@ -30,12 +17,21 @@ export interface BackgroundWorkItem {
|
|
|
30
17
|
/** List every still-running background work item spawned by `sessionId`. */
|
|
31
18
|
export declare function listRunningBackgroundWork(sessionId: string): BackgroundWorkItem[];
|
|
32
19
|
/** One background-work row for the desktop panel, discriminated by `kind`. */
|
|
33
|
-
export
|
|
20
|
+
export interface BackgroundWorkSourceSession {
|
|
21
|
+
sessionId: string;
|
|
22
|
+
shortId: string;
|
|
23
|
+
title?: string;
|
|
24
|
+
current: boolean;
|
|
25
|
+
}
|
|
26
|
+
type WithSource<T> = T & {
|
|
27
|
+
sourceSession: BackgroundWorkSourceSession;
|
|
28
|
+
};
|
|
29
|
+
export type BackgroundWorkEntry = WithSource<{
|
|
34
30
|
kind: "shell";
|
|
35
31
|
/** Full shell snapshot — the panel already renders this shape (output/kill
|
|
36
32
|
* still go through the dedicated agent/backgroundShells RPC by shellId). */
|
|
37
33
|
shell: BgShell;
|
|
38
|
-
} | {
|
|
34
|
+
}> | WithSource<{
|
|
39
35
|
kind: "subagent";
|
|
40
36
|
agentId: string;
|
|
41
37
|
name?: string;
|
|
@@ -44,7 +40,7 @@ export type BackgroundWorkEntry = {
|
|
|
44
40
|
status: AsyncAgentStatus;
|
|
45
41
|
startedAt: number;
|
|
46
42
|
finishedAt?: number;
|
|
47
|
-
} | {
|
|
43
|
+
}> | WithSource<{
|
|
48
44
|
kind: "job";
|
|
49
45
|
jobId: string;
|
|
50
46
|
description: string;
|
|
@@ -55,7 +51,7 @@ export type BackgroundWorkEntry = {
|
|
|
55
51
|
finalText?: string;
|
|
56
52
|
/** Files an external agent (DriveAgent) changed, parsed from its transcript. */
|
|
57
53
|
changedFiles?: string[];
|
|
58
|
-
}
|
|
54
|
+
}>;
|
|
59
55
|
/**
|
|
60
56
|
* Every background-work item spawned by `sessionId`, with per-kind detail, for
|
|
61
57
|
* the desktop panel. Includes finished sub-agents that are still within their
|
|
@@ -64,4 +60,7 @@ export type BackgroundWorkEntry = {
|
|
|
64
60
|
* keep them. Jobs are only ever present while running (the registry drops them
|
|
65
61
|
* on finish).
|
|
66
62
|
*/
|
|
67
|
-
export declare function listBackgroundWorkForUI(sessionId: string
|
|
63
|
+
export declare function listBackgroundWorkForUI(sessionId: string, opts?: {
|
|
64
|
+
scope?: "session" | "all";
|
|
65
|
+
}): BackgroundWorkEntry[];
|
|
66
|
+
export {};
|
|
@@ -11,9 +11,12 @@
|
|
|
11
11
|
* a boolean can't distinguish a finite download from a never-ending dev server,
|
|
12
12
|
* but the judge — given each task's kind + command — can.
|
|
13
13
|
*/
|
|
14
|
+
import { readFileSync, statSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
14
16
|
import { asyncAgentRegistry } from "./agent-registry.js";
|
|
15
17
|
import { backgroundJobRegistry } from "./background-jobs.js";
|
|
16
18
|
import { backgroundShellManager } from "../../runtime/background-shell.js";
|
|
19
|
+
import { codeShellHome } from "../../session/session-manager.js";
|
|
17
20
|
/** List every still-running background work item spawned by `sessionId`. */
|
|
18
21
|
export function listRunningBackgroundWork(sessionId) {
|
|
19
22
|
const items = [];
|
|
@@ -39,6 +42,38 @@ export function listRunningBackgroundWork(sessionId) {
|
|
|
39
42
|
}
|
|
40
43
|
return items;
|
|
41
44
|
}
|
|
45
|
+
const sessionTitleCache = new Map();
|
|
46
|
+
function shortSessionId(sessionId) {
|
|
47
|
+
return sessionId.length <= 10 ? sessionId : sessionId.slice(0, 10);
|
|
48
|
+
}
|
|
49
|
+
function readSessionTitle(sessionId) {
|
|
50
|
+
try {
|
|
51
|
+
const statePath = join(codeShellHome(), "sessions", sessionId, "state.json");
|
|
52
|
+
const st = statSync(statePath);
|
|
53
|
+
const cached = sessionTitleCache.get(sessionId);
|
|
54
|
+
if (cached && cached.mtimeMs === st.mtimeMs)
|
|
55
|
+
return cached.title;
|
|
56
|
+
const raw = JSON.parse(readFileSync(statePath, "utf8"));
|
|
57
|
+
const title = typeof raw.title === "string" && raw.title.trim()
|
|
58
|
+
? raw.title.trim()
|
|
59
|
+
: typeof raw.summary === "string" && raw.summary.trim()
|
|
60
|
+
? raw.summary.trim()
|
|
61
|
+
: undefined;
|
|
62
|
+
sessionTitleCache.set(sessionId, { mtimeMs: st.mtimeMs, title });
|
|
63
|
+
return title;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function sourceSession(currentSessionId, ownerSessionId) {
|
|
70
|
+
return {
|
|
71
|
+
sessionId: ownerSessionId,
|
|
72
|
+
shortId: shortSessionId(ownerSessionId),
|
|
73
|
+
title: readSessionTitle(ownerSessionId),
|
|
74
|
+
current: ownerSessionId === currentSessionId,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
42
77
|
/**
|
|
43
78
|
* Every background-work item spawned by `sessionId`, with per-kind detail, for
|
|
44
79
|
* the desktop panel. Includes finished sub-agents that are still within their
|
|
@@ -47,18 +82,24 @@ export function listRunningBackgroundWork(sessionId) {
|
|
|
47
82
|
* keep them. Jobs are only ever present while running (the registry drops them
|
|
48
83
|
* on finish).
|
|
49
84
|
*/
|
|
50
|
-
export function listBackgroundWorkForUI(sessionId) {
|
|
85
|
+
export function listBackgroundWorkForUI(sessionId, opts = {}) {
|
|
51
86
|
const entries = [];
|
|
52
|
-
|
|
53
|
-
|
|
87
|
+
const scope = opts.scope ?? "session";
|
|
88
|
+
const shells = scope === "all"
|
|
89
|
+
? backgroundShellManager.list()
|
|
90
|
+
: backgroundShellManager.listForSession(sessionId);
|
|
91
|
+
for (const s of shells) {
|
|
92
|
+
entries.push({ kind: "shell", shell: s, sourceSession: sourceSession(sessionId, s.sessionId) });
|
|
54
93
|
}
|
|
55
94
|
const now = Date.now();
|
|
56
|
-
|
|
95
|
+
const agents = scope === "all" ? asyncAgentRegistry.list() : asyncAgentRegistry.listForSession(sessionId);
|
|
96
|
+
for (const a of agents) {
|
|
57
97
|
// Keep running agents, plus finished ones still inside their fade window so
|
|
58
98
|
// a completion is briefly visible. (finishedFadeAt = finishedAt + 30s.)
|
|
59
99
|
const fresh = a.status === "running" || (a.finishedFadeAt != null && a.finishedFadeAt > now);
|
|
60
100
|
if (!fresh)
|
|
61
101
|
continue;
|
|
102
|
+
const ownerSessionId = a.sessionId ?? sessionId;
|
|
62
103
|
entries.push({
|
|
63
104
|
kind: "subagent",
|
|
64
105
|
agentId: a.agentId,
|
|
@@ -68,9 +109,13 @@ export function listBackgroundWorkForUI(sessionId) {
|
|
|
68
109
|
status: a.status,
|
|
69
110
|
startedAt: a.startedAt,
|
|
70
111
|
finishedAt: a.finishedAt,
|
|
112
|
+
sourceSession: sourceSession(sessionId, ownerSessionId),
|
|
71
113
|
});
|
|
72
114
|
}
|
|
73
|
-
|
|
115
|
+
const jobs = scope === "all"
|
|
116
|
+
? backgroundJobRegistry.list()
|
|
117
|
+
: backgroundJobRegistry.listForSession(sessionId);
|
|
118
|
+
for (const j of jobs) {
|
|
74
119
|
entries.push({
|
|
75
120
|
kind: "job",
|
|
76
121
|
jobId: j.jobId,
|
|
@@ -80,6 +125,7 @@ export function listBackgroundWorkForUI(sessionId) {
|
|
|
80
125
|
...(j.finishedAt != null ? { finishedAt: j.finishedAt } : {}),
|
|
81
126
|
...(j.finalText != null ? { finalText: j.finalText } : {}),
|
|
82
127
|
...(j.changedFiles && j.changedFiles.length ? { changedFiles: j.changedFiles } : {}),
|
|
128
|
+
sourceSession: sourceSession(sessionId, j.sessionId),
|
|
83
129
|
});
|
|
84
130
|
}
|
|
85
131
|
return entries;
|
|
@@ -2,5 +2,6 @@
|
|
|
2
2
|
* ConfigTool — read or update project settings.
|
|
3
3
|
*/
|
|
4
4
|
import type { ToolDefinition } from "../../types.js";
|
|
5
|
+
import type { ToolContext } from "../context.js";
|
|
5
6
|
export declare const configToolDef: ToolDefinition;
|
|
6
|
-
export declare function configTool(args: Record<string, unknown
|
|
7
|
+
export declare function configTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
|