@clawos-dev/clawd 0.2.738 → 0.2.740
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/{dispatch → a2a}/mcp-server.cjs +326 -1033
- package/dist/app-builder-plugin/mcp-server.cjs +174 -108
- package/dist/cli.cjs +2188 -2127
- package/dist/cloud-persona-conversations.html +74 -74
- package/dist/cloud-persona-metrics.html +1 -1
- package/dist/cloud-persona-schedules.html +1 -1
- package/dist/owner-ui/assets/{owner-DqXBCm9I.js → owner-BEzWnKsm.js} +220 -220
- package/dist/owner-ui/assets/owner-DkZN0eik.css +32 -0
- package/dist/owner-ui/owner.html +2 -2
- package/dist/persona-defaults/persona-app-builder/CLAUDE.md +2 -2
- package/dist/persona-defaults/persona-app-builder/mcp/clawd-app-builder/mcp-server.cjs +174 -108
- package/dist/persona-defaults/persona-clawd-butler/.claude/skills/clawd-orchestration/SKILL.md +5 -7
- package/dist/persona-defaults/persona-clawd-butler/.claude/skills/clawd-product/SKILL.md +49 -8
- package/dist/persona-defaults/persona-clawd-butler/CLAUDE.md +2 -2
- package/dist/persona-defaults/persona-dataclaw-builder/mcp/clawd-app-builder/mcp-server.cjs +174 -108
- package/dist/persona-defaults/persona-master/CLAUDE.md +16 -17
- package/dist/pi-mcp-bridge/extension.cjs +6 -1
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/guest-DagqEvdb.css +32 -0
- package/dist/share-ui/assets/{guest-Cbaz1yVH.js → guest-fGrEob6x.js} +143 -143
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/owner-ui/assets/owner-z9zJkPHQ.css +0 -32
- package/dist/share-ui/assets/guest-DAdPVo1T.css +0 -32
|
@@ -3227,8 +3227,8 @@ var require_utils = __commonJS({
|
|
|
3227
3227
|
}
|
|
3228
3228
|
return ind;
|
|
3229
3229
|
}
|
|
3230
|
-
function removeDotSegments(
|
|
3231
|
-
let input =
|
|
3230
|
+
function removeDotSegments(path) {
|
|
3231
|
+
let input = path;
|
|
3232
3232
|
const output = [];
|
|
3233
3233
|
let nextSlash = -1;
|
|
3234
3234
|
let len = 0;
|
|
@@ -3480,8 +3480,8 @@ var require_schemes = __commonJS({
|
|
|
3480
3480
|
wsComponent.secure = void 0;
|
|
3481
3481
|
}
|
|
3482
3482
|
if (wsComponent.resourceName) {
|
|
3483
|
-
const [
|
|
3484
|
-
wsComponent.path =
|
|
3483
|
+
const [path, query] = wsComponent.resourceName.split("?");
|
|
3484
|
+
wsComponent.path = path && path !== "/" ? path : void 0;
|
|
3485
3485
|
wsComponent.query = query;
|
|
3486
3486
|
wsComponent.resourceName = void 0;
|
|
3487
3487
|
}
|
|
@@ -4313,7 +4313,7 @@ var require_core = __commonJS({
|
|
|
4313
4313
|
errorsText(errors = this.errors, { separator = ", ", dataVar = "data" } = {}) {
|
|
4314
4314
|
if (!errors || errors.length === 0)
|
|
4315
4315
|
return "No errors";
|
|
4316
|
-
return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((
|
|
4316
|
+
return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text2, msg) => text2 + separator + msg);
|
|
4317
4317
|
}
|
|
4318
4318
|
$dataMetaSchema(metaSchema, keywordsJsonPointers) {
|
|
4319
4319
|
const rules = this.RULES.all;
|
|
@@ -6874,12 +6874,12 @@ var require_dist = __commonJS({
|
|
|
6874
6874
|
throw new Error(`Unknown format "${name}"`);
|
|
6875
6875
|
return f;
|
|
6876
6876
|
};
|
|
6877
|
-
function addFormats(ajv, list,
|
|
6877
|
+
function addFormats(ajv, list, fs2, exportName) {
|
|
6878
6878
|
var _a;
|
|
6879
6879
|
var _b;
|
|
6880
6880
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
6881
6881
|
for (const f of list)
|
|
6882
|
-
ajv.addFormat(f,
|
|
6882
|
+
ajv.addFormat(f, fs2[f]);
|
|
6883
6883
|
}
|
|
6884
6884
|
module2.exports = exports2 = formatsPlugin;
|
|
6885
6885
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -6887,15 +6887,14 @@ var require_dist = __commonJS({
|
|
|
6887
6887
|
}
|
|
6888
6888
|
});
|
|
6889
6889
|
|
|
6890
|
-
// src/
|
|
6890
|
+
// src/a2a/mcp-server.ts
|
|
6891
6891
|
var mcp_server_exports = {};
|
|
6892
6892
|
__export(mcp_server_exports, {
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
handlePersonaDispatchToolCall: () => handlePersonaDispatchToolCall
|
|
6893
|
+
handleAsync: () => handleAsync,
|
|
6894
|
+
handleWait: () => handleWait
|
|
6896
6895
|
});
|
|
6897
6896
|
module.exports = __toCommonJS(mcp_server_exports);
|
|
6898
|
-
var
|
|
6897
|
+
var import_node_fs = __toESM(require("fs"), 1);
|
|
6899
6898
|
|
|
6900
6899
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
|
|
6901
6900
|
var external_exports = {};
|
|
@@ -7375,8 +7374,8 @@ function getErrorMap() {
|
|
|
7375
7374
|
|
|
7376
7375
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
7377
7376
|
var makeIssue = (params) => {
|
|
7378
|
-
const { data, path
|
|
7379
|
-
const fullPath = [...
|
|
7377
|
+
const { data, path, errorMaps, issueData } = params;
|
|
7378
|
+
const fullPath = [...path, ...issueData.path || []];
|
|
7380
7379
|
const fullIssue = {
|
|
7381
7380
|
...issueData,
|
|
7382
7381
|
path: fullPath
|
|
@@ -7492,11 +7491,11 @@ var errorUtil;
|
|
|
7492
7491
|
|
|
7493
7492
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
7494
7493
|
var ParseInputLazyPath = class {
|
|
7495
|
-
constructor(parent, value,
|
|
7494
|
+
constructor(parent, value, path, key) {
|
|
7496
7495
|
this._cachedPath = [];
|
|
7497
7496
|
this.parent = parent;
|
|
7498
7497
|
this.data = value;
|
|
7499
|
-
this._path =
|
|
7498
|
+
this._path = path;
|
|
7500
7499
|
this._key = key;
|
|
7501
7500
|
}
|
|
7502
7501
|
get path() {
|
|
@@ -10744,7 +10743,7 @@ var ZodPipeline = class _ZodPipeline extends ZodType {
|
|
|
10744
10743
|
_parse(input) {
|
|
10745
10744
|
const { status, ctx } = this._processInputParams(input);
|
|
10746
10745
|
if (ctx.common.async) {
|
|
10747
|
-
const
|
|
10746
|
+
const handleAsync2 = async () => {
|
|
10748
10747
|
const inResult = await this._def.in._parseAsync({
|
|
10749
10748
|
data: ctx.data,
|
|
10750
10749
|
path: ctx.path,
|
|
@@ -10763,7 +10762,7 @@ var ZodPipeline = class _ZodPipeline extends ZodType {
|
|
|
10763
10762
|
});
|
|
10764
10763
|
}
|
|
10765
10764
|
};
|
|
10766
|
-
return
|
|
10765
|
+
return handleAsync2();
|
|
10767
10766
|
} else {
|
|
10768
10767
|
const inResult = this._def.in._parseSync({
|
|
10769
10768
|
data: ctx.data,
|
|
@@ -11133,10 +11132,10 @@ function assignProp(target, prop, value) {
|
|
|
11133
11132
|
configurable: true
|
|
11134
11133
|
});
|
|
11135
11134
|
}
|
|
11136
|
-
function getElementAtPath(obj,
|
|
11137
|
-
if (!
|
|
11135
|
+
function getElementAtPath(obj, path) {
|
|
11136
|
+
if (!path)
|
|
11138
11137
|
return obj;
|
|
11139
|
-
return
|
|
11138
|
+
return path.reduce((acc, key) => acc?.[key], obj);
|
|
11140
11139
|
}
|
|
11141
11140
|
function promiseAllObject(promisesObj) {
|
|
11142
11141
|
const keys = Object.keys(promisesObj);
|
|
@@ -11456,11 +11455,11 @@ function aborted(x, startIndex = 0) {
|
|
|
11456
11455
|
}
|
|
11457
11456
|
return false;
|
|
11458
11457
|
}
|
|
11459
|
-
function prefixIssues(
|
|
11458
|
+
function prefixIssues(path, issues) {
|
|
11460
11459
|
return issues.map((iss) => {
|
|
11461
11460
|
var _a;
|
|
11462
11461
|
(_a = iss).path ?? (_a.path = []);
|
|
11463
|
-
iss.path.unshift(
|
|
11462
|
+
iss.path.unshift(path);
|
|
11464
11463
|
return iss;
|
|
11465
11464
|
});
|
|
11466
11465
|
}
|
|
@@ -21109,11 +21108,6 @@ var StdioServerTransport = class {
|
|
|
21109
21108
|
}
|
|
21110
21109
|
};
|
|
21111
21110
|
|
|
21112
|
-
// src/tools/claude.ts
|
|
21113
|
-
var import_node_child_process2 = require("child_process");
|
|
21114
|
-
var import_node_child_process3 = require("child_process");
|
|
21115
|
-
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
21116
|
-
|
|
21117
21111
|
// ../protocol/src/cloud-workspace-schemas.ts
|
|
21118
21112
|
var WORKSPACE_COMPARISON_VALUES = ["head", "index"];
|
|
21119
21113
|
var Id = external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9-]{0,127}$/);
|
|
@@ -22260,98 +22254,108 @@ var ContactPinnedFrameSchema = external_exports.object({
|
|
|
22260
22254
|
pinnedAt: external_exports.number().int().nullable()
|
|
22261
22255
|
}).strict();
|
|
22262
22256
|
|
|
22263
|
-
// ../protocol/src/
|
|
22264
|
-
var
|
|
22265
|
-
|
|
22266
|
-
|
|
22267
|
-
|
|
22268
|
-
|
|
22269
|
-
|
|
22257
|
+
// ../protocol/src/a2a.ts
|
|
22258
|
+
var A2A_MAX_CALLS = 8;
|
|
22259
|
+
var A2A_WAIT_MAX_MS = 2 * 60 * 6e4;
|
|
22260
|
+
var A2A_WAIT_DEFAULT_MS = 30 * 6e4;
|
|
22261
|
+
var A2A_STATES = ["submitted", "working", "input_required", "completed", "failed", "canceled", "rejected"];
|
|
22262
|
+
var A2aStateSchema = external_exports.enum(A2A_STATES);
|
|
22263
|
+
var A2A_TERMINAL_STATES = ["completed", "failed", "canceled", "rejected"];
|
|
22264
|
+
var A2A_DELIVERABLE_STATES = ["input_required", ...A2A_TERMINAL_STATES];
|
|
22265
|
+
var TENANT_DEVICE = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
22266
|
+
var TENANT_PERSONA = /^[a-z0-9-]{1,128}$/;
|
|
22267
|
+
function parseA2aTarget(target) {
|
|
22268
|
+
if (target.startsWith("cloud:")) {
|
|
22269
|
+
const id = target.slice("cloud:".length);
|
|
22270
|
+
return TENANT_PERSONA.test(id) ? { kind: "cloud", personaId: id } : null;
|
|
22271
|
+
}
|
|
22272
|
+
const at = target.indexOf("@");
|
|
22273
|
+
if (at < 0) return TENANT_PERSONA.test(target) ? { kind: "here", personaId: target } : null;
|
|
22274
|
+
const personaId2 = target.slice(0, at);
|
|
22275
|
+
const deviceId = target.slice(at + 1);
|
|
22276
|
+
return TENANT_PERSONA.test(personaId2) && TENANT_DEVICE.test(deviceId) ? { kind: "device", personaId: personaId2, deviceId } : null;
|
|
22277
|
+
}
|
|
22278
|
+
var A2aCallSchema = external_exports.object({
|
|
22279
|
+
target: external_exports.string().refine((v) => parseA2aTarget(v) !== null, {
|
|
22280
|
+
message: "target must be <personaId>, <personaId>@<deviceId> or cloud:<personaId>"
|
|
22270
22281
|
}),
|
|
22271
|
-
external_exports.
|
|
22272
|
-
kind: external_exports.literal("failure"),
|
|
22273
|
-
reason: external_exports.string(),
|
|
22274
|
-
brief: external_exports.string().optional()
|
|
22275
|
-
})
|
|
22276
|
-
]);
|
|
22277
|
-
var DispatchRunArgsSchema = external_exports.object({
|
|
22278
|
-
targetPersona: external_exports.string().min(1).optional(),
|
|
22279
|
-
// 续派(spec 2026-07-21,单 dispatchId 语义:一件事一行一 id):非空 = 把 prompt
|
|
22280
|
-
// 作为新 turn 打进该 dispatch 的原 worker session 接着干(台账行复位 running)。
|
|
22281
|
-
// 省略 = 新开一件事,daemon 铸新 id。
|
|
22282
|
-
dispatchId: external_exports.string().min(1).optional(),
|
|
22283
|
-
prompt: external_exports.string(),
|
|
22282
|
+
text: external_exports.string().min(1),
|
|
22284
22283
|
brief: external_exports.string().optional(),
|
|
22285
|
-
|
|
22286
|
-
|
|
22287
|
-
|
|
22288
|
-
// Model values depend on the selected engine and are validated against its runtime catalog. Overrides apply only to new dispatches.
|
|
22284
|
+
contextId: external_exports.string().min(1).optional(),
|
|
22285
|
+
taskId: external_exports.string().min(1).optional(),
|
|
22286
|
+
sessionLabel: external_exports.string().min(1).max(60).optional(),
|
|
22289
22287
|
model: external_exports.string().min(1).optional(),
|
|
22290
|
-
|
|
22288
|
+
/** 一次性换 worker 的引擎;只对本人设备上的本机目标有效,执行方领活时校验 */
|
|
22291
22289
|
tool: external_exports.string().min(1).optional(),
|
|
22292
|
-
|
|
22293
|
-
sessionLabel: external_exports.string().min(1).max(60).optional(),
|
|
22294
|
-
// 上层消费者(Master)挂载话题/线语义:topicId / lineId / 验收标准 / rejectCount 等。
|
|
22295
|
-
// daemon **不解释**内容,只透传进台账行 DispatchRecord.meta(新开)或与既有 meta
|
|
22296
|
-
// merge(续派,见 handlers/persona-dispatch.ts)。与台账行 meta 同款自由 JSON 契约。
|
|
22290
|
+
/** 线的自由字段(topicId / lineId / acceptance …),中心与 daemon 都不解释,原样进台账 */
|
|
22297
22291
|
meta: external_exports.record(external_exports.unknown()).optional()
|
|
22298
|
-
}).refine((v) => v.
|
|
22299
|
-
message: "
|
|
22300
|
-
}).refine((v) => !(v.dispatchId !== void 0 && v.targetDeviceId !== void 0), {
|
|
22301
|
-
message: "follow-ups take only dispatchId; the target device comes from the ledger row (dispatchId + targetDeviceId are mutually exclusive)"
|
|
22302
|
-
}).refine((v) => !(v.tool !== void 0 && v.targetDeviceId !== void 0), {
|
|
22303
|
-
message: "engine override is not supported for cross-device dispatch (tool + targetDeviceId are mutually exclusive)"
|
|
22304
|
-
}).refine((v) => !(v.dispatchId !== void 0 && (v.tool !== void 0 || v.model !== void 0)), {
|
|
22305
|
-
message: "a follow-up dispatch cannot change engine or model (dispatchId excludes tool / model); start a new dispatch instead"
|
|
22306
|
-
});
|
|
22307
|
-
var DispatchCompleteArgsSchema = external_exports.object({
|
|
22308
|
-
dispatchId: external_exports.string().min(1),
|
|
22309
|
-
outcome: DispatchOutcomeSchema
|
|
22310
|
-
});
|
|
22311
|
-
var DISPATCH_STATUSES = ["running", "completed", "failed"];
|
|
22312
|
-
var DispatchStatusSchema = external_exports.enum(DISPATCH_STATUSES);
|
|
22313
|
-
var DispatchRecordSchema = external_exports.object({
|
|
22314
|
-
dispatchId: external_exports.string().min(1),
|
|
22315
|
-
sourceSessionId: external_exports.string().min(1),
|
|
22316
|
-
sourcePersonaId: external_exports.string().min(1).optional(),
|
|
22317
|
-
targetPersonaId: external_exports.string().min(1),
|
|
22318
|
-
/** A-side target device attribution; absence means local for existing records. Forwarding strips it from the B-side local ledger. */
|
|
22319
|
-
targetDeviceId: external_exports.string().min(1).optional(),
|
|
22320
|
-
/** A-side cross-device rows: the B-side ledger id, used for follow-ups and for resuming polls after an A restart. */
|
|
22321
|
-
remoteDispatchId: external_exports.string().min(1).optional(),
|
|
22322
|
-
/** The A-side round B last accepted; a follow-up reopened but not yet accepted has remoteRound < round, so a restart must not resume polling it. */
|
|
22323
|
-
remoteRound: external_exports.number().int().positive().optional(),
|
|
22324
|
-
/** B 的 sessionId;registerBSession 后回填 */
|
|
22325
|
-
workerSessionId: external_exports.string().min(1).optional(),
|
|
22326
|
-
taskText: external_exports.string(),
|
|
22327
|
-
/** Explicit task summary for list/cards instead of truncated taskText; outcome owns the result summary. */
|
|
22328
|
-
taskBrief: external_exports.string().optional(),
|
|
22329
|
-
/** One ledger row across follow-up rounds. Missing on old rows is consumed as round one. */
|
|
22330
|
-
round: external_exports.number().int().positive().optional(),
|
|
22331
|
-
status: DispatchStatusSchema,
|
|
22332
|
-
outcome: DispatchOutcomeSchema.optional(),
|
|
22333
|
-
meta: external_exports.record(external_exports.unknown()).optional(),
|
|
22334
|
-
createdAt: external_exports.string().min(1),
|
|
22335
|
-
completedAt: external_exports.string().min(1).optional(),
|
|
22336
|
-
/** 结果注入 source session 成功时戳,兼当投递 dedup 标记 */
|
|
22337
|
-
deliveredAt: external_exports.string().min(1).optional()
|
|
22292
|
+
}).refine((v) => !(v.contextId && v.taskId), { message: "contextId (new round) and taskId (answer) are mutually exclusive" }).refine((v) => !((v.contextId || v.taskId) && (v.model || v.tool)), {
|
|
22293
|
+
message: "a follow-up cannot change engine or model (contextId / taskId exclude model / tool); start a new line instead"
|
|
22338
22294
|
});
|
|
22339
|
-
var
|
|
22340
|
-
|
|
22341
|
-
|
|
22342
|
-
relatedSessionId: external_exports.string().min(1).optional()
|
|
22343
|
-
});
|
|
22344
|
-
var DispatchListResultSchema = external_exports.object({
|
|
22345
|
-
records: external_exports.array(DispatchRecordSchema)
|
|
22295
|
+
var A2aSendArgsSchema = external_exports.object({
|
|
22296
|
+
calls: external_exports.array(A2aCallSchema).min(1).max(A2A_MAX_CALLS),
|
|
22297
|
+
sessionId: external_exports.string().min(1).optional()
|
|
22346
22298
|
});
|
|
22347
|
-
var
|
|
22348
|
-
|
|
22299
|
+
var A2A_AWAIT_SLICE_MAX_MS = 6e4;
|
|
22300
|
+
var A2aAwaitArgsSchema = external_exports.object({
|
|
22301
|
+
taskIds: external_exports.array(external_exports.string().min(1)).min(1).max(A2A_MAX_CALLS),
|
|
22302
|
+
timeoutMs: external_exports.number().int().min(0).max(A2A_AWAIT_SLICE_MAX_MS)
|
|
22303
|
+
});
|
|
22304
|
+
var A2aAnswerArgsSchema = external_exports.object({ taskId: external_exports.string().min(1), text: external_exports.string().trim().min(1) });
|
|
22305
|
+
var A2aTaskIdArgsSchema = external_exports.object({ taskId: external_exports.string().min(1) });
|
|
22306
|
+
var A2aListArgsSchema = external_exports.object({
|
|
22307
|
+
contextId: external_exports.string().min(1).optional(),
|
|
22308
|
+
state: A2aStateSchema.optional(),
|
|
22309
|
+
/** 发起会话(Master 按自己的会话列线);agent 调用时 MCP 用调用者会话填 */
|
|
22310
|
+
sessionId: external_exports.string().min(1).optional(),
|
|
22311
|
+
/** UI:这个会话是发起方或 worker 的任务 */
|
|
22312
|
+
relatedSessionId: external_exports.string().min(1).optional()
|
|
22349
22313
|
});
|
|
22350
|
-
var
|
|
22351
|
-
|
|
22352
|
-
|
|
22353
|
-
|
|
22314
|
+
var A2aReportArgsSchema = external_exports.object({
|
|
22315
|
+
contextId: external_exports.string().min(1),
|
|
22316
|
+
state: external_exports.enum(["completed", "failed", "input_required"]),
|
|
22317
|
+
text: external_exports.string(),
|
|
22318
|
+
brief: external_exports.string().optional(),
|
|
22319
|
+
filePaths: external_exports.array(external_exports.string().min(1)).optional()
|
|
22320
|
+
});
|
|
22321
|
+
var A2aTaskViewSchema = external_exports.object({
|
|
22322
|
+
taskId: external_exports.string().min(1),
|
|
22323
|
+
contextId: external_exports.string().min(1),
|
|
22324
|
+
round: external_exports.number().int().positive(),
|
|
22325
|
+
state: A2aStateSchema,
|
|
22326
|
+
/** 本机执行方失联(租约过期但不判失败) */
|
|
22327
|
+
stale: external_exports.boolean(),
|
|
22328
|
+
/** 系统原因:no_executor / executor_lost / executor_restarted / not_authorized … */
|
|
22329
|
+
reason: external_exports.string().nullable(),
|
|
22330
|
+
depth: external_exports.number().int().min(0),
|
|
22331
|
+
tenant: external_exports.string(),
|
|
22332
|
+
targetPersonaId: external_exports.string(),
|
|
22333
|
+
targetDeviceId: external_exports.string().nullable(),
|
|
22334
|
+
initiator: external_exports.object({ host: external_exports.string(), personaId: external_exports.string(), sessionRef: external_exports.string().nullable() }),
|
|
22335
|
+
executorSessionRef: external_exports.string().nullable(),
|
|
22336
|
+
executorThreadId: external_exports.string().nullable(),
|
|
22337
|
+
/** 这条线在本机的 worker 会话:本机执行的,或发起方 daemon 挂出的云 worker 会话;本机没有就缺省 */
|
|
22338
|
+
workerSessionId: external_exports.string().optional(),
|
|
22339
|
+
/** 任务正文(首条 user 消息) */
|
|
22340
|
+
taskText: external_exports.string(),
|
|
22341
|
+
/** worker 的一句话摘要(statusMessage.brief) */
|
|
22342
|
+
brief: external_exports.string().nullable(),
|
|
22343
|
+
/** worker 最后一条回报正文 */
|
|
22344
|
+
resultText: external_exports.string().nullable(),
|
|
22345
|
+
filePaths: external_exports.array(external_exports.string()),
|
|
22346
|
+
line: external_exports.record(external_exports.unknown()),
|
|
22347
|
+
deliveredAt: external_exports.string().nullable(),
|
|
22348
|
+
createdAt: external_exports.string(),
|
|
22349
|
+
updatedAt: external_exports.string(),
|
|
22350
|
+
finishedAt: external_exports.string().nullable()
|
|
22354
22351
|
});
|
|
22352
|
+
var A2aCallResultSchema = external_exports.discriminatedUnion("ok", [
|
|
22353
|
+
external_exports.object({ ok: external_exports.literal(true), task: A2aTaskViewSchema }),
|
|
22354
|
+
external_exports.object({ ok: external_exports.literal(false), error: external_exports.object({ code: external_exports.string(), message: external_exports.string() }) })
|
|
22355
|
+
]);
|
|
22356
|
+
var A2aSendResultSchema = external_exports.object({ results: external_exports.array(A2aCallResultSchema) });
|
|
22357
|
+
var A2aListResultSchema = external_exports.object({ tasks: external_exports.array(A2aTaskViewSchema) });
|
|
22358
|
+
var A2aAwaitResultSchema = external_exports.object({ tasks: external_exports.array(A2aTaskViewSchema), done: external_exports.boolean() });
|
|
22355
22359
|
|
|
22356
22360
|
// ../protocol/src/extension.ts
|
|
22357
22361
|
var EXT_ID_REGEX = /^[a-z0-9][a-z0-9-]*$/;
|
|
@@ -22730,11 +22734,14 @@ var TopicSchema = external_exports.object({
|
|
|
22730
22734
|
});
|
|
22731
22735
|
var TopicLineViewSchema = external_exports.object({
|
|
22732
22736
|
lineId: external_exports.string().min(1),
|
|
22733
|
-
|
|
22737
|
+
/** 这条线(A2A context);打回在同一 context 下开新任务 */
|
|
22738
|
+
contextId: external_exports.string().min(1),
|
|
22739
|
+
/** 最新一轮的任务 */
|
|
22740
|
+
taskId: external_exports.string().min(1),
|
|
22734
22741
|
workerSessionId: external_exports.string().optional(),
|
|
22735
22742
|
assignee: external_exports.string().min(1),
|
|
22736
22743
|
focus: external_exports.string(),
|
|
22737
|
-
status:
|
|
22744
|
+
status: A2aStateSchema,
|
|
22738
22745
|
acceptance: external_exports.array(external_exports.string()),
|
|
22739
22746
|
rejectCount: external_exports.number().int().min(0),
|
|
22740
22747
|
accepted: external_exports.boolean(),
|
|
@@ -22965,6 +22972,37 @@ var OnboardingIosInterestResultSchema = external_exports.object({
|
|
|
22965
22972
|
registered: external_exports.boolean()
|
|
22966
22973
|
});
|
|
22967
22974
|
|
|
22975
|
+
// ../protocol/src/faq-schemas.ts
|
|
22976
|
+
var FaqEvidenceSchema = external_exports.object({
|
|
22977
|
+
kind: external_exports.enum(["rpc", "file"]),
|
|
22978
|
+
/** RPC 方法名,或 `path:line` */
|
|
22979
|
+
ref: external_exports.string().min(1).max(300)
|
|
22980
|
+
});
|
|
22981
|
+
var FaqReportArgs = external_exports.object({
|
|
22982
|
+
/** 管家归纳成一句话的问题,不贴用户原话 */
|
|
22983
|
+
question: external_exports.string().min(1).max(500),
|
|
22984
|
+
status: external_exports.enum(["unanswered", "answered_unverified"]),
|
|
22985
|
+
/** answered_unverified 必填:给用户的答案 */
|
|
22986
|
+
answer: external_exports.string().max(4e3).optional(),
|
|
22987
|
+
/** answered_unverified 必填 */
|
|
22988
|
+
resolvedBy: external_exports.enum(["rpc", "source"]).optional(),
|
|
22989
|
+
/** answered_unverified 至少一项 */
|
|
22990
|
+
evidence: external_exports.array(FaqEvidenceSchema).max(20).optional(),
|
|
22991
|
+
/** 管家先看过的托管文档路径 */
|
|
22992
|
+
docsChecked: external_exports.array(external_exports.string().max(200)).max(20).optional(),
|
|
22993
|
+
/** unanswered 必填 */
|
|
22994
|
+
unansweredReason: external_exports.enum(["no_source_access", "user_declined", "not_found"]).optional()
|
|
22995
|
+
}).superRefine((v, ctx) => {
|
|
22996
|
+
if (v.status === "answered_unverified") {
|
|
22997
|
+
if (!v.answer) ctx.addIssue({ code: "custom", path: ["answer"], message: "answered_unverified \u9700\u8981 answer" });
|
|
22998
|
+
if (!v.resolvedBy) ctx.addIssue({ code: "custom", path: ["resolvedBy"], message: "answered_unverified \u9700\u8981 resolvedBy" });
|
|
22999
|
+
if (!v.evidence?.length) ctx.addIssue({ code: "custom", path: ["evidence"], message: "answered_unverified \u9700\u8981\u81F3\u5C11\u4E00\u9879 evidence" });
|
|
23000
|
+
} else if (!v.unansweredReason) {
|
|
23001
|
+
ctx.addIssue({ code: "custom", path: ["unansweredReason"], message: "unanswered \u9700\u8981 unansweredReason" });
|
|
23002
|
+
}
|
|
23003
|
+
});
|
|
23004
|
+
var FaqReportResultSchema = external_exports.object({ id: external_exports.string() });
|
|
23005
|
+
|
|
22968
23006
|
// ../protocol/src/engine-schemas.ts
|
|
22969
23007
|
var EngineStatusArgs = external_exports.object({
|
|
22970
23008
|
tool: external_exports.enum(PROBE_TOOL_IDS)
|
|
@@ -23065,11 +23103,14 @@ var HISTORY_USER_META_VALUES = [
|
|
|
23065
23103
|
"meta-text",
|
|
23066
23104
|
"attachment-skills",
|
|
23067
23105
|
"attachment-deferred-tools",
|
|
23068
|
-
// persona
|
|
23069
|
-
//
|
|
23070
|
-
//
|
|
23071
|
-
//
|
|
23072
|
-
//
|
|
23106
|
+
// persona 间调用来源分型(信封契约见 a2a-format.ts):
|
|
23107
|
+
// a2a-task 派给 worker 的任务包(首发 + 打回,打回靠信封 round 属性区分,不单开分型)
|
|
23108
|
+
// a2a-result 结果投回发起方 session 的结果包
|
|
23109
|
+
// dispatch-* 旧版信封,只在旧历史里出现,照同样语义展示
|
|
23110
|
+
// 这几类跟其它 meta 的关键差别:**它们是一轮真实交互**,参与 turn 切分与分页计数
|
|
23111
|
+
// (见 isA2aUserMeta 的消费点),不是 CC 内部注入的辅助消息。
|
|
23112
|
+
"a2a-task",
|
|
23113
|
+
"a2a-result",
|
|
23073
23114
|
"dispatch-task",
|
|
23074
23115
|
"dispatch-result"
|
|
23075
23116
|
];
|
|
@@ -23246,6 +23287,8 @@ var SessionFileSchema = external_exports.object({
|
|
|
23246
23287
|
originOwnerPersonaId: external_exports.string().min(1).optional(),
|
|
23247
23288
|
/** Dispatch source session for local tree grouping. Strip on mirrors because remote session ids cannot link into the local tree. */
|
|
23248
23289
|
dispatchedFromSessionId: external_exports.string().min(1).optional(),
|
|
23290
|
+
/** A2A line (contextId) this worker session serves; the spawn env carries it as CLAWD_A2A_CONTEXT_ID so a2aReport finds the current round. Strip on mirrors. */
|
|
23291
|
+
a2aContextId: external_exports.string().min(1).optional(),
|
|
23249
23292
|
/** Scheduler source session, distinct from dispatch/fork ancestry. Strip on mirrors because this linkage is local-only. */
|
|
23250
23293
|
shiftFiredFromSessionId: external_exports.string().min(1).optional(),
|
|
23251
23294
|
/** Bot session key, potentially virtual topic/speaker or document key, not necessarily a real IM chat id. UI hides these sessions from ordinary recent-session lists. */
|
|
@@ -24326,6 +24369,15 @@ var METHOD_DOCS = {
|
|
|
24326
24369
|
summary: "\u767B\u8BB0 owner \u60F3\u8981 iOS TestFlight\uFF1Adaemon \u8F6C\u53D1\u4E2D\u5FC3 API\uFF08\u643A\u5E26 unionId/\u98DE\u4E66\u540D\uFF09\uFF0Cserver \u843D\u8868\u53BB\u91CD\u5E76\u7528\u5B98\u65B9 bot \u901A\u77E5 David \u8D70\u98DE\u4E66\u8054\u7CFB\uFF1B\u9700\u98DE\u4E66\u5DF2\u767B\u5F55\uFF08FEISHU_GATED\uFF09",
|
|
24327
24370
|
args: OnboardingIosInterestArgs
|
|
24328
24371
|
},
|
|
24372
|
+
"faq:report": {
|
|
24373
|
+
summary: "\u7BA1\u5BB6\u4E0A\u62A5\u7B54\u4E0D\u4E0A\u6765 / \u6CA1\u7ECF\u6587\u6863\u6838\u5BF9\u7684\u95EE\u9898\uFF1Adaemon \u5148\u8131\u654F\uFF08\u4E3B\u76EE\u5F55\u8DEF\u5F84\u3001token \u5F62\u72B6\u7684\u4E32\uFF09\uFF0C\u518D\u5E26\u767B\u5F55\u7968\u8F6C\u53D1\u4E2D\u5FC3 faq_inbox\uFF1B\u5931\u8D25\u7531\u8C03\u7528\u65B9\u9759\u9ED8\u5FFD\u7565\uFF1B\u9700\u98DE\u4E66\u5DF2\u767B\u5F55\uFF08FEISHU_GATED\uFF09",
|
|
24374
|
+
args: FaqReportArgs,
|
|
24375
|
+
argsConstraints: {
|
|
24376
|
+
if: { properties: { status: { const: "answered_unverified" } } },
|
|
24377
|
+
then: { required: ["answer", "resolvedBy", "evidence"], properties: { evidence: { minItems: 1 } } },
|
|
24378
|
+
else: { required: ["unansweredReason"] }
|
|
24379
|
+
}
|
|
24380
|
+
},
|
|
24329
24381
|
"skills:list": {
|
|
24330
24382
|
summary: "\u626B\u63CF\u5E76\u5217\u51FA\u8BE5\u76EE\u5F55\u53EF\u7528\u7684 skill",
|
|
24331
24383
|
args: SkillsListArgs
|
|
@@ -24399,25 +24451,33 @@ var METHOD_DOCS = {
|
|
|
24399
24451
|
summary: "\u5220 persona\u3002owner-only",
|
|
24400
24452
|
args: PersonaIdArgsSchema
|
|
24401
24453
|
},
|
|
24402
|
-
"
|
|
24403
|
-
summary: "\
|
|
24404
|
-
args:
|
|
24405
|
-
|
|
24406
|
-
|
|
24407
|
-
|
|
24408
|
-
|
|
24454
|
+
"a2a:send": {
|
|
24455
|
+
summary: "\u6D3E\u6D3B\u7ED9\u53E6\u4E00\u4E2A persona\uFF08\u672C\u673A / \u8054\u7CFB\u4EBA\u8BBE\u5907 / \u4E91\u4E0A\uFF09\uFF0C\u4E00\u6B21 1 \u5230 8 \u4E2A call\uFF0C\u6BCF\u4E2A call \u5355\u72EC\u6210\u8D25\uFF0C\u53D1\u51FA\u5373\u8FD4\u56DE\u4EFB\u52A1\u89C6\u56FE\u3002target \u5199\u6CD5\u540C @ token\uFF1A<personaId> / <personaId>@<deviceId> / cloud:<personaId>\uFF1B\u5E26 contextId = \u540C\u4E00\u6761\u7EBF\u65B0\u4E00\u8F6E\uFF08\u6253\u56DE\uFF09\uFF0C\u5E26 taskId = \u56DE\u7B54 input_required",
|
|
24456
|
+
args: A2aSendArgsSchema
|
|
24457
|
+
},
|
|
24458
|
+
"a2a:await": {
|
|
24459
|
+
summary: "\u7B49\u8FD9\u4E9B\u4EFB\u52A1\u5168\u90E8\u8FDB\u5165\u7EC8\u6001\u6216 input_required\uFF08\u5355\u6B21\u6700\u591A 60 \u79D2\uFF09\u3002done=true \u65F6 daemon \u5F53\u573A\u786E\u8BA4\u6295\u9012\uFF0C\u7ED3\u679C\u4E0D\u518D\u6CE8\u5165\u56DE\u4F1A\u8BDD\uFF1Bdone=false \u4EC0\u4E48\u90FD\u4E0D\u786E\u8BA4",
|
|
24460
|
+
args: A2aAwaitArgsSchema
|
|
24409
24461
|
},
|
|
24410
|
-
"
|
|
24411
|
-
summary:
|
|
24412
|
-
args:
|
|
24462
|
+
"a2a:answer": {
|
|
24463
|
+
summary: "\u56DE\u7B54\u4E00\u4E2A\u505C\u5728 input_required \u7684\u4EFB\u52A1\uFF08\u53D1\u8D77\u65B9\u672C\u4EBA\uFF09\uFF1A\u56DE\u7B54\u8FDB worker \u4F1A\u8BDD\uFF0Cworker \u63A5\u7740\u5E72\u3002\u4EFB\u52A1\u5DF2\u4E0D\u5728\u7B49\u56DE\u7B54\u65F6\u62A5\u9519",
|
|
24464
|
+
args: A2aAnswerArgsSchema
|
|
24413
24465
|
},
|
|
24414
|
-
"
|
|
24415
|
-
summary: "\u67E5
|
|
24416
|
-
args:
|
|
24466
|
+
"a2a:get": {
|
|
24467
|
+
summary: "\u67E5\u4E00\u4E2A A2A \u4EFB\u52A1\u7684\u72B6\u6001\u4E0E\u7ED3\u679C\uFF08\u53D1\u8D77\u65B9\u672C\u4EBA\uFF0C\u6216\u672C\u673A\u76EE\u6807\u8BBE\u5907\uFF09",
|
|
24468
|
+
args: A2aTaskIdArgsSchema
|
|
24417
24469
|
},
|
|
24418
|
-
"
|
|
24419
|
-
summary: "\
|
|
24420
|
-
args:
|
|
24470
|
+
"a2a:list": {
|
|
24471
|
+
summary: "\u5217 A2A \u4EFB\u52A1\uFF1A\u6309 contextId / state \u8FC7\u6EE4\uFF1BsessionId = \u8FD9\u4E2A\u4F1A\u8BDD\u53D1\u51FA\u7684\uFF1BrelatedSessionId = \u8FD9\u4E2A\u4F1A\u8BDD\u662F\u53D1\u8D77\u65B9\u6216 worker \u7684\uFF08UI \u7528\uFF09",
|
|
24472
|
+
args: A2aListArgsSchema
|
|
24473
|
+
},
|
|
24474
|
+
"a2a:cancel": {
|
|
24475
|
+
summary: "\u53D6\u6D88\u4E00\u4E2A\u8FD8\u6CA1\u7ED3\u675F\u7684 A2A \u4EFB\u52A1\uFF1Bworker \u4F1A\u88AB\u4E2D\u65AD",
|
|
24476
|
+
args: A2aTaskIdArgsSchema
|
|
24477
|
+
},
|
|
24478
|
+
"a2a:report": {
|
|
24479
|
+
summary: "worker \u56DE\u62A5\u8FD9\u4E00\u8F6E\u7684\u7ED3\u679C\uFF1Acompleted / failed / input_required\uFF08\u505C\u4E0B\u6765\u8981\u53D1\u8D77\u65B9\u56DE\u7B54\uFF09\u3002contextId \u7531\u5BBF\u4E3B\u6CE8\u5165\uFF0Cdaemon \u636E\u5B83\u627E\u5F53\u524D\u8FD9\u4E00\u8F6E",
|
|
24480
|
+
args: A2aReportArgsSchema
|
|
24421
24481
|
},
|
|
24422
24482
|
"peerExec:run": {
|
|
24423
24483
|
summary: "\u5728\u8054\u7CFB\u4EBA\u8BBE\u5907\u4E0A\u8DD1\u4E00\u6761 bash \u547D\u4EE4\uFF08\u4E00\u53D1\u4E00\u6536\uFF0C\u65E0\u8DE8\u547D\u4EE4\u4F1A\u8BDD\u72B6\u6001\uFF09\u3002**\u672C\u673A\u53D1\u8D77\u5FC5\u586B peerDeviceId**\u2014\u2014\u7701\u7565\u4EC5\u7528\u4E8E\u5BF9\u7AEF guest \u53CD\u5411\u5165\u53E3\uFF0Cowner ctx \u7701\u7565\u4F1A\u88AB\u62D2\uFF1B\u9700\u5BF9\u65B9\u5F00\u4E86 remoteAccess",
|
|
@@ -24723,955 +24783,188 @@ var WebSessionExchangeResultSchema = external_exports.object({
|
|
|
24723
24783
|
expiresAt: external_exports.number()
|
|
24724
24784
|
});
|
|
24725
24785
|
|
|
24726
|
-
// ../protocol/src/
|
|
24727
|
-
var INNER_TAG_NAMES = "clawd-dispatch-task|clawd-dispatch-result|brief|detail|files";
|
|
24786
|
+
// ../protocol/src/a2a-format.ts
|
|
24787
|
+
var INNER_TAG_NAMES = "clawd-a2a-task|clawd-a2a-result|clawd-dispatch-task|clawd-dispatch-result|brief|detail|files";
|
|
24728
24788
|
var INNER_TAG_ESCAPE_RE = new RegExp(`<(\\\\*)(/?)(${INNER_TAG_NAMES})\\b`, "g");
|
|
24729
24789
|
var INNER_TAG_UNESCAPE_RE = new RegExp(`<\\\\(\\\\*)(/?)(${INNER_TAG_NAMES})\\b`, "g");
|
|
24730
24790
|
|
|
24731
|
-
// src/
|
|
24732
|
-
var
|
|
24733
|
-
var import_node_fs = __toESM(require("fs"), 1);
|
|
24734
|
-
var import_node_os = __toESM(require("os"), 1);
|
|
24735
|
-
var import_node_path = __toESM(require("path"), 1);
|
|
24736
|
-
var import_node_util = require("util");
|
|
24737
|
-
var defaultExecFile = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
24738
|
-
|
|
24739
|
-
// src/tools/subscription-channels-apply.ts
|
|
24740
|
-
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
24741
|
-
var import_node_os2 = __toESM(require("os"), 1);
|
|
24742
|
-
var import_node_path2 = __toESM(require("path"), 1);
|
|
24743
|
-
|
|
24744
|
-
// src/tools/claude-history.ts
|
|
24745
|
-
var import_node_crypto = __toESM(require("crypto"), 1);
|
|
24746
|
-
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
24747
|
-
var import_node_os3 = __toESM(require("os"), 1);
|
|
24748
|
-
var import_node_path3 = __toESM(require("path"), 1);
|
|
24749
|
-
var import_node_string_decoder = require("string_decoder");
|
|
24750
|
-
|
|
24751
|
-
// ../node_modules/.pnpm/diff@7.0.0/node_modules/diff/lib/index.mjs
|
|
24752
|
-
function Diff() {
|
|
24753
|
-
}
|
|
24754
|
-
Diff.prototype = {
|
|
24755
|
-
diff: function diff(oldString, newString) {
|
|
24756
|
-
var _options$timeout;
|
|
24757
|
-
var options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
|
|
24758
|
-
var callback = options.callback;
|
|
24759
|
-
if (typeof options === "function") {
|
|
24760
|
-
callback = options;
|
|
24761
|
-
options = {};
|
|
24762
|
-
}
|
|
24763
|
-
var self = this;
|
|
24764
|
-
function done(value) {
|
|
24765
|
-
value = self.postProcess(value, options);
|
|
24766
|
-
if (callback) {
|
|
24767
|
-
setTimeout(function() {
|
|
24768
|
-
callback(value);
|
|
24769
|
-
}, 0);
|
|
24770
|
-
return true;
|
|
24771
|
-
} else {
|
|
24772
|
-
return value;
|
|
24773
|
-
}
|
|
24774
|
-
}
|
|
24775
|
-
oldString = this.castInput(oldString, options);
|
|
24776
|
-
newString = this.castInput(newString, options);
|
|
24777
|
-
oldString = this.removeEmpty(this.tokenize(oldString, options));
|
|
24778
|
-
newString = this.removeEmpty(this.tokenize(newString, options));
|
|
24779
|
-
var newLen = newString.length, oldLen = oldString.length;
|
|
24780
|
-
var editLength = 1;
|
|
24781
|
-
var maxEditLength = newLen + oldLen;
|
|
24782
|
-
if (options.maxEditLength != null) {
|
|
24783
|
-
maxEditLength = Math.min(maxEditLength, options.maxEditLength);
|
|
24784
|
-
}
|
|
24785
|
-
var maxExecutionTime = (_options$timeout = options.timeout) !== null && _options$timeout !== void 0 ? _options$timeout : Infinity;
|
|
24786
|
-
var abortAfterTimestamp = Date.now() + maxExecutionTime;
|
|
24787
|
-
var bestPath = [{
|
|
24788
|
-
oldPos: -1,
|
|
24789
|
-
lastComponent: void 0
|
|
24790
|
-
}];
|
|
24791
|
-
var newPos = this.extractCommon(bestPath[0], newString, oldString, 0, options);
|
|
24792
|
-
if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
24793
|
-
return done(buildValues(self, bestPath[0].lastComponent, newString, oldString, self.useLongestToken));
|
|
24794
|
-
}
|
|
24795
|
-
var minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
|
|
24796
|
-
function execEditLength() {
|
|
24797
|
-
for (var diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
|
|
24798
|
-
var basePath = void 0;
|
|
24799
|
-
var removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
|
|
24800
|
-
if (removePath) {
|
|
24801
|
-
bestPath[diagonalPath - 1] = void 0;
|
|
24802
|
-
}
|
|
24803
|
-
var canAdd = false;
|
|
24804
|
-
if (addPath) {
|
|
24805
|
-
var addPathNewPos = addPath.oldPos - diagonalPath;
|
|
24806
|
-
canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
|
|
24807
|
-
}
|
|
24808
|
-
var canRemove = removePath && removePath.oldPos + 1 < oldLen;
|
|
24809
|
-
if (!canAdd && !canRemove) {
|
|
24810
|
-
bestPath[diagonalPath] = void 0;
|
|
24811
|
-
continue;
|
|
24812
|
-
}
|
|
24813
|
-
if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
|
|
24814
|
-
basePath = self.addToPath(addPath, true, false, 0, options);
|
|
24815
|
-
} else {
|
|
24816
|
-
basePath = self.addToPath(removePath, false, true, 1, options);
|
|
24817
|
-
}
|
|
24818
|
-
newPos = self.extractCommon(basePath, newString, oldString, diagonalPath, options);
|
|
24819
|
-
if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
24820
|
-
return done(buildValues(self, basePath.lastComponent, newString, oldString, self.useLongestToken));
|
|
24821
|
-
} else {
|
|
24822
|
-
bestPath[diagonalPath] = basePath;
|
|
24823
|
-
if (basePath.oldPos + 1 >= oldLen) {
|
|
24824
|
-
maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
|
|
24825
|
-
}
|
|
24826
|
-
if (newPos + 1 >= newLen) {
|
|
24827
|
-
minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
|
|
24828
|
-
}
|
|
24829
|
-
}
|
|
24830
|
-
}
|
|
24831
|
-
editLength++;
|
|
24832
|
-
}
|
|
24833
|
-
if (callback) {
|
|
24834
|
-
(function exec() {
|
|
24835
|
-
setTimeout(function() {
|
|
24836
|
-
if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
|
|
24837
|
-
return callback();
|
|
24838
|
-
}
|
|
24839
|
-
if (!execEditLength()) {
|
|
24840
|
-
exec();
|
|
24841
|
-
}
|
|
24842
|
-
}, 0);
|
|
24843
|
-
})();
|
|
24844
|
-
} else {
|
|
24845
|
-
while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
|
|
24846
|
-
var ret = execEditLength();
|
|
24847
|
-
if (ret) {
|
|
24848
|
-
return ret;
|
|
24849
|
-
}
|
|
24850
|
-
}
|
|
24851
|
-
}
|
|
24852
|
-
},
|
|
24853
|
-
addToPath: function addToPath(path4, added, removed, oldPosInc, options) {
|
|
24854
|
-
var last = path4.lastComponent;
|
|
24855
|
-
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
24856
|
-
return {
|
|
24857
|
-
oldPos: path4.oldPos + oldPosInc,
|
|
24858
|
-
lastComponent: {
|
|
24859
|
-
count: last.count + 1,
|
|
24860
|
-
added,
|
|
24861
|
-
removed,
|
|
24862
|
-
previousComponent: last.previousComponent
|
|
24863
|
-
}
|
|
24864
|
-
};
|
|
24865
|
-
} else {
|
|
24866
|
-
return {
|
|
24867
|
-
oldPos: path4.oldPos + oldPosInc,
|
|
24868
|
-
lastComponent: {
|
|
24869
|
-
count: 1,
|
|
24870
|
-
added,
|
|
24871
|
-
removed,
|
|
24872
|
-
previousComponent: last
|
|
24873
|
-
}
|
|
24874
|
-
};
|
|
24875
|
-
}
|
|
24876
|
-
},
|
|
24877
|
-
extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath, options) {
|
|
24878
|
-
var newLen = newString.length, oldLen = oldString.length, oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
|
|
24879
|
-
while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldString[oldPos + 1], newString[newPos + 1], options)) {
|
|
24880
|
-
newPos++;
|
|
24881
|
-
oldPos++;
|
|
24882
|
-
commonCount++;
|
|
24883
|
-
if (options.oneChangePerToken) {
|
|
24884
|
-
basePath.lastComponent = {
|
|
24885
|
-
count: 1,
|
|
24886
|
-
previousComponent: basePath.lastComponent,
|
|
24887
|
-
added: false,
|
|
24888
|
-
removed: false
|
|
24889
|
-
};
|
|
24890
|
-
}
|
|
24891
|
-
}
|
|
24892
|
-
if (commonCount && !options.oneChangePerToken) {
|
|
24893
|
-
basePath.lastComponent = {
|
|
24894
|
-
count: commonCount,
|
|
24895
|
-
previousComponent: basePath.lastComponent,
|
|
24896
|
-
added: false,
|
|
24897
|
-
removed: false
|
|
24898
|
-
};
|
|
24899
|
-
}
|
|
24900
|
-
basePath.oldPos = oldPos;
|
|
24901
|
-
return newPos;
|
|
24902
|
-
},
|
|
24903
|
-
equals: function equals(left, right, options) {
|
|
24904
|
-
if (options.comparator) {
|
|
24905
|
-
return options.comparator(left, right);
|
|
24906
|
-
} else {
|
|
24907
|
-
return left === right || options.ignoreCase && left.toLowerCase() === right.toLowerCase();
|
|
24908
|
-
}
|
|
24909
|
-
},
|
|
24910
|
-
removeEmpty: function removeEmpty(array2) {
|
|
24911
|
-
var ret = [];
|
|
24912
|
-
for (var i = 0; i < array2.length; i++) {
|
|
24913
|
-
if (array2[i]) {
|
|
24914
|
-
ret.push(array2[i]);
|
|
24915
|
-
}
|
|
24916
|
-
}
|
|
24917
|
-
return ret;
|
|
24918
|
-
},
|
|
24919
|
-
castInput: function castInput(value) {
|
|
24920
|
-
return value;
|
|
24921
|
-
},
|
|
24922
|
-
tokenize: function tokenize(value) {
|
|
24923
|
-
return Array.from(value);
|
|
24924
|
-
},
|
|
24925
|
-
join: function join(chars) {
|
|
24926
|
-
return chars.join("");
|
|
24927
|
-
},
|
|
24928
|
-
postProcess: function postProcess(changeObjects) {
|
|
24929
|
-
return changeObjects;
|
|
24930
|
-
}
|
|
24931
|
-
};
|
|
24932
|
-
function buildValues(diff2, lastComponent, newString, oldString, useLongestToken) {
|
|
24933
|
-
var components = [];
|
|
24934
|
-
var nextComponent;
|
|
24935
|
-
while (lastComponent) {
|
|
24936
|
-
components.push(lastComponent);
|
|
24937
|
-
nextComponent = lastComponent.previousComponent;
|
|
24938
|
-
delete lastComponent.previousComponent;
|
|
24939
|
-
lastComponent = nextComponent;
|
|
24940
|
-
}
|
|
24941
|
-
components.reverse();
|
|
24942
|
-
var componentPos = 0, componentLen = components.length, newPos = 0, oldPos = 0;
|
|
24943
|
-
for (; componentPos < componentLen; componentPos++) {
|
|
24944
|
-
var component = components[componentPos];
|
|
24945
|
-
if (!component.removed) {
|
|
24946
|
-
if (!component.added && useLongestToken) {
|
|
24947
|
-
var value = newString.slice(newPos, newPos + component.count);
|
|
24948
|
-
value = value.map(function(value2, i) {
|
|
24949
|
-
var oldValue = oldString[oldPos + i];
|
|
24950
|
-
return oldValue.length > value2.length ? oldValue : value2;
|
|
24951
|
-
});
|
|
24952
|
-
component.value = diff2.join(value);
|
|
24953
|
-
} else {
|
|
24954
|
-
component.value = diff2.join(newString.slice(newPos, newPos + component.count));
|
|
24955
|
-
}
|
|
24956
|
-
newPos += component.count;
|
|
24957
|
-
if (!component.added) {
|
|
24958
|
-
oldPos += component.count;
|
|
24959
|
-
}
|
|
24960
|
-
} else {
|
|
24961
|
-
component.value = diff2.join(oldString.slice(oldPos, oldPos + component.count));
|
|
24962
|
-
oldPos += component.count;
|
|
24963
|
-
}
|
|
24964
|
-
}
|
|
24965
|
-
return components;
|
|
24966
|
-
}
|
|
24967
|
-
var characterDiff = new Diff();
|
|
24968
|
-
function longestCommonPrefix(str1, str2) {
|
|
24969
|
-
var i;
|
|
24970
|
-
for (i = 0; i < str1.length && i < str2.length; i++) {
|
|
24971
|
-
if (str1[i] != str2[i]) {
|
|
24972
|
-
return str1.slice(0, i);
|
|
24973
|
-
}
|
|
24974
|
-
}
|
|
24975
|
-
return str1.slice(0, i);
|
|
24976
|
-
}
|
|
24977
|
-
function longestCommonSuffix(str1, str2) {
|
|
24978
|
-
var i;
|
|
24979
|
-
if (!str1 || !str2 || str1[str1.length - 1] != str2[str2.length - 1]) {
|
|
24980
|
-
return "";
|
|
24981
|
-
}
|
|
24982
|
-
for (i = 0; i < str1.length && i < str2.length; i++) {
|
|
24983
|
-
if (str1[str1.length - (i + 1)] != str2[str2.length - (i + 1)]) {
|
|
24984
|
-
return str1.slice(-i);
|
|
24985
|
-
}
|
|
24986
|
-
}
|
|
24987
|
-
return str1.slice(-i);
|
|
24988
|
-
}
|
|
24989
|
-
function replacePrefix(string3, oldPrefix, newPrefix) {
|
|
24990
|
-
if (string3.slice(0, oldPrefix.length) != oldPrefix) {
|
|
24991
|
-
throw Error("string ".concat(JSON.stringify(string3), " doesn't start with prefix ").concat(JSON.stringify(oldPrefix), "; this is a bug"));
|
|
24992
|
-
}
|
|
24993
|
-
return newPrefix + string3.slice(oldPrefix.length);
|
|
24994
|
-
}
|
|
24995
|
-
function replaceSuffix(string3, oldSuffix, newSuffix) {
|
|
24996
|
-
if (!oldSuffix) {
|
|
24997
|
-
return string3 + newSuffix;
|
|
24998
|
-
}
|
|
24999
|
-
if (string3.slice(-oldSuffix.length) != oldSuffix) {
|
|
25000
|
-
throw Error("string ".concat(JSON.stringify(string3), " doesn't end with suffix ").concat(JSON.stringify(oldSuffix), "; this is a bug"));
|
|
25001
|
-
}
|
|
25002
|
-
return string3.slice(0, -oldSuffix.length) + newSuffix;
|
|
25003
|
-
}
|
|
25004
|
-
function removePrefix(string3, oldPrefix) {
|
|
25005
|
-
return replacePrefix(string3, oldPrefix, "");
|
|
25006
|
-
}
|
|
25007
|
-
function removeSuffix(string3, oldSuffix) {
|
|
25008
|
-
return replaceSuffix(string3, oldSuffix, "");
|
|
25009
|
-
}
|
|
25010
|
-
function maximumOverlap(string1, string22) {
|
|
25011
|
-
return string22.slice(0, overlapCount(string1, string22));
|
|
25012
|
-
}
|
|
25013
|
-
function overlapCount(a, b) {
|
|
25014
|
-
var startA = 0;
|
|
25015
|
-
if (a.length > b.length) {
|
|
25016
|
-
startA = a.length - b.length;
|
|
25017
|
-
}
|
|
25018
|
-
var endB = b.length;
|
|
25019
|
-
if (a.length < b.length) {
|
|
25020
|
-
endB = a.length;
|
|
25021
|
-
}
|
|
25022
|
-
var map = Array(endB);
|
|
25023
|
-
var k = 0;
|
|
25024
|
-
map[0] = 0;
|
|
25025
|
-
for (var j = 1; j < endB; j++) {
|
|
25026
|
-
if (b[j] == b[k]) {
|
|
25027
|
-
map[j] = map[k];
|
|
25028
|
-
} else {
|
|
25029
|
-
map[j] = k;
|
|
25030
|
-
}
|
|
25031
|
-
while (k > 0 && b[j] != b[k]) {
|
|
25032
|
-
k = map[k];
|
|
25033
|
-
}
|
|
25034
|
-
if (b[j] == b[k]) {
|
|
25035
|
-
k++;
|
|
25036
|
-
}
|
|
25037
|
-
}
|
|
25038
|
-
k = 0;
|
|
25039
|
-
for (var i = startA; i < a.length; i++) {
|
|
25040
|
-
while (k > 0 && a[i] != b[k]) {
|
|
25041
|
-
k = map[k];
|
|
25042
|
-
}
|
|
25043
|
-
if (a[i] == b[k]) {
|
|
25044
|
-
k++;
|
|
25045
|
-
}
|
|
25046
|
-
}
|
|
25047
|
-
return k;
|
|
25048
|
-
}
|
|
25049
|
-
var extendedWordChars = "a-zA-Z0-9_\\u{C0}-\\u{FF}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}";
|
|
25050
|
-
var tokenizeIncludingWhitespace = new RegExp("[".concat(extendedWordChars, "]+|\\s+|[^").concat(extendedWordChars, "]"), "ug");
|
|
25051
|
-
var wordDiff = new Diff();
|
|
25052
|
-
wordDiff.equals = function(left, right, options) {
|
|
25053
|
-
if (options.ignoreCase) {
|
|
25054
|
-
left = left.toLowerCase();
|
|
25055
|
-
right = right.toLowerCase();
|
|
25056
|
-
}
|
|
25057
|
-
return left.trim() === right.trim();
|
|
25058
|
-
};
|
|
25059
|
-
wordDiff.tokenize = function(value) {
|
|
25060
|
-
var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
25061
|
-
var parts;
|
|
25062
|
-
if (options.intlSegmenter) {
|
|
25063
|
-
if (options.intlSegmenter.resolvedOptions().granularity != "word") {
|
|
25064
|
-
throw new Error('The segmenter passed must have a granularity of "word"');
|
|
25065
|
-
}
|
|
25066
|
-
parts = Array.from(options.intlSegmenter.segment(value), function(segment) {
|
|
25067
|
-
return segment.segment;
|
|
25068
|
-
});
|
|
25069
|
-
} else {
|
|
25070
|
-
parts = value.match(tokenizeIncludingWhitespace) || [];
|
|
25071
|
-
}
|
|
25072
|
-
var tokens = [];
|
|
25073
|
-
var prevPart = null;
|
|
25074
|
-
parts.forEach(function(part) {
|
|
25075
|
-
if (/\s/.test(part)) {
|
|
25076
|
-
if (prevPart == null) {
|
|
25077
|
-
tokens.push(part);
|
|
25078
|
-
} else {
|
|
25079
|
-
tokens.push(tokens.pop() + part);
|
|
25080
|
-
}
|
|
25081
|
-
} else if (/\s/.test(prevPart)) {
|
|
25082
|
-
if (tokens[tokens.length - 1] == prevPart) {
|
|
25083
|
-
tokens.push(tokens.pop() + part);
|
|
25084
|
-
} else {
|
|
25085
|
-
tokens.push(prevPart + part);
|
|
25086
|
-
}
|
|
25087
|
-
} else {
|
|
25088
|
-
tokens.push(part);
|
|
25089
|
-
}
|
|
25090
|
-
prevPart = part;
|
|
25091
|
-
});
|
|
25092
|
-
return tokens;
|
|
25093
|
-
};
|
|
25094
|
-
wordDiff.join = function(tokens) {
|
|
25095
|
-
return tokens.map(function(token, i) {
|
|
25096
|
-
if (i == 0) {
|
|
25097
|
-
return token;
|
|
25098
|
-
} else {
|
|
25099
|
-
return token.replace(/^\s+/, "");
|
|
25100
|
-
}
|
|
25101
|
-
}).join("");
|
|
25102
|
-
};
|
|
25103
|
-
wordDiff.postProcess = function(changes, options) {
|
|
25104
|
-
if (!changes || options.oneChangePerToken) {
|
|
25105
|
-
return changes;
|
|
25106
|
-
}
|
|
25107
|
-
var lastKeep = null;
|
|
25108
|
-
var insertion = null;
|
|
25109
|
-
var deletion = null;
|
|
25110
|
-
changes.forEach(function(change) {
|
|
25111
|
-
if (change.added) {
|
|
25112
|
-
insertion = change;
|
|
25113
|
-
} else if (change.removed) {
|
|
25114
|
-
deletion = change;
|
|
25115
|
-
} else {
|
|
25116
|
-
if (insertion || deletion) {
|
|
25117
|
-
dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, change);
|
|
25118
|
-
}
|
|
25119
|
-
lastKeep = change;
|
|
25120
|
-
insertion = null;
|
|
25121
|
-
deletion = null;
|
|
25122
|
-
}
|
|
25123
|
-
});
|
|
25124
|
-
if (insertion || deletion) {
|
|
25125
|
-
dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, null);
|
|
25126
|
-
}
|
|
25127
|
-
return changes;
|
|
25128
|
-
};
|
|
25129
|
-
function dedupeWhitespaceInChangeObjects(startKeep, deletion, insertion, endKeep) {
|
|
25130
|
-
if (deletion && insertion) {
|
|
25131
|
-
var oldWsPrefix = deletion.value.match(/^\s*/)[0];
|
|
25132
|
-
var oldWsSuffix = deletion.value.match(/\s*$/)[0];
|
|
25133
|
-
var newWsPrefix = insertion.value.match(/^\s*/)[0];
|
|
25134
|
-
var newWsSuffix = insertion.value.match(/\s*$/)[0];
|
|
25135
|
-
if (startKeep) {
|
|
25136
|
-
var commonWsPrefix = longestCommonPrefix(oldWsPrefix, newWsPrefix);
|
|
25137
|
-
startKeep.value = replaceSuffix(startKeep.value, newWsPrefix, commonWsPrefix);
|
|
25138
|
-
deletion.value = removePrefix(deletion.value, commonWsPrefix);
|
|
25139
|
-
insertion.value = removePrefix(insertion.value, commonWsPrefix);
|
|
25140
|
-
}
|
|
25141
|
-
if (endKeep) {
|
|
25142
|
-
var commonWsSuffix = longestCommonSuffix(oldWsSuffix, newWsSuffix);
|
|
25143
|
-
endKeep.value = replacePrefix(endKeep.value, newWsSuffix, commonWsSuffix);
|
|
25144
|
-
deletion.value = removeSuffix(deletion.value, commonWsSuffix);
|
|
25145
|
-
insertion.value = removeSuffix(insertion.value, commonWsSuffix);
|
|
25146
|
-
}
|
|
25147
|
-
} else if (insertion) {
|
|
25148
|
-
if (startKeep) {
|
|
25149
|
-
insertion.value = insertion.value.replace(/^\s*/, "");
|
|
25150
|
-
}
|
|
25151
|
-
if (endKeep) {
|
|
25152
|
-
endKeep.value = endKeep.value.replace(/^\s*/, "");
|
|
25153
|
-
}
|
|
25154
|
-
} else if (startKeep && endKeep) {
|
|
25155
|
-
var newWsFull = endKeep.value.match(/^\s*/)[0], delWsStart = deletion.value.match(/^\s*/)[0], delWsEnd = deletion.value.match(/\s*$/)[0];
|
|
25156
|
-
var newWsStart = longestCommonPrefix(newWsFull, delWsStart);
|
|
25157
|
-
deletion.value = removePrefix(deletion.value, newWsStart);
|
|
25158
|
-
var newWsEnd = longestCommonSuffix(removePrefix(newWsFull, newWsStart), delWsEnd);
|
|
25159
|
-
deletion.value = removeSuffix(deletion.value, newWsEnd);
|
|
25160
|
-
endKeep.value = replacePrefix(endKeep.value, newWsFull, newWsEnd);
|
|
25161
|
-
startKeep.value = replaceSuffix(startKeep.value, newWsFull, newWsFull.slice(0, newWsFull.length - newWsEnd.length));
|
|
25162
|
-
} else if (endKeep) {
|
|
25163
|
-
var endKeepWsPrefix = endKeep.value.match(/^\s*/)[0];
|
|
25164
|
-
var deletionWsSuffix = deletion.value.match(/\s*$/)[0];
|
|
25165
|
-
var overlap = maximumOverlap(deletionWsSuffix, endKeepWsPrefix);
|
|
25166
|
-
deletion.value = removeSuffix(deletion.value, overlap);
|
|
25167
|
-
} else if (startKeep) {
|
|
25168
|
-
var startKeepWsSuffix = startKeep.value.match(/\s*$/)[0];
|
|
25169
|
-
var deletionWsPrefix = deletion.value.match(/^\s*/)[0];
|
|
25170
|
-
var _overlap = maximumOverlap(startKeepWsSuffix, deletionWsPrefix);
|
|
25171
|
-
deletion.value = removePrefix(deletion.value, _overlap);
|
|
25172
|
-
}
|
|
25173
|
-
}
|
|
25174
|
-
var wordWithSpaceDiff = new Diff();
|
|
25175
|
-
wordWithSpaceDiff.tokenize = function(value) {
|
|
25176
|
-
var regex = new RegExp("(\\r?\\n)|[".concat(extendedWordChars, "]+|[^\\S\\n\\r]+|[^").concat(extendedWordChars, "]"), "ug");
|
|
25177
|
-
return value.match(regex) || [];
|
|
25178
|
-
};
|
|
25179
|
-
var lineDiff = new Diff();
|
|
25180
|
-
lineDiff.tokenize = function(value, options) {
|
|
25181
|
-
if (options.stripTrailingCr) {
|
|
25182
|
-
value = value.replace(/\r\n/g, "\n");
|
|
25183
|
-
}
|
|
25184
|
-
var retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
|
|
25185
|
-
if (!linesAndNewlines[linesAndNewlines.length - 1]) {
|
|
25186
|
-
linesAndNewlines.pop();
|
|
25187
|
-
}
|
|
25188
|
-
for (var i = 0; i < linesAndNewlines.length; i++) {
|
|
25189
|
-
var line = linesAndNewlines[i];
|
|
25190
|
-
if (i % 2 && !options.newlineIsToken) {
|
|
25191
|
-
retLines[retLines.length - 1] += line;
|
|
25192
|
-
} else {
|
|
25193
|
-
retLines.push(line);
|
|
25194
|
-
}
|
|
25195
|
-
}
|
|
25196
|
-
return retLines;
|
|
25197
|
-
};
|
|
25198
|
-
lineDiff.equals = function(left, right, options) {
|
|
25199
|
-
if (options.ignoreWhitespace) {
|
|
25200
|
-
if (!options.newlineIsToken || !left.includes("\n")) {
|
|
25201
|
-
left = left.trim();
|
|
25202
|
-
}
|
|
25203
|
-
if (!options.newlineIsToken || !right.includes("\n")) {
|
|
25204
|
-
right = right.trim();
|
|
25205
|
-
}
|
|
25206
|
-
} else if (options.ignoreNewlineAtEof && !options.newlineIsToken) {
|
|
25207
|
-
if (left.endsWith("\n")) {
|
|
25208
|
-
left = left.slice(0, -1);
|
|
25209
|
-
}
|
|
25210
|
-
if (right.endsWith("\n")) {
|
|
25211
|
-
right = right.slice(0, -1);
|
|
25212
|
-
}
|
|
25213
|
-
}
|
|
25214
|
-
return Diff.prototype.equals.call(this, left, right, options);
|
|
25215
|
-
};
|
|
25216
|
-
var sentenceDiff = new Diff();
|
|
25217
|
-
sentenceDiff.tokenize = function(value) {
|
|
25218
|
-
return value.split(/(\S.+?[.!?])(?=\s+|$)/);
|
|
25219
|
-
};
|
|
25220
|
-
var cssDiff = new Diff();
|
|
25221
|
-
cssDiff.tokenize = function(value) {
|
|
25222
|
-
return value.split(/([{}:;,]|\s+)/);
|
|
25223
|
-
};
|
|
25224
|
-
function _typeof(o) {
|
|
25225
|
-
"@babel/helpers - typeof";
|
|
25226
|
-
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
|
|
25227
|
-
return typeof o2;
|
|
25228
|
-
} : function(o2) {
|
|
25229
|
-
return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2;
|
|
25230
|
-
}, _typeof(o);
|
|
25231
|
-
}
|
|
25232
|
-
var jsonDiff = new Diff();
|
|
25233
|
-
jsonDiff.useLongestToken = true;
|
|
25234
|
-
jsonDiff.tokenize = lineDiff.tokenize;
|
|
25235
|
-
jsonDiff.castInput = function(value, options) {
|
|
25236
|
-
var undefinedReplacement = options.undefinedReplacement, _options$stringifyRep = options.stringifyReplacer, stringifyReplacer = _options$stringifyRep === void 0 ? function(k, v) {
|
|
25237
|
-
return typeof v === "undefined" ? undefinedReplacement : v;
|
|
25238
|
-
} : _options$stringifyRep;
|
|
25239
|
-
return typeof value === "string" ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, " ");
|
|
25240
|
-
};
|
|
25241
|
-
jsonDiff.equals = function(left, right, options) {
|
|
25242
|
-
return Diff.prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, "$1"), right.replace(/,([\r\n])/g, "$1"), options);
|
|
25243
|
-
};
|
|
25244
|
-
function canonicalize(obj, stack, replacementStack, replacer, key) {
|
|
25245
|
-
stack = stack || [];
|
|
25246
|
-
replacementStack = replacementStack || [];
|
|
25247
|
-
if (replacer) {
|
|
25248
|
-
obj = replacer(key, obj);
|
|
25249
|
-
}
|
|
25250
|
-
var i;
|
|
25251
|
-
for (i = 0; i < stack.length; i += 1) {
|
|
25252
|
-
if (stack[i] === obj) {
|
|
25253
|
-
return replacementStack[i];
|
|
25254
|
-
}
|
|
25255
|
-
}
|
|
25256
|
-
var canonicalizedObj;
|
|
25257
|
-
if ("[object Array]" === Object.prototype.toString.call(obj)) {
|
|
25258
|
-
stack.push(obj);
|
|
25259
|
-
canonicalizedObj = new Array(obj.length);
|
|
25260
|
-
replacementStack.push(canonicalizedObj);
|
|
25261
|
-
for (i = 0; i < obj.length; i += 1) {
|
|
25262
|
-
canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, key);
|
|
25263
|
-
}
|
|
25264
|
-
stack.pop();
|
|
25265
|
-
replacementStack.pop();
|
|
25266
|
-
return canonicalizedObj;
|
|
25267
|
-
}
|
|
25268
|
-
if (obj && obj.toJSON) {
|
|
25269
|
-
obj = obj.toJSON();
|
|
25270
|
-
}
|
|
25271
|
-
if (_typeof(obj) === "object" && obj !== null) {
|
|
25272
|
-
stack.push(obj);
|
|
25273
|
-
canonicalizedObj = {};
|
|
25274
|
-
replacementStack.push(canonicalizedObj);
|
|
25275
|
-
var sortedKeys = [], _key;
|
|
25276
|
-
for (_key in obj) {
|
|
25277
|
-
if (Object.prototype.hasOwnProperty.call(obj, _key)) {
|
|
25278
|
-
sortedKeys.push(_key);
|
|
25279
|
-
}
|
|
25280
|
-
}
|
|
25281
|
-
sortedKeys.sort();
|
|
25282
|
-
for (i = 0; i < sortedKeys.length; i += 1) {
|
|
25283
|
-
_key = sortedKeys[i];
|
|
25284
|
-
canonicalizedObj[_key] = canonicalize(obj[_key], stack, replacementStack, replacer, _key);
|
|
25285
|
-
}
|
|
25286
|
-
stack.pop();
|
|
25287
|
-
replacementStack.pop();
|
|
25288
|
-
} else {
|
|
25289
|
-
canonicalizedObj = obj;
|
|
25290
|
-
}
|
|
25291
|
-
return canonicalizedObj;
|
|
25292
|
-
}
|
|
25293
|
-
var arrayDiff = new Diff();
|
|
25294
|
-
arrayDiff.tokenize = function(value) {
|
|
25295
|
-
return value.slice();
|
|
25296
|
-
};
|
|
25297
|
-
arrayDiff.join = arrayDiff.removeEmpty = function(value) {
|
|
25298
|
-
return value;
|
|
25299
|
-
};
|
|
25300
|
-
|
|
25301
|
-
// src/tools/claude-history.ts
|
|
25302
|
-
var JSONL_CHUNK_BYTES = 256 * 1024;
|
|
25303
|
-
|
|
25304
|
-
// src/tools/claude.ts
|
|
25305
|
-
var CLAUDE_MODEL_IDS = ["opus", "fable", "sonnet", "haiku"];
|
|
25306
|
-
var CLAUDE_MODELS = [
|
|
25307
|
-
{ id: "opus", label: "Opus", description: "Most capable", default: true },
|
|
25308
|
-
{ id: "fable", label: "Fable" },
|
|
25309
|
-
{ id: "sonnet", label: "Sonnet", description: "Fast, balanced" },
|
|
25310
|
-
{ id: "haiku", label: "Haiku", description: "Fastest, lightest" }
|
|
25311
|
-
];
|
|
25312
|
-
var _assertModelIdsAligned = CLAUDE_MODELS.map((m) => m.id);
|
|
25313
|
-
var CLAUDE_PERMISSION_MODES = [
|
|
25314
|
-
// 与 codex 的 'Ask for approval' 同义同名——同一个概念两个 tool 别叫两个名字
|
|
25315
|
-
{ id: "", label: "Ask for approval", description: "\u6BCF\u4E2A\u5DE5\u5177\u8C03\u7528\u90FD\u8981\u4F60\u70B9\u540C\u610F" },
|
|
25316
|
-
{ id: "plan", label: "Plan", description: "\u53EA\u8BFB\uFF0C\u4E0D\u6539\u4EE3\u7801" },
|
|
25317
|
-
{ id: "bypassPermissions", label: "YOLO", description: "\u8DF3\u8FC7\u5168\u90E8\u6388\u6743\u68C0\u67E5" }
|
|
25318
|
-
];
|
|
25319
|
-
var CLAUDE_CAPABILITIES = {
|
|
25320
|
-
tool: "claude",
|
|
25321
|
-
toolSessionIdLabel: "Claude Session ID",
|
|
25322
|
-
models: CLAUDE_MODELS,
|
|
25323
|
-
permissionModes: CLAUDE_PERMISSION_MODES,
|
|
25324
|
-
features: { rewind: true, subagents: true, tui: true, observe: true, fileSharing: true, fork: true },
|
|
25325
|
-
configSchema: [
|
|
25326
|
-
{
|
|
25327
|
-
name: "model",
|
|
25328
|
-
type: "select",
|
|
25329
|
-
label: "Model",
|
|
25330
|
-
scope: "core",
|
|
25331
|
-
options: CLAUDE_MODELS.map((m) => ({ value: m.id, label: m.label, description: m.description })),
|
|
25332
|
-
default: "opus"
|
|
25333
|
-
},
|
|
25334
|
-
{
|
|
25335
|
-
name: "permissionMode",
|
|
25336
|
-
type: "select",
|
|
25337
|
-
label: "Permission Mode",
|
|
25338
|
-
scope: "core",
|
|
25339
|
-
options: CLAUDE_PERMISSION_MODES.map((m) => ({ value: m.id, label: m.label, description: m.description })),
|
|
25340
|
-
default: ""
|
|
25341
|
-
},
|
|
25342
|
-
{
|
|
25343
|
-
name: "effort",
|
|
25344
|
-
type: "select",
|
|
25345
|
-
label: "Effort",
|
|
25346
|
-
description: "Reasoning effort level",
|
|
25347
|
-
scope: "tool-specific",
|
|
25348
|
-
// CC 2.1.187 --effort values. Use high when backfilling persona defaults to match common
|
|
25349
|
-
// settings.json effortLevel; omitting --effort would instead follow that file.
|
|
25350
|
-
options: [
|
|
25351
|
-
{ value: "low", label: "Low" },
|
|
25352
|
-
{ value: "medium", label: "Medium" },
|
|
25353
|
-
{ value: "high", label: "High" },
|
|
25354
|
-
{ value: "xhigh", label: "Extra high" },
|
|
25355
|
-
{ value: "max", label: "Max" }
|
|
25356
|
-
],
|
|
25357
|
-
default: "high"
|
|
25358
|
-
}
|
|
25359
|
-
]
|
|
25360
|
-
};
|
|
25361
|
-
|
|
25362
|
-
// src/dispatch/mcp-server.ts
|
|
25363
|
-
var DISPATCH_LOG = process.env.CLAWD_DISPATCH_LOG;
|
|
24791
|
+
// src/a2a/mcp-server.ts
|
|
24792
|
+
var LOG = process.env.CLAWD_A2A_LOG;
|
|
25364
24793
|
function log(msg, info) {
|
|
25365
|
-
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
24794
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] a2a-mcp ${msg}${info ? " " + JSON.stringify(info) : ""}
|
|
25366
24795
|
`;
|
|
25367
|
-
if (DISPATCH_LOG) {
|
|
25368
|
-
try {
|
|
25369
|
-
import_node_fs5.default.appendFileSync(DISPATCH_LOG, line);
|
|
25370
|
-
return;
|
|
25371
|
-
} catch {
|
|
25372
|
-
}
|
|
25373
|
-
}
|
|
25374
24796
|
try {
|
|
25375
|
-
|
|
24797
|
+
if (LOG) import_node_fs.default.appendFileSync(LOG, line);
|
|
24798
|
+
else process.stderr.write(line);
|
|
25376
24799
|
} catch {
|
|
25377
24800
|
}
|
|
25378
24801
|
}
|
|
25379
|
-
|
|
25380
|
-
|
|
25381
|
-
`2-3 sentences on ${what}. This is what the user sees **without expanding**; they decide from it whether to read the detail. Mirror the detail's top-level structure: if the brief makes three points, the detail must have the three matching sections in the same order. Do not tell a different story from the detail. Always fill this in.`
|
|
25382
|
-
);
|
|
25383
|
-
}
|
|
25384
|
-
async function handlePersonaDispatchToolCall(input, ctx) {
|
|
24802
|
+
var text = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError } : {} });
|
|
24803
|
+
async function rpc(ctx, method, body) {
|
|
25385
24804
|
const f = ctx.fetch ?? fetch;
|
|
25386
|
-
log("personaDispatch tool entered", {
|
|
25387
|
-
targetPersona: input.targetPersona,
|
|
25388
|
-
dispatchId: input.dispatchId,
|
|
25389
|
-
promptLen: input.prompt.length,
|
|
25390
|
-
sessionId: ctx.sessionId,
|
|
25391
|
-
daemonUrl: ctx.daemonUrl
|
|
25392
|
-
});
|
|
25393
|
-
if (!ctx.sessionId) {
|
|
25394
|
-
log("personaDispatch CLAWD_SESSION_ID missing");
|
|
25395
|
-
return {
|
|
25396
|
-
content: [
|
|
25397
|
-
{
|
|
25398
|
-
type: "text",
|
|
25399
|
-
text: "Error: CLAWD_SESSION_ID env not set; cannot dispatch."
|
|
25400
|
-
}
|
|
25401
|
-
],
|
|
25402
|
-
isError: true
|
|
25403
|
-
};
|
|
25404
|
-
}
|
|
25405
|
-
const url = `${ctx.daemonUrl}/rpc/personaDispatch:run`;
|
|
25406
|
-
log("personaDispatch pre-fetch", { url });
|
|
25407
|
-
let res;
|
|
25408
24805
|
try {
|
|
25409
|
-
res = await f(
|
|
24806
|
+
const res = await f(`${ctx.daemonUrl}/rpc/${method}`, {
|
|
25410
24807
|
method: "POST",
|
|
25411
|
-
headers: {
|
|
25412
|
-
|
|
25413
|
-
authorization: `Bearer ${ctx.daemonToken}`
|
|
25414
|
-
},
|
|
25415
|
-
body: JSON.stringify({
|
|
25416
|
-
// sessionId 是普通 body 参数(run handler 用作 sourceSessionId 归因),鉴权只看 Bearer
|
|
25417
|
-
sessionId: ctx.sessionId,
|
|
25418
|
-
...input.targetPersona ? { targetPersona: input.targetPersona } : {},
|
|
25419
|
-
prompt: input.prompt,
|
|
25420
|
-
...input.brief ? { brief: input.brief } : {},
|
|
25421
|
-
...input.dispatchId ? { dispatchId: input.dispatchId } : {},
|
|
25422
|
-
...input.targetDeviceId ? { targetDeviceId: input.targetDeviceId } : {},
|
|
25423
|
-
...input.model ? { model: input.model } : {},
|
|
25424
|
-
...input.tool ? { tool: input.tool } : {},
|
|
25425
|
-
...input.sessionLabel ? { sessionLabel: input.sessionLabel } : {},
|
|
25426
|
-
...input.meta ? { meta: input.meta } : {}
|
|
25427
|
-
})
|
|
24808
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${ctx.daemonToken}` },
|
|
24809
|
+
body: JSON.stringify(body)
|
|
25428
24810
|
});
|
|
24811
|
+
const json = await res.json();
|
|
24812
|
+
if (json.ok === false) return { ok: false, message: `${json.error}: ${json.message}` };
|
|
24813
|
+
return json;
|
|
25429
24814
|
} catch (err) {
|
|
25430
|
-
|
|
25431
|
-
|
|
25432
|
-
log("personaDispatch fetch threw", { url, message: e.message, cause });
|
|
25433
|
-
return {
|
|
25434
|
-
content: [
|
|
25435
|
-
{
|
|
25436
|
-
type: "text",
|
|
25437
|
-
text: `Dispatch fetch failed: ${e.message ?? String(err)}${cause?.message ? ` (cause: ${cause.message}${cause.code ? ` ${cause.code}` : ""})` : ""}`
|
|
25438
|
-
}
|
|
25439
|
-
],
|
|
25440
|
-
isError: true
|
|
25441
|
-
};
|
|
24815
|
+
log("rpc failed", { method, error: err.message });
|
|
24816
|
+
return { ok: false, message: `clawd daemon unreachable: ${err.message}` };
|
|
25442
24817
|
}
|
|
25443
|
-
log("personaDispatch post-fetch", { url, status: res.status });
|
|
25444
|
-
const json = await res.json();
|
|
25445
|
-
if (json.ok === false) {
|
|
25446
|
-
log("personaDispatch RPC adapter error", { error: json.error, message: json.message });
|
|
25447
|
-
return {
|
|
25448
|
-
content: [
|
|
25449
|
-
{ type: "text", text: `Dispatch RPC failed: ${json.error}: ${json.message}` }
|
|
25450
|
-
],
|
|
25451
|
-
isError: true
|
|
25452
|
-
};
|
|
25453
|
-
}
|
|
25454
|
-
const dispatchId = json.result.dispatchId;
|
|
25455
|
-
log("personaDispatch submitted", { dispatchId, followUp: Boolean(input.dispatchId) });
|
|
25456
|
-
const head = input.dispatchId ? `Follow-up sent for dispatch ${dispatchId} \u2014 the new instruction was delivered into the same worker session.` : `Task dispatched to ${input.targetPersona} (dispatchId=${dispatchId}).`;
|
|
25457
|
-
return {
|
|
25458
|
-
content: [
|
|
25459
|
-
{
|
|
25460
|
-
type: "text",
|
|
25461
|
-
text: `${head} The result will be delivered back into this session when the target persona finishes \u2014 you do NOT need to wait or poll. Tell the user the task has been delegated and end your turn. Use personaDispatchList only if the user later asks about progress.`
|
|
25462
|
-
}
|
|
25463
|
-
]
|
|
25464
|
-
};
|
|
25465
24818
|
}
|
|
25466
|
-
|
|
25467
|
-
const f = ctx.fetch ?? fetch;
|
|
25468
|
-
const filter = input.sourceSessionId ?? ctx.sessionId;
|
|
25469
|
-
const url = `${ctx.daemonUrl}/rpc/personaDispatch:list`;
|
|
25470
|
-
log("personaDispatchList pre-fetch", { url, filter });
|
|
25471
|
-
const headers = {
|
|
25472
|
-
"content-type": "application/json",
|
|
25473
|
-
authorization: `Bearer ${ctx.daemonToken}`
|
|
25474
|
-
};
|
|
25475
|
-
let res;
|
|
25476
|
-
try {
|
|
25477
|
-
res = await f(url, {
|
|
25478
|
-
method: "POST",
|
|
25479
|
-
headers,
|
|
25480
|
-
body: JSON.stringify(filter ? { sourceSessionId: filter } : {})
|
|
25481
|
-
});
|
|
25482
|
-
} catch (err) {
|
|
25483
|
-
const e = err;
|
|
25484
|
-
return {
|
|
25485
|
-
content: [{ type: "text", text: `List RPC failed: ${e.message ?? String(err)}` }],
|
|
25486
|
-
isError: true
|
|
25487
|
-
};
|
|
25488
|
-
}
|
|
25489
|
-
const json = await res.json();
|
|
25490
|
-
if (json.ok === false) {
|
|
25491
|
-
return {
|
|
25492
|
-
content: [{ type: "text", text: `List RPC failed: ${json.error}: ${json.message}` }],
|
|
25493
|
-
isError: true
|
|
25494
|
-
};
|
|
25495
|
-
}
|
|
25496
|
-
const lines = json.result.records.map((r) => {
|
|
25497
|
-
const result = r.outcome?.kind === "success" ? ` \u2192 ${(r.outcome.text ?? "").slice(0, 200)}` : r.outcome?.kind === "failure" ? ` \u2192 failed: ${r.outcome.reason ?? ""}` : "";
|
|
25498
|
-
return `- [${r.status}] ${r.dispatchId} \u2192 ${r.targetPersonaId} | ${r.taskText.slice(0, 80)} | created ${r.createdAt}${result}`;
|
|
25499
|
-
});
|
|
24819
|
+
function brief(t) {
|
|
25500
24820
|
return {
|
|
25501
|
-
|
|
25502
|
-
|
|
25503
|
-
|
|
25504
|
-
|
|
25505
|
-
|
|
25506
|
-
|
|
24821
|
+
taskId: t.taskId,
|
|
24822
|
+
contextId: t.contextId,
|
|
24823
|
+
target: t.tenant,
|
|
24824
|
+
round: t.round,
|
|
24825
|
+
state: t.state,
|
|
24826
|
+
...t.stale ? { stale: true } : {},
|
|
24827
|
+
...t.reason ? { reason: t.reason } : {},
|
|
24828
|
+
...t.brief ? { brief: t.brief } : {},
|
|
24829
|
+
...t.resultText ? { result: t.resultText } : {},
|
|
24830
|
+
...t.filePaths?.length ? { filePaths: t.filePaths } : {}
|
|
25507
24831
|
};
|
|
25508
24832
|
}
|
|
25509
|
-
|
|
25510
|
-
|
|
25511
|
-
|
|
25512
|
-
|
|
25513
|
-
|
|
25514
|
-
|
|
25515
|
-
|
|
25516
|
-
|
|
25517
|
-
|
|
25518
|
-
|
|
25519
|
-
|
|
25520
|
-
|
|
25521
|
-
|
|
25522
|
-
|
|
25523
|
-
|
|
25524
|
-
|
|
25525
|
-
|
|
25526
|
-
|
|
25527
|
-
|
|
25528
|
-
|
|
25529
|
-
|
|
25530
|
-
|
|
25531
|
-
|
|
25532
|
-
|
|
25533
|
-
|
|
25534
|
-
|
|
25535
|
-
|
|
25536
|
-
|
|
25537
|
-
...
|
|
25538
|
-
|
|
25539
|
-
};
|
|
25540
|
-
const url = `${ctx.daemonUrl}/rpc/personaDispatch:complete`;
|
|
25541
|
-
log("personaDispatchComplete pre-fetch", { url, hasSessionId: Boolean(ctx.sessionId) });
|
|
25542
|
-
const headers = {
|
|
25543
|
-
"content-type": "application/json",
|
|
25544
|
-
authorization: `Bearer ${ctx.daemonToken}`
|
|
25545
|
-
};
|
|
25546
|
-
try {
|
|
25547
|
-
const res = await f(url, {
|
|
25548
|
-
method: "POST",
|
|
25549
|
-
headers,
|
|
25550
|
-
body: JSON.stringify({ dispatchId: ctx.dispatchId, outcome })
|
|
25551
|
-
});
|
|
25552
|
-
log("personaDispatchComplete post-fetch", { url, status: res.status });
|
|
25553
|
-
} catch (err) {
|
|
25554
|
-
const e = err;
|
|
25555
|
-
const cause = e.cause ? { message: e.cause.message, code: e.cause.code } : void 0;
|
|
25556
|
-
log("personaDispatchComplete fetch threw", { url, message: e.message, cause });
|
|
25557
|
-
return {
|
|
25558
|
-
content: [
|
|
25559
|
-
{
|
|
25560
|
-
type: "text",
|
|
25561
|
-
text: `Complete RPC failed: ${e.message ?? String(err)}${cause?.message ? ` (cause: ${cause.message}${cause.code ? ` ${cause.code}` : ""})` : ""}`
|
|
25562
|
-
}
|
|
25563
|
-
],
|
|
25564
|
-
isError: true
|
|
25565
|
-
};
|
|
25566
|
-
}
|
|
25567
|
-
return {
|
|
25568
|
-
content: [{ type: "text", text: "Reported back to owner. Your session can now end." }]
|
|
25569
|
-
};
|
|
24833
|
+
var sendBody = (input, ctx) => ({ calls: input.calls, ...ctx.sessionId ? { sessionId: ctx.sessionId } : {} });
|
|
24834
|
+
async function handleAsync(input, ctx) {
|
|
24835
|
+
const r = await rpc(ctx, "a2a:send", sendBody(input, ctx));
|
|
24836
|
+
if (!r.ok) return text(`a2aAsync failed: ${r.message}`, true);
|
|
24837
|
+
const results = r.result.results.map((x) => x.ok ? brief(x.task) : { error: x.error });
|
|
24838
|
+
const anyOk = r.result.results.some((x) => x.ok);
|
|
24839
|
+
return text(
|
|
24840
|
+
JSON.stringify({ results }, null, 2) + (anyOk ? "\n\nThe results will be delivered back into this session automatically when each task finishes \u2014 do NOT wait or poll. Tell the user what was delegated and end your turn." : ""),
|
|
24841
|
+
!anyOk
|
|
24842
|
+
);
|
|
24843
|
+
}
|
|
24844
|
+
async function handleWait(input, ctx) {
|
|
24845
|
+
const now = ctx.now ?? Date.now;
|
|
24846
|
+
const sent = await rpc(ctx, "a2a:send", sendBody(input, ctx));
|
|
24847
|
+
if (!sent.ok) return text(`a2aWait failed: ${sent.message}`, true);
|
|
24848
|
+
const results = sent.result.results;
|
|
24849
|
+
const taskIds = results.filter((x) => x.ok).map((x) => x.task.taskId);
|
|
24850
|
+
if (taskIds.length === 0) return text(JSON.stringify({ results: results.map((x) => ({ error: x.error })) }, null, 2), true);
|
|
24851
|
+
const deadline = now() + Math.min(input.timeoutMs ?? A2A_WAIT_DEFAULT_MS, A2A_WAIT_MAX_MS);
|
|
24852
|
+
let last = null;
|
|
24853
|
+
do {
|
|
24854
|
+
const r = await rpc(ctx, "a2a:await", { taskIds, timeoutMs: Math.max(0, Math.min(A2A_AWAIT_SLICE_MAX_MS, deadline - now())) });
|
|
24855
|
+
if (!r.ok) return text(`a2aWait failed while waiting: ${r.message}`, true);
|
|
24856
|
+
last = r.result;
|
|
24857
|
+
} while (!last.done && now() < deadline);
|
|
24858
|
+
const byId = new Map(last.tasks.map((t) => [t.taskId, t]));
|
|
24859
|
+
const out = results.map((x) => x.ok ? brief(byId.get(x.task.taskId) ?? x.task) : { error: x.error });
|
|
24860
|
+
return text(
|
|
24861
|
+
JSON.stringify({ results: out, ...last.done ? {} : { timedOut: true } }, null, 2) + (last.done ? "" : "\n\nTimed out before every task finished. The tasks keep running; check later with a2aGetTask (in a Clawd-hosted session the results will also be delivered back automatically).")
|
|
24862
|
+
);
|
|
25570
24863
|
}
|
|
25571
24864
|
async function main() {
|
|
25572
24865
|
const daemonUrl = process.env.CLAWD_DAEMON_URL;
|
|
25573
24866
|
const daemonToken = process.env.CLAWD_DAEMON_TOKEN;
|
|
25574
24867
|
const sessionId = process.env.CLAWD_SESSION_ID;
|
|
25575
|
-
const
|
|
25576
|
-
log("boot", {
|
|
25577
|
-
pid: process.pid,
|
|
25578
|
-
hasDaemonUrl: Boolean(daemonUrl),
|
|
25579
|
-
hasSessionId: Boolean(sessionId),
|
|
25580
|
-
hasDispatchId: Boolean(dispatchId),
|
|
25581
|
-
logPath: DISPATCH_LOG ?? "(stderr)"
|
|
25582
|
-
});
|
|
24868
|
+
const contextId = process.env.CLAWD_A2A_CONTEXT_ID;
|
|
24869
|
+
log("boot", { pid: process.pid, hasSessionId: Boolean(sessionId), worker: Boolean(contextId) });
|
|
25583
24870
|
if (!daemonUrl || !daemonToken) {
|
|
25584
|
-
|
|
25585
|
-
process.stderr.write(
|
|
25586
|
-
"dispatch-mcp-server: CLAWD_DAEMON_URL/CLAWD_DAEMON_TOKEN not set; refusing to boot\n"
|
|
25587
|
-
);
|
|
24871
|
+
process.stderr.write("a2a-mcp-server: CLAWD_DAEMON_URL/CLAWD_DAEMON_TOKEN not set; refusing to boot\n");
|
|
25588
24872
|
process.exit(1);
|
|
25589
24873
|
}
|
|
25590
|
-
const
|
|
24874
|
+
const ctx = { daemonUrl, daemonToken, sessionId, contextId };
|
|
24875
|
+
const server = new McpServer({ name: "clawd-a2a", version: "1.0.0" });
|
|
24876
|
+
const call = external_exports.object({
|
|
24877
|
+
target: external_exports.string().describe("who: '<personaId>' (a persona on this device; a local mirror of a cloud persona is routed to the cloud), '<personaId>@<deviceId>' (a persona on a contact's device, as in an @persona/<id>@<deviceId> token), or 'cloud:<personaId>'"),
|
|
24878
|
+
text: external_exports.string().describe("the task, with the @persona token stripped out"),
|
|
24879
|
+
brief: external_exports.string().optional().describe("2-3 sentences on what you are asking for and why; shown on the card without expanding. Mirror the structure of text."),
|
|
24880
|
+
contextId: external_exports.string().optional().describe("continue an existing line (send back for rework / add an instruction): a new round in the same worker session, context kept"),
|
|
24881
|
+
taskId: external_exports.string().optional().describe("answer a task that is in input_required"),
|
|
24882
|
+
sessionLabel: external_exports.string().optional().describe("short label for the new worker session, 8-14 chars, verb-led; new lines only"),
|
|
24883
|
+
model: external_exports.string().optional().describe("one-off model for a new line; must belong to the engine that runs (pass tool too when switching engines)"),
|
|
24884
|
+
tool: external_exports.string().optional().describe("one-off engine for a new line: 'claude' | 'codex' | 'pi'; only for personas on your own devices"),
|
|
24885
|
+
meta: external_exports.record(external_exports.unknown()).optional().describe("line semantics for channel topics (topicId / lineId / acceptance); stored verbatim")
|
|
24886
|
+
});
|
|
24887
|
+
const calls = external_exports.array(call).min(1).max(A2A_MAX_CALLS).describe(`1 to ${A2A_MAX_CALLS} tasks; each succeeds or fails on its own`);
|
|
25591
24888
|
server.registerTool(
|
|
25592
|
-
"
|
|
24889
|
+
"a2aWait",
|
|
25593
24890
|
{
|
|
25594
|
-
title: "
|
|
25595
|
-
description: "
|
|
25596
|
-
inputSchema: {
|
|
25597
|
-
targetPersona: external_exports.string().optional().describe(
|
|
25598
|
-
"persona id (e.g. persona-app-builder); omit when continuing an existing dispatch via dispatchId"
|
|
25599
|
-
),
|
|
25600
|
-
dispatchId: external_exports.string().optional().describe(
|
|
25601
|
-
"continue an existing dispatched task: the prompt is delivered into the same worker session as a new turn (context preserved). The worker session keeps its original engine and model \u2014 passing tool or model together with dispatchId is rejected; start a new dispatch to change either."
|
|
25602
|
-
),
|
|
25603
|
-
prompt: external_exports.string().describe(
|
|
25604
|
-
"the task to perform, with the @persona/<id> token stripped out"
|
|
25605
|
-
),
|
|
25606
|
-
brief: BRIEF_DESCRIBE(
|
|
25607
|
-
external_exports.string().optional(),
|
|
25608
|
-
"what you are asking for and why it matters"
|
|
25609
|
-
),
|
|
25610
|
-
targetDeviceId: external_exports.string().optional().describe(
|
|
25611
|
-
"contact deviceId of the remote device when delegating cross-device (omit for a local persona; omit when continuing via dispatchId \u2014 the device is remembered)"
|
|
25612
|
-
),
|
|
25613
|
-
// 模型列表随 engine 版本变化,不能编译期 enum 固定;daemon 按实际 engine capabilities 校验。
|
|
25614
|
-
model: external_exports.string().optional().describe(
|
|
25615
|
-
"override the target persona's default model for this one dispatch. New dispatches only (rejected together with dispatchId). Omit to use the persona default. The valid set depends on the engine that will actually run (see tool): claude \u2192 active subscription model IDs, or in native mode the aliases " + CLAUDE_MODEL_IDS.join(" / ") + "; codex \u2192 model ids vary by installed codex version (e.g. gpt-5.6-sol); pi \u2192 ids are '<provider>/<model>' from pi's own model table. Omit unless you know the exact id (invalid values are rejected with the allowed list)."
|
|
25616
|
-
),
|
|
25617
|
-
// model 的合法值集属于 engine,跨 engine 换模型须同时指定对应 engine。
|
|
25618
|
-
tool: external_exports.string().optional().describe(
|
|
25619
|
-
"run this one dispatch on a specific engine instead of the persona's bound one: 'claude', 'codex' or 'pi'. One-off \u2014 the persona's own binding is untouched. Pass this whenever you pass a model that belongs to the other engine (e.g. tool='codex' + model='gpt-5.6-sol' for a persona bound to claude). New dispatches only: rejected together with dispatchId (follow-ups keep the worker session's engine) or with targetDeviceId (a remote persona keeps its owner's engine)."
|
|
25620
|
-
),
|
|
25621
|
-
// 只给新 worker 设置 label;续派保留既有命名。
|
|
25622
|
-
sessionLabel: external_exports.string().optional().describe(
|
|
25623
|
-
'short human-readable label for the new worker session (shown in sidebar, e.g. "\u4FEE sidebar \u9876\u90E8\u5165\u53E3" / "\u67E5\u6628\u665A SLS \u767B\u5F55\u5931\u8D25"). aim for 8-14 chars, verb-led. ignored when continuing an existing dispatch via dispatchId (worker session keeps its original label).'
|
|
25624
|
-
),
|
|
25625
|
-
meta: external_exports.record(external_exports.unknown()).optional().describe(
|
|
25626
|
-
"orchestrator-level semantics attached to this dispatch line (topicId / lineId / acceptance criteria). lineId is required for the line to show up in its topic \u2014 daemon claims lines by meta.lineId. do NOT track reject counts here: daemon counts them in topic:reject / topic:accept, a hand-kept copy only drifts. daemon stores it verbatim without interpreting; on follow-up it is merged into the existing meta (new keys win, others preserved)."
|
|
25627
|
-
)
|
|
25628
|
-
}
|
|
24891
|
+
title: "Delegate to personas and wait for the results",
|
|
24892
|
+
description: "Send tasks to other personas and wait in this call until every one finishes (or needs your answer), then return the results. Use it when you need the results within this turn, e.g. dispatch several and combine them.",
|
|
24893
|
+
inputSchema: { calls, timeoutMs: external_exports.number().int().min(1e3).max(A2A_WAIT_MAX_MS).optional().describe(`how long to wait in total (default ${A2A_WAIT_DEFAULT_MS} ms)`) }
|
|
25629
24894
|
},
|
|
25630
|
-
async (input) =>
|
|
24895
|
+
async (input) => handleWait(input, ctx)
|
|
25631
24896
|
);
|
|
25632
24897
|
server.registerTool(
|
|
25633
|
-
"
|
|
24898
|
+
"a2aAsync",
|
|
25634
24899
|
{
|
|
25635
|
-
title: "
|
|
25636
|
-
description: "
|
|
25637
|
-
inputSchema: {
|
|
25638
|
-
text: external_exports.string().optional().describe("your result text (omit on failure)"),
|
|
25639
|
-
brief: BRIEF_DESCRIBE(
|
|
25640
|
-
external_exports.string().optional(),
|
|
25641
|
-
"what happened \u2014 did it go smoothly, did anything break, what's the one thing the reader must know"
|
|
25642
|
-
),
|
|
25643
|
-
filePaths: external_exports.array(external_exports.string()).optional().describe("absolute paths to files you produced or modified"),
|
|
25644
|
-
isFailure: external_exports.boolean().optional(),
|
|
25645
|
-
reason: external_exports.string().optional().describe("failure reason (required when isFailure=true)")
|
|
25646
|
-
}
|
|
24900
|
+
title: "Delegate to personas without waiting",
|
|
24901
|
+
description: "Send tasks to other personas and return immediately. Each result is delivered back into this session as a new message when that task finishes; end your turn after telling the user what you delegated.",
|
|
24902
|
+
inputSchema: { calls }
|
|
25647
24903
|
},
|
|
25648
|
-
|
|
25649
|
-
async (input) => handlePersonaDispatchCompleteToolCall(input, { daemonUrl, daemonToken, sessionId, dispatchId })
|
|
24904
|
+
async (input) => handleAsync(input, ctx)
|
|
25650
24905
|
);
|
|
25651
24906
|
server.registerTool(
|
|
25652
|
-
"
|
|
24907
|
+
"a2aGetTask",
|
|
24908
|
+
{ title: "Get one delegated task", description: "State and result of a task you delegated.", inputSchema: { taskId: external_exports.string() } },
|
|
24909
|
+
async (input) => {
|
|
24910
|
+
const r = await rpc(ctx, "a2a:get", input);
|
|
24911
|
+
return r.ok ? text(JSON.stringify(brief(r.result), null, 2)) : text(r.message, true);
|
|
24912
|
+
}
|
|
24913
|
+
);
|
|
24914
|
+
server.registerTool(
|
|
24915
|
+
"a2aListTasks",
|
|
25653
24916
|
{
|
|
25654
|
-
title: "List
|
|
25655
|
-
description: "
|
|
24917
|
+
title: "List delegated tasks",
|
|
24918
|
+
description: "Tasks this session delegated (newest first), optionally narrowed to one line (contextId) or one state.",
|
|
25656
24919
|
inputSchema: {
|
|
25657
|
-
|
|
24920
|
+
contextId: external_exports.string().optional(),
|
|
24921
|
+
state: external_exports.enum(["submitted", "working", "input_required", "completed", "failed", "canceled", "rejected"]).optional()
|
|
25658
24922
|
}
|
|
25659
24923
|
},
|
|
25660
|
-
async (input) =>
|
|
24924
|
+
async (input) => {
|
|
24925
|
+
const r = await rpc(ctx, "a2a:list", { ...input, ...sessionId ? { sessionId } : {} });
|
|
24926
|
+
return r.ok ? text(JSON.stringify(r.result.tasks.map(brief), null, 2)) : text(r.message, true);
|
|
24927
|
+
}
|
|
25661
24928
|
);
|
|
24929
|
+
server.registerTool(
|
|
24930
|
+
"a2aCancelTask",
|
|
24931
|
+
{ title: "Cancel a delegated task", description: "Cancel a task that has not finished; its worker is interrupted.", inputSchema: { taskId: external_exports.string() } },
|
|
24932
|
+
async (input) => {
|
|
24933
|
+
const r = await rpc(ctx, "a2a:cancel", input);
|
|
24934
|
+
return r.ok ? text(JSON.stringify(brief(r.result), null, 2)) : text(r.message, true);
|
|
24935
|
+
}
|
|
24936
|
+
);
|
|
24937
|
+
if (contextId) {
|
|
24938
|
+
server.registerTool(
|
|
24939
|
+
"a2aReport",
|
|
24940
|
+
{
|
|
24941
|
+
title: "Report this round back to the requester",
|
|
24942
|
+
description: "You were delegated a task (a <clawd-a2a-task> message). Call this when the round is done (completed), failed, or when you need the requester to answer something before you can continue (input_required).",
|
|
24943
|
+
inputSchema: {
|
|
24944
|
+
state: external_exports.enum(["completed", "failed", "input_required"]),
|
|
24945
|
+
text: external_exports.string().describe("the result; the failure reason; or your question"),
|
|
24946
|
+
brief: external_exports.string().optional().describe("2-3 sentences: did it go smoothly, did anything break, the one thing the reader must know. Mirror the structure of text."),
|
|
24947
|
+
filePaths: external_exports.array(external_exports.string()).optional().describe("absolute paths of files you produced or changed")
|
|
24948
|
+
}
|
|
24949
|
+
},
|
|
24950
|
+
async (input) => {
|
|
24951
|
+
const r = await rpc(ctx, "a2a:report", { ...input, contextId });
|
|
24952
|
+
return r.ok ? text("Reported back to the requester.") : text(`a2aReport failed: ${r.message}`, true);
|
|
24953
|
+
}
|
|
24954
|
+
);
|
|
24955
|
+
}
|
|
25662
24956
|
await server.connect(new StdioServerTransport());
|
|
25663
24957
|
}
|
|
25664
24958
|
var isMainModule = typeof require !== "undefined" && typeof module !== "undefined" && require.main === module;
|
|
25665
24959
|
if (isMainModule) {
|
|
25666
24960
|
main().catch((err) => {
|
|
25667
|
-
process.stderr.write(`
|
|
24961
|
+
process.stderr.write(`a2a-mcp-server boot failed: ${String(err)}
|
|
25668
24962
|
`);
|
|
25669
24963
|
process.exit(1);
|
|
25670
24964
|
});
|
|
25671
24965
|
}
|
|
25672
24966
|
// Annotate the CommonJS export names for ESM import in node:
|
|
25673
24967
|
0 && (module.exports = {
|
|
25674
|
-
|
|
25675
|
-
|
|
25676
|
-
handlePersonaDispatchToolCall
|
|
24968
|
+
handleAsync,
|
|
24969
|
+
handleWait
|
|
25677
24970
|
});
|