@kindgi/api 0.1.0 → 0.1.2
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/app.d.ts.map +1 -1
- package/dist/app.js +3 -2
- package/dist/app.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +4 -0
- package/dist/errors.js.map +1 -1
- package/dist/middleware/error-mapper.d.ts +14 -7
- package/dist/middleware/error-mapper.d.ts.map +1 -1
- package/dist/middleware/error-mapper.js +24 -22
- package/dist/middleware/error-mapper.js.map +1 -1
- package/dist/openapi/operations.d.ts.map +1 -1
- package/dist/openapi/operations.js +3 -4
- package/dist/openapi/operations.js.map +1 -1
- package/dist/routes/runs.d.ts.map +1 -1
- package/dist/routes/runs.js +13 -81
- package/dist/routes/runs.js.map +1 -1
- package/dist/routes/sse.d.ts +2 -2
- package/dist/routes/sse.js +1 -1
- package/openapi.json +6 -16
- package/package.json +24 -24
- package/src/app.ts +3 -2
- package/src/errors.ts +4 -0
- package/src/middleware/error-mapper.ts +28 -25
- package/src/openapi/operations.ts +3 -4
- package/src/routes/runs.ts +18 -107
- package/src/routes/sse.ts +2 -2
package/src/routes/runs.ts
CHANGED
|
@@ -293,74 +293,25 @@ export function runsRouter(
|
|
|
293
293
|
});
|
|
294
294
|
|
|
295
295
|
// ---------- POST /:runId/resume ----------
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
const parsed = parseResumeBody(body);
|
|
317
|
-
if (parsed.kind === 'err') {
|
|
318
|
-
c.status(statusFor(parsed.error.code) as never);
|
|
319
|
-
return c.json(toWireError(parsed.error, requestId));
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// Resume completes a waitpoint (`completeToken`) and then drives the
|
|
323
|
-
// run on. Resuming without a `waitpointId` is not supported.
|
|
324
|
-
if (parsed.value.waitpointId === undefined) {
|
|
325
|
-
c.status(statusFor('bad-input') as never);
|
|
326
|
-
return c.json(
|
|
327
|
-
toWireError(
|
|
328
|
-
{
|
|
329
|
-
code: 'bad-input',
|
|
330
|
-
message:
|
|
331
|
-
'Programmatic resume without `waitpointId` is not supported yet — supply a waitpoint id to complete a wait token.',
|
|
332
|
-
},
|
|
333
|
-
requestId,
|
|
334
|
-
),
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
const completed = await runBinding.completeToken(
|
|
339
|
-
tenantId,
|
|
340
|
-
runId,
|
|
341
|
-
parsed.value.waitpointId,
|
|
342
|
-
parsed.value.value,
|
|
343
|
-
eventBus,
|
|
296
|
+
// Not available in this release. Every waitpoint a run can wait at
|
|
297
|
+
// belongs to an approval or to the runtime itself (a flow's agent step
|
|
298
|
+
// waiting on its child turn). Completing one here would skip what owns
|
|
299
|
+
// it: an approval's reviewer check and recorded decision, or the
|
|
300
|
+
// runtime's own wake-up. A run waiting for an approval continues
|
|
301
|
+
// through `POST /v1/approvals/:id/complete`. So nothing is read or
|
|
302
|
+
// completed; the route stays mounted for a clear answer.
|
|
303
|
+
r.post('/:runId/resume', (c) => {
|
|
304
|
+
c.status(statusFor('run-resume-not-supported') as never);
|
|
305
|
+
return c.json(
|
|
306
|
+
toWireError(
|
|
307
|
+
{
|
|
308
|
+
code: 'run-resume-not-supported',
|
|
309
|
+
message:
|
|
310
|
+
'Resuming a run at a waitpoint is not available in this release: every waitpoint belongs to an approval or to the runtime. A run waiting for an approval continues when a reviewer decides it (POST /v1/approvals/{approvalId}/complete, or `kindgi approvals complete`).',
|
|
311
|
+
},
|
|
312
|
+
c.get('requestId'),
|
|
313
|
+
),
|
|
344
314
|
);
|
|
345
|
-
if (completed.kind === 'err') {
|
|
346
|
-
const err = completed.error;
|
|
347
|
-
c.status(statusFor(err.code) as never);
|
|
348
|
-
return c.json(toWireError(err as never, requestId));
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Drive the run on in the same request, as approvals do. Soft on
|
|
352
|
-
// failure: the token completion is already durable, so the run is
|
|
353
|
-
// resumable later; the response shows the status it reached.
|
|
354
|
-
await binding.resumeRun({ tenantId, runId }).catch(() => undefined);
|
|
355
|
-
|
|
356
|
-
const reloaded = await runBinding.getRun(tenantId, runId);
|
|
357
|
-
if (reloaded === null) {
|
|
358
|
-
c.status(statusFor('run-not-found') as never);
|
|
359
|
-
return c.json(
|
|
360
|
-
toWireError({ code: 'run-not-found', message: `No run with id ${runId}` }, requestId),
|
|
361
|
-
);
|
|
362
|
-
}
|
|
363
|
-
return c.json(serializeRun(reloaded, { output: true }));
|
|
364
315
|
});
|
|
365
316
|
|
|
366
317
|
// ---------- GET /:runId/stream and /:runId/progress/stream (SSE) ----------
|
|
@@ -770,9 +721,6 @@ function listRunsInput(input: {
|
|
|
770
721
|
};
|
|
771
722
|
}
|
|
772
723
|
|
|
773
|
-
/** Waitpoint ids the runtime reserves for a parent waiting on a child run. */
|
|
774
|
-
const RESERVED_WAITPOINT_PREFIX = 'child:';
|
|
775
|
-
|
|
776
724
|
interface RunListFilter {
|
|
777
725
|
readonly parentRunId?: RunId;
|
|
778
726
|
readonly topLevelOnly: boolean;
|
|
@@ -809,43 +757,6 @@ function parseRunListFilter(
|
|
|
809
757
|
};
|
|
810
758
|
}
|
|
811
759
|
|
|
812
|
-
function parseResumeBody(
|
|
813
|
-
body: unknown,
|
|
814
|
-
):
|
|
815
|
-
| { kind: 'ok'; value: { waitpointId?: string; value?: unknown } }
|
|
816
|
-
| { kind: 'err'; error: { code: string; message: string } } {
|
|
817
|
-
if (body === null || typeof body !== 'object') {
|
|
818
|
-
return { kind: 'err', error: { code: 'bad-input', message: 'Request body must be an object' } };
|
|
819
|
-
}
|
|
820
|
-
const b = body as Record<string, unknown>;
|
|
821
|
-
const waitpointId = b.waitpointId;
|
|
822
|
-
if (waitpointId !== undefined && (typeof waitpointId !== 'string' || waitpointId.length === 0)) {
|
|
823
|
-
return {
|
|
824
|
-
kind: 'err',
|
|
825
|
-
error: {
|
|
826
|
-
code: 'bad-input',
|
|
827
|
-
message: '`waitpointId` must be a non-empty string when supplied',
|
|
828
|
-
},
|
|
829
|
-
};
|
|
830
|
-
}
|
|
831
|
-
if (typeof waitpointId === 'string' && waitpointId.startsWith(RESERVED_WAITPOINT_PREFIX)) {
|
|
832
|
-
return {
|
|
833
|
-
kind: 'err',
|
|
834
|
-
error: {
|
|
835
|
-
code: 'bad-input',
|
|
836
|
-
message: `Waitpoint ids starting with "${RESERVED_WAITPOINT_PREFIX}" belong to the runtime (a parent waiting on a child run) and cannot be completed by a caller.`,
|
|
837
|
-
},
|
|
838
|
-
};
|
|
839
|
-
}
|
|
840
|
-
return {
|
|
841
|
-
kind: 'ok',
|
|
842
|
-
value: {
|
|
843
|
-
...(waitpointId !== undefined && { waitpointId: waitpointId as string }),
|
|
844
|
-
...('value' in b && { value: b.value }),
|
|
845
|
-
},
|
|
846
|
-
};
|
|
847
|
-
}
|
|
848
|
-
|
|
849
760
|
/** `options` of a start body: `dryRun?`, `wait?` (booleans). */
|
|
850
761
|
function parseStartOptions(
|
|
851
762
|
raw: unknown,
|
package/src/routes/sse.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type { RunId, TenantId } from '@kindgi/types';
|
|
|
12
12
|
* Source of truth: `@kindgi/specs/run-event.schema.json`. Names are dotted
|
|
13
13
|
* `run.<xxx>-<yyy>` (e.g. `run.step-completed`) — matches the
|
|
14
14
|
* conventions doc §6 example. Internal-only kernel journal kinds
|
|
15
|
-
* (e.g. `
|
|
15
|
+
* (e.g. `value.recorded`) and kinds absent from the wire enum
|
|
16
16
|
* (`edge.evaluated`) are dropped by the mapper — the journal endpoint
|
|
17
17
|
* still exposes them.
|
|
18
18
|
*/
|
|
@@ -54,7 +54,7 @@ const TERMINAL_KINDS: ReadonlySet<RunEventKind> = new Set([
|
|
|
54
54
|
/**
|
|
55
55
|
* Project a kernel `JournalEntry` into the wire `RunEvent` shape
|
|
56
56
|
* consumed over SSE. Returns `null` for kernel kinds not exposed on
|
|
57
|
-
* the wire (`edge.evaluated`, `
|
|
57
|
+
* the wire (`edge.evaluated`, `value.recorded`).
|
|
58
58
|
*/
|
|
59
59
|
export function projectJournalEntry(
|
|
60
60
|
entry: JournalEntry,
|