duclaw-cli 1.8.2 → 1.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.js +155 -43
- package/dist/main.js +1 -1
- package/dist/web/assets/{index-irglpeKE.js → index-CJCUJ0DH.js} +1 -1
- package/dist/web/assets/index-tSI9zUzw.css +1 -0
- package/dist/web/index.html +2 -2
- package/dist/worker-main.js +1 -1
- package/package.json +1 -1
- package/dist/web/assets/index-DAfUZGs6.css +0 -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.8.
|
|
30245
|
+
console.log(`duclaw-cli v${true ? "1.8.3" : "unknown"}`);
|
|
30246
30246
|
}
|
|
30247
30247
|
function getDuclawTemplate() {
|
|
30248
30248
|
return {
|
|
@@ -45312,10 +45312,24 @@ var executeJob = async (job) => {
|
|
|
45312
45312
|
const resultFilePath = saveResultToFile(job, result);
|
|
45313
45313
|
console.log(`[cron\u6267\u884C\u5B8C\u6210] \u5B9A\u65F6\u4EFB\u52A1\u6267\u884C\u7ED3\u679C: ${resultFilePath}`);
|
|
45314
45314
|
updateJobLastRunTime(job.id);
|
|
45315
|
+
return { ok: true, resultFilePath };
|
|
45315
45316
|
} catch (error) {
|
|
45316
|
-
|
|
45317
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
45318
|
+
console.error(`[cron] \u4EFB\u52A1\u6267\u884C\u5931\u8D25: ${job.id} - ${message}`);
|
|
45319
|
+
return { ok: false, error: message };
|
|
45317
45320
|
}
|
|
45318
45321
|
};
|
|
45322
|
+
var runJobById = async (jobId) => {
|
|
45323
|
+
const job = listJobs().find((item) => item.id === jobId);
|
|
45324
|
+
if (!job) {
|
|
45325
|
+
return { ok: false, error: "job_not_found" };
|
|
45326
|
+
}
|
|
45327
|
+
if (!job.enabled) {
|
|
45328
|
+
return { ok: false, error: "job_disabled", job };
|
|
45329
|
+
}
|
|
45330
|
+
const result = await executeJob(job);
|
|
45331
|
+
return { ...result, job };
|
|
45332
|
+
};
|
|
45319
45333
|
var executeAgentJob = async (job) => {
|
|
45320
45334
|
const { registry: registry2, executor } = getCronTools();
|
|
45321
45335
|
const tools = getAllTools(registry2);
|
|
@@ -49998,6 +50012,23 @@ cronRoutes.get("/cron/jobs/:id/history", (c) => {
|
|
|
49998
50012
|
return c.json({ error: err.message || "Failed to get job history" }, 500);
|
|
49999
50013
|
}
|
|
50000
50014
|
});
|
|
50015
|
+
cronRoutes.post("/cron/jobs/:id/run", async (c) => {
|
|
50016
|
+
const id = c.req.param("id");
|
|
50017
|
+
try {
|
|
50018
|
+
const result = await runJobById(id);
|
|
50019
|
+
if (!result.ok) {
|
|
50020
|
+
const status = result.error === "job_not_found" ? 404 : 400;
|
|
50021
|
+
return c.json({ error: result.error || "Failed to run job" }, status);
|
|
50022
|
+
}
|
|
50023
|
+
return c.json({
|
|
50024
|
+
ok: true,
|
|
50025
|
+
jobId: result.job?.id ?? id,
|
|
50026
|
+
resultFilePath: result.resultFilePath
|
|
50027
|
+
});
|
|
50028
|
+
} catch (err) {
|
|
50029
|
+
return c.json({ error: err.message || "Failed to run job" }, 500);
|
|
50030
|
+
}
|
|
50031
|
+
});
|
|
50001
50032
|
|
|
50002
50033
|
// src/server/routes/mailbox.ts
|
|
50003
50034
|
var mailboxRoutes = new Hono2();
|
|
@@ -50276,7 +50307,16 @@ var extractMemoryUserIdsFromKeys = (keys) => {
|
|
|
50276
50307
|
};
|
|
50277
50308
|
var collectCompactSummaries = async (userId) => {
|
|
50278
50309
|
if (isFileBackedRuntime()) {
|
|
50279
|
-
|
|
50310
|
+
const { compactSummaryStorage: compactSummaryStorage2 } = getSharedDeps();
|
|
50311
|
+
const records2 = [];
|
|
50312
|
+
const prefix2 = `agent:compact:summary:${userId}:`;
|
|
50313
|
+
for (const key of extractFileBackedStorageKeysForTest(getDuclawDataDir())) {
|
|
50314
|
+
if (!key.startsWith(prefix2)) continue;
|
|
50315
|
+
const logicalKey = key.startsWith("agent:") ? key.slice("agent:".length) : key;
|
|
50316
|
+
const value = await compactSummaryStorage2.get(logicalKey);
|
|
50317
|
+
if (value?.length) records2.push(...value);
|
|
50318
|
+
}
|
|
50319
|
+
return records2.sort((a, b) => b.createdAt - a.createdAt);
|
|
50280
50320
|
}
|
|
50281
50321
|
const client2 = await getRedisClient();
|
|
50282
50322
|
const { compactSummaryStorage } = getSharedDeps();
|
|
@@ -50291,6 +50331,61 @@ var collectCompactSummaries = async (userId) => {
|
|
|
50291
50331
|
}
|
|
50292
50332
|
return records.sort((a, b) => b.createdAt - a.createdAt);
|
|
50293
50333
|
};
|
|
50334
|
+
var isMailboxScopedUserId = (userId) => userId === "manager" || userId.includes("::") || userId.startsWith("cron-") || userId.startsWith("kanban:goal:");
|
|
50335
|
+
var collectManagerRelatedUserIds = (userId) => {
|
|
50336
|
+
if (isMailboxScopedUserId(userId)) return [userId];
|
|
50337
|
+
try {
|
|
50338
|
+
const db3 = createSqliteDB();
|
|
50339
|
+
const rows = db3.prepare(
|
|
50340
|
+
`SELECT DISTINCT to_mailbox_id AS toMailboxId, from_mailbox_id AS fromMailboxId
|
|
50341
|
+
FROM mailbox
|
|
50342
|
+
WHERE origin_user_id = ?
|
|
50343
|
+
ORDER BY to_mailbox_id ASC, from_mailbox_id ASC`
|
|
50344
|
+
).all(userId);
|
|
50345
|
+
const ids = /* @__PURE__ */ new Set([userId]);
|
|
50346
|
+
for (const row of rows) {
|
|
50347
|
+
addPlausibleUserId(ids, row.toMailboxId || void 0);
|
|
50348
|
+
addPlausibleUserId(ids, row.fromMailboxId || void 0);
|
|
50349
|
+
}
|
|
50350
|
+
ids.delete("manager");
|
|
50351
|
+
return Array.from(ids);
|
|
50352
|
+
} catch (err) {
|
|
50353
|
+
console.warn(`[memoryRoutes] \u83B7\u53D6 Main Manager \u5173\u8054\u4E0A\u4E0B\u6587\u5931\u8D25 userId=${userId}: ${err.message}`);
|
|
50354
|
+
return [userId];
|
|
50355
|
+
}
|
|
50356
|
+
};
|
|
50357
|
+
var collectMemoryScopeUserIds = (userId) => collectManagerRelatedUserIds(userId);
|
|
50358
|
+
var aggregateMemorySummaries = async (userId, localConversationUserIds) => {
|
|
50359
|
+
const { memoryEngine, dreamStorage, dreamStateStorage, topicStorage } = getSharedDeps();
|
|
50360
|
+
const relatedUserIds = collectMemoryScopeUserIds(userId);
|
|
50361
|
+
const details = await Promise.all(relatedUserIds.map(async (scopeUserId) => {
|
|
50362
|
+
const [memories, dreamContent, dreamState, topics] = await Promise.all([
|
|
50363
|
+
memoryEngine.list(scopeUserId),
|
|
50364
|
+
dreamStorage.get(`dream:latest:${scopeUserId}`),
|
|
50365
|
+
dreamStateStorage.get(`dream:state:${scopeUserId}`),
|
|
50366
|
+
topicStorage.get(`topics:${scopeUserId}`)
|
|
50367
|
+
]);
|
|
50368
|
+
return {
|
|
50369
|
+
userId: scopeUserId,
|
|
50370
|
+
memoryCount: memories.length,
|
|
50371
|
+
hasDream: !!dreamContent,
|
|
50372
|
+
hasConversation: (topics?.length ?? 0) > 0 || localConversationUserIds.has(scopeUserId),
|
|
50373
|
+
lastDreamAt: dreamState?.lastDreamAt ?? null,
|
|
50374
|
+
lastActivityAt: dreamState?.lastActivityAt ?? null
|
|
50375
|
+
};
|
|
50376
|
+
}));
|
|
50377
|
+
const memoryCount = details.reduce((sum, detail) => sum + detail.memoryCount, 0);
|
|
50378
|
+
return {
|
|
50379
|
+
userId,
|
|
50380
|
+
memoryCount,
|
|
50381
|
+
hasMemory: memoryCount > 0,
|
|
50382
|
+
hasDream: details.some((detail) => detail.hasDream),
|
|
50383
|
+
hasConversation: details.some((detail) => detail.hasConversation),
|
|
50384
|
+
lastDreamAt: Math.max(0, ...details.map((detail) => detail.lastDreamAt ?? 0)) || null,
|
|
50385
|
+
lastActivityAt: Math.max(0, ...details.map((detail) => detail.lastActivityAt ?? 0)) || null,
|
|
50386
|
+
relatedUserIds: relatedUserIds.length > 1 ? relatedUserIds : void 0
|
|
50387
|
+
};
|
|
50388
|
+
};
|
|
50294
50389
|
var collectUserIds = async () => {
|
|
50295
50390
|
const userIds = /* @__PURE__ */ new Set();
|
|
50296
50391
|
const localConversationUserIds = collectLocalConversationUserIds();
|
|
@@ -50312,26 +50407,10 @@ var collectUserIds = async () => {
|
|
|
50312
50407
|
var memoryRoutes = new Hono2();
|
|
50313
50408
|
memoryRoutes.get("/memory/users", async (c) => {
|
|
50314
50409
|
try {
|
|
50315
|
-
const { memoryEngine, dreamStorage, dreamStateStorage, topicStorage } = getSharedDeps();
|
|
50316
50410
|
const { userIds, localConversationUserIds } = await collectUserIds();
|
|
50317
|
-
const summaries = await Promise.all(userIds.map(
|
|
50318
|
-
|
|
50319
|
-
|
|
50320
|
-
dreamStorage.get(`dream:latest:${userId}`),
|
|
50321
|
-
dreamStateStorage.get(`dream:state:${userId}`),
|
|
50322
|
-
topicStorage.get(`topics:${userId}`)
|
|
50323
|
-
]);
|
|
50324
|
-
const summary = {
|
|
50325
|
-
userId,
|
|
50326
|
-
memoryCount: memories.length,
|
|
50327
|
-
hasMemory: memories.length > 0,
|
|
50328
|
-
hasDream: !!dreamContent,
|
|
50329
|
-
hasConversation: (topics?.length ?? 0) > 0 || localConversationUserIds.has(userId),
|
|
50330
|
-
lastDreamAt: dreamState?.lastDreamAt ?? null,
|
|
50331
|
-
lastActivityAt: dreamState?.lastActivityAt ?? null
|
|
50332
|
-
};
|
|
50333
|
-
return summary;
|
|
50334
|
-
}));
|
|
50411
|
+
const summaries = await Promise.all(userIds.map(
|
|
50412
|
+
(userId) => aggregateMemorySummaries(userId, localConversationUserIds)
|
|
50413
|
+
));
|
|
50335
50414
|
summaries.sort(
|
|
50336
50415
|
(a, b) => (b.lastActivityAt ?? 0) - (a.lastActivityAt ?? 0) || a.userId.localeCompare(b.userId)
|
|
50337
50416
|
);
|
|
@@ -50345,7 +50424,9 @@ memoryRoutes.get("/memory", async (c) => {
|
|
|
50345
50424
|
if (!userId) return c.json({ error: "userId is required" }, 400);
|
|
50346
50425
|
try {
|
|
50347
50426
|
const { memoryEngine } = getSharedDeps();
|
|
50348
|
-
const memories = await
|
|
50427
|
+
const memories = (await Promise.all(
|
|
50428
|
+
collectMemoryScopeUserIds(userId).map((scopeUserId) => memoryEngine.list(scopeUserId))
|
|
50429
|
+
)).flat();
|
|
50349
50430
|
return c.json(sortMemories(memories));
|
|
50350
50431
|
} catch (err) {
|
|
50351
50432
|
return c.json({ error: err.message || "Failed to list memories" }, 500);
|
|
@@ -50408,16 +50489,27 @@ memoryRoutes.get("/memory/dream", async (c) => {
|
|
|
50408
50489
|
if (!userId) return c.json({ error: "userId is required" }, 400);
|
|
50409
50490
|
try {
|
|
50410
50491
|
const { dreamStorage, dreamHistoryStorage, dreamStateStorage } = getSharedDeps();
|
|
50411
|
-
const
|
|
50412
|
-
|
|
50413
|
-
|
|
50414
|
-
|
|
50415
|
-
|
|
50492
|
+
const scoped = await Promise.all(collectMemoryScopeUserIds(userId).map(async (scopeUserId) => {
|
|
50493
|
+
const [dreamContent2, dreamHistory2, state2] = await Promise.all([
|
|
50494
|
+
dreamStorage.get(`dream:latest:${scopeUserId}`),
|
|
50495
|
+
dreamHistoryStorage.get(`dream:history:${scopeUserId}`),
|
|
50496
|
+
dreamStateStorage.get(`dream:state:${scopeUserId}`)
|
|
50497
|
+
]);
|
|
50498
|
+
return { userId: scopeUserId, dreamContent: dreamContent2 || "", dreamHistory: dreamHistory2 || [], state: state2 || null };
|
|
50499
|
+
}));
|
|
50500
|
+
const dreamContent = scoped.filter((item) => item.dreamContent.trim()).map((item) => scoped.length > 1 ? `## ${item.userId}
|
|
50501
|
+
${item.dreamContent}` : item.dreamContent).join("\n\n");
|
|
50502
|
+
const dreamHistory = scoped.flatMap((item) => item.dreamHistory.map((entry) => ({
|
|
50503
|
+
...entry,
|
|
50504
|
+
content: scoped.length > 1 ? `[${item.userId}]
|
|
50505
|
+
${entry.content}` : entry.content
|
|
50506
|
+
}))).sort((a, b) => b.createdAt - a.createdAt);
|
|
50507
|
+
const state = scoped.map((item) => item.state).filter((item) => !!item).sort((a, b) => b.lastActivityAt - a.lastActivityAt)[0] ?? null;
|
|
50416
50508
|
return c.json({
|
|
50417
50509
|
userId,
|
|
50418
|
-
dreamContent
|
|
50419
|
-
dreamHistory
|
|
50420
|
-
state
|
|
50510
|
+
dreamContent,
|
|
50511
|
+
dreamHistory,
|
|
50512
|
+
state
|
|
50421
50513
|
});
|
|
50422
50514
|
} catch (err) {
|
|
50423
50515
|
return c.json({ error: err.message || "Failed to get dream summary" }, 500);
|
|
@@ -50427,7 +50519,9 @@ memoryRoutes.get("/memory/compact", async (c) => {
|
|
|
50427
50519
|
const userId = requireUserId(c.req.query("userId"));
|
|
50428
50520
|
if (!userId) return c.json({ error: "userId is required" }, 400);
|
|
50429
50521
|
try {
|
|
50430
|
-
const summaries = await
|
|
50522
|
+
const summaries = (await Promise.all(
|
|
50523
|
+
collectMemoryScopeUserIds(userId).map((scopeUserId) => collectCompactSummaries(scopeUserId))
|
|
50524
|
+
)).flat().sort((a, b) => b.createdAt - a.createdAt);
|
|
50431
50525
|
return c.json({
|
|
50432
50526
|
userId,
|
|
50433
50527
|
summaries
|
|
@@ -50444,19 +50538,25 @@ memoryRoutes.get("/memory/recall", async (c) => {
|
|
|
50444
50538
|
const limit = Math.min(Number(c.req.query("limit")) || 20, 50);
|
|
50445
50539
|
try {
|
|
50446
50540
|
const { recallIndexStorage } = getSharedDeps();
|
|
50541
|
+
const scopeUserIds = collectMemoryScopeUserIds(userId);
|
|
50447
50542
|
if (query) {
|
|
50448
|
-
const
|
|
50543
|
+
const scopedResults = await Promise.all(scopeUserIds.map(
|
|
50544
|
+
(scopeUserId) => searchRecallIndex(recallIndexStorage, scopeUserId, query, date, limit)
|
|
50545
|
+
));
|
|
50546
|
+
const matches = scopedResults.flatMap((result) => result.matches).sort((a, b) => b.score - a.score).slice(0, limit);
|
|
50449
50547
|
return c.json({
|
|
50450
50548
|
userId,
|
|
50451
50549
|
query,
|
|
50452
|
-
total: result.total,
|
|
50453
|
-
entries:
|
|
50550
|
+
total: scopedResults.reduce((sum, result) => sum + result.total, 0),
|
|
50551
|
+
entries: matches.map((match2) => ({
|
|
50454
50552
|
...match2.entry,
|
|
50455
50553
|
score: match2.score
|
|
50456
50554
|
}))
|
|
50457
50555
|
});
|
|
50458
50556
|
}
|
|
50459
|
-
const entries = await
|
|
50557
|
+
const entries = (await Promise.all(
|
|
50558
|
+
scopeUserIds.map((scopeUserId) => recallIndexStorage.get(`recall:index:${scopeUserId}`))
|
|
50559
|
+
)).flatMap((items) => items ?? []);
|
|
50460
50560
|
const filtered = date ? entries.filter((entry) => entry.date === date) : entries;
|
|
50461
50561
|
filtered.sort((a, b) => b.createdAt - a.createdAt);
|
|
50462
50562
|
return c.json({
|
|
@@ -50474,10 +50574,18 @@ memoryRoutes.get("/memory/context", async (c) => {
|
|
|
50474
50574
|
if (!userId) return c.json({ error: "userId is required" }, 400);
|
|
50475
50575
|
try {
|
|
50476
50576
|
const { memoryEngine, dreamStorage } = getSharedDeps();
|
|
50477
|
-
const
|
|
50478
|
-
|
|
50479
|
-
|
|
50480
|
-
|
|
50577
|
+
const scoped = await Promise.all(collectMemoryScopeUserIds(userId).map(async (scopeUserId) => {
|
|
50578
|
+
const [memoryContextBlock2, dreamContent2] = await Promise.all([
|
|
50579
|
+
memoryEngine.buildContextBlock(scopeUserId),
|
|
50580
|
+
dreamStorage.get(`dream:latest:${scopeUserId}`)
|
|
50581
|
+
]);
|
|
50582
|
+
return { userId: scopeUserId, memoryContextBlock: memoryContextBlock2, dreamContent: dreamContent2 };
|
|
50583
|
+
}));
|
|
50584
|
+
const memoryContextBlock = scoped.filter((item) => item.memoryContextBlock.trim()).map((item) => scoped.length > 1 ? `<main-manager-context-source userId="${item.userId}">
|
|
50585
|
+
${item.memoryContextBlock}
|
|
50586
|
+
</main-manager-context-source>` : item.memoryContextBlock).join("\n\n");
|
|
50587
|
+
const dreamContent = scoped.filter((item) => item.dreamContent?.trim()).map((item) => scoped.length > 1 ? `## ${item.userId}
|
|
50588
|
+
${item.dreamContent}` : item.dreamContent).join("\n\n");
|
|
50481
50589
|
const dreamContextBlock = dreamContent ? [
|
|
50482
50590
|
"<memory-context>",
|
|
50483
50591
|
"\u4EE5\u4E0B\u662F\u4F60\u901A\u8FC7\u505A\u68A6\u4FDD\u7559\u7684\u8DE8\u5929\u8BB0\u5FC6\u3002\u8BB0\u4F4F\u8FD9\u4E9B\u4FE1\u606F\uFF0C\u4F46\u4E0D\u8981\u4E3B\u52A8\u63D0\u53CA\u2014\u2014\u9664\u975E\u7528\u6237\u7684\u8BDD\u9898\u76F8\u5173\u3002",
|
|
@@ -50550,7 +50658,7 @@ var systemRoutes = new Hono2();
|
|
|
50550
50658
|
var startTime = Date.now();
|
|
50551
50659
|
systemRoutes.get("/system/info", (c) => {
|
|
50552
50660
|
return c.json({
|
|
50553
|
-
version: true ? "1.8.
|
|
50661
|
+
version: true ? "1.8.3" : "unknown",
|
|
50554
50662
|
uptime: Math.floor((Date.now() - startTime) / 1e3),
|
|
50555
50663
|
env: process.env.NODE_ENV || "development",
|
|
50556
50664
|
nodeVersion: process.version
|
|
@@ -50651,8 +50759,12 @@ async function main() {
|
|
|
50651
50759
|
} else {
|
|
50652
50760
|
console.log(`[main] Core Channel Gateway \u5DF2\u8DF3\u8FC7\uFF0C\u5F53\u524D\u5916\u90E8\u6D88\u606F\u5165\u53E3\u7531 SaaS \u5C42\u63A5\u7BA1`);
|
|
50653
50761
|
}
|
|
50654
|
-
|
|
50655
|
-
|
|
50762
|
+
if (process.env.DUCLAW_CRON_SCHEDULER === "saas") {
|
|
50763
|
+
console.log(`[main] \u5B9A\u65F6\u4EFB\u52A1\u8C03\u5EA6\u5668\u5DF2\u8DF3\u8FC7\uFF0C\u5F53\u524D\u7531 SaaS \u5C42\u63A5\u7BA1`);
|
|
50764
|
+
} else {
|
|
50765
|
+
startScheduler();
|
|
50766
|
+
console.log(`[main] \u5B9A\u65F6\u4EFB\u52A1\u8C03\u5EA6\u5668\u5DF2\u542F\u52A8`);
|
|
50767
|
+
}
|
|
50656
50768
|
startMailboxPoller();
|
|
50657
50769
|
console.log(`[main] \u591A\u667A\u80FD\u4F53\u90AE\u7BB1\u8F6E\u8BE2\u5DF2\u542F\u52A8`);
|
|
50658
50770
|
const kanbanPort = Number(process.env.KANBAN_PORT || 3e3);
|