@cleocode/core 2026.3.58 → 2026.3.60
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/agents/agent-registry.d.ts +206 -0
- package/dist/agents/agent-registry.d.ts.map +1 -0
- package/dist/agents/agent-registry.js +288 -0
- package/dist/agents/agent-registry.js.map +1 -0
- package/dist/agents/agent-schema.js +5 -0
- package/dist/agents/agent-schema.js.map +1 -1
- package/dist/agents/execution-learning.js +474 -0
- package/dist/agents/execution-learning.js.map +1 -0
- package/dist/agents/health-monitor.d.ts +161 -0
- package/dist/agents/health-monitor.d.ts.map +1 -0
- package/dist/agents/health-monitor.js +217 -0
- package/dist/agents/health-monitor.js.map +1 -0
- package/dist/agents/index.d.ts +3 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +9 -1
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/retry.d.ts +57 -4
- package/dist/agents/retry.d.ts.map +1 -1
- package/dist/agents/retry.js +57 -4
- package/dist/agents/retry.js.map +1 -1
- package/dist/backfill/index.d.ts +27 -0
- package/dist/backfill/index.d.ts.map +1 -1
- package/dist/backfill/index.js +229 -0
- package/dist/backfill/index.js.map +1 -0
- package/dist/bootstrap.d.ts +2 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +135 -28
- package/dist/bootstrap.js.map +1 -1
- package/dist/cleo.d.ts +40 -0
- package/dist/cleo.d.ts.map +1 -1
- package/dist/config.js +83 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1036 -536
- package/dist/index.js.map +4 -4
- package/dist/intelligence/adaptive-validation.js +497 -0
- package/dist/intelligence/adaptive-validation.js.map +1 -0
- package/dist/intelligence/impact.d.ts +34 -1
- package/dist/intelligence/impact.d.ts.map +1 -1
- package/dist/intelligence/impact.js +176 -0
- package/dist/intelligence/impact.js.map +1 -1
- package/dist/intelligence/index.d.ts +2 -2
- package/dist/intelligence/index.d.ts.map +1 -1
- package/dist/intelligence/index.js +6 -1
- package/dist/intelligence/index.js.map +1 -1
- package/dist/intelligence/types.d.ts +60 -0
- package/dist/intelligence/types.d.ts.map +1 -1
- package/dist/internal.d.ts +5 -4
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +11 -2
- package/dist/internal.js.map +1 -1
- package/dist/lib/index.d.ts +10 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +10 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/retry.d.ts +128 -0
- package/dist/lib/retry.d.ts.map +1 -0
- package/dist/lib/retry.js +152 -0
- package/dist/lib/retry.js.map +1 -0
- package/dist/nexus/sharing/index.d.ts +48 -2
- package/dist/nexus/sharing/index.d.ts.map +1 -1
- package/dist/nexus/sharing/index.js +110 -1
- package/dist/nexus/sharing/index.js.map +1 -1
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +22 -2
- package/dist/scaffold.js.map +1 -1
- package/dist/sessions/session-enforcement.js +4 -0
- package/dist/sessions/session-enforcement.js.map +1 -1
- package/dist/stats/index.js +2 -0
- package/dist/stats/index.js.map +1 -1
- package/dist/stats/workflow-telemetry.d.ts +15 -0
- package/dist/stats/workflow-telemetry.d.ts.map +1 -1
- package/dist/stats/workflow-telemetry.js +400 -0
- package/dist/stats/workflow-telemetry.js.map +1 -0
- package/dist/store/brain-schema.js +4 -1
- package/dist/store/brain-schema.js.map +1 -1
- package/dist/store/converters.js +2 -0
- package/dist/store/converters.js.map +1 -1
- package/dist/store/cross-db-cleanup.d.ts +35 -0
- package/dist/store/cross-db-cleanup.d.ts.map +1 -1
- package/dist/store/cross-db-cleanup.js +169 -0
- package/dist/store/cross-db-cleanup.js.map +1 -0
- package/dist/store/db-helpers.js +2 -0
- package/dist/store/db-helpers.js.map +1 -1
- package/dist/store/migration-sqlite.js +5 -0
- package/dist/store/migration-sqlite.js.map +1 -1
- package/dist/store/sqlite-data-accessor.js +20 -28
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/sqlite.js +13 -2
- package/dist/store/sqlite.js.map +1 -1
- package/dist/store/task-store.js +4 -0
- package/dist/store/task-store.js.map +1 -1
- package/dist/store/tasks-schema.js +50 -20
- package/dist/store/tasks-schema.js.map +1 -1
- package/dist/tasks/add.js +87 -3
- package/dist/tasks/add.js.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +15 -4
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/enforcement.d.ts.map +1 -1
- package/dist/tasks/enforcement.js +8 -1
- package/dist/tasks/enforcement.js.map +1 -1
- package/dist/tasks/epic-enforcement.d.ts +61 -0
- package/dist/tasks/epic-enforcement.d.ts.map +1 -1
- package/dist/tasks/epic-enforcement.js +294 -0
- package/dist/tasks/epic-enforcement.js.map +1 -0
- package/dist/tasks/index.js +1 -1
- package/dist/tasks/index.js.map +1 -1
- package/dist/tasks/pipeline-stage.d.ts +70 -1
- package/dist/tasks/pipeline-stage.d.ts.map +1 -1
- package/dist/tasks/pipeline-stage.js +248 -0
- package/dist/tasks/pipeline-stage.js.map +1 -0
- package/dist/tasks/update.js +28 -0
- package/dist/tasks/update.js.map +1 -1
- package/package.json +5 -5
- package/schemas/config.schema.json +37 -1547
- package/src/__tests__/sharing.test.ts +24 -0
- package/src/agents/__tests__/agent-registry.test.ts +351 -0
- package/src/agents/__tests__/health-monitor.test.ts +332 -0
- package/src/agents/agent-registry.ts +394 -0
- package/src/agents/health-monitor.ts +279 -0
- package/src/agents/index.ts +24 -1
- package/src/agents/retry.ts +57 -4
- package/src/backfill/index.ts +27 -0
- package/src/bootstrap.ts +171 -30
- package/src/cleo.ts +103 -2
- package/src/config.ts +3 -3
- package/src/index.ts +1 -0
- package/src/intelligence/__tests__/impact.test.ts +165 -1
- package/src/intelligence/impact.ts +203 -0
- package/src/intelligence/index.ts +3 -0
- package/src/intelligence/types.ts +76 -0
- package/src/internal.ts +20 -0
- package/src/lib/__tests__/retry.test.ts +321 -0
- package/src/lib/index.ts +16 -0
- package/src/lib/retry.ts +224 -0
- package/src/nexus/sharing/index.ts +142 -2
- package/src/scaffold.ts +24 -2
- package/src/stats/workflow-telemetry.ts +15 -0
- package/src/store/__tests__/session-store.test.ts +43 -7
- package/src/store/__tests__/task-store.test.ts +1 -1
- package/src/store/__tests__/test-db-helper.ts +7 -3
- package/src/store/cross-db-cleanup.ts +35 -0
- package/src/tasks/__tests__/epic-enforcement.test.ts +9 -4
- package/src/tasks/__tests__/minimal-test.test.ts +2 -2
- package/src/tasks/__tests__/update.test.ts +25 -25
- package/src/tasks/complete.ts +11 -6
- package/src/tasks/enforcement.ts +6 -3
- package/src/tasks/epic-enforcement.ts +61 -0
- package/src/tasks/pipeline-stage.ts +70 -1
- package/templates/config.template.json +5 -116
- package/templates/global-config.template.json +2 -44
package/dist/index.js
CHANGED
|
@@ -13159,9 +13159,9 @@ async function readSequenceFromDb(cwd, accessor) {
|
|
|
13159
13159
|
return isValidSequenceState(value) ? value : null;
|
|
13160
13160
|
}
|
|
13161
13161
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
13162
|
-
const { eq:
|
|
13162
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
13163
13163
|
const db = await getDb3(cwd);
|
|
13164
|
-
const rows = await db.select().from(schemaMeta).where(
|
|
13164
|
+
const rows = await db.select().from(schemaMeta).where(eq12(schemaMeta.key, SEQUENCE_META_KEY)).all();
|
|
13165
13165
|
const raw = rows[0]?.value;
|
|
13166
13166
|
if (!raw) return null;
|
|
13167
13167
|
try {
|
|
@@ -14207,7 +14207,7 @@ async function linkPipelineAdr(projectRoot, taskId) {
|
|
|
14207
14207
|
return result;
|
|
14208
14208
|
}
|
|
14209
14209
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
14210
|
-
const { and:
|
|
14210
|
+
const { and: and9, eq: eq12 } = await import("drizzle-orm");
|
|
14211
14211
|
const db = await getDb3(projectRoot);
|
|
14212
14212
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14213
14213
|
for (const filePath of matchingFiles) {
|
|
@@ -14217,7 +14217,7 @@ async function linkPipelineAdr(projectRoot, taskId) {
|
|
|
14217
14217
|
const fm = record2.frontmatter;
|
|
14218
14218
|
const content = readFileSync5(filePath, "utf-8");
|
|
14219
14219
|
const relativePath = `.cleo/adrs/${filename}`;
|
|
14220
|
-
const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(
|
|
14220
|
+
const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq12(architectureDecisions.id, record2.id)).all();
|
|
14221
14221
|
const rowBase = {
|
|
14222
14222
|
id: record2.id,
|
|
14223
14223
|
title: record2.title,
|
|
@@ -14237,19 +14237,19 @@ async function linkPipelineAdr(projectRoot, taskId) {
|
|
|
14237
14237
|
updatedAt: now
|
|
14238
14238
|
};
|
|
14239
14239
|
if (existing.length > 0) {
|
|
14240
|
-
await db.update(architectureDecisions).set(rowBase).where(
|
|
14240
|
+
await db.update(architectureDecisions).set(rowBase).where(eq12(architectureDecisions.id, record2.id));
|
|
14241
14241
|
} else {
|
|
14242
14242
|
await db.insert(architectureDecisions).values({ ...rowBase, createdAt: now });
|
|
14243
14243
|
}
|
|
14244
14244
|
result.synced++;
|
|
14245
|
-
await db.delete(adrTaskLinks).where(
|
|
14245
|
+
await db.delete(adrTaskLinks).where(and9(eq12(adrTaskLinks.adrId, record2.id), eq12(adrTaskLinks.taskId, taskId)));
|
|
14246
14246
|
await db.insert(adrTaskLinks).values({ adrId: record2.id, taskId, linkType: "implements" });
|
|
14247
14247
|
result.linked.push({ adrId: record2.id, taskId });
|
|
14248
14248
|
if (fm["Related ADRs"]) {
|
|
14249
14249
|
const relatedIds = fm["Related ADRs"].split(",").map((r) => r.trim()).filter((r) => /^ADR-\d+$/.test(r));
|
|
14250
14250
|
for (const toId of relatedIds) {
|
|
14251
14251
|
try {
|
|
14252
|
-
const targetExists = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(
|
|
14252
|
+
const targetExists = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq12(architectureDecisions.id, toId)).all();
|
|
14253
14253
|
if (targetExists.length > 0) {
|
|
14254
14254
|
await db.insert(adrRelations).values({ fromAdrId: record2.id, toAdrId: toId, relationType: "related" }).onConflictDoNothing();
|
|
14255
14255
|
}
|
|
@@ -14272,248 +14272,8 @@ var init_link_pipeline = __esm({
|
|
|
14272
14272
|
}
|
|
14273
14273
|
});
|
|
14274
14274
|
|
|
14275
|
-
// packages/core/src/agents/registry.ts
|
|
14276
|
-
var registry_exports2 = {};
|
|
14277
|
-
__export(registry_exports2, {
|
|
14278
|
-
checkAgentHealth: () => checkAgentHealth,
|
|
14279
|
-
classifyError: () => classifyError,
|
|
14280
|
-
deregisterAgent: () => deregisterAgent,
|
|
14281
|
-
generateAgentId: () => generateAgentId,
|
|
14282
|
-
getAgentErrorHistory: () => getAgentErrorHistory,
|
|
14283
|
-
getAgentInstance: () => getAgentInstance,
|
|
14284
|
-
getHealthReport: () => getHealthReport,
|
|
14285
|
-
heartbeat: () => heartbeat,
|
|
14286
|
-
incrementTasksCompleted: () => incrementTasksCompleted,
|
|
14287
|
-
listAgentInstances: () => listAgentInstances,
|
|
14288
|
-
markCrashed: () => markCrashed,
|
|
14289
|
-
registerAgent: () => registerAgent,
|
|
14290
|
-
updateAgentStatus: () => updateAgentStatus
|
|
14291
|
-
});
|
|
14292
|
-
import { randomBytes } from "node:crypto";
|
|
14293
|
-
import { and as and3, eq as eq5, inArray as inArray4, lt as lt2, sql as sql8 } from "drizzle-orm";
|
|
14294
|
-
function generateAgentId() {
|
|
14295
|
-
const now = /* @__PURE__ */ new Date();
|
|
14296
|
-
const ts = now.toISOString().replace(/[-:T]/g, "").substring(0, 14);
|
|
14297
|
-
const hex = randomBytes(3).toString("hex");
|
|
14298
|
-
return `agt_${ts}_${hex}`;
|
|
14299
|
-
}
|
|
14300
|
-
async function registerAgent(opts, cwd) {
|
|
14301
|
-
const db = await getDb(cwd);
|
|
14302
|
-
const id = generateAgentId();
|
|
14303
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14304
|
-
const row = {
|
|
14305
|
-
id,
|
|
14306
|
-
agentType: opts.agentType,
|
|
14307
|
-
status: "starting",
|
|
14308
|
-
sessionId: opts.sessionId ?? null,
|
|
14309
|
-
taskId: opts.taskId ?? null,
|
|
14310
|
-
startedAt: now,
|
|
14311
|
-
lastHeartbeat: now,
|
|
14312
|
-
stoppedAt: null,
|
|
14313
|
-
errorCount: 0,
|
|
14314
|
-
totalTasksCompleted: 0,
|
|
14315
|
-
capacity: "1.0",
|
|
14316
|
-
metadataJson: opts.metadata ? JSON.stringify(opts.metadata) : "{}",
|
|
14317
|
-
parentAgentId: opts.parentAgentId ?? null
|
|
14318
|
-
};
|
|
14319
|
-
await db.insert(agentInstances).values(row);
|
|
14320
|
-
return row;
|
|
14321
|
-
}
|
|
14322
|
-
async function deregisterAgent(id, cwd) {
|
|
14323
|
-
const db = await getDb(cwd);
|
|
14324
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14325
|
-
const existing = await db.select().from(agentInstances).where(eq5(agentInstances.id, id)).get();
|
|
14326
|
-
if (!existing) return null;
|
|
14327
|
-
if (existing.status === "stopped") return existing;
|
|
14328
|
-
await db.update(agentInstances).set({ status: "stopped", stoppedAt: now }).where(eq5(agentInstances.id, id));
|
|
14329
|
-
return { ...existing, status: "stopped", stoppedAt: now };
|
|
14330
|
-
}
|
|
14331
|
-
async function heartbeat(id, cwd) {
|
|
14332
|
-
const db = await getDb(cwd);
|
|
14333
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14334
|
-
const existing = await db.select().from(agentInstances).where(eq5(agentInstances.id, id)).get();
|
|
14335
|
-
if (!existing) return null;
|
|
14336
|
-
if (existing.status === "stopped" || existing.status === "crashed") {
|
|
14337
|
-
return existing.status;
|
|
14338
|
-
}
|
|
14339
|
-
await db.update(agentInstances).set({ lastHeartbeat: now }).where(eq5(agentInstances.id, id));
|
|
14340
|
-
return existing.status;
|
|
14341
|
-
}
|
|
14342
|
-
async function updateAgentStatus(id, opts, cwd) {
|
|
14343
|
-
const db = await getDb(cwd);
|
|
14344
|
-
const existing = await db.select().from(agentInstances).where(eq5(agentInstances.id, id)).get();
|
|
14345
|
-
if (!existing) return null;
|
|
14346
|
-
const updates = {
|
|
14347
|
-
status: opts.status
|
|
14348
|
-
};
|
|
14349
|
-
if (opts.taskId !== void 0) {
|
|
14350
|
-
updates.taskId = opts.taskId;
|
|
14351
|
-
}
|
|
14352
|
-
if (opts.status === "active") {
|
|
14353
|
-
updates.lastHeartbeat = (/* @__PURE__ */ new Date()).toISOString();
|
|
14354
|
-
}
|
|
14355
|
-
if (opts.status === "error" || opts.status === "crashed") {
|
|
14356
|
-
updates.errorCount = existing.errorCount + 1;
|
|
14357
|
-
if (opts.error) {
|
|
14358
|
-
const errorType = classifyError(new Error(opts.error));
|
|
14359
|
-
await db.insert(agentErrorLog).values({
|
|
14360
|
-
agentId: id,
|
|
14361
|
-
errorType,
|
|
14362
|
-
message: opts.error,
|
|
14363
|
-
occurredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
14364
|
-
});
|
|
14365
|
-
}
|
|
14366
|
-
}
|
|
14367
|
-
if (opts.status === "stopped") {
|
|
14368
|
-
updates.stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
14369
|
-
}
|
|
14370
|
-
await db.update(agentInstances).set(updates).where(eq5(agentInstances.id, id));
|
|
14371
|
-
return { ...existing, ...updates };
|
|
14372
|
-
}
|
|
14373
|
-
async function incrementTasksCompleted(id, cwd) {
|
|
14374
|
-
const db = await getDb(cwd);
|
|
14375
|
-
await db.update(agentInstances).set({ totalTasksCompleted: sql8`${agentInstances.totalTasksCompleted} + 1` }).where(eq5(agentInstances.id, id));
|
|
14376
|
-
}
|
|
14377
|
-
async function listAgentInstances(filters, cwd) {
|
|
14378
|
-
const db = await getDb(cwd);
|
|
14379
|
-
const conditions = [];
|
|
14380
|
-
if (filters?.status) {
|
|
14381
|
-
const statuses = Array.isArray(filters.status) ? filters.status : [filters.status];
|
|
14382
|
-
conditions.push(inArray4(agentInstances.status, statuses));
|
|
14383
|
-
}
|
|
14384
|
-
if (filters?.agentType) {
|
|
14385
|
-
const types = Array.isArray(filters.agentType) ? filters.agentType : [filters.agentType];
|
|
14386
|
-
conditions.push(inArray4(agentInstances.agentType, types));
|
|
14387
|
-
}
|
|
14388
|
-
if (filters?.sessionId) {
|
|
14389
|
-
conditions.push(eq5(agentInstances.sessionId, filters.sessionId));
|
|
14390
|
-
}
|
|
14391
|
-
if (filters?.parentAgentId) {
|
|
14392
|
-
conditions.push(eq5(agentInstances.parentAgentId, filters.parentAgentId));
|
|
14393
|
-
}
|
|
14394
|
-
if (conditions.length === 0) {
|
|
14395
|
-
return db.select().from(agentInstances).all();
|
|
14396
|
-
}
|
|
14397
|
-
return db.select().from(agentInstances).where(and3(...conditions)).all();
|
|
14398
|
-
}
|
|
14399
|
-
async function getAgentInstance(id, cwd) {
|
|
14400
|
-
const db = await getDb(cwd);
|
|
14401
|
-
const row = await db.select().from(agentInstances).where(eq5(agentInstances.id, id)).get();
|
|
14402
|
-
return row ?? null;
|
|
14403
|
-
}
|
|
14404
|
-
function classifyError(error40) {
|
|
14405
|
-
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
14406
|
-
for (const pattern of RETRIABLE_PATTERNS) {
|
|
14407
|
-
if (pattern.test(message)) return "retriable";
|
|
14408
|
-
}
|
|
14409
|
-
for (const pattern of PERMANENT_PATTERNS) {
|
|
14410
|
-
if (pattern.test(message)) return "permanent";
|
|
14411
|
-
}
|
|
14412
|
-
return "unknown";
|
|
14413
|
-
}
|
|
14414
|
-
async function getAgentErrorHistory(agentId, cwd) {
|
|
14415
|
-
const db = await getDb(cwd);
|
|
14416
|
-
return db.select().from(agentErrorLog).where(eq5(agentErrorLog.agentId, agentId)).all();
|
|
14417
|
-
}
|
|
14418
|
-
async function checkAgentHealth(thresholdMs = 3e4, cwd) {
|
|
14419
|
-
const db = await getDb(cwd);
|
|
14420
|
-
const cutoff = new Date(Date.now() - thresholdMs).toISOString();
|
|
14421
|
-
return db.select().from(agentInstances).where(
|
|
14422
|
-
and3(
|
|
14423
|
-
inArray4(agentInstances.status, ["active", "idle", "starting"]),
|
|
14424
|
-
lt2(agentInstances.lastHeartbeat, cutoff)
|
|
14425
|
-
)
|
|
14426
|
-
).all();
|
|
14427
|
-
}
|
|
14428
|
-
async function markCrashed(id, reason, cwd) {
|
|
14429
|
-
return updateAgentStatus(
|
|
14430
|
-
id,
|
|
14431
|
-
{ status: "crashed", error: reason ?? "Heartbeat timeout \u2014 agent presumed crashed" },
|
|
14432
|
-
cwd
|
|
14433
|
-
);
|
|
14434
|
-
}
|
|
14435
|
-
async function getHealthReport(thresholdMs = 3e4, cwd) {
|
|
14436
|
-
const allAgents = await listAgentInstances(void 0, cwd);
|
|
14437
|
-
const staleAgents = await checkAgentHealth(thresholdMs, cwd);
|
|
14438
|
-
const report = {
|
|
14439
|
-
total: allAgents.length,
|
|
14440
|
-
active: 0,
|
|
14441
|
-
idle: 0,
|
|
14442
|
-
starting: 0,
|
|
14443
|
-
error: 0,
|
|
14444
|
-
crashed: 0,
|
|
14445
|
-
stopped: 0,
|
|
14446
|
-
totalErrors: 0,
|
|
14447
|
-
staleAgents
|
|
14448
|
-
};
|
|
14449
|
-
for (const agent of allAgents) {
|
|
14450
|
-
switch (agent.status) {
|
|
14451
|
-
case "active":
|
|
14452
|
-
report.active++;
|
|
14453
|
-
break;
|
|
14454
|
-
case "idle":
|
|
14455
|
-
report.idle++;
|
|
14456
|
-
break;
|
|
14457
|
-
case "starting":
|
|
14458
|
-
report.starting++;
|
|
14459
|
-
break;
|
|
14460
|
-
case "error":
|
|
14461
|
-
report.error++;
|
|
14462
|
-
break;
|
|
14463
|
-
case "crashed":
|
|
14464
|
-
report.crashed++;
|
|
14465
|
-
break;
|
|
14466
|
-
case "stopped":
|
|
14467
|
-
report.stopped++;
|
|
14468
|
-
break;
|
|
14469
|
-
}
|
|
14470
|
-
report.totalErrors += agent.errorCount;
|
|
14471
|
-
}
|
|
14472
|
-
return report;
|
|
14473
|
-
}
|
|
14474
|
-
var RETRIABLE_PATTERNS, PERMANENT_PATTERNS;
|
|
14475
|
-
var init_registry2 = __esm({
|
|
14476
|
-
"packages/core/src/agents/registry.ts"() {
|
|
14477
|
-
"use strict";
|
|
14478
|
-
init_sqlite2();
|
|
14479
|
-
init_agent_schema();
|
|
14480
|
-
RETRIABLE_PATTERNS = [
|
|
14481
|
-
/timeout/i,
|
|
14482
|
-
/ECONNREFUSED/,
|
|
14483
|
-
/ECONNRESET/,
|
|
14484
|
-
/EPIPE/,
|
|
14485
|
-
/ETIMEDOUT/,
|
|
14486
|
-
/rate.?limit/i,
|
|
14487
|
-
/429/,
|
|
14488
|
-
/503/,
|
|
14489
|
-
/502/,
|
|
14490
|
-
/SQLITE_BUSY/i,
|
|
14491
|
-
/database is locked/i,
|
|
14492
|
-
/temporarily unavailable/i,
|
|
14493
|
-
/too many requests/i,
|
|
14494
|
-
/network/i,
|
|
14495
|
-
/socket hang up/i
|
|
14496
|
-
];
|
|
14497
|
-
PERMANENT_PATTERNS = [
|
|
14498
|
-
/permission denied/i,
|
|
14499
|
-
/EACCES/,
|
|
14500
|
-
/authentication/i,
|
|
14501
|
-
/unauthorized/i,
|
|
14502
|
-
/401/,
|
|
14503
|
-
/403/,
|
|
14504
|
-
/404/,
|
|
14505
|
-
/not found/i,
|
|
14506
|
-
/invalid.*token/i,
|
|
14507
|
-
/SQLITE_CONSTRAINT/i,
|
|
14508
|
-
/syntax error/i,
|
|
14509
|
-
/type error/i,
|
|
14510
|
-
/reference error/i
|
|
14511
|
-
];
|
|
14512
|
-
}
|
|
14513
|
-
});
|
|
14514
|
-
|
|
14515
14275
|
// packages/core/src/store/brain-accessor.ts
|
|
14516
|
-
import { and as
|
|
14276
|
+
import { and as and3, asc as asc2, desc as desc2, eq as eq5, gte as gte2, or as or3 } from "drizzle-orm";
|
|
14517
14277
|
async function getBrainAccessor(cwd) {
|
|
14518
14278
|
const db = await getBrainDb(cwd);
|
|
14519
14279
|
return new BrainDataAccessor(db);
|
|
@@ -14533,30 +14293,30 @@ var init_brain_accessor = __esm({
|
|
|
14533
14293
|
// =========================================================================
|
|
14534
14294
|
async addDecision(row) {
|
|
14535
14295
|
await this.db.insert(brainDecisions).values(row);
|
|
14536
|
-
const result = await this.db.select().from(brainDecisions).where(
|
|
14296
|
+
const result = await this.db.select().from(brainDecisions).where(eq5(brainDecisions.id, row.id));
|
|
14537
14297
|
return result[0];
|
|
14538
14298
|
}
|
|
14539
14299
|
async getDecision(id) {
|
|
14540
|
-
const result = await this.db.select().from(brainDecisions).where(
|
|
14300
|
+
const result = await this.db.select().from(brainDecisions).where(eq5(brainDecisions.id, id));
|
|
14541
14301
|
return result[0] ?? null;
|
|
14542
14302
|
}
|
|
14543
14303
|
async findDecisions(params = {}) {
|
|
14544
14304
|
const conditions = [];
|
|
14545
14305
|
if (params.type) {
|
|
14546
|
-
conditions.push(
|
|
14306
|
+
conditions.push(eq5(brainDecisions.type, params.type));
|
|
14547
14307
|
}
|
|
14548
14308
|
if (params.confidence) {
|
|
14549
|
-
conditions.push(
|
|
14309
|
+
conditions.push(eq5(brainDecisions.confidence, params.confidence));
|
|
14550
14310
|
}
|
|
14551
14311
|
if (params.outcome) {
|
|
14552
|
-
conditions.push(
|
|
14312
|
+
conditions.push(eq5(brainDecisions.outcome, params.outcome));
|
|
14553
14313
|
}
|
|
14554
14314
|
if (params.contextTaskId) {
|
|
14555
|
-
conditions.push(
|
|
14315
|
+
conditions.push(eq5(brainDecisions.contextTaskId, params.contextTaskId));
|
|
14556
14316
|
}
|
|
14557
14317
|
let query = this.db.select().from(brainDecisions).orderBy(desc2(brainDecisions.createdAt));
|
|
14558
14318
|
if (conditions.length > 0) {
|
|
14559
|
-
query = query.where(
|
|
14319
|
+
query = query.where(and3(...conditions));
|
|
14560
14320
|
}
|
|
14561
14321
|
if (params.limit) {
|
|
14562
14322
|
query = query.limit(params.limit);
|
|
@@ -14564,34 +14324,34 @@ var init_brain_accessor = __esm({
|
|
|
14564
14324
|
return query;
|
|
14565
14325
|
}
|
|
14566
14326
|
async updateDecision(id, updates) {
|
|
14567
|
-
await this.db.update(brainDecisions).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(
|
|
14327
|
+
await this.db.update(brainDecisions).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(eq5(brainDecisions.id, id));
|
|
14568
14328
|
}
|
|
14569
14329
|
// =========================================================================
|
|
14570
14330
|
// Patterns CRUD
|
|
14571
14331
|
// =========================================================================
|
|
14572
14332
|
async addPattern(row) {
|
|
14573
14333
|
await this.db.insert(brainPatterns).values(row);
|
|
14574
|
-
const result = await this.db.select().from(brainPatterns).where(
|
|
14334
|
+
const result = await this.db.select().from(brainPatterns).where(eq5(brainPatterns.id, row.id));
|
|
14575
14335
|
return result[0];
|
|
14576
14336
|
}
|
|
14577
14337
|
async getPattern(id) {
|
|
14578
|
-
const result = await this.db.select().from(brainPatterns).where(
|
|
14338
|
+
const result = await this.db.select().from(brainPatterns).where(eq5(brainPatterns.id, id));
|
|
14579
14339
|
return result[0] ?? null;
|
|
14580
14340
|
}
|
|
14581
14341
|
async findPatterns(params = {}) {
|
|
14582
14342
|
const conditions = [];
|
|
14583
14343
|
if (params.type) {
|
|
14584
|
-
conditions.push(
|
|
14344
|
+
conditions.push(eq5(brainPatterns.type, params.type));
|
|
14585
14345
|
}
|
|
14586
14346
|
if (params.impact) {
|
|
14587
|
-
conditions.push(
|
|
14347
|
+
conditions.push(eq5(brainPatterns.impact, params.impact));
|
|
14588
14348
|
}
|
|
14589
14349
|
if (params.minFrequency !== void 0) {
|
|
14590
14350
|
conditions.push(gte2(brainPatterns.frequency, params.minFrequency));
|
|
14591
14351
|
}
|
|
14592
14352
|
let query = this.db.select().from(brainPatterns).orderBy(desc2(brainPatterns.frequency));
|
|
14593
14353
|
if (conditions.length > 0) {
|
|
14594
|
-
query = query.where(
|
|
14354
|
+
query = query.where(and3(...conditions));
|
|
14595
14355
|
}
|
|
14596
14356
|
if (params.limit) {
|
|
14597
14357
|
query = query.limit(params.limit);
|
|
@@ -14599,18 +14359,18 @@ var init_brain_accessor = __esm({
|
|
|
14599
14359
|
return query;
|
|
14600
14360
|
}
|
|
14601
14361
|
async updatePattern(id, updates) {
|
|
14602
|
-
await this.db.update(brainPatterns).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(
|
|
14362
|
+
await this.db.update(brainPatterns).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(eq5(brainPatterns.id, id));
|
|
14603
14363
|
}
|
|
14604
14364
|
// =========================================================================
|
|
14605
14365
|
// Learnings CRUD
|
|
14606
14366
|
// =========================================================================
|
|
14607
14367
|
async addLearning(row) {
|
|
14608
14368
|
await this.db.insert(brainLearnings).values(row);
|
|
14609
|
-
const result = await this.db.select().from(brainLearnings).where(
|
|
14369
|
+
const result = await this.db.select().from(brainLearnings).where(eq5(brainLearnings.id, row.id));
|
|
14610
14370
|
return result[0];
|
|
14611
14371
|
}
|
|
14612
14372
|
async getLearning(id) {
|
|
14613
|
-
const result = await this.db.select().from(brainLearnings).where(
|
|
14373
|
+
const result = await this.db.select().from(brainLearnings).where(eq5(brainLearnings.id, id));
|
|
14614
14374
|
return result[0] ?? null;
|
|
14615
14375
|
}
|
|
14616
14376
|
async findLearnings(params = {}) {
|
|
@@ -14619,11 +14379,11 @@ var init_brain_accessor = __esm({
|
|
|
14619
14379
|
conditions.push(gte2(brainLearnings.confidence, params.minConfidence));
|
|
14620
14380
|
}
|
|
14621
14381
|
if (params.actionable !== void 0) {
|
|
14622
|
-
conditions.push(
|
|
14382
|
+
conditions.push(eq5(brainLearnings.actionable, params.actionable));
|
|
14623
14383
|
}
|
|
14624
14384
|
let query = this.db.select().from(brainLearnings).orderBy(desc2(brainLearnings.confidence));
|
|
14625
14385
|
if (conditions.length > 0) {
|
|
14626
|
-
query = query.where(
|
|
14386
|
+
query = query.where(and3(...conditions));
|
|
14627
14387
|
}
|
|
14628
14388
|
if (params.limit) {
|
|
14629
14389
|
query = query.limit(params.limit);
|
|
@@ -14631,37 +14391,37 @@ var init_brain_accessor = __esm({
|
|
|
14631
14391
|
return query;
|
|
14632
14392
|
}
|
|
14633
14393
|
async updateLearning(id, updates) {
|
|
14634
|
-
await this.db.update(brainLearnings).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(
|
|
14394
|
+
await this.db.update(brainLearnings).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(eq5(brainLearnings.id, id));
|
|
14635
14395
|
}
|
|
14636
14396
|
// =========================================================================
|
|
14637
14397
|
// Observations CRUD
|
|
14638
14398
|
// =========================================================================
|
|
14639
14399
|
async addObservation(row) {
|
|
14640
14400
|
await this.db.insert(brainObservations).values(row);
|
|
14641
|
-
const result = await this.db.select().from(brainObservations).where(
|
|
14401
|
+
const result = await this.db.select().from(brainObservations).where(eq5(brainObservations.id, row.id));
|
|
14642
14402
|
return result[0];
|
|
14643
14403
|
}
|
|
14644
14404
|
async getObservation(id) {
|
|
14645
|
-
const result = await this.db.select().from(brainObservations).where(
|
|
14405
|
+
const result = await this.db.select().from(brainObservations).where(eq5(brainObservations.id, id));
|
|
14646
14406
|
return result[0] ?? null;
|
|
14647
14407
|
}
|
|
14648
14408
|
async findObservations(params = {}) {
|
|
14649
14409
|
const conditions = [];
|
|
14650
14410
|
if (params.type) {
|
|
14651
|
-
conditions.push(
|
|
14411
|
+
conditions.push(eq5(brainObservations.type, params.type));
|
|
14652
14412
|
}
|
|
14653
14413
|
if (params.project) {
|
|
14654
|
-
conditions.push(
|
|
14414
|
+
conditions.push(eq5(brainObservations.project, params.project));
|
|
14655
14415
|
}
|
|
14656
14416
|
if (params.sourceType) {
|
|
14657
|
-
conditions.push(
|
|
14417
|
+
conditions.push(eq5(brainObservations.sourceType, params.sourceType));
|
|
14658
14418
|
}
|
|
14659
14419
|
if (params.sourceSessionId) {
|
|
14660
|
-
conditions.push(
|
|
14420
|
+
conditions.push(eq5(brainObservations.sourceSessionId, params.sourceSessionId));
|
|
14661
14421
|
}
|
|
14662
14422
|
let query = this.db.select().from(brainObservations).orderBy(desc2(brainObservations.createdAt));
|
|
14663
14423
|
if (conditions.length > 0) {
|
|
14664
|
-
query = query.where(
|
|
14424
|
+
query = query.where(and3(...conditions));
|
|
14665
14425
|
}
|
|
14666
14426
|
if (params.limit) {
|
|
14667
14427
|
query = query.limit(params.limit);
|
|
@@ -14669,7 +14429,7 @@ var init_brain_accessor = __esm({
|
|
|
14669
14429
|
return query;
|
|
14670
14430
|
}
|
|
14671
14431
|
async updateObservation(id, updates) {
|
|
14672
|
-
await this.db.update(brainObservations).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(
|
|
14432
|
+
await this.db.update(brainObservations).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(eq5(brainObservations.id, id));
|
|
14673
14433
|
}
|
|
14674
14434
|
// =========================================================================
|
|
14675
14435
|
// Memory Links CRUD
|
|
@@ -14679,22 +14439,22 @@ var init_brain_accessor = __esm({
|
|
|
14679
14439
|
}
|
|
14680
14440
|
async getLinksForMemory(memoryType, memoryId) {
|
|
14681
14441
|
return this.db.select().from(brainMemoryLinks).where(
|
|
14682
|
-
|
|
14683
|
-
|
|
14684
|
-
|
|
14442
|
+
and3(
|
|
14443
|
+
eq5(brainMemoryLinks.memoryType, memoryType),
|
|
14444
|
+
eq5(brainMemoryLinks.memoryId, memoryId)
|
|
14685
14445
|
)
|
|
14686
14446
|
).orderBy(asc2(brainMemoryLinks.createdAt));
|
|
14687
14447
|
}
|
|
14688
14448
|
async getLinksForTask(taskId) {
|
|
14689
|
-
return this.db.select().from(brainMemoryLinks).where(
|
|
14449
|
+
return this.db.select().from(brainMemoryLinks).where(eq5(brainMemoryLinks.taskId, taskId)).orderBy(asc2(brainMemoryLinks.createdAt));
|
|
14690
14450
|
}
|
|
14691
14451
|
async removeLink(memoryType, memoryId, taskId, linkType) {
|
|
14692
14452
|
await this.db.delete(brainMemoryLinks).where(
|
|
14693
|
-
|
|
14694
|
-
|
|
14695
|
-
|
|
14696
|
-
|
|
14697
|
-
|
|
14453
|
+
and3(
|
|
14454
|
+
eq5(brainMemoryLinks.memoryType, memoryType),
|
|
14455
|
+
eq5(brainMemoryLinks.memoryId, memoryId),
|
|
14456
|
+
eq5(brainMemoryLinks.taskId, taskId),
|
|
14457
|
+
eq5(brainMemoryLinks.linkType, linkType)
|
|
14698
14458
|
)
|
|
14699
14459
|
);
|
|
14700
14460
|
}
|
|
@@ -14703,27 +14463,27 @@ var init_brain_accessor = __esm({
|
|
|
14703
14463
|
// =========================================================================
|
|
14704
14464
|
async addStickyNote(row) {
|
|
14705
14465
|
await this.db.insert(brainStickyNotes).values(row);
|
|
14706
|
-
const result = await this.db.select().from(brainStickyNotes).where(
|
|
14466
|
+
const result = await this.db.select().from(brainStickyNotes).where(eq5(brainStickyNotes.id, row.id));
|
|
14707
14467
|
return result[0];
|
|
14708
14468
|
}
|
|
14709
14469
|
async getStickyNote(id) {
|
|
14710
|
-
const result = await this.db.select().from(brainStickyNotes).where(
|
|
14470
|
+
const result = await this.db.select().from(brainStickyNotes).where(eq5(brainStickyNotes.id, id));
|
|
14711
14471
|
return result[0] ?? null;
|
|
14712
14472
|
}
|
|
14713
14473
|
async findStickyNotes(params = {}) {
|
|
14714
14474
|
const conditions = [];
|
|
14715
14475
|
if (params.status) {
|
|
14716
|
-
conditions.push(
|
|
14476
|
+
conditions.push(eq5(brainStickyNotes.status, params.status));
|
|
14717
14477
|
}
|
|
14718
14478
|
if (params.color) {
|
|
14719
|
-
conditions.push(
|
|
14479
|
+
conditions.push(eq5(brainStickyNotes.color, params.color));
|
|
14720
14480
|
}
|
|
14721
14481
|
if (params.priority) {
|
|
14722
|
-
conditions.push(
|
|
14482
|
+
conditions.push(eq5(brainStickyNotes.priority, params.priority));
|
|
14723
14483
|
}
|
|
14724
14484
|
let query = this.db.select().from(brainStickyNotes).orderBy(desc2(brainStickyNotes.createdAt));
|
|
14725
14485
|
if (conditions.length > 0) {
|
|
14726
|
-
query = query.where(
|
|
14486
|
+
query = query.where(and3(...conditions));
|
|
14727
14487
|
}
|
|
14728
14488
|
if (params.limit) {
|
|
14729
14489
|
query = query.limit(params.limit);
|
|
@@ -14731,31 +14491,31 @@ var init_brain_accessor = __esm({
|
|
|
14731
14491
|
return query;
|
|
14732
14492
|
}
|
|
14733
14493
|
async updateStickyNote(id, updates) {
|
|
14734
|
-
await this.db.update(brainStickyNotes).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(
|
|
14494
|
+
await this.db.update(brainStickyNotes).set({ ...updates, updatedAt: (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19) }).where(eq5(brainStickyNotes.id, id));
|
|
14735
14495
|
}
|
|
14736
14496
|
async deleteStickyNote(id) {
|
|
14737
|
-
await this.db.delete(brainStickyNotes).where(
|
|
14497
|
+
await this.db.delete(brainStickyNotes).where(eq5(brainStickyNotes.id, id));
|
|
14738
14498
|
}
|
|
14739
14499
|
// =========================================================================
|
|
14740
14500
|
// PageIndex Node CRUD (T5383)
|
|
14741
14501
|
// =========================================================================
|
|
14742
14502
|
async addPageNode(node) {
|
|
14743
14503
|
await this.db.insert(brainPageNodes).values(node);
|
|
14744
|
-
const result = await this.db.select().from(brainPageNodes).where(
|
|
14504
|
+
const result = await this.db.select().from(brainPageNodes).where(eq5(brainPageNodes.id, node.id));
|
|
14745
14505
|
return result[0];
|
|
14746
14506
|
}
|
|
14747
14507
|
async getPageNode(id) {
|
|
14748
|
-
const result = await this.db.select().from(brainPageNodes).where(
|
|
14508
|
+
const result = await this.db.select().from(brainPageNodes).where(eq5(brainPageNodes.id, id));
|
|
14749
14509
|
return result[0] ?? null;
|
|
14750
14510
|
}
|
|
14751
14511
|
async findPageNodes(params = {}) {
|
|
14752
14512
|
const conditions = [];
|
|
14753
14513
|
if (params.nodeType) {
|
|
14754
|
-
conditions.push(
|
|
14514
|
+
conditions.push(eq5(brainPageNodes.nodeType, params.nodeType));
|
|
14755
14515
|
}
|
|
14756
14516
|
let query = this.db.select().from(brainPageNodes).orderBy(desc2(brainPageNodes.createdAt));
|
|
14757
14517
|
if (conditions.length > 0) {
|
|
14758
|
-
query = query.where(
|
|
14518
|
+
query = query.where(and3(...conditions));
|
|
14759
14519
|
}
|
|
14760
14520
|
if (params.limit) {
|
|
14761
14521
|
query = query.limit(params.limit);
|
|
@@ -14764,9 +14524,9 @@ var init_brain_accessor = __esm({
|
|
|
14764
14524
|
}
|
|
14765
14525
|
async removePageNode(id) {
|
|
14766
14526
|
await this.db.delete(brainPageEdges).where(
|
|
14767
|
-
or3(
|
|
14527
|
+
or3(eq5(brainPageEdges.fromId, id), eq5(brainPageEdges.toId, id))
|
|
14768
14528
|
);
|
|
14769
|
-
await this.db.delete(brainPageNodes).where(
|
|
14529
|
+
await this.db.delete(brainPageNodes).where(eq5(brainPageNodes.id, id));
|
|
14770
14530
|
}
|
|
14771
14531
|
// =========================================================================
|
|
14772
14532
|
// PageIndex Edge CRUD (T5383)
|
|
@@ -14774,34 +14534,34 @@ var init_brain_accessor = __esm({
|
|
|
14774
14534
|
async addPageEdge(edge) {
|
|
14775
14535
|
await this.db.insert(brainPageEdges).values(edge);
|
|
14776
14536
|
const result = await this.db.select().from(brainPageEdges).where(
|
|
14777
|
-
|
|
14778
|
-
|
|
14779
|
-
|
|
14780
|
-
|
|
14537
|
+
and3(
|
|
14538
|
+
eq5(brainPageEdges.fromId, edge.fromId),
|
|
14539
|
+
eq5(brainPageEdges.toId, edge.toId),
|
|
14540
|
+
eq5(brainPageEdges.edgeType, edge.edgeType)
|
|
14781
14541
|
)
|
|
14782
14542
|
);
|
|
14783
14543
|
return result[0];
|
|
14784
14544
|
}
|
|
14785
14545
|
async getPageEdges(nodeId, direction = "both") {
|
|
14786
14546
|
if (direction === "out") {
|
|
14787
|
-
return this.db.select().from(brainPageEdges).where(
|
|
14547
|
+
return this.db.select().from(brainPageEdges).where(eq5(brainPageEdges.fromId, nodeId)).orderBy(asc2(brainPageEdges.createdAt));
|
|
14788
14548
|
}
|
|
14789
14549
|
if (direction === "in") {
|
|
14790
|
-
return this.db.select().from(brainPageEdges).where(
|
|
14550
|
+
return this.db.select().from(brainPageEdges).where(eq5(brainPageEdges.toId, nodeId)).orderBy(asc2(brainPageEdges.createdAt));
|
|
14791
14551
|
}
|
|
14792
14552
|
return this.db.select().from(brainPageEdges).where(
|
|
14793
14553
|
or3(
|
|
14794
|
-
|
|
14795
|
-
|
|
14554
|
+
eq5(brainPageEdges.fromId, nodeId),
|
|
14555
|
+
eq5(brainPageEdges.toId, nodeId)
|
|
14796
14556
|
)
|
|
14797
14557
|
).orderBy(asc2(brainPageEdges.createdAt));
|
|
14798
14558
|
}
|
|
14799
14559
|
async getNeighbors(nodeId, edgeType) {
|
|
14800
|
-
const conditions = [
|
|
14560
|
+
const conditions = [eq5(brainPageEdges.fromId, nodeId)];
|
|
14801
14561
|
if (edgeType) {
|
|
14802
|
-
conditions.push(
|
|
14562
|
+
conditions.push(eq5(brainPageEdges.edgeType, edgeType));
|
|
14803
14563
|
}
|
|
14804
|
-
const edges = await this.db.select().from(brainPageEdges).where(
|
|
14564
|
+
const edges = await this.db.select().from(brainPageEdges).where(and3(...conditions));
|
|
14805
14565
|
if (edges.length === 0) return [];
|
|
14806
14566
|
const neighborIds = edges.map((e) => e.toId);
|
|
14807
14567
|
const nodes = [];
|
|
@@ -14813,10 +14573,10 @@ var init_brain_accessor = __esm({
|
|
|
14813
14573
|
}
|
|
14814
14574
|
async removePageEdge(fromId, toId, edgeType) {
|
|
14815
14575
|
await this.db.delete(brainPageEdges).where(
|
|
14816
|
-
|
|
14817
|
-
|
|
14818
|
-
|
|
14819
|
-
|
|
14576
|
+
and3(
|
|
14577
|
+
eq5(brainPageEdges.fromId, fromId),
|
|
14578
|
+
eq5(brainPageEdges.toId, toId),
|
|
14579
|
+
eq5(brainPageEdges.edgeType, edgeType)
|
|
14820
14580
|
)
|
|
14821
14581
|
);
|
|
14822
14582
|
}
|
|
@@ -14824,6 +14584,246 @@ var init_brain_accessor = __esm({
|
|
|
14824
14584
|
}
|
|
14825
14585
|
});
|
|
14826
14586
|
|
|
14587
|
+
// packages/core/src/agents/registry.ts
|
|
14588
|
+
var registry_exports2 = {};
|
|
14589
|
+
__export(registry_exports2, {
|
|
14590
|
+
checkAgentHealth: () => checkAgentHealth,
|
|
14591
|
+
classifyError: () => classifyError,
|
|
14592
|
+
deregisterAgent: () => deregisterAgent,
|
|
14593
|
+
generateAgentId: () => generateAgentId,
|
|
14594
|
+
getAgentErrorHistory: () => getAgentErrorHistory,
|
|
14595
|
+
getAgentInstance: () => getAgentInstance,
|
|
14596
|
+
getHealthReport: () => getHealthReport,
|
|
14597
|
+
heartbeat: () => heartbeat,
|
|
14598
|
+
incrementTasksCompleted: () => incrementTasksCompleted,
|
|
14599
|
+
listAgentInstances: () => listAgentInstances,
|
|
14600
|
+
markCrashed: () => markCrashed,
|
|
14601
|
+
registerAgent: () => registerAgent,
|
|
14602
|
+
updateAgentStatus: () => updateAgentStatus
|
|
14603
|
+
});
|
|
14604
|
+
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
14605
|
+
import { and as and4, eq as eq6, inArray as inArray4, lt as lt2, sql as sql8 } from "drizzle-orm";
|
|
14606
|
+
function generateAgentId() {
|
|
14607
|
+
const now = /* @__PURE__ */ new Date();
|
|
14608
|
+
const ts = now.toISOString().replace(/[-:T]/g, "").substring(0, 14);
|
|
14609
|
+
const hex = randomBytes2(3).toString("hex");
|
|
14610
|
+
return `agt_${ts}_${hex}`;
|
|
14611
|
+
}
|
|
14612
|
+
async function registerAgent(opts, cwd) {
|
|
14613
|
+
const db = await getDb(cwd);
|
|
14614
|
+
const id = generateAgentId();
|
|
14615
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14616
|
+
const row = {
|
|
14617
|
+
id,
|
|
14618
|
+
agentType: opts.agentType,
|
|
14619
|
+
status: "starting",
|
|
14620
|
+
sessionId: opts.sessionId ?? null,
|
|
14621
|
+
taskId: opts.taskId ?? null,
|
|
14622
|
+
startedAt: now,
|
|
14623
|
+
lastHeartbeat: now,
|
|
14624
|
+
stoppedAt: null,
|
|
14625
|
+
errorCount: 0,
|
|
14626
|
+
totalTasksCompleted: 0,
|
|
14627
|
+
capacity: "1.0",
|
|
14628
|
+
metadataJson: opts.metadata ? JSON.stringify(opts.metadata) : "{}",
|
|
14629
|
+
parentAgentId: opts.parentAgentId ?? null
|
|
14630
|
+
};
|
|
14631
|
+
await db.insert(agentInstances).values(row);
|
|
14632
|
+
return row;
|
|
14633
|
+
}
|
|
14634
|
+
async function deregisterAgent(id, cwd) {
|
|
14635
|
+
const db = await getDb(cwd);
|
|
14636
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14637
|
+
const existing = await db.select().from(agentInstances).where(eq6(agentInstances.id, id)).get();
|
|
14638
|
+
if (!existing) return null;
|
|
14639
|
+
if (existing.status === "stopped") return existing;
|
|
14640
|
+
await db.update(agentInstances).set({ status: "stopped", stoppedAt: now }).where(eq6(agentInstances.id, id));
|
|
14641
|
+
return { ...existing, status: "stopped", stoppedAt: now };
|
|
14642
|
+
}
|
|
14643
|
+
async function heartbeat(id, cwd) {
|
|
14644
|
+
const db = await getDb(cwd);
|
|
14645
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
14646
|
+
const existing = await db.select().from(agentInstances).where(eq6(agentInstances.id, id)).get();
|
|
14647
|
+
if (!existing) return null;
|
|
14648
|
+
if (existing.status === "stopped" || existing.status === "crashed") {
|
|
14649
|
+
return existing.status;
|
|
14650
|
+
}
|
|
14651
|
+
await db.update(agentInstances).set({ lastHeartbeat: now }).where(eq6(agentInstances.id, id));
|
|
14652
|
+
return existing.status;
|
|
14653
|
+
}
|
|
14654
|
+
async function updateAgentStatus(id, opts, cwd) {
|
|
14655
|
+
const db = await getDb(cwd);
|
|
14656
|
+
const existing = await db.select().from(agentInstances).where(eq6(agentInstances.id, id)).get();
|
|
14657
|
+
if (!existing) return null;
|
|
14658
|
+
const updates = {
|
|
14659
|
+
status: opts.status
|
|
14660
|
+
};
|
|
14661
|
+
if (opts.taskId !== void 0) {
|
|
14662
|
+
updates.taskId = opts.taskId;
|
|
14663
|
+
}
|
|
14664
|
+
if (opts.status === "active") {
|
|
14665
|
+
updates.lastHeartbeat = (/* @__PURE__ */ new Date()).toISOString();
|
|
14666
|
+
}
|
|
14667
|
+
if (opts.status === "error" || opts.status === "crashed") {
|
|
14668
|
+
updates.errorCount = existing.errorCount + 1;
|
|
14669
|
+
if (opts.error) {
|
|
14670
|
+
const errorType = classifyError(new Error(opts.error));
|
|
14671
|
+
await db.insert(agentErrorLog).values({
|
|
14672
|
+
agentId: id,
|
|
14673
|
+
errorType,
|
|
14674
|
+
message: opts.error,
|
|
14675
|
+
occurredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
14676
|
+
});
|
|
14677
|
+
}
|
|
14678
|
+
}
|
|
14679
|
+
if (opts.status === "stopped") {
|
|
14680
|
+
updates.stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
14681
|
+
}
|
|
14682
|
+
await db.update(agentInstances).set(updates).where(eq6(agentInstances.id, id));
|
|
14683
|
+
return { ...existing, ...updates };
|
|
14684
|
+
}
|
|
14685
|
+
async function incrementTasksCompleted(id, cwd) {
|
|
14686
|
+
const db = await getDb(cwd);
|
|
14687
|
+
await db.update(agentInstances).set({ totalTasksCompleted: sql8`${agentInstances.totalTasksCompleted} + 1` }).where(eq6(agentInstances.id, id));
|
|
14688
|
+
}
|
|
14689
|
+
async function listAgentInstances(filters, cwd) {
|
|
14690
|
+
const db = await getDb(cwd);
|
|
14691
|
+
const conditions = [];
|
|
14692
|
+
if (filters?.status) {
|
|
14693
|
+
const statuses = Array.isArray(filters.status) ? filters.status : [filters.status];
|
|
14694
|
+
conditions.push(inArray4(agentInstances.status, statuses));
|
|
14695
|
+
}
|
|
14696
|
+
if (filters?.agentType) {
|
|
14697
|
+
const types = Array.isArray(filters.agentType) ? filters.agentType : [filters.agentType];
|
|
14698
|
+
conditions.push(inArray4(agentInstances.agentType, types));
|
|
14699
|
+
}
|
|
14700
|
+
if (filters?.sessionId) {
|
|
14701
|
+
conditions.push(eq6(agentInstances.sessionId, filters.sessionId));
|
|
14702
|
+
}
|
|
14703
|
+
if (filters?.parentAgentId) {
|
|
14704
|
+
conditions.push(eq6(agentInstances.parentAgentId, filters.parentAgentId));
|
|
14705
|
+
}
|
|
14706
|
+
if (conditions.length === 0) {
|
|
14707
|
+
return db.select().from(agentInstances).all();
|
|
14708
|
+
}
|
|
14709
|
+
return db.select().from(agentInstances).where(and4(...conditions)).all();
|
|
14710
|
+
}
|
|
14711
|
+
async function getAgentInstance(id, cwd) {
|
|
14712
|
+
const db = await getDb(cwd);
|
|
14713
|
+
const row = await db.select().from(agentInstances).where(eq6(agentInstances.id, id)).get();
|
|
14714
|
+
return row ?? null;
|
|
14715
|
+
}
|
|
14716
|
+
function classifyError(error40) {
|
|
14717
|
+
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
14718
|
+
for (const pattern of RETRIABLE_PATTERNS) {
|
|
14719
|
+
if (pattern.test(message)) return "retriable";
|
|
14720
|
+
}
|
|
14721
|
+
for (const pattern of PERMANENT_PATTERNS) {
|
|
14722
|
+
if (pattern.test(message)) return "permanent";
|
|
14723
|
+
}
|
|
14724
|
+
return "unknown";
|
|
14725
|
+
}
|
|
14726
|
+
async function getAgentErrorHistory(agentId, cwd) {
|
|
14727
|
+
const db = await getDb(cwd);
|
|
14728
|
+
return db.select().from(agentErrorLog).where(eq6(agentErrorLog.agentId, agentId)).all();
|
|
14729
|
+
}
|
|
14730
|
+
async function checkAgentHealth(thresholdMs = 3e4, cwd) {
|
|
14731
|
+
const db = await getDb(cwd);
|
|
14732
|
+
const cutoff = new Date(Date.now() - thresholdMs).toISOString();
|
|
14733
|
+
return db.select().from(agentInstances).where(
|
|
14734
|
+
and4(
|
|
14735
|
+
inArray4(agentInstances.status, ["active", "idle", "starting"]),
|
|
14736
|
+
lt2(agentInstances.lastHeartbeat, cutoff)
|
|
14737
|
+
)
|
|
14738
|
+
).all();
|
|
14739
|
+
}
|
|
14740
|
+
async function markCrashed(id, reason, cwd) {
|
|
14741
|
+
return updateAgentStatus(
|
|
14742
|
+
id,
|
|
14743
|
+
{ status: "crashed", error: reason ?? "Heartbeat timeout \u2014 agent presumed crashed" },
|
|
14744
|
+
cwd
|
|
14745
|
+
);
|
|
14746
|
+
}
|
|
14747
|
+
async function getHealthReport(thresholdMs = 3e4, cwd) {
|
|
14748
|
+
const allAgents = await listAgentInstances(void 0, cwd);
|
|
14749
|
+
const staleAgents = await checkAgentHealth(thresholdMs, cwd);
|
|
14750
|
+
const report = {
|
|
14751
|
+
total: allAgents.length,
|
|
14752
|
+
active: 0,
|
|
14753
|
+
idle: 0,
|
|
14754
|
+
starting: 0,
|
|
14755
|
+
error: 0,
|
|
14756
|
+
crashed: 0,
|
|
14757
|
+
stopped: 0,
|
|
14758
|
+
totalErrors: 0,
|
|
14759
|
+
staleAgents
|
|
14760
|
+
};
|
|
14761
|
+
for (const agent of allAgents) {
|
|
14762
|
+
switch (agent.status) {
|
|
14763
|
+
case "active":
|
|
14764
|
+
report.active++;
|
|
14765
|
+
break;
|
|
14766
|
+
case "idle":
|
|
14767
|
+
report.idle++;
|
|
14768
|
+
break;
|
|
14769
|
+
case "starting":
|
|
14770
|
+
report.starting++;
|
|
14771
|
+
break;
|
|
14772
|
+
case "error":
|
|
14773
|
+
report.error++;
|
|
14774
|
+
break;
|
|
14775
|
+
case "crashed":
|
|
14776
|
+
report.crashed++;
|
|
14777
|
+
break;
|
|
14778
|
+
case "stopped":
|
|
14779
|
+
report.stopped++;
|
|
14780
|
+
break;
|
|
14781
|
+
}
|
|
14782
|
+
report.totalErrors += agent.errorCount;
|
|
14783
|
+
}
|
|
14784
|
+
return report;
|
|
14785
|
+
}
|
|
14786
|
+
var RETRIABLE_PATTERNS, PERMANENT_PATTERNS;
|
|
14787
|
+
var init_registry2 = __esm({
|
|
14788
|
+
"packages/core/src/agents/registry.ts"() {
|
|
14789
|
+
"use strict";
|
|
14790
|
+
init_sqlite2();
|
|
14791
|
+
init_agent_schema();
|
|
14792
|
+
RETRIABLE_PATTERNS = [
|
|
14793
|
+
/timeout/i,
|
|
14794
|
+
/ECONNREFUSED/,
|
|
14795
|
+
/ECONNRESET/,
|
|
14796
|
+
/EPIPE/,
|
|
14797
|
+
/ETIMEDOUT/,
|
|
14798
|
+
/rate.?limit/i,
|
|
14799
|
+
/429/,
|
|
14800
|
+
/503/,
|
|
14801
|
+
/502/,
|
|
14802
|
+
/SQLITE_BUSY/i,
|
|
14803
|
+
/database is locked/i,
|
|
14804
|
+
/temporarily unavailable/i,
|
|
14805
|
+
/too many requests/i,
|
|
14806
|
+
/network/i,
|
|
14807
|
+
/socket hang up/i
|
|
14808
|
+
];
|
|
14809
|
+
PERMANENT_PATTERNS = [
|
|
14810
|
+
/permission denied/i,
|
|
14811
|
+
/EACCES/,
|
|
14812
|
+
/authentication/i,
|
|
14813
|
+
/unauthorized/i,
|
|
14814
|
+
/401/,
|
|
14815
|
+
/403/,
|
|
14816
|
+
/404/,
|
|
14817
|
+
/not found/i,
|
|
14818
|
+
/invalid.*token/i,
|
|
14819
|
+
/SQLITE_CONSTRAINT/i,
|
|
14820
|
+
/syntax error/i,
|
|
14821
|
+
/type error/i,
|
|
14822
|
+
/reference error/i
|
|
14823
|
+
];
|
|
14824
|
+
}
|
|
14825
|
+
});
|
|
14826
|
+
|
|
14827
14827
|
// packages/core/src/store/project-detect.ts
|
|
14828
14828
|
var project_detect_exports = {};
|
|
14829
14829
|
__export(project_detect_exports, {
|
|
@@ -17866,19 +17866,19 @@ async function queryAudit(options) {
|
|
|
17866
17866
|
try {
|
|
17867
17867
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
17868
17868
|
const { auditLog: auditLog2 } = await Promise.resolve().then(() => (init_tasks_schema(), tasks_schema_exports));
|
|
17869
|
-
const { and:
|
|
17869
|
+
const { and: and9, eq: eq12, gte: gte3, or: or4 } = await import("drizzle-orm");
|
|
17870
17870
|
const db = await getDb3(process.cwd());
|
|
17871
17871
|
const conditions = [];
|
|
17872
|
-
if (options?.sessionId) conditions.push(
|
|
17873
|
-
if (options?.domain) conditions.push(
|
|
17872
|
+
if (options?.sessionId) conditions.push(eq12(auditLog2.sessionId, options.sessionId));
|
|
17873
|
+
if (options?.domain) conditions.push(eq12(auditLog2.domain, options.domain));
|
|
17874
17874
|
if (options?.operation)
|
|
17875
17875
|
conditions.push(
|
|
17876
|
-
or4(
|
|
17876
|
+
or4(eq12(auditLog2.operation, options.operation), eq12(auditLog2.action, options.operation))
|
|
17877
17877
|
);
|
|
17878
|
-
if (options?.taskId) conditions.push(
|
|
17878
|
+
if (options?.taskId) conditions.push(eq12(auditLog2.taskId, options.taskId));
|
|
17879
17879
|
if (options?.since) conditions.push(gte3(auditLog2.timestamp, options.since));
|
|
17880
17880
|
const limit = options?.limit ?? 1e3;
|
|
17881
|
-
const rows = await db.select().from(auditLog2).where(conditions.length > 0 ?
|
|
17881
|
+
const rows = await db.select().from(auditLog2).where(conditions.length > 0 ? and9(...conditions) : void 0).orderBy(auditLog2.timestamp).limit(limit);
|
|
17882
17882
|
return rows.map((row) => ({
|
|
17883
17883
|
timestamp: row.timestamp,
|
|
17884
17884
|
sessionId: row.sessionId,
|
|
@@ -19102,6 +19102,7 @@ import { execFile as execFile3 } from "node:child_process";
|
|
|
19102
19102
|
import { randomUUID } from "node:crypto";
|
|
19103
19103
|
import { existsSync as existsSync33, constants as fsConstants3, readFileSync as readFileSync22, statSync as statSync8 } from "node:fs";
|
|
19104
19104
|
import { access as access3, mkdir as mkdir5, readFile as readFile6, rm as rm2, writeFile as writeFile5 } from "node:fs/promises";
|
|
19105
|
+
import { homedir as getHomedir } from "node:os";
|
|
19105
19106
|
import { dirname as dirname8, join as join37, resolve as resolve5 } from "node:path";
|
|
19106
19107
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
19107
19108
|
import { promisify as promisify3 } from "node:util";
|
|
@@ -19913,12 +19914,30 @@ function checkGlobalTemplates() {
|
|
|
19913
19914
|
fix: "cleo init (or restart MCP server)"
|
|
19914
19915
|
};
|
|
19915
19916
|
}
|
|
19917
|
+
const xdgContent = readFileSync22(injectionPath, "utf-8");
|
|
19918
|
+
const xdgVersion = xdgContent.match(/^Version:\s*(.+)$/m)?.[1]?.trim();
|
|
19919
|
+
const home = getHomedir();
|
|
19920
|
+
const legacyPath = join37(home, ".cleo", "templates", "CLEO-INJECTION.md");
|
|
19921
|
+
if (existsSync33(legacyPath)) {
|
|
19922
|
+
const legacyContent = readFileSync22(legacyPath, "utf-8");
|
|
19923
|
+
const legacyVersion = legacyContent.match(/^Version:\s*(.+)$/m)?.[1]?.trim();
|
|
19924
|
+
if (legacyVersion && xdgVersion && legacyVersion !== xdgVersion) {
|
|
19925
|
+
return {
|
|
19926
|
+
id: "global_templates",
|
|
19927
|
+
category: "global",
|
|
19928
|
+
status: "warning",
|
|
19929
|
+
message: `Legacy template version (${legacyVersion}) out of sync with XDG (${xdgVersion})`,
|
|
19930
|
+
details: { path: injectionPath, exists: true, xdgVersion, legacyVersion, legacyPath },
|
|
19931
|
+
fix: "npm install -g @cleocode/cleo (reinstall syncs both paths)"
|
|
19932
|
+
};
|
|
19933
|
+
}
|
|
19934
|
+
}
|
|
19916
19935
|
return {
|
|
19917
19936
|
id: "global_templates",
|
|
19918
19937
|
category: "global",
|
|
19919
19938
|
status: "passed",
|
|
19920
|
-
message:
|
|
19921
|
-
details: { path: injectionPath, exists: true },
|
|
19939
|
+
message: `Global injection template present (v${xdgVersion ?? "unknown"})`,
|
|
19940
|
+
details: { path: injectionPath, exists: true, version: xdgVersion },
|
|
19922
19941
|
fix: null
|
|
19923
19942
|
};
|
|
19924
19943
|
}
|
|
@@ -20061,8 +20080,8 @@ function detectEnvMode() {
|
|
|
20061
20080
|
const devKv = {};
|
|
20062
20081
|
const devLines = devContent.trim().split("\n");
|
|
20063
20082
|
for (let i = 1; i < devLines.length; i++) {
|
|
20064
|
-
const
|
|
20065
|
-
if (
|
|
20083
|
+
const eq12 = devLines[i].indexOf("=");
|
|
20084
|
+
if (eq12 > 0) devKv[devLines[i].slice(0, eq12).trim()] = devLines[i].slice(eq12 + 1).trim();
|
|
20066
20085
|
}
|
|
20067
20086
|
if (devKv["mode"] === "dev-ts" && devKv["source"]) {
|
|
20068
20087
|
const devSource = devKv["source"].replace(/\\/g, "/");
|
|
@@ -20375,7 +20394,7 @@ var init_config = __esm({
|
|
|
20375
20394
|
"session.autoStart": false,
|
|
20376
20395
|
"session.requireNotes": true,
|
|
20377
20396
|
"session.multiSession": false,
|
|
20378
|
-
"
|
|
20397
|
+
"enforcement.acceptance.mode": "block",
|
|
20379
20398
|
"lifecycle.mode": "strict"
|
|
20380
20399
|
}
|
|
20381
20400
|
},
|
|
@@ -20385,7 +20404,7 @@ var init_config = __esm({
|
|
|
20385
20404
|
"session.autoStart": false,
|
|
20386
20405
|
"session.requireNotes": false,
|
|
20387
20406
|
"session.multiSession": true,
|
|
20388
|
-
"
|
|
20407
|
+
"enforcement.acceptance.mode": "warn",
|
|
20389
20408
|
"lifecycle.mode": "advisory"
|
|
20390
20409
|
}
|
|
20391
20410
|
},
|
|
@@ -20395,7 +20414,7 @@ var init_config = __esm({
|
|
|
20395
20414
|
"session.autoStart": false,
|
|
20396
20415
|
"session.requireNotes": false,
|
|
20397
20416
|
"session.multiSession": true,
|
|
20398
|
-
"
|
|
20417
|
+
"enforcement.acceptance.mode": "off",
|
|
20399
20418
|
"lifecycle.mode": "off"
|
|
20400
20419
|
}
|
|
20401
20420
|
}
|
|
@@ -20774,13 +20793,13 @@ __export(pipeline_exports, {
|
|
|
20774
20793
|
listPipelines: () => listPipelines,
|
|
20775
20794
|
pipelineExists: () => pipelineExists
|
|
20776
20795
|
});
|
|
20777
|
-
import { and as
|
|
20796
|
+
import { and as and6, asc as asc3, desc as desc3, eq as eq9, sql as sql9 } from "drizzle-orm";
|
|
20778
20797
|
async function initializePipeline(taskId, options = {}) {
|
|
20779
20798
|
const db = await getDb();
|
|
20780
20799
|
const now = /* @__PURE__ */ new Date();
|
|
20781
20800
|
const startStage2 = options.startStage || "research";
|
|
20782
20801
|
const initialStatus = options.initialStatus || "active";
|
|
20783
|
-
const existing = await db.select().from(lifecyclePipelines).where(
|
|
20802
|
+
const existing = await db.select().from(lifecyclePipelines).where(eq9(lifecyclePipelines.taskId, taskId)).limit(1).all();
|
|
20784
20803
|
if (existing.length > 0) {
|
|
20785
20804
|
throw new CleoError(101 /* ALREADY_EXISTS */, `Pipeline already exists for task ${taskId}`);
|
|
20786
20805
|
}
|
|
@@ -20829,13 +20848,13 @@ async function initializePipeline(taskId, options = {}) {
|
|
|
20829
20848
|
}
|
|
20830
20849
|
async function getPipeline(taskId) {
|
|
20831
20850
|
const db = await getDb();
|
|
20832
|
-
const result = await db.select().from(lifecyclePipelines).where(
|
|
20851
|
+
const result = await db.select().from(lifecyclePipelines).where(eq9(lifecyclePipelines.taskId, taskId)).limit(1).all();
|
|
20833
20852
|
if (result.length === 0) {
|
|
20834
20853
|
return null;
|
|
20835
20854
|
}
|
|
20836
20855
|
const row = result[0];
|
|
20837
20856
|
const isActive = row.status === "active";
|
|
20838
|
-
const transitionResult = await db.select({ count: sql9`count(*)` }).from(lifecycleTransitions).where(
|
|
20857
|
+
const transitionResult = await db.select({ count: sql9`count(*)` }).from(lifecycleTransitions).where(eq9(lifecycleTransitions.pipelineId, row.id)).all();
|
|
20839
20858
|
const transitionCount = Number(transitionResult[0]?.count || 0);
|
|
20840
20859
|
return {
|
|
20841
20860
|
id: taskId,
|
|
@@ -20858,7 +20877,7 @@ async function advanceStage(taskId, options) {
|
|
|
20858
20877
|
if (!options.initiatedBy) {
|
|
20859
20878
|
throw new CleoError(2 /* INVALID_INPUT */, "advanceStage() requires initiatedBy agent/user");
|
|
20860
20879
|
}
|
|
20861
|
-
const pipelineResult = await db.select().from(lifecyclePipelines).where(
|
|
20880
|
+
const pipelineResult = await db.select().from(lifecyclePipelines).where(eq9(lifecyclePipelines.taskId, taskId)).limit(1).all();
|
|
20862
20881
|
if (pipelineResult.length === 0) {
|
|
20863
20882
|
throw new CleoError(4 /* NOT_FOUND */, `No pipeline found for task ${taskId}`);
|
|
20864
20883
|
}
|
|
@@ -20866,9 +20885,9 @@ async function advanceStage(taskId, options) {
|
|
|
20866
20885
|
const fromStage = pipeline2.currentStageId;
|
|
20867
20886
|
const toStage = options.toStage;
|
|
20868
20887
|
const currentStageResult = await db.select().from(lifecycleStages).where(
|
|
20869
|
-
|
|
20870
|
-
|
|
20871
|
-
|
|
20888
|
+
and6(
|
|
20889
|
+
eq9(lifecycleStages.pipelineId, pipeline2.id),
|
|
20890
|
+
eq9(lifecycleStages.stageName, fromStage)
|
|
20872
20891
|
)
|
|
20873
20892
|
).limit(1).all();
|
|
20874
20893
|
if (currentStageResult.length === 0) {
|
|
@@ -20879,9 +20898,9 @@ async function advanceStage(taskId, options) {
|
|
|
20879
20898
|
}
|
|
20880
20899
|
const currentStageRecord = currentStageResult[0];
|
|
20881
20900
|
const targetStageResult = await db.select().from(lifecycleStages).where(
|
|
20882
|
-
|
|
20883
|
-
|
|
20884
|
-
|
|
20901
|
+
and6(
|
|
20902
|
+
eq9(lifecycleStages.pipelineId, pipeline2.id),
|
|
20903
|
+
eq9(lifecycleStages.stageName, toStage)
|
|
20885
20904
|
)
|
|
20886
20905
|
).limit(1).all();
|
|
20887
20906
|
if (targetStageResult.length === 0) {
|
|
@@ -20894,14 +20913,14 @@ async function advanceStage(taskId, options) {
|
|
|
20894
20913
|
await db.update(lifecycleStages).set({
|
|
20895
20914
|
status: "completed",
|
|
20896
20915
|
completedAt: now.toISOString()
|
|
20897
|
-
}).where(
|
|
20916
|
+
}).where(eq9(lifecycleStages.id, currentStageRecord.id)).run();
|
|
20898
20917
|
await db.update(lifecycleStages).set({
|
|
20899
20918
|
status: "in_progress",
|
|
20900
20919
|
startedAt: now.toISOString()
|
|
20901
|
-
}).where(
|
|
20920
|
+
}).where(eq9(lifecycleStages.id, targetStageRecord.id)).run();
|
|
20902
20921
|
await db.update(lifecyclePipelines).set({
|
|
20903
20922
|
currentStageId: toStage
|
|
20904
|
-
}).where(
|
|
20923
|
+
}).where(eq9(lifecyclePipelines.id, pipeline2.id)).run();
|
|
20905
20924
|
await db.insert(lifecycleTransitions).values({
|
|
20906
20925
|
id: `${pipeline2.id}_${now.getTime()}_${Math.random().toString(36).slice(2, 7)}`,
|
|
20907
20926
|
pipelineId: pipeline2.id,
|
|
@@ -20918,7 +20937,7 @@ async function advanceStage(taskId, options) {
|
|
|
20918
20937
|
}
|
|
20919
20938
|
async function getCurrentStage(taskId) {
|
|
20920
20939
|
const db = await getDb();
|
|
20921
|
-
const result = await db.select({ currentStageId: lifecyclePipelines.currentStageId }).from(lifecyclePipelines).where(
|
|
20940
|
+
const result = await db.select({ currentStageId: lifecyclePipelines.currentStageId }).from(lifecyclePipelines).where(eq9(lifecyclePipelines.taskId, taskId)).limit(1).all();
|
|
20922
20941
|
if (result.length === 0) {
|
|
20923
20942
|
throw new CleoError(4 /* NOT_FOUND */, `No pipeline found for task ${taskId}`);
|
|
20924
20943
|
}
|
|
@@ -20930,43 +20949,43 @@ async function listPipelines(options = {}) {
|
|
|
20930
20949
|
const conditions = [];
|
|
20931
20950
|
if (options.status) {
|
|
20932
20951
|
conditions.push(
|
|
20933
|
-
|
|
20952
|
+
eq9(
|
|
20934
20953
|
lifecyclePipelines.status,
|
|
20935
20954
|
options.status
|
|
20936
20955
|
)
|
|
20937
20956
|
);
|
|
20938
20957
|
}
|
|
20939
20958
|
if (options.currentStage) {
|
|
20940
|
-
conditions.push(
|
|
20959
|
+
conditions.push(eq9(lifecyclePipelines.currentStageId, options.currentStage));
|
|
20941
20960
|
}
|
|
20942
20961
|
if (conditions.length > 0) {
|
|
20943
|
-
const whereClause = conditions.length === 1 ? conditions[0] :
|
|
20962
|
+
const whereClause = conditions.length === 1 ? conditions[0] : and6(...conditions);
|
|
20944
20963
|
query = db.select().from(lifecyclePipelines).where(whereClause);
|
|
20945
20964
|
}
|
|
20946
20965
|
if (options.orderBy) {
|
|
20947
20966
|
const order = options.order === "asc" ? asc3 : desc3;
|
|
20948
20967
|
switch (options.orderBy) {
|
|
20949
20968
|
case "createdAt":
|
|
20950
|
-
query = db.select().from(lifecyclePipelines).where(conditions.length > 0 ?
|
|
20969
|
+
query = db.select().from(lifecyclePipelines).where(conditions.length > 0 ? and6(...conditions) : void 0).orderBy(order(lifecyclePipelines.startedAt));
|
|
20951
20970
|
break;
|
|
20952
20971
|
case "currentStage":
|
|
20953
|
-
query = db.select().from(lifecyclePipelines).where(conditions.length > 0 ?
|
|
20972
|
+
query = db.select().from(lifecyclePipelines).where(conditions.length > 0 ? and6(...conditions) : void 0).orderBy(order(lifecyclePipelines.currentStageId));
|
|
20954
20973
|
break;
|
|
20955
20974
|
}
|
|
20956
20975
|
} else {
|
|
20957
|
-
query = db.select().from(lifecyclePipelines).where(conditions.length > 0 ?
|
|
20976
|
+
query = db.select().from(lifecyclePipelines).where(conditions.length > 0 ? and6(...conditions) : void 0).orderBy(desc3(lifecyclePipelines.startedAt));
|
|
20958
20977
|
}
|
|
20959
20978
|
if (options.limit) {
|
|
20960
|
-
query = db.select().from(lifecyclePipelines).where(conditions.length > 0 ?
|
|
20979
|
+
query = db.select().from(lifecyclePipelines).where(conditions.length > 0 ? and6(...conditions) : void 0).orderBy(desc3(lifecyclePipelines.startedAt)).limit(options.limit);
|
|
20961
20980
|
}
|
|
20962
20981
|
if (options.offset) {
|
|
20963
|
-
query = db.select().from(lifecyclePipelines).where(conditions.length > 0 ?
|
|
20982
|
+
query = db.select().from(lifecyclePipelines).where(conditions.length > 0 ? and6(...conditions) : void 0).orderBy(desc3(lifecyclePipelines.startedAt)).limit(options.limit || 100).offset(options.offset);
|
|
20964
20983
|
}
|
|
20965
20984
|
const results = await query.all();
|
|
20966
20985
|
return Promise.all(
|
|
20967
20986
|
results.map(async (row) => {
|
|
20968
20987
|
const isActive = row.status === "active";
|
|
20969
|
-
const transitionResult = await db.select({ count: sql9`count(*)` }).from(lifecycleTransitions).where(
|
|
20988
|
+
const transitionResult = await db.select({ count: sql9`count(*)` }).from(lifecycleTransitions).where(eq9(lifecycleTransitions.pipelineId, row.id)).all();
|
|
20970
20989
|
const transitionCount = Number(transitionResult[0]?.count || 0);
|
|
20971
20990
|
return {
|
|
20972
20991
|
id: row.taskId,
|
|
@@ -20985,7 +21004,7 @@ async function listPipelines(options = {}) {
|
|
|
20985
21004
|
async function completePipeline(taskId, reason) {
|
|
20986
21005
|
const db = await getDb();
|
|
20987
21006
|
const now = /* @__PURE__ */ new Date();
|
|
20988
|
-
const pipelineResult = await db.select().from(lifecyclePipelines).where(
|
|
21007
|
+
const pipelineResult = await db.select().from(lifecyclePipelines).where(eq9(lifecyclePipelines.taskId, taskId)).limit(1).all();
|
|
20989
21008
|
if (pipelineResult.length === 0) {
|
|
20990
21009
|
throw new CleoError(4 /* NOT_FOUND */, `No pipeline found for task ${taskId}`);
|
|
20991
21010
|
}
|
|
@@ -21000,21 +21019,21 @@ async function completePipeline(taskId, reason) {
|
|
|
21000
21019
|
stageUpdate.metadataJson = JSON.stringify({ completionReason: reason });
|
|
21001
21020
|
}
|
|
21002
21021
|
await db.update(lifecycleStages).set(stageUpdate).where(
|
|
21003
|
-
|
|
21004
|
-
|
|
21005
|
-
|
|
21022
|
+
and6(
|
|
21023
|
+
eq9(lifecycleStages.pipelineId, pipeline2.id),
|
|
21024
|
+
eq9(lifecycleStages.stageName, pipeline2.currentStageId)
|
|
21006
21025
|
)
|
|
21007
21026
|
).run();
|
|
21008
21027
|
}
|
|
21009
21028
|
await db.update(lifecyclePipelines).set({
|
|
21010
21029
|
status: "completed",
|
|
21011
21030
|
completedAt: now.toISOString()
|
|
21012
|
-
}).where(
|
|
21031
|
+
}).where(eq9(lifecyclePipelines.id, pipeline2.id)).run();
|
|
21013
21032
|
}
|
|
21014
21033
|
async function cancelPipeline(taskId, reason) {
|
|
21015
21034
|
const db = await getDb();
|
|
21016
21035
|
const now = /* @__PURE__ */ new Date();
|
|
21017
|
-
const pipelineResult = await db.select().from(lifecyclePipelines).where(
|
|
21036
|
+
const pipelineResult = await db.select().from(lifecyclePipelines).where(eq9(lifecyclePipelines.taskId, taskId)).limit(1).all();
|
|
21018
21037
|
if (pipelineResult.length === 0) {
|
|
21019
21038
|
throw new CleoError(4 /* NOT_FOUND */, `No pipeline found for task ${taskId}`);
|
|
21020
21039
|
}
|
|
@@ -21031,20 +21050,20 @@ async function cancelPipeline(taskId, reason) {
|
|
|
21031
21050
|
blockedAt: now.toISOString(),
|
|
21032
21051
|
blockReason: `Pipeline cancelled: ${reason}`
|
|
21033
21052
|
}).where(
|
|
21034
|
-
|
|
21035
|
-
|
|
21036
|
-
|
|
21053
|
+
and6(
|
|
21054
|
+
eq9(lifecycleStages.pipelineId, pipeline2.id),
|
|
21055
|
+
eq9(lifecycleStages.stageName, pipeline2.currentStageId)
|
|
21037
21056
|
)
|
|
21038
21057
|
).run();
|
|
21039
21058
|
}
|
|
21040
21059
|
await db.update(lifecyclePipelines).set({
|
|
21041
21060
|
status: "cancelled",
|
|
21042
21061
|
completedAt: now.toISOString()
|
|
21043
|
-
}).where(
|
|
21062
|
+
}).where(eq9(lifecyclePipelines.id, pipeline2.id)).run();
|
|
21044
21063
|
}
|
|
21045
21064
|
async function pipelineExists(taskId) {
|
|
21046
21065
|
const db = await getDb();
|
|
21047
|
-
const result = await db.select({ count: sql9`count(*)` }).from(lifecyclePipelines).where(
|
|
21066
|
+
const result = await db.select({ count: sql9`count(*)` }).from(lifecyclePipelines).where(eq9(lifecyclePipelines.taskId, taskId)).all();
|
|
21048
21067
|
return (result[0]?.count || 0) > 0;
|
|
21049
21068
|
}
|
|
21050
21069
|
async function getPipelineStatistics() {
|
|
@@ -21088,12 +21107,12 @@ async function getPipelineStatistics() {
|
|
|
21088
21107
|
}
|
|
21089
21108
|
async function getPipelineStages(taskId) {
|
|
21090
21109
|
const db = await getDb();
|
|
21091
|
-
const pipelineResult = await db.select({ id: lifecyclePipelines.id }).from(lifecyclePipelines).where(
|
|
21110
|
+
const pipelineResult = await db.select({ id: lifecyclePipelines.id }).from(lifecyclePipelines).where(eq9(lifecyclePipelines.taskId, taskId)).limit(1).all();
|
|
21092
21111
|
if (pipelineResult.length === 0) {
|
|
21093
21112
|
throw new CleoError(4 /* NOT_FOUND */, `No pipeline found for task ${taskId}`);
|
|
21094
21113
|
}
|
|
21095
21114
|
const pipelineId = pipelineResult[0].id;
|
|
21096
|
-
const stages = await db.select().from(lifecycleStages).where(
|
|
21115
|
+
const stages = await db.select().from(lifecycleStages).where(eq9(lifecycleStages.pipelineId, pipelineId)).orderBy(asc3(lifecycleStages.sequence)).all();
|
|
21097
21116
|
return stages.map((stage) => ({
|
|
21098
21117
|
id: stage.id,
|
|
21099
21118
|
pipelineId: stage.pipelineId,
|
|
@@ -23949,9 +23968,9 @@ async function nexusRegister(projectPath, name2, permissions = "read") {
|
|
|
23949
23968
|
const projectHash = generateProjectHash(projectPath);
|
|
23950
23969
|
await nexusInit();
|
|
23951
23970
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
23952
|
-
const { eq:
|
|
23971
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
23953
23972
|
const db = await getNexusDb2();
|
|
23954
|
-
const existingRows = await db.select().from(projectRegistry).where(
|
|
23973
|
+
const existingRows = await db.select().from(projectRegistry).where(eq12(projectRegistry.projectHash, projectHash));
|
|
23955
23974
|
const existing = existingRows[0];
|
|
23956
23975
|
if (existing?.permissions) {
|
|
23957
23976
|
throw new CleoError(
|
|
@@ -23960,7 +23979,7 @@ async function nexusRegister(projectPath, name2, permissions = "read") {
|
|
|
23960
23979
|
);
|
|
23961
23980
|
}
|
|
23962
23981
|
if (!existing) {
|
|
23963
|
-
const nameConflictRows = await db.select().from(projectRegistry).where(
|
|
23982
|
+
const nameConflictRows = await db.select().from(projectRegistry).where(eq12(projectRegistry.name, projectName));
|
|
23964
23983
|
if (nameConflictRows.length > 0) {
|
|
23965
23984
|
throw new CleoError(
|
|
23966
23985
|
6 /* VALIDATION_ERROR */,
|
|
@@ -23978,7 +23997,7 @@ async function nexusRegister(projectPath, name2, permissions = "read") {
|
|
|
23978
23997
|
taskCount: meta.taskCount,
|
|
23979
23998
|
labelsJson: JSON.stringify(meta.labels),
|
|
23980
23999
|
lastSeen: now
|
|
23981
|
-
}).where(
|
|
24000
|
+
}).where(eq12(projectRegistry.projectHash, projectHash));
|
|
23982
24001
|
} else {
|
|
23983
24002
|
if (!projectId) {
|
|
23984
24003
|
projectId = randomUUID3();
|
|
@@ -24016,9 +24035,9 @@ async function nexusUnregister(nameOrHash) {
|
|
|
24016
24035
|
throw new CleoError(4 /* NOT_FOUND */, `Project not found in registry: ${nameOrHash}`);
|
|
24017
24036
|
}
|
|
24018
24037
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
24019
|
-
const { eq:
|
|
24038
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
24020
24039
|
const db = await getNexusDb2();
|
|
24021
|
-
await db.delete(projectRegistry).where(
|
|
24040
|
+
await db.delete(projectRegistry).where(eq12(projectRegistry.projectHash, project.hash));
|
|
24022
24041
|
await writeNexusAudit({
|
|
24023
24042
|
action: "unregister",
|
|
24024
24043
|
projectHash: project.hash,
|
|
@@ -24040,9 +24059,9 @@ async function nexusList() {
|
|
|
24040
24059
|
async function nexusGetProject(nameOrHash) {
|
|
24041
24060
|
try {
|
|
24042
24061
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
24043
|
-
const { eq:
|
|
24062
|
+
const { eq: eq12, or: or4 } = await import("drizzle-orm");
|
|
24044
24063
|
const db = await getNexusDb2();
|
|
24045
|
-
const rows = await db.select().from(projectRegistry).where(or4(
|
|
24064
|
+
const rows = await db.select().from(projectRegistry).where(or4(eq12(projectRegistry.projectHash, nameOrHash), eq12(projectRegistry.name, nameOrHash)));
|
|
24046
24065
|
const row = rows[0];
|
|
24047
24066
|
if (!row) return null;
|
|
24048
24067
|
return rowToProject(row);
|
|
@@ -24065,14 +24084,14 @@ async function nexusSync(nameOrHash) {
|
|
|
24065
24084
|
const meta = await readProjectMeta(project.path);
|
|
24066
24085
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
24067
24086
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
24068
|
-
const { eq:
|
|
24087
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
24069
24088
|
const db = await getNexusDb2();
|
|
24070
24089
|
await db.update(projectRegistry).set({
|
|
24071
24090
|
taskCount: meta.taskCount,
|
|
24072
24091
|
labelsJson: JSON.stringify(meta.labels),
|
|
24073
24092
|
lastSync: now,
|
|
24074
24093
|
lastSeen: now
|
|
24075
|
-
}).where(
|
|
24094
|
+
}).where(eq12(projectRegistry.projectHash, project.hash));
|
|
24076
24095
|
await writeNexusAudit({
|
|
24077
24096
|
action: "sync",
|
|
24078
24097
|
projectHash: project.hash,
|
|
@@ -24086,7 +24105,7 @@ async function nexusSyncAll() {
|
|
|
24086
24105
|
let synced = 0;
|
|
24087
24106
|
let failed = 0;
|
|
24088
24107
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
24089
|
-
const { eq:
|
|
24108
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
24090
24109
|
const db = await getNexusDb2();
|
|
24091
24110
|
for (const project of projects) {
|
|
24092
24111
|
try {
|
|
@@ -24097,7 +24116,7 @@ async function nexusSyncAll() {
|
|
|
24097
24116
|
labelsJson: JSON.stringify(meta.labels),
|
|
24098
24117
|
lastSync: now,
|
|
24099
24118
|
lastSeen: now
|
|
24100
|
-
}).where(
|
|
24119
|
+
}).where(eq12(projectRegistry.projectHash, project.hash));
|
|
24101
24120
|
synced++;
|
|
24102
24121
|
} catch {
|
|
24103
24122
|
failed++;
|
|
@@ -24117,9 +24136,9 @@ async function nexusSetPermission(nameOrHash, permission) {
|
|
|
24117
24136
|
throw new CleoError(4 /* NOT_FOUND */, `Project not found in registry: ${nameOrHash}`);
|
|
24118
24137
|
}
|
|
24119
24138
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
24120
|
-
const { eq:
|
|
24139
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
24121
24140
|
const db = await getNexusDb2();
|
|
24122
|
-
await db.update(projectRegistry).set({ permissions: permission }).where(
|
|
24141
|
+
await db.update(projectRegistry).set({ permissions: permission }).where(eq12(projectRegistry.projectHash, project.hash));
|
|
24123
24142
|
await writeNexusAudit({
|
|
24124
24143
|
action: "set-permission",
|
|
24125
24144
|
projectHash: project.hash,
|
|
@@ -24135,12 +24154,12 @@ async function nexusReconcile(projectRoot) {
|
|
|
24135
24154
|
}
|
|
24136
24155
|
await nexusInit();
|
|
24137
24156
|
const { getNexusDb: getNexusDb2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
24138
|
-
const { eq:
|
|
24157
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
24139
24158
|
const db = await getNexusDb2();
|
|
24140
24159
|
const projectId = await readProjectId(projectRoot);
|
|
24141
24160
|
const currentHash = generateProjectHash(projectRoot);
|
|
24142
24161
|
if (projectId) {
|
|
24143
|
-
const hashRows2 = await db.select().from(projectRegistry).where(
|
|
24162
|
+
const hashRows2 = await db.select().from(projectRegistry).where(eq12(projectRegistry.projectHash, currentHash));
|
|
24144
24163
|
const hashMatch2 = hashRows2[0];
|
|
24145
24164
|
if (hashMatch2 && hashMatch2.projectId !== projectId) {
|
|
24146
24165
|
await writeNexusAudit({
|
|
@@ -24159,12 +24178,12 @@ async function nexusReconcile(projectRoot) {
|
|
|
24159
24178
|
}
|
|
24160
24179
|
}
|
|
24161
24180
|
if (projectId) {
|
|
24162
|
-
const idRows = await db.select().from(projectRegistry).where(
|
|
24181
|
+
const idRows = await db.select().from(projectRegistry).where(eq12(projectRegistry.projectId, projectId));
|
|
24163
24182
|
const existing = idRows[0];
|
|
24164
24183
|
if (existing) {
|
|
24165
24184
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
24166
24185
|
if (existing.projectPath === projectRoot) {
|
|
24167
|
-
await db.update(projectRegistry).set({ lastSeen: now }).where(
|
|
24186
|
+
await db.update(projectRegistry).set({ lastSeen: now }).where(eq12(projectRegistry.projectId, projectId));
|
|
24168
24187
|
await writeNexusAudit({
|
|
24169
24188
|
action: "reconcile",
|
|
24170
24189
|
projectHash: currentHash,
|
|
@@ -24180,7 +24199,7 @@ async function nexusReconcile(projectRoot) {
|
|
|
24180
24199
|
projectPath: projectRoot,
|
|
24181
24200
|
projectHash: currentHash,
|
|
24182
24201
|
lastSeen: now
|
|
24183
|
-
}).where(
|
|
24202
|
+
}).where(eq12(projectRegistry.projectId, projectId));
|
|
24184
24203
|
await writeNexusAudit({
|
|
24185
24204
|
action: "reconcile",
|
|
24186
24205
|
projectHash: currentHash,
|
|
@@ -24192,11 +24211,11 @@ async function nexusReconcile(projectRoot) {
|
|
|
24192
24211
|
return { status: "path_updated", oldPath, newPath: projectRoot };
|
|
24193
24212
|
}
|
|
24194
24213
|
}
|
|
24195
|
-
const hashRows = await db.select().from(projectRegistry).where(
|
|
24214
|
+
const hashRows = await db.select().from(projectRegistry).where(eq12(projectRegistry.projectHash, currentHash));
|
|
24196
24215
|
const hashMatch = hashRows[0];
|
|
24197
24216
|
if (hashMatch) {
|
|
24198
24217
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
24199
|
-
await db.update(projectRegistry).set({ lastSeen: now }).where(
|
|
24218
|
+
await db.update(projectRegistry).set({ lastSeen: now }).where(eq12(projectRegistry.projectHash, currentHash));
|
|
24200
24219
|
await writeNexusAudit({
|
|
24201
24220
|
action: "reconcile",
|
|
24202
24221
|
projectHash: currentHash,
|
|
@@ -26401,7 +26420,7 @@ async function syncAdrsToDb(projectRoot) {
|
|
|
26401
26420
|
return result;
|
|
26402
26421
|
}
|
|
26403
26422
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
26404
|
-
const { eq:
|
|
26423
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
26405
26424
|
const db = await getDb3(projectRoot);
|
|
26406
26425
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26407
26426
|
const allFiles = collectAdrFiles(adrsDir);
|
|
@@ -26435,15 +26454,15 @@ async function syncAdrsToDb(projectRoot) {
|
|
|
26435
26454
|
topics: fm.Topics ?? null,
|
|
26436
26455
|
updatedAt: now
|
|
26437
26456
|
};
|
|
26438
|
-
const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(
|
|
26457
|
+
const existing = await db.select({ id: architectureDecisions.id }).from(architectureDecisions).where(eq12(architectureDecisions.id, record2.id)).all();
|
|
26439
26458
|
if (existing.length > 0) {
|
|
26440
|
-
await db.update(architectureDecisions).set(rowBase).where(
|
|
26459
|
+
await db.update(architectureDecisions).set(rowBase).where(eq12(architectureDecisions.id, record2.id));
|
|
26441
26460
|
result.updated++;
|
|
26442
26461
|
} else {
|
|
26443
26462
|
await db.insert(architectureDecisions).values({ ...rowBase, createdAt: now });
|
|
26444
26463
|
result.inserted++;
|
|
26445
26464
|
}
|
|
26446
|
-
await db.delete(adrTaskLinks).where(
|
|
26465
|
+
await db.delete(adrTaskLinks).where(eq12(adrTaskLinks.adrId, record2.id));
|
|
26447
26466
|
if (fm["Related Tasks"]) {
|
|
26448
26467
|
for (const taskId of parseTaskIds2(fm["Related Tasks"])) {
|
|
26449
26468
|
await db.insert(adrTaskLinks).values({ adrId: record2.id, taskId, linkType: "related" });
|
|
@@ -26545,18 +26564,27 @@ __export(agents_exports, {
|
|
|
26545
26564
|
AGENT_INSTANCE_STATUSES: () => AGENT_INSTANCE_STATUSES,
|
|
26546
26565
|
AGENT_TYPES: () => AGENT_TYPES,
|
|
26547
26566
|
DEFAULT_RETRY_POLICY: () => DEFAULT_RETRY_POLICY,
|
|
26567
|
+
HEARTBEAT_INTERVAL_MS: () => HEARTBEAT_INTERVAL_MS,
|
|
26568
|
+
MAX_TASKS_PER_AGENT: () => MAX_TASKS_PER_AGENT,
|
|
26569
|
+
STALE_THRESHOLD_MS: () => STALE_THRESHOLD_MS,
|
|
26548
26570
|
agentErrorLog: () => agentErrorLog,
|
|
26549
26571
|
agentInstances: () => agentInstances,
|
|
26550
26572
|
calculateDelay: () => calculateDelay,
|
|
26551
|
-
checkAgentHealth: () =>
|
|
26573
|
+
checkAgentHealth: () => checkAgentHealth2,
|
|
26552
26574
|
classifyError: () => classifyError,
|
|
26553
26575
|
createRetryPolicy: () => createRetryPolicy,
|
|
26554
26576
|
deregisterAgent: () => deregisterAgent,
|
|
26577
|
+
detectCrashedAgents: () => detectCrashedAgents,
|
|
26578
|
+
detectStaleAgents: () => detectStaleAgents,
|
|
26555
26579
|
findLeastLoadedAgent: () => findLeastLoadedAgent,
|
|
26580
|
+
findStaleAgentRows: () => checkAgentHealth,
|
|
26556
26581
|
generateAgentId: () => generateAgentId,
|
|
26582
|
+
getAgentCapacity: () => getAgentCapacity,
|
|
26557
26583
|
getAgentErrorHistory: () => getAgentErrorHistory,
|
|
26558
26584
|
getAgentInstance: () => getAgentInstance,
|
|
26559
26585
|
getAgentPerformanceHistory: () => getAgentPerformanceHistory,
|
|
26586
|
+
getAgentSpecializations: () => getAgentSpecializations,
|
|
26587
|
+
getAgentsByCapacity: () => getAgentsByCapacity,
|
|
26560
26588
|
getAvailableCapacity: () => getAvailableCapacity,
|
|
26561
26589
|
getCapacitySummary: () => getCapacitySummary,
|
|
26562
26590
|
getHealthReport: () => getHealthReport,
|
|
@@ -26568,85 +26596,35 @@ __export(agents_exports, {
|
|
|
26568
26596
|
markCrashed: () => markCrashed,
|
|
26569
26597
|
processAgentLifecycleEvent: () => processAgentLifecycleEvent,
|
|
26570
26598
|
recordAgentExecution: () => recordAgentExecution,
|
|
26599
|
+
recordAgentPerformance: () => recordAgentPerformance,
|
|
26571
26600
|
recordFailurePattern: () => recordFailurePattern,
|
|
26601
|
+
recordHeartbeat: () => recordHeartbeat,
|
|
26572
26602
|
recoverCrashedAgents: () => recoverCrashedAgents,
|
|
26573
26603
|
registerAgent: () => registerAgent,
|
|
26574
26604
|
shouldRetry: () => shouldRetry,
|
|
26575
26605
|
storeHealingStrategy: () => storeHealingStrategy,
|
|
26606
|
+
updateAgentSpecializations: () => updateAgentSpecializations,
|
|
26576
26607
|
updateAgentStatus: () => updateAgentStatus,
|
|
26577
26608
|
updateCapacity: () => updateCapacity,
|
|
26578
26609
|
withRetry: () => withRetry
|
|
26579
26610
|
});
|
|
26580
|
-
init_agent_schema();
|
|
26581
26611
|
|
|
26582
|
-
// packages/core/src/agents/
|
|
26612
|
+
// packages/core/src/agents/agent-registry.ts
|
|
26583
26613
|
init_sqlite2();
|
|
26584
26614
|
init_agent_schema();
|
|
26585
|
-
|
|
26586
|
-
import { eq as eq6 } from "drizzle-orm";
|
|
26587
|
-
async function updateCapacity(id, capacity, cwd) {
|
|
26588
|
-
if (capacity < 0 || capacity > 1) {
|
|
26589
|
-
throw new Error(`Capacity must be between 0.0 and 1.0, got ${capacity}`);
|
|
26590
|
-
}
|
|
26591
|
-
const db = await getDb(cwd);
|
|
26592
|
-
const existing = await db.select().from(agentInstances).where(eq6(agentInstances.id, id)).get();
|
|
26593
|
-
if (!existing) return null;
|
|
26594
|
-
const capacityStr = capacity.toFixed(4);
|
|
26595
|
-
await db.update(agentInstances).set({ capacity: capacityStr }).where(eq6(agentInstances.id, id));
|
|
26596
|
-
return { ...existing, capacity: capacityStr };
|
|
26597
|
-
}
|
|
26598
|
-
async function getAvailableCapacity(cwd) {
|
|
26599
|
-
const agents = await listAgentInstances({ status: ["active", "idle"] }, cwd);
|
|
26600
|
-
return agents.reduce((sum, agent) => sum + parseCapacity(agent.capacity), 0);
|
|
26601
|
-
}
|
|
26602
|
-
async function findLeastLoadedAgent(agentType, cwd) {
|
|
26603
|
-
const filters = agentType ? { status: ["active", "idle"], agentType } : { status: ["active", "idle"] };
|
|
26604
|
-
const agents = await listAgentInstances(filters, cwd);
|
|
26605
|
-
if (agents.length === 0) return null;
|
|
26606
|
-
let best = agents[0];
|
|
26607
|
-
let bestCapacity = parseCapacity(best.capacity);
|
|
26608
|
-
for (let i = 1; i < agents.length; i++) {
|
|
26609
|
-
const cap = parseCapacity(agents[i].capacity);
|
|
26610
|
-
if (cap > bestCapacity) {
|
|
26611
|
-
best = agents[i];
|
|
26612
|
-
bestCapacity = cap;
|
|
26613
|
-
}
|
|
26614
|
-
}
|
|
26615
|
-
return best;
|
|
26616
|
-
}
|
|
26617
|
-
async function isOverloaded(threshold = 0.1, cwd) {
|
|
26618
|
-
const capacity = await getAvailableCapacity(cwd);
|
|
26619
|
-
return capacity < threshold;
|
|
26620
|
-
}
|
|
26621
|
-
async function getCapacitySummary(threshold = 0.1, cwd) {
|
|
26622
|
-
const agents = await listAgentInstances({ status: ["active", "idle"] }, cwd);
|
|
26623
|
-
const totalCapacity = agents.reduce((sum, a) => sum + parseCapacity(a.capacity), 0);
|
|
26624
|
-
const activeAgentCount = agents.length;
|
|
26625
|
-
return {
|
|
26626
|
-
totalCapacity,
|
|
26627
|
-
activeAgentCount,
|
|
26628
|
-
averageCapacity: activeAgentCount > 0 ? totalCapacity / activeAgentCount : 0,
|
|
26629
|
-
overloaded: totalCapacity < threshold,
|
|
26630
|
-
threshold
|
|
26631
|
-
};
|
|
26632
|
-
}
|
|
26633
|
-
function parseCapacity(value) {
|
|
26634
|
-
if (!value) return 0;
|
|
26635
|
-
const parsed = parseFloat(value);
|
|
26636
|
-
return Number.isNaN(parsed) ? 0 : Math.max(0, Math.min(1, parsed));
|
|
26637
|
-
}
|
|
26615
|
+
import { and as and5, eq as eq7, inArray as inArray5 } from "drizzle-orm";
|
|
26638
26616
|
|
|
26639
26617
|
// packages/core/src/agents/execution-learning.ts
|
|
26640
26618
|
init_brain_accessor();
|
|
26641
|
-
import { randomBytes
|
|
26619
|
+
import { randomBytes } from "node:crypto";
|
|
26642
26620
|
function generateDecisionId() {
|
|
26643
|
-
return `AGT-${
|
|
26621
|
+
return `AGT-${randomBytes(5).toString("hex")}`;
|
|
26644
26622
|
}
|
|
26645
26623
|
function generatePatternId() {
|
|
26646
|
-
return `P-agt-${
|
|
26624
|
+
return `P-agt-${randomBytes(4).toString("hex")}`;
|
|
26647
26625
|
}
|
|
26648
26626
|
function generateObservationId() {
|
|
26649
|
-
return `O-agt-${
|
|
26627
|
+
return `O-agt-${randomBytes(4).toString("hex")}`;
|
|
26650
26628
|
}
|
|
26651
26629
|
function nowSql() {
|
|
26652
26630
|
return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
@@ -26923,6 +26901,215 @@ function buildHealingSuggestion(agentType, taskType, errorType, frequency) {
|
|
|
26923
26901
|
return `Unknown failure for ${agentType} on ${taskType} tasks (${frequency}x). Check agent logs, retry with fresh context, or reassign to a different agent type.`;
|
|
26924
26902
|
}
|
|
26925
26903
|
|
|
26904
|
+
// packages/core/src/agents/agent-registry.ts
|
|
26905
|
+
init_registry2();
|
|
26906
|
+
var MAX_TASKS_PER_AGENT = 5;
|
|
26907
|
+
async function getAgentCapacity(agentId, cwd) {
|
|
26908
|
+
const db = await getDb(cwd);
|
|
26909
|
+
const agent = await db.select().from(agentInstances).where(eq7(agentInstances.id, agentId)).get();
|
|
26910
|
+
if (!agent) return null;
|
|
26911
|
+
const isTerminal = agent.status === "stopped" || agent.status === "crashed";
|
|
26912
|
+
if (isTerminal) {
|
|
26913
|
+
return {
|
|
26914
|
+
agentId: agent.id,
|
|
26915
|
+
agentType: agent.agentType,
|
|
26916
|
+
status: agent.status,
|
|
26917
|
+
activeTasks: 0,
|
|
26918
|
+
remainingCapacity: 0,
|
|
26919
|
+
maxCapacity: MAX_TASKS_PER_AGENT,
|
|
26920
|
+
available: false
|
|
26921
|
+
};
|
|
26922
|
+
}
|
|
26923
|
+
const children = await db.select({ id: agentInstances.id }).from(agentInstances).where(
|
|
26924
|
+
and5(
|
|
26925
|
+
eq7(agentInstances.parentAgentId, agentId),
|
|
26926
|
+
inArray5(agentInstances.status, ["starting", "active", "idle", "error"])
|
|
26927
|
+
)
|
|
26928
|
+
).all();
|
|
26929
|
+
const selfTask = agent.taskId != null ? 1 : 0;
|
|
26930
|
+
const activeTasks = selfTask + children.length;
|
|
26931
|
+
const remainingCapacity = Math.max(0, MAX_TASKS_PER_AGENT - activeTasks);
|
|
26932
|
+
return {
|
|
26933
|
+
agentId: agent.id,
|
|
26934
|
+
agentType: agent.agentType,
|
|
26935
|
+
status: agent.status,
|
|
26936
|
+
activeTasks,
|
|
26937
|
+
remainingCapacity,
|
|
26938
|
+
maxCapacity: MAX_TASKS_PER_AGENT,
|
|
26939
|
+
available: remainingCapacity > 0
|
|
26940
|
+
};
|
|
26941
|
+
}
|
|
26942
|
+
async function getAgentsByCapacity(agentType, cwd) {
|
|
26943
|
+
const filters = agentType ? { status: ["active", "idle"], agentType } : { status: ["active", "idle"] };
|
|
26944
|
+
const activeAgents = await listAgentInstances(filters, cwd);
|
|
26945
|
+
const capacities = await Promise.all(
|
|
26946
|
+
activeAgents.map((agent) => getAgentCapacity(agent.id, cwd))
|
|
26947
|
+
);
|
|
26948
|
+
return capacities.filter((c) => c !== null).sort((a, b) => b.remainingCapacity - a.remainingCapacity);
|
|
26949
|
+
}
|
|
26950
|
+
async function getAgentSpecializations(agentId, cwd) {
|
|
26951
|
+
const db = await getDb(cwd);
|
|
26952
|
+
const agent = await db.select({ metadataJson: agentInstances.metadataJson }).from(agentInstances).where(eq7(agentInstances.id, agentId)).get();
|
|
26953
|
+
if (!agent) return [];
|
|
26954
|
+
try {
|
|
26955
|
+
const meta = JSON.parse(agent.metadataJson ?? "{}");
|
|
26956
|
+
const specs = meta.specializations;
|
|
26957
|
+
if (!Array.isArray(specs)) return [];
|
|
26958
|
+
return specs.filter((s) => typeof s === "string");
|
|
26959
|
+
} catch {
|
|
26960
|
+
return [];
|
|
26961
|
+
}
|
|
26962
|
+
}
|
|
26963
|
+
async function updateAgentSpecializations(agentId, specializations, cwd) {
|
|
26964
|
+
const db = await getDb(cwd);
|
|
26965
|
+
const agent = await db.select({ metadataJson: agentInstances.metadataJson }).from(agentInstances).where(eq7(agentInstances.id, agentId)).get();
|
|
26966
|
+
if (!agent) return null;
|
|
26967
|
+
let existing = {};
|
|
26968
|
+
try {
|
|
26969
|
+
existing = JSON.parse(agent.metadataJson ?? "{}");
|
|
26970
|
+
} catch {
|
|
26971
|
+
}
|
|
26972
|
+
const updated = { ...existing, specializations };
|
|
26973
|
+
await db.update(agentInstances).set({ metadataJson: JSON.stringify(updated) }).where(eq7(agentInstances.id, agentId));
|
|
26974
|
+
return specializations;
|
|
26975
|
+
}
|
|
26976
|
+
async function recordAgentPerformance(agentId, metrics, cwd) {
|
|
26977
|
+
const db = await getDb(cwd);
|
|
26978
|
+
const agent = await db.select({ agentType: agentInstances.agentType, sessionId: agentInstances.sessionId }).from(agentInstances).where(eq7(agentInstances.id, agentId)).get();
|
|
26979
|
+
if (!agent) return null;
|
|
26980
|
+
const event = {
|
|
26981
|
+
agentId,
|
|
26982
|
+
agentType: agent.agentType,
|
|
26983
|
+
taskId: metrics.taskId,
|
|
26984
|
+
taskType: metrics.taskType,
|
|
26985
|
+
outcome: metrics.outcome,
|
|
26986
|
+
taskLabels: metrics.taskLabels,
|
|
26987
|
+
sessionId: metrics.sessionId ?? agent.sessionId ?? void 0,
|
|
26988
|
+
durationMs: metrics.durationMs,
|
|
26989
|
+
errorMessage: metrics.errorMessage,
|
|
26990
|
+
errorType: metrics.errorType
|
|
26991
|
+
};
|
|
26992
|
+
const decision = await recordAgentExecution(event, cwd);
|
|
26993
|
+
return decision?.id ?? null;
|
|
26994
|
+
}
|
|
26995
|
+
|
|
26996
|
+
// packages/core/src/agents/index.ts
|
|
26997
|
+
init_agent_schema();
|
|
26998
|
+
|
|
26999
|
+
// packages/core/src/agents/capacity.ts
|
|
27000
|
+
init_sqlite2();
|
|
27001
|
+
init_agent_schema();
|
|
27002
|
+
init_registry2();
|
|
27003
|
+
import { eq as eq8 } from "drizzle-orm";
|
|
27004
|
+
async function updateCapacity(id, capacity, cwd) {
|
|
27005
|
+
if (capacity < 0 || capacity > 1) {
|
|
27006
|
+
throw new Error(`Capacity must be between 0.0 and 1.0, got ${capacity}`);
|
|
27007
|
+
}
|
|
27008
|
+
const db = await getDb(cwd);
|
|
27009
|
+
const existing = await db.select().from(agentInstances).where(eq8(agentInstances.id, id)).get();
|
|
27010
|
+
if (!existing) return null;
|
|
27011
|
+
const capacityStr = capacity.toFixed(4);
|
|
27012
|
+
await db.update(agentInstances).set({ capacity: capacityStr }).where(eq8(agentInstances.id, id));
|
|
27013
|
+
return { ...existing, capacity: capacityStr };
|
|
27014
|
+
}
|
|
27015
|
+
async function getAvailableCapacity(cwd) {
|
|
27016
|
+
const agents = await listAgentInstances({ status: ["active", "idle"] }, cwd);
|
|
27017
|
+
return agents.reduce((sum, agent) => sum + parseCapacity(agent.capacity), 0);
|
|
27018
|
+
}
|
|
27019
|
+
async function findLeastLoadedAgent(agentType, cwd) {
|
|
27020
|
+
const filters = agentType ? { status: ["active", "idle"], agentType } : { status: ["active", "idle"] };
|
|
27021
|
+
const agents = await listAgentInstances(filters, cwd);
|
|
27022
|
+
if (agents.length === 0) return null;
|
|
27023
|
+
let best = agents[0];
|
|
27024
|
+
let bestCapacity = parseCapacity(best.capacity);
|
|
27025
|
+
for (let i = 1; i < agents.length; i++) {
|
|
27026
|
+
const cap = parseCapacity(agents[i].capacity);
|
|
27027
|
+
if (cap > bestCapacity) {
|
|
27028
|
+
best = agents[i];
|
|
27029
|
+
bestCapacity = cap;
|
|
27030
|
+
}
|
|
27031
|
+
}
|
|
27032
|
+
return best;
|
|
27033
|
+
}
|
|
27034
|
+
async function isOverloaded(threshold = 0.1, cwd) {
|
|
27035
|
+
const capacity = await getAvailableCapacity(cwd);
|
|
27036
|
+
return capacity < threshold;
|
|
27037
|
+
}
|
|
27038
|
+
async function getCapacitySummary(threshold = 0.1, cwd) {
|
|
27039
|
+
const agents = await listAgentInstances({ status: ["active", "idle"] }, cwd);
|
|
27040
|
+
const totalCapacity = agents.reduce((sum, a) => sum + parseCapacity(a.capacity), 0);
|
|
27041
|
+
const activeAgentCount = agents.length;
|
|
27042
|
+
return {
|
|
27043
|
+
totalCapacity,
|
|
27044
|
+
activeAgentCount,
|
|
27045
|
+
averageCapacity: activeAgentCount > 0 ? totalCapacity / activeAgentCount : 0,
|
|
27046
|
+
overloaded: totalCapacity < threshold,
|
|
27047
|
+
threshold
|
|
27048
|
+
};
|
|
27049
|
+
}
|
|
27050
|
+
function parseCapacity(value) {
|
|
27051
|
+
if (!value) return 0;
|
|
27052
|
+
const parsed = parseFloat(value);
|
|
27053
|
+
return Number.isNaN(parsed) ? 0 : Math.max(0, Math.min(1, parsed));
|
|
27054
|
+
}
|
|
27055
|
+
|
|
27056
|
+
// packages/core/src/agents/health-monitor.ts
|
|
27057
|
+
init_registry2();
|
|
27058
|
+
var HEARTBEAT_INTERVAL_MS = 3e4;
|
|
27059
|
+
var STALE_THRESHOLD_MS = 3 * 6e4;
|
|
27060
|
+
var ALIVE_STATUSES = ["starting", "active", "idle"];
|
|
27061
|
+
async function recordHeartbeat(agentId, cwd) {
|
|
27062
|
+
return heartbeat(agentId, cwd);
|
|
27063
|
+
}
|
|
27064
|
+
async function checkAgentHealth2(agentId, thresholdMs = STALE_THRESHOLD_MS, cwd) {
|
|
27065
|
+
const all = await listAgentInstances(void 0, cwd);
|
|
27066
|
+
const agent = all.find((a) => a.id === agentId);
|
|
27067
|
+
if (!agent) return null;
|
|
27068
|
+
return buildHealthStatus(agent, thresholdMs);
|
|
27069
|
+
}
|
|
27070
|
+
async function detectStaleAgents(thresholdMs = STALE_THRESHOLD_MS, cwd) {
|
|
27071
|
+
const agents = await listAgentInstances({ status: ALIVE_STATUSES }, cwd);
|
|
27072
|
+
return agents.map((a) => buildHealthStatus(a, thresholdMs)).filter((s) => s.stale).sort((a, b) => b.heartbeatAgeMs - a.heartbeatAgeMs);
|
|
27073
|
+
}
|
|
27074
|
+
async function detectCrashedAgents(thresholdMs = STALE_THRESHOLD_MS, cwd) {
|
|
27075
|
+
const activeAgents = await listAgentInstances({ status: "active" }, cwd);
|
|
27076
|
+
const cutoff = new Date(Date.now() - thresholdMs).toISOString();
|
|
27077
|
+
const crashed = [];
|
|
27078
|
+
for (const agent of activeAgents) {
|
|
27079
|
+
if (agent.lastHeartbeat < cutoff) {
|
|
27080
|
+
const updated = await markCrashed(
|
|
27081
|
+
agent.id,
|
|
27082
|
+
`Heartbeat timeout \u2014 no heartbeat for >${Math.round(thresholdMs / 1e3)}s`,
|
|
27083
|
+
cwd
|
|
27084
|
+
);
|
|
27085
|
+
if (updated) {
|
|
27086
|
+
crashed.push(updated);
|
|
27087
|
+
}
|
|
27088
|
+
}
|
|
27089
|
+
}
|
|
27090
|
+
crashed.sort((a, b) => {
|
|
27091
|
+
const aHb = a.lastHeartbeat ?? "";
|
|
27092
|
+
const bHb = b.lastHeartbeat ?? "";
|
|
27093
|
+
return aHb < bHb ? -1 : aHb > bHb ? 1 : 0;
|
|
27094
|
+
});
|
|
27095
|
+
return crashed;
|
|
27096
|
+
}
|
|
27097
|
+
function buildHealthStatus(agent, thresholdMs) {
|
|
27098
|
+
const lastHeartbeatMs = new Date(agent.lastHeartbeat).getTime();
|
|
27099
|
+
const heartbeatAgeMs = Date.now() - lastHeartbeatMs;
|
|
27100
|
+
const stale = ALIVE_STATUSES.includes(agent.status) ? heartbeatAgeMs > thresholdMs : false;
|
|
27101
|
+
const healthy = !stale && ALIVE_STATUSES.includes(agent.status);
|
|
27102
|
+
return {
|
|
27103
|
+
agentId: agent.id,
|
|
27104
|
+
status: agent.status,
|
|
27105
|
+
lastHeartbeat: agent.lastHeartbeat,
|
|
27106
|
+
heartbeatAgeMs,
|
|
27107
|
+
healthy,
|
|
27108
|
+
stale,
|
|
27109
|
+
thresholdMs
|
|
27110
|
+
};
|
|
27111
|
+
}
|
|
27112
|
+
|
|
26926
27113
|
// packages/core/src/agents/index.ts
|
|
26927
27114
|
init_registry2();
|
|
26928
27115
|
|
|
@@ -39185,6 +39372,7 @@ __export(intelligence_exports, {
|
|
|
39185
39372
|
gatherLearningContext: () => gatherLearningContext,
|
|
39186
39373
|
matchPatterns: () => matchPatterns,
|
|
39187
39374
|
predictAndStore: () => predictAndStore,
|
|
39375
|
+
predictImpact: () => predictImpact,
|
|
39188
39376
|
predictValidationOutcome: () => predictValidationOutcome,
|
|
39189
39377
|
scoreVerificationConfidence: () => scoreVerificationConfidence,
|
|
39190
39378
|
storeDetectedPattern: () => storeDetectedPattern,
|
|
@@ -40374,6 +40562,116 @@ function generateRecommendation2(changeType, affectedCount, cascadeDepth, taskId
|
|
|
40374
40562
|
return `${severity} impact: reprioritizing ${taskId} may reorder ${affectedCount} downstream task(s) across ${cascadeDepth} level(s) of dependencies.`;
|
|
40375
40563
|
}
|
|
40376
40564
|
}
|
|
40565
|
+
function scoreTaskMatch(change, task) {
|
|
40566
|
+
const STOP_WORDS3 = /* @__PURE__ */ new Set([
|
|
40567
|
+
"a",
|
|
40568
|
+
"an",
|
|
40569
|
+
"the",
|
|
40570
|
+
"and",
|
|
40571
|
+
"or",
|
|
40572
|
+
"in",
|
|
40573
|
+
"of",
|
|
40574
|
+
"to",
|
|
40575
|
+
"for",
|
|
40576
|
+
"with",
|
|
40577
|
+
"on",
|
|
40578
|
+
"at",
|
|
40579
|
+
"by",
|
|
40580
|
+
"is",
|
|
40581
|
+
"it",
|
|
40582
|
+
"be",
|
|
40583
|
+
"as",
|
|
40584
|
+
"if",
|
|
40585
|
+
"do",
|
|
40586
|
+
"not"
|
|
40587
|
+
]);
|
|
40588
|
+
const tokenise = (text3) => text3.toLowerCase().split(/\W+/).filter((t) => t.length > 2 && !STOP_WORDS3.has(t));
|
|
40589
|
+
const changeTokens = new Set(tokenise(change));
|
|
40590
|
+
if (changeTokens.size === 0) return 0;
|
|
40591
|
+
const taskText = `${task.title ?? ""} ${task.description ?? ""}`;
|
|
40592
|
+
const taskTokens = new Set(tokenise(taskText));
|
|
40593
|
+
let matches = 0;
|
|
40594
|
+
for (const token of changeTokens) {
|
|
40595
|
+
if (taskTokens.has(token)) matches++;
|
|
40596
|
+
}
|
|
40597
|
+
return matches / changeTokens.size;
|
|
40598
|
+
}
|
|
40599
|
+
async function predictImpact(change, cwd, accessor, matchLimit = 5) {
|
|
40600
|
+
const acc = accessor ?? await getAccessor(cwd);
|
|
40601
|
+
const tasks2 = await loadAllTasks2(acc);
|
|
40602
|
+
const taskMap = new Map(tasks2.map((t) => [t.id, t]));
|
|
40603
|
+
const dependentsMap = buildDependentsMap(tasks2);
|
|
40604
|
+
const scored = tasks2.map((t) => ({ task: t, score: scoreTaskMatch(change, t) })).filter(({ score }) => score > 0).sort((a, b) => b.score - a.score);
|
|
40605
|
+
const seeds = scored.slice(0, matchLimit).map(({ task }) => task);
|
|
40606
|
+
if (seeds.length === 0) {
|
|
40607
|
+
return {
|
|
40608
|
+
change,
|
|
40609
|
+
matchedTasks: [],
|
|
40610
|
+
affectedTasks: [],
|
|
40611
|
+
totalAffected: 0,
|
|
40612
|
+
summary: `No tasks matched the change description "${change}".`
|
|
40613
|
+
};
|
|
40614
|
+
}
|
|
40615
|
+
const directMatchIds = new Set(seeds.map((t) => t.id));
|
|
40616
|
+
const exposureMap = /* @__PURE__ */ new Map();
|
|
40617
|
+
for (const id of directMatchIds) {
|
|
40618
|
+
exposureMap.set(id, "direct");
|
|
40619
|
+
}
|
|
40620
|
+
for (const seed of seeds) {
|
|
40621
|
+
const transitive = collectTransitiveDependents(seed.id, dependentsMap);
|
|
40622
|
+
for (const depId of transitive) {
|
|
40623
|
+
if (!exposureMap.has(depId)) {
|
|
40624
|
+
const isDirectDependent = (dependentsMap.get(seed.id) ?? /* @__PURE__ */ new Set()).has(depId);
|
|
40625
|
+
exposureMap.set(depId, isDirectDependent ? "dependent" : "transitive");
|
|
40626
|
+
}
|
|
40627
|
+
}
|
|
40628
|
+
}
|
|
40629
|
+
const EXPOSURE_ORDER = {
|
|
40630
|
+
direct: 0,
|
|
40631
|
+
dependent: 1,
|
|
40632
|
+
transitive: 2
|
|
40633
|
+
};
|
|
40634
|
+
const affectedTasks = [];
|
|
40635
|
+
for (const [id, exposure] of exposureMap) {
|
|
40636
|
+
const task = taskMap.get(id);
|
|
40637
|
+
if (!task) continue;
|
|
40638
|
+
const downstreamTransitive = collectTransitiveDependents(id, dependentsMap);
|
|
40639
|
+
const downstreamCount = downstreamTransitive.size;
|
|
40640
|
+
let reason;
|
|
40641
|
+
if (exposure === "direct") {
|
|
40642
|
+
reason = `Task title/description matched "${change}".`;
|
|
40643
|
+
} else if (exposure === "dependent") {
|
|
40644
|
+
const seedNames = seeds.filter((s) => (dependentsMap.get(s.id) ?? /* @__PURE__ */ new Set()).has(id)).map((s) => s.id).join(", ");
|
|
40645
|
+
reason = `Directly depends on matched task(s): ${seedNames}.`;
|
|
40646
|
+
} else {
|
|
40647
|
+
reason = "Downstream of a matched task via transitive dependency chain.";
|
|
40648
|
+
}
|
|
40649
|
+
affectedTasks.push({
|
|
40650
|
+
id,
|
|
40651
|
+
title: task.title,
|
|
40652
|
+
status: task.status,
|
|
40653
|
+
priority: task.priority,
|
|
40654
|
+
exposure,
|
|
40655
|
+
downstreamCount,
|
|
40656
|
+
reason
|
|
40657
|
+
});
|
|
40658
|
+
}
|
|
40659
|
+
affectedTasks.sort((a, b) => {
|
|
40660
|
+
const expDiff = EXPOSURE_ORDER[a.exposure] - EXPOSURE_ORDER[b.exposure];
|
|
40661
|
+
if (expDiff !== 0) return expDiff;
|
|
40662
|
+
return b.downstreamCount - a.downstreamCount;
|
|
40663
|
+
});
|
|
40664
|
+
const matchedTasks = affectedTasks.filter((t) => t.exposure === "direct");
|
|
40665
|
+
const totalAffected = affectedTasks.length;
|
|
40666
|
+
const summary = matchedTasks.length === 0 ? `No tasks matched "${change}".` : `${matchedTasks.length} task(s) matched "${change}"; ${totalAffected} total task(s) affected (including downstream).`;
|
|
40667
|
+
return {
|
|
40668
|
+
change,
|
|
40669
|
+
matchedTasks,
|
|
40670
|
+
affectedTasks,
|
|
40671
|
+
totalAffected,
|
|
40672
|
+
summary
|
|
40673
|
+
};
|
|
40674
|
+
}
|
|
40377
40675
|
|
|
40378
40676
|
// packages/core/src/intelligence/patterns.ts
|
|
40379
40677
|
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
@@ -40889,13 +41187,13 @@ function extractYamlArray(content, field) {
|
|
|
40889
41187
|
}
|
|
40890
41188
|
const lines = content.split("\n");
|
|
40891
41189
|
const items = [];
|
|
40892
|
-
let
|
|
41190
|
+
let inArray6 = false;
|
|
40893
41191
|
for (const line2 of lines) {
|
|
40894
41192
|
if (line2.match(new RegExp(`^${field}:`))) {
|
|
40895
|
-
|
|
41193
|
+
inArray6 = true;
|
|
40896
41194
|
continue;
|
|
40897
41195
|
}
|
|
40898
|
-
if (
|
|
41196
|
+
if (inArray6) {
|
|
40899
41197
|
const itemMatch = line2.match(/^\s+-\s+["']?(.+?)["']?\s*$/);
|
|
40900
41198
|
if (itemMatch) {
|
|
40901
41199
|
items.push(itemMatch[1].trim());
|
|
@@ -41113,6 +41411,60 @@ function addIssue(params) {
|
|
|
41113
41411
|
};
|
|
41114
41412
|
}
|
|
41115
41413
|
|
|
41414
|
+
// packages/core/src/lib/index.ts
|
|
41415
|
+
var lib_exports = {};
|
|
41416
|
+
__export(lib_exports, {
|
|
41417
|
+
computeDelay: () => computeDelay,
|
|
41418
|
+
withRetry: () => withRetry2
|
|
41419
|
+
});
|
|
41420
|
+
|
|
41421
|
+
// packages/core/src/lib/retry.ts
|
|
41422
|
+
async function withRetry2(fn, options) {
|
|
41423
|
+
const maxAttempts = options?.maxAttempts ?? 3;
|
|
41424
|
+
const baseDelayMs = options?.baseDelayMs ?? 2e3;
|
|
41425
|
+
const maxDelayMs = options?.maxDelayMs ?? 3e4;
|
|
41426
|
+
const retryableErrors = options?.retryableErrors;
|
|
41427
|
+
let lastError;
|
|
41428
|
+
let totalDelayMs = 0;
|
|
41429
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
41430
|
+
try {
|
|
41431
|
+
return await fn();
|
|
41432
|
+
} catch (err) {
|
|
41433
|
+
lastError = err;
|
|
41434
|
+
const isLastAttempt = attempt === maxAttempts;
|
|
41435
|
+
if (isLastAttempt) break;
|
|
41436
|
+
if (retryableErrors !== void 0 && !isRetryable(err, retryableErrors)) break;
|
|
41437
|
+
const delay = computeDelay(attempt, baseDelayMs, maxDelayMs);
|
|
41438
|
+
totalDelayMs += delay;
|
|
41439
|
+
await sleep2(delay);
|
|
41440
|
+
}
|
|
41441
|
+
}
|
|
41442
|
+
const context = { attempts: maxAttempts, totalDelayMs };
|
|
41443
|
+
augmentError(lastError, context);
|
|
41444
|
+
throw lastError;
|
|
41445
|
+
}
|
|
41446
|
+
function computeDelay(attempt, baseDelayMs, maxDelayMs) {
|
|
41447
|
+
const exponential = baseDelayMs * 2 ** (attempt - 1);
|
|
41448
|
+
return Math.min(exponential, maxDelayMs);
|
|
41449
|
+
}
|
|
41450
|
+
function isRetryable(err, predicates) {
|
|
41451
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
41452
|
+
return predicates.some((predicate) => {
|
|
41453
|
+
if (predicate instanceof RegExp) return predicate.test(message);
|
|
41454
|
+
return predicate(err);
|
|
41455
|
+
});
|
|
41456
|
+
}
|
|
41457
|
+
function augmentError(err, context) {
|
|
41458
|
+
if (err instanceof Error) {
|
|
41459
|
+
const mutableErr = err;
|
|
41460
|
+
mutableErr.attempts = context.attempts;
|
|
41461
|
+
mutableErr.totalDelayMs = context.totalDelayMs;
|
|
41462
|
+
}
|
|
41463
|
+
}
|
|
41464
|
+
function sleep2(ms) {
|
|
41465
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
41466
|
+
}
|
|
41467
|
+
|
|
41116
41468
|
// packages/core/src/lifecycle/index.ts
|
|
41117
41469
|
var lifecycle_exports = {};
|
|
41118
41470
|
__export(lifecycle_exports, {
|
|
@@ -41929,12 +42281,12 @@ async function getEnforcementMode(cwd) {
|
|
|
41929
42281
|
}
|
|
41930
42282
|
async function getLifecycleStatus(epicId, cwd) {
|
|
41931
42283
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
41932
|
-
const { eq:
|
|
42284
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
41933
42285
|
const db = await getDb3(cwd);
|
|
41934
42286
|
const pipelineResult = await db.select({
|
|
41935
42287
|
pipeline: lifecyclePipelines,
|
|
41936
42288
|
task: tasks
|
|
41937
|
-
}).from(lifecyclePipelines).innerJoin(tasks,
|
|
42289
|
+
}).from(lifecyclePipelines).innerJoin(tasks, eq12(lifecyclePipelines.taskId, tasks.id)).where(eq12(lifecyclePipelines.taskId, epicId)).limit(1);
|
|
41938
42290
|
if (pipelineResult.length === 0) {
|
|
41939
42291
|
return {
|
|
41940
42292
|
epicId,
|
|
@@ -41947,7 +42299,7 @@ async function getLifecycleStatus(epicId, cwd) {
|
|
|
41947
42299
|
}
|
|
41948
42300
|
const task = pipelineResult[0].task;
|
|
41949
42301
|
const pipelineId = `pipeline-${epicId}`;
|
|
41950
|
-
const stageRows = await db.select().from(lifecycleStages).where(
|
|
42302
|
+
const stageRows = await db.select().from(lifecycleStages).where(eq12(lifecycleStages.pipelineId, pipelineId)).orderBy(lifecycleStages.sequence);
|
|
41951
42303
|
const stageDataMap = /* @__PURE__ */ new Map();
|
|
41952
42304
|
for (const row of stageRows) {
|
|
41953
42305
|
let parsedChain;
|
|
@@ -42016,10 +42368,10 @@ async function getLifecycleStatus(epicId, cwd) {
|
|
|
42016
42368
|
}
|
|
42017
42369
|
async function getLifecycleHistory(epicId, cwd) {
|
|
42018
42370
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
42019
|
-
const { eq:
|
|
42371
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
42020
42372
|
const db = await getDb3(cwd);
|
|
42021
42373
|
const pipelineId = `pipeline-${epicId}`;
|
|
42022
|
-
const stages = await db.select().from(lifecycleStages).where(
|
|
42374
|
+
const stages = await db.select().from(lifecycleStages).where(eq12(lifecycleStages.pipelineId, pipelineId));
|
|
42023
42375
|
if (stages.length === 0) {
|
|
42024
42376
|
return { epicId, history: [] };
|
|
42025
42377
|
}
|
|
@@ -42049,7 +42401,7 @@ async function getLifecycleHistory(epicId, cwd) {
|
|
|
42049
42401
|
}
|
|
42050
42402
|
const stageIds = stages.map((s) => s.id);
|
|
42051
42403
|
if (stageIds.length > 0) {
|
|
42052
|
-
const gateResults = await db.select().from(lifecycleGateResults).where(
|
|
42404
|
+
const gateResults = await db.select().from(lifecycleGateResults).where(eq12(lifecycleGateResults.stageId, stageIds[0]));
|
|
42053
42405
|
for (const gate of gateResults) {
|
|
42054
42406
|
const stageName = stageIdToName.get(gate.stageId);
|
|
42055
42407
|
if (stageName) {
|
|
@@ -42062,7 +42414,7 @@ async function getLifecycleHistory(epicId, cwd) {
|
|
|
42062
42414
|
}
|
|
42063
42415
|
}
|
|
42064
42416
|
for (let i = 1; i < stageIds.length; i++) {
|
|
42065
|
-
const additionalGates = await db.select().from(lifecycleGateResults).where(
|
|
42417
|
+
const additionalGates = await db.select().from(lifecycleGateResults).where(eq12(lifecycleGateResults.stageId, stageIds[i]));
|
|
42066
42418
|
for (const gate of additionalGates) {
|
|
42067
42419
|
const stageName = stageIdToName.get(gate.stageId);
|
|
42068
42420
|
if (stageName) {
|
|
@@ -42081,16 +42433,16 @@ async function getLifecycleHistory(epicId, cwd) {
|
|
|
42081
42433
|
}
|
|
42082
42434
|
async function getLifecycleGates(epicId, cwd) {
|
|
42083
42435
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
42084
|
-
const { eq:
|
|
42436
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
42085
42437
|
const db = await getDb3(cwd);
|
|
42086
42438
|
const pipelineId = `pipeline-${epicId}`;
|
|
42087
|
-
const stages = await db.select().from(lifecycleStages).where(
|
|
42439
|
+
const stages = await db.select().from(lifecycleStages).where(eq12(lifecycleStages.pipelineId, pipelineId));
|
|
42088
42440
|
if (stages.length === 0) {
|
|
42089
42441
|
return {};
|
|
42090
42442
|
}
|
|
42091
42443
|
const gates = {};
|
|
42092
42444
|
for (const stage of stages) {
|
|
42093
|
-
const gateRows = await db.select().from(lifecycleGateResults).where(
|
|
42445
|
+
const gateRows = await db.select().from(lifecycleGateResults).where(eq12(lifecycleGateResults.stageId, stage.id));
|
|
42094
42446
|
if (gateRows.length > 0) {
|
|
42095
42447
|
gates[stage.stageName] = {};
|
|
42096
42448
|
for (const gateRow of gateRows) {
|
|
@@ -42154,7 +42506,7 @@ async function checkStagePrerequisites(epicId, targetStage, cwd) {
|
|
|
42154
42506
|
}
|
|
42155
42507
|
async function ensureLifecycleContext(epicId, stageName, cwd, options) {
|
|
42156
42508
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
42157
|
-
const { eq:
|
|
42509
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
42158
42510
|
const db = await getDb3(cwd);
|
|
42159
42511
|
const pipelineId = `pipeline-${epicId}`;
|
|
42160
42512
|
const stageId = `stage-${epicId}-${stageName}`;
|
|
@@ -42162,7 +42514,7 @@ async function ensureLifecycleContext(epicId, stageName, cwd, options) {
|
|
|
42162
42514
|
getNativeDb2().prepare(
|
|
42163
42515
|
`INSERT OR IGNORE INTO tasks (id, title, status, priority, created_at) VALUES (?, ?, 'pending', 'medium', datetime('now'))`
|
|
42164
42516
|
).run(epicId, `Task ${epicId}`);
|
|
42165
|
-
const existingPipeline = await db.select().from(lifecyclePipelines).where(
|
|
42517
|
+
const existingPipeline = await db.select().from(lifecyclePipelines).where(eq12(lifecyclePipelines.id, pipelineId)).limit(1).all();
|
|
42166
42518
|
if (existingPipeline.length === 0) {
|
|
42167
42519
|
await db.insert(lifecyclePipelines).values({
|
|
42168
42520
|
id: pipelineId,
|
|
@@ -42172,7 +42524,7 @@ async function ensureLifecycleContext(epicId, stageName, cwd, options) {
|
|
|
42172
42524
|
startedAt: options.now
|
|
42173
42525
|
}).run();
|
|
42174
42526
|
}
|
|
42175
|
-
const existingStage = await db.select().from(lifecycleStages).where(
|
|
42527
|
+
const existingStage = await db.select().from(lifecycleStages).where(eq12(lifecycleStages.id, stageId)).limit(1).all();
|
|
42176
42528
|
if (existingStage.length === 0) {
|
|
42177
42529
|
const sequence = isValidStage(stageName) ? STAGE_ORDER[stageName] : 0;
|
|
42178
42530
|
await db.insert(lifecycleStages).values({
|
|
@@ -42185,7 +42537,7 @@ async function ensureLifecycleContext(epicId, stageName, cwd, options) {
|
|
|
42185
42537
|
}).run();
|
|
42186
42538
|
}
|
|
42187
42539
|
if (options.updateCurrentStage) {
|
|
42188
|
-
await db.update(lifecyclePipelines).set({ currentStageId: stageId }).where(
|
|
42540
|
+
await db.update(lifecyclePipelines).set({ currentStageId: stageId }).where(eq12(lifecyclePipelines.id, pipelineId)).run();
|
|
42189
42541
|
}
|
|
42190
42542
|
return { db, pipelineId, stageId };
|
|
42191
42543
|
}
|
|
@@ -42200,7 +42552,7 @@ async function recordStageProgress(epicId, stage, status, notes, cwd) {
|
|
|
42200
42552
|
`Invalid status: ${status}. Valid: ${validStatuses.join(", ")}`
|
|
42201
42553
|
);
|
|
42202
42554
|
}
|
|
42203
|
-
const { eq:
|
|
42555
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
42204
42556
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
42205
42557
|
const stageName = stage;
|
|
42206
42558
|
const { db, stageId, pipelineId } = await ensureLifecycleContext(epicId, stage, cwd, {
|
|
@@ -42216,7 +42568,7 @@ async function recordStageProgress(epicId, stage, status, notes, cwd) {
|
|
|
42216
42568
|
status,
|
|
42217
42569
|
related: artifact.related
|
|
42218
42570
|
};
|
|
42219
|
-
const existingStage = await db.select().from(lifecycleStages).where(
|
|
42571
|
+
const existingStage = await db.select().from(lifecycleStages).where(eq12(lifecycleStages.id, stageId)).limit(1).all();
|
|
42220
42572
|
const sequence = STAGE_ORDER[stage];
|
|
42221
42573
|
const stageValues = {
|
|
42222
42574
|
status,
|
|
@@ -42243,7 +42595,7 @@ async function recordStageProgress(epicId, stage, status, notes, cwd) {
|
|
|
42243
42595
|
provenanceChainJson: JSON.stringify(provenanceChain)
|
|
42244
42596
|
}).run();
|
|
42245
42597
|
} else {
|
|
42246
|
-
await db.update(lifecycleStages).set(stageValues).where(
|
|
42598
|
+
await db.update(lifecycleStages).set(stageValues).where(eq12(lifecycleStages.id, stageId)).run();
|
|
42247
42599
|
}
|
|
42248
42600
|
if (status === "completed") {
|
|
42249
42601
|
await linkProvenance(epicId, stageName, artifact.absolutePath, cwd);
|
|
@@ -42263,7 +42615,7 @@ async function resetStage(epicId, stage, reason, cwd) {
|
|
|
42263
42615
|
if (!PIPELINE_STAGES.includes(stage)) {
|
|
42264
42616
|
throw new CleoError(2 /* INVALID_INPUT */, `Invalid stage: ${stage}`);
|
|
42265
42617
|
}
|
|
42266
|
-
const { eq:
|
|
42618
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
42267
42619
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
42268
42620
|
const { db, stageId } = await ensureLifecycleContext(epicId, stage, cwd, {
|
|
42269
42621
|
now,
|
|
@@ -42276,11 +42628,11 @@ async function resetStage(epicId, stage, reason, cwd) {
|
|
|
42276
42628
|
skippedAt: null,
|
|
42277
42629
|
skipReason: null,
|
|
42278
42630
|
notesJson: JSON.stringify([`Reset: ${reason}`])
|
|
42279
|
-
}).where(
|
|
42631
|
+
}).where(eq12(lifecycleStages.id, stageId)).run();
|
|
42280
42632
|
return { epicId, stage, reason };
|
|
42281
42633
|
}
|
|
42282
42634
|
async function passGate(epicId, gateName, agent, notes, cwd) {
|
|
42283
|
-
const { eq:
|
|
42635
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
42284
42636
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
42285
42637
|
const stageName = gateName.split("-")[0];
|
|
42286
42638
|
const gateId = `gate-${epicId}-${stageName}-${gateName}`;
|
|
@@ -42289,7 +42641,7 @@ async function passGate(epicId, gateName, agent, notes, cwd) {
|
|
|
42289
42641
|
stageStatusOnCreate: "in_progress",
|
|
42290
42642
|
updateCurrentStage: true
|
|
42291
42643
|
});
|
|
42292
|
-
const existingGate = await db.select().from(lifecycleGateResults).where(
|
|
42644
|
+
const existingGate = await db.select().from(lifecycleGateResults).where(eq12(lifecycleGateResults.id, gateId)).limit(1).all();
|
|
42293
42645
|
const gateValues = {
|
|
42294
42646
|
id: gateId,
|
|
42295
42647
|
stageId,
|
|
@@ -42301,14 +42653,14 @@ async function passGate(epicId, gateName, agent, notes, cwd) {
|
|
|
42301
42653
|
reason: null
|
|
42302
42654
|
};
|
|
42303
42655
|
if (existingGate.length > 0) {
|
|
42304
|
-
await db.update(lifecycleGateResults).set(gateValues).where(
|
|
42656
|
+
await db.update(lifecycleGateResults).set(gateValues).where(eq12(lifecycleGateResults.id, gateId)).run();
|
|
42305
42657
|
} else {
|
|
42306
42658
|
await db.insert(lifecycleGateResults).values(gateValues).run();
|
|
42307
42659
|
}
|
|
42308
42660
|
return { epicId, gateName, timestamp: now };
|
|
42309
42661
|
}
|
|
42310
42662
|
async function failGate(epicId, gateName, reason, cwd) {
|
|
42311
|
-
const { eq:
|
|
42663
|
+
const { eq: eq12 } = await import("drizzle-orm");
|
|
42312
42664
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
42313
42665
|
const stageName = gateName.split("-")[0];
|
|
42314
42666
|
const gateId = `gate-${epicId}-${stageName}-${gateName}`;
|
|
@@ -42317,7 +42669,7 @@ async function failGate(epicId, gateName, reason, cwd) {
|
|
|
42317
42669
|
stageStatusOnCreate: "in_progress",
|
|
42318
42670
|
updateCurrentStage: true
|
|
42319
42671
|
});
|
|
42320
|
-
const existingGate = await db.select().from(lifecycleGateResults).where(
|
|
42672
|
+
const existingGate = await db.select().from(lifecycleGateResults).where(eq12(lifecycleGateResults.id, gateId)).limit(1).all();
|
|
42321
42673
|
const gateValues = {
|
|
42322
42674
|
id: gateId,
|
|
42323
42675
|
stageId,
|
|
@@ -42329,7 +42681,7 @@ async function failGate(epicId, gateName, reason, cwd) {
|
|
|
42329
42681
|
reason: reason ?? null
|
|
42330
42682
|
};
|
|
42331
42683
|
if (existingGate.length > 0) {
|
|
42332
|
-
await db.update(lifecycleGateResults).set(gateValues).where(
|
|
42684
|
+
await db.update(lifecycleGateResults).set(gateValues).where(eq12(lifecycleGateResults.id, gateId)).run();
|
|
42333
42685
|
} else {
|
|
42334
42686
|
await db.insert(lifecycleGateResults).values(gateValues).run();
|
|
42335
42687
|
}
|
|
@@ -46463,6 +46815,7 @@ init_registry3();
|
|
|
46463
46815
|
// packages/core/src/nexus/sharing/index.ts
|
|
46464
46816
|
init_config();
|
|
46465
46817
|
init_paths();
|
|
46818
|
+
init_git_checkpoint();
|
|
46466
46819
|
import { existsSync as existsSync54, readdirSync as readdirSync22, statSync as statSync15 } from "node:fs";
|
|
46467
46820
|
import { readFile as readFile10, writeFile as writeFile9 } from "node:fs/promises";
|
|
46468
46821
|
import { join as join61, relative as relative5 } from "node:path";
|
|
@@ -46509,6 +46862,30 @@ function collectCleoFiles(cleoDir) {
|
|
|
46509
46862
|
walk(cleoDir);
|
|
46510
46863
|
return files.sort();
|
|
46511
46864
|
}
|
|
46865
|
+
async function getCleoGitRemotes(cleoDir) {
|
|
46866
|
+
const result = await cleoGitCommand(["remote"], cleoDir);
|
|
46867
|
+
if (!result.success || !result.stdout) return [];
|
|
46868
|
+
return result.stdout.split("\n").map((r) => r.trim()).filter(Boolean);
|
|
46869
|
+
}
|
|
46870
|
+
async function hasCleoGitPendingChanges(cleoDir) {
|
|
46871
|
+
const result = await cleoGitCommand(["status", "--porcelain"], cleoDir);
|
|
46872
|
+
if (!result.success) return false;
|
|
46873
|
+
return result.stdout.length > 0;
|
|
46874
|
+
}
|
|
46875
|
+
async function getLastSyncTimestamp(cleoDir) {
|
|
46876
|
+
const result = await cleoGitCommand(["reflog", "--format=%gs %ci", "HEAD"], cleoDir);
|
|
46877
|
+
if (!result.success || !result.stdout) return null;
|
|
46878
|
+
for (const line2 of result.stdout.split("\n")) {
|
|
46879
|
+
const trimmed = line2.trim();
|
|
46880
|
+
if (/^(fetch|push|pull)\b/i.test(trimmed)) {
|
|
46881
|
+
const isoMatch = trimmed.match(/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [+-]\d{4})$/);
|
|
46882
|
+
if (isoMatch?.[1]) {
|
|
46883
|
+
return new Date(isoMatch[1]).toISOString();
|
|
46884
|
+
}
|
|
46885
|
+
}
|
|
46886
|
+
}
|
|
46887
|
+
return null;
|
|
46888
|
+
}
|
|
46512
46889
|
async function getSharingStatus(cwd) {
|
|
46513
46890
|
const config2 = await loadConfig(cwd);
|
|
46514
46891
|
const sharing = config2.sharing;
|
|
@@ -46525,12 +46902,27 @@ async function getSharingStatus(cwd) {
|
|
|
46525
46902
|
ignored.push(file2);
|
|
46526
46903
|
}
|
|
46527
46904
|
}
|
|
46905
|
+
const hasGit = isCleoGitInitialized(cleoDir);
|
|
46906
|
+
let remotes = [];
|
|
46907
|
+
let pendingChanges = false;
|
|
46908
|
+
let lastSync = null;
|
|
46909
|
+
if (hasGit) {
|
|
46910
|
+
[remotes, pendingChanges, lastSync] = await Promise.all([
|
|
46911
|
+
getCleoGitRemotes(cleoDir),
|
|
46912
|
+
hasCleoGitPendingChanges(cleoDir),
|
|
46913
|
+
getLastSyncTimestamp(cleoDir)
|
|
46914
|
+
]);
|
|
46915
|
+
}
|
|
46528
46916
|
return {
|
|
46529
46917
|
mode: sharing.mode,
|
|
46530
46918
|
allowlist: sharing.commitAllowlist,
|
|
46531
46919
|
denylist: sharing.denylist,
|
|
46532
46920
|
tracked,
|
|
46533
|
-
ignored
|
|
46921
|
+
ignored,
|
|
46922
|
+
hasGit,
|
|
46923
|
+
remotes,
|
|
46924
|
+
pendingChanges,
|
|
46925
|
+
lastSync
|
|
46534
46926
|
};
|
|
46535
46927
|
}
|
|
46536
46928
|
function generateGitignoreEntries(sharing) {
|
|
@@ -46585,25 +46977,25 @@ init_logger();
|
|
|
46585
46977
|
init_sqlite2();
|
|
46586
46978
|
init_tasks_schema();
|
|
46587
46979
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
46588
|
-
import { and as
|
|
46980
|
+
import { and as and7, eq as eq10 } from "drizzle-orm";
|
|
46589
46981
|
async function getLinksByProvider(providerId, cwd) {
|
|
46590
46982
|
const db = await getDb(cwd);
|
|
46591
|
-
const rows = await db.select().from(externalTaskLinks).where(
|
|
46983
|
+
const rows = await db.select().from(externalTaskLinks).where(eq10(externalTaskLinks.providerId, providerId));
|
|
46592
46984
|
return rows.map(rowToLink);
|
|
46593
46985
|
}
|
|
46594
46986
|
async function getLinkByExternalId(providerId, externalId, cwd) {
|
|
46595
46987
|
const db = await getDb(cwd);
|
|
46596
46988
|
const rows = await db.select().from(externalTaskLinks).where(
|
|
46597
|
-
|
|
46598
|
-
|
|
46599
|
-
|
|
46989
|
+
and7(
|
|
46990
|
+
eq10(externalTaskLinks.providerId, providerId),
|
|
46991
|
+
eq10(externalTaskLinks.externalId, externalId)
|
|
46600
46992
|
)
|
|
46601
46993
|
);
|
|
46602
46994
|
return rows.length > 0 ? rowToLink(rows[0]) : null;
|
|
46603
46995
|
}
|
|
46604
46996
|
async function getLinksByTaskId(taskId, cwd) {
|
|
46605
46997
|
const db = await getDb(cwd);
|
|
46606
|
-
const rows = await db.select().from(externalTaskLinks).where(
|
|
46998
|
+
const rows = await db.select().from(externalTaskLinks).where(eq10(externalTaskLinks.taskId, taskId));
|
|
46607
46999
|
return rows.map(rowToLink);
|
|
46608
47000
|
}
|
|
46609
47001
|
async function createLink(params, cwd) {
|
|
@@ -46647,11 +47039,11 @@ async function touchLink(linkId, updates, cwd) {
|
|
|
46647
47039
|
if (updates?.metadata !== void 0) {
|
|
46648
47040
|
values.metadataJson = JSON.stringify(updates.metadata);
|
|
46649
47041
|
}
|
|
46650
|
-
await db.update(externalTaskLinks).set(values).where(
|
|
47042
|
+
await db.update(externalTaskLinks).set(values).where(eq10(externalTaskLinks.id, linkId));
|
|
46651
47043
|
}
|
|
46652
47044
|
async function removeLinksByProvider(providerId, cwd) {
|
|
46653
47045
|
const db = await getDb(cwd);
|
|
46654
|
-
const result = await db.delete(externalTaskLinks).where(
|
|
47046
|
+
const result = await db.delete(externalTaskLinks).where(eq10(externalTaskLinks.providerId, providerId));
|
|
46655
47047
|
return Number(result.changes);
|
|
46656
47048
|
}
|
|
46657
47049
|
function rowToLink(row) {
|
|
@@ -49703,7 +50095,7 @@ import { execFileSync as execFileSync7 } from "node:child_process";
|
|
|
49703
50095
|
import { existsSync as existsSync63, renameSync as renameSync5 } from "node:fs";
|
|
49704
50096
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
49705
50097
|
import { join as join67 } from "node:path";
|
|
49706
|
-
import { and as
|
|
50098
|
+
import { and as and8, count, desc as desc4, eq as eq11 } from "drizzle-orm";
|
|
49707
50099
|
init_paths();
|
|
49708
50100
|
init_tasks_schema();
|
|
49709
50101
|
|
|
@@ -50003,7 +50395,7 @@ function rowToManifest(row) {
|
|
|
50003
50395
|
}
|
|
50004
50396
|
async function findLatestPushedVersion(cwd) {
|
|
50005
50397
|
const db = await getDb2(cwd);
|
|
50006
|
-
const rows = await db.select({ version: releaseManifests.version }).from(releaseManifests).where(
|
|
50398
|
+
const rows = await db.select({ version: releaseManifests.version }).from(releaseManifests).where(eq11(releaseManifests.status, "pushed")).orderBy(desc4(releaseManifests.pushedAt)).limit(1).all();
|
|
50007
50399
|
return rows[0]?.version;
|
|
50008
50400
|
}
|
|
50009
50401
|
async function prepareRelease(version2, tasks2, notes, loadTasksFn, cwd) {
|
|
@@ -50015,7 +50407,7 @@ async function prepareRelease(version2, tasks2, notes, loadTasksFn, cwd) {
|
|
|
50015
50407
|
}
|
|
50016
50408
|
const normalizedVersion = normalizeVersion(version2);
|
|
50017
50409
|
const db = await getDb2(cwd);
|
|
50018
|
-
const existing = await db.select().from(releaseManifests).where(
|
|
50410
|
+
const existing = await db.select().from(releaseManifests).where(eq11(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
50019
50411
|
if (existing.length > 0) {
|
|
50020
50412
|
throw new Error(`Release ${normalizedVersion} already exists (status: ${existing[0].status})`);
|
|
50021
50413
|
}
|
|
@@ -50055,7 +50447,7 @@ async function generateReleaseChangelog(version2, loadTasksFn, cwd) {
|
|
|
50055
50447
|
}
|
|
50056
50448
|
const normalizedVersion = normalizeVersion(version2);
|
|
50057
50449
|
const db = await getDb2(cwd);
|
|
50058
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
50450
|
+
const rows = await db.select().from(releaseManifests).where(eq11(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
50059
50451
|
if (rows.length === 0) {
|
|
50060
50452
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
50061
50453
|
}
|
|
@@ -50192,7 +50584,7 @@ async function generateReleaseChangelog(version2, loadTasksFn, cwd) {
|
|
|
50192
50584
|
sections.push("");
|
|
50193
50585
|
}
|
|
50194
50586
|
const changelog = sections.join("\n");
|
|
50195
|
-
await db.update(releaseManifests).set({ changelog }).where(
|
|
50587
|
+
await db.update(releaseManifests).set({ changelog }).where(eq11(releaseManifests.version, normalizedVersion)).run();
|
|
50196
50588
|
const changelogPath = join67(cwd ?? process.cwd(), "CHANGELOG.md");
|
|
50197
50589
|
let existingChangelogContent = "";
|
|
50198
50590
|
try {
|
|
@@ -50230,8 +50622,8 @@ async function listManifestReleases(optionsOrCwd, cwd) {
|
|
|
50230
50622
|
const db = await getDb2(effectiveCwd);
|
|
50231
50623
|
const totalRow = await db.select({ count: count() }).from(releaseManifests).get();
|
|
50232
50624
|
const total = totalRow?.count ?? 0;
|
|
50233
|
-
const conditions = options.status ? [
|
|
50234
|
-
const whereClause = conditions.length > 0 ?
|
|
50625
|
+
const conditions = options.status ? [eq11(releaseManifests.status, options.status)] : [];
|
|
50626
|
+
const whereClause = conditions.length > 0 ? and8(...conditions) : void 0;
|
|
50235
50627
|
const filteredRow = await db.select({ count: count() }).from(releaseManifests).where(whereClause).get();
|
|
50236
50628
|
const filtered = filteredRow?.count ?? 0;
|
|
50237
50629
|
let query = db.select().from(releaseManifests).where(whereClause).orderBy(desc4(releaseManifests.createdAt));
|
|
@@ -50262,7 +50654,7 @@ async function showManifestRelease(version2, cwd) {
|
|
|
50262
50654
|
}
|
|
50263
50655
|
const normalizedVersion = normalizeVersion(version2);
|
|
50264
50656
|
const db = await getDb2(cwd);
|
|
50265
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
50657
|
+
const rows = await db.select().from(releaseManifests).where(eq11(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
50266
50658
|
if (rows.length === 0) {
|
|
50267
50659
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
50268
50660
|
}
|
|
@@ -50274,7 +50666,7 @@ async function commitRelease(version2, cwd) {
|
|
|
50274
50666
|
}
|
|
50275
50667
|
const normalizedVersion = normalizeVersion(version2);
|
|
50276
50668
|
const db = await getDb2(cwd);
|
|
50277
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
50669
|
+
const rows = await db.select().from(releaseManifests).where(eq11(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
50278
50670
|
if (rows.length === 0) {
|
|
50279
50671
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
50280
50672
|
}
|
|
@@ -50284,7 +50676,7 @@ async function commitRelease(version2, cwd) {
|
|
|
50284
50676
|
);
|
|
50285
50677
|
}
|
|
50286
50678
|
const committedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
50287
|
-
await db.update(releaseManifests).set({ status: "committed", committedAt }).where(
|
|
50679
|
+
await db.update(releaseManifests).set({ status: "committed", committedAt }).where(eq11(releaseManifests.version, normalizedVersion)).run();
|
|
50288
50680
|
return { version: normalizedVersion, status: "committed", committedAt };
|
|
50289
50681
|
}
|
|
50290
50682
|
async function tagRelease(version2, cwd) {
|
|
@@ -50293,12 +50685,12 @@ async function tagRelease(version2, cwd) {
|
|
|
50293
50685
|
}
|
|
50294
50686
|
const normalizedVersion = normalizeVersion(version2);
|
|
50295
50687
|
const db = await getDb2(cwd);
|
|
50296
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
50688
|
+
const rows = await db.select().from(releaseManifests).where(eq11(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
50297
50689
|
if (rows.length === 0) {
|
|
50298
50690
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
50299
50691
|
}
|
|
50300
50692
|
const taggedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
50301
|
-
await db.update(releaseManifests).set({ status: "tagged", taggedAt }).where(
|
|
50693
|
+
await db.update(releaseManifests).set({ status: "tagged", taggedAt }).where(eq11(releaseManifests.version, normalizedVersion)).run();
|
|
50302
50694
|
return { version: normalizedVersion, status: "tagged", taggedAt };
|
|
50303
50695
|
}
|
|
50304
50696
|
async function runReleaseGates(version2, loadTasksFn, cwd, opts) {
|
|
@@ -50307,7 +50699,7 @@ async function runReleaseGates(version2, loadTasksFn, cwd, opts) {
|
|
|
50307
50699
|
}
|
|
50308
50700
|
const normalizedVersion = normalizeVersion(version2);
|
|
50309
50701
|
const db = await getDb2(cwd);
|
|
50310
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
50702
|
+
const rows = await db.select().from(releaseManifests).where(eq11(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
50311
50703
|
if (rows.length === 0) {
|
|
50312
50704
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
50313
50705
|
}
|
|
@@ -50455,7 +50847,7 @@ async function cancelRelease(version2, projectRoot) {
|
|
|
50455
50847
|
}
|
|
50456
50848
|
const normalizedVersion = normalizeVersion(version2);
|
|
50457
50849
|
const db = await getDb2(projectRoot);
|
|
50458
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
50850
|
+
const rows = await db.select().from(releaseManifests).where(eq11(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
50459
50851
|
if (rows.length === 0) {
|
|
50460
50852
|
return {
|
|
50461
50853
|
success: false,
|
|
@@ -50472,7 +50864,7 @@ async function cancelRelease(version2, projectRoot) {
|
|
|
50472
50864
|
version: normalizedVersion
|
|
50473
50865
|
};
|
|
50474
50866
|
}
|
|
50475
|
-
await db.delete(releaseManifests).where(
|
|
50867
|
+
await db.delete(releaseManifests).where(eq11(releaseManifests.version, normalizedVersion)).run();
|
|
50476
50868
|
return {
|
|
50477
50869
|
success: true,
|
|
50478
50870
|
message: `Release ${normalizedVersion} cancelled and removed`,
|
|
@@ -50485,12 +50877,12 @@ async function rollbackRelease(version2, reason, cwd) {
|
|
|
50485
50877
|
}
|
|
50486
50878
|
const normalizedVersion = normalizeVersion(version2);
|
|
50487
50879
|
const db = await getDb2(cwd);
|
|
50488
|
-
const rows = await db.select().from(releaseManifests).where(
|
|
50880
|
+
const rows = await db.select().from(releaseManifests).where(eq11(releaseManifests.version, normalizedVersion)).limit(1).all();
|
|
50489
50881
|
if (rows.length === 0) {
|
|
50490
50882
|
throw new Error(`Release ${normalizedVersion} not found`);
|
|
50491
50883
|
}
|
|
50492
50884
|
const previousStatus = rows[0].status;
|
|
50493
|
-
await db.update(releaseManifests).set({ status: "rolled_back" }).where(
|
|
50885
|
+
await db.update(releaseManifests).set({ status: "rolled_back" }).where(eq11(releaseManifests.version, normalizedVersion)).run();
|
|
50494
50886
|
return {
|
|
50495
50887
|
version: normalizedVersion,
|
|
50496
50888
|
previousStatus,
|
|
@@ -50600,7 +50992,7 @@ async function markReleasePushed(version2, pushedAt, cwd, provenance) {
|
|
|
50600
50992
|
pushedAt,
|
|
50601
50993
|
...provenance?.commitSha != null ? { commitSha: provenance.commitSha } : {},
|
|
50602
50994
|
...provenance?.gitTag != null ? { gitTag: provenance.gitTag } : {}
|
|
50603
|
-
}).where(
|
|
50995
|
+
}).where(eq11(releaseManifests.version, normalizedVersion)).run();
|
|
50604
50996
|
}
|
|
50605
50997
|
async function migrateReleasesJsonToSqlite(projectRoot) {
|
|
50606
50998
|
const releasesPath = join67(getCleoDirAbsolute(projectRoot), "releases.json");
|
|
@@ -50620,7 +51012,7 @@ async function migrateReleasesJsonToSqlite(projectRoot) {
|
|
|
50620
51012
|
const db = await getDb2(projectRoot);
|
|
50621
51013
|
let migrated = 0;
|
|
50622
51014
|
for (const r of raw.releases) {
|
|
50623
|
-
const existing = await db.select({ id: releaseManifests.id }).from(releaseManifests).where(
|
|
51015
|
+
const existing = await db.select({ id: releaseManifests.id }).from(releaseManifests).where(eq11(releaseManifests.version, r.version)).limit(1).all();
|
|
50624
51016
|
if (existing.length > 0) continue;
|
|
50625
51017
|
const id = `rel-${r.version.replace(/[^a-z0-9]/gi, "-")}`;
|
|
50626
51018
|
await db.insert(releaseManifests).values({
|
|
@@ -56078,7 +56470,7 @@ async function queryTasks(cwd, since) {
|
|
|
56078
56470
|
try {
|
|
56079
56471
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
56080
56472
|
const { tasks: tasks2 } = await Promise.resolve().then(() => (init_tasks_schema(), tasks_schema_exports));
|
|
56081
|
-
const { and:
|
|
56473
|
+
const { and: and9, gte: gte3 } = await import("drizzle-orm");
|
|
56082
56474
|
const db = await getDb3(cwd);
|
|
56083
56475
|
const conditions = [];
|
|
56084
56476
|
if (since) {
|
|
@@ -56092,7 +56484,7 @@ async function queryTasks(cwd, since) {
|
|
|
56092
56484
|
sessionId: tasks2.sessionId,
|
|
56093
56485
|
completedAt: tasks2.completedAt,
|
|
56094
56486
|
createdAt: tasks2.createdAt
|
|
56095
|
-
}).from(tasks2).where(conditions.length > 0 ?
|
|
56487
|
+
}).from(tasks2).where(conditions.length > 0 ? and9(...conditions) : void 0).all();
|
|
56096
56488
|
return rows;
|
|
56097
56489
|
} catch (err) {
|
|
56098
56490
|
log7.warn({ err }, "Failed to query tasks for workflow telemetry");
|
|
@@ -56103,7 +56495,7 @@ async function queryCompletionAuditRows(cwd, since) {
|
|
|
56103
56495
|
try {
|
|
56104
56496
|
const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
|
|
56105
56497
|
const { auditLog: auditLog2 } = await Promise.resolve().then(() => (init_tasks_schema(), tasks_schema_exports));
|
|
56106
|
-
const { and:
|
|
56498
|
+
const { and: and9, gte: gte3 } = await import("drizzle-orm");
|
|
56107
56499
|
const db = await getDb3(cwd);
|
|
56108
56500
|
const conditions = [];
|
|
56109
56501
|
if (since) conditions.push(gte3(auditLog2.timestamp, since));
|
|
@@ -56115,7 +56507,7 @@ async function queryCompletionAuditRows(cwd, since) {
|
|
|
56115
56507
|
afterJson: auditLog2.afterJson,
|
|
56116
56508
|
operation: auditLog2.operation,
|
|
56117
56509
|
domain: auditLog2.domain
|
|
56118
|
-
}).from(auditLog2).where(conditions.length > 0 ?
|
|
56510
|
+
}).from(auditLog2).where(conditions.length > 0 ? and9(...conditions) : void 0).orderBy(auditLog2.timestamp).all();
|
|
56119
56511
|
return allRows.filter((row) => {
|
|
56120
56512
|
const isComplete = row.action === "task_completed" || row.action === "complete" || row.operation === "complete" && row.domain === "tasks";
|
|
56121
56513
|
if (!isComplete && row.afterJson) {
|
|
@@ -64084,45 +64476,67 @@ async function bootstrapGlobalCleo(options) {
|
|
|
64084
64476
|
await installSkillsGlobally(ctx);
|
|
64085
64477
|
await installAgentDefinitionGlobally(ctx);
|
|
64086
64478
|
await installProviderAdapters(ctx, options?.packageRoot);
|
|
64479
|
+
await verifyBootstrapHealth(ctx);
|
|
64087
64480
|
return ctx;
|
|
64088
64481
|
}
|
|
64482
|
+
async function writeTemplateTo(content, destPath, isDryRun) {
|
|
64483
|
+
if (isDryRun) return false;
|
|
64484
|
+
const { dirname: dirname20 } = await import("node:path");
|
|
64485
|
+
await mkdir17(dirname20(destPath), { recursive: true });
|
|
64486
|
+
await writeFile12(destPath, content);
|
|
64487
|
+
return true;
|
|
64488
|
+
}
|
|
64089
64489
|
async function ensureGlobalTemplatesBootstrap(ctx, packageRootOverride) {
|
|
64090
64490
|
const globalTemplatesDir = getCleoTemplatesDir();
|
|
64091
64491
|
if (!ctx.isDryRun) {
|
|
64092
64492
|
await mkdir17(globalTemplatesDir, { recursive: true });
|
|
64093
64493
|
}
|
|
64494
|
+
let templateContent = null;
|
|
64094
64495
|
try {
|
|
64095
64496
|
const pkgRoot = packageRootOverride ?? getPackageRoot();
|
|
64096
64497
|
const templatePath = join104(pkgRoot, "templates", "CLEO-INJECTION.md");
|
|
64097
64498
|
if (existsSync103(templatePath)) {
|
|
64098
|
-
|
|
64099
|
-
const destPath = join104(globalTemplatesDir, "CLEO-INJECTION.md");
|
|
64100
|
-
if (!ctx.isDryRun) {
|
|
64101
|
-
await writeFile12(destPath, content);
|
|
64102
|
-
}
|
|
64103
|
-
ctx.created.push(
|
|
64104
|
-
`~/.cleo/templates/CLEO-INJECTION.md (${ctx.isDryRun ? "would refresh" : "refreshed"})`
|
|
64105
|
-
);
|
|
64106
|
-
} else {
|
|
64107
|
-
try {
|
|
64108
|
-
const { getInjectionTemplateContent: getInjectionTemplateContent2 } = await Promise.resolve().then(() => (init_injection(), injection_exports));
|
|
64109
|
-
const content = getInjectionTemplateContent2();
|
|
64110
|
-
if (content) {
|
|
64111
|
-
const destPath = join104(globalTemplatesDir, "CLEO-INJECTION.md");
|
|
64112
|
-
if (!ctx.isDryRun) {
|
|
64113
|
-
await writeFile12(destPath, content);
|
|
64114
|
-
}
|
|
64115
|
-
ctx.created.push(
|
|
64116
|
-
`~/.cleo/templates/CLEO-INJECTION.md (${ctx.isDryRun ? "would refresh" : "refreshed"} from embedded)`
|
|
64117
|
-
);
|
|
64118
|
-
}
|
|
64119
|
-
} catch {
|
|
64120
|
-
ctx.warnings.push("Could not refresh CLEO-INJECTION.md template");
|
|
64121
|
-
}
|
|
64499
|
+
templateContent = readFileSync77(templatePath, "utf-8");
|
|
64122
64500
|
}
|
|
64123
64501
|
} catch {
|
|
64502
|
+
}
|
|
64503
|
+
if (!templateContent) {
|
|
64504
|
+
try {
|
|
64505
|
+
const { getInjectionTemplateContent: getInjectionTemplateContent2 } = await Promise.resolve().then(() => (init_injection(), injection_exports));
|
|
64506
|
+
templateContent = getInjectionTemplateContent2() ?? null;
|
|
64507
|
+
} catch {
|
|
64508
|
+
ctx.warnings.push("Could not refresh CLEO-INJECTION.md template");
|
|
64509
|
+
return;
|
|
64510
|
+
}
|
|
64511
|
+
}
|
|
64512
|
+
if (!templateContent) {
|
|
64124
64513
|
ctx.warnings.push("Could not refresh CLEO-INJECTION.md template");
|
|
64514
|
+
return;
|
|
64125
64515
|
}
|
|
64516
|
+
const xdgDest = join104(globalTemplatesDir, "CLEO-INJECTION.md");
|
|
64517
|
+
const xdgWritten = await writeTemplateTo(templateContent, xdgDest, ctx.isDryRun);
|
|
64518
|
+
ctx.created.push(
|
|
64519
|
+
`${getCleoTemplatesTildePath()}/CLEO-INJECTION.md (${xdgWritten ? "refreshed" : "would refresh"})`
|
|
64520
|
+
);
|
|
64521
|
+
const home = homedir6();
|
|
64522
|
+
const legacyTemplatesDir = join104(home, ".cleo", "templates");
|
|
64523
|
+
if (legacyTemplatesDir !== globalTemplatesDir && existsSync103(join104(home, ".cleo"))) {
|
|
64524
|
+
const legacyDest = join104(legacyTemplatesDir, "CLEO-INJECTION.md");
|
|
64525
|
+
const legacyWritten = await writeTemplateTo(templateContent, legacyDest, ctx.isDryRun);
|
|
64526
|
+
if (legacyWritten) {
|
|
64527
|
+
ctx.created.push("~/.cleo/templates/CLEO-INJECTION.md (legacy sync)");
|
|
64528
|
+
}
|
|
64529
|
+
}
|
|
64530
|
+
}
|
|
64531
|
+
function sanitizeCaampFile(content) {
|
|
64532
|
+
let cleaned = content.replace(/(<!-- CAAMP:END -->)\s*(<!-- CAAMP:END -->)/g, "$1");
|
|
64533
|
+
cleaned = cleaned.replace(
|
|
64534
|
+
/<!-- CAAMP:END -->\s*[A-Z][A-Za-z-]*\.md\s*(?:<!-- CAAMP:END -->)?/g,
|
|
64535
|
+
"<!-- CAAMP:END -->"
|
|
64536
|
+
);
|
|
64537
|
+
cleaned = cleaned.replace(/^[A-Z][A-Za-z-]*\.md\s*$/gm, "");
|
|
64538
|
+
cleaned = cleaned.replace(/\n{3,}/g, "\n\n");
|
|
64539
|
+
return cleaned.trim() + "\n";
|
|
64126
64540
|
}
|
|
64127
64541
|
async function injectAgentsHub(ctx) {
|
|
64128
64542
|
const globalAgentsDir = getAgentsHome();
|
|
@@ -64137,13 +64551,23 @@ async function injectAgentsHub(ctx) {
|
|
|
64137
64551
|
/\n?<!-- CLEO:START[^>]*-->[\s\S]*?<!-- CLEO:END -->\n?/g,
|
|
64138
64552
|
""
|
|
64139
64553
|
);
|
|
64140
|
-
|
|
64141
|
-
|
|
64554
|
+
const sanitized = sanitizeCaampFile(stripped);
|
|
64555
|
+
if (sanitized !== content) {
|
|
64556
|
+
await writeFile12(globalAgentsMd, sanitized, "utf8");
|
|
64557
|
+
ctx.created.push("~/.agents/AGENTS.md (sanitized CAAMP corruption)");
|
|
64142
64558
|
}
|
|
64143
64559
|
}
|
|
64144
64560
|
const templateRef = `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`;
|
|
64145
64561
|
const action = await inject2(globalAgentsMd, templateRef);
|
|
64146
64562
|
ctx.created.push(`~/.agents/AGENTS.md (${action})`);
|
|
64563
|
+
const postContent = await readFile19(globalAgentsMd, "utf8");
|
|
64564
|
+
const caampBlocks = postContent.match(/<!-- CAAMP:START -->/g);
|
|
64565
|
+
const caampEnds = postContent.match(/<!-- CAAMP:END -->/g);
|
|
64566
|
+
if (caampBlocks && caampEnds && caampBlocks.length !== caampEnds.length) {
|
|
64567
|
+
ctx.warnings.push(
|
|
64568
|
+
`~/.agents/AGENTS.md has mismatched CAAMP markers (${caampBlocks.length} START vs ${caampEnds.length} END)`
|
|
64569
|
+
);
|
|
64570
|
+
}
|
|
64147
64571
|
} else {
|
|
64148
64572
|
ctx.created.push("~/.agents/AGENTS.md (would create/update CAAMP block)");
|
|
64149
64573
|
}
|
|
@@ -64277,6 +64701,45 @@ async function installProviderAdapters(ctx, packageRootOverride) {
|
|
|
64277
64701
|
);
|
|
64278
64702
|
}
|
|
64279
64703
|
}
|
|
64704
|
+
async function verifyBootstrapHealth(ctx) {
|
|
64705
|
+
if (ctx.isDryRun) return;
|
|
64706
|
+
try {
|
|
64707
|
+
const xdgTemplatePath = join104(getCleoTemplatesDir(), "CLEO-INJECTION.md");
|
|
64708
|
+
const agentsMd = join104(getAgentsHome(), "AGENTS.md");
|
|
64709
|
+
if (!existsSync103(xdgTemplatePath)) {
|
|
64710
|
+
ctx.warnings.push("Health: XDG template missing after bootstrap");
|
|
64711
|
+
return;
|
|
64712
|
+
}
|
|
64713
|
+
const xdgContent = await readFile19(xdgTemplatePath, "utf8");
|
|
64714
|
+
const xdgVersion = xdgContent.match(/^Version:\s*(.+)$/m)?.[1]?.trim();
|
|
64715
|
+
const home = homedir6();
|
|
64716
|
+
const legacyTemplatePath = join104(home, ".cleo", "templates", "CLEO-INJECTION.md");
|
|
64717
|
+
if (existsSync103(legacyTemplatePath)) {
|
|
64718
|
+
const legacyContent = await readFile19(legacyTemplatePath, "utf8");
|
|
64719
|
+
const legacyVersion = legacyContent.match(/^Version:\s*(.+)$/m)?.[1]?.trim();
|
|
64720
|
+
if (legacyVersion !== xdgVersion) {
|
|
64721
|
+
ctx.warnings.push(
|
|
64722
|
+
`Health: Legacy template version (${legacyVersion}) != XDG version (${xdgVersion})`
|
|
64723
|
+
);
|
|
64724
|
+
}
|
|
64725
|
+
}
|
|
64726
|
+
if (existsSync103(agentsMd)) {
|
|
64727
|
+
const agentsContent = await readFile19(agentsMd, "utf8");
|
|
64728
|
+
const expectedRef = `@${getCleoTemplatesTildePath()}/CLEO-INJECTION.md`;
|
|
64729
|
+
if (!agentsContent.includes(expectedRef)) {
|
|
64730
|
+
ctx.warnings.push(`Health: ~/.agents/AGENTS.md does not reference ${expectedRef}`);
|
|
64731
|
+
}
|
|
64732
|
+
const outsideCaamp = agentsContent.replace(
|
|
64733
|
+
/<!-- CAAMP:START -->[\s\S]*?<!-- CAAMP:END -->/g,
|
|
64734
|
+
""
|
|
64735
|
+
);
|
|
64736
|
+
if (/[A-Z][A-Za-z-]*\.md/.test(outsideCaamp)) {
|
|
64737
|
+
ctx.warnings.push("Health: ~/.agents/AGENTS.md has orphaned content outside CAAMP blocks");
|
|
64738
|
+
}
|
|
64739
|
+
}
|
|
64740
|
+
} catch {
|
|
64741
|
+
}
|
|
64742
|
+
}
|
|
64280
64743
|
|
|
64281
64744
|
// packages/core/src/cleo.ts
|
|
64282
64745
|
import path from "node:path";
|
|
@@ -64351,7 +64814,10 @@ var Cleo = class _Cleo {
|
|
|
64351
64814
|
),
|
|
64352
64815
|
complete: (p) => completeTask({ taskId: p.taskId, notes: p.notes }, root, store),
|
|
64353
64816
|
delete: (p) => deleteTask({ taskId: p.taskId, force: p.force }, root, store),
|
|
64354
|
-
archive: (p) => archiveTasks({ before: p?.before, taskIds: p?.taskIds, dryRun: p?.dryRun }, root, store)
|
|
64817
|
+
archive: (p) => archiveTasks({ before: p?.before, taskIds: p?.taskIds, dryRun: p?.dryRun }, root, store),
|
|
64818
|
+
start: (taskId) => startTask(taskId, root, store),
|
|
64819
|
+
stop: () => stopTask(root, store),
|
|
64820
|
+
current: () => currentTask(root, store)
|
|
64355
64821
|
};
|
|
64356
64822
|
}
|
|
64357
64823
|
// === Sessions ===
|
|
@@ -64359,7 +64825,11 @@ var Cleo = class _Cleo {
|
|
|
64359
64825
|
const root = this.projectRoot;
|
|
64360
64826
|
const store = this._store ?? void 0;
|
|
64361
64827
|
return {
|
|
64362
|
-
start: (p) => startSession(
|
|
64828
|
+
start: (p) => startSession(
|
|
64829
|
+
{ name: p.name, scope: p.scope, agent: p.agent, startTask: p.startTask },
|
|
64830
|
+
root,
|
|
64831
|
+
store
|
|
64832
|
+
),
|
|
64363
64833
|
end: (p) => endSession({ note: p?.note }, root, store),
|
|
64364
64834
|
status: () => sessionStatus(root, store),
|
|
64365
64835
|
resume: (id) => resumeSession(id, root, store),
|
|
@@ -64497,6 +64967,35 @@ var Cleo = class _Cleo {
|
|
|
64497
64967
|
sharingStatus: () => getSharingStatus()
|
|
64498
64968
|
};
|
|
64499
64969
|
}
|
|
64970
|
+
// === Agents ===
|
|
64971
|
+
get agents() {
|
|
64972
|
+
const root = this.projectRoot;
|
|
64973
|
+
return {
|
|
64974
|
+
register: (opts) => registerAgent(opts, root),
|
|
64975
|
+
deregister: (agentId) => deregisterAgent(agentId, root),
|
|
64976
|
+
health: (agentId) => checkAgentHealth2(agentId, void 0, root),
|
|
64977
|
+
detectCrashed: (thresholdMs) => detectCrashedAgents(thresholdMs, root),
|
|
64978
|
+
recordHeartbeat: (agentId) => heartbeat(agentId, root),
|
|
64979
|
+
capacity: (agentId) => getAgentCapacity(agentId, root),
|
|
64980
|
+
isOverloaded: (threshold) => isOverloaded(threshold, root),
|
|
64981
|
+
list: (p) => listAgentInstances(
|
|
64982
|
+
{
|
|
64983
|
+
status: p?.status,
|
|
64984
|
+
agentType: p?.agentType
|
|
64985
|
+
},
|
|
64986
|
+
root
|
|
64987
|
+
)
|
|
64988
|
+
};
|
|
64989
|
+
}
|
|
64990
|
+
// === Intelligence ===
|
|
64991
|
+
get intelligence() {
|
|
64992
|
+
const root = this.projectRoot;
|
|
64993
|
+
const store = this._store ?? void 0;
|
|
64994
|
+
return {
|
|
64995
|
+
predictImpact: (change) => predictImpact(change, root, store ?? void 0),
|
|
64996
|
+
blastRadius: (taskId) => calculateBlastRadius(taskId, store ?? void 0, root)
|
|
64997
|
+
};
|
|
64998
|
+
}
|
|
64500
64999
|
// === Sync (Task Reconciliation) ===
|
|
64501
65000
|
get sync() {
|
|
64502
65001
|
const root = this.projectRoot;
|
|
@@ -64668,6 +65167,7 @@ export {
|
|
|
64668
65167
|
isSuccessCode,
|
|
64669
65168
|
isValidStatus,
|
|
64670
65169
|
issue_exports as issue,
|
|
65170
|
+
lib_exports as lib,
|
|
64671
65171
|
lifecycle_exports as lifecycle,
|
|
64672
65172
|
lifecycleEvidenceTypeSchema,
|
|
64673
65173
|
lifecycleGateResultSchema,
|