duclaw-cli 1.9.4 → 1.9.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/dist/bundle.js +361 -91
- package/dist/main.js +1 -1
- package/dist/worker-main.js +1 -1
- package/package.json +3 -1
package/dist/bundle.js
CHANGED
|
@@ -30242,7 +30242,7 @@ function printHelp() {
|
|
|
30242
30242
|
`);
|
|
30243
30243
|
}
|
|
30244
30244
|
function printVersion() {
|
|
30245
|
-
console.log(`duclaw-cli v${true ? "1.9.
|
|
30245
|
+
console.log(`duclaw-cli v${true ? "1.9.5" : "unknown"}`);
|
|
30246
30246
|
}
|
|
30247
30247
|
function getDuclawTemplate() {
|
|
30248
30248
|
return {
|
|
@@ -33273,7 +33273,7 @@ var chokidar_default = { watch, FSWatcher };
|
|
|
33273
33273
|
var import_node_cron = __toESM(require_node_cron());
|
|
33274
33274
|
|
|
33275
33275
|
// src/agent/createAgent.ts
|
|
33276
|
-
var
|
|
33276
|
+
var import_node_crypto15 = require("node:crypto");
|
|
33277
33277
|
var import_node_fs7 = require("node:fs");
|
|
33278
33278
|
|
|
33279
33279
|
// src/background/BackgroundManager.ts
|
|
@@ -38895,35 +38895,69 @@ var clearMessages = async (storage, userId, date, cronTitle) => {
|
|
|
38895
38895
|
await storage.del(key);
|
|
38896
38896
|
};
|
|
38897
38897
|
|
|
38898
|
-
// src/
|
|
38899
|
-
|
|
38900
|
-
|
|
38901
|
-
|
|
38902
|
-
|
|
38903
|
-
|
|
38904
|
-
|
|
38905
|
-
|
|
38906
|
-
|
|
38907
|
-
|
|
38908
|
-
|
|
38909
|
-
|
|
38910
|
-
|
|
38911
|
-
|
|
38912
|
-
|
|
38913
|
-
|
|
38914
|
-
|
|
38915
|
-
|
|
38916
|
-
|
|
38917
|
-
|
|
38918
|
-
|
|
38919
|
-
|
|
38920
|
-
|
|
38921
|
-
|
|
38922
|
-
|
|
38923
|
-
console.warn(`[runtime-activity] \u4E0A\u62A5\u5931\u8D25: tool=${input.toolName} status=${input.status} http=${response.status}`);
|
|
38898
|
+
// src/tools/ToolExecutor.ts
|
|
38899
|
+
var import_node_crypto2 = require("node:crypto");
|
|
38900
|
+
|
|
38901
|
+
// src/runtime/events.ts
|
|
38902
|
+
var createRuntimeEventBus = () => {
|
|
38903
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
38904
|
+
return {
|
|
38905
|
+
async emit(event) {
|
|
38906
|
+
const subscribers = Array.from(handlers.get(event.type) ?? []);
|
|
38907
|
+
for (const handler of subscribers) {
|
|
38908
|
+
try {
|
|
38909
|
+
await handler(event);
|
|
38910
|
+
} catch (error) {
|
|
38911
|
+
console.warn(`[runtime-event-bus] handler failed: type=${event.type} error=${error.message}`);
|
|
38912
|
+
}
|
|
38913
|
+
}
|
|
38914
|
+
},
|
|
38915
|
+
subscribe(type, handler) {
|
|
38916
|
+
const current = handlers.get(type) ?? /* @__PURE__ */ new Set();
|
|
38917
|
+
current.add(handler);
|
|
38918
|
+
handlers.set(type, current);
|
|
38919
|
+
return () => {
|
|
38920
|
+
current.delete(handler);
|
|
38921
|
+
if (current.size === 0) handlers.delete(type);
|
|
38922
|
+
};
|
|
38924
38923
|
}
|
|
38925
|
-
}
|
|
38926
|
-
|
|
38924
|
+
};
|
|
38925
|
+
};
|
|
38926
|
+
|
|
38927
|
+
// src/runtime/toolHooks.ts
|
|
38928
|
+
function sortToolHookPlugins(plugins = []) {
|
|
38929
|
+
return [...plugins].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
38930
|
+
}
|
|
38931
|
+
async function runPreToolUseHooks(plugins, ctx) {
|
|
38932
|
+
for (const plugin of plugins) {
|
|
38933
|
+
if (!plugin.preToolUse) continue;
|
|
38934
|
+
const decision = await plugin.preToolUse(ctx);
|
|
38935
|
+
if (decision?.metadataPatch) {
|
|
38936
|
+
ctx.metadata = {
|
|
38937
|
+
...ctx.metadata,
|
|
38938
|
+
...decision.metadataPatch
|
|
38939
|
+
};
|
|
38940
|
+
}
|
|
38941
|
+
if (decision?.deny || decision?.allow === false) {
|
|
38942
|
+
return {
|
|
38943
|
+
allow: false,
|
|
38944
|
+
deny: true,
|
|
38945
|
+
reason: decision.reason ?? `blocked_by_${plugin.id}`,
|
|
38946
|
+
userMessage: decision.userMessage,
|
|
38947
|
+
metadataPatch: decision.metadataPatch
|
|
38948
|
+
};
|
|
38949
|
+
}
|
|
38950
|
+
}
|
|
38951
|
+
return { allow: true };
|
|
38952
|
+
}
|
|
38953
|
+
async function runAfterToolUseHooks(plugins, ctx) {
|
|
38954
|
+
for (const plugin of plugins) {
|
|
38955
|
+
if (plugin.afterToolUse) await plugin.afterToolUse(ctx);
|
|
38956
|
+
}
|
|
38957
|
+
}
|
|
38958
|
+
async function runToolUseErrorHooks(plugins, ctx) {
|
|
38959
|
+
for (const plugin of plugins) {
|
|
38960
|
+
if (plugin.onToolUseError) await plugin.onToolUseError(ctx);
|
|
38927
38961
|
}
|
|
38928
38962
|
}
|
|
38929
38963
|
|
|
@@ -38941,7 +38975,9 @@ var UserRecoverableToolError = class extends Error {
|
|
|
38941
38975
|
var isUserRecoverableToolError = (error) => error instanceof UserRecoverableToolError || typeof error === "object" && error !== null && error.name === "UserRecoverableToolError" && typeof error.userMessage === "string";
|
|
38942
38976
|
|
|
38943
38977
|
// src/tools/ToolExecutor.ts
|
|
38944
|
-
var createToolExecutor = (registry2) => {
|
|
38978
|
+
var createToolExecutor = (registry2, options = {}) => {
|
|
38979
|
+
const hookPlugins = sortToolHookPlugins(options.hookPlugins ?? []);
|
|
38980
|
+
const eventBus = options.eventBus ?? createRuntimeEventBus();
|
|
38945
38981
|
return {
|
|
38946
38982
|
async execute(name, input, userRequest) {
|
|
38947
38983
|
const tool = registry2.get(name);
|
|
@@ -38953,42 +38989,78 @@ var createToolExecutor = (registry2) => {
|
|
|
38953
38989
|
}
|
|
38954
38990
|
}
|
|
38955
38991
|
const toolCallId = typeof userRequest?.metadata?.toolCallId === "string" ? userRequest.metadata.toolCallId : null;
|
|
38956
|
-
|
|
38957
|
-
|
|
38992
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
38993
|
+
const ctx = {
|
|
38958
38994
|
toolName: name,
|
|
38959
|
-
status: "started",
|
|
38960
38995
|
toolCallId,
|
|
38961
|
-
|
|
38962
|
-
|
|
38963
|
-
|
|
38964
|
-
|
|
38965
|
-
|
|
38996
|
+
input: input ?? {},
|
|
38997
|
+
userRequest,
|
|
38998
|
+
startedAt,
|
|
38999
|
+
metadata: requestContext(userRequest)
|
|
39000
|
+
};
|
|
39001
|
+
await eventBus.emit({
|
|
39002
|
+
eventId: runtimeEventId("toolUse.started", name, toolCallId, startedAt),
|
|
39003
|
+
type: "toolUse.started",
|
|
39004
|
+
occurredAt: startedAt.toISOString(),
|
|
39005
|
+
toolName: name,
|
|
39006
|
+
toolCallId,
|
|
39007
|
+
inputSummary: summarizeJson(ctx.input),
|
|
39008
|
+
requestContext: ctx.metadata
|
|
38966
39009
|
});
|
|
39010
|
+
const preDecision = await runPreToolUseHooks(hookPlugins, ctx);
|
|
39011
|
+
if (preDecision.deny || preDecision.allow === false) {
|
|
39012
|
+
ctx.durationMs = Date.now() - startedAt.getTime();
|
|
39013
|
+
const reason = preDecision.reason ?? "tool_use_blocked";
|
|
39014
|
+
await eventBus.emit({
|
|
39015
|
+
eventId: runtimeEventId("toolUse.blocked", name, toolCallId, startedAt),
|
|
39016
|
+
type: "toolUse.blocked",
|
|
39017
|
+
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39018
|
+
toolName: name,
|
|
39019
|
+
toolCallId,
|
|
39020
|
+
inputSummary: summarizeJson(ctx.input),
|
|
39021
|
+
durationMs: ctx.durationMs,
|
|
39022
|
+
errorSummary: reason,
|
|
39023
|
+
requestContext: ctx.metadata
|
|
39024
|
+
});
|
|
39025
|
+
throw new UserRecoverableToolError(
|
|
39026
|
+
"tool_use_blocked",
|
|
39027
|
+
preDecision.userMessage ?? "\u5F53\u524D\u5DE5\u5177\u8C03\u7528\u5DF2\u88AB\u7CFB\u7EDF\u7B56\u7565\u963B\u6B62\u3002",
|
|
39028
|
+
reason
|
|
39029
|
+
);
|
|
39030
|
+
}
|
|
38967
39031
|
try {
|
|
38968
39032
|
const result = await tool.execute(input ?? {}, userRequest);
|
|
38969
|
-
|
|
38970
|
-
|
|
39033
|
+
ctx.resultText = result;
|
|
39034
|
+
ctx.durationMs = Date.now() - startedAt.getTime();
|
|
39035
|
+
await runAfterToolUseHooks(hookPlugins, ctx);
|
|
39036
|
+
await eventBus.emit({
|
|
39037
|
+
eventId: runtimeEventId("toolUse.completed", name, toolCallId, startedAt),
|
|
39038
|
+
type: "toolUse.completed",
|
|
39039
|
+
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38971
39040
|
toolName: name,
|
|
38972
|
-
status: "completed",
|
|
38973
39041
|
toolCallId,
|
|
38974
|
-
|
|
38975
|
-
|
|
38976
|
-
|
|
38977
|
-
|
|
38978
|
-
}
|
|
39042
|
+
inputSummary: summarizeJson(ctx.input),
|
|
39043
|
+
durationMs: ctx.durationMs,
|
|
39044
|
+
resultSummary: summarizeText(result),
|
|
39045
|
+
requestContext: ctx.metadata
|
|
38979
39046
|
});
|
|
38980
39047
|
return result;
|
|
38981
39048
|
} catch (error) {
|
|
38982
39049
|
const err = error;
|
|
38983
|
-
|
|
38984
|
-
|
|
39050
|
+
ctx.error = err;
|
|
39051
|
+
ctx.durationMs = Date.now() - startedAt.getTime();
|
|
39052
|
+
await runToolUseErrorHooks(hookPlugins, ctx);
|
|
39053
|
+
await eventBus.emit({
|
|
39054
|
+
eventId: runtimeEventId("toolUse.failed", name, toolCallId, startedAt),
|
|
39055
|
+
type: "toolUse.failed",
|
|
39056
|
+
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38985
39057
|
toolName: name,
|
|
38986
|
-
status: "failed",
|
|
38987
39058
|
toolCallId,
|
|
38988
|
-
|
|
38989
|
-
|
|
38990
|
-
|
|
38991
|
-
|
|
39059
|
+
inputSummary: summarizeJson(ctx.input),
|
|
39060
|
+
durationMs: ctx.durationMs,
|
|
39061
|
+
errorSummary: summarizeText(err.message),
|
|
39062
|
+
requestContext: {
|
|
39063
|
+
...ctx.metadata,
|
|
38992
39064
|
error: err.message
|
|
38993
39065
|
}
|
|
38994
39066
|
});
|
|
@@ -39005,6 +39077,23 @@ var createToolExecutor = (registry2) => {
|
|
|
39005
39077
|
}
|
|
39006
39078
|
};
|
|
39007
39079
|
};
|
|
39080
|
+
function requestContext(userRequest) {
|
|
39081
|
+
return {
|
|
39082
|
+
platform: userRequest?.platform,
|
|
39083
|
+
requestId: userRequest?.requestId,
|
|
39084
|
+
departmentAgentId: userRequest?.departmentAgentId
|
|
39085
|
+
};
|
|
39086
|
+
}
|
|
39087
|
+
function summarizeJson(value, maxChars = 1e3) {
|
|
39088
|
+
return summarizeText(JSON.stringify(value ?? null), maxChars);
|
|
39089
|
+
}
|
|
39090
|
+
function summarizeText(value, maxChars = 1e3) {
|
|
39091
|
+
return value.length <= maxChars ? value : `${value.slice(0, maxChars)}...`;
|
|
39092
|
+
}
|
|
39093
|
+
function runtimeEventId(type, toolName, toolCallId, startedAt) {
|
|
39094
|
+
if (typeof import_node_crypto2.randomUUID === "function") return (0, import_node_crypto2.randomUUID)();
|
|
39095
|
+
return (0, import_node_crypto2.createHash)("sha256").update(type).update("\0").update(toolName).update("\0").update(toolCallId ?? "").update("\0").update(startedAt.toISOString()).digest("hex");
|
|
39096
|
+
}
|
|
39008
39097
|
|
|
39009
39098
|
// src/tools/ToolRegistry.ts
|
|
39010
39099
|
var createToolRegistry = () => {
|
|
@@ -41409,7 +41498,7 @@ var isToolUseBlock = (block) => block.type === "tool_use";
|
|
|
41409
41498
|
var extractText = (blocks) => blocks.filter(isTextBlock).map((b) => b.text).join("\n");
|
|
41410
41499
|
|
|
41411
41500
|
// src/tools/tools/ImageUnderstandMetering.ts
|
|
41412
|
-
var
|
|
41501
|
+
var import_node_crypto3 = require("node:crypto");
|
|
41413
41502
|
var ImageUnderstandMeteringError = class extends Error {
|
|
41414
41503
|
constructor(message, statusCode, meteringStatus) {
|
|
41415
41504
|
super(message);
|
|
@@ -41499,7 +41588,7 @@ function inferImageProvider(baseUrl) {
|
|
|
41499
41588
|
}
|
|
41500
41589
|
}
|
|
41501
41590
|
function fingerprintImageSource(imageSource) {
|
|
41502
|
-
return (0,
|
|
41591
|
+
return (0, import_node_crypto3.createHash)("sha256").update(imageSource).digest("hex");
|
|
41503
41592
|
}
|
|
41504
41593
|
function imageSourceKind(imageSource) {
|
|
41505
41594
|
if (imageSource.startsWith("http://") || imageSource.startsWith("https://")) return "url";
|
|
@@ -42109,10 +42198,10 @@ var goalDelete = {
|
|
|
42109
42198
|
};
|
|
42110
42199
|
|
|
42111
42200
|
// src/tools/tools/department/DepartmentCreate.ts
|
|
42112
|
-
var
|
|
42201
|
+
var import_node_crypto8 = require("node:crypto");
|
|
42113
42202
|
|
|
42114
42203
|
// src/department/mailbox/mailbox.ts
|
|
42115
|
-
var
|
|
42204
|
+
var import_node_crypto7 = require("node:crypto");
|
|
42116
42205
|
|
|
42117
42206
|
// src/agent/interruptRegistry.ts
|
|
42118
42207
|
var registry = /* @__PURE__ */ new Map();
|
|
@@ -42163,7 +42252,7 @@ var drainInterrupts = (userId) => {
|
|
|
42163
42252
|
};
|
|
42164
42253
|
|
|
42165
42254
|
// src/agent/events.ts
|
|
42166
|
-
var
|
|
42255
|
+
var import_node_crypto4 = require("node:crypto");
|
|
42167
42256
|
var rowToEvent = (row) => ({
|
|
42168
42257
|
id: row.id,
|
|
42169
42258
|
userId: row.userId,
|
|
@@ -42180,7 +42269,7 @@ var rowToEvent = (row) => ({
|
|
|
42180
42269
|
var recordAgentEvent = (input) => {
|
|
42181
42270
|
const db3 = createSqliteDB();
|
|
42182
42271
|
const now = Date.now();
|
|
42183
|
-
const id = `evt_${(0,
|
|
42272
|
+
const id = `evt_${(0, import_node_crypto4.randomUUID)().slice(0, 12)}`;
|
|
42184
42273
|
const payloadJson = JSON.stringify(input.payload);
|
|
42185
42274
|
db3.prepare(`
|
|
42186
42275
|
INSERT INTO agent_events (
|
|
@@ -42311,7 +42400,7 @@ ${ceoFollowupInstruction}
|
|
|
42311
42400
|
};
|
|
42312
42401
|
|
|
42313
42402
|
// src/department/mailbox/events.ts
|
|
42314
|
-
var
|
|
42403
|
+
var import_node_crypto5 = require("node:crypto");
|
|
42315
42404
|
var parseDetail = (detailJson) => {
|
|
42316
42405
|
if (!detailJson) return void 0;
|
|
42317
42406
|
try {
|
|
@@ -42352,7 +42441,7 @@ var mapMailboxEventRow = (row) => {
|
|
|
42352
42441
|
var recordMailboxEvent = (input) => {
|
|
42353
42442
|
const db3 = createSqliteDB();
|
|
42354
42443
|
const event = {
|
|
42355
|
-
id: (0,
|
|
42444
|
+
id: (0, import_node_crypto5.randomUUID)().slice(0, 12),
|
|
42356
42445
|
messageId: input.messageId,
|
|
42357
42446
|
mailboxId: input.mailboxId,
|
|
42358
42447
|
actorMailboxId: input.actorMailboxId,
|
|
@@ -42636,7 +42725,7 @@ var deleteDepartmentMemberById = (departmentName, memberId) => {
|
|
|
42636
42725
|
};
|
|
42637
42726
|
|
|
42638
42727
|
// src/department/mailbox/ceoFollowup.ts
|
|
42639
|
-
var
|
|
42728
|
+
var import_node_crypto6 = require("node:crypto");
|
|
42640
42729
|
var rowToFollowup = (row) => ({
|
|
42641
42730
|
id: row.id,
|
|
42642
42731
|
sourceMessageId: row.sourceMessageId,
|
|
@@ -42683,7 +42772,7 @@ var enqueueCeoFollowupFromMailbox = (message) => {
|
|
|
42683
42772
|
if (!message.originUserId || !message.originPlatform) return null;
|
|
42684
42773
|
const db3 = createSqliteDB();
|
|
42685
42774
|
const now = Date.now();
|
|
42686
|
-
const id = `cfu_${(0,
|
|
42775
|
+
const id = `cfu_${(0, import_node_crypto6.randomUUID)().slice(0, 12)}`;
|
|
42687
42776
|
db3.prepare(`
|
|
42688
42777
|
INSERT INTO ceo_followups (
|
|
42689
42778
|
id,
|
|
@@ -43013,7 +43102,7 @@ var recordMailboxReceivedAgentEvent = (msg) => {
|
|
|
43013
43102
|
};
|
|
43014
43103
|
var sendMessage2 = (fromMailboxId, toMailboxId, content, options) => {
|
|
43015
43104
|
const db3 = createSqliteDB();
|
|
43016
|
-
const id = (0,
|
|
43105
|
+
const id = (0, import_node_crypto7.randomUUID)().slice(0, 8);
|
|
43017
43106
|
const threadId = options?.threadId || id;
|
|
43018
43107
|
const workItemContext = resolveWorkItemContext(fromMailboxId, toMailboxId, id, options);
|
|
43019
43108
|
const stmt = db3.prepare(`insert into mailbox (
|
|
@@ -43156,7 +43245,7 @@ var departmentCreate = {
|
|
|
43156
43245
|
return `[departmentCreate] \u4E0D\u5B58\u5728 id=${sourceGoalId} \u7684\u76EE\u6807`;
|
|
43157
43246
|
}
|
|
43158
43247
|
let departmentDefinition = {
|
|
43159
|
-
id: (0,
|
|
43248
|
+
id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
|
|
43160
43249
|
name,
|
|
43161
43250
|
charter,
|
|
43162
43251
|
sourceGoalId,
|
|
@@ -43423,7 +43512,7 @@ var departmentList = {
|
|
|
43423
43512
|
};
|
|
43424
43513
|
|
|
43425
43514
|
// src/tools/tools/department/DepartmentMemberCreate.ts
|
|
43426
|
-
var
|
|
43515
|
+
var import_node_crypto9 = require("node:crypto");
|
|
43427
43516
|
var DESCRIPTION24 = `
|
|
43428
43517
|
\u521B\u5EFA\u90E8\u95E8\u6210\u5458\u3002
|
|
43429
43518
|
|
|
@@ -43489,7 +43578,7 @@ var departmentMemberCreate = {
|
|
|
43489
43578
|
}
|
|
43490
43579
|
}
|
|
43491
43580
|
let departmentMember = {
|
|
43492
|
-
id: (0,
|
|
43581
|
+
id: (0, import_node_crypto9.randomUUID)().slice(0, 8),
|
|
43493
43582
|
name,
|
|
43494
43583
|
departmentId: department.id,
|
|
43495
43584
|
mailBoxId: getMailBoxId(department.name, name),
|
|
@@ -43680,7 +43769,7 @@ ${replies}`;
|
|
|
43680
43769
|
// src/department/learning.ts
|
|
43681
43770
|
var import_node_fs4 = require("node:fs");
|
|
43682
43771
|
var import_node_path13 = __toESM(require("node:path"));
|
|
43683
|
-
var
|
|
43772
|
+
var import_node_crypto10 = require("node:crypto");
|
|
43684
43773
|
|
|
43685
43774
|
// src/skill/SkillValidator.ts
|
|
43686
43775
|
var import_node_fs3 = require("node:fs");
|
|
@@ -43918,7 +44007,7 @@ var listDepartmentMemories = (departmentName) => {
|
|
|
43918
44007
|
var createDepartmentMemory = (departmentName, input) => {
|
|
43919
44008
|
const now = Date.now();
|
|
43920
44009
|
const memory = {
|
|
43921
|
-
id: (0,
|
|
44010
|
+
id: (0, import_node_crypto10.randomUUID)().slice(0, 8),
|
|
43922
44011
|
departmentName,
|
|
43923
44012
|
title: input.title,
|
|
43924
44013
|
content: input.content,
|
|
@@ -43969,7 +44058,7 @@ ${formatSkillValidationIssues(validation)}`);
|
|
|
43969
44058
|
}
|
|
43970
44059
|
const now = Date.now();
|
|
43971
44060
|
const skill = {
|
|
43972
|
-
id: (0,
|
|
44061
|
+
id: (0, import_node_crypto10.randomUUID)().slice(0, 8),
|
|
43973
44062
|
departmentName,
|
|
43974
44063
|
skillName: input.skillName,
|
|
43975
44064
|
description: input.description,
|
|
@@ -44021,7 +44110,7 @@ var createDepartmentProposal = (input) => {
|
|
|
44021
44110
|
const records = readJsonArray(proposalsPath());
|
|
44022
44111
|
const proposal = {
|
|
44023
44112
|
...input,
|
|
44024
|
-
id: (0,
|
|
44113
|
+
id: (0, import_node_crypto10.randomUUID)().slice(0, 8),
|
|
44025
44114
|
status: "pending",
|
|
44026
44115
|
createdAt: Date.now()
|
|
44027
44116
|
};
|
|
@@ -44356,7 +44445,7 @@ var mailboxFollowup = {
|
|
|
44356
44445
|
|
|
44357
44446
|
// src/tools/tools/Bash.ts
|
|
44358
44447
|
var import_node_child_process = require("node:child_process");
|
|
44359
|
-
var
|
|
44448
|
+
var import_node_crypto11 = require("node:crypto");
|
|
44360
44449
|
var import_node_fs5 = require("node:fs");
|
|
44361
44450
|
var DESCRIPTION29 = `\u5728\u7CFB\u7EDF shell \u4E2D\u6267\u884C\u547D\u4EE4\u3002
|
|
44362
44451
|
|
|
@@ -44560,7 +44649,7 @@ var bashTool = {
|
|
|
44560
44649
|
...options,
|
|
44561
44650
|
stdio: ["pipe", "pipe", "pipe"]
|
|
44562
44651
|
});
|
|
44563
|
-
const id = (0,
|
|
44652
|
+
const id = (0, import_node_crypto11.randomUUID)().slice(0, 8);
|
|
44564
44653
|
const session = {
|
|
44565
44654
|
id,
|
|
44566
44655
|
command,
|
|
@@ -44658,10 +44747,183 @@ var sendFile = {
|
|
|
44658
44747
|
}
|
|
44659
44748
|
};
|
|
44660
44749
|
|
|
44750
|
+
// src/runtime/activity.ts
|
|
44751
|
+
async function reportRuntimeActivity(input) {
|
|
44752
|
+
const baseUrl = process.env.DUCLAW_CONTROL_PLANE_BASE_URL?.replace(/\/$/, "");
|
|
44753
|
+
const token = process.env.DUCLAW_CONTROL_PLANE_METERING_TOKEN;
|
|
44754
|
+
const tenantId = process.env.DUCLAW_TENANT_ID;
|
|
44755
|
+
if (!baseUrl || !token || !tenantId) return;
|
|
44756
|
+
try {
|
|
44757
|
+
const response = await fetch(`${baseUrl}/internal/runtime/activity`, {
|
|
44758
|
+
method: "POST",
|
|
44759
|
+
signal: AbortSignal.timeout(2500),
|
|
44760
|
+
headers: {
|
|
44761
|
+
authorization: `Bearer ${token}`,
|
|
44762
|
+
"content-type": "application/json"
|
|
44763
|
+
},
|
|
44764
|
+
body: JSON.stringify({
|
|
44765
|
+
tenantId,
|
|
44766
|
+
kind: input.kind,
|
|
44767
|
+
status: input.status,
|
|
44768
|
+
toolName: input.toolName,
|
|
44769
|
+
toolCallId: input.toolCallId ?? null,
|
|
44770
|
+
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
44771
|
+
metadata: input.metadata ?? {}
|
|
44772
|
+
})
|
|
44773
|
+
});
|
|
44774
|
+
if (!response.ok) {
|
|
44775
|
+
console.warn(`[runtime-activity] \u4E0A\u62A5\u5931\u8D25: tool=${input.toolName} status=${input.status} http=${response.status}`);
|
|
44776
|
+
}
|
|
44777
|
+
} catch (err) {
|
|
44778
|
+
console.warn(`[runtime-activity] \u4E0A\u62A5\u5F02\u5E38: tool=${input.toolName} status=${input.status} error=${err.message}`);
|
|
44779
|
+
}
|
|
44780
|
+
}
|
|
44781
|
+
|
|
44782
|
+
// src/runtime/plugins/activityToolHook.ts
|
|
44783
|
+
var createRuntimeActivityToolHookPlugin = () => ({
|
|
44784
|
+
id: "runtime-activity",
|
|
44785
|
+
priority: 0,
|
|
44786
|
+
async preToolUse(ctx) {
|
|
44787
|
+
await reportRuntimeActivity({
|
|
44788
|
+
kind: "tool_use",
|
|
44789
|
+
toolName: ctx.toolName,
|
|
44790
|
+
status: "started",
|
|
44791
|
+
toolCallId: ctx.toolCallId,
|
|
44792
|
+
metadata: activityMetadata(ctx)
|
|
44793
|
+
});
|
|
44794
|
+
},
|
|
44795
|
+
async afterToolUse(ctx) {
|
|
44796
|
+
await reportRuntimeActivity({
|
|
44797
|
+
kind: "tool_use",
|
|
44798
|
+
toolName: ctx.toolName,
|
|
44799
|
+
status: "completed",
|
|
44800
|
+
toolCallId: ctx.toolCallId,
|
|
44801
|
+
metadata: activityMetadata(ctx)
|
|
44802
|
+
});
|
|
44803
|
+
},
|
|
44804
|
+
async onToolUseError(ctx) {
|
|
44805
|
+
await reportRuntimeActivity({
|
|
44806
|
+
kind: "tool_use",
|
|
44807
|
+
toolName: ctx.toolName,
|
|
44808
|
+
status: "failed",
|
|
44809
|
+
toolCallId: ctx.toolCallId,
|
|
44810
|
+
metadata: {
|
|
44811
|
+
...activityMetadata(ctx),
|
|
44812
|
+
error: ctx.error?.message
|
|
44813
|
+
}
|
|
44814
|
+
});
|
|
44815
|
+
}
|
|
44816
|
+
});
|
|
44817
|
+
function activityMetadata(ctx) {
|
|
44818
|
+
return {
|
|
44819
|
+
platform: ctx.userRequest?.platform,
|
|
44820
|
+
requestId: ctx.userRequest?.requestId,
|
|
44821
|
+
departmentAgentId: ctx.userRequest?.departmentAgentId
|
|
44822
|
+
};
|
|
44823
|
+
}
|
|
44824
|
+
|
|
44825
|
+
// src/runtime/plugins/saasCreditToolHook.ts
|
|
44826
|
+
var DEFAULT_WEB_SEARCH_NUM_RESULTS = 8;
|
|
44827
|
+
var createSaasCreditToolHookPlugin = () => ({
|
|
44828
|
+
id: "saas-credit",
|
|
44829
|
+
priority: 100,
|
|
44830
|
+
async afterToolUse(ctx) {
|
|
44831
|
+
const usage = meteredToolUsage(ctx);
|
|
44832
|
+
if (!usage) return;
|
|
44833
|
+
const baseUrl = process.env.DUCLAW_CONTROL_PLANE_BASE_URL?.replace(/\/$/, "");
|
|
44834
|
+
const token = process.env.DUCLAW_CONTROL_PLANE_METERING_TOKEN;
|
|
44835
|
+
const tenantId = process.env.DUCLAW_TENANT_ID;
|
|
44836
|
+
if (!baseUrl || !token || !tenantId) {
|
|
44837
|
+
if (process.env.NODE_ENV === "production" || process.env.DUCLAW_RUNTIME_PROVIDER) {
|
|
44838
|
+
throw new Error("[saas-credit] runtime metering is not configured");
|
|
44839
|
+
}
|
|
44840
|
+
return;
|
|
44841
|
+
}
|
|
44842
|
+
const response = await fetch(`${baseUrl}/internal/metering/tool-usage`, {
|
|
44843
|
+
method: "POST",
|
|
44844
|
+
signal: AbortSignal.timeout(5e3),
|
|
44845
|
+
headers: {
|
|
44846
|
+
authorization: `Bearer ${token}`,
|
|
44847
|
+
"content-type": "application/json"
|
|
44848
|
+
},
|
|
44849
|
+
body: JSON.stringify({
|
|
44850
|
+
tenantId,
|
|
44851
|
+
toolName: ctx.toolName,
|
|
44852
|
+
toolCallId: ctx.toolCallId,
|
|
44853
|
+
requestId: ctx.userRequest?.requestId ?? null,
|
|
44854
|
+
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
44855
|
+
...usage,
|
|
44856
|
+
metadata: {
|
|
44857
|
+
platform: ctx.userRequest?.platform ?? null,
|
|
44858
|
+
departmentAgentId: ctx.userRequest?.departmentAgentId ?? null,
|
|
44859
|
+
input: sanitizedWebSearchInput(ctx.input)
|
|
44860
|
+
}
|
|
44861
|
+
})
|
|
44862
|
+
});
|
|
44863
|
+
const body = await parseJson2(response);
|
|
44864
|
+
const status = body?.result?.status;
|
|
44865
|
+
if (response.status === 402 || status === "credit_exhausted") {
|
|
44866
|
+
throw new UserRecoverableToolError(
|
|
44867
|
+
"credit_exhausted",
|
|
44868
|
+
"Credit \u4F59\u989D\u4E0D\u8DB3\uFF0C\u65E0\u6CD5\u5B8C\u6210\u672C\u6B21\u7F51\u9875\u641C\u7D22\u3002\u8BF7\u5148\u5145\u503C\u6216\u4F7F\u7528\u6FC0\u6D3B\u7801\u589E\u52A0 Credit\u3002",
|
|
44869
|
+
`[saas-credit] ${ctx.toolName} credit exhausted`
|
|
44870
|
+
);
|
|
44871
|
+
}
|
|
44872
|
+
if (!response.ok || status === "failed") {
|
|
44873
|
+
throw new Error(`[saas-credit] tool metering failed: ${body?.error ?? body?.message ?? status ?? response.status}`);
|
|
44874
|
+
}
|
|
44875
|
+
}
|
|
44876
|
+
});
|
|
44877
|
+
function meteredToolUsage(ctx) {
|
|
44878
|
+
if (ctx.toolName !== "websearch") return null;
|
|
44879
|
+
if (isWebSearchErrorResult(ctx.resultText)) return null;
|
|
44880
|
+
return {
|
|
44881
|
+
meterType: "web.content_retrieval",
|
|
44882
|
+
provider: "exa",
|
|
44883
|
+
unit: "content",
|
|
44884
|
+
quantity: normalizeNumResults(ctx.input.numResults)
|
|
44885
|
+
};
|
|
44886
|
+
}
|
|
44887
|
+
function normalizeNumResults(value) {
|
|
44888
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return DEFAULT_WEB_SEARCH_NUM_RESULTS;
|
|
44889
|
+
return Math.max(1, Math.floor(value));
|
|
44890
|
+
}
|
|
44891
|
+
function isWebSearchErrorResult(result) {
|
|
44892
|
+
if (!result) return true;
|
|
44893
|
+
return /Web search (请求失败|请求超时|执行失败)|未找到搜索结果/.test(result);
|
|
44894
|
+
}
|
|
44895
|
+
function sanitizedWebSearchInput(input) {
|
|
44896
|
+
return {
|
|
44897
|
+
query: typeof input.query === "string" ? input.query.slice(0, 500) : null,
|
|
44898
|
+
numResults: normalizeNumResults(input.numResults),
|
|
44899
|
+
livecrawl: typeof input.livecrawl === "string" ? input.livecrawl : null,
|
|
44900
|
+
type: typeof input.type === "string" ? input.type : null,
|
|
44901
|
+
contextMaxCharacters: typeof input.contextMaxCharacters === "number" ? input.contextMaxCharacters : null
|
|
44902
|
+
};
|
|
44903
|
+
}
|
|
44904
|
+
async function parseJson2(response) {
|
|
44905
|
+
try {
|
|
44906
|
+
return await response.json();
|
|
44907
|
+
} catch {
|
|
44908
|
+
return null;
|
|
44909
|
+
}
|
|
44910
|
+
}
|
|
44911
|
+
|
|
44912
|
+
// src/runtime/plugins/index.ts
|
|
44913
|
+
function createDefaultToolHookPlugins(extra = []) {
|
|
44914
|
+
return [
|
|
44915
|
+
createSaasCreditToolHookPlugin(),
|
|
44916
|
+
createRuntimeActivityToolHookPlugin(),
|
|
44917
|
+
...extra
|
|
44918
|
+
];
|
|
44919
|
+
}
|
|
44920
|
+
|
|
44661
44921
|
// src/tools/index.ts
|
|
44662
|
-
var createDefaultTools = (bg) => {
|
|
44922
|
+
var createDefaultTools = (bg, hookPlugins = []) => {
|
|
44663
44923
|
const registry2 = createToolRegistry();
|
|
44664
|
-
const executor = createToolExecutor(registry2
|
|
44924
|
+
const executor = createToolExecutor(registry2, {
|
|
44925
|
+
hookPlugins: createDefaultToolHookPlugins(hookPlugins)
|
|
44926
|
+
});
|
|
44665
44927
|
registerTool(registry2, dateTool);
|
|
44666
44928
|
registerTool(registry2, bashTool);
|
|
44667
44929
|
registerTool(registry2, globTool);
|
|
@@ -45141,7 +45403,7 @@ var readDreamHistoryLimit = () => {
|
|
|
45141
45403
|
var import_node_fs6 = require("node:fs");
|
|
45142
45404
|
var import_node_os2 = require("node:os");
|
|
45143
45405
|
var import_node_path14 = require("node:path");
|
|
45144
|
-
var
|
|
45406
|
+
var import_node_crypto12 = require("node:crypto");
|
|
45145
45407
|
var SkillForgeEngine = class {
|
|
45146
45408
|
proposalStorage;
|
|
45147
45409
|
draftRoot;
|
|
@@ -45175,7 +45437,7 @@ ${formatSkillValidationIssues(validation)}`);
|
|
|
45175
45437
|
if (pending.some((p) => p.skillName === skillName)) {
|
|
45176
45438
|
return null;
|
|
45177
45439
|
}
|
|
45178
|
-
const id = (0,
|
|
45440
|
+
const id = (0, import_node_crypto12.randomBytes)(4).toString("hex");
|
|
45179
45441
|
const draftDir = (0, import_node_path14.join)(this.draftRoot, userId, id);
|
|
45180
45442
|
(0, import_node_fs6.mkdirSync)(draftDir, { recursive: true });
|
|
45181
45443
|
(0, import_node_fs6.writeFileSync)((0, import_node_path14.join)(draftDir, "SKILL.md"), skillMd, "utf-8");
|
|
@@ -45457,7 +45719,7 @@ var skillForgeDrop = (engine) => ({
|
|
|
45457
45719
|
});
|
|
45458
45720
|
|
|
45459
45721
|
// src/memory/MemoryEngine.ts
|
|
45460
|
-
var
|
|
45722
|
+
var import_node_crypto13 = require("node:crypto");
|
|
45461
45723
|
var MemoryEngine = class {
|
|
45462
45724
|
storage;
|
|
45463
45725
|
recallIndexStorage;
|
|
@@ -45485,7 +45747,7 @@ var MemoryEngine = class {
|
|
|
45485
45747
|
}
|
|
45486
45748
|
const now = Date.now();
|
|
45487
45749
|
const memory = {
|
|
45488
|
-
id: (0,
|
|
45750
|
+
id: (0, import_node_crypto13.randomBytes)(4).toString("hex"),
|
|
45489
45751
|
userId,
|
|
45490
45752
|
title,
|
|
45491
45753
|
content,
|
|
@@ -46137,13 +46399,13 @@ var COMPANY_VALUES_PROMPT = `<\u516C\u53F8\u5171\u540C\u4FE1\u5FF5>
|
|
|
46137
46399
|
</\u516C\u53F8\u5171\u540C\u4FE1\u5FF5>`;
|
|
46138
46400
|
|
|
46139
46401
|
// src/agent/outboundDedup.ts
|
|
46140
|
-
var
|
|
46402
|
+
var import_node_crypto14 = require("node:crypto");
|
|
46141
46403
|
var DEFAULT_WINDOW_MS = 15e3;
|
|
46142
46404
|
var recentSends = /* @__PURE__ */ new Map();
|
|
46143
46405
|
var lastSweepAt = 0;
|
|
46144
46406
|
var normalize3 = (text2) => text2.replace(/\s+/g, " ").trim();
|
|
46145
46407
|
var keyFor = (userId, normalized) => {
|
|
46146
|
-
const hash = (0,
|
|
46408
|
+
const hash = (0, import_node_crypto14.createHash)("sha1").update(normalized).digest("hex");
|
|
46147
46409
|
return `${userId}::${hash}`;
|
|
46148
46410
|
};
|
|
46149
46411
|
var sweep = (now, windowMs) => {
|
|
@@ -46181,7 +46443,7 @@ var isAbortError2 = (error) => {
|
|
|
46181
46443
|
return error.name === "AbortError" || error.message.includes("aborted") || error.message.includes("AbortError");
|
|
46182
46444
|
};
|
|
46183
46445
|
var llmRequestIdForTurn = (request, messages, system, tools) => {
|
|
46184
|
-
const hash = (0,
|
|
46446
|
+
const hash = (0, import_node_crypto15.createHash)("sha256").update(request.requestId).update("\0").update(system).update("\0").update(JSON.stringify(messages)).update("\0").update(JSON.stringify(tools.map((tool) => tool.name).sort())).digest("hex").slice(0, 40);
|
|
46185
46447
|
return `dreq_${hash}`;
|
|
46186
46448
|
};
|
|
46187
46449
|
var getDefaultAgentConfig = (tools, systemPrompt) => {
|
|
@@ -46376,7 +46638,9 @@ ${getSkillMeta()}
|
|
|
46376
46638
|
} else {
|
|
46377
46639
|
finalTools = tools;
|
|
46378
46640
|
const toolRegistry = createToolRegistry();
|
|
46379
|
-
const executor = createToolExecutor(toolRegistry
|
|
46641
|
+
const executor = createToolExecutor(toolRegistry, {
|
|
46642
|
+
hookPlugins: createDefaultToolHookPlugins()
|
|
46643
|
+
});
|
|
46380
46644
|
for (let tool of finalTools) {
|
|
46381
46645
|
registerTool(toolRegistry, tool);
|
|
46382
46646
|
}
|
|
@@ -47070,7 +47334,9 @@ var updateJobLastRunTime = (jobId) => {
|
|
|
47070
47334
|
};
|
|
47071
47335
|
var getCronTools = () => {
|
|
47072
47336
|
const registry2 = createToolRegistry();
|
|
47073
|
-
const executor = createToolExecutor(registry2
|
|
47337
|
+
const executor = createToolExecutor(registry2, {
|
|
47338
|
+
hookPlugins: createDefaultToolHookPlugins()
|
|
47339
|
+
});
|
|
47074
47340
|
registerTool(registry2, dateTool);
|
|
47075
47341
|
registerTool(registry2, globTool);
|
|
47076
47342
|
registerTool(registry2, grepTool);
|
|
@@ -48117,7 +48383,9 @@ var startMailboxPoller = (intervalMs = 3e3) => {
|
|
|
48117
48383
|
};
|
|
48118
48384
|
var createDepartmentAgentTools = () => {
|
|
48119
48385
|
const registry2 = createToolRegistry();
|
|
48120
|
-
const executor = createToolExecutor(registry2
|
|
48386
|
+
const executor = createToolExecutor(registry2, {
|
|
48387
|
+
hookPlugins: createDefaultToolHookPlugins()
|
|
48388
|
+
});
|
|
48121
48389
|
registerTool(registry2, dateTool);
|
|
48122
48390
|
registerTool(registry2, bashTool);
|
|
48123
48391
|
registerTool(registry2, globTool);
|
|
@@ -48255,7 +48523,9 @@ ${workspacePath ? `
|
|
|
48255
48523
|
} else {
|
|
48256
48524
|
finalTools = tools;
|
|
48257
48525
|
const toolRegistry = createToolRegistry();
|
|
48258
|
-
const executor = createToolExecutor(toolRegistry
|
|
48526
|
+
const executor = createToolExecutor(toolRegistry, {
|
|
48527
|
+
hookPlugins: createDefaultToolHookPlugins()
|
|
48528
|
+
});
|
|
48259
48529
|
for (let tool of finalTools) {
|
|
48260
48530
|
registerTool(toolRegistry, tool);
|
|
48261
48531
|
}
|
|
@@ -53173,7 +53443,7 @@ var systemRoutes = new Hono2();
|
|
|
53173
53443
|
var startTime = Date.now();
|
|
53174
53444
|
systemRoutes.get("/system/info", (c) => {
|
|
53175
53445
|
return c.json({
|
|
53176
|
-
version: true ? "1.9.
|
|
53446
|
+
version: true ? "1.9.5" : "unknown",
|
|
53177
53447
|
uptime: Math.floor((Date.now() - startTime) / 1e3),
|
|
53178
53448
|
env: process.env.NODE_ENV || "development",
|
|
53179
53449
|
nodeVersion: process.version
|
|
@@ -53181,7 +53451,7 @@ systemRoutes.get("/system/info", (c) => {
|
|
|
53181
53451
|
});
|
|
53182
53452
|
|
|
53183
53453
|
// src/server/routes/mobile.ts
|
|
53184
|
-
var
|
|
53454
|
+
var import_node_crypto16 = require("node:crypto");
|
|
53185
53455
|
var import_promises12 = require("node:fs/promises");
|
|
53186
53456
|
var import_node_path16 = __toESM(require("node:path"));
|
|
53187
53457
|
var mobileRoutes = new Hono2();
|
|
@@ -53285,7 +53555,7 @@ mobileRoutes.post("/mobile/attachments", async (c) => {
|
|
|
53285
53555
|
const fileName = sanitizeFileName(body.fileName || `attachment-${Date.now()}`);
|
|
53286
53556
|
const mimeType = body.mimeType || "application/octet-stream";
|
|
53287
53557
|
const type = inferAttachmentType2(mimeType, fileName);
|
|
53288
|
-
const attachmentId = (0,
|
|
53558
|
+
const attachmentId = (0, import_node_crypto16.randomUUID)();
|
|
53289
53559
|
const buffer = Buffer.from(dataBase64, "base64");
|
|
53290
53560
|
const dir = import_node_path16.default.join(getDuclawWorkspaceDir(), mobileUserId, "mobile", type === "image" ? "images" : "files");
|
|
53291
53561
|
await (0, import_promises12.mkdir)(dir, { recursive: true });
|
|
@@ -53317,7 +53587,7 @@ mobileRoutes.post("/mobile/messages", async (c) => {
|
|
|
53317
53587
|
}
|
|
53318
53588
|
const mobileUserId = resolveMobileUserId(body, c.req.header("x-user-id"));
|
|
53319
53589
|
const threadId = resolveThreadId(body.goalId, mobileUserId);
|
|
53320
|
-
const requestId = body.clientMessageId?.trim() || (0,
|
|
53590
|
+
const requestId = body.clientMessageId?.trim() || (0, import_node_crypto16.randomUUID)();
|
|
53321
53591
|
const agentText = body.contextText?.trim() || text2;
|
|
53322
53592
|
const attachmentContent = buildContentWithAttachments(agentText, attachments);
|
|
53323
53593
|
const content = buildGoalPrompt(body.goalId, attachmentContent.content);
|