@cjhyy/code-shell-core 0.6.0-rc.2 → 0.6.0-rc.3
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/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/protocol/server.js +18 -2
- package/dist/protocol/types.d.ts +2 -0
- package/dist/runtime/spawn-common.js +4 -2
- package/dist/tool-system/builtin/cron.js +10 -2
- package/dist/tool-system/builtin/sleep.js +5 -0
- package/dist/tool-system/executor.js +4 -2
- package/dist/tool-system/permission.d.ts +3 -1
- package/dist/tool-system/permission.js +2 -1
- package/dist/tool-system/sandbox/off.js +5 -1
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Public API exports.
|
|
5
5
|
*/
|
|
6
|
-
export declare const VERSION = "0.
|
|
6
|
+
export declare const VERSION = "0.6.0-rc.3";
|
|
7
7
|
export type { Message, ContentBlock, ToolDefinition, ToolCall, ToolResult, RegisteredTool, TranscriptEvent, TranscriptEventType, SessionState, SessionStatus, TokenUsage, CompiledInput, PermissionDecision, PermissionMode, PermissionRule, TurnPhase, TurnResult, TerminalReason, StreamEvent, StreamCallback, LLMConfig, ClientDefaults, LLMResponse, Settings, MCPServerConfig, } from "./types.js";
|
|
8
8
|
export { FrameworkError, LLMError, LLMRateLimitError, ContextLimitError, ToolError, ToolNotFoundError, ToolExecutionError, ToolTimeoutError, PermissionDeniedError, SessionError, TranscriptError, ConfigError, SandboxUnavailableError, } from "./exceptions.js";
|
|
9
9
|
export { Engine, loadAgentDefinitionsForCwd } from "./engine/engine.js";
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Public API exports.
|
|
5
5
|
*/
|
|
6
|
-
export const VERSION = "0.
|
|
6
|
+
export const VERSION = "0.6.0-rc.3";
|
|
7
7
|
// ─── Exceptions ──────────────────────────────────────────────────
|
|
8
8
|
export { FrameworkError, LLMError, LLMRateLimitError, ContextLimitError, ToolError, ToolNotFoundError, ToolExecutionError, ToolTimeoutError, PermissionDeniedError, SessionError, TranscriptError, ConfigError, SandboxUnavailableError, } from "./exceptions.js";
|
|
9
9
|
// ─── Engine (primary API) ────────────────────────────────────────
|
package/dist/protocol/server.js
CHANGED
|
@@ -461,7 +461,18 @@ export class AgentServer {
|
|
|
461
461
|
}
|
|
462
462
|
const resolve = s.pendingApprovals.get(params.requestId);
|
|
463
463
|
if (!resolve) {
|
|
464
|
-
|
|
464
|
+
// Tool approvals still resolve through the interactive backend's
|
|
465
|
+
// legacy pending map; the sessionId on their envelope is UI routing
|
|
466
|
+
// metadata. Accept a session-tagged response for those requests too.
|
|
467
|
+
const legacyResolve = this.pendingApprovals.get(params.requestId);
|
|
468
|
+
if (!legacyResolve) {
|
|
469
|
+
this.transport.send(createErrorResponse(req.id, ErrorCodes.InvalidParams, `No pending approval: ${params.requestId}`));
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
this.pendingApprovals.delete(params.requestId);
|
|
473
|
+
this.clearApprovalTimer(params.requestId);
|
|
474
|
+
legacyResolve(params.decision);
|
|
475
|
+
this.transport.send(createResponse(req.id, { ok: true }));
|
|
465
476
|
return;
|
|
466
477
|
}
|
|
467
478
|
s.pendingApprovals.delete(params.requestId);
|
|
@@ -1291,6 +1302,7 @@ export class AgentServer {
|
|
|
1291
1302
|
requestApprovalFromClient(request) {
|
|
1292
1303
|
return new Promise((resolve) => {
|
|
1293
1304
|
const requestId = nanoid(12);
|
|
1305
|
+
const sessionId = typeof request.sessionId === "string" ? request.sessionId : undefined;
|
|
1294
1306
|
this.pendingApprovals.set(requestId, resolve);
|
|
1295
1307
|
const timer = setTimeout(() => {
|
|
1296
1308
|
if (this.pendingApprovals.has(requestId)) {
|
|
@@ -1300,7 +1312,11 @@ export class AgentServer {
|
|
|
1300
1312
|
}
|
|
1301
1313
|
}, AgentServer.APPROVAL_TIMEOUT_MS);
|
|
1302
1314
|
this.approvalTimers.set(requestId, timer);
|
|
1303
|
-
this.notify(Methods.ApprovalRequest, {
|
|
1315
|
+
this.notify(Methods.ApprovalRequest, {
|
|
1316
|
+
...(sessionId ? { sessionId } : {}),
|
|
1317
|
+
requestId,
|
|
1318
|
+
request,
|
|
1319
|
+
});
|
|
1304
1320
|
});
|
|
1305
1321
|
}
|
|
1306
1322
|
/**
|
package/dist/protocol/types.d.ts
CHANGED
|
@@ -243,6 +243,8 @@ export interface AgentStreamEventNotification {
|
|
|
243
243
|
}
|
|
244
244
|
/** Server requests approval from the client (UI). */
|
|
245
245
|
export interface ApprovalRequestNotification {
|
|
246
|
+
/** Originating engine session when known. */
|
|
247
|
+
sessionId?: string;
|
|
246
248
|
requestId: string;
|
|
247
249
|
request: ApprovalRequest;
|
|
248
250
|
}
|
|
@@ -143,8 +143,10 @@ export function resolveSpawnTarget(command, opts) {
|
|
|
143
143
|
const wrapped = opts.sandbox.wrap(command, { cwd: opts.cwd, shell: opts.shell });
|
|
144
144
|
return { file: wrapped.file, args: wrapped.args, cleanup: wrapped.cleanup };
|
|
145
145
|
}
|
|
146
|
-
// No sandbox
|
|
147
|
-
//
|
|
146
|
+
// No sandbox configured: pick the shell + command-flag form for the
|
|
147
|
+
// platform instead of assuming POSIX `-c`. Note Bash always passes a
|
|
148
|
+
// backend (off at minimum), so it never reaches this line — the off
|
|
149
|
+
// backend's wrap() delegates to resolveShellInvocation itself.
|
|
148
150
|
return resolveShellInvocation(command, opts.shell);
|
|
149
151
|
}
|
|
150
152
|
/**
|
|
@@ -27,7 +27,14 @@ export const cronCreateToolDef = {
|
|
|
27
27
|
"'30 8 * * 1' = 8:30am every Monday. Day-of-week: 0=Sunday..6=Saturday.\n\n" +
|
|
28
28
|
"For calendar schedules, set `timezone` to the user's IANA zone (e.g. 'Asia/Shanghai', " +
|
|
29
29
|
"'America/New_York'); ask the user if unknown. Set `cwd` to the project the job operates on. " +
|
|
30
|
-
"Leave `permissionLevel` as 'read-only' unless the user explicitly wants the job to modify code
|
|
30
|
+
"Leave `permissionLevel` as 'read-only' unless the user explicitly wants the job to modify code.\n\n" +
|
|
31
|
+
"SELF-WAKEUP / background-task safety net: you can also schedule THIS job for yourself, with no user " +
|
|
32
|
+
"request, to re-check on a long-running background task (a download, a build, a background shell/agent) " +
|
|
33
|
+
"that might hang and never signal completion. Use a short interval + `once: true` + `continueInSession: true` " +
|
|
34
|
+
"and a `prompt` that reminds you what to check, e.g. schedule '5m', once true, continueInSession true, " +
|
|
35
|
+
"prompt 'check whether the yt-dlp download finished (BashOutput/ListShells); if still running, wait again'. " +
|
|
36
|
+
"You wake back in THIS conversation with full context, inspect the task, and either finish or reschedule. " +
|
|
37
|
+
"This is the right pattern for a simple poll-until-done loop or a hang safety net — prefer it over looping Sleep.",
|
|
31
38
|
inputSchema: {
|
|
32
39
|
type: "object",
|
|
33
40
|
properties: {
|
|
@@ -52,7 +59,8 @@ export const cronCreateToolDef = {
|
|
|
52
59
|
once: {
|
|
53
60
|
type: "boolean",
|
|
54
61
|
description: "true = one-shot: run once at the scheduled time, then auto-delete (for 'in N minutes / " +
|
|
55
|
-
"at <time>, do X once' reminders or
|
|
62
|
+
"at <time>, do X once' reminders, tasks, or a self-wakeup to re-check a background task). " +
|
|
63
|
+
"Default false = recurring per `schedule`. " +
|
|
56
64
|
"A one-shot still uses `schedule` for its time: interval '10m' = 10 minutes from now; " +
|
|
57
65
|
"cron '0 7 25 6 *' = once at 07:00 on June 25.",
|
|
58
66
|
},
|
|
@@ -6,6 +6,11 @@ export const sleepToolDef = {
|
|
|
6
6
|
description: "Pause execution for a brief, deterministic wait (e.g. letting a just-started service settle for a few seconds). " +
|
|
7
7
|
"Do NOT use Sleep to poll for or wait on background work (background shells, async sub-agents, video generation): " +
|
|
8
8
|
"the system wakes you automatically when that work completes — just end your turn instead of looping Sleep. " +
|
|
9
|
+
"If you want a safety net in case a background task hangs and never signals completion, do NOT loop Sleep either — " +
|
|
10
|
+
"instead end your turn and schedule a one-shot self-wakeup with CronCreate " +
|
|
11
|
+
"({ schedule: '5m', once: true, continueInSession: true, permissionLevel: 'read-only', " +
|
|
12
|
+
"prompt: 'check whether <that task> finished; if still running, wait again' }). " +
|
|
13
|
+
"That returns control to you at the interval without burning a turn spinning. " +
|
|
9
14
|
"Maximum duration is 300 seconds (5 minutes).",
|
|
10
15
|
inputSchema: {
|
|
11
16
|
type: "object",
|
|
@@ -274,7 +274,7 @@ export class ToolExecutor {
|
|
|
274
274
|
// the hook and the user together have decided.
|
|
275
275
|
if (hookResult.decision === "ask") {
|
|
276
276
|
const reason = hookResult.messages?.join("\n") ?? undefined;
|
|
277
|
-
const approved = await this.permission.handleAsk(call.toolName, call.args, reason);
|
|
277
|
+
const approved = await this.permission.handleAsk(call.toolName, call.args, reason, { sessionId: this.toolCtx?.sessionId });
|
|
278
278
|
if (!approved) {
|
|
279
279
|
return {
|
|
280
280
|
id: call.id,
|
|
@@ -347,7 +347,9 @@ export class ToolExecutor {
|
|
|
347
347
|
}
|
|
348
348
|
if (decision === "ask") {
|
|
349
349
|
const reason = permHook.messages?.join("\n");
|
|
350
|
-
const approved = await this.permission.handleAsk(call.toolName, call.args, reason
|
|
350
|
+
const approved = await this.permission.handleAsk(call.toolName, call.args, reason, {
|
|
351
|
+
sessionId: this.toolCtx?.sessionId,
|
|
352
|
+
});
|
|
351
353
|
if (!approved) {
|
|
352
354
|
return {
|
|
353
355
|
id: call.id,
|
|
@@ -130,7 +130,9 @@ export declare class PermissionClassifier {
|
|
|
130
130
|
reconfigure(mode: PermissionMode, approvalBackend: ApprovalBackend, rules?: PermissionRule[]): void;
|
|
131
131
|
getMode(): PermissionMode;
|
|
132
132
|
classify(toolName: string, args: Record<string, unknown>): PermissionDecision;
|
|
133
|
-
handleAsk(toolName: string, args: Record<string, unknown>, reason?: string
|
|
133
|
+
handleAsk(toolName: string, args: Record<string, unknown>, reason?: string, opts?: {
|
|
134
|
+
sessionId?: string;
|
|
135
|
+
}): Promise<boolean>;
|
|
134
136
|
/** Get denial warning message if the model keeps getting denied. */
|
|
135
137
|
getDenialWarning(toolName: string): string | undefined;
|
|
136
138
|
private matchesRule;
|
|
@@ -861,7 +861,7 @@ export class PermissionClassifier {
|
|
|
861
861
|
return "ask";
|
|
862
862
|
}
|
|
863
863
|
}
|
|
864
|
-
async handleAsk(toolName, args, reason) {
|
|
864
|
+
async handleAsk(toolName, args, reason, opts) {
|
|
865
865
|
if (this.defaultMode === "dontAsk") {
|
|
866
866
|
this.log.info("permission.auto_deny", {
|
|
867
867
|
cat: "permission",
|
|
@@ -900,6 +900,7 @@ export class PermissionClassifier {
|
|
|
900
900
|
? `${baseDescription}\n\nReason (from pre_tool_use hook): ${reason}`
|
|
901
901
|
: baseDescription;
|
|
902
902
|
result = await this.approvalBackend.requestApproval({
|
|
903
|
+
...(opts?.sessionId ? { sessionId: opts.sessionId } : {}),
|
|
903
904
|
toolName,
|
|
904
905
|
args,
|
|
905
906
|
description,
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { resolveShellInvocation } from "../../runtime/spawn-common.js";
|
|
1
2
|
export function createOffBackend() {
|
|
2
3
|
return {
|
|
3
4
|
name: "off",
|
|
4
5
|
wrap(command, opts) {
|
|
5
|
-
|
|
6
|
+
// Platform-aware flag: cmd.exe takes /c, PowerShell -Command, POSIX -c.
|
|
7
|
+
// Bash always passes a backend (off at minimum), so resolveSpawnTarget's
|
|
8
|
+
// no-sandbox fallback never covers this path — wrap() must handle it.
|
|
9
|
+
return resolveShellInvocation(command, opts.shell);
|
|
6
10
|
},
|
|
7
11
|
};
|
|
8
12
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -229,6 +229,8 @@ export interface PermissionRule {
|
|
|
229
229
|
reason?: string;
|
|
230
230
|
}
|
|
231
231
|
export interface ApprovalRequest {
|
|
232
|
+
/** Originating engine session. Hosts use this only to route the prompt UI. */
|
|
233
|
+
sessionId?: string;
|
|
232
234
|
toolName: string;
|
|
233
235
|
args: Record<string, unknown>;
|
|
234
236
|
description: string;
|
package/package.json
CHANGED