@margay/ccl-core 1.5.1-alpha.3 → 1.5.1-alpha.5
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/QUICKSTART.md +9 -7
- package/README.md +15 -15
- package/dist/cli.js +186368 -202079
- package/dist/sdk/background.d.ts +14 -0
- package/dist/sdk/background.js +3 -1
- package/dist/sdk/index.d.ts +1 -0
- package/dist/sdk/mcpServer.d.ts +1 -1
- package/dist/sdk/mcpServer.js +1 -1
- package/dist/sdk/query.js +2 -2
- package/dist/sdk/scheduledNotificationTypes.d.ts +53 -0
- package/dist/sdk/scheduledNotificationTypes.js +18 -0
- package/dist/sdk/types.d.ts +5 -7
- package/dist/sdk/types.js +2 -4
- package/docs/background-runs.md +46 -2
- package/docs/ccl-duo-agent.md +1 -1
- package/docs/error-recovery-usage.md +6 -4
- package/docs/gateway-quickstart.md +2 -2
- package/docs/releases/1.5.1-alpha.4.md +27 -0
- package/docs/releases/1.5.1-alpha.5.md +35 -0
- package/docs/self-hosted-product-events.md +1 -1
- package/package.json +5 -3
- package/sdk/API.md +10 -3
- package/sdk/README.md +5 -7
package/dist/sdk/background.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BackgroundRun, BackgroundRunAction, BackgroundRunApproval, BackgroundRunEvents, BackgroundRunLookup, BackgroundRunSelector, BackgroundRunSpec, BackgroundRunSource } from './backgroundRunTypes.js';
|
|
2
2
|
import type { OccurrenceCancelRequest, OccurrenceApprovalRequest, OccurrenceApprovalReceipt, OccurrenceLookup, OccurrenceEvents, ScheduledOccurrence } from './scheduledOccurrenceTypes.js';
|
|
3
|
+
import type { ScheduledNotificationSelector, ScheduledNotificationRebind, ScheduledNotificationBindingLookup } from './scheduledNotificationTypes.js';
|
|
3
4
|
export type BackgroundClientOptions = {
|
|
4
5
|
cwd: string;
|
|
5
6
|
cliPath: string;
|
|
@@ -19,6 +20,19 @@ export declare class BackgroundClientError extends Error {
|
|
|
19
20
|
/** Durable runs do not retain JS callbacks or in-process SDK MCP servers. Use
|
|
20
21
|
* persistent stdio/HTTP tools configured through launch instead. */
|
|
21
22
|
export declare function createBackgroundClient(options: BackgroundClientOptions): {
|
|
23
|
+
getScheduledNotificationBinding: (selector: ScheduledNotificationSelector) => Promise<ScheduledNotificationBindingLookup>;
|
|
24
|
+
rebindScheduledNotifications: (request: ScheduledNotificationRebind) => Promise<{
|
|
25
|
+
selector: {
|
|
26
|
+
taskId: string;
|
|
27
|
+
taskCreatedAt: number;
|
|
28
|
+
} | {
|
|
29
|
+
occurrenceId: string;
|
|
30
|
+
};
|
|
31
|
+
sessionId: string;
|
|
32
|
+
revision: number;
|
|
33
|
+
generation: string;
|
|
34
|
+
updatedAt: number;
|
|
35
|
+
}>;
|
|
22
36
|
getOccurrence: (request: {
|
|
23
37
|
occurrenceId: string;
|
|
24
38
|
}) => Promise<OccurrenceLookup>;
|
package/dist/sdk/background.js
CHANGED
|
@@ -18,7 +18,7 @@ export function createBackgroundClient(options) {
|
|
|
18
18
|
// Serialization can throw (for example for a cyclic input); do it before
|
|
19
19
|
// allocating a subprocess that would otherwise wait forever for stdin.
|
|
20
20
|
const input = JSON.stringify(request);
|
|
21
|
-
const retryAdvice = command.includes('occurrence') ? 'Read the original occurrence and approvalDecisions. Retry approval only with the same actionId and payload.' : 'Query the original requestKey; do not submit a new key.';
|
|
21
|
+
const retryAdvice = command.includes('notification') ? 'Read the original notification binding. Retry a binding mutation only with the same actionId and payload.' : command.includes('occurrence') ? 'Read the original occurrence and approvalDecisions. Retry approval only with the same actionId and payload.' : 'Query the original requestKey; do not submit a new key.';
|
|
22
22
|
return new Promise((resolve, reject) => {
|
|
23
23
|
const child = spawn(options.execPath ?? process.execPath, [options.cliPath, 'daemon', command, '--cwd', options.cwd, '--request-stdin'], {
|
|
24
24
|
cwd: options.cwd, env: options.env ?? process.env, stdio: ['pipe', 'pipe', 'pipe'],
|
|
@@ -73,6 +73,8 @@ export function createBackgroundClient(options) {
|
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
75
|
return {
|
|
76
|
+
getScheduledNotificationBinding: (selector) => invoke('get-scheduled-notification-binding', { selector }),
|
|
77
|
+
rebindScheduledNotifications: (request) => invoke('rebind-scheduled-notifications', request),
|
|
76
78
|
getOccurrence: (request) => invoke('get-occurrence', request),
|
|
77
79
|
listOccurrences: (request = {}) => invoke('list-occurrences', request),
|
|
78
80
|
readOccurrenceEvents: (request) => invoke('occurrence-events', request),
|
package/dist/sdk/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export type { GatewayRequestPhase, GatewayRequestProgress } from './requestProgr
|
|
|
21
21
|
export type { AccumulatedUsage, CanUseToolContext, CanUseToolFn, CanUseToolResult, InitializationResult, LifecycleHooks, PendingApproval, PendingDecision, ProviderConfig, Query, QueryOptions, SDKEvent, SDKUserMessage, SessionStore, SessionLifecycleEvent, Transport, Usage, WireMessage, } from './types.js';
|
|
22
22
|
export { getExecutionGuidance } from './executionGuidance.js';
|
|
23
23
|
export { createBackgroundClient, BackgroundClientError, type BackgroundClientOptions } from './background.js';
|
|
24
|
+
export type { ScheduledNotificationSelector, ScheduledNotificationRebind, ScheduledNotificationBinding, ScheduledNotificationBindingLookup, EffectiveScheduledNotificationRoute } from './scheduledNotificationTypes.js';
|
|
24
25
|
export type { BackgroundRun, BackgroundRunSpec, BackgroundRunLookup, BackgroundRunSelector, BackgroundRunEvent, BackgroundRunEvents, BackgroundRunAction, BackgroundRunApproval, BackgroundPermission, BackgroundRunSource } from './backgroundRunTypes.js';
|
|
25
26
|
export { runCommandProcess, type CommandProcessInput, type CommandProcessResult } from './commandProcess.js';
|
|
26
27
|
export { createCommandAdapter, type CommandAdapter, type CommandAdapterSpec, type CommandDefinition, type CommandOperation, type CommandOutcome, type CommandExecution, type JsonValue } from './commandAdapter.js';
|
package/dist/sdk/mcpServer.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export type McpSdkServerConfigWithInstance = {
|
|
|
22
22
|
instance?: Server;
|
|
23
23
|
[key: string]: unknown;
|
|
24
24
|
};
|
|
25
|
-
/** Define one in-process tool (
|
|
25
|
+
/** Define one in-process tool (compatible agent SDK signature). */
|
|
26
26
|
export declare function tool(name: string, description: string, inputSchema: ZodRawShape, handler: SdkMcpToolDefinition['handler'], extras?: Pick<SdkMcpToolDefinition, 'annotations' | 'searchHint' | 'alwaysLoad'>): SdkMcpToolDefinition;
|
|
27
27
|
/**
|
|
28
28
|
* Build an in-process MCP server from host-defined JS tools. Returns a config carrying the live
|
package/dist/sdk/mcpServer.js
CHANGED
|
@@ -6,7 +6,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
6
6
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
7
7
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import { z } from 'zod/v4';
|
|
9
|
-
/** Define one in-process tool (
|
|
9
|
+
/** Define one in-process tool (compatible agent SDK signature). */
|
|
10
10
|
export function tool(name, description, inputSchema, handler, extras) {
|
|
11
11
|
return { name, description, inputSchema, handler, ...(extras ?? {}) };
|
|
12
12
|
}
|
package/dist/sdk/query.js
CHANGED
|
@@ -102,7 +102,7 @@ export function buildCliArgs(options) {
|
|
|
102
102
|
if (options.cwd)
|
|
103
103
|
args.push('--cwd', options.cwd);
|
|
104
104
|
// slice sdk-token-streaming (G3): opt-in token-level streaming — the CLI then emits stream_event
|
|
105
|
-
// (
|
|
105
|
+
// (Messages API raw message stream) deltas. Default off keeps the minimal event set unchanged.
|
|
106
106
|
if (options.includePartialMessages)
|
|
107
107
|
args.push('--include-partial-messages');
|
|
108
108
|
if (options.includeErrorDiagnostics)
|
|
@@ -831,7 +831,7 @@ export async function* queryWithTransport(prompt, options, transport) {
|
|
|
831
831
|
break;
|
|
832
832
|
}
|
|
833
833
|
case 'stream_event': {
|
|
834
|
-
// slice sdk-token-streaming (G3): forward one
|
|
834
|
+
// slice sdk-token-streaming (G3): forward one Messages API raw message stream event
|
|
835
835
|
// (token-level delta). Only arrives when includePartialMessages passed the flag.
|
|
836
836
|
const streamEvent = message.event;
|
|
837
837
|
if (streamEvent && typeof streamEvent.type === 'string') {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
export declare const scheduledNotificationSelectorSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
3
|
+
taskId: z.ZodString;
|
|
4
|
+
taskCreatedAt: z.ZodNumber;
|
|
5
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
6
|
+
occurrenceId: z.ZodString;
|
|
7
|
+
}, z.core.$strict>]>;
|
|
8
|
+
export type ScheduledNotificationSelector = z.infer<typeof scheduledNotificationSelectorSchema>;
|
|
9
|
+
export declare const scheduledNotificationLookupSchema: z.ZodObject<{
|
|
10
|
+
selector: z.ZodUnion<readonly [z.ZodObject<{
|
|
11
|
+
taskId: z.ZodString;
|
|
12
|
+
taskCreatedAt: z.ZodNumber;
|
|
13
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
14
|
+
occurrenceId: z.ZodString;
|
|
15
|
+
}, z.core.$strict>]>;
|
|
16
|
+
}, z.core.$strict>;
|
|
17
|
+
export declare const scheduledNotificationRebindSchema: z.ZodObject<{
|
|
18
|
+
selector: z.ZodUnion<readonly [z.ZodObject<{
|
|
19
|
+
taskId: z.ZodString;
|
|
20
|
+
taskCreatedAt: z.ZodNumber;
|
|
21
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
22
|
+
occurrenceId: z.ZodString;
|
|
23
|
+
}, z.core.$strict>]>;
|
|
24
|
+
targetSessionId: z.ZodString;
|
|
25
|
+
expectedRevision: z.ZodNumber;
|
|
26
|
+
actionId: z.ZodString;
|
|
27
|
+
}, z.core.$strict>;
|
|
28
|
+
export type ScheduledNotificationRebind = z.infer<typeof scheduledNotificationRebindSchema>;
|
|
29
|
+
export declare const scheduledNotificationBindingSchema: z.ZodObject<{
|
|
30
|
+
selector: z.ZodUnion<readonly [z.ZodObject<{
|
|
31
|
+
taskId: z.ZodString;
|
|
32
|
+
taskCreatedAt: z.ZodNumber;
|
|
33
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
34
|
+
occurrenceId: z.ZodString;
|
|
35
|
+
}, z.core.$strict>]>;
|
|
36
|
+
sessionId: z.ZodString;
|
|
37
|
+
revision: z.ZodNumber;
|
|
38
|
+
generation: z.ZodString;
|
|
39
|
+
updatedAt: z.ZodNumber;
|
|
40
|
+
}, z.core.$strict>;
|
|
41
|
+
export type ScheduledNotificationBinding = z.infer<typeof scheduledNotificationBindingSchema>;
|
|
42
|
+
export type EffectiveScheduledNotificationRoute = {
|
|
43
|
+
sessionId: string | null;
|
|
44
|
+
source: 'occurrence' | 'task' | 'delegation' | 'unbound';
|
|
45
|
+
binding?: ScheduledNotificationBinding;
|
|
46
|
+
};
|
|
47
|
+
export type ScheduledNotificationBindingLookup = {
|
|
48
|
+
selector: ScheduledNotificationSelector;
|
|
49
|
+
revision: number;
|
|
50
|
+
binding: ScheduledNotificationBinding | null;
|
|
51
|
+
/** For occurrence selectors, includes inherited task routing. */
|
|
52
|
+
effective?: EffectiveScheduledNotificationRoute;
|
|
53
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
export const scheduledNotificationSelectorSchema = z.union([
|
|
3
|
+
z.strictObject({ taskId: z.string().min(1), taskCreatedAt: z.number().int().nonnegative() }),
|
|
4
|
+
z.strictObject({ occurrenceId: z.string().regex(/^[a-f0-9]{64}$/) }),
|
|
5
|
+
]);
|
|
6
|
+
export const scheduledNotificationLookupSchema = z.strictObject({ selector: scheduledNotificationSelectorSchema });
|
|
7
|
+
export const scheduledNotificationRebindSchema = scheduledNotificationLookupSchema.extend({
|
|
8
|
+
targetSessionId: z.string().min(1).max(200),
|
|
9
|
+
expectedRevision: z.number().int().nonnegative(),
|
|
10
|
+
actionId: z.string().min(1).max(200),
|
|
11
|
+
});
|
|
12
|
+
export const scheduledNotificationBindingSchema = z.strictObject({
|
|
13
|
+
selector: scheduledNotificationSelectorSchema,
|
|
14
|
+
sessionId: z.string().min(1).max(200),
|
|
15
|
+
revision: z.number().int().positive(),
|
|
16
|
+
generation: z.string().uuid(),
|
|
17
|
+
updatedAt: z.number().int().nonnegative(),
|
|
18
|
+
});
|
package/dist/sdk/types.d.ts
CHANGED
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
* ccl-sdk public types — the embeddable SDK form of CCL (issue: CCL 改造升级,
|
|
3
3
|
* 抽出可内嵌的 SDK 形态支撑 margay 内嵌 CoS 常驻运行).
|
|
4
4
|
*
|
|
5
|
-
* The interface
|
|
6
|
-
*
|
|
7
|
-
* keep a single call seam and swap between ccl-sdk (domestic-model customers)
|
|
8
|
-
* and the Anthropic Agent SDK (Claude customers).
|
|
5
|
+
* The interface exposes query(), a canUseTool callback, and session resume
|
|
6
|
+
* so hosts can keep a shared calling interface across compatible runtimes.
|
|
9
7
|
*
|
|
10
8
|
* Wire contract: these types mirror the stream-json control protocol that
|
|
11
9
|
* cli/print.ts + cli/structuredIO.ts already speak. The SDK is the HOST side
|
|
@@ -138,7 +136,7 @@ export type QueryOptions = {
|
|
|
138
136
|
/**
|
|
139
137
|
* slice sdk-token-streaming (G3): emit `stream_event` deltas as they arrive (token-level
|
|
140
138
|
* streaming). Passes `--include-partial-messages` to the CLI so the subprocess streams
|
|
141
|
-
*
|
|
139
|
+
* Messages API raw message stream events (content_block_delta/text_delta, etc.). Default off →
|
|
142
140
|
* unchanged behavior; the full-block `assistant_text` events are still emitted alongside.
|
|
143
141
|
*/
|
|
144
142
|
includePartialMessages?: boolean;
|
|
@@ -181,7 +179,7 @@ export type QueryOptions = {
|
|
|
181
179
|
skillsDirs?: string[];
|
|
182
180
|
/**
|
|
183
181
|
* Model provider (issue P0-4). 'anthropic' maps to --base-url/--api-key
|
|
184
|
-
* (any
|
|
182
|
+
* (any Messages API endpoint). 'openai-compatible' maps to CCL's
|
|
185
183
|
* gateway channel (CCL_GATEWAY_URL/CCL_GATEWAY_KEY) — CCL reaches
|
|
186
184
|
* OpenAI-compatible models through its gateway, which normalizes
|
|
187
185
|
* tool-calling and rejects models without native function calling instead
|
|
@@ -446,7 +444,7 @@ type SDKEventPayload = {
|
|
|
446
444
|
message: Record<string, unknown>;
|
|
447
445
|
}
|
|
448
446
|
/**
|
|
449
|
-
* slice sdk-token-streaming (G3): one
|
|
447
|
+
* slice sdk-token-streaming (G3): one Messages API raw message stream event (token-level delta),
|
|
450
448
|
* emitted only when `includePartialMessages` is set. `event.type` is one of
|
|
451
449
|
* content_block_start / content_block_delta / content_block_stop / message_delta /
|
|
452
450
|
* message_start / message_stop; e.g. a content_block_delta carries `delta.text` (text_delta).
|
package/dist/sdk/types.js
CHANGED
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
* ccl-sdk public types — the embeddable SDK form of CCL (issue: CCL 改造升级,
|
|
3
3
|
* 抽出可内嵌的 SDK 形态支撑 margay 内嵌 CoS 常驻运行).
|
|
4
4
|
*
|
|
5
|
-
* The interface
|
|
6
|
-
*
|
|
7
|
-
* keep a single call seam and swap between ccl-sdk (domestic-model customers)
|
|
8
|
-
* and the Anthropic Agent SDK (Claude customers).
|
|
5
|
+
* The interface exposes query(), a canUseTool callback, and session resume
|
|
6
|
+
* so hosts can keep a shared calling interface across compatible runtimes.
|
|
9
7
|
*
|
|
10
8
|
* Wire contract: these types mirror the stream-json control protocol that
|
|
11
9
|
* cli/print.ts + cli/structuredIO.ts already speak. The SDK is the HOST side
|
package/docs/background-runs.md
CHANGED
|
@@ -93,6 +93,24 @@ await background.cancelRun({ runId, expectedRevision, actionId: 'cancel-1' })
|
|
|
93
93
|
|
|
94
94
|
`ccl daemon submit|get|events|cancel-run|approve-run --request-stdin --cwd PROJECT` 从 stdin 接收 JSON。submit 可启动缺失的兼容 daemon;读取不会启动进程。旧活 owner 配置不匹配时明确拒绝,不暗中替换。daemon stop 停调度;取消某一 run 使用 cancel-run。
|
|
95
95
|
|
|
96
|
+
### 安装升级与已有定时任务
|
|
97
|
+
|
|
98
|
+
安装新包不会重启正在运行的 daemon。`ccl daemon status --cwd PROJECT`、`scheduledStatus` 和 `CronList` 的 background 结果包含:
|
|
99
|
+
|
|
100
|
+
- `runningCliDigest`:通过活 owner 协议核实的启动时 CLI SHA-256;旧 owner 未保存该字段或没有核实到活 owner 时为 `null`。
|
|
101
|
+
- `installedCliDigest`:执行这次查询的 CLI 文件 SHA-256;读取失败时为 `null`。嵌入 service 的调用者可显式传比较路径。
|
|
102
|
+
- `cliCompatibility`:`match`、`mismatch` 或 `unknown`,另有 `cliCompatibilityReason` 解释不同或未知的原因。
|
|
103
|
+
|
|
104
|
+
`owner.ready` 仍表示已获得调度租约,不等于版本一致或任务已完成。摘要一致只表示 CLI 字节一致,不证明启动配置一致。旧 owner 的 `configId` 不能反推其 CLI 摘要;升级覆盖同一路径后也不能从新文件推断旧进程版本。`CronCreate` 的后台 handoff 结果也带相同的摘要字段。
|
|
105
|
+
|
|
106
|
+
产品启动或巡检可只读查询并提示用户。需要切换时,保留任务 ID、原启动配置及 occurrence 状态,由用户决定时机;明确执行 `ccl daemon stop --cwd PROJECT`,确认旧 owner 已退出、租约已释放,再从原宿主以相同配置对原 taskId 重试 `CronCreate operation:handoff`。采用 CLI start 时也要保留原宿主对应的配置;无条件裸 start 可能使用不同模型/设置,导致下一次 handoff 仍拒绝。不要删除重建排程,也不要循环重试不同配置或自动杀进程。stop 超时先查原 owner 状态,不能把超时当成已停止。
|
|
107
|
+
|
|
108
|
+
已接受的 occurrence 独立于排程定义:删除定义只影响未来触发,旧 occurrence 仍可按原 ID 查询、按明确决定取消;取消不会撤销已经发生的外部效果。新 owner 保留 waiting_permission,running/resuming 的不确定执行按 interrupted 处理,不自动重放。错过时点仍按原 missed/coalesce 规则处理,不意味着所有错过任务都自动补跑。
|
|
109
|
+
|
|
110
|
+
恢复审批必须同时存在原 session 的 confirmed pending 与精确匹配的 suspended 事件。`pendingPermission` 缺失时,新 owner 尝试恢复;失败会保留 `approvalRecoveryError`,不能编造 request/tool ID 批准。alpha.4 的原生 pending 没有新版 confirmed 挂起协议,因此不能承诺它能直接恢复,也不能补写 confirmed 绕过检查。由获授权的项目宿主先查询原 occurrence、核实已有外部效果,再按用户决定保留或使用 `cancel-occurrence`(snapshot.revision + 稳定 actionId)取消;不会自动取消或重新执行整项工作。
|
|
111
|
+
|
|
112
|
+
未显式绑定时,通知仍按原 `delegation.sourceSessionId` 投递。新会话可以使用下面的独立换绑接口;没有 delegation 或已删定义的旧 occurrence 也能绑定。`reauthorize` 只更新未来触发的权限委托,不改变既有 occurrence 或显式通知绑定。
|
|
113
|
+
|
|
96
114
|
| 目的 | SDK | CLI 子命令 | `BackgroundRun` 模型工具 action |
|
|
97
115
|
| --- | --- | --- | --- |
|
|
98
116
|
| 持久接受 | `submitRun` | `submit` | `submit` |
|
|
@@ -217,11 +235,37 @@ CLI 使用 `ccl daemon <子命令> --request-stdin --cwd PROJECT`,stdin 中为
|
|
|
217
235
|
|
|
218
236
|
只读查询不启动 owner,也不消费通知;决定和取消需要兼容的运行 owner。旧 `daemon approve <id> allow` 无精确身份,返回迁移错误。模型工具用 `BackgroundRun` 的 `occurrence_id` 配合 `get/events/approve/cancel`;批准字段为 `expected_revision/request_id/tool_use_id/action_id/decision`,事件使用 `after_sequence`,不用 run 的 opaque `cursor`。模型收到宿主通知不等于用户授权,allow 仍遵循前台权限确认或明确适用策略。
|
|
219
237
|
|
|
238
|
+
### 新会话接收原任务通知
|
|
239
|
+
|
|
240
|
+
换绑只改变通知收件人,不启动 owner,不删除重建任务,也不改变计划、执行状态、worker session、权限或待批身份。CLI/SDK 是受信本机宿主接口,可指定目标 session;模型工具请求确认,并由宿主填入当前 session,模型不能指定其他会话。
|
|
241
|
+
|
|
242
|
+
- 整项排程:在新会话用 `CronList` 读取原任务的 `notificationBinding.revision`,调用 `CronCreate`,输入 `operation: "rebind-notifications"`、原 `taskId`、`bindingRevision` 和稳定 `actionId`。首次 revision 为 0。此入口要求定义仍存在;一次性任务触发后定义可能已移除。
|
|
243
|
+
- 单次发生:使用 `BackgroundRun action:"notification-binding", occurrence_id:原ID` 读取该 occurrence 的绑定 revision,再用 `action:"rebind-notifications"`、相同 `occurrence_id`、`binding_revision`、稳定 `action_id` 换绑。它适用于定义已删或没有 delegation 的旧记录。
|
|
244
|
+
- SDK/CLI 整项选择器为 `{taskId, taskCreatedAt}`;它匹配已有记录和未来触发,防止同 ID 重建任务串收件人。定义已删时可从原 occurrence 的 task 快照取得身份。单次选择器为 `{occurrenceId}`。两种选择器不能混用。
|
|
245
|
+
|
|
246
|
+
```js
|
|
247
|
+
const selector = { occurrenceId: originalOccurrenceId }
|
|
248
|
+
const binding = await background.getScheduledNotificationBinding(selector)
|
|
249
|
+
const request = {
|
|
250
|
+
selector, targetSessionId: newSessionId,
|
|
251
|
+
expectedRevision: binding.revision, actionId: stableActionId,
|
|
252
|
+
}
|
|
253
|
+
const receipt = await background.rebindScheduledNotifications(request)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
对应 CLI 为 `ccl daemon get-scheduled-notification-binding --request-stdin --cwd PROJECT`,stdin 内容 `{ "selector": { "occurrenceId": "原64位ID" } }`;写接口为 `rebind-scheduled-notifications`,另加 `targetSessionId`、`expectedRevision`、`actionId`。读取不创建绑定。确认回执不确定时重试原请求;同一 actionId 同一内容返回原回执,不再次换绑。复用 actionId 改内容报 `action_conflict`;新动作遇到 `stale_binding` 时先读现状,再由宿主决定是否发起新的修改。
|
|
257
|
+
|
|
258
|
+
有效路由优先级是单次 occurrence 显式绑定、task 身份绑定、原 delegation。换绑整项任务不会覆盖单次显式选择。lookup 的 revision 只属于所选绑定,不能把 `effective.binding.revision` 当成另一选择器的 revision。`CronList.background` 和 `daemon status` 显示 task 的绑定 revision、收件 session,以及 occurrence 的有效 route;路由文件损坏时报告 `notificationRoutingError`,不会回退投递给原收件人,owner readiness 和 CLI 摘要仍可查询。修复路由存储前先保留原文件并核实目标,不用删文件来隐式恢复旧路由。
|
|
259
|
+
|
|
260
|
+
显式换绑后只补发最新可通知状态,不回放过期审批历史。稳定通知 UUID 包含绑定代次和当前待批身份/终态;coalesce 或 delivery 更新不重复同一待办,新的 pending 或终态会通知。A→B→A 使用新代次,旧 A 回执不会吞掉新通知。只有实际持久 transcript 消息才算接收回执,入队、get/events 或缓存本身都不算。
|
|
261
|
+
|
|
262
|
+
换绑对尚未被消费者 prepare 接受的通知生效:旧队列项在消费前复核路由和当前状态,不匹配则丢弃重取。已经接受或持久保存的旧通知无法撤回,因此不承诺两个会话在换绑瞬间零重叠。收到通知不授予审批权,批准仍须查询原 occurrence 并使用精确 pending 身份。旧格式无法恢复 pending 时,通知报告恢复错误,不生成虚构批准。
|
|
263
|
+
|
|
220
264
|
### 前端体验与故障恢复
|
|
221
265
|
|
|
222
|
-
- TUI 与持续运行的 SDK/headless
|
|
266
|
+
- TUI 与持续运行的 SDK/headless 主循环:有效绑定会话收到 `scheduled-task` 宿主事件,主助手解释具体待批工具、当前结果或失败。此事件不冒充新的用户指令。SDK 的自主通知结果不绑定到上一条用户输入的 turn UUID。
|
|
223
267
|
- 已退出的一次性 headless:不承诺向已关闭的输出流推送。消费者可通过上述 SDK/CLI 查询和处理结构化 pending;恢复原会话时补收未投递消息。Pepper 等 assistant 负责自己的外部消息渠道及送达回执。
|
|
224
|
-
- 接收者离线、入队失败或入队后尚未写入 transcript:保留通知游标,补投稳定 UUID
|
|
268
|
+
- 接收者离线、入队失败或入队后尚未写入 transcript:保留通知游标,补投稳定 UUID。只有接收会话持久保存的通知消息才算宿主接收回执;get/events 和队列操作记录都不算。已保存不代表模型已解释或 IM 已送达。
|
|
225
269
|
- 同一待批调用跨周期只提示一次,查询及实际消费时显示最新合并次数。投递前、队列消费前重查状态,已经批准、拒绝、取消或结束的旧审批不再提问;历史事件仍可读。状态读取失败不会冒充“已解决”。
|
|
226
270
|
- 等待批准时 owner 重启:保留经确认尚未执行的原调用,可在明确批准后恢复原 session。恢复严格核对工具与完整输入,不因同名工具就套用旧批准。
|
|
227
271
|
- 决定和恢复 intent 已保存后崩溃:重启标记 `interrupted`,不自动再执行。先核查原收据、工具结果及适用的 Operation 恢复契约;宿主不保证任意外部系统 exactly-once。
|
package/docs/ccl-duo-agent.md
CHANGED
|
@@ -133,6 +133,6 @@ WS_NO_BUFFER_UTIL=1 ~/.local/bin/ccl --ide
|
|
|
133
133
|
|
|
134
134
|
前提是 IDE 已安装兼容扩展、打开同一项目,并与 CCL 使用同一配置目录。完整步骤、默认连接失败记录和连接范围见 [CCL 在 VS Code 中的使用说明](ccl-ide-usage.md)。此临时参数没有修复产品默认行为,也不涉及 Gateway 升级。
|
|
135
135
|
|
|
136
|
-
`/ide` 接通编辑器能力,聊天仍在 CCL
|
|
136
|
+
`/ide` 接通编辑器能力,聊天仍在 CCL 终端。通过其它扩展的聊天面板运行 CCL,以及迁移当前 Duo 会话,均尚未验证。专用 Duo 面板、tmux 中的完整版 RLL 和 SDK 多用户服务另行处理。
|
|
137
137
|
|
|
138
138
|
普通 `/buddy` 先创建或复用 Team,再按返回的实际团队名启动 Agent;`/buddy --peer-review` 仍需固定审核模型和开发目标。两条 Buddy 路径与 Duo 的完成条件不同,详见[轻量开发审查说明](peer-development-review.md)。
|
|
@@ -229,9 +229,9 @@ CCL 将响应读取中断与用户取消区分处理。半截响应尚未执行
|
|
|
229
229
|
恢复诊断包含网关 request ID、底层连接错误及恢复阶段。连续中断会停止自动恢复并返回失败,
|
|
230
230
|
不会无限重试,也不声称修复了 VPN 或网关自身的连接问题。
|
|
231
231
|
|
|
232
|
-
#
|
|
232
|
+
# 记忆提取未完成的诊断日志
|
|
233
233
|
|
|
234
|
-
|
|
234
|
+
从 `1.5.1-alpha.5` 起,后台记忆提取的失败、恢复和退出等待超时只进入现有调试日志,不再写入普通会话消息或默认 CLI/SDK stderr。可通过 `--debug-file <文件>` 保存诊断;用户显式选择 `--debug-to-stderr` 时仍遵循该日志设置。日志是否启用和保留由现有设置决定,不新增默认采集。
|
|
235
235
|
|
|
236
236
|
`Memory extraction did not complete (...); saving is not confirmed` 表示本次提取没有满足完整结束和工具结果确认条件,不能据此宣称这些输入已全部保存。括号里的原因来自实际分支,例如:
|
|
237
237
|
|
|
@@ -241,8 +241,10 @@ CCL 将响应读取中断与用户取消区分处理。半截响应尚未执行
|
|
|
241
241
|
- `output_limit` / `response_not_finished`:最终响应达到输出限制,或没有完整结束。
|
|
242
242
|
- `system_blocked` / `interrupted` / `runtime_error`:系统阻断、取消中断,或提取处理抛出异常。后者没有足够信息细分时不猜测是网络或权限问题。
|
|
243
243
|
|
|
244
|
-
|
|
244
|
+
同一失败期间的固定摘要不重复记录相同原因,出现新的失败类别会追加摘要,已有详细错误日志和原因事件继续保留。下一次符合提取条件的正常回合可重试原输入;这不是退出后必定重试的承诺。日志中的 `Memory extraction checks have resumed` 只说明检查恢复,不说明历史所有信息都已保存;有已确认写入时的成功保存通知保持原行为。
|
|
245
245
|
|
|
246
|
-
|
|
246
|
+
固定摘要和原因事件不附加任意模型/工具正文、路径或异常文本;现有本地调试日志仍可能包含详细错误,不能把整份日志默认当成可对外公开的材料。静默展示不改变失败判定、未确认输入游标、权限或重试条件,也不提高预算、新增全记忆扫描,或使宿主记忆成为可靠业务账本。
|
|
247
|
+
|
|
248
|
+
正在运行的旧进程不会因安装更新而自动换用新代码;需要正常退出后重新启动。旧会话中已保存的提示也不会被删除,新版本恢复历史时仍可能显示原有记录。
|
|
247
249
|
|
|
248
250
|
旧 `Memory lookup is incomplete...` 属于已移除的自动发现路径,与这里的提取提示不同。看到旧文本时应区分历史记录重绘与旧进程的新消息,核对实际安装和运行版本,不能靠新源码中没有这句话就判定运行中的进程已更新。
|
|
@@ -74,7 +74,7 @@ Start `node dist/cli.js`, then use:
|
|
|
74
74
|
| `/gateway status` | Verify saved account; show membership and credit balance |
|
|
75
75
|
| `/gateway logout` | Remove the saved account locally |
|
|
76
76
|
| `/gateway doctor` | Diagnose gateway configuration and environment overrides |
|
|
77
|
-
| `/login` |
|
|
77
|
+
| `/login` | Margay website login/registration, the same flow as `/gateway login` |
|
|
78
78
|
|
|
79
79
|
At the first-launch account step, Enter starts website login; S or Esc defers
|
|
80
80
|
setup. During TUI login, Esc cancels. After an error, Enter or R retries.
|
|
@@ -227,7 +227,7 @@ before repeating work that may have side effects. SDK hosts can opt into
|
|
|
227
227
|
## Troubleshooting
|
|
228
228
|
|
|
229
229
|
In the source candidate, headless runs with `CI=1` can authenticate using an
|
|
230
|
-
admitted gateway configuration alone. A separate
|
|
230
|
+
admitted gateway configuration alone. A separate direct API key is not
|
|
231
231
|
required for that route. Missing or rejected gateway credentials still require
|
|
232
232
|
a valid login or another supported credential source. This fixes a startup
|
|
233
233
|
failure present in rc.9; it does not change the gateway's 401 handling.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# 1.5.1-alpha.4
|
|
2
|
+
|
|
3
|
+
本预发布版在 [1.5.1-alpha.3](1.5.1-alpha.3.md) 基础上交付 #60 的 daemon 升级状态和独立通知换绑。安装指定版本或使用 `alpha` 标签;`latest` 保持不变。CLI 与 SDK 应使用同版本。
|
|
4
|
+
|
|
5
|
+
## 升级状态与旧记录
|
|
6
|
+
|
|
7
|
+
`daemon status`、`CronList.background` 和 `CronCreate` 的后台返回包含运行/安装 CLI 摘要及 `cliCompatibility: match | mismatch | unknown`。旧 owner 没有启动摘要时明确 unknown;不会把升级后同路径的新文件当成旧进程版本。`owner.ready` 与版本一致性分开。
|
|
8
|
+
|
|
9
|
+
安装不会重启现有 daemon。需要切换时保留原任务身份和启动配置,明确 stop 并确认旧 owner 退出,再从原宿主对原 taskId handoff;不要删除重建排程。stop 导致活动 SDK aborted 时保存 interrupted,重启不自动重放;等待审批记录保留,错过周期按既有 missed/coalesce 契约处理。
|
|
10
|
+
|
|
11
|
+
恢复审批仍要求原 session 的 confirmed pending 和精确请求身份。旧 alpha.4 原生 pending 没有该确认协议时,保留恢复错误,不伪造批准或自动重跑;可查询原 occurrence,并在明确授权下取消。删除定义不删除已接受记录,取消不撤销已发生的外部效果。
|
|
12
|
+
|
|
13
|
+
## 新会话通知换绑
|
|
14
|
+
|
|
15
|
+
SDK `getScheduledNotificationBinding` / `rebindScheduledNotifications` 与同名 kebab-case CLI 子命令支持原 `{taskId, taskCreatedAt}` 或 `{occurrenceId}` 选择器。换绑含 `targetSessionId`、`expectedRevision`(首次 0)、稳定 `actionId`;同动作重试返回原回执,冲突和损坏明确报错。
|
|
16
|
+
|
|
17
|
+
模型工具使用 `CronCreate operation:rebind-notifications` 或 `BackgroundRun action:notification-binding/rebind-notifications`;经过权限确认,收件人固定为宿主当前会话。换绑不启动 owner,不改任务、计划、执行、权限或待批身份。单 occurrence 显式绑定优先于 task,最后才使用原 delegation。已删定义的 occurrence 仍可换绑。
|
|
18
|
+
|
|
19
|
+
REPL 和持续 headless 会话使用共同通知实现。新绑定只投当前待办/结果,以持久 transcript 为回执;代次隔离支持 A→B→A,合并周期不重复同一待办。消费前复核会丢弃旧路由队列项,已经接受的旧通知无法撤回,不承诺换绑瞬间零重叠。通知不是审批,仍需查询原 occurrence 后针对精确 pending 决定。
|
|
20
|
+
|
|
21
|
+
## 验证与兼容边界
|
|
22
|
+
|
|
23
|
+
隔离测试覆盖真实旧 alpha.4 产物切换、现代 pending 原会话恢复、运行任务中止与 missed/coalesce,以及最终候选 CLI/SDK、真实 detached owner、两个持续会话、工具拒绝/允许换绑、真实 transcript 和原精确批准一次执行。确定性 provider 证明接线与生命周期,不证明真实模型自主规划质量;REPL 验证为实际 hook/队列消费,不是整屏视觉验收。
|
|
24
|
+
|
|
25
|
+
独立路由是新增可选存储,未绑定任务沿用原路由。旧运行版本不会理解新绑定,启用此功能后不应混用旧前台消费者或直接降级并期待新路由仍生效。包回退不能撤销已经接受的通知或业务效果,回退前需核实接收方与待执行记录。
|
|
26
|
+
|
|
27
|
+
完整升级顺序、CLI/SDK/工具字段、优先级及失败处理见 [后台任务契约](../background-runs.md) 与 [SDK API](../../sdk/API.md)。本版包含 alpha.3 的 #58/#59 修复,不宣称解决视觉模型准确性问题。
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# 1.5.1-alpha.5
|
|
2
|
+
|
|
3
|
+
本预发布版在 [1.5.1-alpha.4](1.5.1-alpha.4.md) 基础上交付 CCL 产品文案清理、并行 Skill 正文恢复,以及图片本地校验和读取说明修复。发布后可安装指定版本:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install -g @margay/ccl-core@1.5.1-alpha.5
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
使用 `alpha` 标签分发,`latest` 保持不变。SDK/桌面宿主需升级实际嵌入的 CLI 与 SDK 依赖;全局安装不会自动替换宿主内置版本。已运行的会话和 daemon 不会因安装自动重启。
|
|
10
|
+
|
|
11
|
+
## 产品文案与 tips
|
|
12
|
+
|
|
13
|
+
清理界面、帮助、提示和错误信息中的上游产品推广,替换为 CCL 用语及 12 条自定义 tips。实际使用中的模型名称、兼容协议/API 标识、用户内容及法律归属按其用途保留。更新不改写既有会话文本。
|
|
14
|
+
|
|
15
|
+
## 并行 Skill 正文恢复(#61)
|
|
16
|
+
|
|
17
|
+
恢复会话时,保留同一并行响应中已经持久化、且关联来源有效的 Skill 方法正文,避免只恢复“加载成功”的工具结果却漏掉正文。恢复逻辑检查来源和分支范围,不把普通工具返回或无关旁支提升为技能正文。
|
|
18
|
+
|
|
19
|
+
修复位于共享读取恢复链,适用于原生 resume/fork 消费者;宿主无需另建正文持久化器。不会改写历史、重新执行工具或重放权限,也无法恢复中断前从未持久化的内容。验证覆盖真实 writer 的不同落盘断点、并行交错、重复恢复、resume/fork 及真实模型对恢复规则的消费。
|
|
20
|
+
|
|
21
|
+
## 图片读取与视觉分工(#62,部分交付)
|
|
22
|
+
|
|
23
|
+
Read 对支持的图片格式执行本地元数据与像素解码校验;损坏或不支持的输入在本地明确失败。成功结果保留图片内容,并附本地读取回执。读取成功不代表网关已把原图交给模型,也不代表当前主模型能够理解图片。
|
|
24
|
+
|
|
25
|
+
移除 Read 说明中无条件宣称主模型具有视觉能力的表述,协调 `visual-ui-analysis` 的适用说明。专员成功路径不要求先出现图片错误,也不要求先将 PNG 转为 JPEG。既有网关诊断继续区分本地读取、模型/路由与适配失败;HTTP 200 不能单独作为视觉成功证据。
|
|
26
|
+
|
|
27
|
+
验证包含真实直接附件视觉请求、专员路径与专员不可用场景,以及 CLI/SDK 的拒绝、空结果和诊断传播。先前真实模型错误归因的失败记录保留,后续成功不证明所有模型都稳定遵循只读要求或不会绕路。
|
|
28
|
+
|
|
29
|
+
所选模型/部署的版本化视觉能力声明,以及 CCL 的能力接收、模型或路由变化后的刷新,仍待 [网关 #28](https://github.com/YW1975/margay-gateway/issues/28) 契约落地和接入。本版不宣称整体 #62 已解决;能力未知时不按模型名猜测支持情况,也不自动替换用户主模型。
|
|
30
|
+
|
|
31
|
+
## 兼容与回退
|
|
32
|
+
|
|
33
|
+
后台记忆提取的失败、恢复和退出等待超时改为现有调试日志,不再显示普通会话警告或写入默认 CLI/SDK stderr;可用 `--debug-file <文件>` 查看原因,显式 `--debug-to-stderr` 仍按用户设置输出。失败输入继续保留供后续符合条件的回合重试,不将未确认保存改判为成功;有确认写入时的成功保存通知保持。旧进程需正常退出后重启,历史已有提示不改写。
|
|
34
|
+
|
|
35
|
+
本版未改变依赖声明、历史记录格式或权限契约。升级后从原宿主继续使用原会话;安装检查不等于宿主已完成升级。需要回退时可安装此前使用的确切版本,回退不会撤销已经发生的业务操作,旧版本也不包含本次恢复与图片说明修复。
|
|
@@ -17,7 +17,7 @@ The spool is `analytics-spool-v1.json` in the same private config directory as t
|
|
|
17
17
|
|
|
18
18
|
Only an exact authenticated durable-acceptance ACK deletes sent records. Lost ACKs preserve event ID/time/body across restart. Retry delay persists and caps at five minutes; permanent schema/auth rejections are counted and removed. Status reports pending count and expired/overflow/identity/disabled/rejected drops. The session loop sends on startup and every ten seconds, with a three-second request budget and up to one second of shutdown waiting. Full-batch immediate dispatch will be connected with the feature lifecycle registry; it is not present yet. Concurrent CLI processes share the lock, and the gateway deduplicates concurrent/replayed event IDs.
|
|
19
19
|
|
|
20
|
-
Legacy GrowthBook/Datadog/1P and other legacy background traffic remain suppressed by `CCL_DISABLE_LEGACY_NONESSENTIAL_TRAFFIC`. The CLI no longer overwrites the user's explicit NONESSENTIAL setting. `isClientTelemetryDisabled` checks the original user privacy signals; the old privacy helpers continue suppressing old routes. Optional
|
|
20
|
+
Legacy GrowthBook/Datadog/1P and other legacy background traffic remain suppressed by `CCL_DISABLE_LEGACY_NONESSENTIAL_TRAFFIC`. The CLI no longer overwrites the user's explicit NONESSENTIAL setting. `isClientTelemetryDisabled` checks the original user privacy signals; the old privacy helpers continue suppressing old routes. Optional direct API preconnect and upstream registry fetch now honor that boundary as well.
|
|
21
21
|
|
|
22
22
|
## Querying analytics
|
|
23
23
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@margay/ccl-core",
|
|
3
|
-
"version": "1.5.1-alpha.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.5.1-alpha.5",
|
|
4
|
+
"description": "CCL agent runtime for Margay integration",
|
|
5
5
|
"license": "SEE LICENSE IN README.md",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -55,7 +55,9 @@
|
|
|
55
55
|
"docs/releases/1.5.1-alpha.md",
|
|
56
56
|
"docs/releases/1.5.1-alpha.1.md",
|
|
57
57
|
"docs/releases/1.5.1-alpha.2.md",
|
|
58
|
-
"docs/releases/1.5.1-alpha.3.md"
|
|
58
|
+
"docs/releases/1.5.1-alpha.3.md",
|
|
59
|
+
"docs/releases/1.5.1-alpha.4.md",
|
|
60
|
+
"docs/releases/1.5.1-alpha.5.md"
|
|
59
61
|
],
|
|
60
62
|
"engines": {
|
|
61
63
|
"node": ">=22.19.0"
|
package/sdk/API.md
CHANGED
|
@@ -336,7 +336,7 @@ for await (const event of result) { /* 消费实际结果 */ }
|
|
|
336
336
|
## 7. Provider 配置(双引擎)
|
|
337
337
|
|
|
338
338
|
```ts
|
|
339
|
-
//
|
|
339
|
+
// Messages API 端点(直连服务或兼容网关)
|
|
340
340
|
provider: { type: 'anthropic', baseUrl?: string, apiKey?: string }
|
|
341
341
|
// → 映射 --base-url / --api-key
|
|
342
342
|
|
|
@@ -347,7 +347,7 @@ provider: { type: 'openai-compatible', baseUrl: string, apiKey?: string }
|
|
|
347
347
|
|
|
348
348
|
- `openai-compatible` 的 `baseUrl` 指向 **CCL/margay 网关**(litellm 类,前置 OpenAI 兼容上游);网关负责 tool-calling 归一化,对不支持原生 function calling 的模型**显式报错**而非静默劣化。
|
|
349
349
|
- 省略 `provider` 时继承 CLI 自身配置(`~/.ccl/gateway.json` 等)。
|
|
350
|
-
- margay 双引擎互换:同一调用 seam 下,ccl-sdk
|
|
350
|
+
- margay 双引擎互换:同一调用 seam 下,ccl-sdk 与兼容 Agent SDK 的 `query()`/`canUseTool`/resume 形状对齐,切换引擎不改业务代码结构。
|
|
351
351
|
|
|
352
352
|
---
|
|
353
353
|
|
|
@@ -475,7 +475,7 @@ for await (const ev of query('写一段', { includePartialMessages: true })) {
|
|
|
475
475
|
}
|
|
476
476
|
}
|
|
477
477
|
```
|
|
478
|
-
- 默认关。开后收 `{ type:'stream_event', event }`(
|
|
478
|
+
- 默认关。开后收 `{ type:'stream_event', event }`(原始 Messages API 事件:content_block_delta/text_delta 等);整块 `assistant_text` 仍并存。
|
|
479
479
|
|
|
480
480
|
### 13.3 结构化输出 jsonSchema(G4)
|
|
481
481
|
```ts
|
|
@@ -732,3 +732,10 @@ Increasing output allowance can increase cost and does not establish visual
|
|
|
732
732
|
accuracy. Verify page observations separately; a complete response alone is not
|
|
733
733
|
business acceptance. These variables require a build containing this feature;
|
|
734
734
|
the previously published alpha.2 does not support them.
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
## Scheduled notification bindings
|
|
738
|
+
|
|
739
|
+
`createBackgroundClient()` 提供 `getScheduledNotificationBinding(selector)` 与 `rebindScheduledNotifications(request)`,用于新会话接收原定时任务通知。选择器为 `{ taskId, taskCreatedAt }` 或 `{ occurrenceId }`;请求包含 `selector`、`targetSessionId`、`expectedRevision`(初始 0)和稳定 `actionId`。返回绑定含 `sessionId/revision/generation/updatedAt`。读取 occurrence 绑定还返回 `effective` 路由;显式 occurrence 优先于 task,task 优先于原 delegation。
|
|
740
|
+
|
|
741
|
+
换绑不启动 owner、不改变原任务或审批状态。超时重试原 actionId 和原请求;同 ID 改内容拒绝,revision 冲突须读取当前状态后决定新动作。模型工具固定绑定到自己的宿主 session,并请求权限确认。已被消费者接受的旧通知不会撤回;新代次只通知当前待办或结果,不重放过期历史。完整 CLI、工具字段、错误和恢复说明见 [新会话接收原任务通知](../docs/background-runs.md#新会话接收原任务通知)。
|
package/sdk/README.md
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Programmatic, headless, no-TTY entry to a CCL agent session, for hosts like
|
|
4
4
|
margay that need a resident (7×24) agent brain with code-level tool
|
|
5
|
-
interception.
|
|
6
|
-
|
|
7
|
-
and swap engines.
|
|
5
|
+
interception. It exposes `query()`, `canUseTool`, and session resume for
|
|
6
|
+
streaming responses, host-controlled tool permissions, and continuing sessions.
|
|
8
7
|
|
|
9
8
|
## Usage
|
|
10
9
|
|
|
@@ -116,8 +115,7 @@ The SDK is the **host side** of the stream-json control protocol that
|
|
|
116
115
|
CLI as a **managed subprocess** (`--print --input-format stream-json
|
|
117
116
|
--output-format stream-json`, all-pipe stdio, no TTY), which keeps every CLI
|
|
118
117
|
behavior — tools, skills, hooks, session persistence, gateway/model routing —
|
|
119
|
-
|
|
120
|
-
SDK wraps Claude Code.
|
|
118
|
+
consistent between CLI and SDK use.
|
|
121
119
|
|
|
122
120
|
Permission flow (`canUseTool` set ⇒ `--permission-prompt-tool stdio`):
|
|
123
121
|
|
|
@@ -143,7 +141,7 @@ session continues). Wire schemas live in
|
|
|
143
141
|
| P0-2 fail-closed (throw / timeout / unrecognized ⇒ deny, tool never runs) | **done**, unit-tested |
|
|
144
142
|
| P0-2 `pending` + suspend + cross-process resume | **done** — see mechanism below; `resumeWithDecision(sessionId, {behavior})` |
|
|
145
143
|
| P0-3 session persistence + `resume(session_id)` | **done** — transcripts via the CLI's store (`--session-id`/`--resume`); SDK-level state (pending approvals, usage) via the pluggable `SessionStore` (file reference impl; Redis/DB implement the same 6-method interface) |
|
|
146
|
-
| P0-4 provider layer (
|
|
144
|
+
| P0-4 provider layer (Messages API + OpenAI-compatible) | **done at the SDK seam** — `provider: {type:'anthropic'}` → `--base-url`/`--api-key`; `{type:'openai-compatible'}` → CCL gateway channel (`CCL_GATEWAY_URL`/`KEY`), which normalizes tool-calling and rejects non-function-calling models explicitly. Mapping unit-tested; live two-provider round-trip belongs to the DoD slice (CoS side provides mock endpoints per the issue). |
|
|
147
145
|
| P1-5 explicit `skills_dirs` | **done** — each dir is wrapped as an ephemeral plugin (skills symlink) and loaded via `--plugin-dir`, the CLI's cwd-independent skill channel; missing dirs fail loudly |
|
|
148
146
|
| P1-6 hooks (`on_tool_use`/`on_turn_end`/`on_session_end`) | **done** — observability-only contract: hook errors are swallowed, never affect control flow |
|
|
149
147
|
| P1-7 usage in `result` event + per-session accumulation | **done** — provider-raw `usage` + `total_cost_usd` on every result; accumulated per session in the store, queryable via `getSessionUsage(sessionId)` |
|
|
@@ -199,7 +197,7 @@ that mode's available set; an explicit incompatible selection such as
|
|
|
199
197
|
still apply; `--allowedTools` does not add tools to the available set.
|
|
200
198
|
|
|
201
199
|
Use `extraArgs: ['--thinking', 'disabled']` to explicitly disable thinking on
|
|
202
|
-
|
|
200
|
+
Messages API compatible routes. Omitting the option retains the route's
|
|
203
201
|
default. The selection persists across requests; a query handle's
|
|
204
202
|
`setMaxThinkingTokens(0)` explicitly disables it, and `null` restores the default.
|
|
205
203
|
# Persistent sessions and streamed input
|