@hotmeshio/long-tail 0.25.4 → 0.27.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.
- package/README.md +1 -0
- package/build/index.d.ts +5 -0
- package/build/index.js +36 -7
- package/build/lib/events/nats.d.ts +11 -0
- package/build/lib/events/nats.js +33 -2
- package/build/lib/machines/index.d.ts +6 -0
- package/build/lib/machines/index.js +22 -0
- package/build/lib/machines/line.d.ts +44 -0
- package/build/lib/machines/line.js +114 -0
- package/build/lib/machines/protocol/codec.d.ts +108 -0
- package/build/lib/machines/protocol/codec.js +80 -0
- package/build/lib/machines/protocol/constants.d.ts +120 -0
- package/build/lib/machines/protocol/constants.js +97 -0
- package/build/lib/machines/protocol/contract.d.ts +19 -0
- package/build/lib/machines/protocol/contract.js +141 -0
- package/build/lib/machines/protocol/envelope.d.ts +14 -0
- package/build/lib/machines/protocol/envelope.js +43 -0
- package/build/lib/machines/protocol/index.d.ts +5 -0
- package/build/lib/machines/protocol/index.js +21 -0
- package/build/lib/machines/protocol/topics.d.ts +33 -0
- package/build/lib/machines/protocol/topics.js +79 -0
- package/build/lib/machines/site/edge-account.d.ts +11 -0
- package/build/lib/machines/site/edge-account.js +24 -0
- package/build/lib/machines/site/mosquitto-conf.d.ts +27 -0
- package/build/lib/machines/site/mosquitto-conf.js +81 -0
- package/build/lib/machines/site/site-conf.d.ts +23 -0
- package/build/lib/machines/site/site-conf.js +62 -0
- package/build/lib/machines/transport/callback-feed.d.ts +18 -0
- package/build/lib/machines/transport/callback-feed.js +31 -0
- package/build/lib/machines/transport/delivery.d.ts +20 -0
- package/build/lib/machines/transport/delivery.js +37 -0
- package/build/lib/machines/transport/index.d.ts +13 -0
- package/build/lib/machines/transport/index.js +29 -0
- package/build/lib/machines/transport/memory-broker.d.ts +35 -0
- package/build/lib/machines/transport/memory-broker.js +145 -0
- package/build/lib/machines/transport/memory.d.ts +40 -0
- package/build/lib/machines/transport/memory.js +79 -0
- package/build/lib/machines/transport/mqtt-bus.d.ts +24 -0
- package/build/lib/machines/transport/mqtt-bus.js +43 -0
- package/build/lib/machines/transport/mqtt-link.d.ts +16 -0
- package/build/lib/machines/transport/mqtt-link.js +37 -0
- package/build/lib/machines/transport/mqtt-session.d.ts +34 -0
- package/build/lib/machines/transport/mqtt-session.js +127 -0
- package/build/lib/machines/transport/nats-bus.d.ts +36 -0
- package/build/lib/machines/transport/nats-bus.js +47 -0
- package/build/lib/machines/transport/nats-feed.d.ts +26 -0
- package/build/lib/machines/transport/nats-feed.js +49 -0
- package/build/lib/machines/transport/pubsub-feed.d.ts +17 -0
- package/build/lib/machines/transport/pubsub-feed.js +39 -0
- package/build/lib/machines/transport/serial.d.ts +21 -0
- package/build/lib/machines/transport/serial.js +54 -0
- package/build/lib/machines/transport/stream-bus.d.ts +40 -0
- package/build/lib/machines/transport/stream-bus.js +57 -0
- package/build/lib/machines/transport/streams.d.ts +24 -0
- package/build/lib/machines/transport/streams.js +49 -0
- package/build/lib/messaging/config.d.ts +25 -0
- package/build/lib/messaging/config.js +55 -0
- package/build/lib/messaging/constants.d.ts +26 -0
- package/build/lib/messaging/constants.js +26 -0
- package/build/lib/messaging/index.d.ts +24 -0
- package/build/lib/messaging/index.js +65 -0
- package/build/lib/messaging/memory.d.ts +16 -0
- package/build/lib/messaging/memory.js +147 -0
- package/build/lib/messaging/nats/permissions.d.ts +13 -0
- package/build/lib/messaging/nats/permissions.js +22 -0
- package/build/lib/messaging/nats/provider.d.ts +30 -0
- package/build/lib/messaging/nats/provider.js +77 -0
- package/build/lib/messaging/nats/render-conf.d.ts +68 -0
- package/build/lib/messaging/nats/render-conf.js +58 -0
- package/build/lib/messaging/nats/streams.d.ts +26 -0
- package/build/lib/messaging/nats/streams.js +97 -0
- package/build/lib/messaging/subjects.d.ts +8 -0
- package/build/lib/messaging/subjects.js +25 -0
- package/build/scripts/bambu-boat.d.ts +17 -0
- package/build/scripts/bambu-boat.js +134 -0
- package/build/scripts/bambu-print.d.ts +18 -0
- package/build/scripts/bambu-print.js +114 -0
- package/build/scripts/machine-line.d.ts +33 -0
- package/build/scripts/machine-line.js +301 -0
- package/build/services/machines/commands.d.ts +29 -0
- package/build/services/machines/commands.js +37 -0
- package/build/services/machines/config.d.ts +49 -0
- package/build/services/machines/config.js +94 -0
- package/build/services/machines/contracts.d.ts +210 -0
- package/build/services/machines/contracts.js +124 -0
- package/build/services/machines/forms.d.ts +55 -0
- package/build/services/machines/forms.js +37 -0
- package/build/services/machines/gateway/actions.d.ts +111 -0
- package/build/services/machines/gateway/actions.js +8 -0
- package/build/services/machines/gateway/address-book.d.ts +16 -0
- package/build/services/machines/gateway/address-book.js +24 -0
- package/build/services/machines/gateway/admission.d.ts +35 -0
- package/build/services/machines/gateway/admission.js +66 -0
- package/build/services/machines/gateway/api-escalations.d.ts +23 -0
- package/build/services/machines/gateway/api-escalations.js +101 -0
- package/build/services/machines/gateway/dispatcher.d.ts +76 -0
- package/build/services/machines/gateway/dispatcher.js +197 -0
- package/build/services/machines/gateway/escalations.d.ts +51 -0
- package/build/services/machines/gateway/escalations.js +40 -0
- package/build/services/machines/gateway/executor.d.ts +60 -0
- package/build/services/machines/gateway/executor.js +221 -0
- package/build/services/machines/gateway/gateway.d.ts +88 -0
- package/build/services/machines/gateway/gateway.js +270 -0
- package/build/services/machines/gateway/index.d.ts +10 -0
- package/build/services/machines/gateway/index.js +26 -0
- package/build/services/machines/gateway/jobs.d.ts +16 -0
- package/build/services/machines/gateway/jobs.js +24 -0
- package/build/services/machines/gateway/lifecycle.d.ts +21 -0
- package/build/services/machines/gateway/lifecycle.js +89 -0
- package/build/services/machines/gateway/log.d.ts +41 -0
- package/build/services/machines/gateway/log.js +42 -0
- package/build/services/machines/gateway/lt-http.d.ts +51 -0
- package/build/services/machines/gateway/lt-http.js +120 -0
- package/build/services/machines/gateway/pacing.d.ts +43 -0
- package/build/services/machines/gateway/pacing.js +158 -0
- package/build/services/machines/gateway/plan-escalation.d.ts +19 -0
- package/build/services/machines/gateway/plan-escalation.js +210 -0
- package/build/services/machines/gateway/plan-machine.d.ts +17 -0
- package/build/services/machines/gateway/plan-machine.js +283 -0
- package/build/services/machines/gateway/plan-shared.d.ts +18 -0
- package/build/services/machines/gateway/plan-shared.js +36 -0
- package/build/services/machines/gateway/provision.d.ts +22 -0
- package/build/services/machines/gateway/provision.js +79 -0
- package/build/services/machines/gateway/receipts.d.ts +33 -0
- package/build/services/machines/gateway/receipts.js +65 -0
- package/build/services/machines/gateway/reconcile.d.ts +35 -0
- package/build/services/machines/gateway/reconcile.js +99 -0
- package/build/services/machines/gateway/registration.d.ts +38 -0
- package/build/services/machines/gateway/registration.js +121 -0
- package/build/services/machines/gateway/reply-waiter.d.ts +24 -0
- package/build/services/machines/gateway/reply-waiter.js +65 -0
- package/build/services/machines/gateway/state.d.ts +145 -0
- package/build/services/machines/gateway/state.js +241 -0
- package/build/services/machines/gateway/trace.d.ts +16 -0
- package/build/services/machines/gateway/trace.js +43 -0
- package/build/services/machines/identities.d.ts +25 -0
- package/build/services/machines/identities.js +77 -0
- package/build/services/machines/index.d.ts +11 -0
- package/build/services/machines/index.js +27 -0
- package/build/services/machines/leadership.d.ts +35 -0
- package/build/services/machines/leadership.js +100 -0
- package/build/services/machines/roles.d.ts +13 -0
- package/build/services/machines/roles.js +62 -0
- package/build/services/machines/rows.d.ts +30 -0
- package/build/services/machines/rows.js +71 -0
- package/build/services/machines/select.d.ts +25 -0
- package/build/services/machines/select.js +76 -0
- package/build/services/machines/surface.d.ts +33 -0
- package/build/services/machines/surface.js +104 -0
- package/build/services/machines/testing/fake-long-tail.d.ts +79 -0
- package/build/services/machines/testing/fake-long-tail.js +158 -0
- package/build/services/machines/testing/index.d.ts +3 -0
- package/build/services/machines/testing/index.js +19 -0
- package/build/services/machines/testing/recording-log.d.ts +14 -0
- package/build/services/machines/testing/recording-log.js +22 -0
- package/build/services/machines/testing/wait.d.ts +3 -0
- package/build/services/machines/testing/wait.js +17 -0
- package/build/services/mcp/db-server/schemas.d.ts +2 -2
- package/build/start/adapters.js +11 -2
- package/build/start/index.js +20 -1
- package/build/system/mcp-servers/admin/schemas.d.ts +221 -221
- package/build/system/mcp-servers/db-query/schemas.d.ts +2 -2
- package/build/system/mcp-servers/human-queue-schemas.d.ts +6 -6
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/index.d.ts +3 -1
- package/build/types/machines.d.ts +167 -0
- package/build/types/machines.js +7 -0
- package/build/types/messaging.d.ts +72 -0
- package/build/types/messaging.js +11 -0
- package/build/types/startup.d.ts +49 -1
- package/docs/events.md +50 -4
- package/docs/machines.md +322 -0
- package/package.json +13 -1
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the unit workflow and the machine gateway agree on: row types, roles,
|
|
3
|
+
* the metadata a handoff row carries, error codes and resolution shapes. A
|
|
4
|
+
* handoff row is the same for a machine resolver and a person; only the
|
|
5
|
+
* protocol that resolves it differs.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ROW_TYPE: {
|
|
8
|
+
readonly HANDOFF: "handoff";
|
|
9
|
+
readonly HANDOFF_ERROR: "handoff-error";
|
|
10
|
+
readonly ALARM: "line-alarm";
|
|
11
|
+
readonly MACHINE_OFFLINE: "machine-offline";
|
|
12
|
+
readonly MACHINE_QUIET: "machine-quiet";
|
|
13
|
+
/** A host asks a machine to start, stop, pause, resume or change over. */
|
|
14
|
+
readonly MACHINE_COMMAND: "machine-command";
|
|
15
|
+
/** A message that broke the contract under a strict codec: held for a person, never acted on. */
|
|
16
|
+
readonly CONTRACT_VIOLATION: "contract-violation";
|
|
17
|
+
/** An address claims a station the line already knows by another address, or the reverse: a person approves or rejects. */
|
|
18
|
+
readonly MACHINE_REGISTRATION: "machine-registration";
|
|
19
|
+
};
|
|
20
|
+
export declare const LINE_ROLE: {
|
|
21
|
+
/** People who clear alarms, bring machines back and decide failed handoffs. */
|
|
22
|
+
readonly OPERATOR: "line-operator";
|
|
23
|
+
/** People who take finished units off the line: the final handoff. */
|
|
24
|
+
readonly EXIT: "line-exit";
|
|
25
|
+
/** The gateway's own identity. */
|
|
26
|
+
readonly CONTROLLER: "line-controller";
|
|
27
|
+
};
|
|
28
|
+
/** A file a machine fetches and verifies before it starts, by reference. */
|
|
29
|
+
export interface ArtifactRef {
|
|
30
|
+
url: string;
|
|
31
|
+
sha256: string;
|
|
32
|
+
/** The host's id for the file. */
|
|
33
|
+
id?: string;
|
|
34
|
+
contentType?: string;
|
|
35
|
+
sizeBytes?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface HandoffUnit {
|
|
38
|
+
unitId: string;
|
|
39
|
+
carrierId: string | null;
|
|
40
|
+
/** This unit's own file, when each unit has one (a per-unit model or toolpath). */
|
|
41
|
+
artifact?: ArtifactRef;
|
|
42
|
+
/** This unit's files, when it has several. */
|
|
43
|
+
artifacts?: ArtifactRef[];
|
|
44
|
+
/** Parameters for this unit alone, sent to the machine as given. */
|
|
45
|
+
parameters?: Record<string, unknown>;
|
|
46
|
+
}
|
|
47
|
+
/** Metadata on a handoff row. Everything a dispatch needs rides here. */
|
|
48
|
+
export interface HandoffFacets {
|
|
49
|
+
/** The line the row belongs to; a gateway acts only on its own line's rows. */
|
|
50
|
+
siteId: string;
|
|
51
|
+
lineId: string;
|
|
52
|
+
/** The units that move together as one job. */
|
|
53
|
+
units: HandoffUnit[];
|
|
54
|
+
/** The receiver's job for these units. */
|
|
55
|
+
jobId: string;
|
|
56
|
+
/** The sender's job for these units; cancelled with the row. */
|
|
57
|
+
senderJobId: string | null;
|
|
58
|
+
orderRef: string;
|
|
59
|
+
fromMachine: string | null;
|
|
60
|
+
toMachine: string | null;
|
|
61
|
+
recipeId: string | null;
|
|
62
|
+
recipeVersion: string | null;
|
|
63
|
+
process: string | null;
|
|
64
|
+
artifactUrl: string | null;
|
|
65
|
+
artifactSha256: string | null;
|
|
66
|
+
attempt: number;
|
|
67
|
+
/** Parameters for the job, sent to the machine as given; what they mean is between the host and its codec. */
|
|
68
|
+
parameters?: Record<string, unknown>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Items a handoff row accumulates, one per unit: the sender's finished-job
|
|
72
|
+
* record, and the receiver's arrival. When every unit's arrival is held, the
|
|
73
|
+
* receiver resolves the row.
|
|
74
|
+
*/
|
|
75
|
+
export declare const itemKeys: {
|
|
76
|
+
released: (unitId: string) => string;
|
|
77
|
+
arrived: (unitId: string) => string;
|
|
78
|
+
started: (unitId: string) => string;
|
|
79
|
+
progress: (unitId: string, step: number) => string;
|
|
80
|
+
stage: (unitId: string, stage: string) => string;
|
|
81
|
+
paused: (alarmId: string, raisedAt: string) => string;
|
|
82
|
+
resumed: (alarmId: string, raisedAt: string) => string;
|
|
83
|
+
};
|
|
84
|
+
/** The unit an arrival item names; null for any other item. */
|
|
85
|
+
export declare function arrivedUnit(itemKey: string): string | null;
|
|
86
|
+
/** Where a handoff's units stand, read from its items. */
|
|
87
|
+
export interface HandoffProgress {
|
|
88
|
+
/** Units the sender reported finished and released. */
|
|
89
|
+
released: string[];
|
|
90
|
+
/** Units the receiver reported arrived. */
|
|
91
|
+
arrived: string[];
|
|
92
|
+
/** Units with no arrival, in the handoff's order. */
|
|
93
|
+
missing: string[];
|
|
94
|
+
}
|
|
95
|
+
/** A handoff's progress from its items (a row's items, or `$accumulated` on a finished wait), for the units it carries. */
|
|
96
|
+
export declare function handoffProgress(units: readonly string[], items: readonly {
|
|
97
|
+
itemKey: string;
|
|
98
|
+
}[]): HandoffProgress;
|
|
99
|
+
export declare const HANDOFF_ERROR: {
|
|
100
|
+
readonly JAM: "jam";
|
|
101
|
+
readonly INCOMPLETE_HANDSHAKE: "incomplete-handshake";
|
|
102
|
+
readonly CARRIER_MISMATCH: "carrier-mismatch";
|
|
103
|
+
readonly UNREADABLE_ID: "unreadable-id";
|
|
104
|
+
readonly DISPATCH_REFUSED: "dispatch-refused";
|
|
105
|
+
/** Accepted, then the machine could not prepare the job (artifact, recipe). */
|
|
106
|
+
readonly DISPATCH_FAILED: "dispatch-failed";
|
|
107
|
+
readonly NO_REPLY: "no-reply";
|
|
108
|
+
readonly SENDER_REJECTED: "sender-rejected";
|
|
109
|
+
readonly HANDOFF_TIMEOUT: "handoff-timeout";
|
|
110
|
+
/** The handoff timed out after some of its units arrived; the units are split between two stations. */
|
|
111
|
+
readonly PARTIAL_ARRIVAL: "partial-arrival";
|
|
112
|
+
readonly SOFTWARE_UNSUPPORTED: "software-unsupported";
|
|
113
|
+
readonly WITHDRAWN: "withdrawn";
|
|
114
|
+
readonly CANCELLED: "cancelled";
|
|
115
|
+
};
|
|
116
|
+
export type HandoffErrorCode = typeof HANDOFF_ERROR[keyof typeof HANDOFF_ERROR];
|
|
117
|
+
/** A material lot a machine consumed for a unit. */
|
|
118
|
+
export interface TraceMaterial {
|
|
119
|
+
material: string;
|
|
120
|
+
lot: string;
|
|
121
|
+
}
|
|
122
|
+
/** One unit as a machine finished it, kept on the handoff row so a search by lot finds it. */
|
|
123
|
+
export interface TraceEntry {
|
|
124
|
+
unitId: string;
|
|
125
|
+
machineId: string;
|
|
126
|
+
jobId: string | null;
|
|
127
|
+
result: string | null;
|
|
128
|
+
materials: TraceMaterial[];
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Facets a handoff row gains as the sender finishes its units: `trace`, one
|
|
132
|
+
* entry per unit, and `lots`, every lot those units consumed. Both are
|
|
133
|
+
* containment-searchable, e.g. `{ lots: ['LOT-7'] }`.
|
|
134
|
+
*/
|
|
135
|
+
export declare const TRACE_FACET: {
|
|
136
|
+
readonly TRACE: "trace";
|
|
137
|
+
readonly LOTS: "lots";
|
|
138
|
+
};
|
|
139
|
+
/** The facet a row holding a job carries while it runs: its latest noted progress. */
|
|
140
|
+
export declare const LIFECYCLE_FACET: {
|
|
141
|
+
readonly PROGRESS: "progress";
|
|
142
|
+
};
|
|
143
|
+
/** What resolves a handoff row, from a machine or from a person's form. */
|
|
144
|
+
export interface HandoffResolution {
|
|
145
|
+
received: boolean;
|
|
146
|
+
receiver?: string;
|
|
147
|
+
/** Every unit received, on success. */
|
|
148
|
+
units?: string[];
|
|
149
|
+
/** The unit that failed, on an error. */
|
|
150
|
+
unitId?: string;
|
|
151
|
+
/** The machine that reported the error, when it is not the one resolving. */
|
|
152
|
+
reportedBy?: string;
|
|
153
|
+
errorCode?: HandoffErrorCode;
|
|
154
|
+
reason?: string | null;
|
|
155
|
+
detail?: string;
|
|
156
|
+
}
|
|
157
|
+
/** Decisions on line-operator rows: failed handoffs, alarms, dark machines, contested registrations. */
|
|
158
|
+
export declare const DECISION: {
|
|
159
|
+
readonly RETRY: "retry";
|
|
160
|
+
readonly MANUAL: "manual";
|
|
161
|
+
readonly SCRAP: "scrap";
|
|
162
|
+
readonly ACKNOWLEDGE: "acknowledge";
|
|
163
|
+
readonly CLEARED: "cleared";
|
|
164
|
+
readonly RESTORED: "restored";
|
|
165
|
+
readonly APPROVE: "approve";
|
|
166
|
+
readonly REJECT: "reject";
|
|
167
|
+
};
|
|
168
|
+
export type Decision = typeof DECISION[keyof typeof DECISION];
|
|
169
|
+
/** The decisions an operator may take on a failed handoff; retry only while every unit is still at the sender. */
|
|
170
|
+
export declare function handoffDecisions(errorCode?: HandoffErrorCode): Decision[];
|
|
171
|
+
export interface OperatorResolution {
|
|
172
|
+
decision: Decision;
|
|
173
|
+
note?: string;
|
|
174
|
+
}
|
|
175
|
+
/** Signal keys for the unit workflow; every attempt mints a fresh key. */
|
|
176
|
+
export declare const signalKeys: {
|
|
177
|
+
handoff: (jobKey: string, step: number, attempt: number) => string;
|
|
178
|
+
handoffError: (jobKey: string, step: number, attempt: number, round?: number) => string;
|
|
179
|
+
jobStop: (jobKey: string, step: number, attempt: number) => string;
|
|
180
|
+
};
|
|
181
|
+
/** Metadata on a machine-command row. */
|
|
182
|
+
export interface CommandFacets {
|
|
183
|
+
siteId: string;
|
|
184
|
+
lineId: string;
|
|
185
|
+
machineId: string;
|
|
186
|
+
op: string;
|
|
187
|
+
args: Record<string, unknown>;
|
|
188
|
+
}
|
|
189
|
+
export declare const COMMAND_STATUS: {
|
|
190
|
+
readonly NO_REPLY: "no-reply";
|
|
191
|
+
readonly UNSUPPORTED: "unsupported";
|
|
192
|
+
readonly ACCEPTED: "accepted";
|
|
193
|
+
readonly COMPLETED: "completed";
|
|
194
|
+
readonly REFUSED: "refused";
|
|
195
|
+
readonly FAILED: "failed";
|
|
196
|
+
};
|
|
197
|
+
export type CommandStatus = typeof COMMAND_STATUS[keyof typeof COMMAND_STATUS];
|
|
198
|
+
/** What resolves a machine-command row: the machine's reply, as data. */
|
|
199
|
+
export interface CommandResolution {
|
|
200
|
+
accepted: boolean;
|
|
201
|
+
machineId: string;
|
|
202
|
+
op: string;
|
|
203
|
+
status: CommandStatus;
|
|
204
|
+
reason?: string;
|
|
205
|
+
}
|
|
206
|
+
/** A row's dispatch command in its validity round; a later round is a new command (gateway/pacing.ts dispatchWindow). */
|
|
207
|
+
export declare const dispatchCommandId: (escalationId: string, round?: number) => string;
|
|
208
|
+
/** A command row's command in its validity round; a later round is a new command (gateway/pacing.ts dispatchWindow). */
|
|
209
|
+
export declare const controlCommandId: (escalationId: string, round?: number) => string;
|
|
210
|
+
export declare const cancelCommandId: (escalationId: string) => string;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* What the unit workflow and the machine gateway agree on: row types, roles,
|
|
4
|
+
* the metadata a handoff row carries, error codes and resolution shapes. A
|
|
5
|
+
* handoff row is the same for a machine resolver and a person; only the
|
|
6
|
+
* protocol that resolves it differs.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.cancelCommandId = exports.controlCommandId = exports.dispatchCommandId = exports.COMMAND_STATUS = exports.signalKeys = exports.DECISION = exports.LIFECYCLE_FACET = exports.TRACE_FACET = exports.HANDOFF_ERROR = exports.itemKeys = exports.LINE_ROLE = exports.ROW_TYPE = void 0;
|
|
10
|
+
exports.arrivedUnit = arrivedUnit;
|
|
11
|
+
exports.handoffProgress = handoffProgress;
|
|
12
|
+
exports.handoffDecisions = handoffDecisions;
|
|
13
|
+
const line_1 = require("../../lib/machines/line");
|
|
14
|
+
const protocol_1 = require("../../lib/machines/protocol");
|
|
15
|
+
exports.ROW_TYPE = {
|
|
16
|
+
HANDOFF: 'handoff',
|
|
17
|
+
HANDOFF_ERROR: 'handoff-error',
|
|
18
|
+
ALARM: 'line-alarm',
|
|
19
|
+
MACHINE_OFFLINE: 'machine-offline',
|
|
20
|
+
MACHINE_QUIET: 'machine-quiet',
|
|
21
|
+
/** A host asks a machine to start, stop, pause, resume or change over. */
|
|
22
|
+
MACHINE_COMMAND: 'machine-command',
|
|
23
|
+
/** A message that broke the contract under a strict codec: held for a person, never acted on. */
|
|
24
|
+
CONTRACT_VIOLATION: 'contract-violation',
|
|
25
|
+
/** An address claims a station the line already knows by another address, or the reverse: a person approves or rejects. */
|
|
26
|
+
MACHINE_REGISTRATION: 'machine-registration',
|
|
27
|
+
};
|
|
28
|
+
exports.LINE_ROLE = {
|
|
29
|
+
/** People who clear alarms, bring machines back and decide failed handoffs. */
|
|
30
|
+
OPERATOR: line_1.DEFAULT_OPERATOR_ROLE,
|
|
31
|
+
/** People who take finished units off the line: the final handoff. */
|
|
32
|
+
EXIT: line_1.DEFAULT_EXIT_ROLE,
|
|
33
|
+
/** The gateway's own identity. */
|
|
34
|
+
CONTROLLER: 'line-controller',
|
|
35
|
+
};
|
|
36
|
+
const RELEASED_PREFIX = 'released:';
|
|
37
|
+
const ARRIVED_PREFIX = 'arrived:';
|
|
38
|
+
/**
|
|
39
|
+
* Items a handoff row accumulates, one per unit: the sender's finished-job
|
|
40
|
+
* record, and the receiver's arrival. When every unit's arrival is held, the
|
|
41
|
+
* receiver resolves the row.
|
|
42
|
+
*/
|
|
43
|
+
exports.itemKeys = {
|
|
44
|
+
released: (unitId) => `${RELEASED_PREFIX}${unitId}`,
|
|
45
|
+
arrived: (unitId) => `${ARRIVED_PREFIX}${unitId}`,
|
|
46
|
+
started: (unitId) => `started:${unitId}`,
|
|
47
|
+
progress: (unitId, step) => `progress:${unitId}:${step}`,
|
|
48
|
+
stage: (unitId, stage) => `stage:${unitId}:${stage}`,
|
|
49
|
+
paused: (alarmId, raisedAt) => `paused:${alarmId}:${raisedAt}`,
|
|
50
|
+
resumed: (alarmId, raisedAt) => `resumed:${alarmId}:${raisedAt}`,
|
|
51
|
+
};
|
|
52
|
+
/** The unit an arrival item names; null for any other item. */
|
|
53
|
+
function arrivedUnit(itemKey) {
|
|
54
|
+
return itemKey.startsWith(ARRIVED_PREFIX) ? itemKey.slice(ARRIVED_PREFIX.length) : null;
|
|
55
|
+
}
|
|
56
|
+
/** A handoff's progress from its items (a row's items, or `$accumulated` on a finished wait), for the units it carries. */
|
|
57
|
+
function handoffProgress(units, items) {
|
|
58
|
+
const keys = new Set(items.map((i) => i.itemKey));
|
|
59
|
+
const arrived = units.filter((u) => keys.has(exports.itemKeys.arrived(u)));
|
|
60
|
+
return {
|
|
61
|
+
released: units.filter((u) => keys.has(exports.itemKeys.released(u))),
|
|
62
|
+
arrived,
|
|
63
|
+
missing: units.filter((u) => !arrived.includes(u)),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
exports.HANDOFF_ERROR = {
|
|
67
|
+
DISPATCH_REFUSED: 'dispatch-refused',
|
|
68
|
+
/** Accepted, then the machine could not prepare the job (artifact, recipe). */
|
|
69
|
+
DISPATCH_FAILED: 'dispatch-failed',
|
|
70
|
+
NO_REPLY: 'no-reply',
|
|
71
|
+
SENDER_REJECTED: 'sender-rejected',
|
|
72
|
+
HANDOFF_TIMEOUT: 'handoff-timeout',
|
|
73
|
+
/** The handoff timed out after some of its units arrived; the units are split between two stations. */
|
|
74
|
+
PARTIAL_ARRIVAL: 'partial-arrival',
|
|
75
|
+
SOFTWARE_UNSUPPORTED: 'software-unsupported',
|
|
76
|
+
WITHDRAWN: 'withdrawn',
|
|
77
|
+
CANCELLED: 'cancelled',
|
|
78
|
+
...protocol_1.TRANSFER_FAILURE,
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Facets a handoff row gains as the sender finishes its units: `trace`, one
|
|
82
|
+
* entry per unit, and `lots`, every lot those units consumed. Both are
|
|
83
|
+
* containment-searchable, e.g. `{ lots: ['LOT-7'] }`.
|
|
84
|
+
*/
|
|
85
|
+
exports.TRACE_FACET = { TRACE: 'trace', LOTS: 'lots' };
|
|
86
|
+
/** The facet a row holding a job carries while it runs: its latest noted progress. */
|
|
87
|
+
exports.LIFECYCLE_FACET = { PROGRESS: 'progress' };
|
|
88
|
+
/** Decisions on line-operator rows: failed handoffs, alarms, dark machines, contested registrations. */
|
|
89
|
+
exports.DECISION = {
|
|
90
|
+
RETRY: 'retry',
|
|
91
|
+
MANUAL: 'manual',
|
|
92
|
+
SCRAP: 'scrap',
|
|
93
|
+
ACKNOWLEDGE: 'acknowledge',
|
|
94
|
+
CLEARED: 'cleared',
|
|
95
|
+
RESTORED: 'restored',
|
|
96
|
+
APPROVE: 'approve',
|
|
97
|
+
REJECT: 'reject',
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Failures a retry cannot repair. Units a sender finished as not ok leave the
|
|
101
|
+
* automated line and never re-enter it; units split by a partial arrival are
|
|
102
|
+
* no longer all at the sender, so the same hop cannot move them again.
|
|
103
|
+
*/
|
|
104
|
+
const NO_RETRY = [exports.HANDOFF_ERROR.SENDER_REJECTED, exports.HANDOFF_ERROR.PARTIAL_ARRIVAL];
|
|
105
|
+
/** The decisions an operator may take on a failed handoff; retry only while every unit is still at the sender. */
|
|
106
|
+
function handoffDecisions(errorCode) {
|
|
107
|
+
const noRetry = !!errorCode && NO_RETRY.includes(errorCode);
|
|
108
|
+
return noRetry ? [exports.DECISION.MANUAL, exports.DECISION.SCRAP] : [exports.DECISION.RETRY, exports.DECISION.MANUAL, exports.DECISION.SCRAP];
|
|
109
|
+
}
|
|
110
|
+
/** Signal keys for the unit workflow; every attempt mints a fresh key. */
|
|
111
|
+
exports.signalKeys = {
|
|
112
|
+
handoff: (jobKey, step, attempt) => `handoff-${jobKey}-s${step}-a${attempt}`,
|
|
113
|
+
handoffError: (jobKey, step, attempt, round = 1) => `handoff-error-${jobKey}-s${step}-a${attempt}${round > 1 ? `-r${round}` : ''}`,
|
|
114
|
+
jobStop: (jobKey, step, attempt) => `job-stop-${jobKey}-s${step}-a${attempt}`,
|
|
115
|
+
};
|
|
116
|
+
exports.COMMAND_STATUS = { ...protocol_1.REPLY_STATUS, NO_REPLY: 'no-reply', UNSUPPORTED: 'unsupported' };
|
|
117
|
+
/** A row's dispatch command in its validity round; a later round is a new command (gateway/pacing.ts dispatchWindow). */
|
|
118
|
+
const dispatchCommandId = (escalationId, round = 1) => (round > 1 ? `${escalationId}:dispatch:r${round}` : `${escalationId}:dispatch`);
|
|
119
|
+
exports.dispatchCommandId = dispatchCommandId;
|
|
120
|
+
/** A command row's command in its validity round; a later round is a new command (gateway/pacing.ts dispatchWindow). */
|
|
121
|
+
const controlCommandId = (escalationId, round = 1) => (round > 1 ? `${escalationId}:command:r${round}` : `${escalationId}:command`);
|
|
122
|
+
exports.controlCommandId = controlCommandId;
|
|
123
|
+
const cancelCommandId = (escalationId) => `${escalationId}:cancel`;
|
|
124
|
+
exports.cancelCommandId = cancelCommandId;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The escalation surfaces each role owns. A handoff row looks the same to a
|
|
3
|
+
* machine and to a person: machines resolve it through the gateway, a person
|
|
4
|
+
* resolves the line-exit row with this form. Line operators decide failed
|
|
5
|
+
* handoffs and close alarm and machine-state rows.
|
|
6
|
+
*/
|
|
7
|
+
export declare const HANDOFF_FORM_SCHEMA: {
|
|
8
|
+
title: string;
|
|
9
|
+
description: string;
|
|
10
|
+
'x-lt-order': string[];
|
|
11
|
+
required: string[];
|
|
12
|
+
properties: {
|
|
13
|
+
received: {
|
|
14
|
+
type: string;
|
|
15
|
+
default: boolean;
|
|
16
|
+
description: string;
|
|
17
|
+
};
|
|
18
|
+
receiver: {
|
|
19
|
+
type: string;
|
|
20
|
+
default: string;
|
|
21
|
+
description: string;
|
|
22
|
+
};
|
|
23
|
+
note: {
|
|
24
|
+
type: string;
|
|
25
|
+
format: string;
|
|
26
|
+
default: string;
|
|
27
|
+
description: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export declare const OPERATOR_FORM_SCHEMA: {
|
|
32
|
+
title: string;
|
|
33
|
+
description: string;
|
|
34
|
+
'x-lt-order': string[];
|
|
35
|
+
required: string[];
|
|
36
|
+
properties: {
|
|
37
|
+
decision: {
|
|
38
|
+
type: string;
|
|
39
|
+
enum: ("reject" | "scrap" | "retry" | "manual" | "acknowledge" | "cleared" | "restored" | "approve")[];
|
|
40
|
+
default: "acknowledge";
|
|
41
|
+
description: string;
|
|
42
|
+
};
|
|
43
|
+
note: {
|
|
44
|
+
type: string;
|
|
45
|
+
format: string;
|
|
46
|
+
default: string;
|
|
47
|
+
description: string;
|
|
48
|
+
};
|
|
49
|
+
clearedBy: {
|
|
50
|
+
type: string;
|
|
51
|
+
default: string;
|
|
52
|
+
description: string;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The escalation surfaces each role owns. A handoff row looks the same to a
|
|
4
|
+
* machine and to a person: machines resolve it through the gateway, a person
|
|
5
|
+
* resolves the line-exit row with this form. Line operators decide failed
|
|
6
|
+
* handoffs and close alarm and machine-state rows.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.OPERATOR_FORM_SCHEMA = exports.HANDOFF_FORM_SCHEMA = void 0;
|
|
10
|
+
const contracts_1 = require("./contracts");
|
|
11
|
+
exports.HANDOFF_FORM_SCHEMA = {
|
|
12
|
+
title: 'Receive units',
|
|
13
|
+
description: 'Confirm the units are in hand. A machine confirms its own receipts; this form is for a person receiving them.',
|
|
14
|
+
'x-lt-order': ['received', 'receiver', 'note'],
|
|
15
|
+
required: ['received'],
|
|
16
|
+
properties: {
|
|
17
|
+
received: { type: 'boolean', default: true, description: 'Every unit in this handoff is in hand' },
|
|
18
|
+
receiver: { type: 'string', default: '', description: 'Who or what received them' },
|
|
19
|
+
note: { type: 'string', format: 'textarea', default: '', description: 'Anything notable about the units' },
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
exports.OPERATOR_FORM_SCHEMA = {
|
|
23
|
+
title: 'Line decision',
|
|
24
|
+
description: 'A handoff that did not complete: retry it, finish the units by hand, or scrap them. Units a machine finished as not ok are off the line: finish them by hand or scrap them. An alarm or a machine that went dark: acknowledge it once handled.',
|
|
25
|
+
'x-lt-order': ['decision', 'note'],
|
|
26
|
+
required: ['decision'],
|
|
27
|
+
properties: {
|
|
28
|
+
decision: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
enum: Object.values(contracts_1.DECISION),
|
|
31
|
+
default: contracts_1.DECISION.ACKNOWLEDGE,
|
|
32
|
+
description: 'One of the row\'s decisions for a failed handoff; acknowledge for an alarm or a machine',
|
|
33
|
+
},
|
|
34
|
+
note: { type: 'string', format: 'textarea', default: '', description: 'What was done' },
|
|
35
|
+
clearedBy: { type: 'string', default: '', description: 'Who cleared it at the machine, when the machine reports it' },
|
|
36
|
+
},
|
|
37
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The gateway's side effects as data. The planner decides; the executor does.
|
|
3
|
+
* `as` names the identity a verb runs under: a machine id, or the controller.
|
|
4
|
+
*/
|
|
5
|
+
import type { Disposition } from '../../../lib/machines/transport';
|
|
6
|
+
export declare const CONTROLLER = "controller";
|
|
7
|
+
export type Actor = string;
|
|
8
|
+
export interface CreateRowInput {
|
|
9
|
+
type: string;
|
|
10
|
+
subtype?: string;
|
|
11
|
+
role: string;
|
|
12
|
+
description: string;
|
|
13
|
+
priority: number;
|
|
14
|
+
metadata: Record<string, any>;
|
|
15
|
+
/** JSON envelope, e.g. `{ lookups: [...] }` naming the catalog edition a code comes from. */
|
|
16
|
+
envelope?: string;
|
|
17
|
+
/** What the row shows a person, serialized. */
|
|
18
|
+
escalation_payload?: string;
|
|
19
|
+
}
|
|
20
|
+
export type Action =
|
|
21
|
+
/** `receivedOnAccept`: the units are already at the machine, so its acceptance completes the handoff. */
|
|
22
|
+
{
|
|
23
|
+
kind: 'dispatch';
|
|
24
|
+
rowId: string;
|
|
25
|
+
machineId: string;
|
|
26
|
+
cmdId: string;
|
|
27
|
+
args: Record<string, any>;
|
|
28
|
+
receivedOnAccept?: boolean;
|
|
29
|
+
} | {
|
|
30
|
+
kind: 'command';
|
|
31
|
+
machineId: string;
|
|
32
|
+
op: string;
|
|
33
|
+
cmdId: string;
|
|
34
|
+
args: Record<string, any>;
|
|
35
|
+
}
|
|
36
|
+
/** A host's machine-command row: send the command, resolve the row with the reply. */
|
|
37
|
+
| {
|
|
38
|
+
kind: 'control';
|
|
39
|
+
rowId: string;
|
|
40
|
+
machineId: string;
|
|
41
|
+
op: string;
|
|
42
|
+
args: Record<string, any>;
|
|
43
|
+
createdAt?: number;
|
|
44
|
+
} | {
|
|
45
|
+
kind: 'claim';
|
|
46
|
+
as: Actor;
|
|
47
|
+
rowId: string;
|
|
48
|
+
}
|
|
49
|
+
/** `metadata` is merged into the row's metadata in the same statement. */
|
|
50
|
+
| {
|
|
51
|
+
kind: 'accumulate';
|
|
52
|
+
as: Actor;
|
|
53
|
+
rowId: string;
|
|
54
|
+
itemKey: string;
|
|
55
|
+
payload: Record<string, any>;
|
|
56
|
+
metadata?: Record<string, any>;
|
|
57
|
+
complete?: Completion;
|
|
58
|
+
} | {
|
|
59
|
+
kind: 'resolve';
|
|
60
|
+
as: Actor;
|
|
61
|
+
rowId: string;
|
|
62
|
+
payload: Record<string, any>;
|
|
63
|
+
} | {
|
|
64
|
+
kind: 'createAlarmRow';
|
|
65
|
+
machineId: string;
|
|
66
|
+
alarmId: string;
|
|
67
|
+
row: CreateRowInput;
|
|
68
|
+
}
|
|
69
|
+
/** A row for a person, raised by the controller. */
|
|
70
|
+
| {
|
|
71
|
+
kind: 'createRow';
|
|
72
|
+
row: CreateRowInput;
|
|
73
|
+
} | {
|
|
74
|
+
kind: 'watchOffline';
|
|
75
|
+
machineId: string;
|
|
76
|
+
} | {
|
|
77
|
+
kind: 'settleReply';
|
|
78
|
+
cmdId: string;
|
|
79
|
+
status: string;
|
|
80
|
+
reason: string;
|
|
81
|
+
}
|
|
82
|
+
/** A machine reported the jobs it holds: answers a status query in flight. */
|
|
83
|
+
| {
|
|
84
|
+
kind: 'settleSnapshot';
|
|
85
|
+
machineId: string;
|
|
86
|
+
jobIds: string[];
|
|
87
|
+
}
|
|
88
|
+
/** Bind a station to the address that claims it, and keep the binding in the address book. `by`: who approved it, when someone did. */
|
|
89
|
+
| {
|
|
90
|
+
kind: 'bindAddress';
|
|
91
|
+
machineId: string;
|
|
92
|
+
address: string;
|
|
93
|
+
by?: string;
|
|
94
|
+
}
|
|
95
|
+
/** An approved registration the gateway will not bind, and why. */
|
|
96
|
+
| {
|
|
97
|
+
kind: 'refuseBinding';
|
|
98
|
+
machineId: string;
|
|
99
|
+
address: string;
|
|
100
|
+
reason: string;
|
|
101
|
+
};
|
|
102
|
+
/** Once the row holds every one of `keys`: resolve it with `payload`, or run `then` instead. */
|
|
103
|
+
export interface Completion {
|
|
104
|
+
keys: string[];
|
|
105
|
+
payload?: Record<string, any>;
|
|
106
|
+
then?: Action[];
|
|
107
|
+
}
|
|
108
|
+
export interface Plan {
|
|
109
|
+
actions: Action[];
|
|
110
|
+
disposition: Disposition;
|
|
111
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The gateway's side effects as data. The planner decides; the executor does.
|
|
4
|
+
* `as` names the identity a verb runs under: a machine id, or the controller.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.CONTROLLER = void 0;
|
|
8
|
+
exports.CONTROLLER = 'controller';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a line keeps the machine addresses it learned, so a gateway that
|
|
3
|
+
* takes the line over sends to the same machines. The memory book lasts as
|
|
4
|
+
* long as the process; Long Tail keeps each binding on the station's bot
|
|
5
|
+
* account (identities.ts).
|
|
6
|
+
*/
|
|
7
|
+
export interface AddressBook {
|
|
8
|
+
/** Station → address, for every station bound so far. */
|
|
9
|
+
load(): Promise<Map<string, string>>;
|
|
10
|
+
bind(machineId: string, address: string): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare class MemoryAddressBook implements AddressBook {
|
|
13
|
+
private readonly bindings;
|
|
14
|
+
load(): Promise<Map<string, string>>;
|
|
15
|
+
bind(machineId: string, address: string): Promise<void>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Where a line keeps the machine addresses it learned, so a gateway that
|
|
4
|
+
* takes the line over sends to the same machines. The memory book lasts as
|
|
5
|
+
* long as the process; Long Tail keeps each binding on the station's bot
|
|
6
|
+
* account (identities.ts).
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.MemoryAddressBook = void 0;
|
|
10
|
+
class MemoryAddressBook {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.bindings = new Map();
|
|
13
|
+
}
|
|
14
|
+
async load() {
|
|
15
|
+
return new Map(this.bindings);
|
|
16
|
+
}
|
|
17
|
+
async bind(machineId, address) {
|
|
18
|
+
for (const [station, bound] of this.bindings)
|
|
19
|
+
if (bound === address)
|
|
20
|
+
this.bindings.delete(station);
|
|
21
|
+
this.bindings.set(machineId, address);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.MemoryAddressBook = MemoryAddressBook;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What happens to a decoded machine message before the planner sees it: the
|
|
3
|
+
* sender is checked against the line's learned addresses (registration.ts),
|
|
4
|
+
* and under a strict codec a message that breaks the contract is held for a
|
|
5
|
+
* person instead of acted on.
|
|
6
|
+
*/
|
|
7
|
+
import { type LineDef } from '../../../lib/machines/line';
|
|
8
|
+
import type { Inspection } from '../../../lib/machines/protocol';
|
|
9
|
+
import { type Disposition, type InboundMessage } from '../../../lib/machines/transport';
|
|
10
|
+
import type { Action } from './actions';
|
|
11
|
+
import { type GatewayLog } from './log';
|
|
12
|
+
import type { GatewayState } from './state';
|
|
13
|
+
/** What handling one decoded message came to. */
|
|
14
|
+
export interface Applied {
|
|
15
|
+
disposition: Disposition;
|
|
16
|
+
failed: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface AdmissionContext {
|
|
19
|
+
state: GatewayState;
|
|
20
|
+
line: LineDef;
|
|
21
|
+
executor: {
|
|
22
|
+
apply(actions: Action[]): Promise<void>;
|
|
23
|
+
};
|
|
24
|
+
log: GatewayLog;
|
|
25
|
+
/** Send waiting handoffs that may now go out. */
|
|
26
|
+
pace(): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The station a message is from (registration.ts). A newly claimed station is
|
|
30
|
+
* bound and its waiting work goes out; a contested claim raises one row for a
|
|
31
|
+
* person; either of those, and an address no station claims, is not acted on.
|
|
32
|
+
*/
|
|
33
|
+
export declare function admitSender(ctx: AdmissionContext, topic: string, raw: Inspection): Promise<Inspection | Applied>;
|
|
34
|
+
/** Under a strict codec a broken message is not acted on: a person sees it on a row, once. */
|
|
35
|
+
export declare function holdViolation(ctx: AdmissionContext, msg: InboundMessage, seen: Inspection): Promise<Applied>;
|