@lumenflow/packs-sidekick 4.23.0 → 5.0.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/dist/channel-ingress.d.ts +46 -0
- package/dist/channel-ingress.d.ts.map +1 -0
- package/dist/channel-ingress.js +90 -0
- package/dist/channel-ingress.js.map +1 -0
- package/dist/manifest.d.ts +17 -0
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +67 -0
- package/dist/manifest.js.map +1 -1
- package/dist/sidekick-events.d.ts +166 -0
- package/dist/sidekick-events.d.ts.map +1 -0
- package/dist/sidekick-events.js +288 -0
- package/dist/sidekick-events.js.map +1 -0
- package/dist/src/adapters/cloud-queue.d.ts +20 -0
- package/dist/src/adapters/cloud-queue.d.ts.map +1 -0
- package/dist/src/adapters/cloud-queue.js +90 -0
- package/dist/src/adapters/cloud-queue.js.map +1 -0
- package/dist/src/adapters/control-plane-bridge.adapter.d.ts +31 -0
- package/dist/src/adapters/control-plane-bridge.adapter.d.ts.map +1 -0
- package/dist/src/adapters/control-plane-bridge.adapter.js +263 -0
- package/dist/src/adapters/control-plane-bridge.adapter.js.map +1 -0
- package/dist/src/adapters/filesystem-bridge.adapter.d.ts +11 -0
- package/dist/src/adapters/filesystem-bridge.adapter.d.ts.map +1 -0
- package/dist/src/adapters/filesystem-bridge.adapter.js +161 -0
- package/dist/src/adapters/filesystem-bridge.adapter.js.map +1 -0
- package/dist/src/channel-ingress.d.ts +46 -0
- package/dist/src/channel-ingress.d.ts.map +1 -0
- package/dist/src/channel-ingress.js +90 -0
- package/dist/src/channel-ingress.js.map +1 -0
- package/dist/src/domain/channel.types.d.ts +79 -0
- package/dist/src/domain/channel.types.d.ts.map +1 -0
- package/dist/src/domain/channel.types.js +4 -0
- package/dist/src/domain/channel.types.js.map +1 -0
- package/dist/src/ports/channel-bridge.port.d.ts +49 -0
- package/dist/src/ports/channel-bridge.port.d.ts.map +1 -0
- package/dist/src/ports/channel-bridge.port.js +18 -0
- package/dist/src/ports/channel-bridge.port.js.map +1 -0
- package/dist/src/routines/commit.d.ts +21 -0
- package/dist/src/routines/commit.d.ts.map +1 -0
- package/dist/src/routines/commit.js +42 -0
- package/dist/src/routines/commit.js.map +1 -0
- package/dist/src/sidekick-events.d.ts +166 -0
- package/dist/src/sidekick-events.d.ts.map +1 -0
- package/dist/src/sidekick-events.js +288 -0
- package/dist/src/sidekick-events.js.map +1 -0
- package/dist/tool-impl/channel-tools.d.ts.map +1 -1
- package/dist/tool-impl/channel-tools.js +24 -0
- package/dist/tool-impl/channel-tools.js.map +1 -1
- package/dist/tool-impl/memory-tools.d.ts.map +1 -1
- package/dist/tool-impl/memory-tools.js +7 -0
- package/dist/tool-impl/memory-tools.js.map +1 -1
- package/dist/tool-impl/routine-commit.d.ts +3 -0
- package/dist/tool-impl/routine-commit.d.ts.map +1 -0
- package/dist/tool-impl/routine-commit.js +69 -0
- package/dist/tool-impl/routine-commit.js.map +1 -0
- package/dist/tool-impl/routine-tools.d.ts.map +1 -1
- package/dist/tool-impl/routine-tools.js +50 -7
- package/dist/tool-impl/routine-tools.js.map +1 -1
- package/dist/tool-impl/runtime-context.d.ts +4 -0
- package/dist/tool-impl/runtime-context.d.ts.map +1 -1
- package/dist/tool-impl/runtime-context.js.map +1 -1
- package/dist/tool-impl/storage.d.ts.map +1 -1
- package/dist/tool-impl/storage.js +3 -0
- package/dist/tool-impl/storage.js.map +1 -1
- package/dist/tool-impl/system-tools.d.ts.map +1 -1
- package/dist/tool-impl/system-tools.js +2 -0
- package/dist/tool-impl/system-tools.js.map +1 -1
- package/dist/tool-impl/task-tools.d.ts.map +1 -1
- package/dist/tool-impl/task-tools.js +30 -0
- package/dist/tool-impl/task-tools.js.map +1 -1
- package/manifest.yaml +88 -0
- package/package.json +4 -2
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
// Copyright (c) 2026 Hellmai Ltd
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
4
|
+
import { appendFile, mkdir } from 'node:fs/promises';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { getSidekickRuntimeContext } from './tool-impl/runtime-context.js';
|
|
7
|
+
import { getStoragePort, } from './tool-impl/storage.js';
|
|
8
|
+
const SCHEMA_VERSION_V2 = 2;
|
|
9
|
+
const CONTENT_HASH_ALGORITHM = 'sha256';
|
|
10
|
+
const CONTENT_HASH_ENCODING = 'hex';
|
|
11
|
+
const CONTENT_HASH_PREFIX_LENGTH = 32;
|
|
12
|
+
const OUTBOX_RELATIVE_PATH = path.join('.lumenflow', 'state', 'conductor', 'outbox', 'sidekick-events.jsonl');
|
|
13
|
+
export const SIDEKICK_CHANNEL_ID = 'sidekick';
|
|
14
|
+
export const SIDEKICK_EVENT_KINDS = {
|
|
15
|
+
TASK_CREATED: 'sidekick:task_created',
|
|
16
|
+
TASK_COMPLETED: 'sidekick:task_completed',
|
|
17
|
+
TASK_SCHEDULED: 'sidekick:task_scheduled',
|
|
18
|
+
TASK_SNOOZED: 'sidekick:task_snoozed',
|
|
19
|
+
MEMORY_STORED: 'sidekick:memory_stored',
|
|
20
|
+
MEMORY_RECALLED: 'sidekick:memory_recalled',
|
|
21
|
+
MEMORY_FORGOTTEN: 'sidekick:memory_forgotten',
|
|
22
|
+
CHANNEL_MESSAGE_SENT: 'sidekick:channel_message_sent',
|
|
23
|
+
CHANNEL_MESSAGE_RECEIVED: 'sidekick:channel_message_received',
|
|
24
|
+
CHANNEL_BRIDGE_CONNECTED: 'sidekick:channel_bridge_connected',
|
|
25
|
+
CHANNEL_BRIDGE_DISCONNECTED: 'sidekick:channel_bridge_disconnected',
|
|
26
|
+
ROUTINE_PLANNED: 'sidekick:routine_planned',
|
|
27
|
+
ROUTINE_COMMITTED: 'sidekick:routine_committed',
|
|
28
|
+
ROUTINE_EXECUTED: 'sidekick:routine_executed',
|
|
29
|
+
ROUTINE_STEP_FAILED: 'sidekick:routine_step_failed',
|
|
30
|
+
STATE_REHYDRATED: 'sidekick:state_rehydrated',
|
|
31
|
+
};
|
|
32
|
+
export const SIDEKICK_EVENT_KIND_VALUES = [
|
|
33
|
+
SIDEKICK_EVENT_KINDS.TASK_CREATED,
|
|
34
|
+
SIDEKICK_EVENT_KINDS.TASK_COMPLETED,
|
|
35
|
+
SIDEKICK_EVENT_KINDS.TASK_SCHEDULED,
|
|
36
|
+
SIDEKICK_EVENT_KINDS.TASK_SNOOZED,
|
|
37
|
+
SIDEKICK_EVENT_KINDS.MEMORY_STORED,
|
|
38
|
+
SIDEKICK_EVENT_KINDS.MEMORY_RECALLED,
|
|
39
|
+
SIDEKICK_EVENT_KINDS.MEMORY_FORGOTTEN,
|
|
40
|
+
SIDEKICK_EVENT_KINDS.CHANNEL_MESSAGE_SENT,
|
|
41
|
+
SIDEKICK_EVENT_KINDS.CHANNEL_MESSAGE_RECEIVED,
|
|
42
|
+
SIDEKICK_EVENT_KINDS.CHANNEL_BRIDGE_CONNECTED,
|
|
43
|
+
SIDEKICK_EVENT_KINDS.CHANNEL_BRIDGE_DISCONNECTED,
|
|
44
|
+
SIDEKICK_EVENT_KINDS.ROUTINE_PLANNED,
|
|
45
|
+
SIDEKICK_EVENT_KINDS.ROUTINE_COMMITTED,
|
|
46
|
+
SIDEKICK_EVENT_KINDS.ROUTINE_EXECUTED,
|
|
47
|
+
SIDEKICK_EVENT_KINDS.ROUTINE_STEP_FAILED,
|
|
48
|
+
SIDEKICK_EVENT_KINDS.STATE_REHYDRATED,
|
|
49
|
+
];
|
|
50
|
+
const QUEUE_WITH_REPLAY = 'queue-with-replay';
|
|
51
|
+
const EPHEMERAL = 'ephemeral';
|
|
52
|
+
export const SIDEKICK_EVENT_BACKPRESSURE_POLICY = {
|
|
53
|
+
[SIDEKICK_EVENT_KINDS.TASK_CREATED]: QUEUE_WITH_REPLAY,
|
|
54
|
+
[SIDEKICK_EVENT_KINDS.TASK_COMPLETED]: QUEUE_WITH_REPLAY,
|
|
55
|
+
[SIDEKICK_EVENT_KINDS.TASK_SCHEDULED]: QUEUE_WITH_REPLAY,
|
|
56
|
+
[SIDEKICK_EVENT_KINDS.TASK_SNOOZED]: QUEUE_WITH_REPLAY,
|
|
57
|
+
[SIDEKICK_EVENT_KINDS.MEMORY_STORED]: EPHEMERAL,
|
|
58
|
+
[SIDEKICK_EVENT_KINDS.MEMORY_RECALLED]: EPHEMERAL,
|
|
59
|
+
[SIDEKICK_EVENT_KINDS.MEMORY_FORGOTTEN]: EPHEMERAL,
|
|
60
|
+
[SIDEKICK_EVENT_KINDS.CHANNEL_MESSAGE_SENT]: EPHEMERAL,
|
|
61
|
+
[SIDEKICK_EVENT_KINDS.CHANNEL_MESSAGE_RECEIVED]: EPHEMERAL,
|
|
62
|
+
[SIDEKICK_EVENT_KINDS.CHANNEL_BRIDGE_CONNECTED]: EPHEMERAL,
|
|
63
|
+
[SIDEKICK_EVENT_KINDS.CHANNEL_BRIDGE_DISCONNECTED]: EPHEMERAL,
|
|
64
|
+
[SIDEKICK_EVENT_KINDS.ROUTINE_PLANNED]: QUEUE_WITH_REPLAY,
|
|
65
|
+
[SIDEKICK_EVENT_KINDS.ROUTINE_COMMITTED]: QUEUE_WITH_REPLAY,
|
|
66
|
+
[SIDEKICK_EVENT_KINDS.ROUTINE_EXECUTED]: QUEUE_WITH_REPLAY,
|
|
67
|
+
[SIDEKICK_EVENT_KINDS.ROUTINE_STEP_FAILED]: QUEUE_WITH_REPLAY,
|
|
68
|
+
[SIDEKICK_EVENT_KINDS.STATE_REHYDRATED]: QUEUE_WITH_REPLAY,
|
|
69
|
+
};
|
|
70
|
+
const channelSeqCounters = new Map();
|
|
71
|
+
function nextSeq(channelId) {
|
|
72
|
+
const current = channelSeqCounters.get(channelId) ?? 0;
|
|
73
|
+
const next = current + 1;
|
|
74
|
+
channelSeqCounters.set(channelId, next);
|
|
75
|
+
return next;
|
|
76
|
+
}
|
|
77
|
+
function resolveTimestamp(timestamp) {
|
|
78
|
+
return timestamp ?? new Date().toISOString();
|
|
79
|
+
}
|
|
80
|
+
function resolveEventId(kind, payload, timestamp, idempotencyKey) {
|
|
81
|
+
if (!idempotencyKey) {
|
|
82
|
+
return randomUUID();
|
|
83
|
+
}
|
|
84
|
+
return createHash(CONTENT_HASH_ALGORITHM)
|
|
85
|
+
.update(JSON.stringify({
|
|
86
|
+
kind,
|
|
87
|
+
payload,
|
|
88
|
+
timestamp,
|
|
89
|
+
idempotencyKey,
|
|
90
|
+
}))
|
|
91
|
+
.digest(CONTENT_HASH_ENCODING)
|
|
92
|
+
.slice(0, CONTENT_HASH_PREFIX_LENGTH);
|
|
93
|
+
}
|
|
94
|
+
function stampSidekickEvent(payload, options) {
|
|
95
|
+
const timestamp = resolveTimestamp(options?.timestamp);
|
|
96
|
+
const event_id = resolveEventId(payload.kind, payload, timestamp, options?.idempotencyKey);
|
|
97
|
+
return {
|
|
98
|
+
...payload,
|
|
99
|
+
schema_version: SCHEMA_VERSION_V2,
|
|
100
|
+
timestamp,
|
|
101
|
+
event_id,
|
|
102
|
+
channel_id: SIDEKICK_CHANNEL_ID,
|
|
103
|
+
seq: nextSeq(SIDEKICK_CHANNEL_ID),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async function queueEvent(event, workspaceRoot) {
|
|
107
|
+
const outboxPath = path.join(workspaceRoot, OUTBOX_RELATIVE_PATH);
|
|
108
|
+
await mkdir(path.dirname(outboxPath), { recursive: true });
|
|
109
|
+
await appendFile(outboxPath, `${JSON.stringify(event)}\n`, 'utf8');
|
|
110
|
+
}
|
|
111
|
+
export function resetSidekickSeqCounter() {
|
|
112
|
+
channelSeqCounters.clear();
|
|
113
|
+
}
|
|
114
|
+
export function readSidekickOrgId(config) {
|
|
115
|
+
if (!config || typeof config !== 'object') {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
const controlPlane = config.control_plane;
|
|
119
|
+
if (!controlPlane || typeof controlPlane !== 'object') {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
const raw = controlPlane.org_id;
|
|
123
|
+
if (typeof raw !== 'string') {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
const trimmed = raw.trim();
|
|
127
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
128
|
+
}
|
|
129
|
+
export async function emitSidekickEvent(event) {
|
|
130
|
+
const runtimeContext = getSidekickRuntimeContext();
|
|
131
|
+
const policy = SIDEKICK_EVENT_BACKPRESSURE_POLICY[event.kind];
|
|
132
|
+
const orgId = readSidekickOrgId(runtimeContext?.workspaceConfig);
|
|
133
|
+
const sink = runtimeContext?.eventSink;
|
|
134
|
+
if (policy === 'ephemeral') {
|
|
135
|
+
if (!orgId || !sink) {
|
|
136
|
+
return event;
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
await sink(event);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Ephemeral events fail silent when the control plane is unavailable.
|
|
143
|
+
}
|
|
144
|
+
return event;
|
|
145
|
+
}
|
|
146
|
+
if (orgId && sink) {
|
|
147
|
+
try {
|
|
148
|
+
await sink(event);
|
|
149
|
+
return event;
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Fall through to queued replay on transport failure.
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
await queueEvent(event, runtimeContext?.workspaceRoot ?? process.cwd());
|
|
156
|
+
return event;
|
|
157
|
+
}
|
|
158
|
+
export async function snapshotSidekickState() {
|
|
159
|
+
const storage = getStoragePort();
|
|
160
|
+
const [tasks, memories, channels, messages, routines] = await Promise.all([
|
|
161
|
+
storage.readStore('tasks'),
|
|
162
|
+
storage.readStore('memories'),
|
|
163
|
+
storage.readStore('channels'),
|
|
164
|
+
storage.readStore('messages'),
|
|
165
|
+
storage.readStore('routines'),
|
|
166
|
+
]);
|
|
167
|
+
return { tasks, memories, channels, messages, routines };
|
|
168
|
+
}
|
|
169
|
+
export function buildTaskCreatedEvent(task) {
|
|
170
|
+
return stampSidekickEvent({
|
|
171
|
+
kind: SIDEKICK_EVENT_KINDS.TASK_CREATED,
|
|
172
|
+
task,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
export function buildTaskCompletedEvent(task) {
|
|
176
|
+
return stampSidekickEvent({
|
|
177
|
+
kind: SIDEKICK_EVENT_KINDS.TASK_COMPLETED,
|
|
178
|
+
task,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
export function buildTaskScheduledEvent(task) {
|
|
182
|
+
return stampSidekickEvent({
|
|
183
|
+
kind: SIDEKICK_EVENT_KINDS.TASK_SCHEDULED,
|
|
184
|
+
task,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
export function buildTaskSnoozedEvent(input) {
|
|
188
|
+
return stampSidekickEvent({
|
|
189
|
+
kind: SIDEKICK_EVENT_KINDS.TASK_SNOOZED,
|
|
190
|
+
...input,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
export function buildMemoryStoredEvent(memory) {
|
|
194
|
+
return stampSidekickEvent({
|
|
195
|
+
kind: SIDEKICK_EVENT_KINDS.MEMORY_STORED,
|
|
196
|
+
memory,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
export function buildMemoryRecalledEvent(input) {
|
|
200
|
+
return stampSidekickEvent({
|
|
201
|
+
kind: SIDEKICK_EVENT_KINDS.MEMORY_RECALLED,
|
|
202
|
+
query: input.query,
|
|
203
|
+
count: input.memories.length,
|
|
204
|
+
memory_ids: input.memories.map((memory) => memory.id),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
export function buildMemoryForgottenEvent(memory_id) {
|
|
208
|
+
return stampSidekickEvent({
|
|
209
|
+
kind: SIDEKICK_EVENT_KINDS.MEMORY_FORGOTTEN,
|
|
210
|
+
memory_id,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
export function buildChannelMessageSentEvent(message) {
|
|
214
|
+
return stampSidekickEvent({
|
|
215
|
+
kind: SIDEKICK_EVENT_KINDS.CHANNEL_MESSAGE_SENT,
|
|
216
|
+
message,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
export function buildChannelMessageReceivedEvent(input) {
|
|
220
|
+
return stampSidekickEvent({
|
|
221
|
+
kind: SIDEKICK_EVENT_KINDS.CHANNEL_MESSAGE_RECEIVED,
|
|
222
|
+
channel: input.channel,
|
|
223
|
+
count: input.count,
|
|
224
|
+
...(input.provider ? { provider: input.provider } : {}),
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
export function buildChannelBridgeConnectedEvent(channel) {
|
|
228
|
+
return stampSidekickEvent({
|
|
229
|
+
kind: SIDEKICK_EVENT_KINDS.CHANNEL_BRIDGE_CONNECTED,
|
|
230
|
+
channel,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
export function buildChannelBridgeDisconnectedEvent(input) {
|
|
234
|
+
return stampSidekickEvent({
|
|
235
|
+
kind: SIDEKICK_EVENT_KINDS.CHANNEL_BRIDGE_DISCONNECTED,
|
|
236
|
+
...input,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
export function buildRoutinePlannedEvent(routine) {
|
|
240
|
+
return stampSidekickEvent({
|
|
241
|
+
kind: SIDEKICK_EVENT_KINDS.ROUTINE_PLANNED,
|
|
242
|
+
routine,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
export function buildRoutineCommittedEvent(routine, options) {
|
|
246
|
+
return stampSidekickEvent({
|
|
247
|
+
kind: SIDEKICK_EVENT_KINDS.ROUTINE_COMMITTED,
|
|
248
|
+
routine,
|
|
249
|
+
...(options?.envelope_content_hash
|
|
250
|
+
? { envelope_content_hash: options.envelope_content_hash }
|
|
251
|
+
: {}),
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
export function buildRoutineExecutedEvent(input) {
|
|
255
|
+
return stampSidekickEvent({
|
|
256
|
+
kind: SIDEKICK_EVENT_KINDS.ROUTINE_EXECUTED,
|
|
257
|
+
routine_id: input.routine_id,
|
|
258
|
+
name: input.name,
|
|
259
|
+
step_count: input.step_count,
|
|
260
|
+
plan_only: true,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
export function buildRoutineStepFailedEvent(input) {
|
|
264
|
+
return stampSidekickEvent({
|
|
265
|
+
kind: SIDEKICK_EVENT_KINDS.ROUTINE_STEP_FAILED,
|
|
266
|
+
step_index: input.step_index,
|
|
267
|
+
reason: input.reason,
|
|
268
|
+
...(input.routine_id ? { routine_id: input.routine_id } : {}),
|
|
269
|
+
...(input.routine_name ? { routine_name: input.routine_name } : {}),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
export function buildStateRehydratedEvent(snapshot) {
|
|
273
|
+
return stampSidekickEvent({
|
|
274
|
+
kind: SIDEKICK_EVENT_KINDS.STATE_REHYDRATED,
|
|
275
|
+
snapshot,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
export function serializeLocalChannelMessage(message, channelName) {
|
|
279
|
+
return {
|
|
280
|
+
id: message.id,
|
|
281
|
+
channel_id: message.channel_id,
|
|
282
|
+
...(channelName ? { channel: channelName } : {}),
|
|
283
|
+
sender: message.sender,
|
|
284
|
+
content: message.content,
|
|
285
|
+
created_at: message.created_at,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=sidekick-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidekick-events.js","sourceRoot":"","sources":["../sidekick-events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ChannelEnvelope } from '../domain/channel.types.js';
|
|
2
|
+
export interface OutboxRecord {
|
|
3
|
+
channel_id: string;
|
|
4
|
+
envelope: ChannelEnvelope;
|
|
5
|
+
/** Internal filename so the adapter can remove the entry after a successful replay. */
|
|
6
|
+
_filename: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class CloudOutbox {
|
|
9
|
+
private readonly outboxDir;
|
|
10
|
+
constructor(outboxDir: string);
|
|
11
|
+
enqueue(channelId: string, envelope: ChannelEnvelope): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Lists outbox records in FIFO order. The returned filename is opaque; pass
|
|
14
|
+
* it back to `remove()` after a successful replay.
|
|
15
|
+
*/
|
|
16
|
+
list(): Promise<OutboxRecord[]>;
|
|
17
|
+
remove(filename: string): Promise<void>;
|
|
18
|
+
isEmpty(): Promise<boolean>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=cloud-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-queue.d.ts","sourceRoot":"","sources":["../../../src/adapters/cloud-queue.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,eAAe,CAAC;IAC1B,uFAAuF;IACvF,SAAS,EAAE,MAAM,CAAC;CACnB;AAcD,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM;IAExC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAW1E;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IA8B/B,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;CAIlC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Copyright (c) 2026 Hellmai Ltd
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
/**
|
|
4
|
+
* WU-2737 (INIT-060 WU-7b, ADR-013 §ChannelBridge):
|
|
5
|
+
* Local outbox for queue-kind envelopes when the cloud is unreachable.
|
|
6
|
+
*
|
|
7
|
+
* Backing layout:
|
|
8
|
+
* <outboxDir>/<channel-id>/<timestamp>-<envelope-id>.json
|
|
9
|
+
*
|
|
10
|
+
* Each file is a JSON blob `{ channel_id, envelope }` matching the request
|
|
11
|
+
* body shape published in `channel-bridge-cloud-stub.md`. FIFO ordering comes
|
|
12
|
+
* from the sorted filename (lexicographic on timestamp + envelope id).
|
|
13
|
+
*
|
|
14
|
+
* The outbox is intentionally dumb: no retry state, no backoff, no watcher.
|
|
15
|
+
* The adapter drives drains explicitly via `flush()` or reactively on the
|
|
16
|
+
* next successful POST; ADR-013 §4 treats the outbox as a passive spool.
|
|
17
|
+
*/
|
|
18
|
+
import { mkdir, readdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
/**
|
|
21
|
+
* Seconds-precision epoch plus a short random suffix keeps filenames sortable
|
|
22
|
+
* FIFO while avoiding collisions when two envelopes enqueue in the same
|
|
23
|
+
* millisecond.
|
|
24
|
+
*/
|
|
25
|
+
function mintFilename(envelopeId) {
|
|
26
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-');
|
|
27
|
+
const safeId = envelopeId.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
28
|
+
const suffix = Math.random().toString(36).slice(2, 8);
|
|
29
|
+
return `${ts}-${safeId}-${suffix}.json`;
|
|
30
|
+
}
|
|
31
|
+
export class CloudOutbox {
|
|
32
|
+
outboxDir;
|
|
33
|
+
constructor(outboxDir) {
|
|
34
|
+
this.outboxDir = outboxDir;
|
|
35
|
+
}
|
|
36
|
+
async enqueue(channelId, envelope) {
|
|
37
|
+
const dir = path.resolve(this.outboxDir);
|
|
38
|
+
await mkdir(dir, { recursive: true });
|
|
39
|
+
const filename = mintFilename(envelope.id);
|
|
40
|
+
const tmpPath = path.join(dir, `.tmp-${process.pid}-${filename}`);
|
|
41
|
+
const finalPath = path.join(dir, filename);
|
|
42
|
+
const payload = JSON.stringify({ channel_id: channelId, envelope });
|
|
43
|
+
await writeFile(tmpPath, payload, 'utf8');
|
|
44
|
+
await rename(tmpPath, finalPath);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Lists outbox records in FIFO order. The returned filename is opaque; pass
|
|
48
|
+
* it back to `remove()` after a successful replay.
|
|
49
|
+
*/
|
|
50
|
+
async list() {
|
|
51
|
+
const dir = path.resolve(this.outboxDir);
|
|
52
|
+
let entries;
|
|
53
|
+
try {
|
|
54
|
+
entries = await readdir(dir);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
const err = error;
|
|
58
|
+
if (err.code === 'ENOENT') {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
const records = [];
|
|
64
|
+
const sortedEntries = entries
|
|
65
|
+
.filter((e) => e.endsWith('.json') && !e.startsWith('.tmp-'))
|
|
66
|
+
.sort();
|
|
67
|
+
for (const name of sortedEntries) {
|
|
68
|
+
const full = path.join(dir, name);
|
|
69
|
+
try {
|
|
70
|
+
const raw = await readFile(full, 'utf8');
|
|
71
|
+
const parsed = JSON.parse(raw);
|
|
72
|
+
records.push({ ...parsed, _filename: name });
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Corrupt or partial file — skip (will not block FIFO drain).
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return records;
|
|
80
|
+
}
|
|
81
|
+
async remove(filename) {
|
|
82
|
+
const full = path.join(path.resolve(this.outboxDir), filename);
|
|
83
|
+
await rm(full, { force: true });
|
|
84
|
+
}
|
|
85
|
+
async isEmpty() {
|
|
86
|
+
const records = await this.list();
|
|
87
|
+
return records.length === 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=cloud-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-queue.js","sourceRoot":"","sources":["../../../src/adapters/cloud-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ChannelBridge } from '../ports/channel-bridge.port.js';
|
|
2
|
+
export interface ControlPlaneChannelBridgeOptions {
|
|
3
|
+
/** Cloud API base URL, e.g. `https://app.lumenflow.dev` (no trailing slash). */
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
/** Workspace id — path parameter on the POST route. */
|
|
6
|
+
workspaceId: string;
|
|
7
|
+
/**
|
|
8
|
+
* Returns the current enrollment token. Called on every request so token
|
|
9
|
+
* rotation (re-auth) is transparent to callers.
|
|
10
|
+
*/
|
|
11
|
+
tokenProvider: () => Promise<string>;
|
|
12
|
+
/** Local outbox root for queue-kind envelopes. */
|
|
13
|
+
outboxDir: string;
|
|
14
|
+
/** Polling interval for `receive()`. Defaults to 1000ms. */
|
|
15
|
+
pollIntervalMs?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Optional override for `fetch`. Primarily a test seam; production wiring
|
|
18
|
+
* uses the platform global `fetch`.
|
|
19
|
+
*/
|
|
20
|
+
fetchImpl?: typeof fetch;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* `ChannelBridge` extended with `flush()` so operators (and the disconnect
|
|
24
|
+
* path) can explicitly drain the outbox. The port contract itself does NOT
|
|
25
|
+
* require `flush`; it's an adapter affordance.
|
|
26
|
+
*/
|
|
27
|
+
export interface ControlPlaneChannelBridge extends ChannelBridge {
|
|
28
|
+
flush(): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export declare function createControlPlaneChannelBridge(options: ControlPlaneChannelBridgeOptions): ControlPlaneChannelBridge;
|
|
31
|
+
//# sourceMappingURL=control-plane-bridge.adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-plane-bridge.adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/control-plane-bridge.adapter.ts"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAQrE,MAAM,WAAW,gCAAgC;IAC/C,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,aAAa,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAA0B,SAAQ,aAAa;IAC9D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAsDD,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,gCAAgC,GACxC,yBAAyB,CAmP3B"}
|