@hasna/loops 0.3.52 → 0.3.53
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/cli/index.js +68 -7
- package/dist/daemon/index.js +60 -1
- package/dist/index.js +59 -0
- package/dist/lib/store.d.ts +1 -0
- package/dist/lib/store.js +59 -0
- package/dist/sdk/index.js +59 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1567,6 +1567,65 @@ class Store {
|
|
|
1567
1567
|
throw new Error(`workflow invocation not found after create: ${id}`);
|
|
1568
1568
|
return rowToWorkflowInvocation(row);
|
|
1569
1569
|
}
|
|
1570
|
+
refreshWorkflowInvocationForWorkItem(workItemId, input) {
|
|
1571
|
+
const sourceDedupeKey = input.sourceRef.dedupeKey ?? undefined;
|
|
1572
|
+
if (!sourceDedupeKey)
|
|
1573
|
+
throw new Error("cannot refresh workflow invocation without sourceRef.dedupeKey");
|
|
1574
|
+
const now = nowIso();
|
|
1575
|
+
const claimableStatuses = ["queued", "deferred", "failed", "dead_letter", "cancelled"];
|
|
1576
|
+
const statusBindings = Object.fromEntries(claimableStatuses.map((status, index) => [`$status${index}`, status]));
|
|
1577
|
+
const placeholders = claimableStatuses.map((_, index) => `$status${index}`).join(",");
|
|
1578
|
+
const result = this.db.query(`UPDATE workflow_invocations
|
|
1579
|
+
SET workflow_id=COALESCE($workflowId, workflow_id),
|
|
1580
|
+
template_id=COALESCE($templateId, template_id),
|
|
1581
|
+
source_id=COALESCE($sourceId, source_id),
|
|
1582
|
+
source_json=$sourceJson,
|
|
1583
|
+
subject_kind=$subjectKind,
|
|
1584
|
+
subject_id=COALESCE($subjectId, subject_id),
|
|
1585
|
+
subject_path=COALESCE($subjectPath, subject_path),
|
|
1586
|
+
subject_url=COALESCE($subjectUrl, subject_url),
|
|
1587
|
+
subject_json=$subjectJson,
|
|
1588
|
+
intent=$intent,
|
|
1589
|
+
scope_json=COALESCE($scopeJson, scope_json),
|
|
1590
|
+
output_policy_json=COALESCE($outputPolicyJson, output_policy_json),
|
|
1591
|
+
updated_at=$updated
|
|
1592
|
+
WHERE source_kind=$sourceKind
|
|
1593
|
+
AND source_dedupe_key=$sourceDedupeKey
|
|
1594
|
+
AND EXISTS (
|
|
1595
|
+
SELECT 1
|
|
1596
|
+
FROM workflow_work_items
|
|
1597
|
+
WHERE id=$workItemId
|
|
1598
|
+
AND invocation_id=workflow_invocations.id
|
|
1599
|
+
AND status IN (${placeholders})
|
|
1600
|
+
)`).run({
|
|
1601
|
+
$workItemId: workItemId,
|
|
1602
|
+
$sourceKind: input.sourceRef.kind,
|
|
1603
|
+
$sourceDedupeKey: sourceDedupeKey,
|
|
1604
|
+
$workflowId: input.workflowId ?? null,
|
|
1605
|
+
$templateId: input.templateId ?? null,
|
|
1606
|
+
$sourceId: input.sourceRef.id ?? null,
|
|
1607
|
+
$sourceJson: JSON.stringify(input.sourceRef),
|
|
1608
|
+
$subjectKind: input.subjectRef.kind,
|
|
1609
|
+
$subjectId: input.subjectRef.id ?? null,
|
|
1610
|
+
$subjectPath: input.subjectRef.path ?? null,
|
|
1611
|
+
$subjectUrl: input.subjectRef.url ?? null,
|
|
1612
|
+
$subjectJson: JSON.stringify(input.subjectRef),
|
|
1613
|
+
$intent: input.intent,
|
|
1614
|
+
$scopeJson: input.scope ? JSON.stringify(input.scope) : null,
|
|
1615
|
+
$outputPolicyJson: input.outputPolicy ? JSON.stringify(input.outputPolicy) : null,
|
|
1616
|
+
$updated: now,
|
|
1617
|
+
...statusBindings
|
|
1618
|
+
});
|
|
1619
|
+
if (result.changes !== 1)
|
|
1620
|
+
throw new Error(`workflow work item is not refreshable: ${workItemId}`);
|
|
1621
|
+
const updated = this.db.query(`SELECT workflow_invocations.*
|
|
1622
|
+
FROM workflow_invocations
|
|
1623
|
+
JOIN workflow_work_items ON workflow_work_items.invocation_id = workflow_invocations.id
|
|
1624
|
+
WHERE workflow_work_items.id = ?`).get(workItemId);
|
|
1625
|
+
if (!updated)
|
|
1626
|
+
throw new Error(`workflow invocation not found after refresh for work item: ${workItemId}`);
|
|
1627
|
+
return rowToWorkflowInvocation(updated);
|
|
1628
|
+
}
|
|
1570
1629
|
getWorkflowInvocation(id) {
|
|
1571
1630
|
const row = this.db.query("SELECT * FROM workflow_invocations WHERE id = ?").get(id);
|
|
1572
1631
|
return row ? rowToWorkflowInvocation(row) : undefined;
|
|
@@ -5908,7 +5967,7 @@ function buildScriptInventoryReport(store, opts = {}) {
|
|
|
5908
5967
|
// package.json
|
|
5909
5968
|
var package_default = {
|
|
5910
5969
|
name: "@hasna/loops",
|
|
5911
|
-
version: "0.3.
|
|
5970
|
+
version: "0.3.53",
|
|
5912
5971
|
description: "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
|
|
5913
5972
|
type: "module",
|
|
5914
5973
|
main: "dist/index.js",
|
|
@@ -8536,8 +8595,9 @@ function routeTodosTaskEvent(event, opts) {
|
|
|
8536
8595
|
status: throttle && !throttle.allowed ? "deferred" : "queued",
|
|
8537
8596
|
lastReason: throttle && !throttle.allowed ? throttle.reason : undefined
|
|
8538
8597
|
});
|
|
8598
|
+
const refreshedInvocation = store.refreshWorkflowInvocationForWorkItem(workItem.id, invocationInput);
|
|
8539
8599
|
if (throttle && !throttle.allowed)
|
|
8540
|
-
return { kind: "throttled", invocation, workItem, throttle };
|
|
8600
|
+
return { kind: "throttled", invocation: refreshedInvocation, workItem, throttle };
|
|
8541
8601
|
const workflow = routeWorkflowForStorage(store, workflowBody);
|
|
8542
8602
|
const loop = store.createLoop({
|
|
8543
8603
|
...loopInput,
|
|
@@ -8545,13 +8605,13 @@ function routeTodosTaskEvent(event, opts) {
|
|
|
8545
8605
|
type: "workflow",
|
|
8546
8606
|
workflowId: workflow.id,
|
|
8547
8607
|
input: {
|
|
8548
|
-
workflowInvocationId:
|
|
8608
|
+
workflowInvocationId: refreshedInvocation.id,
|
|
8549
8609
|
workflowWorkItemId: workItem.id
|
|
8550
8610
|
}
|
|
8551
8611
|
}
|
|
8552
8612
|
});
|
|
8553
8613
|
const admitted = store.admitWorkflowWorkItem(workItem.id, { workflowId: workflow.id, loopId: loop.id, reason: "admitted by todos-task route" });
|
|
8554
|
-
return { kind: "created", invocation, workItem: admitted, workflow, loop, throttle };
|
|
8614
|
+
return { kind: "created", invocation: refreshedInvocation, workItem: admitted, workflow, loop, throttle };
|
|
8555
8615
|
});
|
|
8556
8616
|
if (outcome.kind === "deduped") {
|
|
8557
8617
|
return {
|
|
@@ -8752,8 +8812,9 @@ function routeGenericEvent(event, opts) {
|
|
|
8752
8812
|
status: throttle && !throttle.allowed ? "deferred" : "queued",
|
|
8753
8813
|
lastReason: throttle && !throttle.allowed ? throttle.reason : undefined
|
|
8754
8814
|
});
|
|
8815
|
+
const refreshedInvocation = store.refreshWorkflowInvocationForWorkItem(workItem.id, invocationInput);
|
|
8755
8816
|
if (throttle && !throttle.allowed)
|
|
8756
|
-
return { kind: "throttled", invocation, workItem, throttle };
|
|
8817
|
+
return { kind: "throttled", invocation: refreshedInvocation, workItem, throttle };
|
|
8757
8818
|
const workflow = routeWorkflowForStorage(store, workflowBody);
|
|
8758
8819
|
const loop = store.createLoop({
|
|
8759
8820
|
...loopInput,
|
|
@@ -8761,13 +8822,13 @@ function routeGenericEvent(event, opts) {
|
|
|
8761
8822
|
type: "workflow",
|
|
8762
8823
|
workflowId: workflow.id,
|
|
8763
8824
|
input: {
|
|
8764
|
-
workflowInvocationId:
|
|
8825
|
+
workflowInvocationId: refreshedInvocation.id,
|
|
8765
8826
|
workflowWorkItemId: workItem.id
|
|
8766
8827
|
}
|
|
8767
8828
|
}
|
|
8768
8829
|
});
|
|
8769
8830
|
const admitted = store.admitWorkflowWorkItem(workItem.id, { workflowId: workflow.id, loopId: loop.id, reason: "admitted by generic-event route" });
|
|
8770
|
-
return { kind: "created", invocation, workItem: admitted, workflow, loop, throttle };
|
|
8831
|
+
return { kind: "created", invocation: refreshedInvocation, workItem: admitted, workflow, loop, throttle };
|
|
8771
8832
|
});
|
|
8772
8833
|
if (outcome.kind === "deduped") {
|
|
8773
8834
|
return {
|
package/dist/daemon/index.js
CHANGED
|
@@ -1567,6 +1567,65 @@ class Store {
|
|
|
1567
1567
|
throw new Error(`workflow invocation not found after create: ${id}`);
|
|
1568
1568
|
return rowToWorkflowInvocation(row);
|
|
1569
1569
|
}
|
|
1570
|
+
refreshWorkflowInvocationForWorkItem(workItemId, input) {
|
|
1571
|
+
const sourceDedupeKey = input.sourceRef.dedupeKey ?? undefined;
|
|
1572
|
+
if (!sourceDedupeKey)
|
|
1573
|
+
throw new Error("cannot refresh workflow invocation without sourceRef.dedupeKey");
|
|
1574
|
+
const now = nowIso();
|
|
1575
|
+
const claimableStatuses = ["queued", "deferred", "failed", "dead_letter", "cancelled"];
|
|
1576
|
+
const statusBindings = Object.fromEntries(claimableStatuses.map((status, index) => [`$status${index}`, status]));
|
|
1577
|
+
const placeholders = claimableStatuses.map((_, index) => `$status${index}`).join(",");
|
|
1578
|
+
const result = this.db.query(`UPDATE workflow_invocations
|
|
1579
|
+
SET workflow_id=COALESCE($workflowId, workflow_id),
|
|
1580
|
+
template_id=COALESCE($templateId, template_id),
|
|
1581
|
+
source_id=COALESCE($sourceId, source_id),
|
|
1582
|
+
source_json=$sourceJson,
|
|
1583
|
+
subject_kind=$subjectKind,
|
|
1584
|
+
subject_id=COALESCE($subjectId, subject_id),
|
|
1585
|
+
subject_path=COALESCE($subjectPath, subject_path),
|
|
1586
|
+
subject_url=COALESCE($subjectUrl, subject_url),
|
|
1587
|
+
subject_json=$subjectJson,
|
|
1588
|
+
intent=$intent,
|
|
1589
|
+
scope_json=COALESCE($scopeJson, scope_json),
|
|
1590
|
+
output_policy_json=COALESCE($outputPolicyJson, output_policy_json),
|
|
1591
|
+
updated_at=$updated
|
|
1592
|
+
WHERE source_kind=$sourceKind
|
|
1593
|
+
AND source_dedupe_key=$sourceDedupeKey
|
|
1594
|
+
AND EXISTS (
|
|
1595
|
+
SELECT 1
|
|
1596
|
+
FROM workflow_work_items
|
|
1597
|
+
WHERE id=$workItemId
|
|
1598
|
+
AND invocation_id=workflow_invocations.id
|
|
1599
|
+
AND status IN (${placeholders})
|
|
1600
|
+
)`).run({
|
|
1601
|
+
$workItemId: workItemId,
|
|
1602
|
+
$sourceKind: input.sourceRef.kind,
|
|
1603
|
+
$sourceDedupeKey: sourceDedupeKey,
|
|
1604
|
+
$workflowId: input.workflowId ?? null,
|
|
1605
|
+
$templateId: input.templateId ?? null,
|
|
1606
|
+
$sourceId: input.sourceRef.id ?? null,
|
|
1607
|
+
$sourceJson: JSON.stringify(input.sourceRef),
|
|
1608
|
+
$subjectKind: input.subjectRef.kind,
|
|
1609
|
+
$subjectId: input.subjectRef.id ?? null,
|
|
1610
|
+
$subjectPath: input.subjectRef.path ?? null,
|
|
1611
|
+
$subjectUrl: input.subjectRef.url ?? null,
|
|
1612
|
+
$subjectJson: JSON.stringify(input.subjectRef),
|
|
1613
|
+
$intent: input.intent,
|
|
1614
|
+
$scopeJson: input.scope ? JSON.stringify(input.scope) : null,
|
|
1615
|
+
$outputPolicyJson: input.outputPolicy ? JSON.stringify(input.outputPolicy) : null,
|
|
1616
|
+
$updated: now,
|
|
1617
|
+
...statusBindings
|
|
1618
|
+
});
|
|
1619
|
+
if (result.changes !== 1)
|
|
1620
|
+
throw new Error(`workflow work item is not refreshable: ${workItemId}`);
|
|
1621
|
+
const updated = this.db.query(`SELECT workflow_invocations.*
|
|
1622
|
+
FROM workflow_invocations
|
|
1623
|
+
JOIN workflow_work_items ON workflow_work_items.invocation_id = workflow_invocations.id
|
|
1624
|
+
WHERE workflow_work_items.id = ?`).get(workItemId);
|
|
1625
|
+
if (!updated)
|
|
1626
|
+
throw new Error(`workflow invocation not found after refresh for work item: ${workItemId}`);
|
|
1627
|
+
return rowToWorkflowInvocation(updated);
|
|
1628
|
+
}
|
|
1570
1629
|
getWorkflowInvocation(id) {
|
|
1571
1630
|
const row = this.db.query("SELECT * FROM workflow_invocations WHERE id = ?").get(id);
|
|
1572
1631
|
return row ? rowToWorkflowInvocation(row) : undefined;
|
|
@@ -5240,7 +5299,7 @@ function enableStartup(result) {
|
|
|
5240
5299
|
// package.json
|
|
5241
5300
|
var package_default = {
|
|
5242
5301
|
name: "@hasna/loops",
|
|
5243
|
-
version: "0.3.
|
|
5302
|
+
version: "0.3.53",
|
|
5244
5303
|
description: "Persistent local loop and workflow runner for deterministic commands and headless AI coding agents",
|
|
5245
5304
|
type: "module",
|
|
5246
5305
|
main: "dist/index.js",
|
package/dist/index.js
CHANGED
|
@@ -1565,6 +1565,65 @@ class Store {
|
|
|
1565
1565
|
throw new Error(`workflow invocation not found after create: ${id}`);
|
|
1566
1566
|
return rowToWorkflowInvocation(row);
|
|
1567
1567
|
}
|
|
1568
|
+
refreshWorkflowInvocationForWorkItem(workItemId, input) {
|
|
1569
|
+
const sourceDedupeKey = input.sourceRef.dedupeKey ?? undefined;
|
|
1570
|
+
if (!sourceDedupeKey)
|
|
1571
|
+
throw new Error("cannot refresh workflow invocation without sourceRef.dedupeKey");
|
|
1572
|
+
const now = nowIso();
|
|
1573
|
+
const claimableStatuses = ["queued", "deferred", "failed", "dead_letter", "cancelled"];
|
|
1574
|
+
const statusBindings = Object.fromEntries(claimableStatuses.map((status, index) => [`$status${index}`, status]));
|
|
1575
|
+
const placeholders = claimableStatuses.map((_, index) => `$status${index}`).join(",");
|
|
1576
|
+
const result = this.db.query(`UPDATE workflow_invocations
|
|
1577
|
+
SET workflow_id=COALESCE($workflowId, workflow_id),
|
|
1578
|
+
template_id=COALESCE($templateId, template_id),
|
|
1579
|
+
source_id=COALESCE($sourceId, source_id),
|
|
1580
|
+
source_json=$sourceJson,
|
|
1581
|
+
subject_kind=$subjectKind,
|
|
1582
|
+
subject_id=COALESCE($subjectId, subject_id),
|
|
1583
|
+
subject_path=COALESCE($subjectPath, subject_path),
|
|
1584
|
+
subject_url=COALESCE($subjectUrl, subject_url),
|
|
1585
|
+
subject_json=$subjectJson,
|
|
1586
|
+
intent=$intent,
|
|
1587
|
+
scope_json=COALESCE($scopeJson, scope_json),
|
|
1588
|
+
output_policy_json=COALESCE($outputPolicyJson, output_policy_json),
|
|
1589
|
+
updated_at=$updated
|
|
1590
|
+
WHERE source_kind=$sourceKind
|
|
1591
|
+
AND source_dedupe_key=$sourceDedupeKey
|
|
1592
|
+
AND EXISTS (
|
|
1593
|
+
SELECT 1
|
|
1594
|
+
FROM workflow_work_items
|
|
1595
|
+
WHERE id=$workItemId
|
|
1596
|
+
AND invocation_id=workflow_invocations.id
|
|
1597
|
+
AND status IN (${placeholders})
|
|
1598
|
+
)`).run({
|
|
1599
|
+
$workItemId: workItemId,
|
|
1600
|
+
$sourceKind: input.sourceRef.kind,
|
|
1601
|
+
$sourceDedupeKey: sourceDedupeKey,
|
|
1602
|
+
$workflowId: input.workflowId ?? null,
|
|
1603
|
+
$templateId: input.templateId ?? null,
|
|
1604
|
+
$sourceId: input.sourceRef.id ?? null,
|
|
1605
|
+
$sourceJson: JSON.stringify(input.sourceRef),
|
|
1606
|
+
$subjectKind: input.subjectRef.kind,
|
|
1607
|
+
$subjectId: input.subjectRef.id ?? null,
|
|
1608
|
+
$subjectPath: input.subjectRef.path ?? null,
|
|
1609
|
+
$subjectUrl: input.subjectRef.url ?? null,
|
|
1610
|
+
$subjectJson: JSON.stringify(input.subjectRef),
|
|
1611
|
+
$intent: input.intent,
|
|
1612
|
+
$scopeJson: input.scope ? JSON.stringify(input.scope) : null,
|
|
1613
|
+
$outputPolicyJson: input.outputPolicy ? JSON.stringify(input.outputPolicy) : null,
|
|
1614
|
+
$updated: now,
|
|
1615
|
+
...statusBindings
|
|
1616
|
+
});
|
|
1617
|
+
if (result.changes !== 1)
|
|
1618
|
+
throw new Error(`workflow work item is not refreshable: ${workItemId}`);
|
|
1619
|
+
const updated = this.db.query(`SELECT workflow_invocations.*
|
|
1620
|
+
FROM workflow_invocations
|
|
1621
|
+
JOIN workflow_work_items ON workflow_work_items.invocation_id = workflow_invocations.id
|
|
1622
|
+
WHERE workflow_work_items.id = ?`).get(workItemId);
|
|
1623
|
+
if (!updated)
|
|
1624
|
+
throw new Error(`workflow invocation not found after refresh for work item: ${workItemId}`);
|
|
1625
|
+
return rowToWorkflowInvocation(updated);
|
|
1626
|
+
}
|
|
1568
1627
|
getWorkflowInvocation(id) {
|
|
1569
1628
|
const row = this.db.query("SELECT * FROM workflow_invocations WHERE id = ?").get(id);
|
|
1570
1629
|
return row ? rowToWorkflowInvocation(row) : undefined;
|
package/dist/lib/store.d.ts
CHANGED
|
@@ -104,6 +104,7 @@ export declare class Store {
|
|
|
104
104
|
private maybeArchiveGeneratedRouteWorkflow;
|
|
105
105
|
private maybeArchiveTerminalGeneratedRouteWorkflow;
|
|
106
106
|
createWorkflowInvocation(input: CreateWorkflowInvocationInput): WorkflowInvocation;
|
|
107
|
+
refreshWorkflowInvocationForWorkItem(workItemId: string, input: CreateWorkflowInvocationInput): WorkflowInvocation;
|
|
107
108
|
getWorkflowInvocation(id: string): WorkflowInvocation | undefined;
|
|
108
109
|
listWorkflowInvocations(opts?: {
|
|
109
110
|
limit?: number;
|
package/dist/lib/store.js
CHANGED
|
@@ -1565,6 +1565,65 @@ class Store {
|
|
|
1565
1565
|
throw new Error(`workflow invocation not found after create: ${id}`);
|
|
1566
1566
|
return rowToWorkflowInvocation(row);
|
|
1567
1567
|
}
|
|
1568
|
+
refreshWorkflowInvocationForWorkItem(workItemId, input) {
|
|
1569
|
+
const sourceDedupeKey = input.sourceRef.dedupeKey ?? undefined;
|
|
1570
|
+
if (!sourceDedupeKey)
|
|
1571
|
+
throw new Error("cannot refresh workflow invocation without sourceRef.dedupeKey");
|
|
1572
|
+
const now = nowIso();
|
|
1573
|
+
const claimableStatuses = ["queued", "deferred", "failed", "dead_letter", "cancelled"];
|
|
1574
|
+
const statusBindings = Object.fromEntries(claimableStatuses.map((status, index) => [`$status${index}`, status]));
|
|
1575
|
+
const placeholders = claimableStatuses.map((_, index) => `$status${index}`).join(",");
|
|
1576
|
+
const result = this.db.query(`UPDATE workflow_invocations
|
|
1577
|
+
SET workflow_id=COALESCE($workflowId, workflow_id),
|
|
1578
|
+
template_id=COALESCE($templateId, template_id),
|
|
1579
|
+
source_id=COALESCE($sourceId, source_id),
|
|
1580
|
+
source_json=$sourceJson,
|
|
1581
|
+
subject_kind=$subjectKind,
|
|
1582
|
+
subject_id=COALESCE($subjectId, subject_id),
|
|
1583
|
+
subject_path=COALESCE($subjectPath, subject_path),
|
|
1584
|
+
subject_url=COALESCE($subjectUrl, subject_url),
|
|
1585
|
+
subject_json=$subjectJson,
|
|
1586
|
+
intent=$intent,
|
|
1587
|
+
scope_json=COALESCE($scopeJson, scope_json),
|
|
1588
|
+
output_policy_json=COALESCE($outputPolicyJson, output_policy_json),
|
|
1589
|
+
updated_at=$updated
|
|
1590
|
+
WHERE source_kind=$sourceKind
|
|
1591
|
+
AND source_dedupe_key=$sourceDedupeKey
|
|
1592
|
+
AND EXISTS (
|
|
1593
|
+
SELECT 1
|
|
1594
|
+
FROM workflow_work_items
|
|
1595
|
+
WHERE id=$workItemId
|
|
1596
|
+
AND invocation_id=workflow_invocations.id
|
|
1597
|
+
AND status IN (${placeholders})
|
|
1598
|
+
)`).run({
|
|
1599
|
+
$workItemId: workItemId,
|
|
1600
|
+
$sourceKind: input.sourceRef.kind,
|
|
1601
|
+
$sourceDedupeKey: sourceDedupeKey,
|
|
1602
|
+
$workflowId: input.workflowId ?? null,
|
|
1603
|
+
$templateId: input.templateId ?? null,
|
|
1604
|
+
$sourceId: input.sourceRef.id ?? null,
|
|
1605
|
+
$sourceJson: JSON.stringify(input.sourceRef),
|
|
1606
|
+
$subjectKind: input.subjectRef.kind,
|
|
1607
|
+
$subjectId: input.subjectRef.id ?? null,
|
|
1608
|
+
$subjectPath: input.subjectRef.path ?? null,
|
|
1609
|
+
$subjectUrl: input.subjectRef.url ?? null,
|
|
1610
|
+
$subjectJson: JSON.stringify(input.subjectRef),
|
|
1611
|
+
$intent: input.intent,
|
|
1612
|
+
$scopeJson: input.scope ? JSON.stringify(input.scope) : null,
|
|
1613
|
+
$outputPolicyJson: input.outputPolicy ? JSON.stringify(input.outputPolicy) : null,
|
|
1614
|
+
$updated: now,
|
|
1615
|
+
...statusBindings
|
|
1616
|
+
});
|
|
1617
|
+
if (result.changes !== 1)
|
|
1618
|
+
throw new Error(`workflow work item is not refreshable: ${workItemId}`);
|
|
1619
|
+
const updated = this.db.query(`SELECT workflow_invocations.*
|
|
1620
|
+
FROM workflow_invocations
|
|
1621
|
+
JOIN workflow_work_items ON workflow_work_items.invocation_id = workflow_invocations.id
|
|
1622
|
+
WHERE workflow_work_items.id = ?`).get(workItemId);
|
|
1623
|
+
if (!updated)
|
|
1624
|
+
throw new Error(`workflow invocation not found after refresh for work item: ${workItemId}`);
|
|
1625
|
+
return rowToWorkflowInvocation(updated);
|
|
1626
|
+
}
|
|
1568
1627
|
getWorkflowInvocation(id) {
|
|
1569
1628
|
const row = this.db.query("SELECT * FROM workflow_invocations WHERE id = ?").get(id);
|
|
1570
1629
|
return row ? rowToWorkflowInvocation(row) : undefined;
|
package/dist/sdk/index.js
CHANGED
|
@@ -1565,6 +1565,65 @@ class Store {
|
|
|
1565
1565
|
throw new Error(`workflow invocation not found after create: ${id}`);
|
|
1566
1566
|
return rowToWorkflowInvocation(row);
|
|
1567
1567
|
}
|
|
1568
|
+
refreshWorkflowInvocationForWorkItem(workItemId, input) {
|
|
1569
|
+
const sourceDedupeKey = input.sourceRef.dedupeKey ?? undefined;
|
|
1570
|
+
if (!sourceDedupeKey)
|
|
1571
|
+
throw new Error("cannot refresh workflow invocation without sourceRef.dedupeKey");
|
|
1572
|
+
const now = nowIso();
|
|
1573
|
+
const claimableStatuses = ["queued", "deferred", "failed", "dead_letter", "cancelled"];
|
|
1574
|
+
const statusBindings = Object.fromEntries(claimableStatuses.map((status, index) => [`$status${index}`, status]));
|
|
1575
|
+
const placeholders = claimableStatuses.map((_, index) => `$status${index}`).join(",");
|
|
1576
|
+
const result = this.db.query(`UPDATE workflow_invocations
|
|
1577
|
+
SET workflow_id=COALESCE($workflowId, workflow_id),
|
|
1578
|
+
template_id=COALESCE($templateId, template_id),
|
|
1579
|
+
source_id=COALESCE($sourceId, source_id),
|
|
1580
|
+
source_json=$sourceJson,
|
|
1581
|
+
subject_kind=$subjectKind,
|
|
1582
|
+
subject_id=COALESCE($subjectId, subject_id),
|
|
1583
|
+
subject_path=COALESCE($subjectPath, subject_path),
|
|
1584
|
+
subject_url=COALESCE($subjectUrl, subject_url),
|
|
1585
|
+
subject_json=$subjectJson,
|
|
1586
|
+
intent=$intent,
|
|
1587
|
+
scope_json=COALESCE($scopeJson, scope_json),
|
|
1588
|
+
output_policy_json=COALESCE($outputPolicyJson, output_policy_json),
|
|
1589
|
+
updated_at=$updated
|
|
1590
|
+
WHERE source_kind=$sourceKind
|
|
1591
|
+
AND source_dedupe_key=$sourceDedupeKey
|
|
1592
|
+
AND EXISTS (
|
|
1593
|
+
SELECT 1
|
|
1594
|
+
FROM workflow_work_items
|
|
1595
|
+
WHERE id=$workItemId
|
|
1596
|
+
AND invocation_id=workflow_invocations.id
|
|
1597
|
+
AND status IN (${placeholders})
|
|
1598
|
+
)`).run({
|
|
1599
|
+
$workItemId: workItemId,
|
|
1600
|
+
$sourceKind: input.sourceRef.kind,
|
|
1601
|
+
$sourceDedupeKey: sourceDedupeKey,
|
|
1602
|
+
$workflowId: input.workflowId ?? null,
|
|
1603
|
+
$templateId: input.templateId ?? null,
|
|
1604
|
+
$sourceId: input.sourceRef.id ?? null,
|
|
1605
|
+
$sourceJson: JSON.stringify(input.sourceRef),
|
|
1606
|
+
$subjectKind: input.subjectRef.kind,
|
|
1607
|
+
$subjectId: input.subjectRef.id ?? null,
|
|
1608
|
+
$subjectPath: input.subjectRef.path ?? null,
|
|
1609
|
+
$subjectUrl: input.subjectRef.url ?? null,
|
|
1610
|
+
$subjectJson: JSON.stringify(input.subjectRef),
|
|
1611
|
+
$intent: input.intent,
|
|
1612
|
+
$scopeJson: input.scope ? JSON.stringify(input.scope) : null,
|
|
1613
|
+
$outputPolicyJson: input.outputPolicy ? JSON.stringify(input.outputPolicy) : null,
|
|
1614
|
+
$updated: now,
|
|
1615
|
+
...statusBindings
|
|
1616
|
+
});
|
|
1617
|
+
if (result.changes !== 1)
|
|
1618
|
+
throw new Error(`workflow work item is not refreshable: ${workItemId}`);
|
|
1619
|
+
const updated = this.db.query(`SELECT workflow_invocations.*
|
|
1620
|
+
FROM workflow_invocations
|
|
1621
|
+
JOIN workflow_work_items ON workflow_work_items.invocation_id = workflow_invocations.id
|
|
1622
|
+
WHERE workflow_work_items.id = ?`).get(workItemId);
|
|
1623
|
+
if (!updated)
|
|
1624
|
+
throw new Error(`workflow invocation not found after refresh for work item: ${workItemId}`);
|
|
1625
|
+
return rowToWorkflowInvocation(updated);
|
|
1626
|
+
}
|
|
1568
1627
|
getWorkflowInvocation(id) {
|
|
1569
1628
|
const row = this.db.query("SELECT * FROM workflow_invocations WHERE id = ?").get(id);
|
|
1570
1629
|
return row ? rowToWorkflowInvocation(row) : undefined;
|
package/package.json
CHANGED