@pellux/goodvibes-daemon-sdk 0.18.3 → 0.30.1
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 +13 -7
- package/dist/api-router.d.ts +8 -1
- package/dist/api-router.d.ts.map +1 -1
- package/dist/api-router.js +12 -3
- package/dist/artifact-upload.d.ts +26 -0
- package/dist/artifact-upload.d.ts.map +1 -0
- package/dist/artifact-upload.js +535 -0
- package/dist/automation.d.ts +2 -2
- package/dist/automation.d.ts.map +1 -1
- package/dist/channel-route-types.d.ts.map +1 -1
- package/dist/channel-routes.d.ts +2 -2
- package/dist/channel-routes.d.ts.map +1 -1
- package/dist/channel-routes.js +28 -3
- package/dist/context.d.ts +151 -51
- package/dist/context.d.ts.map +1 -1
- package/dist/control-routes.d.ts +2 -2
- package/dist/control-routes.d.ts.map +1 -1
- package/dist/error-response.d.ts.map +1 -1
- package/dist/error-response.js +172 -12
- package/dist/http-policy.d.ts +1 -1
- package/dist/http-policy.d.ts.map +1 -1
- package/dist/http-policy.js +0 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/integration-route-types.d.ts +3 -1
- package/dist/integration-route-types.d.ts.map +1 -1
- package/dist/integration-routes.d.ts +2 -2
- package/dist/integration-routes.d.ts.map +1 -1
- package/dist/integration-routes.js +3 -0
- package/dist/knowledge-refinement-routes.d.ts +4 -0
- package/dist/knowledge-refinement-routes.d.ts.map +1 -0
- package/dist/knowledge-refinement-routes.js +58 -0
- package/dist/knowledge-route-types.d.ts +11 -1
- package/dist/knowledge-route-types.d.ts.map +1 -1
- package/dist/knowledge-routes.d.ts +2 -2
- package/dist/knowledge-routes.d.ts.map +1 -1
- package/dist/knowledge-routes.js +156 -13
- package/dist/media-route-types.d.ts +10 -0
- package/dist/media-route-types.d.ts.map +1 -1
- package/dist/media-routes.d.ts +2 -2
- package/dist/media-routes.d.ts.map +1 -1
- package/dist/media-routes.js +134 -15
- package/dist/operator.d.ts +2 -2
- package/dist/operator.d.ts.map +1 -1
- package/dist/operator.js +49 -15
- package/dist/otlp-protobuf.d.ts +3 -0
- package/dist/otlp-protobuf.d.ts.map +1 -0
- package/dist/otlp-protobuf.js +977 -0
- package/dist/remote-routes.d.ts +2 -2
- package/dist/remote-routes.d.ts.map +1 -1
- package/dist/remote-routes.js +146 -13
- package/dist/remote.d.ts +2 -2
- package/dist/remote.d.ts.map +1 -1
- package/dist/route-helpers.d.ts +8 -0
- package/dist/route-helpers.d.ts.map +1 -1
- package/dist/route-helpers.js +24 -0
- package/dist/runtime-automation-routes.d.ts +2 -2
- package/dist/runtime-automation-routes.d.ts.map +1 -1
- package/dist/runtime-automation-routes.js +4 -1
- package/dist/runtime-route-types.d.ts +46 -3
- package/dist/runtime-route-types.d.ts.map +1 -1
- package/dist/runtime-routes.d.ts +2 -2
- package/dist/runtime-routes.d.ts.map +1 -1
- package/dist/runtime-routes.js +1 -0
- package/dist/runtime-session-routes.d.ts +13 -3
- package/dist/runtime-session-routes.d.ts.map +1 -1
- package/dist/runtime-session-routes.js +102 -10
- package/dist/sessions.d.ts +2 -2
- package/dist/sessions.d.ts.map +1 -1
- package/dist/sessions.js +3 -0
- package/dist/system-route-types.d.ts +19 -0
- package/dist/system-route-types.d.ts.map +1 -1
- package/dist/system-routes.d.ts +2 -2
- package/dist/system-routes.d.ts.map +1 -1
- package/dist/system-routes.js +18 -0
- package/dist/tasks.d.ts +2 -2
- package/dist/tasks.d.ts.map +1 -1
- package/dist/telemetry-routes.d.ts +25 -2
- package/dist/telemetry-routes.d.ts.map +1 -1
- package/dist/telemetry-routes.js +131 -15
- package/package.json +128 -5
package/dist/knowledge-routes.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { buildMissingScopeBody, resolvePrivateHostFetchOptions, } from './http-policy.js';
|
|
2
|
+
import { GoodVibesSdkError, DaemonErrorCategory } from '@pellux/goodvibes-errors';
|
|
2
3
|
import { jsonErrorResponse, summarizeErrorForRecord } from './error-response.js';
|
|
4
|
+
import { createArtifactFromUploadRequest, isArtifactUploadRequest } from './artifact-upload.js';
|
|
5
|
+
import { readBoundedPositiveInteger, readOptionalBoundedInteger } from './route-helpers.js';
|
|
6
|
+
import { createDaemonKnowledgeRefinementRouteHandlers } from './knowledge-refinement-routes.js';
|
|
3
7
|
export function createDaemonKnowledgeRouteHandlers(context) {
|
|
4
8
|
return {
|
|
5
9
|
getKnowledgeStatus: async () => Response.json(await context.knowledgeService.getStatus()),
|
|
@@ -26,6 +30,13 @@ export function createDaemonKnowledgeRouteHandlers(context) {
|
|
|
26
30
|
: Response.json({ error: 'Unknown knowledge connector' }, { status: 404 });
|
|
27
31
|
},
|
|
28
32
|
getKnowledgeProjectionTargets: async (url) => Response.json({ targets: await context.knowledgeService.listProjectionTargets(readLimit(url, 25)) }),
|
|
33
|
+
getKnowledgeMap: async (url) => Response.json(await context.knowledgeService.map({
|
|
34
|
+
limit: readLimit(url, 500),
|
|
35
|
+
includeSources: readBooleanQuery(url, 'includeSources'),
|
|
36
|
+
includeIssues: readBooleanQuery(url, 'includeIssues'),
|
|
37
|
+
includeGenerated: readBooleanQuery(url, 'includeGenerated'),
|
|
38
|
+
...readKnowledgeMapFilters(url),
|
|
39
|
+
})),
|
|
29
40
|
getKnowledgeGraphqlSchema: () => Response.json({
|
|
30
41
|
language: 'graphql',
|
|
31
42
|
domain: 'knowledge',
|
|
@@ -95,6 +106,7 @@ export function createDaemonKnowledgeRouteHandlers(context) {
|
|
|
95
106
|
const jobId = url.searchParams.get('jobId') ?? undefined;
|
|
96
107
|
return Response.json({ runs: context.knowledgeService.listJobRuns(readLimit(url, 25), jobId) });
|
|
97
108
|
},
|
|
109
|
+
...createDaemonKnowledgeRefinementRouteHandlers(context),
|
|
98
110
|
getKnowledgeSchedules: (url) => Response.json({ schedules: context.knowledgeService.listSchedules(readLimit(url, 100)) }),
|
|
99
111
|
getKnowledgeSchedule: (id) => {
|
|
100
112
|
const schedule = context.knowledgeService.getSchedule(id);
|
|
@@ -104,11 +116,14 @@ export function createDaemonKnowledgeRouteHandlers(context) {
|
|
|
104
116
|
},
|
|
105
117
|
postKnowledgeIngestUrl: async (request) => handleKnowledgeIngestUrl(context, request),
|
|
106
118
|
postKnowledgeIngestArtifact: async (request) => handleKnowledgeIngestArtifact(context, request),
|
|
119
|
+
postKnowledgeSyncBrowserHistory: async (request) => handleKnowledgeSyncBrowserHistory(context, request),
|
|
107
120
|
postKnowledgeImportBookmarks: async (request) => handleKnowledgeImportBookmarks(context, request),
|
|
108
121
|
postKnowledgeImportUrls: async (request) => handleKnowledgeImportUrls(context, request),
|
|
109
122
|
postKnowledgeIngestConnector: async (request) => handleKnowledgeIngestConnector(context, request),
|
|
110
123
|
postKnowledgeSearch: async (request) => handleKnowledgeSearch(context, request),
|
|
124
|
+
postKnowledgeAsk: async (request) => handleKnowledgeAsk(context, request),
|
|
111
125
|
postKnowledgePacket: async (request) => handleKnowledgePacket(context, request),
|
|
126
|
+
postKnowledgeReviewIssue: async (id, request) => handleKnowledgeReviewIssue(context, id, request),
|
|
112
127
|
postKnowledgeDecideCandidate: async (id, request) => handleKnowledgeDecideCandidate(context, id, request),
|
|
113
128
|
postKnowledgeRunJob: async (jobId, request) => handleKnowledgeRunJob(context, jobId, request),
|
|
114
129
|
postKnowledgeLint: async (request) => {
|
|
@@ -140,7 +155,39 @@ export function createDaemonKnowledgeRouteHandlers(context) {
|
|
|
140
155
|
};
|
|
141
156
|
}
|
|
142
157
|
function readLimit(url, fallback) {
|
|
143
|
-
return
|
|
158
|
+
return readBoundedPositiveInteger(url.searchParams.get('limit'), fallback, 1_000);
|
|
159
|
+
}
|
|
160
|
+
function readBooleanQuery(url, key) {
|
|
161
|
+
const raw = url.searchParams.get(key);
|
|
162
|
+
if (raw === null || raw.trim() === '')
|
|
163
|
+
return undefined;
|
|
164
|
+
return raw === '1' || raw.toLowerCase() === 'true' || raw.toLowerCase() === 'yes';
|
|
165
|
+
}
|
|
166
|
+
function readKnowledgeMapFilters(url) {
|
|
167
|
+
const minConfidence = readOptionalBoundedInteger(url.searchParams.get('minConfidence'), 0, 100);
|
|
168
|
+
return {
|
|
169
|
+
...(url.searchParams.get('query') ? { query: url.searchParams.get('query') } : {}),
|
|
170
|
+
...(Number.isFinite(minConfidence) ? { minConfidence } : {}),
|
|
171
|
+
recordKinds: readStringList(url, 'recordKinds', 'recordKind'),
|
|
172
|
+
ids: readStringList(url, 'ids', 'id'),
|
|
173
|
+
linkedToIds: readStringList(url, 'linkedToIds', 'linkedToId'),
|
|
174
|
+
nodeKinds: readStringList(url, 'nodeKinds', 'nodeKind'),
|
|
175
|
+
sourceTypes: readStringList(url, 'sourceTypes', 'sourceType'),
|
|
176
|
+
sourceStatuses: readStringList(url, 'sourceStatuses', 'sourceStatus'),
|
|
177
|
+
nodeStatuses: readStringList(url, 'nodeStatuses', 'nodeStatus'),
|
|
178
|
+
issueCodes: readStringList(url, 'issueCodes', 'issueCode'),
|
|
179
|
+
issueStatuses: readStringList(url, 'issueStatuses', 'issueStatus'),
|
|
180
|
+
issueSeverities: readStringList(url, 'issueSeverities', 'issueSeverity'),
|
|
181
|
+
edgeRelations: readStringList(url, 'edgeRelations', 'edgeRelation'),
|
|
182
|
+
tags: readStringList(url, 'tags', 'tag'),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function readStringList(url, ...names) {
|
|
186
|
+
return names
|
|
187
|
+
.flatMap((name) => url.searchParams.getAll(name))
|
|
188
|
+
.flatMap((value) => value.split(','))
|
|
189
|
+
.map((value) => value.trim())
|
|
190
|
+
.filter(Boolean);
|
|
144
191
|
}
|
|
145
192
|
function readKnowledgeProjectionRequest(body) {
|
|
146
193
|
const rawKind = typeof body.kind === 'string' ? body.kind.trim().toLowerCase() : '';
|
|
@@ -148,11 +195,15 @@ function readKnowledgeProjectionRequest(body) {
|
|
|
148
195
|
&& rawKind !== 'bundle'
|
|
149
196
|
&& rawKind !== 'source'
|
|
150
197
|
&& rawKind !== 'node'
|
|
151
|
-
&& rawKind !== 'issue'
|
|
152
|
-
|
|
198
|
+
&& rawKind !== 'issue'
|
|
199
|
+
&& rawKind !== 'dashboard'
|
|
200
|
+
&& rawKind !== 'rollup') {
|
|
201
|
+
return Response.json({
|
|
202
|
+
error: 'Projection kind must be one of overview, bundle, source, node, issue, dashboard, or rollup.',
|
|
203
|
+
}, { status: 400 });
|
|
153
204
|
}
|
|
154
205
|
const id = typeof body.id === 'string' ? body.id.trim() : '';
|
|
155
|
-
if ((rawKind === 'source' || rawKind === 'node' || rawKind === 'issue') && !id) {
|
|
206
|
+
if ((rawKind === 'source' || rawKind === 'node' || rawKind === 'issue' || rawKind === 'rollup') && !id) {
|
|
156
207
|
return Response.json({ error: `Projection kind ${rawKind} requires id.` }, { status: 400 });
|
|
157
208
|
}
|
|
158
209
|
return {
|
|
@@ -176,18 +227,18 @@ function readKnowledgeSchedule(context, value) {
|
|
|
176
227
|
if (typeof schedule.interval === 'string') {
|
|
177
228
|
return context.normalizeEverySchedule(schedule.interval, typeof schedule.anchorAt === 'number' ? schedule.anchorAt : undefined);
|
|
178
229
|
}
|
|
179
|
-
throw new
|
|
230
|
+
throw new GoodVibesSdkError('Invalid schedule: every schedule requires intervalMs or an interval object. Set schedule.intervalMs (number, in milliseconds) or schedule.interval.', { category: DaemonErrorCategory.BAD_REQUEST, source: 'contract', recoverable: false });
|
|
180
231
|
case 'cron':
|
|
181
232
|
if (typeof schedule.expression !== 'string' || !schedule.expression.trim()) {
|
|
182
|
-
throw new
|
|
233
|
+
throw new GoodVibesSdkError('Invalid schedule: cron schedule requires a cron expression string in schedule.expression (e.g. "0 9 * * 1-5").', { category: DaemonErrorCategory.BAD_REQUEST, source: 'contract', recoverable: false });
|
|
183
234
|
}
|
|
184
235
|
return context.normalizeCronSchedule(schedule.expression, typeof schedule.timezone === 'string' ? schedule.timezone : undefined, schedule.staggerMs);
|
|
185
236
|
case 'at':
|
|
186
237
|
if (typeof schedule.at !== 'number')
|
|
187
|
-
throw new
|
|
238
|
+
throw new GoodVibesSdkError('Invalid schedule: at schedule requires schedule.at as a Unix timestamp in milliseconds.', { category: DaemonErrorCategory.BAD_REQUEST, source: 'contract', recoverable: false });
|
|
188
239
|
return context.normalizeAtSchedule(schedule.at);
|
|
189
240
|
default:
|
|
190
|
-
throw new
|
|
241
|
+
throw new GoodVibesSdkError('Invalid schedule kind. Expected schedule.kind to be one of: "at", "every", or "cron".', { category: DaemonErrorCategory.BAD_REQUEST, source: 'contract', recoverable: false });
|
|
191
242
|
}
|
|
192
243
|
}
|
|
193
244
|
catch (error) {
|
|
@@ -311,7 +362,7 @@ async function handleKnowledgeIngestUrl(context, request) {
|
|
|
311
362
|
...(typeof body.sessionId === 'string' ? { sessionId: body.sessionId } : {}),
|
|
312
363
|
...(typeof body.sourceType === 'string' ? { sourceType: body.sourceType } : {}),
|
|
313
364
|
...(typeof body.connectorId === 'string' ? { connectorId: body.connectorId } : {}),
|
|
314
|
-
...privateHostFetchOptions,
|
|
365
|
+
...(privateHostFetchOptions ?? {}),
|
|
315
366
|
...(typeof body.metadata === 'object' && body.metadata !== null ? { metadata: body.metadata } : {}),
|
|
316
367
|
}), { status: 201 });
|
|
317
368
|
}
|
|
@@ -323,6 +374,20 @@ async function handleKnowledgeIngestArtifact(context, request) {
|
|
|
323
374
|
const admin = context.requireAdmin(request);
|
|
324
375
|
if (admin)
|
|
325
376
|
return admin;
|
|
377
|
+
if (isArtifactUploadRequest(request)) {
|
|
378
|
+
const uploaded = await createArtifactFromUploadRequest(context.artifactStore, request);
|
|
379
|
+
if (uploaded instanceof Response)
|
|
380
|
+
return uploaded;
|
|
381
|
+
try {
|
|
382
|
+
return Response.json(await context.knowledgeService.ingestArtifact({
|
|
383
|
+
...uploaded.fields,
|
|
384
|
+
artifactId: uploaded.artifactId,
|
|
385
|
+
}), { status: 201 });
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
return jsonErrorResponse(error, { status: 400 });
|
|
389
|
+
}
|
|
390
|
+
}
|
|
326
391
|
const body = await context.parseJsonBody(request);
|
|
327
392
|
if (body instanceof Response)
|
|
328
393
|
return body;
|
|
@@ -340,7 +405,7 @@ async function handleKnowledgeIngestArtifact(context, request) {
|
|
|
340
405
|
...(typeof body.sessionId === 'string' ? { sessionId: body.sessionId } : {}),
|
|
341
406
|
...(typeof body.sourceType === 'string' ? { sourceType: body.sourceType } : {}),
|
|
342
407
|
...(typeof body.connectorId === 'string' ? { connectorId: body.connectorId } : {}),
|
|
343
|
-
...privateHostFetchOptions,
|
|
408
|
+
...(privateHostFetchOptions ?? {}),
|
|
344
409
|
...(typeof body.metadata === 'object' && body.metadata !== null ? { metadata: body.metadata } : {}),
|
|
345
410
|
}), { status: 201 });
|
|
346
411
|
}
|
|
@@ -348,6 +413,35 @@ async function handleKnowledgeIngestArtifact(context, request) {
|
|
|
348
413
|
return jsonErrorResponse(error, { status: 400 });
|
|
349
414
|
}
|
|
350
415
|
}
|
|
416
|
+
async function handleKnowledgeSyncBrowserHistory(context, request) {
|
|
417
|
+
const admin = context.requireAdmin(request);
|
|
418
|
+
if (admin)
|
|
419
|
+
return admin;
|
|
420
|
+
const body = await context.parseOptionalJsonBody(request);
|
|
421
|
+
if (body instanceof Response)
|
|
422
|
+
return body;
|
|
423
|
+
const input = body ?? {};
|
|
424
|
+
const sourceKinds = Array.isArray(input.sourceKinds)
|
|
425
|
+
? input.sourceKinds.filter((entry) => entry === 'history' || entry === 'bookmark')
|
|
426
|
+
: undefined;
|
|
427
|
+
const browsers = Array.isArray(input.browsers)
|
|
428
|
+
? input.browsers.filter((entry) => typeof entry === 'string' && entry.trim().length > 0)
|
|
429
|
+
: undefined;
|
|
430
|
+
try {
|
|
431
|
+
return Response.json(await context.knowledgeService.syncBrowserHistory({
|
|
432
|
+
...(typeof input.limit === 'number' ? { limit: Math.max(1, input.limit) } : {}),
|
|
433
|
+
...(typeof input.sinceMs === 'number' ? { sinceMs: input.sinceMs } : {}),
|
|
434
|
+
...(typeof input.homeOverride === 'string' ? { homeOverride: input.homeOverride } : {}),
|
|
435
|
+
...(typeof input.sessionId === 'string' ? { sessionId: input.sessionId } : {}),
|
|
436
|
+
...(typeof input.connectorId === 'string' ? { connectorId: input.connectorId } : {}),
|
|
437
|
+
...(browsers?.length ? { browsers } : {}),
|
|
438
|
+
...(sourceKinds?.length ? { sourceKinds } : {}),
|
|
439
|
+
}), { status: 201 });
|
|
440
|
+
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
return jsonErrorResponse(error, { status: 400 });
|
|
443
|
+
}
|
|
444
|
+
}
|
|
351
445
|
async function handleKnowledgeImportBookmarks(context, request) {
|
|
352
446
|
const admin = context.requireAdmin(request);
|
|
353
447
|
if (admin)
|
|
@@ -365,7 +459,7 @@ async function handleKnowledgeImportBookmarks(context, request) {
|
|
|
365
459
|
return Response.json(await context.knowledgeService.importBookmarksFromFile({
|
|
366
460
|
path,
|
|
367
461
|
...(typeof body.sessionId === 'string' ? { sessionId: body.sessionId } : {}),
|
|
368
|
-
...privateHostFetchOptions,
|
|
462
|
+
...(privateHostFetchOptions ?? {}),
|
|
369
463
|
}), { status: 201 });
|
|
370
464
|
}
|
|
371
465
|
catch (error) {
|
|
@@ -389,7 +483,7 @@ async function handleKnowledgeImportUrls(context, request) {
|
|
|
389
483
|
return Response.json(await context.knowledgeService.importUrlsFromFile({
|
|
390
484
|
path,
|
|
391
485
|
...(typeof body.sessionId === 'string' ? { sessionId: body.sessionId } : {}),
|
|
392
|
-
...privateHostFetchOptions,
|
|
486
|
+
...(privateHostFetchOptions ?? {}),
|
|
393
487
|
}), { status: 201 });
|
|
394
488
|
}
|
|
395
489
|
catch (error) {
|
|
@@ -416,7 +510,7 @@ async function handleKnowledgeIngestConnector(context, request) {
|
|
|
416
510
|
...(typeof body.content === 'string' ? { content: body.content } : {}),
|
|
417
511
|
...(typeof body.path === 'string' ? { path: body.path } : {}),
|
|
418
512
|
...(typeof body.sessionId === 'string' ? { sessionId: body.sessionId } : {}),
|
|
419
|
-
...privateHostFetchOptions,
|
|
513
|
+
...(privateHostFetchOptions ?? {}),
|
|
420
514
|
}), { status: 201 });
|
|
421
515
|
}
|
|
422
516
|
catch (error) {
|
|
@@ -433,6 +527,26 @@ async function handleKnowledgeSearch(context, request) {
|
|
|
433
527
|
const limit = typeof body.limit === 'number' ? body.limit : 10;
|
|
434
528
|
return Response.json({ results: context.knowledgeService.search(query, limit) });
|
|
435
529
|
}
|
|
530
|
+
async function handleKnowledgeAsk(context, request) {
|
|
531
|
+
const body = await context.parseJsonBody(request);
|
|
532
|
+
if (body instanceof Response)
|
|
533
|
+
return body;
|
|
534
|
+
const query = typeof body.query === 'string' ? body.query.trim() : '';
|
|
535
|
+
if (!query)
|
|
536
|
+
return Response.json({ error: 'Missing query' }, { status: 400 });
|
|
537
|
+
return Response.json(await context.knowledgeService.ask({
|
|
538
|
+
query,
|
|
539
|
+
...(typeof body.knowledgeSpaceId === 'string' ? { knowledgeSpaceId: body.knowledgeSpaceId } : {}),
|
|
540
|
+
...(typeof body.limit === 'number' ? { limit: Math.max(1, body.limit) } : {}),
|
|
541
|
+
...(typeof body.mode === 'string' && ['concise', 'standard', 'detailed'].includes(body.mode) ? { mode: body.mode } : {}),
|
|
542
|
+
...(typeof body.includeSources === 'boolean' ? { includeSources: body.includeSources } : {}),
|
|
543
|
+
...(typeof body.includeConfidence === 'boolean' ? { includeConfidence: body.includeConfidence } : {}),
|
|
544
|
+
...(typeof body.includeLinkedObjects === 'boolean' ? { includeLinkedObjects: body.includeLinkedObjects } : {}),
|
|
545
|
+
...(Array.isArray(body.candidateSourceIds) ? { candidateSourceIds: body.candidateSourceIds.filter(isString) } : {}),
|
|
546
|
+
...(Array.isArray(body.candidateNodeIds) ? { candidateNodeIds: body.candidateNodeIds.filter(isString) } : {}),
|
|
547
|
+
...(typeof body.strictCandidates === 'boolean' ? { strictCandidates: body.strictCandidates } : {}),
|
|
548
|
+
}));
|
|
549
|
+
}
|
|
436
550
|
async function handleKnowledgePacket(context, request) {
|
|
437
551
|
const body = await context.parseJsonBody(request);
|
|
438
552
|
if (body instanceof Response)
|
|
@@ -451,6 +565,32 @@ async function handleKnowledgePacket(context, request) {
|
|
|
451
565
|
...(typeof budgetLimit === 'number' ? { budgetLimit } : {}),
|
|
452
566
|
}));
|
|
453
567
|
}
|
|
568
|
+
async function handleKnowledgeReviewIssue(context, id, request) {
|
|
569
|
+
const admin = context.requireAdmin(request);
|
|
570
|
+
if (admin)
|
|
571
|
+
return admin;
|
|
572
|
+
const body = await context.parseOptionalJsonBody(request);
|
|
573
|
+
if (body instanceof Response)
|
|
574
|
+
return body;
|
|
575
|
+
const action = typeof body?.action === 'string' ? body.action.trim().toLowerCase() : '';
|
|
576
|
+
if (!['accept', 'reject', 'resolve', 'reopen', 'edit', 'forget'].includes(action)) {
|
|
577
|
+
return Response.json({ error: 'Action must be accept, reject, resolve, reopen, edit, or forget.' }, { status: 400 });
|
|
578
|
+
}
|
|
579
|
+
try {
|
|
580
|
+
return Response.json(await context.knowledgeService.reviewIssue({
|
|
581
|
+
issueId: id,
|
|
582
|
+
action,
|
|
583
|
+
...(typeof body?.reviewer === 'string' ? { reviewer: body.reviewer } : {}),
|
|
584
|
+
...(body?.value && typeof body.value === 'object' && !Array.isArray(body.value) ? { value: body.value } : {}),
|
|
585
|
+
}));
|
|
586
|
+
}
|
|
587
|
+
catch (error) {
|
|
588
|
+
const message = summarizeErrorForRecord(error);
|
|
589
|
+
return jsonErrorResponse(error, {
|
|
590
|
+
status: message.startsWith('Unknown knowledge issue:') ? 404 : 400,
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
}
|
|
454
594
|
async function handleKnowledgeDecideCandidate(context, id, request) {
|
|
455
595
|
const admin = context.requireAdmin(request);
|
|
456
596
|
if (admin)
|
|
@@ -580,3 +720,6 @@ async function handleKnowledgeMaterializeProjection(context, request) {
|
|
|
580
720
|
return jsonErrorResponse(error, { status: 400 });
|
|
581
721
|
}
|
|
582
722
|
}
|
|
723
|
+
function isString(value) {
|
|
724
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
725
|
+
}
|
|
@@ -4,6 +4,15 @@ export type MediaArtifact = Record<string, unknown>;
|
|
|
4
4
|
export type MultimodalAnalysisResult = unknown;
|
|
5
5
|
export type MultimodalDetail = string;
|
|
6
6
|
export type VoiceAudioArtifact = Record<string, unknown>;
|
|
7
|
+
export interface VoiceSynthesisStreamLike {
|
|
8
|
+
readonly providerId: string;
|
|
9
|
+
readonly mimeType: string;
|
|
10
|
+
readonly format: string;
|
|
11
|
+
readonly chunks: AsyncIterable<{
|
|
12
|
+
readonly data: Uint8Array;
|
|
13
|
+
}>;
|
|
14
|
+
readonly metadata: Record<string, unknown>;
|
|
15
|
+
}
|
|
7
16
|
export type WebSearchSafeSearch = string;
|
|
8
17
|
export type WebSearchTimeRange = string;
|
|
9
18
|
export type WebSearchVerbosity = string;
|
|
@@ -16,6 +25,7 @@ export interface VoiceServiceLike {
|
|
|
16
25
|
}>;
|
|
17
26
|
listVoices(providerId?: string): Promise<readonly unknown[]>;
|
|
18
27
|
synthesize(providerId: string | undefined, input: Record<string, unknown>): Promise<unknown>;
|
|
28
|
+
synthesizeStream(providerId: string | undefined, input: Record<string, unknown>): Promise<VoiceSynthesisStreamLike>;
|
|
19
29
|
transcribe(providerId: string | undefined, input: Record<string, unknown>): Promise<unknown>;
|
|
20
30
|
openRealtimeSession(providerId: string | undefined, input: Record<string, unknown>): Promise<unknown>;
|
|
21
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-route-types.d.ts","sourceRoot":"","sources":["../src/media-route-types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"media-route-types.d.ts","sourceRoot":"","sources":["../src/media-route-types.ts"],"names":[],"mappings":"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"}
|
package/dist/media-routes.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DaemonMediaRouteHandlers } from './context.js';
|
|
2
2
|
import type { DaemonMediaRouteContext } from './media-route-types.js';
|
|
3
|
-
export declare function createDaemonMediaRouteHandlers(context: DaemonMediaRouteContext):
|
|
3
|
+
export declare function createDaemonMediaRouteHandlers(context: DaemonMediaRouteContext): DaemonMediaRouteHandlers;
|
|
4
4
|
//# sourceMappingURL=media-routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-routes.d.ts","sourceRoot":"","sources":["../src/media-routes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"media-routes.d.ts","sourceRoot":"","sources":["../src/media-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAK7D,OAAO,KAAK,EAEV,uBAAuB,EAUxB,MAAM,wBAAwB,CAAC;AA2BhC,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,uBAAuB,GAC/B,wBAAwB,CAgC1B"}
|
package/dist/media-routes.js
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
import { resolvePrivateHostFetchOptions } from './http-policy.js';
|
|
2
2
|
import { jsonErrorResponse } from './error-response.js';
|
|
3
|
+
import { DaemonErrorCategory } from '@pellux/goodvibes-errors';
|
|
4
|
+
import { createArtifactFromUploadRequest, isArtifactUploadRequest } from './artifact-upload.js';
|
|
5
|
+
function readErrorMessage(error) {
|
|
6
|
+
if (typeof error === 'string')
|
|
7
|
+
return error;
|
|
8
|
+
if (error instanceof Error)
|
|
9
|
+
return error.message;
|
|
10
|
+
if (error && typeof error === 'object' && typeof error.message === 'string') {
|
|
11
|
+
return error.message;
|
|
12
|
+
}
|
|
13
|
+
return 'Unknown error';
|
|
14
|
+
}
|
|
15
|
+
function isProviderNotConfiguredError(error) {
|
|
16
|
+
const msg = readErrorMessage(error).toLowerCase();
|
|
17
|
+
return (msg.includes('not configured')
|
|
18
|
+
|| msg.includes('no provider')
|
|
19
|
+
|| msg.includes('api key')
|
|
20
|
+
|| msg.includes('api_key')
|
|
21
|
+
|| msg.includes('missing key')
|
|
22
|
+
|| msg.includes('no api')
|
|
23
|
+
|| msg.includes('provider not')
|
|
24
|
+
|| msg.includes('unconfigured'));
|
|
25
|
+
}
|
|
3
26
|
export function createDaemonMediaRouteHandlers(context) {
|
|
4
27
|
return {
|
|
5
28
|
getVoiceStatus: async () => Response.json(await context.voiceService.getStatus(Boolean(context.configManager.get('ui.voiceEnabled')))),
|
|
@@ -8,6 +31,7 @@ export function createDaemonMediaRouteHandlers(context) {
|
|
|
8
31
|
}),
|
|
9
32
|
getVoiceVoices: async (url) => Response.json({ voices: await context.voiceService.listVoices(url.searchParams.get('providerId') ?? undefined) }),
|
|
10
33
|
postVoiceTts: async (request) => handleVoiceTts(context, request),
|
|
34
|
+
postVoiceTtsStream: async (request) => handleVoiceTtsStream(context, request),
|
|
11
35
|
postVoiceStt: async (request) => handleVoiceStt(context, request),
|
|
12
36
|
postVoiceRealtimeSession: async (request) => handleVoiceRealtimeSession(context, request),
|
|
13
37
|
getWebSearchProviders: async () => Response.json({ providers: await context.webSearchService.getStatus().then((status) => status.providers) }),
|
|
@@ -32,27 +56,110 @@ export function createDaemonMediaRouteHandlers(context) {
|
|
|
32
56
|
postMultimodalWriteback: async (request) => handleMultimodalWriteback(context, request),
|
|
33
57
|
};
|
|
34
58
|
}
|
|
59
|
+
function readOptionalConfigString(context, key) {
|
|
60
|
+
const value = context.configManager.get(key);
|
|
61
|
+
return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;
|
|
62
|
+
}
|
|
63
|
+
function readVoiceSynthesisRequest(body, context) {
|
|
64
|
+
const providerId = typeof body.providerId === 'string'
|
|
65
|
+
? body.providerId
|
|
66
|
+
: context
|
|
67
|
+
? readOptionalConfigString(context, 'tts.provider')
|
|
68
|
+
: undefined;
|
|
69
|
+
const voiceId = typeof body.voiceId === 'string'
|
|
70
|
+
? body.voiceId
|
|
71
|
+
: context
|
|
72
|
+
? readOptionalConfigString(context, 'tts.voice')
|
|
73
|
+
: undefined;
|
|
74
|
+
const modelId = typeof body.modelId === 'string' ? body.modelId : undefined;
|
|
75
|
+
const format = typeof body.format === 'string' ? body.format : undefined;
|
|
76
|
+
const speed = typeof body.speed === 'number' ? body.speed : undefined;
|
|
77
|
+
const input = {
|
|
78
|
+
text: typeof body.text === 'string' ? body.text : '',
|
|
79
|
+
metadata: typeof body.metadata === 'object' && body.metadata !== null ? body.metadata : {},
|
|
80
|
+
};
|
|
81
|
+
if (voiceId !== undefined)
|
|
82
|
+
input.voiceId = voiceId;
|
|
83
|
+
if (modelId !== undefined)
|
|
84
|
+
input.modelId = modelId;
|
|
85
|
+
if (format !== undefined)
|
|
86
|
+
input.format = format;
|
|
87
|
+
if (speed !== undefined)
|
|
88
|
+
input.speed = speed;
|
|
89
|
+
return {
|
|
90
|
+
...(providerId !== undefined ? { providerId } : {}),
|
|
91
|
+
input,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
35
94
|
async function handleVoiceTts(context, req) {
|
|
36
95
|
const body = await context.parseJsonBody(req);
|
|
37
96
|
if (body instanceof Response)
|
|
38
97
|
return body;
|
|
39
|
-
const
|
|
40
|
-
if (!text.trim())
|
|
98
|
+
const { providerId, input } = readVoiceSynthesisRequest(body);
|
|
99
|
+
if (!input.text.trim())
|
|
41
100
|
return Response.json({ error: 'Missing text' }, { status: 400 });
|
|
42
101
|
try {
|
|
43
|
-
const result = await context.voiceService.synthesize(
|
|
44
|
-
text,
|
|
45
|
-
voiceId: typeof body.voiceId === 'string' ? body.voiceId : undefined,
|
|
46
|
-
modelId: typeof body.modelId === 'string' ? body.modelId : undefined,
|
|
47
|
-
format: typeof body.format === 'string' ? body.format : undefined,
|
|
48
|
-
speed: typeof body.speed === 'number' ? body.speed : undefined,
|
|
49
|
-
metadata: typeof body.metadata === 'object' && body.metadata !== null ? body.metadata : {},
|
|
50
|
-
});
|
|
102
|
+
const result = await context.voiceService.synthesize(providerId, input);
|
|
51
103
|
return Response.json(result);
|
|
52
104
|
}
|
|
53
105
|
catch (error) {
|
|
54
|
-
|
|
106
|
+
if (isProviderNotConfiguredError(error)) {
|
|
107
|
+
return Response.json({ code: 'PROVIDER_NOT_CONFIGURED', error: readErrorMessage(error), category: DaemonErrorCategory.CONFIG, source: 'provider', recoverable: false, hint: 'Configure the voice provider API key or service credentials.' }, { status: 409 });
|
|
108
|
+
}
|
|
109
|
+
return jsonErrorResponse(error, { status: 400 });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async function handleVoiceTtsStream(context, req) {
|
|
113
|
+
const body = await context.parseJsonBody(req);
|
|
114
|
+
if (body instanceof Response)
|
|
115
|
+
return body;
|
|
116
|
+
const { providerId, input } = readVoiceSynthesisRequest(body, context);
|
|
117
|
+
if (!input.text.trim())
|
|
118
|
+
return Response.json({ error: 'Missing text' }, { status: 400 });
|
|
119
|
+
try {
|
|
120
|
+
const result = await context.voiceService.synthesizeStream(providerId, { ...input, signal: req.signal });
|
|
121
|
+
return voiceStreamResponse(result);
|
|
55
122
|
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (isProviderNotConfiguredError(error)) {
|
|
125
|
+
return Response.json({ code: 'PROVIDER_NOT_CONFIGURED', error: readErrorMessage(error), category: DaemonErrorCategory.CONFIG, source: 'provider', recoverable: false, hint: 'Configure the streaming TTS provider API key or service credentials.' }, { status: 409 });
|
|
126
|
+
}
|
|
127
|
+
return jsonErrorResponse(error, { status: 400 });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function voiceStreamResponse(result) {
|
|
131
|
+
const iterator = result.chunks[Symbol.asyncIterator]();
|
|
132
|
+
const stream = new ReadableStream({
|
|
133
|
+
async pull(controller) {
|
|
134
|
+
try {
|
|
135
|
+
while (true) {
|
|
136
|
+
const { done, value } = await iterator.next();
|
|
137
|
+
if (done) {
|
|
138
|
+
controller.close();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (value.data.byteLength > 0) {
|
|
142
|
+
controller.enqueue(value.data);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
controller.error(error);
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
async cancel(reason) {
|
|
152
|
+
await iterator.return?.(reason);
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
return new Response(stream, {
|
|
156
|
+
headers: {
|
|
157
|
+
'Content-Type': result.mimeType,
|
|
158
|
+
'Cache-Control': 'no-store',
|
|
159
|
+
'X-GoodVibes-Voice-Provider': result.providerId,
|
|
160
|
+
'X-GoodVibes-Audio-Format': result.format,
|
|
161
|
+
},
|
|
162
|
+
});
|
|
56
163
|
}
|
|
57
164
|
async function handleVoiceStt(context, req) {
|
|
58
165
|
const body = await context.parseJsonBody(req);
|
|
@@ -72,7 +179,10 @@ async function handleVoiceStt(context, req) {
|
|
|
72
179
|
return Response.json(result);
|
|
73
180
|
}
|
|
74
181
|
catch (error) {
|
|
75
|
-
|
|
182
|
+
if (isProviderNotConfiguredError(error)) {
|
|
183
|
+
return Response.json({ code: 'PROVIDER_NOT_CONFIGURED', error: readErrorMessage(error), category: DaemonErrorCategory.CONFIG, source: 'provider', recoverable: false, hint: 'Configure the voice provider API key or service credentials.' }, { status: 409 });
|
|
184
|
+
}
|
|
185
|
+
return jsonErrorResponse(error, { status: 400 });
|
|
76
186
|
}
|
|
77
187
|
}
|
|
78
188
|
async function handleVoiceRealtimeSession(context, req) {
|
|
@@ -91,7 +201,10 @@ async function handleVoiceRealtimeSession(context, req) {
|
|
|
91
201
|
return Response.json(result, { status: 201 });
|
|
92
202
|
}
|
|
93
203
|
catch (error) {
|
|
94
|
-
|
|
204
|
+
if (isProviderNotConfiguredError(error)) {
|
|
205
|
+
return Response.json({ code: 'PROVIDER_NOT_CONFIGURED', error: readErrorMessage(error), category: DaemonErrorCategory.CONFIG, source: 'provider', recoverable: false, hint: 'Configure the voice provider API key or service credentials.' }, { status: 409 });
|
|
206
|
+
}
|
|
207
|
+
return jsonErrorResponse(error, { status: 400 });
|
|
95
208
|
}
|
|
96
209
|
}
|
|
97
210
|
async function handleMediaAnalyze(context, req) {
|
|
@@ -121,6 +234,12 @@ async function handleMediaAnalyze(context, req) {
|
|
|
121
234
|
}));
|
|
122
235
|
}
|
|
123
236
|
async function handleArtifactCreate(context, req) {
|
|
237
|
+
if (isArtifactUploadRequest(req)) {
|
|
238
|
+
const uploaded = await createArtifactFromUploadRequest(context.artifactStore, req);
|
|
239
|
+
if (uploaded instanceof Response)
|
|
240
|
+
return uploaded;
|
|
241
|
+
return Response.json({ artifact: uploaded.artifact }, { status: 201 });
|
|
242
|
+
}
|
|
124
243
|
const body = await context.parseJsonBody(req);
|
|
125
244
|
if (body instanceof Response)
|
|
126
245
|
return body;
|
|
@@ -140,7 +259,7 @@ async function handleArtifactCreate(context, req) {
|
|
|
140
259
|
...(typeof body.text === 'string' ? { text: body.text } : {}),
|
|
141
260
|
...(typeof body.path === 'string' ? { path: body.path } : {}),
|
|
142
261
|
...(typeof body.uri === 'string' ? { uri: body.uri } : {}),
|
|
143
|
-
...privateHostFetchOptions,
|
|
262
|
+
...(privateHostFetchOptions ?? {}),
|
|
144
263
|
...(typeof body.retentionMs === 'number' ? { retentionMs: body.retentionMs } : {}),
|
|
145
264
|
...(typeof body.metadata === 'object' && body.metadata !== null ? { metadata: body.metadata } : {}),
|
|
146
265
|
});
|
|
@@ -254,7 +373,7 @@ async function handleMultimodalAnalyze(context, req) {
|
|
|
254
373
|
...(requestedArtifact ? {
|
|
255
374
|
artifact: {
|
|
256
375
|
...requestedArtifact,
|
|
257
|
-
...privateHostFetchOptions,
|
|
376
|
+
...(privateHostFetchOptions ?? {}),
|
|
258
377
|
},
|
|
259
378
|
} : {}),
|
|
260
379
|
...(typeof body.prompt === 'string' ? { prompt: body.prompt } : {}),
|
package/dist/operator.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function dispatchOperatorRoutes(req: Request, handlers:
|
|
1
|
+
import type { DaemonOperatorRouteHandlers } from './context.js';
|
|
2
|
+
export declare function dispatchOperatorRoutes(req: Request, handlers: DaemonOperatorRouteHandlers): Promise<Response | null>;
|
|
3
3
|
//# sourceMappingURL=operator.d.ts.map
|
package/dist/operator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operator.d.ts","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"operator.d.ts","sourceRoot":"","sources":["../src/operator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAGhE,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,2BAA2B,GACpC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA8S1B"}
|