@hotmeshio/long-tail 0.25.4 → 0.26.0

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 (139) hide show
  1. package/README.md +1 -0
  2. package/build/index.d.ts +1 -0
  3. package/build/index.js +8 -1
  4. package/build/lib/machines/index.d.ts +5 -0
  5. package/build/lib/machines/index.js +21 -0
  6. package/build/lib/machines/line.d.ts +44 -0
  7. package/build/lib/machines/line.js +114 -0
  8. package/build/lib/machines/protocol/codec.d.ts +92 -0
  9. package/build/lib/machines/protocol/codec.js +79 -0
  10. package/build/lib/machines/protocol/constants.d.ts +120 -0
  11. package/build/lib/machines/protocol/constants.js +97 -0
  12. package/build/lib/machines/protocol/contract.d.ts +19 -0
  13. package/build/lib/machines/protocol/contract.js +132 -0
  14. package/build/lib/machines/protocol/envelope.d.ts +14 -0
  15. package/build/lib/machines/protocol/envelope.js +43 -0
  16. package/build/lib/machines/protocol/index.d.ts +5 -0
  17. package/build/lib/machines/protocol/index.js +21 -0
  18. package/build/lib/machines/protocol/topics.d.ts +33 -0
  19. package/build/lib/machines/protocol/topics.js +79 -0
  20. package/build/lib/machines/site/mosquitto-conf.d.ts +27 -0
  21. package/build/lib/machines/site/mosquitto-conf.js +81 -0
  22. package/build/lib/machines/site/site-conf.d.ts +20 -0
  23. package/build/lib/machines/site/site-conf.js +55 -0
  24. package/build/lib/machines/transport/callback-feed.d.ts +18 -0
  25. package/build/lib/machines/transport/callback-feed.js +31 -0
  26. package/build/lib/machines/transport/delivery.d.ts +21 -0
  27. package/build/lib/machines/transport/delivery.js +42 -0
  28. package/build/lib/machines/transport/index.d.ts +11 -0
  29. package/build/lib/machines/transport/index.js +27 -0
  30. package/build/lib/machines/transport/memory-broker.d.ts +35 -0
  31. package/build/lib/machines/transport/memory-broker.js +145 -0
  32. package/build/lib/machines/transport/memory.d.ts +40 -0
  33. package/build/lib/machines/transport/memory.js +79 -0
  34. package/build/lib/machines/transport/mqtt-bus.d.ts +24 -0
  35. package/build/lib/machines/transport/mqtt-bus.js +43 -0
  36. package/build/lib/machines/transport/mqtt-link.d.ts +16 -0
  37. package/build/lib/machines/transport/mqtt-link.js +37 -0
  38. package/build/lib/machines/transport/mqtt-session.d.ts +34 -0
  39. package/build/lib/machines/transport/mqtt-session.js +127 -0
  40. package/build/lib/machines/transport/nats-bus.d.ts +42 -0
  41. package/build/lib/machines/transport/nats-bus.js +67 -0
  42. package/build/lib/machines/transport/nats-durable.d.ts +11 -0
  43. package/build/lib/machines/transport/nats-durable.js +28 -0
  44. package/build/lib/machines/transport/nats-feed.d.ts +26 -0
  45. package/build/lib/machines/transport/nats-feed.js +49 -0
  46. package/build/lib/machines/transport/serial.d.ts +21 -0
  47. package/build/lib/machines/transport/serial.js +54 -0
  48. package/build/lib/machines/transport/streams.d.ts +28 -0
  49. package/build/lib/machines/transport/streams.js +92 -0
  50. package/build/scripts/machine-line.d.ts +33 -0
  51. package/build/scripts/machine-line.js +301 -0
  52. package/build/services/machines/commands.d.ts +29 -0
  53. package/build/services/machines/commands.js +37 -0
  54. package/build/services/machines/config.d.ts +43 -0
  55. package/build/services/machines/config.js +84 -0
  56. package/build/services/machines/contracts.d.ts +193 -0
  57. package/build/services/machines/contracts.js +115 -0
  58. package/build/services/machines/forms.d.ts +55 -0
  59. package/build/services/machines/forms.js +37 -0
  60. package/build/services/machines/gateway/actions.d.ts +111 -0
  61. package/build/services/machines/gateway/actions.js +8 -0
  62. package/build/services/machines/gateway/address-book.d.ts +16 -0
  63. package/build/services/machines/gateway/address-book.js +24 -0
  64. package/build/services/machines/gateway/admission.d.ts +35 -0
  65. package/build/services/machines/gateway/admission.js +66 -0
  66. package/build/services/machines/gateway/api-escalations.d.ts +23 -0
  67. package/build/services/machines/gateway/api-escalations.js +101 -0
  68. package/build/services/machines/gateway/dispatcher.d.ts +63 -0
  69. package/build/services/machines/gateway/dispatcher.js +157 -0
  70. package/build/services/machines/gateway/escalations.d.ts +51 -0
  71. package/build/services/machines/gateway/escalations.js +40 -0
  72. package/build/services/machines/gateway/executor.d.ts +55 -0
  73. package/build/services/machines/gateway/executor.js +195 -0
  74. package/build/services/machines/gateway/gateway.d.ts +82 -0
  75. package/build/services/machines/gateway/gateway.js +247 -0
  76. package/build/services/machines/gateway/index.d.ts +10 -0
  77. package/build/services/machines/gateway/index.js +26 -0
  78. package/build/services/machines/gateway/jobs.d.ts +16 -0
  79. package/build/services/machines/gateway/jobs.js +24 -0
  80. package/build/services/machines/gateway/log.d.ts +41 -0
  81. package/build/services/machines/gateway/log.js +42 -0
  82. package/build/services/machines/gateway/lt-http.d.ts +51 -0
  83. package/build/services/machines/gateway/lt-http.js +120 -0
  84. package/build/services/machines/gateway/pacing.d.ts +29 -0
  85. package/build/services/machines/gateway/pacing.js +134 -0
  86. package/build/services/machines/gateway/plan-escalation.d.ts +19 -0
  87. package/build/services/machines/gateway/plan-escalation.js +201 -0
  88. package/build/services/machines/gateway/plan-machine.d.ts +16 -0
  89. package/build/services/machines/gateway/plan-machine.js +242 -0
  90. package/build/services/machines/gateway/plan-shared.d.ts +18 -0
  91. package/build/services/machines/gateway/plan-shared.js +36 -0
  92. package/build/services/machines/gateway/provision.d.ts +22 -0
  93. package/build/services/machines/gateway/provision.js +79 -0
  94. package/build/services/machines/gateway/receipts.d.ts +33 -0
  95. package/build/services/machines/gateway/receipts.js +65 -0
  96. package/build/services/machines/gateway/reconcile.d.ts +33 -0
  97. package/build/services/machines/gateway/reconcile.js +86 -0
  98. package/build/services/machines/gateway/registration.d.ts +38 -0
  99. package/build/services/machines/gateway/registration.js +121 -0
  100. package/build/services/machines/gateway/reply-waiter.d.ts +24 -0
  101. package/build/services/machines/gateway/reply-waiter.js +65 -0
  102. package/build/services/machines/gateway/state.d.ts +125 -0
  103. package/build/services/machines/gateway/state.js +228 -0
  104. package/build/services/machines/gateway/trace.d.ts +16 -0
  105. package/build/services/machines/gateway/trace.js +43 -0
  106. package/build/services/machines/identities.d.ts +25 -0
  107. package/build/services/machines/identities.js +77 -0
  108. package/build/services/machines/index.d.ts +11 -0
  109. package/build/services/machines/index.js +27 -0
  110. package/build/services/machines/leadership.d.ts +22 -0
  111. package/build/services/machines/leadership.js +75 -0
  112. package/build/services/machines/roles.d.ts +13 -0
  113. package/build/services/machines/roles.js +62 -0
  114. package/build/services/machines/rows.d.ts +30 -0
  115. package/build/services/machines/rows.js +56 -0
  116. package/build/services/machines/select.d.ts +18 -0
  117. package/build/services/machines/select.js +63 -0
  118. package/build/services/machines/surface.d.ts +33 -0
  119. package/build/services/machines/surface.js +98 -0
  120. package/build/services/machines/testing/fake-long-tail.d.ts +78 -0
  121. package/build/services/machines/testing/fake-long-tail.js +155 -0
  122. package/build/services/machines/testing/index.d.ts +3 -0
  123. package/build/services/machines/testing/index.js +19 -0
  124. package/build/services/machines/testing/recording-log.d.ts +14 -0
  125. package/build/services/machines/testing/recording-log.js +22 -0
  126. package/build/services/machines/testing/wait.d.ts +3 -0
  127. package/build/services/machines/testing/wait.js +17 -0
  128. package/build/services/mcp/db-server/schemas.d.ts +2 -2
  129. package/build/start/index.js +13 -0
  130. package/build/system/mcp-servers/admin/schemas.d.ts +221 -221
  131. package/build/system/mcp-servers/db-query/schemas.d.ts +2 -2
  132. package/build/system/mcp-servers/human-queue-schemas.d.ts +6 -6
  133. package/build/tsconfig.tsbuildinfo +1 -1
  134. package/build/types/index.d.ts +2 -1
  135. package/build/types/machines.d.ts +166 -0
  136. package/build/types/machines.js +7 -0
  137. package/build/types/startup.d.ts +23 -0
  138. package/docs/machines.md +293 -0
  139. package/package.json +11 -1
@@ -0,0 +1,78 @@
1
+ /**
2
+ * An in-memory Long Tail for the machine gateway: escalation rows with the
3
+ * claim / accumulate / resolve / create verbs, each publishing the lifecycle
4
+ * event Long Tail publishes, plus helpers that play the unit workflow and the
5
+ * people (exit, operator).
6
+ */
7
+ import { type Actor, type CreateRowInput } from '../gateway/actions';
8
+ import { type LineEscalations, type RowItem, type VerbResult } from '../gateway/escalations';
9
+ import { type HandoffFacets } from '../contracts';
10
+ import type { MemoryEscalationFeed } from '../../../lib/machines/transport';
11
+ import type { OpenRowQuery } from '../rows';
12
+ export interface FakeRow {
13
+ id: string;
14
+ type: string;
15
+ subtype?: string;
16
+ role: string;
17
+ status: 'pending' | 'resolved' | 'cancelled' | 'expired';
18
+ assigned_to?: string;
19
+ metadata: Record<string, any>;
20
+ items: {
21
+ itemKey: string;
22
+ payload: any;
23
+ actor: Actor;
24
+ }[];
25
+ resolver_payload?: Record<string, any>;
26
+ resolved_by?: string;
27
+ envelope?: string;
28
+ escalation_payload?: string;
29
+ }
30
+ export interface Call {
31
+ verb: string;
32
+ as: Actor;
33
+ id: string;
34
+ payload?: any;
35
+ }
36
+ export declare class FakeLongTail implements LineEscalations {
37
+ private readonly feed;
38
+ readonly rows: Map<string, FakeRow>;
39
+ readonly calls: Call[];
40
+ private seq;
41
+ private failing;
42
+ /** The next `times` calls of `verb` fail as a Long Tail outage would (5xx). */
43
+ failNext(verb: 'claim' | 'accumulate' | 'resolve' | 'create', times?: number): void;
44
+ /** Roles each actor holds; an actor outside a row's role gets not found, as Long Tail's RBAC answers. */
45
+ readonly holds: Map<string, Set<string>>;
46
+ private hidden;
47
+ private outage;
48
+ constructor(feed: MemoryEscalationFeed);
49
+ private emit;
50
+ private add;
51
+ /** What the unit workflow's conditionalAccumulator does: park a handoff row. */
52
+ park(role: string, facets: HandoffFacets): FakeRow;
53
+ /** Park any row, as a host workflow parks its own. */
54
+ parkRow(input: {
55
+ type: string;
56
+ role: string;
57
+ subtype?: string;
58
+ metadata: Record<string, any>;
59
+ }): FakeRow;
60
+ /** A person resolving a row on the dashboard. */
61
+ personResolves(id: string, payload: Record<string, any>, person?: string): void;
62
+ /** A person or the workflow cancelling the row. */
63
+ cancel(id: string): void;
64
+ /** The row's timeout firing (conditional `timeout`). */
65
+ expire(id: string): void;
66
+ claim(as: Actor, id: string): Promise<VerbResult>;
67
+ accumulate(as: Actor, id: string, itemKey: string, payload: Record<string, any>, metadata?: Record<string, any>): Promise<VerbResult>;
68
+ resolve(as: Actor, id: string, payload: Record<string, any>): Promise<VerbResult>;
69
+ create(_as: Actor, input: CreateRowInput): Promise<{
70
+ id: string;
71
+ }>;
72
+ itemKeys(id: string): Promise<string[]>;
73
+ items(id: string): Promise<RowItem[]>;
74
+ get(id: string): Promise<Record<string, any> | null>;
75
+ listOpen(query: OpenRowQuery): Promise<Record<string, any>[]>;
76
+ ofType(type: string): FakeRow[];
77
+ ended(id: string, ms?: number): Promise<FakeRow>;
78
+ }
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ /**
3
+ * An in-memory Long Tail for the machine gateway: escalation rows with the
4
+ * claim / accumulate / resolve / create verbs, each publishing the lifecycle
5
+ * event Long Tail publishes, plus helpers that play the unit workflow and the
6
+ * people (exit, operator).
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.FakeLongTail = void 0;
10
+ const actions_1 = require("../gateway/actions");
11
+ const escalations_1 = require("../gateway/escalations");
12
+ const contracts_1 = require("../contracts");
13
+ const wait_1 = require("./wait");
14
+ class FakeLongTail {
15
+ /** The next `times` calls of `verb` fail as a Long Tail outage would (5xx). */
16
+ failNext(verb, times = 1) {
17
+ this.failing.set(verb, times);
18
+ }
19
+ hidden(as, row) {
20
+ const roles = this.holds.get(as);
21
+ return !!row && !!roles && !roles.has(row.role);
22
+ }
23
+ outage(verb) {
24
+ const left = this.failing.get(verb) ?? 0;
25
+ if (left <= 0)
26
+ return;
27
+ this.failing.set(verb, left - 1);
28
+ throw new Error(`Long Tail unavailable (${verb})`);
29
+ }
30
+ constructor(feed) {
31
+ this.feed = feed;
32
+ this.rows = new Map();
33
+ this.calls = [];
34
+ this.seq = 0;
35
+ this.failing = new Map();
36
+ /** Roles each actor holds; an actor outside a row's role gets not found, as Long Tail's RBAC answers. */
37
+ this.holds = new Map();
38
+ }
39
+ emit(row, verb, extra = {}) {
40
+ this.feed.emit({
41
+ type: `system.escalation.${row.role}.${row.id}.${verb}`, escalationId: row.id, role: row.role,
42
+ data: { id: row.id, type: row.type, subtype: row.subtype, role: row.role, status: row.status, assigned_to: row.assigned_to, metadata: row.metadata, ...extra },
43
+ });
44
+ }
45
+ add(input) {
46
+ const row = { ...input, id: `e${++this.seq}`, status: 'pending', items: [] };
47
+ this.rows.set(row.id, row);
48
+ this.emit(row, 'created');
49
+ return row;
50
+ }
51
+ /** What the unit workflow's conditionalAccumulator does: park a handoff row. */
52
+ park(role, facets) {
53
+ return this.add({ type: contracts_1.ROW_TYPE.HANDOFF, role, metadata: { ...facets } });
54
+ }
55
+ /** Park any row, as a host workflow parks its own. */
56
+ parkRow(input) {
57
+ return this.add({ ...input, metadata: { ...input.metadata } });
58
+ }
59
+ /** A person resolving a row on the dashboard. */
60
+ personResolves(id, payload, person = 'person-1') {
61
+ const row = this.rows.get(id);
62
+ row.status = 'resolved';
63
+ row.resolver_payload = payload;
64
+ row.resolved_by = person;
65
+ this.emit(row, 'resolved', { resolved_by: person });
66
+ }
67
+ /** A person or the workflow cancelling the row. */
68
+ cancel(id) {
69
+ const row = this.rows.get(id);
70
+ row.status = 'cancelled';
71
+ this.emit(row, 'cancelled');
72
+ }
73
+ /** The row's timeout firing (conditional `timeout`). */
74
+ expire(id) {
75
+ const row = this.rows.get(id);
76
+ row.status = 'expired';
77
+ this.emit(row, 'expired');
78
+ }
79
+ async claim(as, id) {
80
+ this.outage('claim');
81
+ this.calls.push({ verb: 'claim', as, id });
82
+ const row = this.rows.get(id);
83
+ if (!row || row.status !== 'pending')
84
+ return { outcome: escalations_1.VERB_OUTCOME.ALREADY };
85
+ row.assigned_to = as;
86
+ this.emit(row, 'claimed');
87
+ return { outcome: escalations_1.VERB_OUTCOME.DONE };
88
+ }
89
+ async accumulate(as, id, itemKey, payload, metadata) {
90
+ this.outage('accumulate');
91
+ this.calls.push({ verb: 'accumulate', as, id, payload: { itemKey, ...payload } });
92
+ const row = this.rows.get(id);
93
+ if (this.hidden(as, row))
94
+ return { outcome: escalations_1.VERB_OUTCOME.ALREADY, status: 404 };
95
+ if (!row || row.status !== 'pending')
96
+ return { outcome: escalations_1.VERB_OUTCOME.ALREADY };
97
+ if (row.items.some((i) => i.itemKey === itemKey))
98
+ return { outcome: escalations_1.VERB_OUTCOME.ALREADY };
99
+ row.items.push({ itemKey, payload, actor: as });
100
+ if (metadata)
101
+ row.metadata = { ...row.metadata, ...metadata };
102
+ return { outcome: escalations_1.VERB_OUTCOME.DONE, itemKeys: row.items.map((i) => i.itemKey) };
103
+ }
104
+ async resolve(as, id, payload) {
105
+ this.outage('resolve');
106
+ this.calls.push({ verb: 'resolve', as, id, payload });
107
+ const row = this.rows.get(id);
108
+ if (!row || row.status !== 'pending')
109
+ return { outcome: escalations_1.VERB_OUTCOME.ALREADY };
110
+ // Long Tail refuses a resolve by id while someone else holds a live claim (409).
111
+ if (row.assigned_to && row.assigned_to !== as)
112
+ return { outcome: escalations_1.VERB_OUTCOME.ALREADY, detail: 'claimed by another' };
113
+ row.status = 'resolved';
114
+ row.resolver_payload = payload;
115
+ row.resolved_by = as;
116
+ this.emit(row, 'resolved', { resolved_by: as });
117
+ return { outcome: escalations_1.VERB_OUTCOME.DONE };
118
+ }
119
+ async create(_as, input) {
120
+ this.outage('create');
121
+ return { id: this.add({ ...input }).id };
122
+ }
123
+ async itemKeys(id) {
124
+ return (this.rows.get(id)?.items ?? []).map((i) => i.itemKey);
125
+ }
126
+ async items(id) {
127
+ return (this.rows.get(id)?.items ?? []).map((i) => ({ itemKey: i.itemKey, payload: i.payload }));
128
+ }
129
+ async get(id) {
130
+ const row = this.rows.get(id);
131
+ if (!row || this.hidden(actions_1.CONTROLLER, row))
132
+ return null;
133
+ return {
134
+ id: row.id, type: row.type, subtype: row.subtype, role: row.role, status: row.status,
135
+ assigned_to: row.assigned_to ?? null, resolved_by: row.resolved_by ?? null, metadata: { ...row.metadata },
136
+ // Stored serialized, as Long Tail returns it.
137
+ resolver_payload: row.resolver_payload ? JSON.stringify(row.resolver_payload) : null,
138
+ };
139
+ }
140
+ async listOpen(query) {
141
+ return [...this.rows.values()]
142
+ .filter((r) => r.status === 'pending' && (!query.type || r.type === query.type) && (!query.role || r.role === query.role))
143
+ .map((r) => ({ id: r.id, type: r.type, subtype: r.subtype, role: r.role, status: r.status, assigned_to: r.assigned_to ?? null, metadata: r.metadata }));
144
+ }
145
+ ofType(type) {
146
+ return [...this.rows.values()].filter((r) => r.type === type);
147
+ }
148
+ ended(id, ms = 1_000) {
149
+ return (0, wait_1.until)(() => {
150
+ const row = this.rows.get(id);
151
+ return row && row.status !== 'pending' ? row : undefined;
152
+ }, ms);
153
+ }
154
+ }
155
+ exports.FakeLongTail = FakeLongTail;
@@ -0,0 +1,3 @@
1
+ export * from './fake-long-tail';
2
+ export * from './wait';
3
+ export * from './recording-log';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./fake-long-tail"), exports);
18
+ __exportStar(require("./wait"), exports);
19
+ __exportStar(require("./recording-log"), exports);
@@ -0,0 +1,14 @@
1
+ import type { GatewayLog, GatewayLogEvent } from '../gateway/log';
2
+ export interface LogEntry {
3
+ level: 'info' | 'warn' | 'error';
4
+ event: GatewayLogEvent;
5
+ context: Record<string, unknown>;
6
+ }
7
+ /** A gateway log that keeps every entry, for assertions. */
8
+ export declare class RecordingLog implements GatewayLog {
9
+ readonly entries: LogEntry[];
10
+ info(event: GatewayLogEvent, context?: Record<string, unknown>): void;
11
+ warn(event: GatewayLogEvent, context?: Record<string, unknown>): void;
12
+ error(event: GatewayLogEvent, context?: Record<string, unknown>): void;
13
+ of(event: GatewayLogEvent): Record<string, unknown>[];
14
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RecordingLog = void 0;
4
+ /** A gateway log that keeps every entry, for assertions. */
5
+ class RecordingLog {
6
+ constructor() {
7
+ this.entries = [];
8
+ }
9
+ info(event, context = {}) {
10
+ this.entries.push({ level: 'info', event, context });
11
+ }
12
+ warn(event, context = {}) {
13
+ this.entries.push({ level: 'warn', event, context });
14
+ }
15
+ error(event, context = {}) {
16
+ this.entries.push({ level: 'error', event, context });
17
+ }
18
+ of(event) {
19
+ return this.entries.filter((e) => e.event === event).map((e) => e.context);
20
+ }
21
+ }
22
+ exports.RecordingLog = RecordingLog;
@@ -0,0 +1,3 @@
1
+ export declare const sleep: (ms: number) => Promise<unknown>;
2
+ /** Resolve with the first truthy value `check` returns, or throw after `ms`. */
3
+ export declare function until<T>(check: () => T | undefined | null | false, ms?: number): Promise<T>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sleep = void 0;
4
+ exports.until = until;
5
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
6
+ exports.sleep = sleep;
7
+ /** Resolve with the first truthy value `check` returns, or throw after `ms`. */
8
+ async function until(check, ms = 500) {
9
+ const end = Date.now() + ms;
10
+ while (Date.now() < end) {
11
+ const value = check();
12
+ if (value)
13
+ return value;
14
+ await (0, exports.sleep)(2);
15
+ }
16
+ throw new Error('condition not met in time');
17
+ }
@@ -8,13 +8,13 @@ export declare const findTasksSchema: z.ZodObject<{
8
8
  }, "strip", z.ZodTypeAny, {
9
9
  limit: number;
10
10
  status?: "completed" | "pending" | "in_progress" | "needs_intervention" | "failed" | undefined;
11
- workflow_type?: string | undefined;
12
11
  workflow_id?: string | undefined;
12
+ workflow_type?: string | undefined;
13
13
  origin_id?: string | undefined;
14
14
  }, {
15
15
  status?: "completed" | "pending" | "in_progress" | "needs_intervention" | "failed" | undefined;
16
- workflow_type?: string | undefined;
17
16
  workflow_id?: string | undefined;
17
+ workflow_type?: string | undefined;
18
18
  origin_id?: string | undefined;
19
19
  limit?: number | undefined;
20
20
  }>;
@@ -5,6 +5,9 @@ const hotmesh_1 = require("@hotmeshio/hotmesh");
5
5
  const logger_1 = require("../lib/logger");
6
6
  const telemetry_1 = require("../lib/telemetry");
7
7
  const events_1 = require("../lib/events");
8
+ const callback_1 = require("../lib/events/callback");
9
+ const surface_1 = require("../services/machines/surface");
10
+ const roles_1 = require("../services/machines/roles");
8
11
  const maintenance_1 = require("../services/maintenance");
9
12
  const cron_1 = require("../services/cron");
10
13
  const mcp_1 = require("../services/mcp");
@@ -67,8 +70,15 @@ async function start(startConfig) {
67
70
  (0, adapters_1.registerAdapters)(startConfig);
68
71
  logger_1.loggerRegistry.info('[long-tail] starting...');
69
72
  // 4-5. Collect workers, run migrations, start workers, seed data
73
+ if (startConfig.machines && startConfig.machines.declareRoles !== false) {
74
+ startConfig = { ...startConfig, roles: (0, roles_1.withMachineRoles)(startConfig.roles, startConfig.machines.lines) };
75
+ }
70
76
  const { workers, builtinMcpServerFactories } = await (0, workers_1.collectWorkers)(startConfig);
71
77
  const { adminUserId } = await (0, workers_1.startWorkers)(startConfig, workers, builtinMcpServerFactories);
78
+ // 5b. Machines, after the workers exist so their rows publish lifecycle events
79
+ const machines = startConfig.machines
80
+ ? surface_1.MachineSurface.start({ ...startConfig.machines, callbacks: events_1.eventRegistry.getAdapter(callback_1.CallbackEventAdapter) })
81
+ : null;
72
82
  // 6. Start embedded server (if enabled)
73
83
  const serverEnabled = startConfig.server?.enabled !== false;
74
84
  let httpServer = null;
@@ -85,6 +95,9 @@ async function start(startConfig) {
85
95
  if (httpServer) {
86
96
  await new Promise((resolve) => httpServer.close(() => resolve()));
87
97
  }
98
+ if (machines) {
99
+ await machines.stop();
100
+ }
88
101
  if (mcp_1.mcpRegistry.hasAdapter) {
89
102
  await mcp_1.mcpRegistry.disconnect();
90
103
  }