omkit 0.4.4 → 0.4.5

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.
@@ -7,8 +7,8 @@ export interface Transport {
7
7
  onClose(handler: (code: number | null) => void): void;
8
8
  }
9
9
  /**
10
- * Turn a child transport into a {@link RunSession}: fan `log`/`prompt` child messages out to
11
- * handlers, resolve `result` on `settled`, and map `answer`/`cancel` back down the wire. A
12
- * close before `settled` resolves a failed verdict so `result` never hangs.
10
+ * Turn a child transport into a {@link RunSession}: fan `log`/`prompt`/`prompt-done` child
11
+ * messages out to handlers, resolve `result` on `settled`, and map `answer`/`cancel` back down
12
+ * the wire. A close before `settled` resolves a failed verdict so `result` never hangs.
13
13
  */
14
14
  export declare function createChannel(transport: Transport): RunSession;
@@ -1,12 +1,13 @@
1
1
  /**
2
- * Turn a child transport into a {@link RunSession}: fan `log`/`prompt` child messages out to
3
- * handlers, resolve `result` on `settled`, and map `answer`/`cancel` back down the wire. A
4
- * close before `settled` resolves a failed verdict so `result` never hangs.
2
+ * Turn a child transport into a {@link RunSession}: fan `log`/`prompt`/`prompt-done` child
3
+ * messages out to handlers, resolve `result` on `settled`, and map `answer`/`cancel` back down
4
+ * the wire. A close before `settled` resolves a failed verdict so `result` never hangs.
5
5
  */
6
6
  export function createChannel(transport) {
7
7
  const handlers = {
8
8
  log: [],
9
9
  prompt: [],
10
+ promptDone: [],
10
11
  settled: [],
11
12
  };
12
13
  let settled = false;
@@ -21,6 +22,10 @@ export function createChannel(transport) {
21
22
  for (const h of handlers.prompt)
22
23
  h({ id: message.id, spec: message.spec });
23
24
  }
25
+ else if (message.kind === "prompt-done") {
26
+ for (const h of handlers.promptDone)
27
+ h(message.id);
28
+ }
24
29
  else if (message.kind === "settled") {
25
30
  settled = true;
26
31
  const verdict = { ok: message.ok, folder: message.folder, summary: message.summary };
@@ -30,6 +30,8 @@ export interface PromptRequest {
30
30
  export interface RunEvents {
31
31
  log: (entry: LogEntry) => void;
32
32
  prompt: (request: PromptRequest) => void;
33
+ /** A pending prompt was withdrawn by the child (timed out or torn down) — clear it from the UI. */
34
+ promptDone: (id: string) => void;
33
35
  settled: (verdict: Verdict) => void;
34
36
  }
35
37
  /** A live handle to one supervised run. */
@@ -39,6 +39,10 @@ export function App({ client, onExit, oms: initialOms, }) {
39
39
  setLines((prev) => [...prev, rendered.text]);
40
40
  });
41
41
  s.on("prompt", (req) => setPrompt(req));
42
+ // The child gave up on the prompt (timed out or torn down). Withdraw its box so a stale,
43
+ // unanswerable prompt doesn't linger — but only if it's still the one on screen, so a late
44
+ // withdrawal can't clobber a fresh prompt.
45
+ s.on("promptDone", (id) => setPrompt((p) => (p?.id === id ? undefined : p)));
42
46
  s.on("settled", (v) => {
43
47
  setVerdict(v);
44
48
  setPrompt(undefined);
@@ -17,6 +17,9 @@ export type ChildMessage = {
17
17
  kind: "prompt";
18
18
  id: string;
19
19
  spec: PromptSpec;
20
+ } | {
21
+ kind: "prompt-done";
22
+ id: string;
20
23
  } | {
21
24
  kind: "log";
22
25
  entry: LogEntry;
@@ -29,6 +29,10 @@ export class Supervisor {
29
29
  return new Promise((resolve, reject) => {
30
30
  const onAbort = () => {
31
31
  this.pending.delete(id);
32
+ // The child is giving up on this prompt (timeout or teardown) and moving on. Tell the
33
+ // supervisor so it withdraws the prompt from its UI — otherwise a stale, unanswerable
34
+ // prompt box lingers on screen for the rest of the run.
35
+ this.send({ kind: "prompt-done", id });
32
36
  reject(new Error("prompt aborted"));
33
37
  };
34
38
  if (signal.aborted)
@@ -58,10 +58,11 @@ export interface OmContext {
58
58
  }
59
59
  /**
60
60
  * A launched action: the live node's awaitable/observable surface, returned by
61
- * **invoking an {@link Action}**. `.result` always resolves an {@link Outcome} (never
62
- * throws); `.ref` rejects on failure/cancel. The body is committed one microtask after
63
- * the launching call, so pre-body config (`withCache`) chained before the first `await`
64
- * still applies.
61
+ * **invoking an {@link Action}**. `.result` (like `.ref` and `once`) resolves the value on
62
+ * success and **rejects** with the action's error on failure (or `CancelledError` on cancel);
63
+ * reading it observes the activity, so a handled failure won't tear the run down. The body is
64
+ * committed one microtask after the launching call, so pre-body config (`withCache`) chained
65
+ * before the first `await` still applies.
65
66
  */
66
67
  export interface Activity<Result = unknown, Events extends object = NoEvents, Handle = void> {
67
68
  readonly id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omkit",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "description": "A tiny runtime for developer workflows: typed actions that pass runtime capabilities and emit typed events, under one run and one shared log. The operational/runtime layer to tskb's knowledge layer.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",