@cadraos/sdk 0.3.7 → 0.3.9
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/board-host/index.d.cts +74 -6
- package/dist/board-host/index.d.ts +74 -6
- package/dist/board-host/server/index.d.cts +81 -6
- package/dist/board-host/server/index.d.ts +81 -6
- package/dist/chat/index.cjs +4 -43
- package/dist/chat/index.cjs.map +1 -1
- package/dist/chat/index.d.cts +7 -0
- package/dist/chat/index.d.ts +7 -0
- package/dist/chat/index.js +4 -43
- package/dist/chat/index.js.map +1 -1
- package/dist/index.cjs +4 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +4 -43
- package/dist/index.js.map +1 -1
- package/dist/kanban/engine/index.cjs +119 -31
- package/dist/kanban/engine/index.cjs.map +1 -1
- package/dist/kanban/engine/index.d.cts +112 -6
- package/dist/kanban/engine/index.d.ts +112 -6
- package/dist/kanban/engine/index.js +119 -31
- package/dist/kanban/engine/index.js.map +1 -1
- package/dist/kanban/index.cjs +574 -155
- package/dist/kanban/index.cjs.map +1 -1
- package/dist/kanban/index.d.cts +277 -11
- package/dist/kanban/index.d.ts +277 -11
- package/dist/kanban/index.js +569 -156
- package/dist/kanban/index.js.map +1 -1
- package/dist/teams/index.cjs +4 -43
- package/dist/teams/index.cjs.map +1 -1
- package/dist/teams/index.d.cts +7 -0
- package/dist/teams/index.d.ts +7 -0
- package/dist/teams/index.js +4 -43
- package/dist/teams/index.js.map +1 -1
- package/package.json +16 -15
|
@@ -12,6 +12,10 @@ function mapHandler(h) {
|
|
|
12
12
|
type: h.type,
|
|
13
13
|
agentUuid: h.agent_uuid,
|
|
14
14
|
teamUuid: h.team_uuid,
|
|
15
|
+
// FINDING-6: carry the remote_agent binding through the wire parse. The
|
|
16
|
+
// engine's remote_agent dispatch reads `remoteAgentUuid`; dropping it here
|
|
17
|
+
// made every published remote_agent lane dispatch-dead.
|
|
18
|
+
remoteAgentUuid: h.remote_agent_uuid,
|
|
15
19
|
agentRef: h.agent_ref,
|
|
16
20
|
webhook: h.webhook ? {
|
|
17
21
|
url: h.webhook.url,
|
|
@@ -219,6 +223,8 @@ var WebhookDeliveryError = class extends Error {
|
|
|
219
223
|
this.retryable = retryable;
|
|
220
224
|
this.name = "WebhookDeliveryError";
|
|
221
225
|
}
|
|
226
|
+
status;
|
|
227
|
+
retryable;
|
|
222
228
|
};
|
|
223
229
|
async function hmacSign(secret, payload) {
|
|
224
230
|
const enc = new TextEncoder();
|
|
@@ -321,6 +327,8 @@ async function dispatchStageHandler(ctx, cadra, webhookOpts) {
|
|
|
321
327
|
orgId: ctx.orgId,
|
|
322
328
|
input: ctx.input,
|
|
323
329
|
idemKey: runIdemKey,
|
|
330
|
+
// Board/headless dispatch always disables ask_user (spec §6.5 / FINDING-5).
|
|
331
|
+
allowAskUser: false,
|
|
324
332
|
callbackRef: ctx.callbackUrl
|
|
325
333
|
});
|
|
326
334
|
return { dispatched: true, executionUuid };
|
|
@@ -334,6 +342,8 @@ async function dispatchStageHandler(ctx, cadra, webhookOpts) {
|
|
|
334
342
|
orgId: ctx.orgId,
|
|
335
343
|
input: ctx.input,
|
|
336
344
|
idemKey: runIdemKey,
|
|
345
|
+
// Board/headless dispatch always disables ask_user (spec §6.5 / FINDING-5).
|
|
346
|
+
allowAskUser: false,
|
|
337
347
|
callbackRef: ctx.callbackUrl
|
|
338
348
|
});
|
|
339
349
|
return { dispatched: true, executionUuid };
|
|
@@ -384,10 +394,25 @@ function nextId(prefix) {
|
|
|
384
394
|
idSeq += 1;
|
|
385
395
|
return `${prefix}-${idSeq}`;
|
|
386
396
|
}
|
|
397
|
+
var DEFAULT_STALE_QUEUED_MS = 15 * 6e4;
|
|
387
398
|
var InMemoryStorageAdapter = class {
|
|
388
399
|
cards = /* @__PURE__ */ new Map();
|
|
389
400
|
logs = /* @__PURE__ */ new Map();
|
|
390
401
|
runs = /* @__PURE__ */ new Map();
|
|
402
|
+
/**
|
|
403
|
+
* A `queued` stage-run older than this (ms) is STALE and re-claimable by
|
|
404
|
+
* `beginStageRun` (design §10) — it models a run whose process died between
|
|
405
|
+
* `beginStageRun` and dispatch, so `failStageRun` never ran. A `failed` run is
|
|
406
|
+
* re-claimable regardless of age. Must comfortably exceed the dispatch time so
|
|
407
|
+
* a genuinely in-flight `queued` run is never re-claimed out from under it.
|
|
408
|
+
*/
|
|
409
|
+
staleQueuedMs;
|
|
410
|
+
/** Injectable clock (ms) — real hosts use `Date.now`; tests pin it. */
|
|
411
|
+
now;
|
|
412
|
+
constructor(opts) {
|
|
413
|
+
this.staleQueuedMs = opts?.staleQueuedMs ?? DEFAULT_STALE_QUEUED_MS;
|
|
414
|
+
this.now = opts?.now ?? (() => Date.now());
|
|
415
|
+
}
|
|
391
416
|
// ----- Cards -----
|
|
392
417
|
async listCards(boardConfigUuid) {
|
|
393
418
|
return [...this.cards.values()].filter((c) => c.boardConfigUuid === boardConfigUuid).map((c) => this.publicCard(c));
|
|
@@ -487,18 +512,48 @@ var InMemoryStorageAdapter = class {
|
|
|
487
512
|
// ----- Stage runs -----
|
|
488
513
|
async beginStageRun(cardId, r) {
|
|
489
514
|
const existing = this.runs.get(r.idemKey);
|
|
490
|
-
if (existing)
|
|
515
|
+
if (existing) {
|
|
516
|
+
if (this.isReclaimable(existing)) {
|
|
517
|
+
const run2 = {
|
|
518
|
+
idemKey: r.idemKey,
|
|
519
|
+
cardId,
|
|
520
|
+
stageId: r.stageId,
|
|
521
|
+
handlerType: r.handlerType,
|
|
522
|
+
status: "queued",
|
|
523
|
+
attempts: (existing.attempts ?? 1) + 1,
|
|
524
|
+
createdAt: new Date(this.now()).toISOString()
|
|
525
|
+
};
|
|
526
|
+
this.runs.set(r.idemKey, run2);
|
|
527
|
+
return { created: true, run: { ...run2 } };
|
|
528
|
+
}
|
|
529
|
+
return { created: false, run: { ...existing } };
|
|
530
|
+
}
|
|
491
531
|
const run = {
|
|
492
532
|
idemKey: r.idemKey,
|
|
493
533
|
cardId,
|
|
494
534
|
stageId: r.stageId,
|
|
495
535
|
handlerType: r.handlerType,
|
|
496
536
|
status: "queued",
|
|
497
|
-
|
|
537
|
+
attempts: 1,
|
|
538
|
+
createdAt: new Date(this.now()).toISOString()
|
|
498
539
|
};
|
|
499
540
|
this.runs.set(r.idemKey, run);
|
|
500
541
|
return { created: true, run: { ...run } };
|
|
501
542
|
}
|
|
543
|
+
/**
|
|
544
|
+
* A stranded stage-run the next `beginStageRun` may re-claim (design §10): a
|
|
545
|
+
* `failed` run (dispatch threw), or a `queued` run older than `staleQueuedMs`
|
|
546
|
+
* (a process died before dispatch flipped it). `running`/`completed` runs are
|
|
547
|
+
* never re-claimed.
|
|
548
|
+
*/
|
|
549
|
+
isReclaimable(run) {
|
|
550
|
+
if (run.status === "failed") return true;
|
|
551
|
+
if (run.status === "queued") {
|
|
552
|
+
const age = this.now() - Date.parse(run.createdAt);
|
|
553
|
+
return Number.isFinite(age) && age >= this.staleQueuedMs;
|
|
554
|
+
}
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
502
557
|
async completeStageRun(idemKey, c) {
|
|
503
558
|
const run = this.runs.get(idemKey);
|
|
504
559
|
if (!run) throw new Error(`No stage run for idemKey ${idemKey}`);
|
|
@@ -642,6 +697,10 @@ var HttpAdapterError = class extends Error {
|
|
|
642
697
|
this.body = body;
|
|
643
698
|
this.name = "HttpAdapterError";
|
|
644
699
|
}
|
|
700
|
+
status;
|
|
701
|
+
method;
|
|
702
|
+
path;
|
|
703
|
+
body;
|
|
645
704
|
code = "http_adapter_error";
|
|
646
705
|
};
|
|
647
706
|
var CapabilitiesNotLoadedError = class extends Error {
|
|
@@ -1193,6 +1252,14 @@ function runAdapterConformance(makeAdapter, runner) {
|
|
|
1193
1252
|
expect(still.lane).toBe("generate");
|
|
1194
1253
|
});
|
|
1195
1254
|
const asConductor = (adapter) => adapter.listDueCards && adapter.countsByLane && adapter.capabilities ? adapter : null;
|
|
1255
|
+
const supportsField = (adapter, field) => {
|
|
1256
|
+
const fields = adapter.capabilities().dueRuleFields;
|
|
1257
|
+
return fields.includes("*") || fields.includes(field);
|
|
1258
|
+
};
|
|
1259
|
+
const supportsPredicate = (adapter, ref) => {
|
|
1260
|
+
const preds = adapter.capabilities().dueRulePredicates;
|
|
1261
|
+
return preds.includes("*") || preds.includes(ref);
|
|
1262
|
+
};
|
|
1196
1263
|
it("listDueCards {kind:'always'} returns every card in the lane", async () => {
|
|
1197
1264
|
const base = await makeAdapter();
|
|
1198
1265
|
const adapter = asConductor(base);
|
|
@@ -1224,6 +1291,7 @@ function runAdapterConformance(makeAdapter, runner) {
|
|
|
1224
1291
|
const base = await makeAdapter();
|
|
1225
1292
|
const adapter = asConductor(base);
|
|
1226
1293
|
if (!adapter) return;
|
|
1294
|
+
if (!supportsField(adapter, "next_touch_at")) return;
|
|
1227
1295
|
const past = new Date(Date.now() - 6e4).toISOString();
|
|
1228
1296
|
const future = new Date(Date.now() + 6e4).toISOString();
|
|
1229
1297
|
await seedCard(adapter, "scheduled", "due", { next_touch_at: past });
|
|
@@ -1245,6 +1313,7 @@ function runAdapterConformance(makeAdapter, runner) {
|
|
|
1245
1313
|
const base = await makeAdapter();
|
|
1246
1314
|
const adapter = asConductor(base);
|
|
1247
1315
|
if (!adapter) return;
|
|
1316
|
+
if (!supportsPredicate(adapter, "status")) return;
|
|
1248
1317
|
await seedCard(adapter, "queued", "approved", { status: "approved" });
|
|
1249
1318
|
await seedCard(adapter, "queued", "draft", { status: "draft" });
|
|
1250
1319
|
const rule = {
|
|
@@ -1261,6 +1330,8 @@ function runAdapterConformance(makeAdapter, runner) {
|
|
|
1261
1330
|
const base = await makeAdapter();
|
|
1262
1331
|
const adapter = asConductor(base);
|
|
1263
1332
|
if (!adapter) return;
|
|
1333
|
+
if (!supportsField(adapter, "next_touch_at") || !supportsPredicate(adapter, "status"))
|
|
1334
|
+
return;
|
|
1264
1335
|
const past = new Date(Date.now() - 6e4).toISOString();
|
|
1265
1336
|
const future = new Date(Date.now() + 6e4).toISOString();
|
|
1266
1337
|
await seedCard(adapter, "queued", "send-me", {
|
|
@@ -1523,20 +1594,28 @@ function createEngine(options) {
|
|
|
1523
1594
|
if (!begin.created) {
|
|
1524
1595
|
return { dispatched: false, executionUuid: begin.run.executionUuid };
|
|
1525
1596
|
}
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1597
|
+
let result;
|
|
1598
|
+
try {
|
|
1599
|
+
result = await dispatchStageHandler(
|
|
1600
|
+
{
|
|
1601
|
+
cardId,
|
|
1602
|
+
boardConfigUuid: card.boardId,
|
|
1603
|
+
configVersion: cfg.version,
|
|
1604
|
+
stage,
|
|
1605
|
+
idemKey,
|
|
1606
|
+
input: cardContext(card, stage),
|
|
1607
|
+
orgId: options.orgId,
|
|
1608
|
+
callbackUrl
|
|
1609
|
+
},
|
|
1610
|
+
cadraClient,
|
|
1611
|
+
webhookOptions
|
|
1612
|
+
);
|
|
1613
|
+
} catch (err) {
|
|
1614
|
+
await adapter.failStageRun(idemKey, {
|
|
1615
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1616
|
+
});
|
|
1617
|
+
throw err;
|
|
1618
|
+
}
|
|
1540
1619
|
if (result.executionUuid && adapter.markStageRunDispatched) {
|
|
1541
1620
|
await adapter.markStageRunDispatched(idemKey, {
|
|
1542
1621
|
executionUuid: result.executionUuid
|
|
@@ -1605,21 +1684,30 @@ function createEngine(options) {
|
|
|
1605
1684
|
}));
|
|
1606
1685
|
batchMembers.set(batchKey, batchCards.map((c) => c.idemKey));
|
|
1607
1686
|
const lead = eligible[0].card;
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1687
|
+
let result;
|
|
1688
|
+
try {
|
|
1689
|
+
result = await dispatchStageHandler(
|
|
1690
|
+
{
|
|
1691
|
+
cardId: lead.id,
|
|
1692
|
+
boardConfigUuid: lead.boardId,
|
|
1693
|
+
configVersion: cfg.version,
|
|
1694
|
+
stage,
|
|
1695
|
+
idemKey: eligible[0].idemKey,
|
|
1696
|
+
input: batchContext(lead, stage, batchCards),
|
|
1697
|
+
orgId: options.orgId,
|
|
1698
|
+
callbackUrl,
|
|
1699
|
+
batch: { batchKey, cards: batchCards }
|
|
1700
|
+
},
|
|
1701
|
+
cadraClient,
|
|
1702
|
+
webhookOptions
|
|
1703
|
+
);
|
|
1704
|
+
} catch (err) {
|
|
1705
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1706
|
+
for (const { idemKey } of eligible) {
|
|
1707
|
+
await adapter.failStageRun(idemKey, { error: msg });
|
|
1708
|
+
}
|
|
1709
|
+
throw err;
|
|
1710
|
+
}
|
|
1623
1711
|
if (result.executionUuid && adapter.markStageRunDispatched) {
|
|
1624
1712
|
for (const { idemKey } of eligible) {
|
|
1625
1713
|
await adapter.markStageRunDispatched(idemKey, {
|