@crouton-kit/humanloop 0.3.13 → 0.3.14

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/api.js CHANGED
@@ -4,7 +4,7 @@ import { join } from 'node:path';
4
4
  import { resolveInteractionDir } from './tui/app.js';
5
5
  import { scanInbox } from './inbox/scan.js';
6
6
  import { pickFromInbox } from './inbox/tui.js';
7
- import { deckPath, atomicWriteJson, readJson } from './inbox/convention.js';
7
+ import { deckPath, atomicWriteJson, readJson, stampCanvasNode } from './inbox/convention.js';
8
8
  import { getTerminalSize } from './tui/terminal.js';
9
9
  import { approveDeck, notifyDeck } from './inbox/deck-factories.js';
10
10
  const RESPONSE_SCHEMA_ID = 'humanloop.response/v2';
@@ -61,6 +61,7 @@ function buildSummary(deck, responses) {
61
61
  export async function ask(deck, opts = {}) {
62
62
  const dir = opts.dir ?? managedDir();
63
63
  mkdirSync(dir, { recursive: true });
64
+ stampCanvasNode(deck);
64
65
  atomicWriteJson(deckPath(dir), deck);
65
66
  const { responses, completedAt, responsePath, deck: answeredDeck } = await resolveInteractionDir(dir, deck, {
66
67
  sessionId: opts.sessionId,
package/dist/cli.js CHANGED
@@ -11,7 +11,7 @@ import { ask, inbox } from './api.js';
11
11
  import { display } from './surfaces/display.js';
12
12
  import { renderMarkdown, checkMarkdown } from './render/termrender.js';
13
13
  import { scanInbox } from './inbox/scan.js';
14
- import { deckPath, atomicWriteJson, readJson, responsePath, } from './inbox/convention.js';
14
+ import { deckPath, atomicWriteJson, readJson, responsePath, stampCanvasNode, } from './inbox/convention.js';
15
15
  // ── Version ───────────────────────────────────────────────────────────────────
16
16
  const HL_VERSION = '0.2.1';
17
17
  function emitError(err, exitCode = 1) {
@@ -372,6 +372,7 @@ deckCmd
372
372
  }
373
373
  const dir = input.dir ? resolve(input.dir) : mkdtempSync(join(tmpdir(), 'hl-ix-'));
374
374
  mkdirSync(dir, { recursive: true });
375
+ stampCanvasNode(deck);
375
376
  atomicWriteJson(deckPath(dir), deck);
376
377
  const jobId = basename(dir);
377
378
  const visuals = input.visuals !== false;
@@ -1,4 +1,4 @@
1
- import type { InteractionResponse } from '../types.js';
1
+ import type { Deck, InteractionResponse } from '../types.js';
2
2
  export declare function deckPath(dir: string): string;
3
3
  export declare function responsePath(dir: string): string;
4
4
  export declare function progressPath(dir: string): string;
@@ -10,6 +10,15 @@ export declare function interactionState(dir: string): InteractionState;
10
10
  export declare function isResolved(dir: string): boolean;
11
11
  /** Returns true if a live resolver owns this dir (progress.json mtime < 300s). */
12
12
  export declare function isClaimed(dir: string): boolean;
13
+ /**
14
+ * Stamp the originating canvas node id onto a deck's `source` so per-node
15
+ * attention scoping (crouter's nav chrome) can attribute the ask to the node
16
+ * that raised it rather than every sibling node sharing the same cwd.
17
+ *
18
+ * No-op when not inside a canvas node (CRTR_NODE_ID unset) or when the deck
19
+ * already carries a nodeId. Mutates `deck` in place.
20
+ */
21
+ export declare function stampCanvasNode(deck: Deck): void;
13
22
  export declare function atomicWriteJson(path: string, value: unknown): void;
14
23
  export declare function readJson<T>(path: string): T | null;
15
24
  export declare function writeResponse(dir: string, responses: InteractionResponse[], completedAt: string): string;
@@ -47,6 +47,23 @@ export function isClaimed(dir) {
47
47
  return false;
48
48
  }
49
49
  }
50
+ // ── Canvas-node attribution ─────────────────────────────────────────
51
+ /**
52
+ * Stamp the originating canvas node id onto a deck's `source` so per-node
53
+ * attention scoping (crouter's nav chrome) can attribute the ask to the node
54
+ * that raised it rather than every sibling node sharing the same cwd.
55
+ *
56
+ * No-op when not inside a canvas node (CRTR_NODE_ID unset) or when the deck
57
+ * already carries a nodeId. Mutates `deck` in place.
58
+ */
59
+ export function stampCanvasNode(deck) {
60
+ const id = process.env['CRTR_NODE_ID'];
61
+ if (id === undefined || id.trim() === '')
62
+ return;
63
+ if (deck.source?.nodeId != null && deck.source.nodeId !== '')
64
+ return;
65
+ deck.source = { ...(deck.source ?? {}), nodeId: id };
66
+ }
50
67
  // ── Atomic I/O ────────────────────────────────────────────────────────────────
51
68
  export function atomicWriteJson(path, value) {
52
69
  const payload = JSON.stringify(value, null, 2);
@@ -18,6 +18,7 @@ export declare const deckSchema: z.ZodObject<{
18
18
  sessionName: z.ZodOptional<z.ZodString>;
19
19
  askedBy: z.ZodOptional<z.ZodString>;
20
20
  blockedSince: z.ZodOptional<z.ZodString>;
21
+ nodeId: z.ZodOptional<z.ZodString>;
21
22
  }, z.core.$strip>>;
22
23
  interactions: z.ZodArray<z.ZodObject<{
23
24
  id: z.ZodString;
@@ -33,6 +33,7 @@ const deckSourceSchema = z.object({
33
33
  sessionName: z.string().optional(),
34
34
  askedBy: z.string().optional(),
35
35
  blockedSince: z.string().optional(),
36
+ nodeId: z.string().optional(),
36
37
  });
37
38
  export const deckSchema = z.object({
38
39
  title: z.string().optional(),
package/dist/types.d.ts CHANGED
@@ -54,6 +54,10 @@ export interface DeckSource {
54
54
  sessionName?: string;
55
55
  askedBy?: string;
56
56
  blockedSince?: string;
57
+ /** Originating canvas node id (CRTR_NODE_ID) when the ask was raised inside
58
+ * a crouter canvas node. Lets per-node attention scoping attribute the ask
59
+ * to the node that raised it rather than every sibling sharing the cwd. */
60
+ nodeId?: string;
57
61
  }
58
62
  export interface Deck {
59
63
  title?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crouton-kit/humanloop",
3
- "version": "0.3.13",
3
+ "version": "0.3.14",
4
4
  "description": "Human-in-the-loop decision TUI — agents write questions, humans answer them",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",