@relaycast/engine 8.11.5 → 8.11.7
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/engine/action.d.ts.map +1 -1
- package/dist/engine/action.js +14 -125
- package/dist/engine/action.js.map +1 -1
- package/dist/engine/agent.d.ts +20 -0
- package/dist/engine/agent.d.ts.map +1 -1
- package/dist/engine/agent.js +35 -2
- package/dist/engine/agent.js.map +1 -1
- package/dist/engine/node.d.ts.map +1 -1
- package/dist/engine/node.js +58 -5
- package/dist/engine/node.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../src/engine/action.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAW,iBAAiB,EAAoE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../src/engine/action.ts"],"names":[],"mappings":"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"}
|
package/dist/engine/action.js
CHANGED
|
@@ -2,7 +2,7 @@ import { and, asc, eq, inArray, isNotNull, isNull, lte, or, sql } from 'drizzle-
|
|
|
2
2
|
import { actions, actionInvocations, agents, agentNodeBindings, channelMembers, dmParticipants, nodes } from '../db/schema.js';
|
|
3
3
|
import { waitForPendingInvocationRetry } from './invocationRetry.js';
|
|
4
4
|
import { generateId } from './snowflake.js';
|
|
5
|
-
import { assertRegistrableAgentName, RELEASED_AGENT_STATUS, releasedAgentName } from './agent.js';
|
|
5
|
+
import { assertRegistrableAgentName, buildDeadLetterReleasedAgentDeliveriesWrite, RELEASED_AGENT_STATUS, releasedAgentName, } from './agent.js';
|
|
6
6
|
import { randomHex, sha256Hex } from '../lib/crypto.js';
|
|
7
7
|
import { codedError } from '../lib/httpError.js';
|
|
8
8
|
import { D1_SAFE_IN_QUERY_CHUNK_SIZE } from '../lib/queryChunks.js';
|
|
@@ -939,6 +939,7 @@ async function dispatchRelease(args) {
|
|
|
939
939
|
writes.push(writeDb
|
|
940
940
|
.delete(dmParticipants)
|
|
941
941
|
.where(and(eq(dmParticipants.agentId, agent.id), invocationCompleted, generationStillCurrent)));
|
|
942
|
+
writes.push(buildDeadLetterReleasedAgentDeliveriesWrite(writeDb, args.workspaceId, agent.id, completedAt, and(invocationCompleted, generationStillCurrent)));
|
|
942
943
|
writes.push(writeDb
|
|
943
944
|
.delete(nodes)
|
|
944
945
|
.where(and(eq(nodes.workspaceId, args.workspaceId), eq(nodes.id, `node_direct_${agent.id}`), invocationCompleted, generationStillCurrent)));
|
|
@@ -965,7 +966,7 @@ async function dispatchRelease(args) {
|
|
|
965
966
|
})
|
|
966
967
|
.where(and(eq(agents.workspaceId, args.workspaceId), eq(agents.id, agent.id), ...(expectedTokenHash ? [eq(agents.tokenHash, expectedTokenHash)] : []), invocationCompleted)));
|
|
967
968
|
return writes;
|
|
968
|
-
},
|
|
969
|
+
}, { requireAtomic: true });
|
|
969
970
|
const generationConflict = results[0];
|
|
970
971
|
const completed = results[1];
|
|
971
972
|
const completedExitNodeId = completed[0]?.handlerNodeId ?? null;
|
|
@@ -1606,7 +1607,7 @@ function publicInvocation(row) {
|
|
|
1606
1607
|
...(row.taskState ? { task_execution: taskExecution(row) } : {}),
|
|
1607
1608
|
};
|
|
1608
1609
|
}
|
|
1609
|
-
async function
|
|
1610
|
+
async function completeReleaseNodeInvocation(db, workspaceId, nodeId, providerName, invocation, data, deps) {
|
|
1610
1611
|
const input = recordInput(invocation.input);
|
|
1611
1612
|
const name = typeof input.name === 'string' ? input.name : null;
|
|
1612
1613
|
const persistedTokenHash = input.expected_token_hash;
|
|
@@ -1615,7 +1616,7 @@ async function completeGuardedReleaseNodeInvocation(db, workspaceId, nodeId, pro
|
|
|
1615
1616
|
? persistedTokenHash
|
|
1616
1617
|
: null;
|
|
1617
1618
|
const expectedAgentId = releaseExpectedAgentId(input);
|
|
1618
|
-
if (!name || (!expectedTokenHash && !expectedAgentId)) {
|
|
1619
|
+
if (!name || (persistedTokenHash !== undefined && !expectedTokenHash && !expectedAgentId)) {
|
|
1619
1620
|
const [failed] = await db
|
|
1620
1621
|
.update(actionInvocations)
|
|
1621
1622
|
.set({
|
|
@@ -1676,10 +1677,9 @@ async function completeGuardedReleaseNodeInvocation(db, workspaceId, nodeId, pro
|
|
|
1676
1677
|
let successIndex = -1;
|
|
1677
1678
|
const results = await runAtomicWrites(db, (writeDb) => {
|
|
1678
1679
|
const writes = [];
|
|
1679
|
-
//
|
|
1680
|
-
//
|
|
1681
|
-
//
|
|
1682
|
-
// statement ordering and rollback guarantee apply.
|
|
1680
|
+
// Settle conflicts before lifecycle mutations. Every statement belongs
|
|
1681
|
+
// to one required transaction or atomic batch, including legacy releases
|
|
1682
|
+
// without an explicit identity or token guard.
|
|
1683
1683
|
writes.push(writeDb
|
|
1684
1684
|
.update(actionInvocations)
|
|
1685
1685
|
.set({
|
|
@@ -1722,6 +1722,10 @@ async function completeGuardedReleaseNodeInvocation(db, workspaceId, nodeId, pro
|
|
|
1722
1722
|
.returning());
|
|
1723
1723
|
const currentAgent = and(eq(agents.workspaceId, workspaceId), eq(agents.id, agent.id), eq(agents.name, name), ...(expectedTokenHash ? [eq(agents.tokenHash, expectedTokenHash)] : []), invocationCompleted);
|
|
1724
1724
|
if (input.delete_agent === true) {
|
|
1725
|
+
// Settle while the release generation is still current. The tombstone
|
|
1726
|
+
// update below intentionally rotates its token and name, after which the
|
|
1727
|
+
// same generation predicate must no longer match.
|
|
1728
|
+
writes.push(buildDeadLetterReleasedAgentDeliveriesWrite(writeDb, workspaceId, agent.id, completedAt, and(invocationCompleted, generationStillCurrent)));
|
|
1725
1729
|
writes.push(writeDb
|
|
1726
1730
|
.update(agents)
|
|
1727
1731
|
.set({
|
|
@@ -1795,115 +1799,6 @@ async function completeGuardedReleaseNodeInvocation(db, workspaceId, nodeId, pro
|
|
|
1795
1799
|
}
|
|
1796
1800
|
return publicInvocation(settled);
|
|
1797
1801
|
}
|
|
1798
|
-
async function applyReleaseCompletionEffect(db, workspaceId, nodeId, invocation, data, deps, options = {}) {
|
|
1799
|
-
if (!isBuiltinReleaseInvocation(invocation) || data.error)
|
|
1800
|
-
return false;
|
|
1801
|
-
const input = recordInput(invocation.input);
|
|
1802
|
-
const name = typeof input.name === 'string' ? input.name : null;
|
|
1803
|
-
if (!name)
|
|
1804
|
-
return false;
|
|
1805
|
-
const [agent] = await db
|
|
1806
|
-
.select()
|
|
1807
|
-
.from(agents)
|
|
1808
|
-
.where(and(eq(agents.workspaceId, workspaceId), eq(agents.name, name), ...(options.expectedAgentId ? [eq(agents.id, options.expectedAgentId)] : []), ...(!options.allowMissingBinding && nodeId ? [
|
|
1809
|
-
eq(agents.locationType, 'via_node'),
|
|
1810
|
-
eq(agents.locationNodeId, nodeId),
|
|
1811
|
-
] : [])));
|
|
1812
|
-
if (!agent)
|
|
1813
|
-
return false;
|
|
1814
|
-
// Only proceed if an active binding actually flipped to inactive. This guards
|
|
1815
|
-
// against a second release (e.g. a retry) double-decrementing activeAgents for
|
|
1816
|
-
// an agent that was already released from this node.
|
|
1817
|
-
const deactivatedBindings = await db
|
|
1818
|
-
.update(agentNodeBindings)
|
|
1819
|
-
.set({ status: 'inactive', updatedAt: new Date() })
|
|
1820
|
-
.where(and(eq(agentNodeBindings.workspaceId, workspaceId), eq(agentNodeBindings.agentId, agent.id), eq(agentNodeBindings.status, 'active'), ...(nodeId ? [eq(agentNodeBindings.nodeId, nodeId)] : [])))
|
|
1821
|
-
.returning({ nodeId: agentNodeBindings.nodeId });
|
|
1822
|
-
if (deactivatedBindings.length === 0 && !options.allowMissingBinding)
|
|
1823
|
-
return false;
|
|
1824
|
-
// Capture exit correlation BEFORE the mutation deletes the row or strips the
|
|
1825
|
-
// spawn/cli metadata, so a durable agent.exited can still be emitted.
|
|
1826
|
-
const exited = { agentId: agent.id, agentName: agent.name, invocationId: fleetInvocationId(agent.metadata) };
|
|
1827
|
-
const deactivatedNodeIds = Array.from(new Set(deactivatedBindings.map((binding) => binding.nodeId)));
|
|
1828
|
-
if (deactivatedNodeIds.length > 0) {
|
|
1829
|
-
await db
|
|
1830
|
-
.update(nodes)
|
|
1831
|
-
.set({
|
|
1832
|
-
activeAgents: sql `CASE WHEN ${nodes.activeAgents} > 0 THEN ${nodes.activeAgents} - 1 ELSE 0 END`,
|
|
1833
|
-
})
|
|
1834
|
-
.where(and(eq(nodes.workspaceId, workspaceId), inArray(nodes.id, deactivatedNodeIds)));
|
|
1835
|
-
}
|
|
1836
|
-
if (input.delete_agent === true) {
|
|
1837
|
-
// Tombstone rather than DELETE, matching `dispatchRelease`'s
|
|
1838
|
-
// `completeLocally`. Four FKs reference `agents.id` without an ON DELETE
|
|
1839
|
-
// action (`messages.agent_id`, `channels.created_by`, `files.uploaded_by`,
|
|
1840
|
-
// `webhooks.created_by`), so a bare delete is refused for any agent that
|
|
1841
|
-
// has ever spoken — and this runs inside the completion's atomic unit, so
|
|
1842
|
-
// that refusal aborts the invocation completion too. The seat and the name
|
|
1843
|
-
// then stay claimed forever and the caller only ever sees `dispatched`.
|
|
1844
|
-
// Renaming frees the unique `(workspace_id, name)` immediately while every
|
|
1845
|
-
// FK target stays valid and every message keeps its sender.
|
|
1846
|
-
const releasedName = releasedAgentName(agent.name, agent.id);
|
|
1847
|
-
// The row survives, so its credential must not. `token_hash` is NOT NULL
|
|
1848
|
-
// UNIQUE and cannot be cleared, so rotate it to a value nobody holds.
|
|
1849
|
-
const releasedTokenHash = await sha256Hex(`released:${agent.id}:${randomHex(16)}`);
|
|
1850
|
-
await db
|
|
1851
|
-
.update(agents)
|
|
1852
|
-
.set({
|
|
1853
|
-
name: releasedName,
|
|
1854
|
-
handle: `@${releasedName}`,
|
|
1855
|
-
status: RELEASED_AGENT_STATUS,
|
|
1856
|
-
tokenHash: releasedTokenHash,
|
|
1857
|
-
// Same reason as the other release paths — the grace slot survives
|
|
1858
|
-
// `token_hash` rewrites unless we clear it. See 0035_agent_token_grace.
|
|
1859
|
-
previousTokenHash: null,
|
|
1860
|
-
previousTokenExpiresAt: null,
|
|
1861
|
-
locationType: 'self_connected',
|
|
1862
|
-
locationNodeId: null,
|
|
1863
|
-
lastSeen: new Date(),
|
|
1864
|
-
})
|
|
1865
|
-
.where(and(eq(agents.workspaceId, workspaceId), eq(agents.id, agent.id)));
|
|
1866
|
-
// `channel_members` and `dm_participants` reference `agents.id` ON DELETE
|
|
1867
|
-
// CASCADE; an UPDATE does not fire that cascade, so drop the memberships
|
|
1868
|
-
// explicitly or the released agent stays a delivery target.
|
|
1869
|
-
await db.delete(channelMembers).where(eq(channelMembers.agentId, agent.id));
|
|
1870
|
-
await db.delete(dmParticipants).where(eq(dmParticipants.agentId, agent.id));
|
|
1871
|
-
const implicitNodeId = `node_direct_${agent.id}`;
|
|
1872
|
-
await db.delete(nodes).where(and(eq(nodes.workspaceId, workspaceId), eq(nodes.id, implicitNodeId)));
|
|
1873
|
-
}
|
|
1874
|
-
else {
|
|
1875
|
-
const existingMetadata = agent.metadata ?? {};
|
|
1876
|
-
const { spawn: _spawn, cli: _cli, ...restMetadata } = existingMetadata;
|
|
1877
|
-
await db
|
|
1878
|
-
.update(agents)
|
|
1879
|
-
.set({
|
|
1880
|
-
status: 'offline',
|
|
1881
|
-
// Clear the node location so the agent is no longer routable to the released
|
|
1882
|
-
// node and a repeat release can't re-decrement the node's active count.
|
|
1883
|
-
locationType: 'self_connected',
|
|
1884
|
-
locationNodeId: null,
|
|
1885
|
-
lastSeen: new Date(),
|
|
1886
|
-
metadata: {
|
|
1887
|
-
...restMetadata,
|
|
1888
|
-
release: {
|
|
1889
|
-
reason: typeof input.reason === 'string' ? input.reason : null,
|
|
1890
|
-
released_at: new Date().toISOString(),
|
|
1891
|
-
},
|
|
1892
|
-
},
|
|
1893
|
-
})
|
|
1894
|
-
.where(and(eq(agents.workspaceId, workspaceId), eq(agents.id, agent.id)));
|
|
1895
|
-
}
|
|
1896
|
-
if (deps && nodeId) {
|
|
1897
|
-
await emitAgentExitedEffects(deps, workspaceId, {
|
|
1898
|
-
agentId: exited.agentId,
|
|
1899
|
-
agentName: exited.agentName,
|
|
1900
|
-
nodeId,
|
|
1901
|
-
invocationId: exited.invocationId,
|
|
1902
|
-
reason: 'released',
|
|
1903
|
-
});
|
|
1904
|
-
}
|
|
1905
|
-
return true;
|
|
1906
|
-
}
|
|
1907
1802
|
async function dispatchNodeAttempt(db, workspaceId, invocationId, nodeId, opts) {
|
|
1908
1803
|
const stateFields = opts.pending
|
|
1909
1804
|
? { status: 'pending', dispatchedAt: null, retryAfterAt: opts.retryAfterAt ?? null }
|
|
@@ -2732,11 +2627,8 @@ export async function completeNodeInvocation(db, registry, workspaceId, nodeId,
|
|
|
2732
2627
|
// Fall through and fail the invocation if no eligible node exists.
|
|
2733
2628
|
}
|
|
2734
2629
|
}
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
&& isBuiltinReleaseInvocation(existing)
|
|
2738
|
-
&& (existingInput.expected_token_hash !== undefined || existingInput.expected_agent_id !== undefined)) {
|
|
2739
|
-
return completeGuardedReleaseNodeInvocation(db, workspaceId, nodeId, providerName, existing, data, deps);
|
|
2630
|
+
if (!data.error && isBuiltinReleaseInvocation(existing)) {
|
|
2631
|
+
return completeReleaseNodeInvocation(db, workspaceId, nodeId, providerName, existing, data, deps);
|
|
2740
2632
|
}
|
|
2741
2633
|
const [updated] = await db
|
|
2742
2634
|
.update(actionInvocations)
|
|
@@ -2755,9 +2647,6 @@ export async function completeNodeInvocation(db, registry, workspaceId, nodeId,
|
|
|
2755
2647
|
if (updated && isSpawnInvocation(updated.actionName) && updated.dispatchedNodeId && existing.spawnReservedAt) {
|
|
2756
2648
|
await releaseNodeCapacity(db, workspaceId, updated.dispatchedNodeId);
|
|
2757
2649
|
}
|
|
2758
|
-
if (updated) {
|
|
2759
|
-
await applyReleaseCompletionEffect(db, workspaceId, nodeId, existing, data, deps);
|
|
2760
|
-
}
|
|
2761
2650
|
return updated ? publicInvocation(updated) : null;
|
|
2762
2651
|
}
|
|
2763
2652
|
/**
|