@vincemakes/kiso-server 0.41.1 → 0.41.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/README.md CHANGED
@@ -66,6 +66,20 @@ await service.close(5_000); // abort what is live,
66
66
  product that must guarantee no prose reaches a client supplies its own
67
67
  `sanitize` in the projection options.
68
68
 
69
+ ## Shutting down, and one thing not to call
70
+
71
+ The order that keeps every run resumable: `service.drain(graceMs)` (no
72
+ new runs; wait for executing tools; the report says what was parked or
73
+ cut), then stop the listener, then `store.closeAll()`, then exit. Do not
74
+ call `service.close()` for that — it ABORTS what is live, including a
75
+ run parked at an approval, which voids the draft its answer would have
76
+ continued. And do not call `agent.close()` on a factory's agent when the
77
+ store is shared: in the runtime it closes the whole store.
78
+
79
+ `hooks.onSettled` is the product's "what next" after a run: a follow-up
80
+ turn, a resume when `uncertainRemaining` reaches zero, a notification.
81
+ The service never starts a run on its own.
82
+
69
83
  ## What a host still writes
70
84
 
71
85
  The transport (routes, SSE framing, `Last-Event-ID`, keepalive, status
package/dist/http.js CHANGED
@@ -1,6 +1,10 @@
1
1
  import { DrainingError, InFlightError, OpenRunError } from "./errors.js";
2
2
  import { toWireEvent } from "./wire.js";
3
- const SESSION_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
3
+ /** The store's own rule (`^[A-Za-z0-9._-]+$`), with a length cap. 0.41.2:
4
+ * the first version also required a leading letter or digit, which the
5
+ * store never did — a nanoid can start with `_` or `-` (about 1 in 32 do)
6
+ * and every such session answered 404. */
7
+ const SESSION_ID = /^[A-Za-z0-9._-]{1,128}$/;
4
8
  const ACTIONS = new Set(["", "state", "events", "replay", "run", "resume", "abort", "approve", "uncertain"]);
5
9
  export function createHttpHandler(service, options) {
6
10
  const prefix = (options.prefix ?? "/v1/sessions").replace(/\/+$/, "");
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * the agent factory, and every run is the runtime's own `Session.run()`.
8
8
  */
9
9
  export { createSessionService, SessionService } from "./service.js";
10
- export type { AbortOutcome, DrainReport, OpenRun, RunHandle, RunOptions, SessionServiceOptions } from "./service.js";
10
+ export type { AbortOutcome, DrainReport, OpenRun, RunHandle, RunOptions, SessionServiceOptions, SettledRun } from "./service.js";
11
11
  export { DrainingError, InFlightError, OpenRunError, StoreMismatchError } from "./errors.js";
12
12
  export { EXECUTION_ENDED, executionDelta } from "./execution.js";
13
13
  export { tail } from "./tail.js";
package/dist/service.d.ts CHANGED
@@ -48,8 +48,26 @@ export interface SessionServiceOptions {
48
48
  /** After `abort()` has aborted a run: the product's cleanup, e.g.
49
49
  * finishing paid jobs the run left in flight. */
50
50
  readonly onAbort?: (sessionId: string, runId: string) => Promise<void> | void;
51
+ /** After a run has settled — its terminal delivered to every
52
+ * listener, the session idle again. The product's "what next": a
53
+ * follow-up turn (`service.run`), a resume when the last uncertain
54
+ * verdict is in (`uncertainRemaining === 0`), a notification. The
55
+ * service itself never starts a run on its own. Runs after the
56
+ * store check, so a mismatched session never reaches it. */
57
+ readonly onSettled?: (settled: SettledRun) => Promise<void> | void;
51
58
  };
52
59
  }
60
+ /** What `hooks.onSettled` receives. */
61
+ export interface SettledRun {
62
+ readonly sessionId: string;
63
+ readonly runId: string;
64
+ /** The terminal's outcome kind: completed | aborted | error | max_turns | max_tokens | hook_stopped. */
65
+ readonly outcome: string;
66
+ /** Executions still awaiting a human verdict after this run. */
67
+ readonly uncertainRemaining: number;
68
+ /** The highest seq this run delivered. */
69
+ readonly highWater: number;
70
+ }
53
71
  export interface RunHandle {
54
72
  readonly runId: string;
55
73
  /** Settles when the run has reached its terminal and the last event has
package/dist/service.js CHANGED
@@ -81,6 +81,16 @@ export class SessionService {
81
81
  held.mismatch = new StoreMismatchError(held.id, run.runId, held.highWater);
82
82
  throw held.mismatch;
83
83
  }
84
+ if (this.#hooks.onSettled !== undefined) {
85
+ const terminal = [...held.session.log.all].reverse().find((e) => e.type === "terminal");
86
+ await this.#hooks.onSettled({
87
+ sessionId: held.id,
88
+ runId: run.runId,
89
+ outcome: terminal !== undefined && terminal.type === "terminal" ? terminal.outcome.kind : "unknown",
90
+ uncertainRemaining: held.session.uncertainExecutions().length,
91
+ highWater: held.highWater,
92
+ });
93
+ }
84
94
  })();
85
95
  held.pumping = pumping;
86
96
  void pumping.catch(() => { }); // a host that does not await `done` gets no unhandled rejection
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-server",
3
- "version": "0.41.1",
3
+ "version": "0.41.2",
4
4
  "description": "kiso server — the hosted-session service: many durable sessions in one process, observers with exact replay from a sequence number, approve / abort / resume routed to the right run, drain and close. No transport; a product supplies the agent factory.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -25,12 +25,12 @@
25
25
  "test": "vitest run"
26
26
  },
27
27
  "dependencies": {
28
- "@vincemakes/kiso-core": "0.41.1",
29
- "@vincemakes/kiso-protocol": "0.41.1",
30
- "@vincemakes/kiso-runtime": "0.41.1"
28
+ "@vincemakes/kiso-core": "0.41.2",
29
+ "@vincemakes/kiso-protocol": "0.41.2",
30
+ "@vincemakes/kiso-runtime": "0.41.2"
31
31
  },
32
32
  "devDependencies": {
33
- "@vincemakes/kiso-evals": "0.41.1",
33
+ "@vincemakes/kiso-evals": "0.41.2",
34
34
  "@types/node": "^26.1.2",
35
35
  "typescript": "^5.7.2",
36
36
  "vitest": "^3.0.0"