@pellux/goodvibes-daemon-sdk 0.18.3
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 +32 -0
- package/dist/api-router.d.ts +3 -0
- package/dist/api-router.d.ts.map +1 -0
- package/dist/api-router.js +13 -0
- package/dist/automation.d.ts +3 -0
- package/dist/automation.d.ts.map +1 -0
- package/dist/automation.js +56 -0
- package/dist/channel-route-types.d.ts +78 -0
- package/dist/channel-route-types.d.ts.map +1 -0
- package/dist/channel-route-types.js +1 -0
- package/dist/channel-routes.d.ts +4 -0
- package/dist/channel-routes.d.ts.map +1 -0
- package/dist/channel-routes.js +264 -0
- package/dist/context.d.ts +207 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +1 -0
- package/dist/control-routes.d.ts +57 -0
- package/dist/control-routes.d.ts.map +1 -0
- package/dist/control-routes.js +120 -0
- package/dist/error-response.d.ts +10 -0
- package/dist/error-response.d.ts.map +1 -0
- package/dist/error-response.js +84 -0
- package/dist/http-policy.d.ts +33 -0
- package/dist/http-policy.d.ts.map +1 -0
- package/dist/http-policy.js +30 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/integration-route-types.d.ts +64 -0
- package/dist/integration-route-types.d.ts.map +1 -0
- package/dist/integration-route-types.js +1 -0
- package/dist/integration-routes.d.ts +4 -0
- package/dist/integration-routes.d.ts.map +1 -0
- package/dist/integration-routes.js +172 -0
- package/dist/knowledge-route-types.d.ts +114 -0
- package/dist/knowledge-route-types.d.ts.map +1 -0
- package/dist/knowledge-route-types.js +1 -0
- package/dist/knowledge-routes.d.ts +4 -0
- package/dist/knowledge-routes.d.ts.map +1 -0
- package/dist/knowledge-routes.js +582 -0
- package/dist/media-route-types.d.ts +66 -0
- package/dist/media-route-types.d.ts.map +1 -0
- package/dist/media-route-types.js +1 -0
- package/dist/media-routes.d.ts +4 -0
- package/dist/media-routes.d.ts.map +1 -0
- package/dist/media-routes.js +328 -0
- package/dist/operator.d.ts +3 -0
- package/dist/operator.d.ts.map +1 -0
- package/dist/operator.js +395 -0
- package/dist/remote-routes.d.ts +40 -0
- package/dist/remote-routes.d.ts.map +1 -0
- package/dist/remote-routes.js +238 -0
- package/dist/remote.d.ts +3 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +35 -0
- package/dist/route-helpers.d.ts +11 -0
- package/dist/route-helpers.d.ts.map +1 -0
- package/dist/route-helpers.js +54 -0
- package/dist/runtime-automation-routes.d.ts +4 -0
- package/dist/runtime-automation-routes.d.ts.map +1 -0
- package/dist/runtime-automation-routes.js +165 -0
- package/dist/runtime-route-types.d.ts +240 -0
- package/dist/runtime-route-types.d.ts.map +1 -0
- package/dist/runtime-route-types.js +1 -0
- package/dist/runtime-routes.d.ts +5 -0
- package/dist/runtime-routes.d.ts.map +1 -0
- package/dist/runtime-routes.js +8 -0
- package/dist/runtime-session-routes.d.ts +4 -0
- package/dist/runtime-session-routes.d.ts.map +1 -0
- package/dist/runtime-session-routes.js +387 -0
- package/dist/sessions.d.ts +3 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/sessions.js +37 -0
- package/dist/system-route-types.d.ts +124 -0
- package/dist/system-route-types.d.ts.map +1 -0
- package/dist/system-route-types.js +1 -0
- package/dist/system-routes.d.ts +4 -0
- package/dist/system-routes.d.ts.map +1 -0
- package/dist/system-routes.js +327 -0
- package/dist/tasks.d.ts +3 -0
- package/dist/tasks.d.ts.map +1 -0
- package/dist/tasks.js +22 -0
- package/dist/telemetry-routes.d.ts +44 -0
- package/dist/telemetry-routes.d.ts.map +1 -0
- package/dist/telemetry-routes.js +227 -0
- package/package.json +42 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { jsonErrorResponse } from './error-response.js';
|
|
2
|
+
export function createDaemonSystemRouteHandlers(context, request) {
|
|
3
|
+
return {
|
|
4
|
+
getWatchers: () => Response.json({ watchers: context.watcherRegistry.list() }),
|
|
5
|
+
postWatcher: (req) => {
|
|
6
|
+
const admin = context.requireAdmin(req);
|
|
7
|
+
if (admin)
|
|
8
|
+
return admin;
|
|
9
|
+
return handleRegisterWatcher(context, req);
|
|
10
|
+
},
|
|
11
|
+
patchWatcher: (watcherId, req) => {
|
|
12
|
+
const admin = context.requireAdmin(req);
|
|
13
|
+
if (admin)
|
|
14
|
+
return admin;
|
|
15
|
+
return handleUpdateWatcher(context, watcherId, req);
|
|
16
|
+
},
|
|
17
|
+
watcherAction: (watcherId, action) => {
|
|
18
|
+
const admin = context.requireAdmin(request);
|
|
19
|
+
if (admin)
|
|
20
|
+
return admin;
|
|
21
|
+
return handleWatcherAction(context, watcherId, action);
|
|
22
|
+
},
|
|
23
|
+
deleteWatcher: (watcherId) => {
|
|
24
|
+
const admin = context.requireAdmin(request);
|
|
25
|
+
if (admin)
|
|
26
|
+
return admin;
|
|
27
|
+
const removed = context.watcherRegistry.removeWatcher(watcherId);
|
|
28
|
+
return removed
|
|
29
|
+
? Response.json({ removed: true, id: watcherId })
|
|
30
|
+
: Response.json({ error: 'Unknown watcher' }, { status: 404 });
|
|
31
|
+
},
|
|
32
|
+
getServiceStatus: () => Response.json({
|
|
33
|
+
...context.platformServiceManager.status(),
|
|
34
|
+
network: {
|
|
35
|
+
controlPlane: context.inspectInboundTls('controlPlane'),
|
|
36
|
+
httpListener: context.inspectInboundTls('httpListener'),
|
|
37
|
+
outbound: context.inspectOutboundTls(),
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
installService: () => {
|
|
41
|
+
const admin = context.requireAdmin(request);
|
|
42
|
+
if (admin)
|
|
43
|
+
return admin;
|
|
44
|
+
return Response.json(context.platformServiceManager.install());
|
|
45
|
+
},
|
|
46
|
+
startService: () => {
|
|
47
|
+
const admin = context.requireAdmin(request);
|
|
48
|
+
if (admin)
|
|
49
|
+
return admin;
|
|
50
|
+
return Response.json(context.platformServiceManager.start());
|
|
51
|
+
},
|
|
52
|
+
stopService: () => {
|
|
53
|
+
const admin = context.requireAdmin(request);
|
|
54
|
+
if (admin)
|
|
55
|
+
return admin;
|
|
56
|
+
return Response.json(context.platformServiceManager.stop());
|
|
57
|
+
},
|
|
58
|
+
restartService: () => {
|
|
59
|
+
const admin = context.requireAdmin(request);
|
|
60
|
+
if (admin)
|
|
61
|
+
return admin;
|
|
62
|
+
return Response.json(context.platformServiceManager.restart());
|
|
63
|
+
},
|
|
64
|
+
uninstallService: () => {
|
|
65
|
+
const admin = context.requireAdmin(request);
|
|
66
|
+
if (admin)
|
|
67
|
+
return admin;
|
|
68
|
+
return Response.json(context.platformServiceManager.uninstall());
|
|
69
|
+
},
|
|
70
|
+
getRouteBindings: () => Response.json({ bindings: context.routeBindings.listBindings() }),
|
|
71
|
+
postRouteBinding: async (req) => {
|
|
72
|
+
const admin = context.requireAdmin(req);
|
|
73
|
+
if (admin)
|
|
74
|
+
return admin;
|
|
75
|
+
const body = await context.parseJsonBody(req);
|
|
76
|
+
if (body instanceof Response)
|
|
77
|
+
return body;
|
|
78
|
+
const surfaceKind = typeof body.surfaceKind === 'string' ? body.surfaceKind : '';
|
|
79
|
+
const kind = typeof body.kind === 'string' ? body.kind : '';
|
|
80
|
+
const surfaceId = typeof body.surfaceId === 'string' ? body.surfaceId : '';
|
|
81
|
+
const externalId = typeof body.externalId === 'string' ? body.externalId : '';
|
|
82
|
+
if (!surfaceKind || !kind || !surfaceId || !externalId) {
|
|
83
|
+
return Response.json({ error: 'Missing required route binding fields' }, { status: 400 });
|
|
84
|
+
}
|
|
85
|
+
const binding = await context.routeBindings.upsertBinding({
|
|
86
|
+
id: typeof body.id === 'string' ? body.id : undefined,
|
|
87
|
+
kind: kind,
|
|
88
|
+
surfaceKind: surfaceKind,
|
|
89
|
+
surfaceId,
|
|
90
|
+
externalId,
|
|
91
|
+
sessionPolicy: typeof body.sessionPolicy === 'string' ? body.sessionPolicy : undefined,
|
|
92
|
+
threadPolicy: typeof body.threadPolicy === 'string' ? body.threadPolicy : undefined,
|
|
93
|
+
deliveryGuarantee: typeof body.deliveryGuarantee === 'string' ? body.deliveryGuarantee : undefined,
|
|
94
|
+
threadId: typeof body.threadId === 'string' ? body.threadId : undefined,
|
|
95
|
+
channelId: typeof body.channelId === 'string' ? body.channelId : undefined,
|
|
96
|
+
sessionId: typeof body.sessionId === 'string' ? body.sessionId : undefined,
|
|
97
|
+
jobId: typeof body.jobId === 'string' ? body.jobId : undefined,
|
|
98
|
+
runId: typeof body.runId === 'string' ? body.runId : undefined,
|
|
99
|
+
title: typeof body.title === 'string' ? body.title : undefined,
|
|
100
|
+
metadata: typeof body.metadata === 'object' && body.metadata !== null ? body.metadata : {},
|
|
101
|
+
});
|
|
102
|
+
return Response.json(binding, { status: 201 });
|
|
103
|
+
},
|
|
104
|
+
patchRouteBinding: async (bindingId, req) => {
|
|
105
|
+
const admin = context.requireAdmin(req);
|
|
106
|
+
if (admin)
|
|
107
|
+
return admin;
|
|
108
|
+
const body = await context.parseJsonBody(req);
|
|
109
|
+
if (body instanceof Response)
|
|
110
|
+
return body;
|
|
111
|
+
const updated = await context.routeBindings.patchBinding(bindingId, {
|
|
112
|
+
...(body.sessionPolicy !== undefined ? { sessionPolicy: typeof body.sessionPolicy === 'string' ? body.sessionPolicy : undefined } : {}),
|
|
113
|
+
...(body.threadPolicy !== undefined ? { threadPolicy: typeof body.threadPolicy === 'string' ? body.threadPolicy : undefined } : {}),
|
|
114
|
+
...(body.deliveryGuarantee !== undefined ? { deliveryGuarantee: typeof body.deliveryGuarantee === 'string' ? body.deliveryGuarantee : undefined } : {}),
|
|
115
|
+
...(body.threadId !== undefined ? { threadId: typeof body.threadId === 'string' ? body.threadId : undefined } : {}),
|
|
116
|
+
...(body.channelId !== undefined ? { channelId: typeof body.channelId === 'string' ? body.channelId : undefined } : {}),
|
|
117
|
+
...(body.sessionId !== undefined ? { sessionId: body.sessionId === null ? null : typeof body.sessionId === 'string' ? body.sessionId : undefined } : {}),
|
|
118
|
+
...(body.jobId !== undefined ? { jobId: body.jobId === null ? null : typeof body.jobId === 'string' ? body.jobId : undefined } : {}),
|
|
119
|
+
...(body.runId !== undefined ? { runId: body.runId === null ? null : typeof body.runId === 'string' ? body.runId : undefined } : {}),
|
|
120
|
+
...(typeof body.title === 'string' ? { title: body.title } : {}),
|
|
121
|
+
...(typeof body.metadata === 'object' && body.metadata !== null ? { metadata: body.metadata } : {}),
|
|
122
|
+
});
|
|
123
|
+
return updated
|
|
124
|
+
? Response.json(updated)
|
|
125
|
+
: Response.json({ error: 'Unknown route binding' }, { status: 404 });
|
|
126
|
+
},
|
|
127
|
+
deleteRouteBinding: async (bindingId) => {
|
|
128
|
+
const admin = context.requireAdmin(request);
|
|
129
|
+
if (admin)
|
|
130
|
+
return admin;
|
|
131
|
+
const removed = await context.routeBindings.removeBinding(bindingId);
|
|
132
|
+
return removed
|
|
133
|
+
? Response.json({ removed: true, id: bindingId })
|
|
134
|
+
: Response.json({ error: 'Unknown route binding' }, { status: 404 });
|
|
135
|
+
},
|
|
136
|
+
getApprovals: () => {
|
|
137
|
+
if (!context.integrationHelpers) {
|
|
138
|
+
return Response.json({ error: 'Integration helper service unavailable' }, { status: 503 });
|
|
139
|
+
}
|
|
140
|
+
return Response.json(context.integrationHelpers.getApprovalSnapshot());
|
|
141
|
+
},
|
|
142
|
+
approvalAction: (approvalId, action, req) => handleApprovalAction(context, approvalId, action, req),
|
|
143
|
+
getConfig: () => {
|
|
144
|
+
const admin = context.requireAdmin(request);
|
|
145
|
+
if (admin)
|
|
146
|
+
return admin;
|
|
147
|
+
return Response.json(context.configManager.getAll());
|
|
148
|
+
},
|
|
149
|
+
postConfig: async (req) => {
|
|
150
|
+
const admin = context.requireAdmin(req);
|
|
151
|
+
if (admin)
|
|
152
|
+
return admin;
|
|
153
|
+
const payload = await context.parseJsonBody(req);
|
|
154
|
+
if (payload instanceof Response)
|
|
155
|
+
return payload;
|
|
156
|
+
const { key, value } = payload;
|
|
157
|
+
if (!key || typeof key !== 'string') {
|
|
158
|
+
return Response.json({ error: 'Missing or invalid key' }, { status: 400 });
|
|
159
|
+
}
|
|
160
|
+
if (!context.isValidConfigKey(key)) {
|
|
161
|
+
return Response.json({ error: 'Invalid config key' }, { status: 400 });
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
context.configManager.setDynamic(key, value);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
return jsonErrorResponse(error, { status: 400, fallbackMessage: 'Failed to set config' });
|
|
168
|
+
}
|
|
169
|
+
return Response.json({ success: true, key, value });
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
async function handleRegisterWatcher(context, req) {
|
|
174
|
+
const body = await context.parseJsonBody(req);
|
|
175
|
+
if (body instanceof Response)
|
|
176
|
+
return body;
|
|
177
|
+
const label = typeof body.label === 'string' && body.label.trim().length > 0 ? body.label.trim() : '';
|
|
178
|
+
const id = typeof body.id === 'string' && body.id.trim().length > 0
|
|
179
|
+
? body.id.trim()
|
|
180
|
+
: label
|
|
181
|
+
? `watcher-${label.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '')}`
|
|
182
|
+
: `watcher-${Date.now()}`;
|
|
183
|
+
const kind = typeof body.kind === 'string'
|
|
184
|
+
? body.kind
|
|
185
|
+
: typeof body.sourceKind === 'string'
|
|
186
|
+
? body.sourceKind === 'webhook'
|
|
187
|
+
? 'webhook'
|
|
188
|
+
: body.sourceKind === 'file'
|
|
189
|
+
? 'filesystem'
|
|
190
|
+
: body.sourceKind === 'stream'
|
|
191
|
+
? 'socket'
|
|
192
|
+
: body.sourceKind === 'api'
|
|
193
|
+
? 'integration'
|
|
194
|
+
: 'polling'
|
|
195
|
+
: 'polling';
|
|
196
|
+
const intervalMs = Number(body.intervalMs ?? context.configManager.get('watchers.pollIntervalMs') ?? 60_000);
|
|
197
|
+
if (!label) {
|
|
198
|
+
return Response.json({ error: 'Missing watcher label' }, { status: 400 });
|
|
199
|
+
}
|
|
200
|
+
const metadata = typeof body.metadata === 'object' && body.metadata !== null
|
|
201
|
+
? body.metadata
|
|
202
|
+
: {};
|
|
203
|
+
const sourceMetadata = {
|
|
204
|
+
...metadata,
|
|
205
|
+
...(typeof body.url === 'string' ? { url: body.url } : {}),
|
|
206
|
+
...(typeof body.method === 'string' ? { method: body.method.toUpperCase() } : {}),
|
|
207
|
+
...(typeof body.path === 'string' ? { path: body.path } : {}),
|
|
208
|
+
...(typeof body.endpoint === 'string' ? { endpoint: body.endpoint } : {}),
|
|
209
|
+
...(typeof body.address === 'string' ? { address: body.address } : {}),
|
|
210
|
+
...(typeof body.headers === 'object' && body.headers !== null ? { headers: body.headers } : {}),
|
|
211
|
+
};
|
|
212
|
+
const record = context.watcherRegistry.registerWatcher({
|
|
213
|
+
id,
|
|
214
|
+
label,
|
|
215
|
+
kind,
|
|
216
|
+
source: {
|
|
217
|
+
id: typeof body.sourceId === 'string' && body.sourceId.trim() ? body.sourceId.trim() : `source:${id}`,
|
|
218
|
+
kind: typeof body.sourceKind === 'string'
|
|
219
|
+
? body.sourceKind === 'webhook'
|
|
220
|
+
? 'webhook'
|
|
221
|
+
: body.sourceKind === 'file' || body.sourceKind === 'stream' || body.sourceKind === 'api'
|
|
222
|
+
? 'hook'
|
|
223
|
+
: 'watcher'
|
|
224
|
+
: 'watcher',
|
|
225
|
+
label,
|
|
226
|
+
enabled: true,
|
|
227
|
+
createdAt: Date.now(),
|
|
228
|
+
updatedAt: Date.now(),
|
|
229
|
+
metadata: sourceMetadata,
|
|
230
|
+
},
|
|
231
|
+
intervalMs,
|
|
232
|
+
metadata: sourceMetadata,
|
|
233
|
+
...(typeof body.run === 'string' ? { run: () => body.run } : {}),
|
|
234
|
+
});
|
|
235
|
+
return Response.json(record, { status: 201 });
|
|
236
|
+
}
|
|
237
|
+
async function handleUpdateWatcher(context, watcherId, req) {
|
|
238
|
+
const body = await context.parseJsonBody(req);
|
|
239
|
+
if (body instanceof Response)
|
|
240
|
+
return body;
|
|
241
|
+
const current = context.watcherRegistry.getWatcher(watcherId);
|
|
242
|
+
if (!current) {
|
|
243
|
+
return Response.json({ error: 'Unknown watcher' }, { status: 404 });
|
|
244
|
+
}
|
|
245
|
+
const nextSourceKind = typeof body.sourceKind === 'string'
|
|
246
|
+
? body.sourceKind === 'webhook'
|
|
247
|
+
? 'webhook'
|
|
248
|
+
: body.sourceKind === 'file' || body.sourceKind === 'stream' || body.sourceKind === 'api'
|
|
249
|
+
? 'hook'
|
|
250
|
+
: 'watcher'
|
|
251
|
+
: current.source.kind;
|
|
252
|
+
const updated = context.watcherRegistry.registerWatcher({
|
|
253
|
+
id: watcherId,
|
|
254
|
+
label: typeof body.label === 'string' ? body.label : current.label,
|
|
255
|
+
kind: typeof body.kind === 'string'
|
|
256
|
+
? body.kind
|
|
257
|
+
: current.kind,
|
|
258
|
+
source: {
|
|
259
|
+
...current.source,
|
|
260
|
+
...(typeof body.source === 'object' && body.source !== null ? body.source : {}),
|
|
261
|
+
kind: nextSourceKind,
|
|
262
|
+
...(typeof body.sourceId === 'string' && body.sourceId.trim().length > 0 ? { id: body.sourceId.trim() } : {}),
|
|
263
|
+
...(typeof body.label === 'string' && body.label.trim().length > 0 ? { label: body.label.trim() } : {}),
|
|
264
|
+
...(typeof body.enabled === 'boolean' ? { enabled: body.enabled } : {}),
|
|
265
|
+
metadata: {
|
|
266
|
+
...current.source.metadata,
|
|
267
|
+
...(typeof body.url === 'string' ? { url: body.url } : {}),
|
|
268
|
+
...(typeof body.method === 'string' ? { method: body.method.toUpperCase() } : {}),
|
|
269
|
+
...(typeof body.path === 'string' ? { path: body.path } : {}),
|
|
270
|
+
...(typeof body.endpoint === 'string' ? { endpoint: body.endpoint } : {}),
|
|
271
|
+
...(typeof body.address === 'string' ? { address: body.address } : {}),
|
|
272
|
+
...(typeof body.headers === 'object' && body.headers !== null ? { headers: body.headers } : {}),
|
|
273
|
+
...(typeof body.metadata === 'object' && body.metadata !== null ? body.metadata : {}),
|
|
274
|
+
},
|
|
275
|
+
updatedAt: Date.now(),
|
|
276
|
+
},
|
|
277
|
+
intervalMs: typeof body.intervalMs === 'number' ? body.intervalMs : (current.intervalMs ?? 60_000),
|
|
278
|
+
metadata: typeof body.metadata === 'object' && body.metadata !== null ? body.metadata : current.metadata,
|
|
279
|
+
});
|
|
280
|
+
return Response.json(updated);
|
|
281
|
+
}
|
|
282
|
+
async function handleWatcherAction(context, watcherId, action) {
|
|
283
|
+
if (action === 'start') {
|
|
284
|
+
const watcher = context.watcherRegistry.startWatcher(watcherId);
|
|
285
|
+
return watcher
|
|
286
|
+
? Response.json(watcher)
|
|
287
|
+
: Response.json({ error: 'Unknown watcher' }, { status: 404 });
|
|
288
|
+
}
|
|
289
|
+
if (action === 'stop') {
|
|
290
|
+
const watcher = context.watcherRegistry.stopWatcher(watcherId, 'operator-stop');
|
|
291
|
+
return watcher
|
|
292
|
+
? Response.json(watcher)
|
|
293
|
+
: Response.json({ error: 'Unknown watcher' }, { status: 404 });
|
|
294
|
+
}
|
|
295
|
+
const watcher = await context.watcherRegistry.runWatcherNow(watcherId);
|
|
296
|
+
return watcher
|
|
297
|
+
? Response.json(watcher)
|
|
298
|
+
: Response.json({ error: 'Unknown watcher' }, { status: 404 });
|
|
299
|
+
}
|
|
300
|
+
async function handleApprovalAction(context, approvalId, action, req) {
|
|
301
|
+
const body = await context.parseOptionalJsonBody(req);
|
|
302
|
+
const payload = body instanceof Response || body === null ? {} : body;
|
|
303
|
+
const actor = context.requireAuthenticatedSession(req)?.username ?? 'operator';
|
|
304
|
+
const note = typeof payload.note === 'string' ? payload.note : undefined;
|
|
305
|
+
if (action === 'claim') {
|
|
306
|
+
const approval = await context.approvalBroker.claimApproval(approvalId, actor, 'web', note);
|
|
307
|
+
return approval
|
|
308
|
+
? context.recordApiResponse(req, `/api/approvals/${approvalId}/${action}`, Response.json({ approval }))
|
|
309
|
+
: context.recordApiResponse(req, `/api/approvals/${approvalId}/${action}`, Response.json({ error: 'Unknown approval' }, { status: 404 }));
|
|
310
|
+
}
|
|
311
|
+
if (action === 'cancel') {
|
|
312
|
+
const approval = await context.approvalBroker.cancelApproval(approvalId, actor, 'web', note);
|
|
313
|
+
return approval
|
|
314
|
+
? context.recordApiResponse(req, `/api/approvals/${approvalId}/${action}`, Response.json({ approval }))
|
|
315
|
+
: context.recordApiResponse(req, `/api/approvals/${approvalId}/${action}`, Response.json({ error: 'Unknown approval' }, { status: 404 }));
|
|
316
|
+
}
|
|
317
|
+
const approval = await context.approvalBroker.resolveApproval(approvalId, {
|
|
318
|
+
approved: action === 'approve',
|
|
319
|
+
remember: typeof payload.remember === 'boolean' ? payload.remember : false,
|
|
320
|
+
actor,
|
|
321
|
+
actorSurface: 'web',
|
|
322
|
+
note,
|
|
323
|
+
});
|
|
324
|
+
return approval
|
|
325
|
+
? context.recordApiResponse(req, `/api/approvals/${approvalId}/${action}`, Response.json({ approval }))
|
|
326
|
+
: context.recordApiResponse(req, `/api/approvals/${approvalId}/${action}`, Response.json({ error: 'Unknown approval' }, { status: 404 }));
|
|
327
|
+
}
|
package/dist/tasks.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DaemonApiRouteHandlers } from './context.js';
|
|
2
|
+
export declare function dispatchTaskRoutes(req: Request, handlers: Pick<DaemonApiRouteHandlers, 'getIntegrationTasks' | 'getRuntimeTask' | 'runtimeTaskAction' | 'getTaskStatus' | 'postTask'>): Promise<Response | null>;
|
|
3
|
+
//# sourceMappingURL=tasks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../src/tasks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAE3D,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,IAAI,CACZ,sBAAsB,EACpB,qBAAqB,GACrB,gBAAgB,GAChB,mBAAmB,GACnB,eAAe,GACf,UAAU,CACb,GACA,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAqB1B"}
|
package/dist/tasks.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export async function dispatchTaskRoutes(req, handlers) {
|
|
2
|
+
const url = new URL(req.url);
|
|
3
|
+
const { pathname } = url;
|
|
4
|
+
const method = req.method;
|
|
5
|
+
if (pathname === '/task' && method === 'POST')
|
|
6
|
+
return handlers.postTask(req);
|
|
7
|
+
if (pathname === '/task' && method === 'GET')
|
|
8
|
+
return null;
|
|
9
|
+
if (pathname === '/api/tasks' && method === 'GET')
|
|
10
|
+
return handlers.getIntegrationTasks();
|
|
11
|
+
const taskDetailMatch = pathname.match(/^\/api\/tasks\/([^/]+)$/);
|
|
12
|
+
if (taskDetailMatch && method === 'GET')
|
|
13
|
+
return handlers.getRuntimeTask(taskDetailMatch[1]);
|
|
14
|
+
const taskActionMatch = pathname.match(/^\/api\/tasks\/([^/]+)\/(cancel|retry)$/);
|
|
15
|
+
if (taskActionMatch && method === 'POST') {
|
|
16
|
+
return handlers.runtimeTaskAction(taskActionMatch[1], taskActionMatch[2], req);
|
|
17
|
+
}
|
|
18
|
+
const taskStatusMatch = pathname.match(/^\/task\/([^/]+)$/);
|
|
19
|
+
if (taskStatusMatch && method === 'GET')
|
|
20
|
+
return handlers.getTaskStatus(taskStatusMatch[1]);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { DaemonApiRouteHandlers } from './context.js';
|
|
2
|
+
import { type AuthenticatedPrincipal } from './http-policy.js';
|
|
3
|
+
import type { RuntimeEventDomain } from '@pellux/goodvibes-contracts';
|
|
4
|
+
type TelemetrySeverity = 'debug' | 'info' | 'warn' | 'error';
|
|
5
|
+
type TelemetryViewMode = 'safe' | 'raw';
|
|
6
|
+
interface TelemetryFilter {
|
|
7
|
+
readonly limit?: number;
|
|
8
|
+
readonly since?: number;
|
|
9
|
+
readonly until?: number;
|
|
10
|
+
readonly domains?: readonly RuntimeEventDomain[];
|
|
11
|
+
readonly eventTypes?: readonly string[];
|
|
12
|
+
readonly severity?: TelemetrySeverity;
|
|
13
|
+
readonly traceId?: string;
|
|
14
|
+
readonly sessionId?: string;
|
|
15
|
+
readonly turnId?: string;
|
|
16
|
+
readonly agentId?: string;
|
|
17
|
+
readonly taskId?: string;
|
|
18
|
+
readonly cursor?: string;
|
|
19
|
+
readonly view?: TelemetryViewMode;
|
|
20
|
+
}
|
|
21
|
+
interface TelemetryApiLike {
|
|
22
|
+
getSnapshot(filter: TelemetryFilter, view: TelemetryViewMode, rawAccessible: boolean): {
|
|
23
|
+
readonly generatedAt: number;
|
|
24
|
+
readonly view: TelemetryViewMode;
|
|
25
|
+
readonly rawAccessible: boolean;
|
|
26
|
+
readonly runtime: unknown;
|
|
27
|
+
readonly sessionMetrics: unknown;
|
|
28
|
+
readonly aggregates: unknown;
|
|
29
|
+
};
|
|
30
|
+
listEventPage(filter: TelemetryFilter, view: TelemetryViewMode, rawAccessible: boolean): unknown;
|
|
31
|
+
listErrorPage(filter: TelemetryFilter, view: TelemetryViewMode, rawAccessible: boolean): unknown;
|
|
32
|
+
listSpanPage(filter: TelemetryFilter, view: TelemetryViewMode, rawAccessible: boolean): unknown;
|
|
33
|
+
createStream(req: Request, filter: TelemetryFilter, view: TelemetryViewMode, rawAccessible: boolean): Response;
|
|
34
|
+
buildOtlpTraceDocument(filter: TelemetryFilter, view: TelemetryViewMode): unknown;
|
|
35
|
+
buildOtlpLogDocument(filter: TelemetryFilter, view: TelemetryViewMode): unknown;
|
|
36
|
+
buildOtlpMetricDocument(): unknown;
|
|
37
|
+
}
|
|
38
|
+
interface TelemetryRouteContext {
|
|
39
|
+
readonly telemetryApi: TelemetryApiLike | null;
|
|
40
|
+
readonly resolveAuthenticatedPrincipal: (req: Request) => AuthenticatedPrincipal | null;
|
|
41
|
+
}
|
|
42
|
+
export declare function createDaemonTelemetryRouteHandlers(context: TelemetryRouteContext): Pick<DaemonApiRouteHandlers, 'getTelemetrySnapshot' | 'getTelemetryEvents' | 'getTelemetryErrors' | 'getTelemetryTraces' | 'getTelemetryMetrics' | 'createTelemetryEventStream' | 'getTelemetryOtlpTraces' | 'getTelemetryOtlpLogs' | 'getTelemetryOtlpMetrics'>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=telemetry-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-routes.d.ts","sourceRoot":"","sources":["../src/telemetry-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { buildMissingScopeBody } from './http-policy.js';
|
|
2
|
+
function parseNumber(value) {
|
|
3
|
+
if (value === null || value.trim().length === 0)
|
|
4
|
+
return undefined;
|
|
5
|
+
const parsed = Number(value);
|
|
6
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
7
|
+
}
|
|
8
|
+
function parseCsv(value) {
|
|
9
|
+
if (!value)
|
|
10
|
+
return undefined;
|
|
11
|
+
const parsed = value
|
|
12
|
+
.split(',')
|
|
13
|
+
.map((entry) => entry.trim())
|
|
14
|
+
.filter(Boolean);
|
|
15
|
+
return parsed.length > 0 ? parsed : undefined;
|
|
16
|
+
}
|
|
17
|
+
function parseSeverity(value) {
|
|
18
|
+
return value === 'debug' || value === 'info' || value === 'warn' || value === 'error'
|
|
19
|
+
? value
|
|
20
|
+
: undefined;
|
|
21
|
+
}
|
|
22
|
+
function parseView(value) {
|
|
23
|
+
return value === 'safe' || value === 'raw' ? value : undefined;
|
|
24
|
+
}
|
|
25
|
+
function buildFilter(url) {
|
|
26
|
+
return {
|
|
27
|
+
...(parseNumber(url.searchParams.get('limit')) !== undefined ? { limit: parseNumber(url.searchParams.get('limit')) } : {}),
|
|
28
|
+
...(parseNumber(url.searchParams.get('since')) !== undefined ? { since: parseNumber(url.searchParams.get('since')) } : {}),
|
|
29
|
+
...(parseNumber(url.searchParams.get('until')) !== undefined ? { until: parseNumber(url.searchParams.get('until')) } : {}),
|
|
30
|
+
...(parseCsv(url.searchParams.get('domains')) ? { domains: parseCsv(url.searchParams.get('domains')) } : {}),
|
|
31
|
+
...(parseCsv(url.searchParams.get('types')) ? { eventTypes: parseCsv(url.searchParams.get('types')) } : {}),
|
|
32
|
+
...(parseSeverity(url.searchParams.get('severity')) ? { severity: parseSeverity(url.searchParams.get('severity')) } : {}),
|
|
33
|
+
...(url.searchParams.get('traceId') ? { traceId: url.searchParams.get('traceId') ?? undefined } : {}),
|
|
34
|
+
...(url.searchParams.get('sessionId') ? { sessionId: url.searchParams.get('sessionId') ?? undefined } : {}),
|
|
35
|
+
...(url.searchParams.get('turnId') ? { turnId: url.searchParams.get('turnId') ?? undefined } : {}),
|
|
36
|
+
...(url.searchParams.get('agentId') ? { agentId: url.searchParams.get('agentId') ?? undefined } : {}),
|
|
37
|
+
...(url.searchParams.get('taskId') ? { taskId: url.searchParams.get('taskId') ?? undefined } : {}),
|
|
38
|
+
...(url.searchParams.get('cursor') ? { cursor: url.searchParams.get('cursor') ?? undefined } : {}),
|
|
39
|
+
...(parseView(url.searchParams.get('view')) ? { view: parseView(url.searchParams.get('view')) } : {}),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function unavailable() {
|
|
43
|
+
return Response.json({
|
|
44
|
+
error: 'Telemetry API unavailable',
|
|
45
|
+
code: 'TELEMETRY_UNAVAILABLE',
|
|
46
|
+
category: 'service',
|
|
47
|
+
source: 'runtime',
|
|
48
|
+
recoverable: true,
|
|
49
|
+
hint: 'Start the daemon runtime and ensure the runtime store is available before reading telemetry.',
|
|
50
|
+
status: 503,
|
|
51
|
+
}, { status: 503 });
|
|
52
|
+
}
|
|
53
|
+
function invalidCursor(error) {
|
|
54
|
+
return Response.json({
|
|
55
|
+
error: error instanceof Error ? error.message : 'Invalid telemetry cursor',
|
|
56
|
+
code: 'INVALID_CURSOR',
|
|
57
|
+
category: 'bad_request',
|
|
58
|
+
source: 'runtime',
|
|
59
|
+
recoverable: false,
|
|
60
|
+
hint: 'Use the nextCursor returned by the previous telemetry page, or omit cursor to start from the newest records.',
|
|
61
|
+
status: 400,
|
|
62
|
+
}, { status: 400 });
|
|
63
|
+
}
|
|
64
|
+
function authenticateTelemetryRequest(context, req, requestedView) {
|
|
65
|
+
const principal = context.resolveAuthenticatedPrincipal(req);
|
|
66
|
+
if (!principal) {
|
|
67
|
+
return Response.json({
|
|
68
|
+
error: 'Authentication required for telemetry access',
|
|
69
|
+
code: 'AUTH_REQUIRED',
|
|
70
|
+
category: 'authentication',
|
|
71
|
+
source: 'runtime',
|
|
72
|
+
recoverable: false,
|
|
73
|
+
hint: 'Authenticate with the operator shared token or an authenticated user session before calling telemetry APIs.',
|
|
74
|
+
status: 401,
|
|
75
|
+
}, { status: 401 });
|
|
76
|
+
}
|
|
77
|
+
const missingRead = buildMissingScopeBody('telemetry access', ['read:telemetry'], principal.scopes);
|
|
78
|
+
if (missingRead) {
|
|
79
|
+
return Response.json({
|
|
80
|
+
error: missingRead.error,
|
|
81
|
+
code: 'MISSING_SCOPE',
|
|
82
|
+
category: 'authorization',
|
|
83
|
+
source: 'permission',
|
|
84
|
+
recoverable: false,
|
|
85
|
+
hint: 'Use a token or session with the read:telemetry scope, or elevate to an admin/shared-token session.',
|
|
86
|
+
status: 403,
|
|
87
|
+
detail: JSON.stringify(missingRead),
|
|
88
|
+
}, { status: 403 });
|
|
89
|
+
}
|
|
90
|
+
const rawAccessible = principal.admin || principal.scopes.includes('read:telemetry-sensitive');
|
|
91
|
+
if (requestedView === 'raw' && !rawAccessible) {
|
|
92
|
+
return Response.json({
|
|
93
|
+
error: 'Raw telemetry view requires elevated telemetry scope',
|
|
94
|
+
code: 'MISSING_SCOPE',
|
|
95
|
+
category: 'authorization',
|
|
96
|
+
source: 'permission',
|
|
97
|
+
recoverable: false,
|
|
98
|
+
hint: 'Use an admin/shared-token session or a token granted read:telemetry-sensitive to access raw telemetry payloads.',
|
|
99
|
+
status: 403,
|
|
100
|
+
}, { status: 403 });
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
principal,
|
|
104
|
+
view: requestedView,
|
|
105
|
+
rawAccessible,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
export function createDaemonTelemetryRouteHandlers(context) {
|
|
109
|
+
return {
|
|
110
|
+
getTelemetrySnapshot: (req) => {
|
|
111
|
+
if (!context.telemetryApi)
|
|
112
|
+
return unavailable();
|
|
113
|
+
const url = new URL(req.url);
|
|
114
|
+
const filter = buildFilter(url);
|
|
115
|
+
const access = authenticateTelemetryRequest(context, req, filter.view ?? 'safe');
|
|
116
|
+
if (access instanceof Response)
|
|
117
|
+
return access;
|
|
118
|
+
return Response.json(context.telemetryApi.getSnapshot(filter, access.view, access.rawAccessible));
|
|
119
|
+
},
|
|
120
|
+
getTelemetryEvents: (req) => {
|
|
121
|
+
if (!context.telemetryApi)
|
|
122
|
+
return unavailable();
|
|
123
|
+
const url = new URL(req.url);
|
|
124
|
+
const filter = buildFilter(url);
|
|
125
|
+
const access = authenticateTelemetryRequest(context, req, filter.view ?? 'safe');
|
|
126
|
+
if (access instanceof Response)
|
|
127
|
+
return access;
|
|
128
|
+
try {
|
|
129
|
+
return Response.json(context.telemetryApi.listEventPage(filter, access.view, access.rawAccessible));
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
return invalidCursor(error);
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
getTelemetryErrors: (req) => {
|
|
136
|
+
if (!context.telemetryApi)
|
|
137
|
+
return unavailable();
|
|
138
|
+
const url = new URL(req.url);
|
|
139
|
+
const filter = buildFilter(url);
|
|
140
|
+
const access = authenticateTelemetryRequest(context, req, filter.view ?? 'safe');
|
|
141
|
+
if (access instanceof Response)
|
|
142
|
+
return access;
|
|
143
|
+
try {
|
|
144
|
+
return Response.json(context.telemetryApi.listErrorPage(filter, access.view, access.rawAccessible));
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
return invalidCursor(error);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
getTelemetryTraces: (req) => {
|
|
151
|
+
if (!context.telemetryApi)
|
|
152
|
+
return unavailable();
|
|
153
|
+
const url = new URL(req.url);
|
|
154
|
+
const filter = buildFilter(url);
|
|
155
|
+
const access = authenticateTelemetryRequest(context, req, filter.view ?? 'safe');
|
|
156
|
+
if (access instanceof Response)
|
|
157
|
+
return access;
|
|
158
|
+
try {
|
|
159
|
+
return Response.json(context.telemetryApi.listSpanPage(filter, access.view, access.rawAccessible));
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
return invalidCursor(error);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
getTelemetryMetrics: (req) => {
|
|
166
|
+
if (!context.telemetryApi)
|
|
167
|
+
return unavailable();
|
|
168
|
+
const url = new URL(req.url);
|
|
169
|
+
const filter = buildFilter(url);
|
|
170
|
+
const access = authenticateTelemetryRequest(context, req, filter.view ?? 'safe');
|
|
171
|
+
if (access instanceof Response)
|
|
172
|
+
return access;
|
|
173
|
+
const snapshot = context.telemetryApi.getSnapshot(filter, access.view, access.rawAccessible);
|
|
174
|
+
return Response.json({
|
|
175
|
+
version: 1,
|
|
176
|
+
generatedAt: snapshot.generatedAt,
|
|
177
|
+
view: snapshot.view,
|
|
178
|
+
rawAccessible: snapshot.rawAccessible,
|
|
179
|
+
runtime: snapshot.runtime,
|
|
180
|
+
sessionMetrics: snapshot.sessionMetrics,
|
|
181
|
+
aggregates: snapshot.aggregates,
|
|
182
|
+
});
|
|
183
|
+
},
|
|
184
|
+
createTelemetryEventStream: (req) => {
|
|
185
|
+
if (!context.telemetryApi)
|
|
186
|
+
return unavailable();
|
|
187
|
+
const filter = buildFilter(new URL(req.url));
|
|
188
|
+
const access = authenticateTelemetryRequest(context, req, filter.view ?? 'safe');
|
|
189
|
+
if (access instanceof Response)
|
|
190
|
+
return access;
|
|
191
|
+
try {
|
|
192
|
+
return context.telemetryApi.createStream(req, filter, access.view, access.rawAccessible);
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
return invalidCursor(error);
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
getTelemetryOtlpTraces: (req) => {
|
|
199
|
+
if (!context.telemetryApi)
|
|
200
|
+
return unavailable();
|
|
201
|
+
const url = new URL(req.url);
|
|
202
|
+
const filter = buildFilter(url);
|
|
203
|
+
const access = authenticateTelemetryRequest(context, req, filter.view ?? 'safe');
|
|
204
|
+
if (access instanceof Response)
|
|
205
|
+
return access;
|
|
206
|
+
return Response.json(context.telemetryApi.buildOtlpTraceDocument(filter, access.view));
|
|
207
|
+
},
|
|
208
|
+
getTelemetryOtlpLogs: (req) => {
|
|
209
|
+
if (!context.telemetryApi)
|
|
210
|
+
return unavailable();
|
|
211
|
+
const url = new URL(req.url);
|
|
212
|
+
const filter = buildFilter(url);
|
|
213
|
+
const access = authenticateTelemetryRequest(context, req, filter.view ?? 'safe');
|
|
214
|
+
if (access instanceof Response)
|
|
215
|
+
return access;
|
|
216
|
+
return Response.json(context.telemetryApi.buildOtlpLogDocument(filter, access.view));
|
|
217
|
+
},
|
|
218
|
+
getTelemetryOtlpMetrics: (req) => {
|
|
219
|
+
if (!context.telemetryApi)
|
|
220
|
+
return unavailable();
|
|
221
|
+
const access = authenticateTelemetryRequest(context, req, 'safe');
|
|
222
|
+
if (access instanceof Response)
|
|
223
|
+
return access;
|
|
224
|
+
return Response.json(context.telemetryApi.buildOtlpMetricDocument());
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|