@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.
@@ -1 +1 @@
1
- {"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../src/engine/action.ts"],"names":[],"mappings":"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"}
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;AAa/H,OAAO,EAIL,KAAK,wBAAwB,EAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAOrF,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AAEnC,KAAK,aAAa,GAAG,OAAO,iBAAiB,CAAC,YAAY,CAAC;AAC3D,KAAK,sBAAsB,GAAG,IAAI,CAChC,aAAa,EACb,IAAI,GAAG,aAAa,GAAG,UAAU,GAAG,YAAY,GAAG,kBAAkB,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,kBAAkB,GAAG,yBAAyB,GAAG,iBAAiB,GAAG,kBAAkB,GAAG,kBAAkB,CACvN,CAAC;AAIF,eAAO,MAAM,0BAA0B,QAAS,CAAC;AACjD;;;;;;;GAOG;AACH,eAAO,MAAM,iCAAiC,SAAU,CAAC;AACzD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,6BAA6B,QAAsB,CAAC;AACjE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,+BAA+B,OAAQ,CAAC;AAIrD,MAAM,WAAW,+BAA+B;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,0DAA0D;IAC1D,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,4DAA4D;IAC5D,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,2EAA2E;IAC3E,cAAc,CAAC,EAAE,wBAAwB,CAAC;CAC3C;AAkPD,wBAAsB,cAAc,CAClC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IACJ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB,EACD,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,wBAAwB,CAAA;CAAO;;;;;;;;;;;;;;;GAoJ5D;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;;;;;;;;;;;;KAuBjF;AAED,wBAAsB,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;;;;;;;;;;;;UA4B7F;AAED,wBAAsB,YAAY,CAChC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,wBAAwB,CAAA;CAAO,oBAyB5D;AA2PD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE7D;AAwwBD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IACJ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,EACD,OAAO,GAAE;IACP,eAAe,CAAC,EAAE,sBAAsB,CAAC;IACzC,cAAc,CAAC,EAAE,wBAAwB,CAAC;IAC1C,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACxB;;;;;;;;;GAWP;AA6JD;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5G,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,sBAAsB,CAAA;CAAO;;;;;;;;;GAU3D;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE;IACJ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,EACD,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,sBAAsB,CAAA;CAAO;;;;;;;;;GAgE3D;AAED,wBAAsB,YAAY,CAChC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE;IACJ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,EACD,OAAO,GAAE;IACP,eAAe,CAAC,EAAE,sBAAsB,CAAC;IACzC,cAAc,CAAC,EAAE,wBAAwB,CAAC;IAC1C,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;yEACqE;IACrE,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACxB;;;;;;;;;GAqTP;AAglBD;;;;;;;;;GASG;AACH,wBAAsB,+BAA+B,CACnD,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAYlB;AAyVD,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,sBAAsB,EAChC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,MAAM,CAAC,CA6IjB;AAED,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,sBAAsB,EAChC,UAAU,EAAE,sBAAsB,EAClC,IAAI,GAAE;IAAE,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;CAAO,oBAyL5E;AAED,wBAAsB,gCAAgC,CACpD,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,sBAAsB,EAChC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,mBAiCf;AAED,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,EAAE,EACN,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE;IACJ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;;;;;;;;;;;;;;;;;;;;;;;;UA2DF;AAED,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,sBAAsB,EAChC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE;IACJ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,EACD,IAAI,CAAC,EAAE,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;UA6FhC;AAiKD,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,sBAAsB,EAChC,IAAI,GAAE,+BAA+B,GAAG,MAAM,GAAG,IAAS,mBAkD3D;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;UAcxG"}
@@ -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
- }, expectedTokenHash || expectedAgentId ? { requireAtomic: true } : undefined);
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 completeGuardedReleaseNodeInvocation(db, workspaceId, nodeId, providerName, invocation, data, deps) {
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
- // The conflict settlement comes first. In a sequential SQLite batch it
1680
- // closes the invocation before every mutation below if either the token
1681
- // generation or node binding changed; on transactional adapters the same
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
- const existingInput = recordInput(existing.input);
2736
- if (!data.error
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
  /**