@cjhyy/code-shell-core 0.6.0-rc.9 → 0.7.0-beta.1
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 +2 -0
- package/dist/cc-orchestrator/agent-adapter.js +7 -1
- package/dist/cc-orchestrator/codex-session-history.js +1 -1
- 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-driver.d.ts +1 -0
- package/dist/cc-orchestrator/external-agent-driver.js +102 -51
- 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.js +2 -2
- 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 +56 -0
- package/dist/credentials/access.js +183 -0
- package/dist/credentials/index.d.ts +1 -0
- package/dist/credentials/index.js +1 -0
- package/dist/credentials/inject-credential-tool.d.ts +3 -1
- package/dist/credentials/inject-credential-tool.js +30 -11
- package/dist/credentials/types.d.ts +2 -2
- 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 +17 -1
- package/dist/engine/engine.js +247 -89
- 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 +255 -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/streaming-tool-queue.d.ts +11 -7
- package/dist/engine/streaming-tool-queue.js +11 -7
- package/dist/engine/turn-loop.d.ts +7 -1
- package/dist/engine/turn-loop.js +117 -27
- 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/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 +16 -9
- 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 +246 -46
- package/dist/protocol/types.d.ts +47 -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 +190 -3
- 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/background-jobs.d.ts +10 -1
- package/dist/tool-system/builtin/background-jobs.js +12 -1
- 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/drive-claude-code.d.ts +16 -2
- package/dist/tool-system/builtin/drive-claude-code.js +301 -47
- 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 +37 -21
- 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/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 +23 -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 +18 -5
- package/dist/tool-system/mcp-manager.js +140 -74
- 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 +55 -4
- package/dist/utils/toolDisplay.js +1 -1
- package/package.json +4 -3
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
* 跨进程:实际的 restoreCookiesToBrowser 在 desktop main(core 够不到 Electron
|
|
11
11
|
* session),经 `ctx.injectCredentialToBrowser` 回调(宿主注入,镜像 askUser)触发。
|
|
12
12
|
*/
|
|
13
|
-
import { CredentialStore } from "./store.js";
|
|
14
13
|
import { credentialUseGate, } from "./use-gate.js";
|
|
15
14
|
import { SettingsManager } from "../settings/manager.js";
|
|
15
|
+
import { credentialAccessScope, getCredentialAccess } from "./access.js";
|
|
16
16
|
const TOOL_NAME = "InjectCredential";
|
|
17
17
|
const BASE_DESCRIPTION = "Inject a stored COOKIE credential into the built-in browser to restore its " +
|
|
18
18
|
"login state, so you can then drive the page as that logged-in account with the " +
|
|
@@ -62,9 +62,14 @@ function sessionAllowFor(ctx) {
|
|
|
62
62
|
}
|
|
63
63
|
return set;
|
|
64
64
|
}
|
|
65
|
-
|
|
65
|
+
// CredentialStore only distinguishes full user+project from project-only.
|
|
66
|
+
// Isolated engines must be at least as restrictive as project-scoped engines.
|
|
67
|
+
function credentialScope(scope) {
|
|
68
|
+
return credentialAccessScope(scope);
|
|
69
|
+
}
|
|
70
|
+
function readAutoApprove(cwd, scope) {
|
|
66
71
|
try {
|
|
67
|
-
const s = new SettingsManager(cwd, "full").get();
|
|
72
|
+
const s = new SettingsManager(cwd, scope === "full" ? "full" : "project").get();
|
|
68
73
|
return s.credentialUse?.autoApprove === true;
|
|
69
74
|
}
|
|
70
75
|
catch {
|
|
@@ -72,9 +77,11 @@ function readAutoApprove(cwd) {
|
|
|
72
77
|
}
|
|
73
78
|
}
|
|
74
79
|
/** 该工具仅在有 cookie 凭证 且 宿主接了注入回调时才可见(BUILTIN_TOOL_GUARDS)。 */
|
|
75
|
-
export function isInjectCredentialAvailable(cwd) {
|
|
80
|
+
export function isInjectCredentialAvailable(cwd, settingsScope) {
|
|
76
81
|
try {
|
|
77
|
-
return
|
|
82
|
+
return getCredentialAccess()
|
|
83
|
+
.listMasked(cwd, credentialScope(settingsScope))
|
|
84
|
+
.some((c) => c.type === "cookie");
|
|
78
85
|
}
|
|
79
86
|
catch {
|
|
80
87
|
return false;
|
|
@@ -82,10 +89,14 @@ export function isInjectCredentialAvailable(cwd) {
|
|
|
82
89
|
}
|
|
83
90
|
export async function injectCredentialTool(args, ctx) {
|
|
84
91
|
const cwd = ctx?.cwd ?? process.cwd();
|
|
92
|
+
const scope = credentialScope(ctx?.settingsScope);
|
|
85
93
|
const id = typeof args.id === "string" ? args.id.trim() : "";
|
|
86
94
|
const purpose = typeof args.purpose === "string" ? args.purpose : undefined;
|
|
87
95
|
if (!id) {
|
|
88
|
-
return json({
|
|
96
|
+
return json({
|
|
97
|
+
kind: "error",
|
|
98
|
+
error: "缺少 id。先用 UseCredential(无参)列出凭证,再用 cookie 凭证的 id 调本工具。",
|
|
99
|
+
});
|
|
89
100
|
}
|
|
90
101
|
if (!ctx?.injectCredentialToBrowser) {
|
|
91
102
|
return json({
|
|
@@ -93,17 +104,22 @@ export async function injectCredentialTool(args, ctx) {
|
|
|
93
104
|
error: "当前环境无内置浏览器(headless/无面板),无法注入。请改用 UseCredential 取 cookie 走 HTTP 请求。",
|
|
94
105
|
});
|
|
95
106
|
}
|
|
96
|
-
const cred =
|
|
107
|
+
const cred = getCredentialAccess().resolveMeta(cwd, id, scope);
|
|
97
108
|
if (!cred) {
|
|
98
|
-
return json({
|
|
109
|
+
return json({
|
|
110
|
+
kind: "error",
|
|
111
|
+
error: `凭证不存在: "${id}"。调用 UseCredential(无参)可列出可用凭证。`,
|
|
112
|
+
});
|
|
99
113
|
}
|
|
100
114
|
if (cred.type !== "cookie") {
|
|
101
115
|
return json({ kind: "error", error: `凭证「${cred.label}」不是 cookie 类型,不能注入浏览器。` });
|
|
102
116
|
}
|
|
103
117
|
// 过门:复用三档,但用该凭证的 autoInjectByAI(不是 autoUseByAI)。
|
|
104
|
-
const ask = ctx.askUser
|
|
118
|
+
const ask = ctx.askUser
|
|
119
|
+
? (q, opts) => ctx.askUser(q, opts)
|
|
120
|
+
: undefined;
|
|
105
121
|
const decision = await credentialUseGate({ id: cred.id, label: cred.label, purpose }, {
|
|
106
|
-
autoApprove: readAutoApprove(cwd),
|
|
122
|
+
autoApprove: readAutoApprove(cwd, scope),
|
|
107
123
|
credentialAutoUse: cred.autoInjectByAI === true,
|
|
108
124
|
sessionAllow: sessionAllowFor(ctx),
|
|
109
125
|
ask,
|
|
@@ -115,7 +131,7 @@ export async function injectCredentialTool(args, ctx) {
|
|
|
115
131
|
return json({ kind: "error", error: msg });
|
|
116
132
|
}
|
|
117
133
|
// 跨进程触发宿主注入。
|
|
118
|
-
const res = await ctx.injectCredentialToBrowser(cred.id);
|
|
134
|
+
const res = await ctx.injectCredentialToBrowser(cred.id, scope);
|
|
119
135
|
if (!res.ok) {
|
|
120
136
|
return json({ kind: "error", error: res.error ?? "注入浏览器失败(宿主未返回成功)。" });
|
|
121
137
|
}
|
|
@@ -128,3 +144,6 @@ function json(r) {
|
|
|
128
144
|
export function __resetInjectCredentialSessionAllowForTests() {
|
|
129
145
|
injectSessionAllowByEngine.clear();
|
|
130
146
|
}
|
|
147
|
+
export function clearInjectCredentialSessionAllow(sessionId) {
|
|
148
|
+
injectSessionAllowByEngine.delete(sessionId);
|
|
149
|
+
}
|
|
@@ -39,8 +39,8 @@ export interface Credential {
|
|
|
39
39
|
/**
|
|
40
40
|
* link: 业务方 app 注册地址;cookie: 拓取所用平台与主域 + 抓取范围 + 切换策略。
|
|
41
41
|
* - scope="all" 表示该 jar 是整分区全量抓的(切换时整包导回);缺省/"domain" = 仅该域。
|
|
42
|
-
* - switchMode 决定「切换」时怎么写回浏览器:"
|
|
43
|
-
* "
|
|
42
|
+
* - switchMode 决定「切换」时怎么写回浏览器:"merge"(默认)只覆盖同名 cookie、保留
|
|
43
|
+
* 分区里其他站(不踢掉别的登录态);"clear" 先清空整分区再注入(干净换号,需显式选)。
|
|
44
44
|
*/
|
|
45
45
|
meta?: {
|
|
46
46
|
appUrl?: string;
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* - token/link → `{ kind: "value", value }`
|
|
8
8
|
* - cookie → 就地写临时 cookies.txt(0600),返回 `{ kind: "cookie", cookiesFile, count }`
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* desktop 下通过 host credential access IPC 按需解析 secret;headless/SDK
|
|
11
|
+
* 仍可使用本地 CredentialStore。
|
|
11
12
|
* 集中在 core/src/credentials/ 下,只经 ToolDefinition 注册 + ToolContext.askUser 耦合 core,
|
|
12
13
|
* 满足设计稿 §1「可整块外移」约束。
|
|
13
14
|
*/
|
|
@@ -25,5 +26,12 @@ export declare function useCredentialToolDefFor(cwd: string): ToolDefinition;
|
|
|
25
26
|
*/
|
|
26
27
|
export declare function sweepStaleCredentialCookies(now?: number): void;
|
|
27
28
|
export declare function useCredentialTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
|
|
29
|
+
export declare function useCredentialBuiltinTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string | {
|
|
30
|
+
result: string;
|
|
31
|
+
sensitive: true;
|
|
32
|
+
displayResult: string;
|
|
33
|
+
transcriptResult: string;
|
|
34
|
+
}>;
|
|
28
35
|
/** 测试钩子:清空会话 allow 集(避免跨用例污染)。 */
|
|
29
36
|
export declare function __resetCredentialSessionAllowForTests(): void;
|
|
37
|
+
export declare function clearCredentialSessionAllow(sessionId: string): void;
|
|
@@ -7,22 +7,17 @@
|
|
|
7
7
|
* - token/link → `{ kind: "value", value }`
|
|
8
8
|
* - cookie → 就地写临时 cookies.txt(0600),返回 `{ kind: "cookie", cookiesFile, count }`
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* desktop 下通过 host credential access IPC 按需解析 secret;headless/SDK
|
|
11
|
+
* 仍可使用本地 CredentialStore。
|
|
11
12
|
* 集中在 core/src/credentials/ 下,只经 ToolDefinition 注册 + ToolContext.askUser 耦合 core,
|
|
12
13
|
* 满足设计稿 §1「可整块外移」约束。
|
|
13
14
|
*/
|
|
14
|
-
import {
|
|
15
|
-
import { join } from "node:path";
|
|
16
|
-
import { tmpdir } from "node:os";
|
|
17
|
-
import { randomUUID } from "node:crypto";
|
|
18
|
-
import { CredentialStore } from "./store.js";
|
|
19
|
-
import { formatNetscapeCookies, parseCookieJar } from "./cookie-jar.js";
|
|
15
|
+
import { SENSITIVE_TOOL_RESULT_PLACEHOLDER } from "../tool-system/tool-result-redaction.js";
|
|
20
16
|
import { credentialUseGate, } from "./use-gate.js";
|
|
21
17
|
import { SettingsManager } from "../settings/manager.js";
|
|
22
18
|
import { logger } from "../logging/logger.js";
|
|
19
|
+
import { credentialAccessScope, getCredentialAccess, materializeCookieSecret, sweepStaleCredentialCookieFiles, } from "./access.js";
|
|
23
20
|
const TOOL_NAME = "UseCredential";
|
|
24
|
-
const COOKIE_FILE_PREFIX = "codeshell-cred-cookie-";
|
|
25
|
-
const COOKIE_FILE_MAX_AGE_MS = 30 * 60 * 1000; // 30min 启动 sweep 上限
|
|
26
21
|
const BASE_DESCRIPTION = "Use a stored credential (token / API key / login cookie) to run a command. " +
|
|
27
22
|
"Call with NO arguments first to list available credentials (id + label + type); " +
|
|
28
23
|
"then call again with `id` to fetch one. Token/link credentials return their secret " +
|
|
@@ -52,7 +47,7 @@ export const useCredentialToolDef = {
|
|
|
52
47
|
*/
|
|
53
48
|
export function useCredentialToolDefFor(cwd) {
|
|
54
49
|
try {
|
|
55
|
-
const list =
|
|
50
|
+
const list = getCredentialAccess().listMasked(cwd, "full");
|
|
56
51
|
if (list.length === 0)
|
|
57
52
|
return useCredentialToolDef;
|
|
58
53
|
const names = list.map((c) => `${c.id} (${c.type})`).join(", ");
|
|
@@ -70,26 +65,7 @@ export function useCredentialToolDefFor(cwd) {
|
|
|
70
65
|
* 不引入 lease 对象/定时器 —— 文件用完靠进程退出 + 这个轻量 sweep。
|
|
71
66
|
*/
|
|
72
67
|
export function sweepStaleCredentialCookies(now = Date.now()) {
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
if (!existsSync(dir))
|
|
76
|
-
return;
|
|
77
|
-
for (const f of readdirSync(dir)) {
|
|
78
|
-
if (!f.startsWith(COOKIE_FILE_PREFIX))
|
|
79
|
-
continue;
|
|
80
|
-
const p = join(dir, f);
|
|
81
|
-
try {
|
|
82
|
-
if (now - statSync(p).mtimeMs > COOKIE_FILE_MAX_AGE_MS)
|
|
83
|
-
rmSync(p, { force: true });
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
/* skip */
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
/* best-effort */
|
|
92
|
-
}
|
|
68
|
+
sweepStaleCredentialCookieFiles(now);
|
|
93
69
|
}
|
|
94
70
|
/** 内存会话 allow 集:每个 Engine 一份(从 ctx.sessionId 键)。纯内存,关进程即忘。 */
|
|
95
71
|
const sessionAllowByEngine = new Map();
|
|
@@ -112,7 +88,7 @@ function sessionAllowFor(ctx) {
|
|
|
112
88
|
// (project-only). An "isolated" engine is at least as restrictive as project,
|
|
113
89
|
// so it maps to "project" — it must never read the host user's ~/.code-shell.
|
|
114
90
|
function credentialScope(scope) {
|
|
115
|
-
return scope
|
|
91
|
+
return credentialAccessScope(scope);
|
|
116
92
|
}
|
|
117
93
|
function readAutoApprove(cwd, scope) {
|
|
118
94
|
try {
|
|
@@ -128,19 +104,19 @@ function readAutoApprove(cwd, scope) {
|
|
|
128
104
|
}
|
|
129
105
|
export async function useCredentialTool(args, ctx) {
|
|
130
106
|
const cwd = ctx?.cwd ?? process.cwd();
|
|
131
|
-
const
|
|
107
|
+
const access = getCredentialAccess();
|
|
132
108
|
const scope = credentialScope(ctx?.settingsScope);
|
|
133
109
|
const id = typeof args.id === "string" ? args.id.trim() : "";
|
|
134
110
|
const purpose = typeof args.purpose === "string" ? args.purpose : undefined;
|
|
135
111
|
// 无 id → 清单(脱敏,权威实时源)。按 engine scope 过滤:project/isolated
|
|
136
112
|
// 引擎不得列出宿主 user 层凭证。
|
|
137
113
|
if (!id) {
|
|
138
|
-
const credentials =
|
|
139
|
-
.listMasked(scope)
|
|
114
|
+
const credentials = access
|
|
115
|
+
.listMasked(cwd, scope)
|
|
140
116
|
.map((c) => ({ id: c.id, label: c.label, type: c.type }));
|
|
141
117
|
return json({ kind: "list", credentials });
|
|
142
118
|
}
|
|
143
|
-
const cred =
|
|
119
|
+
const cred = access.resolveMeta(cwd, id, scope);
|
|
144
120
|
if (!cred) {
|
|
145
121
|
return json({ kind: "error", error: `凭证不存在: "${id}"。调用本工具(无参)可列出可用凭证。` });
|
|
146
122
|
}
|
|
@@ -162,14 +138,20 @@ export async function useCredentialTool(args, ctx) {
|
|
|
162
138
|
}
|
|
163
139
|
// token/link → 直接返回值
|
|
164
140
|
if (cred.type === "token" || cred.type === "link") {
|
|
165
|
-
if (!cred.
|
|
141
|
+
if (!cred.hasSecret || !access.resolveValue) {
|
|
142
|
+
return json({ kind: "error", error: `凭证「${cred.label}」没有可用的值。` });
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const value = await access.resolveValue({ cwd, id: cred.id, scope, purpose: "use" });
|
|
146
|
+
return json({ kind: "value", value });
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
166
149
|
return json({ kind: "error", error: `凭证「${cred.label}」没有可用的值。` });
|
|
167
|
-
|
|
150
|
+
}
|
|
168
151
|
}
|
|
169
152
|
// cookie → 就地写临时 cookies.txt
|
|
170
153
|
if (cred.type === "cookie") {
|
|
171
|
-
|
|
172
|
-
if (jar.length === 0) {
|
|
154
|
+
if (!cred.hasSecret) {
|
|
173
155
|
return json({
|
|
174
156
|
kind: "error",
|
|
175
157
|
error: `凭证「${cred.label}」的 cookie 为空或已失效,请在凭证页对该账号点「重拓」(重新登录后重新拓取)。`,
|
|
@@ -180,26 +162,57 @@ export async function useCredentialTool(args, ctx) {
|
|
|
180
162
|
// same process — the second write would clobber the first and a caller could
|
|
181
163
|
// read another account's cookies. A random component makes each file distinct.
|
|
182
164
|
// Prefix is unchanged so the 30-min startup sweep still matches & cleans them.
|
|
183
|
-
const file = join(tmpdir(), `${COOKIE_FILE_PREFIX}${safe(cred.id)}-${process.pid}-${randomUUID()}.txt`);
|
|
184
165
|
try {
|
|
185
|
-
|
|
166
|
+
const materialized = access.materializeCookie
|
|
167
|
+
? await access.materializeCookie({ cwd, id: cred.id, scope })
|
|
168
|
+
: materializeCookieSecret(cred.id, await access.resolveValue({ cwd, id: cred.id, scope, purpose: "use" }));
|
|
169
|
+
return json({
|
|
170
|
+
kind: "cookie",
|
|
171
|
+
cookiesFile: materialized.cookiesFile,
|
|
172
|
+
count: materialized.count,
|
|
173
|
+
});
|
|
186
174
|
}
|
|
187
175
|
catch (e) {
|
|
176
|
+
if (String(e).includes("cookie jar is empty or invalid")) {
|
|
177
|
+
return json({
|
|
178
|
+
kind: "error",
|
|
179
|
+
error: `凭证「${cred.label}」的 cookie 为空或已失效,请在凭证页对该账号点「重拓」(重新登录后重新拓取)。`,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
188
182
|
logger.warn(`UseCredential: failed to write cookies.txt: ${String(e)}`);
|
|
189
183
|
return json({ kind: "error", error: `写临时 cookie 文件失败: ${String(e)}` });
|
|
190
184
|
}
|
|
191
|
-
return json({ kind: "cookie", cookiesFile: file, count: jar.length });
|
|
192
185
|
}
|
|
193
186
|
return json({ kind: "error", error: `未知凭证类型: ${cred.type}` });
|
|
194
187
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
188
|
+
export async function useCredentialBuiltinTool(args, ctx) {
|
|
189
|
+
const result = await useCredentialTool(args, ctx);
|
|
190
|
+
if (!isValueResult(result))
|
|
191
|
+
return result;
|
|
192
|
+
const redacted = json({ kind: "value", value: SENSITIVE_TOOL_RESULT_PLACEHOLDER });
|
|
193
|
+
return {
|
|
194
|
+
result,
|
|
195
|
+
sensitive: true,
|
|
196
|
+
displayResult: redacted,
|
|
197
|
+
transcriptResult: redacted,
|
|
198
|
+
};
|
|
198
199
|
}
|
|
199
200
|
function json(r) {
|
|
200
201
|
return JSON.stringify(r);
|
|
201
202
|
}
|
|
203
|
+
function isValueResult(result) {
|
|
204
|
+
try {
|
|
205
|
+
const parsed = JSON.parse(result);
|
|
206
|
+
return parsed.kind === "value" && typeof parsed.value === "string";
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
202
212
|
/** 测试钩子:清空会话 allow 集(避免跨用例污染)。 */
|
|
203
213
|
export function __resetCredentialSessionAllowForTests() {
|
|
204
214
|
sessionAllowByEngine.clear();
|
|
205
215
|
}
|
|
216
|
+
export function clearCredentialSessionAllow(sessionId) {
|
|
217
|
+
sessionAllowByEngine.delete(sessionId);
|
|
218
|
+
}
|
package/dist/engine/engine.d.ts
CHANGED
|
@@ -12,9 +12,11 @@ import type { AskUserFn } from "../tool-system/builtin/ask-user.js";
|
|
|
12
12
|
import type { CapabilityOverride } from "../settings/schema.js";
|
|
13
13
|
import { type FeatureFlagName } from "../settings/feature-flags.js";
|
|
14
14
|
import type { ToolContext } from "../tool-system/context.js";
|
|
15
|
+
import { type SandboxBackend } from "../tool-system/sandbox/index.js";
|
|
15
16
|
import { ModelPool, type ModelEntry } from "../llm/model-pool.js";
|
|
16
17
|
import { AgentDefinitionRegistry } from "../agent/agent-definition-registry.js";
|
|
17
18
|
import { EngineRuntime } from "./runtime.js";
|
|
19
|
+
import type { InputAttachmentMeta } from "../protocol/types.js";
|
|
18
20
|
/**
|
|
19
21
|
* Build ScanOptions.compatFileNames from the user's instruction compat toggles.
|
|
20
22
|
* Primary file name stays hard-wired to CODESHELL.md (not exposed). Turning a
|
|
@@ -53,7 +55,7 @@ export declare function resolveChildLlm(modelKey: string | undefined, pool: Mode
|
|
|
53
55
|
* Names in `disabledAgents` are filtered out so the LLM never sees them.
|
|
54
56
|
*/
|
|
55
57
|
/**
|
|
56
|
-
* Resolve the working directory for a run. Precedence:
|
|
58
|
+
* Resolve the working directory for a run. Precedence for legacy sessions:
|
|
57
59
|
* options.cwd > resumed session's state.cwd > config.cwd > process.cwd()
|
|
58
60
|
*
|
|
59
61
|
* The session-cwd tier is what stops a project-bound session from being
|
|
@@ -261,6 +263,8 @@ export declare class Engine {
|
|
|
261
263
|
* clear "no browser panel" error.
|
|
262
264
|
*/
|
|
263
265
|
setBrowserBridge(bridge: import("../tool-system/browser-bridge.js").BrowserBridge | undefined): void;
|
|
266
|
+
/** Inject the host-backed workspace bridge after construction. */
|
|
267
|
+
setWorkspaceBridge(bridge: import("../tool-system/workspace-bridge.js").WorkspaceBridge | undefined): void;
|
|
264
268
|
/**
|
|
265
269
|
* Queue a user message to be spliced into the in-flight run for `sessionId`
|
|
266
270
|
* at the next turn-loop step boundary — the 不打断 steering path (vs cancel +
|
|
@@ -325,6 +329,8 @@ export declare class Engine {
|
|
|
325
329
|
injected?: boolean;
|
|
326
330
|
/** Stable id for this user-intent, used to make duplicate submits idempotent. */
|
|
327
331
|
clientMessageId?: string;
|
|
332
|
+
/** Structured input attachments. Legacy `<codeshell-image>` blocks remain supported. */
|
|
333
|
+
attachments?: InputAttachmentMeta[];
|
|
328
334
|
}): Promise<EngineResult>;
|
|
329
335
|
/**
|
|
330
336
|
* Run the end-of-session memory pipeline as a fire-and-forget background
|
|
@@ -460,6 +466,12 @@ export declare class Engine {
|
|
|
460
466
|
* session with no active goal is a no-op returning false.
|
|
461
467
|
*/
|
|
462
468
|
clearGoal(sessionId: string): boolean;
|
|
469
|
+
/**
|
|
470
|
+
* Reset a session's workspace pointer back to its main root. If the session is
|
|
471
|
+
* actively running, mutate that live SessionBundle first so the run's next
|
|
472
|
+
* saveState cannot resurrect a stale worktree pointer.
|
|
473
|
+
*/
|
|
474
|
+
releaseSessionWorkspace(sessionId: string): import("../types.js").SessionWorkspace | null;
|
|
463
475
|
injectContext(sessionId: string, content: string): void;
|
|
464
476
|
/**
|
|
465
477
|
* Force context compaction on a session.
|
|
@@ -570,6 +582,7 @@ export declare class Engine {
|
|
|
570
582
|
* by tests that want a ToolContext without a full run() cycle.
|
|
571
583
|
*/
|
|
572
584
|
private resolveSandboxWithoutRuntime;
|
|
585
|
+
private resolveSandboxConfigForCwd;
|
|
573
586
|
/**
|
|
574
587
|
* Build the shell env layered onto the Bash tool / background shells (see
|
|
575
588
|
* mergeShellEnv). Three user-configured sources, merged lowest → highest:
|
|
@@ -622,6 +635,9 @@ export declare class Engine {
|
|
|
622
635
|
linux?: string;
|
|
623
636
|
windows?: string;
|
|
624
637
|
} | undefined;
|
|
638
|
+
readWorktreeBranchPrefix(cwd?: string): string | undefined;
|
|
639
|
+
resolveWorktreeSetupSandbox(cwd: string): Promise<SandboxBackend | undefined>;
|
|
640
|
+
readWorktreeSetupShellEnv(cwd?: string): Record<string, string> | undefined;
|
|
625
641
|
buildToolContext(): ToolContext;
|
|
626
642
|
/**
|
|
627
643
|
* Read settings.disabledSkills + settings.disabledPlugins in a single
|