@tangle-network/agent-runtime 3.0.32 → 3.0.35

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.
Files changed (64) hide show
  1. package/dist/{activation-CWOj5iZe.js → activation-B3vLJDlj.js} +2 -2
  2. package/dist/{activation-CWOj5iZe.js.map → activation-B3vLJDlj.js.map} +1 -1
  3. package/dist/{activation-DQhy-ET-.d.ts → activation-CCttbkSj.d.ts} +2 -2
  4. package/dist/agent.d.ts +1 -1
  5. package/dist/agent.js +3 -3
  6. package/dist/{coordination-manager-s1hbIqXx.js → coordination-manager-CZzhPx_F.js} +4 -4
  7. package/dist/{coordination-manager-s1hbIqXx.js.map → coordination-manager-CZzhPx_F.js.map} +1 -1
  8. package/dist/{delegate-ubXkOvcK.js → delegate-D0NpQF_z.js} +2 -2
  9. package/dist/{delegate-ubXkOvcK.js.map → delegate-D0NpQF_z.js.map} +1 -1
  10. package/dist/durable.d.ts +1 -1
  11. package/dist/durable.js +6 -6
  12. package/dist/{graph-BPqKAgZp.js → graph-BKMPvIk6.js} +5 -5
  13. package/dist/{graph-BPqKAgZp.js.map → graph-BKMPvIk6.js.map} +1 -1
  14. package/dist/{improve-CXK2GKbS.js → improve-YLCiNpX1.js} +6 -6
  15. package/dist/{improve-CXK2GKbS.js.map → improve-YLCiNpX1.js.map} +1 -1
  16. package/dist/index.d.ts +3 -3
  17. package/dist/index.js +8 -8
  18. package/dist/intelligence.d.ts +2 -2
  19. package/dist/intelligence.js +4 -4
  20. package/dist/kernel.d.ts +1 -1
  21. package/dist/kernel.js +11 -11
  22. package/dist/{loop-runner-CJxzdLr-.js → loop-runner-BmoENiTj.js} +2 -2
  23. package/dist/{loop-runner-CJxzdLr-.js.map → loop-runner-BmoENiTj.js.map} +1 -1
  24. package/dist/{loop-runner-D1JVNvwC.d.ts → loop-runner-CRZ3pF7w.d.ts} +2 -2
  25. package/dist/loop-runner-bin.d.ts +1 -1
  26. package/dist/loop-runner-bin.js +1 -1
  27. package/dist/mcp/bin.js +76 -3
  28. package/dist/mcp/bin.js.map +1 -1
  29. package/dist/mcp/index.d.ts +2 -2
  30. package/dist/mcp/index.js +5 -5
  31. package/dist/profiles.d.ts +1 -1
  32. package/dist/{provision-supervisor-B6-0_VQb.js → provision-supervisor-BqbXjSYT.js} +4 -4
  33. package/dist/{provision-supervisor-B6-0_VQb.js.map → provision-supervisor-BqbXjSYT.js.map} +1 -1
  34. package/dist/{run-cancellation-BRIB385R.js → run-cancellation-Cy8NtCtz.js} +2 -2
  35. package/dist/{run-cancellation-BRIB385R.js.map → run-cancellation-Cy8NtCtz.js.map} +1 -1
  36. package/dist/{runtime-LN0kcRwo.js → runtime-Cxlb_vie.js} +11 -11
  37. package/dist/{runtime-LN0kcRwo.js.map → runtime-Cxlb_vie.js.map} +1 -1
  38. package/dist/{scope-CCHfmCvY.js → scope-CBW-oIwP.js} +10 -2
  39. package/dist/scope-CBW-oIwP.js.map +1 -0
  40. package/dist/{search-executor-Cypg4sCQ.js → search-executor-A2dtsTlx.js} +3 -3
  41. package/dist/{search-executor-Cypg4sCQ.js.map → search-executor-A2dtsTlx.js.map} +1 -1
  42. package/dist/{server-CdP5hoHJ.js → server-DINjmAT0.js} +305 -4
  43. package/dist/server-DINjmAT0.js.map +1 -0
  44. package/dist/{structural-rollout-BS3hVAq2.js → structural-rollout-BBKSnDfB.js} +3 -3
  45. package/dist/{structural-rollout-BS3hVAq2.js.map → structural-rollout-BBKSnDfB.js.map} +1 -1
  46. package/dist/{supervise-CfuHhf-S.js → supervise-CeUM7jMe.js} +23 -47
  47. package/dist/supervise-CeUM7jMe.js.map +1 -0
  48. package/dist/{supervision-discovery-DcQU64rK.js → supervision-discovery-CvXb-yDc.js} +2 -2
  49. package/dist/{supervision-discovery-DcQU64rK.js.map → supervision-discovery-CvXb-yDc.js.map} +1 -1
  50. package/dist/{supervisor-C-mx3kR8.js → supervisor-B68cSh2T.js} +11 -2
  51. package/dist/supervisor-B68cSh2T.js.map +1 -0
  52. package/dist/testing.d.ts +1 -1
  53. package/dist/testing.js +11 -11
  54. package/dist/{top-web-l3naxnjo.js → top-web-C8TMsrZ6.js} +4 -4
  55. package/dist/{top-web-l3naxnjo.js.map → top-web-C8TMsrZ6.js.map} +1 -1
  56. package/dist/tui/bin.js +3 -3
  57. package/dist/tui/index.d.ts +1 -1
  58. package/dist/tui/index.js +2 -2
  59. package/dist/{types-ISwInoqb.d.ts → types-CQviVtZC.d.ts} +43 -2
  60. package/package.json +1 -1
  61. package/dist/scope-CCHfmCvY.js.map +0 -1
  62. package/dist/server-CdP5hoHJ.js.map +0 -1
  63. package/dist/supervise-CfuHhf-S.js.map +0 -1
  64. package/dist/supervisor-C-mx3kR8.js.map +0 -1
@@ -1,9 +1,10 @@
1
- import { In as buildLoopSpanNodes } from "./scope-CCHfmCvY.js";
1
+ import { In as buildLoopSpanNodes } from "./scope-CBW-oIwP.js";
2
2
  import { m as ValidationError, o as NotFoundError, t as AgentEvalError } from "./errors-AzSuGI23.js";
3
3
  import { X as fnv1a32Hex, Y as errorMessage } from "./workspace-streams-8ALHaZzx.js";
4
4
  import { n as createStdioToolServer } from "./tool-server-CZWd_Opp.js";
5
- import { n as delegate } from "./delegate-ubXkOvcK.js";
5
+ import { n as delegate } from "./delegate-D0NpQF_z.js";
6
6
  import { t as UI_LENSES } from "./substrate-Db2pp6y3.js";
7
+ import { randomUUID } from "node:crypto";
7
8
  import path, { dirname } from "node:path";
8
9
  import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
9
10
  import "node:stream";
@@ -1515,6 +1516,296 @@ function createDelegationStatusHandler(options) {
1515
1516
  return status;
1516
1517
  };
1517
1518
  }
1519
+ // src/mcp/tools/events.ts
1520
+ /**
1521
+ * `events_*` MCP tools — the runtime-owned piece of the agent-inbox event track (chatgpt-plugins
1522
+ * #18 / agent-runtime #1497): expose the NATIVE event journal (the durable `ObserverJournal`:
1523
+ * runtime hook events + decision points, digest-chained) via an explicit subscription lifecycle.
1524
+ * Boundaries, by design:
1525
+ * - No scheduler, no cron, no second schedule authority. Recurrence and wake-ups stay with the
1526
+ * native trigger owners; these tools only read and acknowledge what the journal already recorded.
1527
+ * - Delivery is at-least-once until acknowledged: `events_fetch` pages from the acknowledged
1528
+ * cursor, so a lost response is redelivered, and sequence numbers deduplicate on the client.
1529
+ * - Records are verified against the journal's digest chain on every page; a mutated, reordered
1530
+ * or deleted tail refuses the page instead of serving unverifiable history.
1531
+ * - Subscriptions are idempotent by caller key: a reconnect resubscribes to the SAME subscription
1532
+ * (same id, same cursor), never a duplicate stream.
1533
+ * - Optional expiry is lazy: an expired subscription reads as gone, and the caller resubscribes
1534
+ * with the same key to resume from its cursor.
1535
+ * @experimental
1536
+ */
1537
+ /** @experimental */
1538
+ var InMemoryEventSubscriptionStore = class {
1539
+ byId = /* @__PURE__ */ new Map();
1540
+ byKey = /* @__PURE__ */ new Map();
1541
+ async get(subscriptionId) {
1542
+ return this.byId.get(subscriptionId) ?? null;
1543
+ }
1544
+ async findByKey(key) {
1545
+ const id = this.byKey.get(key);
1546
+ return id ? this.byId.get(id) ?? null : null;
1547
+ }
1548
+ async put(subscription) {
1549
+ this.byId.set(subscription.subscriptionId, subscription);
1550
+ this.byKey.set(subscription.key, subscription.subscriptionId);
1551
+ }
1552
+ async delete(subscriptionId) {
1553
+ const existing = this.byId.get(subscriptionId);
1554
+ this.byId.delete(subscriptionId);
1555
+ if (existing && this.byKey.get(existing.key) === subscriptionId) this.byKey.delete(existing.key);
1556
+ }
1557
+ };
1558
+ const DEFAULT_TTL_SECONDS = 86400;
1559
+ const MAX_PAGE_LIMIT = 200;
1560
+ function isMcpEventRecord(value) {
1561
+ if (value === null || typeof value !== "object") return false;
1562
+ const record = value;
1563
+ return Number.isSafeInteger(record.sequence) && record.sequence >= 0 && typeof record.pursuitId === "string" && (record.kind === "event" || record.kind === "decision") && Number.isFinite(record.observedAt) && typeof record.digest === "string" && (record.previousDigest === void 0 || typeof record.previousDigest === "string");
1564
+ }
1565
+ /** The read model: journal order, digest-chain linked. The durable journal
1566
+ * verifies record digests on read; this linkage check is the second fence that
1567
+ * refuses a page carved from reordered or spliced history. */
1568
+ async function verifiedPage(source, after, limit, kinds) {
1569
+ const all = (await source.read()).filter(isMcpEventRecord).sort((a, b) => a.sequence - b.sequence);
1570
+ const page = [];
1571
+ for (let index = 0; index < all.length; index += 1) {
1572
+ const record = all[index];
1573
+ if (!record) continue;
1574
+ const previous = index > 0 ? all[index - 1] : void 0;
1575
+ if (previous && record.previousDigest !== previous.digest) throw new ValidationError("events: journal chain verification failed; refusing to serve unverifiable history");
1576
+ if (record.sequence > after && kinds.includes(record.kind) && page.length < limit) page.push(record);
1577
+ }
1578
+ const last = all[all.length - 1];
1579
+ return {
1580
+ records: page,
1581
+ highWatermark: last ? last.sequence : 0
1582
+ };
1583
+ }
1584
+ async function currentHighWatermark(source) {
1585
+ return (await verifiedPage(source, 0, 0, ["event", "decision"])).highWatermark;
1586
+ }
1587
+ function parseKinds(raw) {
1588
+ if (raw === void 0) return void 0;
1589
+ if (!Array.isArray(raw) || raw.length === 0 || !raw.every((kind) => kind === "event" || kind === "decision")) throw new ValidationError("events: `kinds` must be a non-empty array of \"event\" or \"decision\"");
1590
+ return raw;
1591
+ }
1592
+ function expired(subscription, nowMs) {
1593
+ return subscription.expiresAt !== null && subscription.expiresAt <= nowMs;
1594
+ }
1595
+ async function liveSubscription(store, subscriptionId, nowMs) {
1596
+ const subscription = await store.get(subscriptionId);
1597
+ if (!subscription || expired(subscription, nowMs)) throw new ValidationError(`events: unknown or expired subscription "${subscriptionId}"; resubscribe with the same key to resume from its cursor`);
1598
+ return subscription;
1599
+ }
1600
+ /** Build the four `events_*` tool descriptors. Register them only when an event source is wired. @experimental */
1601
+ function createEventsTools(options) {
1602
+ const source = options.eventSource;
1603
+ const store = options.subscriptionStore ?? new InMemoryEventSubscriptionStore();
1604
+ const now = options.now ?? Date.now;
1605
+ async function subscribe(raw) {
1606
+ if (raw === null || typeof raw !== "object") throw new ValidationError("events_subscribe: arguments must be an object");
1607
+ const value = raw;
1608
+ if (typeof value.key !== "string" || value.key.trim().length === 0 || value.key.length > 256) throw new ValidationError("events_subscribe: `key` must be a non-empty string (max 256 chars)");
1609
+ const key = value.key.trim();
1610
+ const kinds = parseKinds(value.kinds) ?? ["event", "decision"];
1611
+ const rawFrom = value.fromSequence;
1612
+ if (rawFrom !== void 0 && (typeof rawFrom !== "number" || !Number.isSafeInteger(rawFrom) || rawFrom < 0)) throw new ValidationError("events_subscribe: `fromSequence` must be a non-negative integer");
1613
+ const fromSequence = rawFrom;
1614
+ const rawTtl = value.ttlSeconds;
1615
+ if (rawTtl !== void 0 && (typeof rawTtl !== "number" || !Number.isSafeInteger(rawTtl) || rawTtl <= 0 || rawTtl > 2592e3)) throw new ValidationError("events_subscribe: `ttlSeconds` must be an integer in (0, 2592000]");
1616
+ const ttlSeconds = rawTtl ?? DEFAULT_TTL_SECONDS;
1617
+ const existing = await store.findByKey(key);
1618
+ if (existing && !expired(existing, now())) {
1619
+ const renewed = {
1620
+ ...existing,
1621
+ expiresAt: now() + ttlSeconds * 1e3
1622
+ };
1623
+ await store.put(renewed);
1624
+ return {
1625
+ subscriptionId: renewed.subscriptionId,
1626
+ key,
1627
+ cursor: renewed.cursor,
1628
+ kinds: [...renewed.kinds],
1629
+ expiresAt: renewed.expiresAt
1630
+ };
1631
+ }
1632
+ const resumedCursor = existing ? existing.cursor : void 0;
1633
+ if (existing) await store.delete(existing.subscriptionId);
1634
+ const cursor = fromSequence !== void 0 ? fromSequence : resumedCursor ?? await currentHighWatermark(source);
1635
+ const subscription = {
1636
+ subscriptionId: randomUUID(),
1637
+ key,
1638
+ kinds,
1639
+ cursor,
1640
+ createdAt: now(),
1641
+ expiresAt: now() + ttlSeconds * 1e3
1642
+ };
1643
+ await store.put(subscription);
1644
+ return {
1645
+ subscriptionId: subscription.subscriptionId,
1646
+ key,
1647
+ cursor,
1648
+ kinds: [...kinds],
1649
+ expiresAt: subscription.expiresAt
1650
+ };
1651
+ }
1652
+ async function fetch(raw) {
1653
+ if (raw === null || typeof raw !== "object") throw new ValidationError("events_fetch: arguments must be an object");
1654
+ const value = raw;
1655
+ if (typeof value.subscriptionId !== "string" || value.subscriptionId.length === 0) throw new ValidationError("events_fetch: `subscriptionId` must be a non-empty string");
1656
+ const rawLimit = value.limit;
1657
+ if (rawLimit !== void 0 && (typeof rawLimit !== "number" || !Number.isSafeInteger(rawLimit) || rawLimit <= 0 || rawLimit > MAX_PAGE_LIMIT)) throw new ValidationError(`events_fetch: \`limit\` must be an integer in (0, ${MAX_PAGE_LIMIT}]`);
1658
+ const limit = rawLimit ?? MAX_PAGE_LIMIT;
1659
+ const subscription = await liveSubscription(store, value.subscriptionId, now());
1660
+ const page = await verifiedPage(source, subscription.cursor, limit, subscription.kinds);
1661
+ return {
1662
+ subscriptionId: subscription.subscriptionId,
1663
+ cursor: subscription.cursor,
1664
+ records: page.records.map((record) => ({
1665
+ sequence: record.sequence,
1666
+ pursuitId: record.pursuitId,
1667
+ kind: record.kind,
1668
+ observedAt: record.observedAt,
1669
+ digest: record.digest,
1670
+ payload: record.payload
1671
+ })),
1672
+ highWatermark: page.highWatermark
1673
+ };
1674
+ }
1675
+ async function acknowledge(raw) {
1676
+ if (raw === null || typeof raw !== "object") throw new ValidationError("events_ack: arguments must be an object");
1677
+ const value = raw;
1678
+ if (typeof value.subscriptionId !== "string" || value.subscriptionId.length === 0) throw new ValidationError("events_ack: `subscriptionId` must be a non-empty string");
1679
+ if (typeof value.sequence !== "number" || !Number.isSafeInteger(value.sequence) || value.sequence < 0) throw new ValidationError("events_ack: `sequence` must be a non-negative integer");
1680
+ const subscription = await liveSubscription(store, value.subscriptionId, now());
1681
+ const highWatermark = await currentHighWatermark(source);
1682
+ if (value.sequence > highWatermark) throw new ValidationError(`events_ack: \`sequence\` ${value.sequence} is beyond the journal high-watermark ${highWatermark}; acknowledge only delivered records`);
1683
+ if (value.sequence > subscription.cursor) subscription.cursor = value.sequence;
1684
+ await store.put(subscription);
1685
+ return {
1686
+ subscriptionId: subscription.subscriptionId,
1687
+ cursor: subscription.cursor
1688
+ };
1689
+ }
1690
+ async function unsubscribe(raw) {
1691
+ if (raw === null || typeof raw !== "object") throw new ValidationError("events_unsubscribe: arguments must be an object");
1692
+ const value = raw;
1693
+ if (typeof value.subscriptionId !== "string" || value.subscriptionId.length === 0) throw new ValidationError("events_unsubscribe: `subscriptionId` must be a non-empty string");
1694
+ if (!await store.get(value.subscriptionId)) return {
1695
+ subscriptionId: value.subscriptionId,
1696
+ removed: false
1697
+ };
1698
+ await store.delete(value.subscriptionId);
1699
+ return {
1700
+ subscriptionId: value.subscriptionId,
1701
+ removed: true
1702
+ };
1703
+ }
1704
+ return {
1705
+ subscribeTool: {
1706
+ name: "events_subscribe",
1707
+ description: [
1708
+ "Subscribe to the native runtime event journal (task events and decision points).",
1709
+ "Idempotent by `key`: reconnecting with the same key resumes the same",
1710
+ "subscription and its acknowledged cursor — never a duplicate stream.",
1711
+ "Default cursor is the current high-watermark (only new records); pass",
1712
+ "`fromSequence` to replay history. Optional `kinds` filter and `ttlSeconds`",
1713
+ "expiry. This is a read surface over recorded history: it schedules nothing",
1714
+ "and triggers nothing; recurrence and wake-ups stay with their native owners."
1715
+ ].join("\n"),
1716
+ inputSchema: EVENTS_SUBSCRIBE_INPUT_SCHEMA,
1717
+ handler: subscribe
1718
+ },
1719
+ fetchTool: {
1720
+ name: "events_fetch",
1721
+ description: [
1722
+ "Fetch one page of journaled records after the acknowledged cursor.",
1723
+ "At-least-once: records are redelivered until `events_ack` advances the",
1724
+ "cursor; deduplicate by `sequence`. Every page is verified against the",
1725
+ "journal digest chain. An expired or unknown subscription errors: resubscribe",
1726
+ "with the same key to resume from its cursor."
1727
+ ].join("\n"),
1728
+ inputSchema: EVENTS_FETCH_INPUT_SCHEMA,
1729
+ handler: fetch
1730
+ },
1731
+ ackTool: {
1732
+ name: "events_ack",
1733
+ description: "Acknowledge records up to `sequence` (forward-only). Unacknowledged records are redelivered.",
1734
+ inputSchema: EVENTS_ACK_INPUT_SCHEMA,
1735
+ handler: acknowledge
1736
+ },
1737
+ unsubscribeTool: {
1738
+ name: "events_unsubscribe",
1739
+ description: "Remove a subscription. Idempotent; the journal itself is unaffected.",
1740
+ inputSchema: EVENTS_UNSUBSCRIBE_INPUT_SCHEMA,
1741
+ handler: unsubscribe
1742
+ }
1743
+ };
1744
+ }
1745
+ const EVENTS_SUBSCRIBE_INPUT_SCHEMA = {
1746
+ type: "object",
1747
+ properties: {
1748
+ key: {
1749
+ type: "string",
1750
+ description: "Caller-chosen idempotency key; one consumer key resumes one stream."
1751
+ },
1752
+ kinds: {
1753
+ type: "array",
1754
+ items: { enum: ["event", "decision"] },
1755
+ description: "Optional kind filter."
1756
+ },
1757
+ fromSequence: {
1758
+ type: "integer",
1759
+ description: "Inclusive replay start; default: current high-watermark."
1760
+ },
1761
+ ttlSeconds: {
1762
+ type: "integer",
1763
+ description: "Subscription expiry in seconds; default 86400."
1764
+ }
1765
+ },
1766
+ required: ["key"],
1767
+ additionalProperties: false
1768
+ };
1769
+ const EVENTS_FETCH_INPUT_SCHEMA = {
1770
+ type: "object",
1771
+ properties: {
1772
+ subscriptionId: { type: "string" },
1773
+ limit: {
1774
+ type: "integer",
1775
+ description: `Max records per page (max ${MAX_PAGE_LIMIT}).`
1776
+ }
1777
+ },
1778
+ required: ["subscriptionId"],
1779
+ additionalProperties: false
1780
+ };
1781
+ const EVENTS_ACK_INPUT_SCHEMA = {
1782
+ type: "object",
1783
+ properties: {
1784
+ subscriptionId: { type: "string" },
1785
+ sequence: { type: "integer" }
1786
+ },
1787
+ required: ["subscriptionId", "sequence"],
1788
+ additionalProperties: false
1789
+ };
1790
+ const EVENTS_UNSUBSCRIBE_INPUT_SCHEMA = {
1791
+ type: "object",
1792
+ properties: { subscriptionId: { type: "string" } },
1793
+ required: ["subscriptionId"],
1794
+ additionalProperties: false
1795
+ };
1796
+ function observerJournalEventSource(journal) {
1797
+ return { async read() {
1798
+ return (await journal.read()).map((record) => ({
1799
+ sequence: record.sequence,
1800
+ pursuitId: record.pursuitId,
1801
+ kind: record.kind,
1802
+ observedAt: record.observedAt,
1803
+ digest: record.digest,
1804
+ ...record.previousDigest !== void 0 ? { previousDigest: record.previousDigest } : {},
1805
+ payload: record.event ?? record.decision ?? null
1806
+ }));
1807
+ } };
1808
+ }
1518
1809
  // src/mcp/server.ts
1519
1810
  const DEFAULT_SERVER_NAME = "agent-runtime-mcp";
1520
1811
  const DEFAULT_SERVER_VERSION = "0.22.0";
@@ -1559,6 +1850,16 @@ function createMcpServer(options = {}) {
1559
1850
  inputSchema: DELEGATION_STATUS_INPUT_SCHEMA,
1560
1851
  handler: createDelegationStatusHandler({ queue })
1561
1852
  });
1853
+ if (options.eventSource) {
1854
+ const events = createEventsTools({
1855
+ eventSource: options.eventSource,
1856
+ ...options.eventSubscriptionStore !== void 0 ? { subscriptionStore: options.eventSubscriptionStore } : {}
1857
+ });
1858
+ tools.set(events.subscribeTool.name, events.subscribeTool);
1859
+ tools.set(events.fetchTool.name, events.fetchTool);
1860
+ tools.set(events.ackTool.name, events.ackTool);
1861
+ tools.set(events.unsubscribeTool.name, events.unsubscribeTool);
1862
+ }
1562
1863
  tools.set(DELEGATION_HISTORY_TOOL_NAME, {
1563
1864
  name: DELEGATION_HISTORY_TOOL_NAME,
1564
1865
  description: DELEGATION_HISTORY_DESCRIPTION,
@@ -1583,6 +1884,6 @@ function createMcpServer(options = {}) {
1583
1884
  stop: stdio.stop
1584
1885
  };
1585
1886
  }
1586
- export { composeLoopTraceEmitters as a, FileDelegationStore as i, createDelegateHandler as n, DelegationTaskQueue as r, createMcpServer as t };
1887
+ export { FileDelegationStore as a, DelegationTaskQueue as i, observerJournalEventSource as n, composeLoopTraceEmitters as o, createDelegateHandler as r, createMcpServer as t };
1587
1888
 
1588
- //# sourceMappingURL=server-CdP5hoHJ.js.map
1889
+ //# sourceMappingURL=server-DINjmAT0.js.map