@co0ontty/wand 4.56.1 → 4.57.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/dist/build-info.json +3 -3
- package/dist/server-session-routes.js +4 -4
- package/dist/structured-permission.d.ts +14 -0
- package/dist/structured-permission.js +56 -0
- package/dist/structured-session-manager.d.ts +9 -0
- package/dist/structured-session-manager.js +178 -0
- package/dist/taskboard-bridge.js +12 -1
- package/dist/web-ui/content/scripts.js +70 -70
- package/dist/web-ui/embedded-assets.js +1 -1
- package/package.json +1 -1
- package/vendor/codex-taskboard/dist/web/assets/AiChat-BNn4VJ5a.js +12 -0
- package/vendor/codex-taskboard/dist/web/assets/GanttView-D8wnfGrG.css +1 -0
- package/vendor/codex-taskboard/dist/web/assets/GanttView-rGWhuEX9.js +39 -0
- package/vendor/codex-taskboard/dist/web/assets/abnfDiagram-N423BO3Z-DbFG6lbA.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/arc-BjSQqbzd.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/architecture-TIHT7OUA-C9-t8p4o.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/architectureDiagram-T3A2C74G-Db4kJZwO.js +36 -0
- package/vendor/codex-taskboard/dist/web/assets/array-BifhSqXX.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/blockDiagram-VBNYF7ZC-C-BywuWV.js +132 -0
- package/vendor/codex-taskboard/dist/web/assets/c4Diagram-5PPSVZJV-Dq-80rjP.js +10 -0
- package/vendor/codex-taskboard/dist/web/assets/channel-C7mnz8Xc.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-2GRJ4B5K-B2G57us9.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-3NCLNEKW-DVGIRib_.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-4I5QYGJK-kNoGFqr0.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-5RXB4S5H-4iv6-xM6.js +231 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-6Q2QTUOP-1J34vxHr.js +88 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-7Z6QIM7H-CDQpQlxX.js +10 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-GF5L2VYU-Dg92oHHl.js +206 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-I66GZJ75-Bk8_gFs2.js +125 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-J7OUQ5F2-CJRcenlr.js +2 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-JQJVKLGR-BLBV_Sus.js +156 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-KBJHAD2P-Da9Yjz0p.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-KEIR6QF5-Dj-OpFgW.js +161 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-NSK5VX7P-Cb56tnGK.js +2 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-QR6OTTB3-BwoszTxn.js +62 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-RYQCIY6F-D_L2RdcQ.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-UBXNYLIW-YX5mN8cl.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-W5SLKNZC-DlOLhhDO.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-WRU74C26-B7SBmP0K.js +70 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-XXDRQBXY-BuE3VzE_.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/chunk-ZIRB5QZD-C6fEPe3t.js +32 -0
- package/vendor/codex-taskboard/dist/web/assets/classDiagram-JCYQIIEL-KIdCVvbA.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/classDiagram-v2-OCEON4UE-KIdCVvbA.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/cose-bilkent-JH36ORCC-BzQvy5TC.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/cynefin-VYW2F7L2-D1_5O1XR.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/cynefinDiagram-MW4NZA55-DOW_U5QN.js +62 -0
- package/vendor/codex-taskboard/dist/web/assets/cytoscape.esm-DnGd5Fuo.js +321 -0
- package/vendor/codex-taskboard/dist/web/assets/dagre-VZM6K2ZE-0Dntc3NT.js +4 -0
- package/vendor/codex-taskboard/dist/web/assets/dagre-dpRSp0QF.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/defaultLocale-C8Fc0cco.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/diagram-7IWD3JNH-D7GleYAM.js +30 -0
- package/vendor/codex-taskboard/dist/web/assets/diagram-B4RE2ZJO-DCXTe6q5.js +3 -0
- package/vendor/codex-taskboard/dist/web/assets/diagram-LBJQPF4R-ZFJyXEXl.js +24 -0
- package/vendor/codex-taskboard/dist/web/assets/diagram-Q27KOJAE-DUGCuGd9.js +24 -0
- package/vendor/codex-taskboard/dist/web/assets/diagram-UB23O5K3-DRmp4Nng.js +41 -0
- package/vendor/codex-taskboard/dist/web/assets/dist-D9sYb5Oa.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/ebnfDiagram-BXEA7PRR-CkKoaf7T.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/erDiagram-JOGREHBK-nBX5z4R4.js +85 -0
- package/vendor/codex-taskboard/dist/web/assets/eventmodeling-45OFAUF4-pexmK65N.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/flowDiagram-UKHOOZJN-aroohRbL.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/ganttDiagram-PKOTCBZU-BOJWUTXa.js +292 -0
- package/vendor/codex-taskboard/dist/web/assets/gitGraph-TEB2WS4Q-DxnuhSZU.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/gitGraphDiagram-DS77QQ5N-Cte975TC.js +106 -0
- package/vendor/codex-taskboard/dist/web/assets/graphlib-DS17s2tU.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/index-Docmx4uQ.css +1 -0
- package/vendor/codex-taskboard/dist/web/assets/index-Du07lEGz.js +121 -0
- package/vendor/codex-taskboard/dist/web/assets/info-DKCQHKI2-DOTjgYxk.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/infoDiagram-6WML65LV-SpyV9UJd.js +2 -0
- package/vendor/codex-taskboard/dist/web/assets/init-D6jRqBbL.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/ishikawaDiagram-WSZJBQD7-T0PZwoUZ.js +70 -0
- package/vendor/codex-taskboard/dist/web/assets/journeyDiagram-NVQOT4AX-B88b8UgX.js +139 -0
- package/vendor/codex-taskboard/dist/web/assets/kanban-definition-27J2QSJJ-CIlfNnl_.js +89 -0
- package/vendor/codex-taskboard/dist/web/assets/katex-B7rAX3Vi.js +257 -0
- package/vendor/codex-taskboard/dist/web/assets/line-fWrwPZhB.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/linear-B7l8qgEw.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/map-BaFkSB1l.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/mermaid-parser.core-C5gls2nC.js +7 -0
- package/vendor/codex-taskboard/dist/web/assets/mermaid.core-POz2Xcvr.js +11 -0
- package/vendor/codex-taskboard/dist/web/assets/mindmap-definition-FAOFIHXS-BM0-egZ5.js +96 -0
- package/vendor/codex-taskboard/dist/web/assets/ordinal-hYBb2elL.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/packet-7NZHBO7P-DQZzyVos.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/path-BWPyau1x.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/pegDiagram-VL7TDLO6-B8aEwl-7.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/pie-RZYD4A2V-DRUflilR.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/pieDiagram-7S7Q4E2Y-0cDDxlua.js +39 -0
- package/vendor/codex-taskboard/dist/web/assets/purify.es-Bwt4ulIK.js +3 -0
- package/vendor/codex-taskboard/dist/web/assets/quadrantDiagram-CIZ2JOQS-CBgb0YZ0.js +7 -0
- package/vendor/codex-taskboard/dist/web/assets/radar-I7S5WNFK-tRocoKxq.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/railroad-3IZDKUUU-DaS4ZlX_.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/railroad-abnf-AHOZXSZD-BN1T5dBT.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/railroad-ebnf-EBAXGLYW-Cuf8qyKs.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/railroad-peg-LSFZ7HO6-B511_EYq.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/railroadDiagram-AXF67PYL-QtPo-JZb.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/requirementDiagram-LRYGKXZP-CuBIF85r.js +84 -0
- package/vendor/codex-taskboard/dist/web/assets/rolldown-runtime-QTnfLwEv.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/rough.esm-CSKSodPl.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/sankeyDiagram-W5VNT64P-CRA-b_za.js +40 -0
- package/vendor/codex-taskboard/dist/web/assets/sequenceDiagram-SI44F4Z6-CoddVWwY.js +162 -0
- package/vendor/codex-taskboard/dist/web/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/src-_wZywoZs.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/stateDiagram-OKZ733FA-D8DMM2ln.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/stateDiagram-v2-UEYNNEHI-CVp0eYAS.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/swimlanes-SLNWSIFB-C1fC7EFu.js +2 -0
- package/vendor/codex-taskboard/dist/web/assets/swimlanesDiagram-ULZ7WXOC-CPd58Xso.js +8 -0
- package/vendor/codex-taskboard/dist/web/assets/timeline-definition-Z64GVDOM-BUBv8aKP.js +120 -0
- package/vendor/codex-taskboard/dist/web/assets/treeView-QDETBFTQ-C-Bve2kY.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/treemap-6X3UGDF4-BcphHDdV.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/vennDiagram-T6HMQDX7-0wQnwAyA.js +34 -0
- package/vendor/codex-taskboard/dist/web/assets/wardley-OPB4EBWU-CJZ4BevB.js +1 -0
- package/vendor/codex-taskboard/dist/web/assets/wardleyDiagram-T6FBY63Y-U9nwPrkN.js +78 -0
- package/vendor/codex-taskboard/dist/web/assets/xychartDiagram-ELKLHX3M-CyCqnzgE.js +7 -0
- package/vendor/codex-taskboard/dist/web/codex-agent-logo.png +0 -0
- package/vendor/codex-taskboard/dist/web/codex-app-icon.png +0 -0
- package/vendor/codex-taskboard/dist/web/favicon.svg +7 -0
- package/vendor/codex-taskboard/dist/web/index.html +20 -0
package/dist/build-info.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"commit": "
|
|
3
|
-
"builtAt": "2026-09-
|
|
4
|
-
"version": "4.
|
|
2
|
+
"commit": "d240da17b4bfee37b304e0a51c90506979357d8c",
|
|
3
|
+
"builtAt": "2026-09-10T04:56:25.817Z",
|
|
4
|
+
"version": "4.57.0",
|
|
5
5
|
"channel": "stable"
|
|
6
6
|
}
|
|
@@ -1395,7 +1395,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1395
1395
|
app.post("/api/sessions/:id/approve-permission", (req, res) => {
|
|
1396
1396
|
try {
|
|
1397
1397
|
if (sessions.ownerOf(req.params.id) === "structured") {
|
|
1398
|
-
res.
|
|
1398
|
+
res.json(sessionResponseDTO(structured.approvePermission(req.params.id)));
|
|
1399
1399
|
return;
|
|
1400
1400
|
}
|
|
1401
1401
|
const snapshot = sessions.get(req.params.id);
|
|
@@ -1412,7 +1412,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1412
1412
|
app.post("/api/sessions/:id/deny-permission", (req, res) => {
|
|
1413
1413
|
try {
|
|
1414
1414
|
if (sessions.ownerOf(req.params.id) === "structured") {
|
|
1415
|
-
res.
|
|
1415
|
+
res.json(sessionResponseDTO(structured.denyPermission(req.params.id)));
|
|
1416
1416
|
return;
|
|
1417
1417
|
}
|
|
1418
1418
|
const snapshot = sessions.get(req.params.id);
|
|
@@ -1429,7 +1429,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1429
1429
|
app.post("/api/sessions/:id/toggle-auto-approve", (req, res) => {
|
|
1430
1430
|
try {
|
|
1431
1431
|
if (sessions.ownerOf(req.params.id) === "structured") {
|
|
1432
|
-
res.
|
|
1432
|
+
res.json(sessionResponseDTO(structured.toggleAutoApprove(req.params.id)));
|
|
1433
1433
|
return;
|
|
1434
1434
|
}
|
|
1435
1435
|
const snapshot = sessions.get(req.params.id);
|
|
@@ -1453,7 +1453,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1453
1453
|
return;
|
|
1454
1454
|
}
|
|
1455
1455
|
if (sessions.ownerOf(req.params.id) === "structured") {
|
|
1456
|
-
res.
|
|
1456
|
+
res.json(sessionResponseDTO(structured.resolveEscalation(req.params.id, requestId, resolution)));
|
|
1457
1457
|
return;
|
|
1458
1458
|
}
|
|
1459
1459
|
res.json(sessionResponseDTO(processes.resolveEscalation(req.params.id, requestId, resolution)));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { EscalationRequest } from "./types.js";
|
|
2
|
+
export interface StructuredToolPermissionContext {
|
|
3
|
+
title?: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
blockedPath?: string;
|
|
6
|
+
displayName?: string;
|
|
7
|
+
toolUseID?: string;
|
|
8
|
+
decisionReason?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function inferStructuredEscalation(toolName: string, input: Record<string, unknown>, ctx?: StructuredToolPermissionContext): Pick<EscalationRequest, "scope" | "target" | "reason">;
|
|
11
|
+
export declare function structuredPermissionDenied(message: string): {
|
|
12
|
+
behavior: "deny";
|
|
13
|
+
message: string;
|
|
14
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const FILE_TOOLS = new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
2
|
+
const COMMAND_TOOLS = new Set(["Bash", "BashOutput"]);
|
|
3
|
+
const NETWORK_TOOLS = new Set(["WebFetch", "WebSearch"]);
|
|
4
|
+
const DANGEROUS_SHELL_RE = /\bsudo\b|\brm\s+-[rf]{1,2}\b|\bmkfs\b|\bdd\s+if=|\bshutdown\b|\breboot\b/i;
|
|
5
|
+
function firstString(input, keys) {
|
|
6
|
+
for (const key of keys) {
|
|
7
|
+
const value = input[key];
|
|
8
|
+
if (typeof value === "string" && value.trim())
|
|
9
|
+
return value.trim();
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
function truncateTarget(value) {
|
|
14
|
+
if (!value)
|
|
15
|
+
return undefined;
|
|
16
|
+
const compact = value.replace(/\s+/g, " ").trim();
|
|
17
|
+
if (!compact)
|
|
18
|
+
return undefined;
|
|
19
|
+
return compact.length > 200 ? `${compact.slice(0, 197)}...` : compact;
|
|
20
|
+
}
|
|
21
|
+
export function inferStructuredEscalation(toolName, input, ctx = {}) {
|
|
22
|
+
let scope = "unknown";
|
|
23
|
+
let target = firstString(input, ["file_path", "path", "command", "url", "query", "description", "prompt", "name"]);
|
|
24
|
+
if (FILE_TOOLS.has(toolName)) {
|
|
25
|
+
scope = "write_file";
|
|
26
|
+
target = firstString(input, ["file_path", "path"]) ?? target;
|
|
27
|
+
}
|
|
28
|
+
else if (COMMAND_TOOLS.has(toolName)) {
|
|
29
|
+
const command = firstString(input, ["command"]) ?? target;
|
|
30
|
+
scope = command && DANGEROUS_SHELL_RE.test(command) ? "dangerous_shell" : "run_command";
|
|
31
|
+
target = command;
|
|
32
|
+
}
|
|
33
|
+
else if (NETWORK_TOOLS.has(toolName)) {
|
|
34
|
+
scope = "network";
|
|
35
|
+
target = firstString(input, ["url", "query"]) ?? target;
|
|
36
|
+
}
|
|
37
|
+
else if (typeof ctx.blockedPath === "string" && ctx.blockedPath.trim()) {
|
|
38
|
+
scope = "outside_workspace";
|
|
39
|
+
target = ctx.blockedPath.trim();
|
|
40
|
+
}
|
|
41
|
+
if (!target && typeof ctx.blockedPath === "string" && ctx.blockedPath.trim()) {
|
|
42
|
+
target = ctx.blockedPath.trim();
|
|
43
|
+
}
|
|
44
|
+
const reason = (ctx.title?.trim()
|
|
45
|
+
|| ctx.description?.trim()
|
|
46
|
+
|| ctx.decisionReason?.trim()
|
|
47
|
+
|| `需要授权使用 ${toolName}`).slice(0, 300);
|
|
48
|
+
return {
|
|
49
|
+
scope,
|
|
50
|
+
target: truncateTarget(target),
|
|
51
|
+
reason,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function structuredPermissionDenied(message) {
|
|
55
|
+
return { behavior: "deny", message };
|
|
56
|
+
}
|
|
@@ -63,6 +63,10 @@ export declare class StructuredSessionManager {
|
|
|
63
63
|
* Only populated while an SDK call is in flight.
|
|
64
64
|
*/
|
|
65
65
|
private readonly pendingSdkQueries;
|
|
66
|
+
/** In-flight canUseTool waiters. One pending prompt per session. */
|
|
67
|
+
private readonly pendingPermissions;
|
|
68
|
+
/** approve_turn memory, scoped to the current SDK query. */
|
|
69
|
+
private readonly turnApprovalMemory;
|
|
66
70
|
private readonly interruptedWith;
|
|
67
71
|
private readonly interruptedSkills;
|
|
68
72
|
/**
|
|
@@ -172,6 +176,8 @@ export declare class StructuredSessionManager {
|
|
|
172
176
|
setSessionMode(sessionId: string, mode: ExecutionMode): SessionSnapshot;
|
|
173
177
|
/** Toggle auto-approve for the session. */
|
|
174
178
|
toggleAutoApprove(sessionId: string): SessionSnapshot;
|
|
179
|
+
approvePermission(sessionId: string): SessionSnapshot;
|
|
180
|
+
denyPermission(sessionId: string): SessionSnapshot;
|
|
175
181
|
/** Resolve a specific escalation by requestId. */
|
|
176
182
|
resolveEscalation(sessionId: string, requestId: string, resolution: unknown): SessionSnapshot;
|
|
177
183
|
stop(id: string): SessionSnapshot;
|
|
@@ -188,6 +194,9 @@ export declare class StructuredSessionManager {
|
|
|
188
194
|
private flushNextQueuedMessage;
|
|
189
195
|
private emit;
|
|
190
196
|
private incrementApprovalStats;
|
|
197
|
+
private rememberTurnApproval;
|
|
198
|
+
private settlePendingPermission;
|
|
199
|
+
private handleCanUseTool;
|
|
191
200
|
private runCodexStreaming;
|
|
192
201
|
private runGrokStreaming;
|
|
193
202
|
private runOpenCodeStreaming;
|
|
@@ -12,6 +12,7 @@ import { CodexRunner } from "./structured-codex-adapter.js";
|
|
|
12
12
|
import { CodexProtocolReducer } from "./structured-codex-protocol.js";
|
|
13
13
|
import { normalizeStructuredToolResultContent } from "./structured-content.js";
|
|
14
14
|
import { buildAppendSystemPromptParts, buildClaudeSdkThinking, ClaudeCliRunner, derivePermissionPolicy, } from "./structured-claude-adapter.js";
|
|
15
|
+
import { inferStructuredEscalation, structuredPermissionDenied } from "./structured-permission.js";
|
|
15
16
|
import { captureTaskMeta, extractClaudeAssistantMessage, extractClaudeModelName, normalizeClaudeToolInput, stampParentTaskResults, stampSelfTask, tagSubagentBlocks, ClaudeCliProtocolReducer, } from "./structured-claude-protocol.js";
|
|
16
17
|
import { OpenCodeRunner, applyOpenCodeEvent } from "./structured-opencode-adapter.js";
|
|
17
18
|
import { GrokRunner, applyGrokEvent } from "./structured-grok-adapter.js";
|
|
@@ -297,6 +298,10 @@ export class StructuredSessionManager {
|
|
|
297
298
|
* Only populated while an SDK call is in flight.
|
|
298
299
|
*/
|
|
299
300
|
pendingSdkQueries = new Map();
|
|
301
|
+
/** In-flight canUseTool waiters. One pending prompt per session. */
|
|
302
|
+
pendingPermissions = new Map();
|
|
303
|
+
/** approve_turn memory, scoped to the current SDK query. */
|
|
304
|
+
turnApprovalMemory = new Map();
|
|
300
305
|
interruptedWith = new Map();
|
|
301
306
|
interruptedSkills = new Map();
|
|
302
307
|
/**
|
|
@@ -475,6 +480,11 @@ export class StructuredSessionManager {
|
|
|
475
480
|
continue;
|
|
476
481
|
execution.interrupt();
|
|
477
482
|
}
|
|
483
|
+
for (const [sessionId, waiter] of this.pendingPermissions) {
|
|
484
|
+
waiter.resolve(structuredPermissionDenied("服务已关闭"));
|
|
485
|
+
this.pendingPermissions.delete(sessionId);
|
|
486
|
+
}
|
|
487
|
+
this.turnApprovalMemory.clear();
|
|
478
488
|
for (const query of this.pendingSdkQueries.values()) {
|
|
479
489
|
void query.interrupt().catch(() => { });
|
|
480
490
|
}
|
|
@@ -1206,11 +1216,15 @@ export class StructuredSessionManager {
|
|
|
1206
1216
|
if (!this.isCurrentRequest(id, requestId)) {
|
|
1207
1217
|
return current;
|
|
1208
1218
|
}
|
|
1219
|
+
this.settlePendingPermission(id, undefined, structuredPermissionDenied("会话执行失败"));
|
|
1220
|
+
this.turnApprovalMemory.delete(id);
|
|
1209
1221
|
const failed = {
|
|
1210
1222
|
...current,
|
|
1211
1223
|
status: "failed",
|
|
1212
1224
|
exitCode: 1,
|
|
1213
1225
|
endedAt: new Date().toISOString(),
|
|
1226
|
+
pendingEscalation: null,
|
|
1227
|
+
permissionBlocked: false,
|
|
1214
1228
|
structuredState: {
|
|
1215
1229
|
...current.structuredState,
|
|
1216
1230
|
inFlight: false,
|
|
@@ -1410,11 +1424,40 @@ export class StructuredSessionManager {
|
|
|
1410
1424
|
toggleAutoApprove(sessionId) {
|
|
1411
1425
|
const session = this.requireSession(sessionId);
|
|
1412
1426
|
const newVal = !session.autoApprovePermissions;
|
|
1427
|
+
if (newVal && session.pendingEscalation) {
|
|
1428
|
+
const resolved = this.resolveEscalation(sessionId, session.pendingEscalation.requestId, "approve_once");
|
|
1429
|
+
const updated = { ...resolved, autoApprovePermissions: true };
|
|
1430
|
+
this.sessions.set(sessionId, updated);
|
|
1431
|
+
this.storage.updateSessionRuntimeMetadata(updated);
|
|
1432
|
+
this.emit({
|
|
1433
|
+
type: "status",
|
|
1434
|
+
sessionId,
|
|
1435
|
+
data: { sessionKind: "structured", autoApprovePermissions: true },
|
|
1436
|
+
});
|
|
1437
|
+
return updated;
|
|
1438
|
+
}
|
|
1413
1439
|
const updated = { ...session, autoApprovePermissions: newVal };
|
|
1414
1440
|
this.sessions.set(sessionId, updated);
|
|
1415
1441
|
this.storage.updateSessionRuntimeMetadata(updated);
|
|
1442
|
+
this.emit({
|
|
1443
|
+
type: "status",
|
|
1444
|
+
sessionId,
|
|
1445
|
+
data: { sessionKind: "structured", autoApprovePermissions: newVal },
|
|
1446
|
+
});
|
|
1416
1447
|
return updated;
|
|
1417
1448
|
}
|
|
1449
|
+
approvePermission(sessionId) {
|
|
1450
|
+
const pending = this.requireSession(sessionId).pendingEscalation;
|
|
1451
|
+
if (!pending)
|
|
1452
|
+
throw new Error("当前会话没有待处理的授权请求。");
|
|
1453
|
+
return this.resolveEscalation(sessionId, pending.requestId, "approve_once");
|
|
1454
|
+
}
|
|
1455
|
+
denyPermission(sessionId) {
|
|
1456
|
+
const pending = this.requireSession(sessionId).pendingEscalation;
|
|
1457
|
+
if (!pending)
|
|
1458
|
+
throw new Error("当前会话没有待处理的授权请求。");
|
|
1459
|
+
return this.resolveEscalation(sessionId, pending.requestId, "deny");
|
|
1460
|
+
}
|
|
1418
1461
|
/** Resolve a specific escalation by requestId. */
|
|
1419
1462
|
resolveEscalation(sessionId, requestId, resolution) {
|
|
1420
1463
|
const session = this.requireSession(sessionId);
|
|
@@ -1433,6 +1476,12 @@ export class StructuredSessionManager {
|
|
|
1433
1476
|
if (approved && scope) {
|
|
1434
1477
|
this.incrementApprovalStats(session, scope);
|
|
1435
1478
|
}
|
|
1479
|
+
if (approved && resolution === "approve_turn") {
|
|
1480
|
+
this.rememberTurnApproval(sessionId, pending.scope, pending.target);
|
|
1481
|
+
}
|
|
1482
|
+
this.settlePendingPermission(sessionId, pending.requestId, approved
|
|
1483
|
+
? { behavior: "allow" }
|
|
1484
|
+
: structuredPermissionDenied("User rejected permission request"));
|
|
1436
1485
|
const updated = {
|
|
1437
1486
|
...session,
|
|
1438
1487
|
pendingEscalation: null,
|
|
@@ -1453,6 +1502,8 @@ export class StructuredSessionManager {
|
|
|
1453
1502
|
return updated;
|
|
1454
1503
|
}
|
|
1455
1504
|
stop(id) {
|
|
1505
|
+
this.settlePendingPermission(id, undefined, structuredPermissionDenied("已停止"));
|
|
1506
|
+
this.turnApprovalMemory.delete(id);
|
|
1456
1507
|
const session = this.requireSession(id);
|
|
1457
1508
|
this.interruptedWith.delete(id);
|
|
1458
1509
|
this.interruptedSkills.delete(id);
|
|
@@ -1499,6 +1550,8 @@ export class StructuredSessionManager {
|
|
|
1499
1550
|
return cancelled;
|
|
1500
1551
|
}
|
|
1501
1552
|
delete(id) {
|
|
1553
|
+
this.settlePendingPermission(id, undefined, structuredPermissionDenied("会话已删除"));
|
|
1554
|
+
this.turnApprovalMemory.delete(id);
|
|
1502
1555
|
const runnerExecution = this.pendingRunnerExecutions.get(id);
|
|
1503
1556
|
const sdkQuery = this.pendingSdkQueries.get(id);
|
|
1504
1557
|
const sdkAbort = this.pendingSdkAbort.get(id);
|
|
@@ -1643,6 +1696,123 @@ export class StructuredSessionManager {
|
|
|
1643
1696
|
stats.total++;
|
|
1644
1697
|
session.approvalStats = stats;
|
|
1645
1698
|
}
|
|
1699
|
+
rememberTurnApproval(sessionId, scope, target) {
|
|
1700
|
+
let memory = this.turnApprovalMemory.get(sessionId);
|
|
1701
|
+
if (!memory) {
|
|
1702
|
+
memory = { scopes: new Set(), targets: new Set() };
|
|
1703
|
+
this.turnApprovalMemory.set(sessionId, memory);
|
|
1704
|
+
}
|
|
1705
|
+
memory.scopes.add(scope);
|
|
1706
|
+
if (target)
|
|
1707
|
+
memory.targets.add(target);
|
|
1708
|
+
}
|
|
1709
|
+
settlePendingPermission(sessionId, requestId, result) {
|
|
1710
|
+
const waiter = this.pendingPermissions.get(sessionId);
|
|
1711
|
+
if (!waiter)
|
|
1712
|
+
return;
|
|
1713
|
+
if (requestId !== undefined && waiter.requestId !== requestId)
|
|
1714
|
+
return;
|
|
1715
|
+
this.pendingPermissions.delete(sessionId);
|
|
1716
|
+
waiter.resolve(result);
|
|
1717
|
+
}
|
|
1718
|
+
async handleCanUseTool(sessionId, requestId, toolName, input, ctx) {
|
|
1719
|
+
const deny = (message) => structuredPermissionDenied(message);
|
|
1720
|
+
if (ctx.signal.aborted || this.disposed)
|
|
1721
|
+
return deny("已取消");
|
|
1722
|
+
const current = this.currentSessionForRequest(sessionId, requestId);
|
|
1723
|
+
if (!current)
|
|
1724
|
+
return deny("会话已结束");
|
|
1725
|
+
const inferred = inferStructuredEscalation(toolName, input, ctx);
|
|
1726
|
+
if (current.autoApprovePermissions) {
|
|
1727
|
+
this.incrementApprovalStats(current, inferred.scope);
|
|
1728
|
+
this.storage.updateSessionRuntimeMetadata(current);
|
|
1729
|
+
return { behavior: "allow" };
|
|
1730
|
+
}
|
|
1731
|
+
const memory = this.turnApprovalMemory.get(sessionId);
|
|
1732
|
+
if (memory && (memory.scopes.has(inferred.scope) || (inferred.target && memory.targets.has(inferred.target)))) {
|
|
1733
|
+
return { behavior: "allow" };
|
|
1734
|
+
}
|
|
1735
|
+
const existing = this.pendingPermissions.get(sessionId);
|
|
1736
|
+
if (existing) {
|
|
1737
|
+
await new Promise((resolve) => {
|
|
1738
|
+
const previous = existing.resolve;
|
|
1739
|
+
existing.resolve = (result) => {
|
|
1740
|
+
previous(result);
|
|
1741
|
+
resolve(result);
|
|
1742
|
+
};
|
|
1743
|
+
});
|
|
1744
|
+
if (ctx.signal.aborted || this.disposed)
|
|
1745
|
+
return deny("已取消");
|
|
1746
|
+
return this.handleCanUseTool(sessionId, requestId, toolName, input, ctx);
|
|
1747
|
+
}
|
|
1748
|
+
const escalation = {
|
|
1749
|
+
requestId: ctx.toolUseID ? `sdk-${ctx.toolUseID}` : `sdk-${Date.now()}`,
|
|
1750
|
+
scope: inferred.scope,
|
|
1751
|
+
runner: "json",
|
|
1752
|
+
source: "tool_permission_request",
|
|
1753
|
+
target: inferred.target,
|
|
1754
|
+
reason: inferred.reason,
|
|
1755
|
+
};
|
|
1756
|
+
return await new Promise((resolve) => {
|
|
1757
|
+
let settled = false;
|
|
1758
|
+
const finish = (result) => {
|
|
1759
|
+
if (settled)
|
|
1760
|
+
return;
|
|
1761
|
+
settled = true;
|
|
1762
|
+
ctx.signal.removeEventListener("abort", onAbort);
|
|
1763
|
+
if (this.pendingPermissions.get(sessionId)?.requestId === escalation.requestId) {
|
|
1764
|
+
this.pendingPermissions.delete(sessionId);
|
|
1765
|
+
}
|
|
1766
|
+
resolve(result);
|
|
1767
|
+
};
|
|
1768
|
+
const onAbort = () => {
|
|
1769
|
+
finish(deny("已取消"));
|
|
1770
|
+
const latest = this.currentSessionForRequest(sessionId, requestId);
|
|
1771
|
+
if (latest?.pendingEscalation?.requestId === escalation.requestId) {
|
|
1772
|
+
const cleared = {
|
|
1773
|
+
...latest,
|
|
1774
|
+
pendingEscalation: null,
|
|
1775
|
+
permissionBlocked: false,
|
|
1776
|
+
};
|
|
1777
|
+
this.sessions.set(sessionId, cleared);
|
|
1778
|
+
this.storage.updateSessionRuntimeMetadata(cleared);
|
|
1779
|
+
this.emit({
|
|
1780
|
+
type: "status",
|
|
1781
|
+
sessionId,
|
|
1782
|
+
data: { permissionBlocked: false, sessionKind: "structured" },
|
|
1783
|
+
});
|
|
1784
|
+
}
|
|
1785
|
+
};
|
|
1786
|
+
ctx.signal.addEventListener("abort", onAbort, { once: true });
|
|
1787
|
+
this.pendingPermissions.set(sessionId, { requestId: escalation.requestId, resolve: finish });
|
|
1788
|
+
const latest = this.currentSessionForRequest(sessionId, requestId);
|
|
1789
|
+
if (!latest || ctx.signal.aborted) {
|
|
1790
|
+
finish(deny("会话已结束"));
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
const updated = {
|
|
1794
|
+
...latest,
|
|
1795
|
+
pendingEscalation: escalation,
|
|
1796
|
+
permissionBlocked: true,
|
|
1797
|
+
};
|
|
1798
|
+
this.sessions.set(sessionId, updated);
|
|
1799
|
+
this.storage.updateSessionRuntimeMetadata(updated);
|
|
1800
|
+
this.emit({
|
|
1801
|
+
type: "status",
|
|
1802
|
+
sessionId,
|
|
1803
|
+
data: {
|
|
1804
|
+
sessionKind: "structured",
|
|
1805
|
+
permissionBlocked: true,
|
|
1806
|
+
permissionRequest: {
|
|
1807
|
+
scope: escalation.scope,
|
|
1808
|
+
target: escalation.target,
|
|
1809
|
+
prompt: escalation.reason,
|
|
1810
|
+
},
|
|
1811
|
+
pendingEscalation: escalation,
|
|
1812
|
+
},
|
|
1813
|
+
});
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1646
1816
|
// ---------------------------------------------------------------------------
|
|
1647
1817
|
// Streaming codex exec --json execution
|
|
1648
1818
|
// ---------------------------------------------------------------------------
|
|
@@ -2323,6 +2493,7 @@ export class StructuredSessionManager {
|
|
|
2323
2493
|
async runClaudeSdkStreaming(sessionId, session, prompt, requestId, skills) {
|
|
2324
2494
|
const abortController = new AbortController();
|
|
2325
2495
|
this.pendingSdkAbort.set(sessionId, abortController);
|
|
2496
|
+
this.turnApprovalMemory.delete(sessionId);
|
|
2326
2497
|
const isManaged = session.mode === "managed";
|
|
2327
2498
|
let killedForAskUserQuestion = false;
|
|
2328
2499
|
// 权限策略 + 系统提示词都通过共享 helper 派生,与 CLI runner 一字不差。
|
|
@@ -2339,6 +2510,11 @@ export class StructuredSessionManager {
|
|
|
2339
2510
|
env: sdkEnv,
|
|
2340
2511
|
permissionMode: permPolicy.permissionMode,
|
|
2341
2512
|
...(permPolicy.permissionMode === "bypassPermissions" ? { allowDangerouslySkipPermissions: true } : {}),
|
|
2513
|
+
...(permPolicy.permissionMode !== "bypassPermissions"
|
|
2514
|
+
? {
|
|
2515
|
+
canUseTool: (toolName, input, ctx) => this.handleCanUseTool(sessionId, requestId, toolName, input, ctx),
|
|
2516
|
+
}
|
|
2517
|
+
: {}),
|
|
2342
2518
|
...(permPolicy.allowedTools ? { allowedTools: permPolicy.allowedTools } : {}),
|
|
2343
2519
|
...(isManaged ? { disallowedTools: ["AskUserQuestion"] } : {}),
|
|
2344
2520
|
skills,
|
|
@@ -2714,6 +2890,8 @@ export class StructuredSessionManager {
|
|
|
2714
2890
|
}
|
|
2715
2891
|
}
|
|
2716
2892
|
// Cleanup
|
|
2893
|
+
this.settlePendingPermission(sessionId, undefined, structuredPermissionDenied("本轮已结束"));
|
|
2894
|
+
this.turnApprovalMemory.delete(sessionId);
|
|
2717
2895
|
const releasedAbort = this.releasePendingSdkAbort(sessionId, abortController);
|
|
2718
2896
|
const releasedQuery = this.releasePendingSdkQuery(sessionId, queryHandle);
|
|
2719
2897
|
if (releasedAbort || releasedQuery)
|
package/dist/taskboard-bridge.js
CHANGED
|
@@ -153,7 +153,18 @@ export function taskboardIntegrationScript() {
|
|
|
153
153
|
});
|
|
154
154
|
};
|
|
155
155
|
const scan = () => document.querySelectorAll("[data-task-id]").forEach(setup);
|
|
156
|
-
|
|
156
|
+
let readyAnnounced = false;
|
|
157
|
+
const announceReady = (repeat = false) => {
|
|
158
|
+
const root = document.getElementById("root");
|
|
159
|
+
if (!root || !root.childElementCount || window.parent === window || (readyAnnounced && !repeat)) return;
|
|
160
|
+
readyAnnounced = true;
|
|
161
|
+
window.parent.postMessage({type:"wand-taskboard-ready"}, location.origin);
|
|
162
|
+
};
|
|
163
|
+
new MutationObserver(() => { scan(); announceReady(); }).observe(document.documentElement, {childList:true, subtree:true});
|
|
164
|
+
window.addEventListener("load", () => announceReady());
|
|
165
|
+
window.addEventListener("message", (event) => {
|
|
166
|
+
if (event.origin === location.origin && event.source === window.parent && event.data?.type === "wand-taskboard-ready-request") announceReady(true);
|
|
167
|
+
});
|
|
157
168
|
scan();
|
|
158
169
|
})();
|
|
159
170
|
</script>`;
|