@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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Permission system — classifier + approval backend.
|
|
3
3
|
*/
|
|
4
4
|
import { resolve as resolvePath, dirname } from "node:path";
|
|
5
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from "node:fs";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
7
|
import { logger as rootPermLogger } from "../logging/logger.js";
|
|
8
8
|
import { READ_ONLY_TOOLS } from "./plan-mode-allowlist.js";
|
|
@@ -93,6 +93,17 @@ export class AutoApprovalBackend {
|
|
|
93
93
|
return false;
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Closed-session tombstones are a bounded replay guard. A prompt that started
|
|
98
|
+
* before close is still protected by the state-object identity check in
|
|
99
|
+
* isActiveSessionState(): clearSession deletes the captured state, so the late
|
|
100
|
+
* result cannot write into a new bucket even if an old tombstone has aged out.
|
|
101
|
+
* The tombstone only blocks fresh post-close calls carrying a recently closed
|
|
102
|
+
* sessionId from creating an empty bucket. 4096 is 256x the default
|
|
103
|
+
* ChatSessionManager.maxSessions (16), which covers normal late-result bursts
|
|
104
|
+
* while keeping long-lived processes from retaining every historical id.
|
|
105
|
+
*/
|
|
106
|
+
export const CLOSED_SESSION_TOMBSTONE_LIMIT = 4096;
|
|
96
107
|
/**
|
|
97
108
|
* Interactive approval backend — prompts the user via a callback.
|
|
98
109
|
*
|
|
@@ -106,29 +117,21 @@ export class AutoApprovalBackend {
|
|
|
106
117
|
* the next time the user opens the project.
|
|
107
118
|
*/
|
|
108
119
|
export class InteractiveApprovalBackend {
|
|
109
|
-
// Session-scoped grants
|
|
110
|
-
//
|
|
111
|
-
// the
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
120
|
+
// Session-scoped grants are bucketed by ApprovalRequest.sessionId and then
|
|
121
|
+
// keyed on the OPERATION (tool + narrowed argsPattern via buildProjectRule),
|
|
122
|
+
// NOT just the tool name. Approving `git status` for one session must not
|
|
123
|
+
// auto-allow either `rm -rf /` in that same session or `git ...` in another.
|
|
124
|
+
// Allow and deny are tracked separately so a one-off deny of `curl evil`
|
|
125
|
+
// never blocks an unrelated `git status`.
|
|
126
|
+
sessionStateById = new Map();
|
|
127
|
+
closedSessionIds = new Set();
|
|
116
128
|
promptFn = null;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
savedProjectRules = [];
|
|
124
|
-
onProjectRules = null;
|
|
125
|
-
// Serialize prompts so a burst of parallel tool calls doesn't queue N
|
|
126
|
-
// identical cards: while one ask is outstanding, later requests wait here
|
|
127
|
-
// and RE-CHECK the session rules when their turn comes — the first
|
|
128
|
-
// "本会话一直允许" answer then silently absorbs the queued duplicates.
|
|
129
|
-
// (All callers were already serialized at the UI anyway — the renderer
|
|
130
|
-
// shows one approval card at a time.)
|
|
131
|
-
promptTurn = Promise.resolve();
|
|
129
|
+
legacyPromptTurn = Promise.resolve();
|
|
130
|
+
legacyContext = {
|
|
131
|
+
cwd: null,
|
|
132
|
+
savedProjectRules: [],
|
|
133
|
+
onProjectRules: null,
|
|
134
|
+
};
|
|
132
135
|
setPromptFn(fn) {
|
|
133
136
|
this.promptFn = fn;
|
|
134
137
|
}
|
|
@@ -144,7 +147,7 @@ export class InteractiveApprovalBackend {
|
|
|
144
147
|
}
|
|
145
148
|
/** Inject the project root so persistence writes to the right settings file. */
|
|
146
149
|
setCwd(cwd) {
|
|
147
|
-
this.cwd = cwd;
|
|
150
|
+
this.legacyContext.cwd = cwd;
|
|
148
151
|
}
|
|
149
152
|
/**
|
|
150
153
|
* Inject a callback fired when the user approves "for this project". The
|
|
@@ -153,11 +156,68 @@ export class InteractiveApprovalBackend {
|
|
|
153
156
|
* earlier approvals.
|
|
154
157
|
*/
|
|
155
158
|
setOnProjectRules(fn) {
|
|
156
|
-
this.onProjectRules = fn;
|
|
159
|
+
this.legacyContext.onProjectRules = fn;
|
|
160
|
+
}
|
|
161
|
+
setSessionContext(sessionId, context) {
|
|
162
|
+
const state = this.getSessionState(sessionId, true);
|
|
163
|
+
if (!state)
|
|
164
|
+
return;
|
|
165
|
+
state.cwd = context.cwd;
|
|
166
|
+
state.onProjectRules = context.onProjectRules;
|
|
167
|
+
}
|
|
168
|
+
openSession(sessionId) {
|
|
169
|
+
if (!sessionId)
|
|
170
|
+
return;
|
|
171
|
+
this.closedSessionIds.delete(sessionId);
|
|
172
|
+
}
|
|
173
|
+
clearSession(sessionId) {
|
|
174
|
+
if (!sessionId)
|
|
175
|
+
return;
|
|
176
|
+
this.sessionStateById.delete(sessionId);
|
|
177
|
+
this.rememberClosedSession(sessionId);
|
|
178
|
+
}
|
|
179
|
+
rememberClosedSession(sessionId) {
|
|
180
|
+
this.closedSessionIds.delete(sessionId);
|
|
181
|
+
this.closedSessionIds.add(sessionId);
|
|
182
|
+
while (this.closedSessionIds.size > CLOSED_SESSION_TOMBSTONE_LIMIT) {
|
|
183
|
+
const oldest = this.closedSessionIds.values().next().value;
|
|
184
|
+
if (oldest === undefined)
|
|
185
|
+
break;
|
|
186
|
+
this.closedSessionIds.delete(oldest);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
makeSessionState() {
|
|
190
|
+
return {
|
|
191
|
+
allowRules: [],
|
|
192
|
+
denyRules: [],
|
|
193
|
+
promptTurn: Promise.resolve(),
|
|
194
|
+
cwd: null,
|
|
195
|
+
savedProjectRules: [],
|
|
196
|
+
onProjectRules: null,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
getSessionState(sessionId, create) {
|
|
200
|
+
if (!sessionId)
|
|
201
|
+
return null;
|
|
202
|
+
if (this.closedSessionIds.has(sessionId))
|
|
203
|
+
return null;
|
|
204
|
+
const existing = this.sessionStateById.get(sessionId);
|
|
205
|
+
if (existing || !create)
|
|
206
|
+
return existing ?? null;
|
|
207
|
+
const next = this.makeSessionState();
|
|
208
|
+
this.sessionStateById.set(sessionId, next);
|
|
209
|
+
return next;
|
|
210
|
+
}
|
|
211
|
+
isActiveSessionState(sessionId, state) {
|
|
212
|
+
return (!!sessionId &&
|
|
213
|
+
!!state &&
|
|
214
|
+
!this.closedSessionIds.has(sessionId) &&
|
|
215
|
+
this.sessionStateById.get(sessionId) === state);
|
|
157
216
|
}
|
|
158
217
|
async requestApproval(req) {
|
|
218
|
+
const state = this.getSessionState(req.sessionId, true);
|
|
159
219
|
// Fast path: the operation may already be covered by a session rule.
|
|
160
|
-
const cached = this.checkSessionRules(req);
|
|
220
|
+
const cached = state ? this.checkSessionRules(req, state) : null;
|
|
161
221
|
if (cached)
|
|
162
222
|
return cached;
|
|
163
223
|
if (!this.promptFn) {
|
|
@@ -167,51 +227,68 @@ export class InteractiveApprovalBackend {
|
|
|
167
227
|
// field doc): a burst of parallel tool calls all passes the fast path
|
|
168
228
|
// before the first decision lands; without the re-check the user had to
|
|
169
229
|
// answer one card per duplicate.
|
|
170
|
-
const prevTurn = this.
|
|
230
|
+
const prevTurn = state ? state.promptTurn : this.legacyPromptTurn;
|
|
171
231
|
let release;
|
|
172
|
-
|
|
232
|
+
const currentTurn = new Promise((r) => (release = r));
|
|
233
|
+
if (state) {
|
|
234
|
+
state.promptTurn = currentTurn;
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
this.legacyPromptTurn = currentTurn;
|
|
238
|
+
}
|
|
173
239
|
try {
|
|
174
240
|
await prevTurn;
|
|
175
|
-
const
|
|
241
|
+
const activeState = this.isActiveSessionState(req.sessionId, state) ? state : null;
|
|
242
|
+
const nowCached = activeState ? this.checkSessionRules(req, activeState) : null;
|
|
176
243
|
if (nowCached)
|
|
177
244
|
return nowCached;
|
|
178
|
-
return await this.promptAndRecord(req);
|
|
245
|
+
return await this.promptAndRecord(req, activeState);
|
|
179
246
|
}
|
|
180
247
|
finally {
|
|
181
248
|
release();
|
|
182
249
|
}
|
|
183
250
|
}
|
|
184
|
-
/** Session-rule lookup — operation-scoped (see
|
|
251
|
+
/** Session-rule lookup — operation-scoped (see sessionStateById doc). Deny
|
|
185
252
|
* wins over allow if both somehow match (conservative). Null = no rule. */
|
|
186
|
-
checkSessionRules(req) {
|
|
187
|
-
if (
|
|
253
|
+
checkSessionRules(req, state) {
|
|
254
|
+
if (state.denyRules.some((r) => ruleMatches(r, req.toolName, req.args))) {
|
|
188
255
|
return { approved: false };
|
|
189
256
|
}
|
|
190
|
-
if (
|
|
257
|
+
if (state.allowRules.some((r) => ruleMatches(r, req.toolName, req.args))) {
|
|
191
258
|
return { approved: true };
|
|
192
259
|
}
|
|
193
260
|
return null;
|
|
194
261
|
}
|
|
195
262
|
/** The actual interactive ask + rule recording (runs inside the prompt turn). */
|
|
196
|
-
async promptAndRecord(req) {
|
|
263
|
+
async promptAndRecord(req, state) {
|
|
197
264
|
if (!this.promptFn) {
|
|
198
265
|
return { approved: false, reason: "interactive approval backend has no prompt function" };
|
|
199
266
|
}
|
|
200
267
|
const result = await this.promptFn(req);
|
|
201
268
|
const scope = result.scope ?? (result.always ? "session" : "once");
|
|
269
|
+
const activeState = this.isActiveSessionState(req.sessionId, state) ? state : null;
|
|
270
|
+
const context = activeState ?? (!req.sessionId ? this.legacyContext : null);
|
|
202
271
|
// Path narrowing only rides on an APPROVE: a path-scoped deny is confusing
|
|
203
272
|
// (deny stays tool-wide). pathScope is ignored by buildProjectRule for
|
|
204
273
|
// non-file tools / when absent.
|
|
205
274
|
const ruleOpts = result.approved
|
|
206
|
-
? { pathScope: result.pathScope, cwd:
|
|
275
|
+
? { pathScope: result.pathScope, cwd: context?.cwd ?? undefined }
|
|
207
276
|
: undefined;
|
|
208
277
|
if (scope === "session" && result.always) {
|
|
278
|
+
if (!activeState) {
|
|
279
|
+
rootPermLogger.warn("permission.session_remember_ignored", {
|
|
280
|
+
cat: "permission",
|
|
281
|
+
tool: req.toolName,
|
|
282
|
+
reason: req.sessionId ? "session_closed" : "missing_session_id",
|
|
283
|
+
});
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
209
286
|
// Narrow to the operation (Bash → head command, file tools → path scope)
|
|
210
287
|
// so the session grant is scoped, not tool-wide. A rule with no
|
|
211
288
|
// argsPattern keeps the prior tool-granularity behavior.
|
|
212
289
|
const rule = buildProjectRule(req.toolName, req.args, ruleOpts);
|
|
213
290
|
if (rule) {
|
|
214
|
-
const target = result.approved ?
|
|
291
|
+
const target = result.approved ? activeState.allowRules : activeState.denyRules;
|
|
215
292
|
const dup = target.some((r) => r.tool === rule.tool &&
|
|
216
293
|
JSON.stringify(r.argsPattern) === JSON.stringify(rule.argsPattern));
|
|
217
294
|
if (!dup) {
|
|
@@ -225,23 +302,23 @@ export class InteractiveApprovalBackend {
|
|
|
225
302
|
// We only persist allow rules — denies stay session-only because a
|
|
226
303
|
// persisted deny is harder to recover from than a session deny.
|
|
227
304
|
const rule = buildProjectRule(req.toolName, req.args, ruleOpts);
|
|
228
|
-
if (rule &&
|
|
305
|
+
if (rule && context?.cwd) {
|
|
229
306
|
try {
|
|
230
|
-
persistProjectRule(
|
|
307
|
+
persistProjectRule(context.cwd, rule);
|
|
231
308
|
// Dedup against the in-memory list using the same equality used by
|
|
232
309
|
// persistProjectRule so re-prompts on the same tool/argsPattern
|
|
233
310
|
// don't bloat the live rule set.
|
|
234
|
-
const dup =
|
|
311
|
+
const dup = context.savedProjectRules.some((r) => r.tool === rule.tool &&
|
|
235
312
|
r.decision === rule.decision &&
|
|
236
313
|
JSON.stringify(r.argsPattern) === JSON.stringify(rule.argsPattern));
|
|
237
314
|
if (!dup)
|
|
238
|
-
|
|
239
|
-
|
|
315
|
+
context.savedProjectRules.push(rule);
|
|
316
|
+
context.onProjectRules?.(context.savedProjectRules);
|
|
240
317
|
rootPermLogger.info("permission.persist", {
|
|
241
318
|
cat: "permission",
|
|
242
319
|
tool: rule.tool,
|
|
243
320
|
decision: rule.decision,
|
|
244
|
-
totalProjectRules:
|
|
321
|
+
totalProjectRules: context.savedProjectRules.length,
|
|
245
322
|
duplicate: dup,
|
|
246
323
|
});
|
|
247
324
|
}
|
|
@@ -258,11 +335,11 @@ export class InteractiveApprovalBackend {
|
|
|
258
335
|
// Also seed the session allow list (operation-scoped) so the rest of
|
|
259
336
|
// this REPL session benefits even if the classifier path doesn't pick
|
|
260
337
|
// the rule up immediately.
|
|
261
|
-
if (rule) {
|
|
262
|
-
const dup =
|
|
338
|
+
if (rule && activeState) {
|
|
339
|
+
const dup = activeState.allowRules.some((r) => r.tool === rule.tool &&
|
|
263
340
|
JSON.stringify(r.argsPattern) === JSON.stringify(rule.argsPattern));
|
|
264
341
|
if (!dup)
|
|
265
|
-
|
|
342
|
+
activeState.allowRules.push(rule);
|
|
266
343
|
}
|
|
267
344
|
}
|
|
268
345
|
return result;
|
|
@@ -452,6 +529,12 @@ export function getInteractiveApprovalBackend() {
|
|
|
452
529
|
}
|
|
453
530
|
return _interactiveBackend;
|
|
454
531
|
}
|
|
532
|
+
export function openInteractiveApprovalSession(sessionId) {
|
|
533
|
+
getInteractiveApprovalBackend().openSession(sessionId);
|
|
534
|
+
}
|
|
535
|
+
export function clearInteractiveApprovalSession(sessionId) {
|
|
536
|
+
getInteractiveApprovalBackend().clearSession(sessionId);
|
|
537
|
+
}
|
|
455
538
|
export function setInteractiveApprovalFn(fn) {
|
|
456
539
|
getInteractiveApprovalBackend().setPromptFn(fn);
|
|
457
540
|
}
|
|
@@ -896,9 +979,7 @@ export class PermissionClassifier {
|
|
|
896
979
|
let result;
|
|
897
980
|
try {
|
|
898
981
|
const baseDescription = this.describeToolCall(toolName, args);
|
|
899
|
-
const description = reason
|
|
900
|
-
? `${baseDescription}\n\nReason (from pre_tool_use hook): ${reason}`
|
|
901
|
-
: baseDescription;
|
|
982
|
+
const description = reason ? `${baseDescription}\n\nReason:\n${reason}` : baseDescription;
|
|
902
983
|
result = await this.approvalBackend.requestApproval({
|
|
903
984
|
...(opts?.sessionId ? { sessionId: opts.sessionId } : {}),
|
|
904
985
|
toolName,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unified tool registry — built-in tools + MCP tools.
|
|
3
3
|
*/
|
|
4
|
-
import { ConfigError, ToolNotFoundError, ToolExecutionError, ToolTimeoutError } from "../exceptions.js";
|
|
4
|
+
import { ConfigError, ToolNotFoundError, ToolExecutionError, ToolTimeoutError, } from "../exceptions.js";
|
|
5
5
|
import { BUILTIN_TOOLS } from "./builtin/index.js";
|
|
6
6
|
import { validateToolMetadata } from "./validate-tool-metadata.js";
|
|
7
7
|
/**
|
|
@@ -22,7 +22,9 @@ export class ToolRegistry {
|
|
|
22
22
|
if (selectedNames) {
|
|
23
23
|
const unknown = [...selectedNames].filter((name) => !availableNames.has(name));
|
|
24
24
|
if (unknown.length > 0) {
|
|
25
|
-
throw new ConfigError(`Unknown built-in tool(s): ${unknown.join(", ")}`, {
|
|
25
|
+
throw new ConfigError(`Unknown built-in tool(s): ${unknown.join(", ")}`, {
|
|
26
|
+
unknownBuiltinTools: unknown,
|
|
27
|
+
});
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
for (const tool of BUILTIN_TOOLS) {
|
|
@@ -120,12 +122,18 @@ export class ToolRegistry {
|
|
|
120
122
|
// 各取所有,缺的字段为 undefined。
|
|
121
123
|
const contentBlocks = "contentBlocks" in result ? result.contentBlocks : undefined;
|
|
122
124
|
const sandbox = "sandbox" in result ? result.sandbox : undefined;
|
|
125
|
+
const sensitive = "sensitive" in result ? result.sensitive : undefined;
|
|
126
|
+
const displayResult = "displayResult" in result ? result.displayResult : undefined;
|
|
127
|
+
const transcriptResult = "transcriptResult" in result ? result.transcriptResult : undefined;
|
|
123
128
|
return {
|
|
124
129
|
id,
|
|
125
130
|
toolName: name,
|
|
126
131
|
result: result.result ?? (contentBlocks ? "(image)" : ""),
|
|
127
132
|
contentBlocks,
|
|
128
133
|
sandbox,
|
|
134
|
+
sensitive,
|
|
135
|
+
displayResult,
|
|
136
|
+
transcriptResult,
|
|
129
137
|
};
|
|
130
138
|
}
|
|
131
139
|
catch (err) {
|
|
@@ -133,8 +141,7 @@ export class ToolRegistry {
|
|
|
133
141
|
parentSignal?.removeEventListener("abort", onParentAbort);
|
|
134
142
|
// Always return error as ToolResult, never throw
|
|
135
143
|
let errorMsg;
|
|
136
|
-
const isAbort = err?.name === "AbortError" ||
|
|
137
|
-
parentSignal?.aborted === true;
|
|
144
|
+
const isAbort = err?.name === "AbortError" || parentSignal?.aborted === true;
|
|
138
145
|
if (err instanceof ToolTimeoutError) {
|
|
139
146
|
errorMsg = `Tool timed out after ${timeout}ms: ${name}`;
|
|
140
147
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Message, ToolResult } from "../types.js";
|
|
2
|
+
export declare const SENSITIVE_TOOL_RESULT_PLACEHOLDER = "[credential value withheld]";
|
|
3
|
+
export declare function toolResultDisplayText(result: ToolResult): string | undefined;
|
|
4
|
+
export declare function toolResultTranscriptText(result: ToolResult): string | undefined;
|
|
5
|
+
export declare function toolResultForDisplay(result: ToolResult): ToolResult;
|
|
6
|
+
export declare function toolResultsForDisplay(results: ToolResult[]): ToolResult[];
|
|
7
|
+
export declare function redactSensitiveToolResultsInMessages(messages: Message[], redactions: ReadonlyMap<string, string>): Message[];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export const SENSITIVE_TOOL_RESULT_PLACEHOLDER = "[credential value withheld]";
|
|
2
|
+
export function toolResultDisplayText(result) {
|
|
3
|
+
if (!result.sensitive)
|
|
4
|
+
return result.result;
|
|
5
|
+
return result.displayResult ?? result.transcriptResult ?? SENSITIVE_TOOL_RESULT_PLACEHOLDER;
|
|
6
|
+
}
|
|
7
|
+
export function toolResultTranscriptText(result) {
|
|
8
|
+
if (!result.sensitive)
|
|
9
|
+
return result.result;
|
|
10
|
+
return result.transcriptResult ?? result.displayResult ?? SENSITIVE_TOOL_RESULT_PLACEHOLDER;
|
|
11
|
+
}
|
|
12
|
+
export function toolResultForDisplay(result) {
|
|
13
|
+
if (!result.sensitive)
|
|
14
|
+
return result;
|
|
15
|
+
const { displayResult: _displayResult, transcriptResult: _transcriptResult, ...rest } = result;
|
|
16
|
+
return {
|
|
17
|
+
...rest,
|
|
18
|
+
result: toolResultDisplayText(result),
|
|
19
|
+
contentBlocks: undefined,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function toolResultsForDisplay(results) {
|
|
23
|
+
return results.map((result) => toolResultForDisplay(result));
|
|
24
|
+
}
|
|
25
|
+
export function redactSensitiveToolResultsInMessages(messages, redactions) {
|
|
26
|
+
if (redactions.size === 0)
|
|
27
|
+
return messages;
|
|
28
|
+
let changed = false;
|
|
29
|
+
const out = messages.map((message) => {
|
|
30
|
+
if (!Array.isArray(message.content))
|
|
31
|
+
return message;
|
|
32
|
+
let contentChanged = false;
|
|
33
|
+
const content = message.content.map((block) => {
|
|
34
|
+
if (block.type !== "tool_result")
|
|
35
|
+
return block;
|
|
36
|
+
const replacement = typeof block.tool_use_id === "string" ? redactions.get(block.tool_use_id) : undefined;
|
|
37
|
+
if (replacement === undefined)
|
|
38
|
+
return block;
|
|
39
|
+
contentChanged = true;
|
|
40
|
+
return { ...block, content: replacement };
|
|
41
|
+
});
|
|
42
|
+
if (!contentChanged)
|
|
43
|
+
return message;
|
|
44
|
+
changed = true;
|
|
45
|
+
return { ...message, content };
|
|
46
|
+
});
|
|
47
|
+
return changed ? out : messages;
|
|
48
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SessionWorkspace } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* WorkspaceBridge — host-backed session workspace switching.
|
|
4
|
+
*
|
|
5
|
+
* Desktop implements this through Electron main so model-initiated switches use
|
|
6
|
+
* the same service path as the UI workspace switcher. Undefined in headless or
|
|
7
|
+
* non-desktop contexts.
|
|
8
|
+
*/
|
|
9
|
+
export interface WorkspaceBridge {
|
|
10
|
+
switch(target: string): Promise<SessionWorkspace>;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Core type definitions for the code-shell orchestration framework.
|
|
3
3
|
*/
|
|
4
|
-
import type { GoalConfig } from "./engine/goal.js";
|
|
4
|
+
import type { GoalConfig, GoalTerminal } from "./engine/goal.js";
|
|
5
5
|
export interface ContentBlock {
|
|
6
6
|
type: "text" | "tool_use" | "tool_result" | "image" | "reasoning";
|
|
7
7
|
text?: string;
|
|
@@ -43,7 +43,15 @@ export interface ToolCall {
|
|
|
43
43
|
export interface ToolResult {
|
|
44
44
|
id: string;
|
|
45
45
|
toolName: string;
|
|
46
|
+
/**
|
|
47
|
+
* Sensitive tool results keep `result` as the model-facing value for the
|
|
48
|
+
* current model round only. Persisted/displayed/streamed observers must use
|
|
49
|
+
* `transcriptResult`/`displayResult` (or the standard placeholder) instead.
|
|
50
|
+
*/
|
|
51
|
+
sensitive?: boolean;
|
|
46
52
|
result?: string;
|
|
53
|
+
displayResult?: string;
|
|
54
|
+
transcriptResult?: string;
|
|
47
55
|
/**
|
|
48
56
|
* 结构化结果块(目前仅图片)。存在时优先于 `result` 用作发给 LLM 的
|
|
49
57
|
* tool_result content —— view_image 用它把本地图片以 image ContentBlock
|
|
@@ -54,13 +62,13 @@ export interface ToolResult {
|
|
|
54
62
|
error?: string;
|
|
55
63
|
isError?: boolean;
|
|
56
64
|
/**
|
|
57
|
-
* Set by tools
|
|
58
|
-
* worktree) so the UI can show whether THIS call was isolated. `backend`
|
|
65
|
+
* Set by command-executing tools with sandbox visibility (Bash / background
|
|
66
|
+
* shell / worktree / PowerShell) so the UI can show whether THIS call was isolated. `backend`
|
|
59
67
|
* "off" means the command ran un-sandboxed (we surface it explicitly so the
|
|
60
68
|
* user sees "未隔离" rather than guessing from an absent badge); "seatbelt"
|
|
61
69
|
* / "bwrap" mean OS-level isolation applied. `network` is the policy that
|
|
62
|
-
* was in force (absent when off). Tools
|
|
63
|
-
*
|
|
70
|
+
* was in force (absent when off). Tools with no sandbox visibility leave this
|
|
71
|
+
* undefined and the UI renders no badge.
|
|
64
72
|
*/
|
|
65
73
|
sandbox?: {
|
|
66
74
|
backend: "off" | "seatbelt" | "bwrap";
|
|
@@ -97,6 +105,12 @@ export interface RegisteredTool {
|
|
|
97
105
|
inputSchema: Record<string, unknown>;
|
|
98
106
|
source: ToolSource;
|
|
99
107
|
serverName?: string;
|
|
108
|
+
/**
|
|
109
|
+
* Declarative UI/metadata hint for hosts, docs, and capability listings.
|
|
110
|
+
* It is not an execution-policy input: PermissionClassifier does not read
|
|
111
|
+
* RegisteredTool and runtime decisions come from explicit rules, permission
|
|
112
|
+
* mode, approval backend, and tool-specific gates.
|
|
113
|
+
*/
|
|
100
114
|
permissionDefault: PermissionDecision;
|
|
101
115
|
isConcurrencySafe?: boolean;
|
|
102
116
|
isReadOnly?: boolean;
|
|
@@ -119,7 +133,7 @@ export interface RegisteredTool {
|
|
|
119
133
|
*/
|
|
120
134
|
timeoutMs?: number;
|
|
121
135
|
}
|
|
122
|
-
export type TranscriptEventType = "message" | "tool_use" | "tool_result" | "summary" | "content_replace" | "file_history" | "plan_operation" | "session_meta" | "subagent" | "turn_boundary" | "goal_progress" | "turn_stopped" | "error";
|
|
136
|
+
export type TranscriptEventType = "message" | "tool_use" | "tool_result" | "summary" | "content_replace" | "file_history" | "plan_operation" | "session_meta" | "subagent" | "external_file_changes" | "turn_boundary" | "goal_progress" | "turn_stopped" | "error";
|
|
123
137
|
export interface TranscriptEvent {
|
|
124
138
|
id: string;
|
|
125
139
|
type: TranscriptEventType;
|
|
@@ -139,9 +153,29 @@ export type SessionStatus = "active" | "paused" | TerminalReason;
|
|
|
139
153
|
/** Which host/context created a session — used by the desktop disk-rebuild to
|
|
140
154
|
* filter the sidebar (only `desktop` + `automation` are shown). */
|
|
141
155
|
export type SessionOrigin = "desktop" | "tui" | "automation" | "subagent";
|
|
156
|
+
export interface SessionWorkspace {
|
|
157
|
+
root: string;
|
|
158
|
+
kind: "main" | "worktree";
|
|
159
|
+
worktree?: {
|
|
160
|
+
path: string;
|
|
161
|
+
branch: string;
|
|
162
|
+
baseRef: string;
|
|
163
|
+
createdBy: "codeshell";
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
export interface ContextUsageAnchor {
|
|
167
|
+
promptTokens: number;
|
|
168
|
+
messageCount: number;
|
|
169
|
+
estimateAtAnchor?: number;
|
|
170
|
+
recordedAt: number;
|
|
171
|
+
provider?: string;
|
|
172
|
+
model?: string;
|
|
173
|
+
}
|
|
142
174
|
export interface SessionState {
|
|
143
175
|
sessionId: string;
|
|
144
176
|
cwd: string;
|
|
177
|
+
/** Current session workspace pointer. Absent only on legacy state.json files. */
|
|
178
|
+
workspace?: SessionWorkspace;
|
|
145
179
|
startedAt: number;
|
|
146
180
|
model: string;
|
|
147
181
|
provider: string;
|
|
@@ -150,6 +184,12 @@ export interface SessionState {
|
|
|
150
184
|
* (for example model switches), so it must not drive whole-session metrics.
|
|
151
185
|
*/
|
|
152
186
|
tokenUsage: TokenUsage;
|
|
187
|
+
/**
|
|
188
|
+
* Last provider-reported prompt-token count for the current context window.
|
|
189
|
+
* Separate from cumulative tokenUsage; used only to seed context-size estimates
|
|
190
|
+
* before the next provider response.
|
|
191
|
+
*/
|
|
192
|
+
contextUsageAnchor?: ContextUsageAnchor;
|
|
153
193
|
/**
|
|
154
194
|
* Monotonic prompt-cache counters for the whole session. These only increase
|
|
155
195
|
* from session start and are separate from the resettable tokenUsage window.
|
|
@@ -202,6 +242,12 @@ export interface SessionState {
|
|
|
202
242
|
* baselines reset (matching CC). See engine.run goal-resolution.
|
|
203
243
|
*/
|
|
204
244
|
activeGoal?: GoalConfig;
|
|
245
|
+
/**
|
|
246
|
+
* Last force-terminated goal instance. Kept separately from activeGoal so an
|
|
247
|
+
* old whole-state writer cannot make that same exhausted goal armable again.
|
|
248
|
+
* Optional for backward compatibility with pre-tombstone state.json files.
|
|
249
|
+
*/
|
|
250
|
+
goalTerminal?: GoalTerminal;
|
|
205
251
|
}
|
|
206
252
|
export interface TokenUsage {
|
|
207
253
|
promptTokens: number;
|
|
@@ -293,10 +339,14 @@ export interface TaskInfo {
|
|
|
293
339
|
activeForm?: string;
|
|
294
340
|
status: "pending" | "in_progress" | "completed" | "stopped";
|
|
295
341
|
}
|
|
342
|
+
export type PromptTokenSource = "provider_usage" | "anchor_delta" | "anchor_rescale" | "calibrated_estimate" | "heuristic_estimate" | "session_cumulative";
|
|
343
|
+
export type PromptTokenConfidence = "high" | "medium" | "low";
|
|
296
344
|
export type StreamEvent = {
|
|
297
345
|
type: "session_started";
|
|
298
346
|
sessionId: string;
|
|
299
347
|
promptTokens: number;
|
|
348
|
+
promptTokensSource?: PromptTokenSource;
|
|
349
|
+
promptTokensConfidence?: PromptTokenConfidence;
|
|
300
350
|
} | {
|
|
301
351
|
type: "session_title";
|
|
302
352
|
sessionId: string;
|
|
@@ -304,6 +354,7 @@ export type StreamEvent = {
|
|
|
304
354
|
} | {
|
|
305
355
|
type: "stream_request_start";
|
|
306
356
|
turnNumber: number;
|
|
357
|
+
messageId?: string;
|
|
307
358
|
agentId?: string;
|
|
308
359
|
} | {
|
|
309
360
|
type: "steer_injected";
|
|
@@ -330,6 +381,7 @@ export type StreamEvent = {
|
|
|
330
381
|
} | {
|
|
331
382
|
type: "assistant_message";
|
|
332
383
|
message: Message;
|
|
384
|
+
messageId?: string;
|
|
333
385
|
agentId?: string;
|
|
334
386
|
} | {
|
|
335
387
|
type: "turn_complete";
|
|
@@ -360,6 +412,7 @@ export type StreamEvent = {
|
|
|
360
412
|
} | {
|
|
361
413
|
type: "tombstone";
|
|
362
414
|
messageId: string;
|
|
415
|
+
agentId?: string;
|
|
363
416
|
} | {
|
|
364
417
|
type: "task_update";
|
|
365
418
|
tasks: TaskInfo[];
|
|
@@ -401,6 +454,8 @@ export type StreamEvent = {
|
|
|
401
454
|
} | {
|
|
402
455
|
type: "tool_summary";
|
|
403
456
|
summary: string;
|
|
457
|
+
toolCallIds?: string[];
|
|
458
|
+
agentId?: string;
|
|
404
459
|
} | {
|
|
405
460
|
type: "context_compact";
|
|
406
461
|
strategy: "micro" | "summary" | "window" | "snip" | "emergency" | "compacted";
|
|
@@ -410,6 +465,8 @@ export type StreamEvent = {
|
|
|
410
465
|
} | {
|
|
411
466
|
type: "usage_update";
|
|
412
467
|
promptTokens: number;
|
|
468
|
+
promptTokensSource?: PromptTokenSource;
|
|
469
|
+
promptTokensConfidence?: PromptTokenConfidence;
|
|
413
470
|
/**
|
|
414
471
|
* Provider-reported prompt-cache counts, forwarded so the UI can show a
|
|
415
472
|
* cache hit rate in the context-ring tooltip. Present only when the LLM
|
|
@@ -455,7 +512,7 @@ export type StreamEvent = {
|
|
|
455
512
|
agentId: string;
|
|
456
513
|
name?: string;
|
|
457
514
|
description: string;
|
|
458
|
-
status: "completed" | "failed";
|
|
515
|
+
status: "completed" | "failed" | "cancelled";
|
|
459
516
|
/**
|
|
460
517
|
* What kind of background work this was. Lets UIs localize the
|
|
461
518
|
* completion toast (e.g. a shell shows "命令完成" not the raw English
|
|
@@ -467,8 +524,16 @@ export type StreamEvent = {
|
|
|
467
524
|
command?: string;
|
|
468
525
|
/** Final assistant text (status === "completed" only). */
|
|
469
526
|
finalText?: string;
|
|
470
|
-
/** Error message (status === "failed" only). */
|
|
527
|
+
/** Error message (status === "failed" or "cancelled" only). */
|
|
471
528
|
error?: string;
|
|
529
|
+
/** External Claude/Codex session id, when workKind === "cc". */
|
|
530
|
+
ccSessionId?: string;
|
|
531
|
+
/** Files attributed to an external DriveAgent transcript. */
|
|
532
|
+
changedFiles?: string[];
|
|
533
|
+
/** Working directory used to canonicalize relative/absolute path aliases. */
|
|
534
|
+
cwd?: string;
|
|
535
|
+
/** Client id of the real user turn that launched this background work. */
|
|
536
|
+
originClientMessageId?: string;
|
|
472
537
|
/** When the bg agent finished (Date.now() value). */
|
|
473
538
|
enqueuedAt: number;
|
|
474
539
|
};
|
|
@@ -601,9 +666,10 @@ export interface MCPServerConfig {
|
|
|
601
666
|
*/
|
|
602
667
|
envHeaders?: Record<string, string>;
|
|
603
668
|
/**
|
|
604
|
-
* (HTTP) id of a stored credential (
|
|
605
|
-
*
|
|
606
|
-
* the secret is never stored in
|
|
669
|
+
* (HTTP) id of a stored credential (token/link/oauth) to use as Bearer auth.
|
|
670
|
+
* OAuth credentials inject their current access token. Resolved at connect
|
|
671
|
+
* time via CredentialStore; the secret is never stored in MCP config. Wins
|
|
672
|
+
* over bearerTokenEnvVar.
|
|
607
673
|
*/
|
|
608
674
|
credentialRef?: string;
|
|
609
675
|
/**
|
|
@@ -626,6 +692,7 @@ export interface MCPServerConfig {
|
|
|
626
692
|
export interface MCPServerOverride {
|
|
627
693
|
env?: Record<string, string>;
|
|
628
694
|
envVars?: string[];
|
|
695
|
+
/** (HTTP) id of a stored token/link/oauth credential used as Bearer auth. */
|
|
629
696
|
credentialRef?: string;
|
|
630
697
|
bearerTokenEnvVar?: string;
|
|
631
698
|
envHeaders?: Record<string, string>;
|
|
@@ -57,7 +57,7 @@ const TOOL_ARG_KEYS = {
|
|
|
57
57
|
Agent: ["description"],
|
|
58
58
|
TodoWrite: ["todos"],
|
|
59
59
|
Sleep: ["seconds"],
|
|
60
|
-
EnterWorktree: ["slug"],
|
|
60
|
+
EnterWorktree: ["target", "slug"],
|
|
61
61
|
CronCreate: ["name", "schedule"],
|
|
62
62
|
LSP: ["action", "file_path"],
|
|
63
63
|
NotebookEdit: ["action", "file_path"],
|