@north-light/crouter 0.3.198 → 0.3.200
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/client.d.ts +18 -18
- package/dist/api/client.js +29 -37
- package/dist/api/dto/broker-ops.d.ts +3 -1
- package/dist/api/dto/broker.d.ts +13 -2
- package/dist/api/dto/broker.js +4 -4
- package/dist/api/dto/human.d.ts +6 -5
- package/dist/api/dto/inbox.d.ts +81 -34
- package/dist/api/dto/nodes.d.ts +8 -2
- package/dist/api/dto/profiles.d.ts +23 -0
- package/dist/api/dto/profiles.js +2 -2
- package/dist/api/dto/worktree.d.ts +3 -5
- package/dist/api/routes.d.ts +3 -5
- package/dist/api/routes.js +4 -6
- package/dist/builtin-memory/00-runtime-base.md +6 -6
- package/dist/builtin-memory/01-spine/01-no-manager.md +1 -1
- package/dist/builtin-memory/02-lifecycle/00-terminal.md +3 -3
- package/dist/builtin-memory/04-orchestration-kernel.md +6 -6
- package/dist/builtin-memory/05-kinds/design/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +2 -2
- package/dist/builtin-memory/05-kinds/review/00-base.md +2 -2
- package/dist/builtin-memory/05-kinds/review/01-orchestrator.md +1 -1
- package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +1 -1
- package/dist/builtin-memory/insights/capture.md +2 -2
- package/dist/builtin-memory/insights/init.md +3 -3
- package/dist/builtin-memory/internal/INDEX.md +1 -1
- package/dist/builtin-memory/internal/memory-loading.md +1 -1
- package/dist/builtin-memory/internal/nodes-and-canvas.md +2 -2
- package/dist/builtin-memory/internal/plugins.md +59 -2
- package/dist/builtin-memory/internal/storage-tiers.md +3 -1
- package/dist/builtin-memory/spec/roadmap.md +2 -2
- package/dist/builtin-memory/testing.md +1 -1
- package/dist/clients/attach/chrome/bash-jobs.js +3 -3
- package/dist/clients/attach/render/chat-view.d.ts +26 -1
- package/dist/clients/attach/render/chat-view.js +61 -11
- package/dist/clients/attach/render/page-block.d.ts +34 -0
- package/dist/clients/attach/render/page-block.js +226 -0
- package/dist/clients/attach/session/whip.d.ts +2 -0
- package/dist/clients/attach/session/whip.js +2 -0
- package/dist/clients/attach/viewer.js +1419 -993
- package/dist/clients/conversation/projection.js +18 -3
- package/dist/clients/inbox/__tests__/serial/inbox-controller.test.js +9 -6
- package/dist/clients/inbox/__tests__/serial/mount-panel.test.js +13 -21
- package/dist/clients/inbox/controller.js +10 -16
- package/dist/clients/inbox/page-adapter.d.ts +1 -3
- package/dist/clients/inbox/page-adapter.js +3 -4
- package/dist/clients/inbox/resolve.d.ts +1 -1
- package/dist/clients/inbox/resolve.js +3 -3
- package/dist/clients/inbox/review/document-surface.js +3 -1
- package/dist/clients/inbox/review/state.d.ts +2 -1
- package/dist/clients/inbox/review/state.js +5 -16
- package/dist/clients/inbox/tui/input.js +37 -19
- package/dist/clients/inbox/tui/panel.js +5 -31
- package/dist/clients/inbox/tui/render.d.ts +11 -0
- package/dist/clients/inbox/tui/render.js +71 -27
- package/dist/clients/inbox/tui/slots.d.ts +3 -1
- package/dist/clients/inbox/tui/slots.js +16 -12
- package/dist/clients/inbox/tui/types.d.ts +2 -7
- package/dist/clients/inbox/tui.js +2 -2
- package/dist/commands/__tests__/human.test.js +71 -114
- package/dist/commands/__tests__/node-message.test.js +14 -0
- package/dist/commands/attention.js +4 -4
- package/dist/commands/canvas-snapshot.js +1 -1
- package/dist/commands/canvas.js +1 -1
- package/dist/commands/dashboard.js +1 -1
- package/dist/commands/human/{html.d.ts → components.d.ts} +1 -1
- package/dist/commands/human/components.js +77 -0
- package/dist/commands/human/feedback.d.ts +2 -0
- package/dist/commands/human/feedback.js +108 -0
- package/dist/commands/human/prompts.d.ts +13 -5
- package/dist/commands/human/prompts.js +160 -97
- package/dist/commands/human/queue.js +57 -88
- package/dist/commands/human/shared.d.ts +2 -12
- package/dist/commands/human/shared.js +17 -11
- package/dist/commands/human.js +29 -21
- package/dist/commands/memory/origin.js +2 -2
- package/dist/commands/node/bash.js +4 -4
- package/dist/commands/node/inspect.js +3 -3
- package/dist/commands/node/lifecycle.js +1 -1
- package/dist/commands/node/message.js +2 -2
- package/dist/commands/node-worktree.js +8 -8
- package/dist/commands/pkg/browse.js +1 -1
- package/dist/commands/pkg/plugin-manage.js +129 -10
- package/dist/commands/profile/delete.js +41 -15
- package/dist/commands/profile.js +1 -1
- package/dist/commands/push.js +1 -1
- package/dist/commands/surface/node/focus.js +29 -14
- package/dist/commands/surface-edit.js +3 -3
- package/dist/commands/surface-inbox.d.ts +2 -0
- package/dist/commands/{human/inbox.js → surface-inbox.js} +14 -18
- package/dist/commands/surface.js +2 -1
- package/dist/commands/sys/doctor.js +60 -3
- package/dist/commands/sys/feedback.js +79 -25
- package/dist/commands/sys/settings.js +1 -1
- package/dist/core/__tests__/cron-broker-capacity.test.js +1 -1
- package/dist/core/__tests__/extension-abort.test.js +5 -2
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +13 -2
- package/dist/core/__tests__/fixtures/fake-engine.js +47 -3
- package/dist/core/__tests__/helpers/harness.js +17 -55
- package/dist/core/__tests__/human-cancel-guard.test.js +31 -10
- package/dist/core/__tests__/human-deliver.test.js +31 -26
- package/dist/core/__tests__/human-node-not-supervised.test.js +1 -1
- package/dist/core/__tests__/plugin-page-components.test.js +157 -0
- package/dist/core/__tests__/seam/broker-crash-teardown.test.js +4 -5
- package/dist/core/__tests__/seam/dormancy-release.test.js +40 -0
- package/dist/core/__tests__/serial/flagship-lifecycle.test.js +2 -2
- package/dist/core/__tests__/serial/human-deliver-e2e.test.js +12 -6
- package/dist/core/__tests__/serial/live-mutation.test.js +1 -1
- package/dist/core/__tests__/serial/tmux-surface.test.js +4 -2
- package/dist/core/__tests__/serial/worktree.test.js +24 -198
- package/dist/core/__tests__/session-cycles.test.js +22 -0
- package/dist/core/__tests__/stop-guard.test.js +4 -4
- package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +19 -4
- package/dist/core/bash-jobs.d.ts +6 -0
- package/dist/core/bash-jobs.js +10 -0
- package/dist/core/canvas/__tests__/attention.test.js +8 -5
- package/dist/core/canvas/__tests__/render-remote.test.js +5 -5
- package/dist/core/canvas/attention.js +8 -6
- package/dist/core/canvas/browse/model.d.ts +8 -2
- package/dist/core/canvas/browse/model.js +11 -4
- package/dist/core/canvas/canvas.d.ts +7 -0
- package/dist/core/canvas/canvas.js +37 -0
- package/dist/core/canvas/crons.d.ts +9 -0
- package/dist/core/canvas/crons.js +51 -0
- package/dist/core/canvas/node-order.d.ts +22 -1
- package/dist/core/canvas/node-order.js +26 -1
- package/dist/core/canvas/render-source.d.ts +5 -0
- package/dist/core/canvas/render-source.js +1 -0
- package/dist/core/canvas/types.d.ts +9 -3
- package/dist/core/command-plugins/bundle.d.ts +6 -1
- package/dist/core/command-plugins/bundle.js +26 -13
- package/dist/core/command.js +2 -1
- package/dist/core/config.d.ts +47 -1
- package/dist/core/config.js +137 -4
- package/dist/core/help.js +1 -1
- package/dist/core/human/__tests__/page-catalog.test.js +4 -0
- package/dist/core/human/__tests__/page-tickets.test.js +65 -52
- package/dist/core/human/__tests__/page.test.js +56 -98
- package/dist/core/human/__tests__/serial/inbox-core.test.js +6 -6
- package/dist/core/human/answer-text.js +3 -3
- package/dist/core/human/answer.d.ts +6 -4
- package/dist/core/human/answer.js +4 -10
- package/dist/core/human/component-docs.d.ts +11 -7
- package/dist/core/human/component-docs.js +361 -88
- package/dist/core/human/convention.d.ts +17 -3
- package/dist/core/human/convention.js +36 -5
- package/dist/core/human/feedback-companion.d.ts +20 -0
- package/dist/core/human/feedback-companion.js +98 -0
- package/dist/core/human/feedback.d.ts +65 -0
- package/dist/core/human/feedback.js +116 -0
- package/dist/core/human/page-catalog.d.ts +40 -5
- package/dist/core/human/page-catalog.js +102 -30
- package/dist/core/human/page-errors.d.ts +4 -0
- package/dist/core/human/page-errors.js +7 -0
- package/dist/core/human/page-eval.d.ts +20 -0
- package/dist/core/human/page-eval.js +123 -0
- package/dist/core/human/page-schema.d.ts +23 -191
- package/dist/core/human/page-schema.js +60 -89
- package/dist/core/human/page-synth.d.ts +1 -1
- package/dist/core/human/page-synth.js +15 -18
- package/dist/core/human/page.d.ts +12 -27
- package/dist/core/human/page.js +142 -474
- package/dist/core/human/root.d.ts +6 -2
- package/dist/core/human/root.js +12 -4
- package/dist/core/human/scan.d.ts +3 -4
- package/dist/core/human/scan.js +16 -15
- package/dist/core/human/summary.d.ts +1 -2
- package/dist/core/human/summary.js +2 -2
- package/dist/core/human/tickets.d.ts +20 -14
- package/dist/core/human/tickets.js +91 -31
- package/dist/core/human/types.d.ts +10 -2
- package/dist/core/preview-registry.js +8 -10
- package/dist/core/profiles/default-binding.d.ts +4 -0
- package/dist/core/profiles/default-binding.js +24 -0
- package/dist/core/profiles/deletion-reservation.d.ts +8 -0
- package/dist/core/profiles/deletion-reservation.js +38 -0
- package/dist/core/profiles/manifest.d.ts +3 -0
- package/dist/core/profiles/manifest.js +12 -0
- package/dist/core/profiles/select.js +2 -2
- package/dist/core/review/realize.js +3 -3
- package/dist/core/review/store.d.ts +6 -0
- package/dist/core/review/store.js +31 -0
- package/dist/core/runtime/bearings.d.ts +0 -4
- package/dist/core/runtime/bearings.js +4 -62
- package/dist/core/runtime/bin-contributions.d.ts +44 -0
- package/dist/core/runtime/bin-contributions.js +186 -0
- package/dist/core/runtime/broker/client-registry.d.ts +4 -0
- package/dist/core/runtime/broker/client-registry.js +13 -1
- package/dist/core/runtime/broker/extension-abort.d.ts +1 -1
- package/dist/core/runtime/broker/extension-abort.js +4 -2
- package/dist/core/runtime/broker/fault-retry.js +4 -0
- package/dist/core/runtime/broker/frame-dispatch.d.ts +3 -1
- package/dist/core/runtime/broker/frame-dispatch.js +5 -6
- package/dist/core/runtime/broker/read-ops.d.ts +1 -1
- package/dist/core/runtime/broker/read-ops.js +2 -2
- package/dist/core/runtime/broker/rebind.d.ts +1 -0
- package/dist/core/runtime/broker/rebind.js +6 -1
- package/dist/core/runtime/broker-extension-render.js +19 -0
- package/dist/core/runtime/broker-protocol.d.ts +14 -0
- package/dist/core/runtime/broker.d.ts +1 -1
- package/dist/core/runtime/broker.js +17 -6
- package/dist/core/runtime/front-door-env.d.ts +5 -0
- package/dist/core/runtime/front-door-env.js +16 -0
- package/dist/core/runtime/front-door.d.ts +1 -5
- package/dist/core/runtime/front-door.js +2 -5
- package/dist/core/runtime/host.d.ts +1 -1
- package/dist/core/runtime/invocation.d.ts +6 -0
- package/dist/core/runtime/invocation.js +10 -0
- package/dist/core/runtime/kickoff.js +34 -0
- package/dist/core/runtime/launch.d.ts +2 -6
- package/dist/core/runtime/node-read.js +4 -1
- package/dist/core/runtime/nodes.js +2 -0
- package/dist/core/runtime/promote.d.ts +1 -0
- package/dist/core/runtime/promote.js +3 -1
- package/dist/core/runtime/session-cycles.d.ts +6 -0
- package/dist/core/runtime/session-cycles.js +15 -1
- package/dist/core/runtime/session-visibility.d.ts +17 -8
- package/dist/core/runtime/session-visibility.js +19 -10
- package/dist/core/runtime/spawn-env.d.ts +9 -1
- package/dist/core/runtime/spawn-env.js +62 -2
- package/dist/core/runtime/stop-guard.d.ts +2 -2
- package/dist/core/runtime/stop-guard.js +2 -2
- package/dist/core/runtime/stop-signals.d.ts +1 -1
- package/dist/core/runtime/stop-signals.js +2 -2
- package/dist/core/runtime/tmux-bindings.js +1 -1
- package/dist/core/session-model/session-state.d.ts +4 -3
- package/dist/core/session-model/session-state.js +14 -1
- package/dist/core/user-settings.d.ts +21 -2
- package/dist/core/user-settings.js +32 -11
- package/dist/core/worktree.d.ts +15 -45
- package/dist/core/worktree.js +59 -261
- package/dist/daemon/api/__tests__/seam/profile-delete.test.d.ts +1 -0
- package/dist/daemon/api/__tests__/seam/profile-delete.test.js +386 -0
- package/dist/daemon/api/handlers/bash-jobs.js +1 -1
- package/dist/daemon/api/handlers/broker-ops.js +9 -5
- package/dist/daemon/api/handlers/feedback-comments.d.ts +2 -0
- package/dist/daemon/api/handlers/feedback-comments.js +207 -0
- package/dist/daemon/api/handlers/human.js +24 -20
- package/dist/daemon/api/handlers/inbox.d.ts +10 -0
- package/dist/daemon/api/handlers/inbox.js +39 -115
- package/dist/daemon/api/handlers/profiles.js +11 -29
- package/dist/daemon/api/map.d.ts +6 -1
- package/dist/daemon/api/map.js +23 -0
- package/dist/daemon/api/server.js +3 -1
- package/dist/daemon/companion-retire.d.ts +2 -0
- package/dist/daemon/companion-retire.js +33 -0
- package/dist/daemon/cron-run.js +14 -16
- package/dist/daemon/human/finish.d.ts +12 -7
- package/dist/daemon/human/finish.js +101 -38
- package/dist/daemon/human/sweep.js +5 -1
- package/dist/daemon/profile-delete.d.ts +7 -0
- package/dist/daemon/profile-delete.js +306 -0
- package/dist/daemon/reconcilers/broker-supervision.js +3 -1
- package/dist/daemon/review/deliver.js +3 -3
- package/dist/daemon/review/finish.d.ts +0 -2
- package/dist/daemon/review/finish.js +1 -29
- package/dist/pi-extensions/__tests__/canvas-bash-valve.test.js +56 -1
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +4 -4
- package/dist/pi-extensions/canvas-bash-valve.js +19 -5
- package/dist/pi-extensions/canvas-inbox-watcher.js +1 -1
- package/dist/pi-extensions/canvas-review-boundary.d.ts +4 -0
- package/dist/pi-extensions/canvas-review-boundary.js +18 -9
- package/dist/pi-extensions/canvas-stophook.js +4 -4
- package/dist/shared/generated-context.js +2 -2
- package/dist/types.d.ts +44 -2
- package/dist/types.js +7 -2
- package/package.json +6 -5
- package/runtime.lock.json +5 -33
- package/dist/builtin-memory/init.md +0 -38
- package/dist/builtin-memory/plan.md +0 -19
- package/dist/builtin-memory/spec.md +0 -19
- package/dist/commands/human/doc.d.ts +0 -2
- package/dist/commands/human/doc.js +0 -91
- package/dist/commands/human/html.js +0 -81
- package/dist/commands/human/inbox.d.ts +0 -2
- package/dist/core/human/__tests__/html-markdown.test.js +0 -52
- package/dist/core/human/__tests__/page-render.test.js +0 -66
- package/dist/core/human/html-markdown.d.ts +0 -3
- package/dist/core/human/html-markdown.js +0 -288
- package/dist/core/human/page-render.d.ts +0 -4
- package/dist/core/human/page-render.js +0 -105
- package/dist/pages/bundle.css +0 -1
- package/dist/pages/bundle.js +0 -1778
- package/dist/pages/comments.d.ts +0 -72
- package/dist/pages/comments.js +0 -176
- package/dist/pages/controls.d.ts +0 -98
- package/dist/pages/controls.js +0 -261
- package/dist/pages/elements/cards.d.ts +0 -28
- package/dist/pages/elements/cards.js +0 -915
- package/dist/pages/elements/chart.d.ts +0 -23
- package/dist/pages/elements/chart.js +0 -664
- package/dist/pages/elements/options.d.ts +0 -30
- package/dist/pages/elements/options.js +0 -742
- package/dist/pages/elements/pages.d.ts +0 -30
- package/dist/pages/elements/pages.js +0 -377
- package/dist/pages/elements/slot.d.ts +0 -26
- package/dist/pages/elements/slot.js +0 -112
- package/dist/pages/elements/table.d.ts +0 -36
- package/dist/pages/elements/table.js +0 -1043
- package/dist/pages/elements/text.d.ts +0 -31
- package/dist/pages/elements/text.js +0 -1175
- package/dist/pages/entry.d.ts +0 -8
- package/dist/pages/entry.js +0 -8
- package/dist/pages/host.d.ts +0 -134
- package/dist/pages/host.js +0 -165
- package/dist/pages/readonly.d.ts +0 -24
- package/dist/pages/readonly.js +0 -31
- package/dist/pages/register.d.ts +0 -2
- package/dist/pages/register.js +0 -3
- package/dist/pages/responses.d.ts +0 -37
- package/dist/pages/responses.js +0 -56
- package/dist/pages/slot-config.d.ts +0 -36
- package/dist/pages/slot-config.js +0 -50
- package/dist/pages/types.d.ts +0 -98
- package/dist/pages/types.js +0 -23
- /package/dist/{core/human/__tests__/html-markdown.test.d.ts → commands/__tests__/node-message.test.d.ts} +0 -0
- /package/dist/core/{human/__tests__/page-render.test.d.ts → __tests__/plugin-page-components.test.d.ts} +0 -0
|
@@ -13,21 +13,19 @@ function uniqueIds(items, ctx, label) {
|
|
|
13
13
|
seen.add(item.id);
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
|
+
// Response comments qualify the answer itself, so anchors name only answerable structure:
|
|
17
|
+
// one of a question's options, or a table row. Feedback on rendered page content — including
|
|
18
|
+
// the question text itself — is a ticket-level feedback comment (feedback.ts), not part of
|
|
19
|
+
// any response.
|
|
16
20
|
export const commentAnchorSchema = z.discriminatedUnion('kind', [
|
|
17
|
-
z.object({ kind: z.literal('whole') }).strict(),
|
|
18
21
|
z.object({ kind: z.literal('option'), optionId: itemIdSchema }).strict(),
|
|
19
22
|
z.object({ kind: z.literal('row'), rowId: itemIdSchema }).strict(),
|
|
20
|
-
z.object({ kind: z.literal('column'), columnId: itemIdSchema }).strict(),
|
|
21
|
-
z.object({ kind: z.literal('card'), cardId: itemIdSchema }).strict(),
|
|
22
|
-
z.object({ kind: z.literal('range'), start: z.number().int().nonnegative(), end: z.number().int().nonnegative(), quote: z.string() }).strict().superRefine((anchor, ctx) => {
|
|
23
|
-
if (anchor.end < anchor.start)
|
|
24
|
-
ctx.addIssue({ code: 'custom', path: ['end'], message: 'range end must be greater than or equal to start' });
|
|
25
|
-
}),
|
|
26
23
|
]);
|
|
27
24
|
export const commentSchema = z.object({ id: z.string().min(1), anchor: commentAnchorSchema, text: z.string() }).strict();
|
|
28
25
|
export const optionSchema = z.object({ id: itemIdSchema, label: z.string().min(1), description: z.string().optional() }).strict();
|
|
29
26
|
export const optionsConfigSchema = z.object({
|
|
30
27
|
label: z.string().optional(),
|
|
28
|
+
body: z.string().optional(),
|
|
31
29
|
options: z.array(optionSchema).min(1).superRefine((items, ctx) => uniqueIds(items, ctx, 'option')),
|
|
32
30
|
mode: z.enum(['single', 'multi']),
|
|
33
31
|
allowFreetext: z.boolean().optional(),
|
|
@@ -35,49 +33,38 @@ export const optionsConfigSchema = z.object({
|
|
|
35
33
|
freetextPlaceholder: z.string().optional(),
|
|
36
34
|
}).strict();
|
|
37
35
|
export const optionsResponseSchema = z.object({ selectedOptionIds: z.array(itemIdSchema), comments: z.array(commentSchema), freetext: z.string().optional() }).strict();
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
export const textConfigSchema = z.object({ label: z.string().optional(), initialText: z.string(),
|
|
42
|
-
|
|
43
|
-
ctx.addIssue({ code: 'custom', path: ['editable'], message: 'single-line text is always editable; drop editable: false' });
|
|
44
|
-
});
|
|
45
|
-
export const textResponseSchema = z.object({ text: z.string(), edited: z.boolean(), comments: z.array(commentSchema) }).strict();
|
|
36
|
+
// Text is a writing surface, always: its whole point is the string the user hands back, so
|
|
37
|
+
// there is no read-only mode. `singleLine` only swaps the multi-line surface for one compact
|
|
38
|
+
// form field — a subject line, a name, a URL.
|
|
39
|
+
export const textConfigSchema = z.object({ label: z.string().optional(), initialText: z.string(), placeholder: z.string().optional(), singleLine: z.boolean().optional() }).strict();
|
|
40
|
+
export const textResponseSchema = z.object({ text: z.string(), edited: z.boolean() }).strict();
|
|
46
41
|
export const tableColumnSchema = z.object({ id: itemIdSchema, label: z.string().min(1), align: z.enum(['left', 'right']).optional(), mono: z.boolean().optional() }).strict();
|
|
47
42
|
export const tableCellSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
|
|
48
43
|
export const tableRowSchema = z.object({ id: itemIdSchema, cells: z.record(z.string(), tableCellSchema) }).strict();
|
|
49
44
|
export const tableRowsSchema = z.array(tableRowSchema).superRefine((items, ctx) => uniqueIds(items, ctx, 'row'));
|
|
50
45
|
const tableConfigFields = {
|
|
51
46
|
label: z.string().optional(),
|
|
47
|
+
body: z.string().optional(),
|
|
52
48
|
columns: z.array(tableColumnSchema).min(1).superRefine((items, ctx) => uniqueIds(items, ctx, 'column')),
|
|
53
49
|
rows: tableRowsSchema.optional(),
|
|
54
50
|
rowSelect: selectModeSchema.default('none'),
|
|
55
51
|
columnSelect: selectModeSchema.default('none'),
|
|
56
52
|
};
|
|
57
|
-
/**
|
|
53
|
+
/** Table config: its data is always embedded. */
|
|
58
54
|
export const tableConfigSchema = z.object(tableConfigFields).strict();
|
|
59
|
-
/** Authored table config: `source` is resolved before the manifest is stored. */
|
|
60
|
-
export const authoredTableConfigSchema = z.object({ ...tableConfigFields, source: z.string() }).strict().superRefine((config, ctx) => {
|
|
61
|
-
if (config.rows !== undefined)
|
|
62
|
-
ctx.addIssue({ code: 'custom', message: 'table rows and source are mutually exclusive' });
|
|
63
|
-
});
|
|
64
55
|
export const tableResponseSchema = z.object({ selectedRowIds: z.array(itemIdSchema), selectedColumnIds: z.array(itemIdSchema), comments: z.array(commentSchema) }).strict();
|
|
65
56
|
export const cardSchema = z.object({ id: itemIdSchema, title: z.string().min(1), subtitle: z.string().optional(), body: z.string().optional(), tag: z.string().optional() }).strict();
|
|
66
57
|
export const cardsSchema = z.array(cardSchema).superRefine((items, ctx) => uniqueIds(items, ctx, 'card'));
|
|
67
58
|
const cardsConfigFields = {
|
|
68
59
|
label: z.string().optional(),
|
|
60
|
+
body: z.string().optional(),
|
|
69
61
|
cards: cardsSchema.optional(),
|
|
70
62
|
mode: z.enum(['single', 'multi']),
|
|
71
63
|
columns: z.union([z.literal(2), z.literal(3)]).optional(),
|
|
72
64
|
};
|
|
73
|
-
/**
|
|
65
|
+
/** Cards config: its data is always embedded. */
|
|
74
66
|
export const cardsConfigSchema = z.object(cardsConfigFields).strict();
|
|
75
|
-
|
|
76
|
-
export const authoredCardsConfigSchema = z.object({ ...cardsConfigFields, source: z.string() }).strict().superRefine((config, ctx) => {
|
|
77
|
-
if (config.cards !== undefined)
|
|
78
|
-
ctx.addIssue({ code: 'custom', message: 'cards data and source are mutually exclusive' });
|
|
79
|
-
});
|
|
80
|
-
export const cardsResponseSchema = z.object({ selectedCardIds: z.array(itemIdSchema), comments: z.array(commentSchema) }).strict();
|
|
67
|
+
export const cardsResponseSchema = z.object({ selectedCardIds: z.array(itemIdSchema) }).strict();
|
|
81
68
|
export const chartSeriesSchema = z.object({ field: z.string().min(1), label: z.string().optional() }).strict();
|
|
82
69
|
export const chartDataRowsSchema = z.array(z.record(z.string(), z.unknown()));
|
|
83
70
|
const chartConfigFields = {
|
|
@@ -87,26 +74,27 @@ const chartConfigFields = {
|
|
|
87
74
|
title: z.string().optional(),
|
|
88
75
|
data: chartDataRowsSchema.optional(),
|
|
89
76
|
};
|
|
90
|
-
/**
|
|
77
|
+
/** Chart config: its data is always embedded. */
|
|
91
78
|
export const chartConfigSchema = z.object(chartConfigFields).strict();
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (config.data !== undefined)
|
|
95
|
-
ctx.addIssue({ code: 'custom', message: 'chart data and source are mutually exclusive' });
|
|
96
|
-
});
|
|
97
|
-
const sourceSchema = z.object({ sessionName: z.string().optional(), askedBy: z.string().optional(), blockedSince: z.string().optional(), profileName: z.string().optional(), nodeId: z.string().optional() }).strict();
|
|
79
|
+
const sourceSchema = z.object({ sessionName: z.string().optional(), askedBy: z.string().optional(), emittedAt: z.string().datetime({ offset: true }).optional(), profileName: z.string().optional(), nodeId: z.string().optional() }).strict();
|
|
80
|
+
const deliverySchema = z.object({ placement: z.enum(['inline', 'panel']), inbox: z.boolean(), reply: z.boolean() }).strict();
|
|
98
81
|
const rawSlotSchema = z.object({ id: idSchema.optional(), kind: z.string().min(1), step: z.number().int().nonnegative(), config: jsonObjectSchema, unvalidated: z.literal(true).optional(), display: z.literal(true).optional() }).strict();
|
|
99
82
|
const rawPageManifestSchema = z.object({
|
|
100
|
-
schema: z.literal('crtr.page/
|
|
101
|
-
dialect: z.enum(['
|
|
83
|
+
schema: z.literal('crtr.page/v2'),
|
|
84
|
+
dialect: z.enum(['jsx', 'html']),
|
|
102
85
|
title: z.string().trim().min(1),
|
|
103
86
|
subtitle: z.string().optional(),
|
|
104
|
-
|
|
105
|
-
document: z.enum(['page.
|
|
87
|
+
delivery: deliverySchema,
|
|
88
|
+
document: z.enum(['page.tsx', 'page.html']),
|
|
106
89
|
steps: z.number().int().positive(),
|
|
107
90
|
slots: z.array(rawSlotSchema),
|
|
108
91
|
source: sourceSchema.optional(),
|
|
109
|
-
}).strict()
|
|
92
|
+
}).strict().superRefine((manifest, ctx) => {
|
|
93
|
+
if ((manifest.dialect === 'jsx') !== (manifest.document === 'page.tsx'))
|
|
94
|
+
ctx.addIssue({ code: 'custom', path: ['document'], message: 'document must agree with dialect' });
|
|
95
|
+
if (manifest.dialect === 'html' && (manifest.steps !== 1 || manifest.slots.length !== 0))
|
|
96
|
+
ctx.addIssue({ code: 'custom', path: ['slots'], message: 'HTML pages have exactly one step and no slots' });
|
|
97
|
+
});
|
|
110
98
|
export const BUILTIN_PAGE_CONFIG_SCHEMAS = {
|
|
111
99
|
options: optionsConfigSchema,
|
|
112
100
|
text: textConfigSchema,
|
|
@@ -114,13 +102,6 @@ export const BUILTIN_PAGE_CONFIG_SCHEMAS = {
|
|
|
114
102
|
cards: cardsConfigSchema,
|
|
115
103
|
chart: chartConfigSchema,
|
|
116
104
|
};
|
|
117
|
-
const AUTHORED_PAGE_CONFIG_SCHEMAS = {
|
|
118
|
-
options: optionsConfigSchema,
|
|
119
|
-
text: textConfigSchema,
|
|
120
|
-
table: z.union([tableConfigSchema, authoredTableConfigSchema]),
|
|
121
|
-
cards: z.union([cardsConfigSchema, authoredCardsConfigSchema]),
|
|
122
|
-
chart: z.union([chartConfigSchema, authoredChartConfigSchema]),
|
|
123
|
-
};
|
|
124
105
|
export const BUILTIN_PAGE_RESPONSE_SCHEMAS = {
|
|
125
106
|
options: optionsResponseSchema,
|
|
126
107
|
text: textResponseSchema,
|
|
@@ -145,10 +126,8 @@ export function isResponseBearingSlot(slot) {
|
|
|
145
126
|
}
|
|
146
127
|
function validateManifest(parsed, productComponents, authored) {
|
|
147
128
|
const manifest = rawPageManifestSchema.parse(parsed);
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
if (manifest.dialect === 'md' && manifest.steps !== 1)
|
|
151
|
-
throw new Error(`md page steps must be 1; received ${manifest.steps}`);
|
|
129
|
+
if (!authored && manifest.dialect === 'html')
|
|
130
|
+
return manifest;
|
|
152
131
|
const seen = new Set();
|
|
153
132
|
const slots = manifest.slots.map((raw, index) => {
|
|
154
133
|
if (raw.step >= manifest.steps)
|
|
@@ -159,29 +138,38 @@ function validateManifest(parsed, productComponents, authored) {
|
|
|
159
138
|
throw new Error(`built-in slot kind "${raw.kind}" cannot be unvalidated`);
|
|
160
139
|
if (raw.display === true)
|
|
161
140
|
throw new Error(`built-in slot kind "${raw.kind}" cannot set display: true`);
|
|
162
|
-
const result =
|
|
141
|
+
const result = BUILTIN_PAGE_CONFIG_SCHEMAS[raw.kind].safeParse(raw.config);
|
|
163
142
|
if (!result.success)
|
|
164
143
|
throw new Error(`invalid config for slot ${raw.id === undefined ? `#${index}` : `"${raw.id}"`} (${raw.kind}): ${issueText(result.error)}`);
|
|
144
|
+
// Authoring-time only: persisted manifests predate this rule and must keep reading.
|
|
145
|
+
if (authored && raw.kind === 'options') {
|
|
146
|
+
const options = result.data;
|
|
147
|
+
const slotName = raw.id === undefined ? `#${index}` : `"${raw.id}"`;
|
|
148
|
+
if ((options.label ?? '').trim() === '')
|
|
149
|
+
throw new Error(`slot ${slotName} (options): label is required — the question itself, drawn as the bold first line`);
|
|
150
|
+
if ((options.body ?? '').trim() === '')
|
|
151
|
+
throw new Error(`slot ${slotName} (options): body is required — the context under the question a label cannot carry`);
|
|
152
|
+
}
|
|
165
153
|
slot = { ...(raw.id === undefined ? {} : { id: raw.id }), kind: raw.kind, step: raw.step, config: result.data };
|
|
166
154
|
}
|
|
167
155
|
else {
|
|
168
|
-
const component = productPageComponent(raw.kind, productComponents);
|
|
169
|
-
if (component === undefined)
|
|
156
|
+
const component = productComponents === undefined ? undefined : productPageComponent(raw.kind, productComponents);
|
|
157
|
+
if (authored && component === undefined)
|
|
170
158
|
throw new Error(`unregistered page slot kind "${raw.kind}" at slot #${index}`);
|
|
171
159
|
if (raw.unvalidated !== true)
|
|
172
|
-
throw new Error(`registered
|
|
173
|
-
if (!authored
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
160
|
+
throw new Error(`registered page slot kind "${raw.kind}" must set unvalidated: true`);
|
|
161
|
+
if (!authored)
|
|
162
|
+
slot = { ...(raw.id === undefined ? {} : { id: raw.id }), kind: raw.kind, step: raw.step, config: raw.config, unvalidated: true, ...(raw.display === true ? { display: true } : {}) };
|
|
163
|
+
else {
|
|
164
|
+
if (raw.display === true && component?.display !== true)
|
|
165
|
+
throw new Error(`non-display page slot kind "${raw.kind}" cannot set display: true`);
|
|
166
|
+
slot = { ...(raw.id === undefined ? {} : { id: raw.id }), kind: raw.kind, step: raw.step, config: raw.config, unvalidated: true, ...(component?.display === true ? { display: true } : {}) };
|
|
167
|
+
}
|
|
180
168
|
}
|
|
181
169
|
if (isResponseBearingSlot(slot) && slot.id === undefined) {
|
|
182
170
|
throw new Error(slot.unvalidated === true
|
|
183
|
-
? `product slot kind "${slot.kind}" at slot #${index} requires an id
|
|
184
|
-
: `response-bearing slot kind "${slot.kind}" at slot #${index} requires an id
|
|
171
|
+
? `product slot kind "${slot.kind}" at slot #${index} requires an id prop`
|
|
172
|
+
: `response-bearing slot kind "${slot.kind}" at slot #${index} requires an id prop`);
|
|
185
173
|
}
|
|
186
174
|
if (slot.id !== undefined) {
|
|
187
175
|
if (seen.has(slot.id))
|
|
@@ -192,26 +180,25 @@ function validateManifest(parsed, productComponents, authored) {
|
|
|
192
180
|
});
|
|
193
181
|
return { ...manifest, slots };
|
|
194
182
|
}
|
|
195
|
-
/** Validate a persisted manifest.
|
|
196
|
-
export function validatePageManifest(parsed
|
|
197
|
-
return validateManifest(parsed,
|
|
183
|
+
/** Validate a persisted manifest. Publish-time validation made its slots authoritative, so reads do not resolve a component catalog. */
|
|
184
|
+
export function validatePageManifest(parsed) {
|
|
185
|
+
return validateManifest(parsed, undefined, false);
|
|
198
186
|
}
|
|
199
|
-
/** Validate an authored
|
|
187
|
+
/** Validate a manifest derived from an authored page, where the display flag comes from the registration rather than the source. */
|
|
200
188
|
export function validateAuthoredPageManifest(parsed, productComponents = []) {
|
|
201
189
|
return validateManifest(parsed, productComponents, true);
|
|
202
190
|
}
|
|
203
|
-
export function createPageManifestSchema(
|
|
191
|
+
export function createPageManifestSchema() {
|
|
204
192
|
return z.custom((value) => {
|
|
205
193
|
try {
|
|
206
|
-
validatePageManifest(value
|
|
194
|
+
validatePageManifest(value);
|
|
207
195
|
return true;
|
|
208
196
|
}
|
|
209
197
|
catch {
|
|
210
198
|
return false;
|
|
211
199
|
}
|
|
212
|
-
}, { error: 'invalid page manifest' }).transform((value) => validatePageManifest(value
|
|
200
|
+
}, { error: 'invalid page manifest' }).transform((value) => validatePageManifest(value));
|
|
213
201
|
}
|
|
214
|
-
/** Built-in-only manifest schema; product-aware callers use createPageManifestSchema. */
|
|
215
202
|
export const pageManifestSchema = createPageManifestSchema();
|
|
216
203
|
function assertUnique(values, slotId, field) {
|
|
217
204
|
if (new Set(values).size !== values.length)
|
|
@@ -221,30 +208,16 @@ function validateComments(slot, comments) {
|
|
|
221
208
|
const config = slot.config;
|
|
222
209
|
for (const comment of comments) {
|
|
223
210
|
const anchor = comment.anchor;
|
|
224
|
-
if (anchor.kind === 'whole')
|
|
225
|
-
continue;
|
|
226
211
|
if (slot.kind === 'options' && anchor.kind === 'option') {
|
|
227
212
|
if (!config.options.some((option) => option.id === anchor.optionId))
|
|
228
213
|
throw new Error(`slot "${slot.id}" comment names unknown option id "${anchor.optionId}"`);
|
|
229
214
|
continue;
|
|
230
215
|
}
|
|
231
|
-
if (slot.kind === 'text' && anchor.kind === 'range')
|
|
232
|
-
continue;
|
|
233
216
|
if (slot.kind === 'table' && anchor.kind === 'row') {
|
|
234
217
|
if (!(config.rows ?? []).some((row) => row.id === anchor.rowId))
|
|
235
218
|
throw new Error(`slot "${slot.id}" comment names unknown row id "${anchor.rowId}"`);
|
|
236
219
|
continue;
|
|
237
220
|
}
|
|
238
|
-
if (slot.kind === 'table' && anchor.kind === 'column') {
|
|
239
|
-
if (!config.columns.some((column) => column.id === anchor.columnId))
|
|
240
|
-
throw new Error(`slot "${slot.id}" comment names unknown column id "${anchor.columnId}"`);
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
if (slot.kind === 'cards' && anchor.kind === 'card') {
|
|
244
|
-
if (!(config.cards ?? []).some((card) => card.id === anchor.cardId))
|
|
245
|
-
throw new Error(`slot "${slot.id}" comment names unknown card id "${anchor.cardId}"`);
|
|
246
|
-
continue;
|
|
247
|
-
}
|
|
248
221
|
throw new Error(`slot "${slot.id}" does not allow comment anchor kind "${anchor.kind}"`);
|
|
249
222
|
}
|
|
250
223
|
}
|
|
@@ -281,7 +254,6 @@ function parseResponse(slot, raw) {
|
|
|
281
254
|
const result = textResponseSchema.safeParse(raw);
|
|
282
255
|
if (!result.success)
|
|
283
256
|
throw new Error(`invalid response for slot "${slot.id}": ${issueText(result.error)}`);
|
|
284
|
-
validateComments(slot, result.data.comments);
|
|
285
257
|
return result.data;
|
|
286
258
|
}
|
|
287
259
|
if (slot.kind === 'table') {
|
|
@@ -319,7 +291,6 @@ function parseResponse(slot, raw) {
|
|
|
319
291
|
throw new Error(`slot "${slot.id}" selects unknown card id "${id}"`);
|
|
320
292
|
if (config.mode === 'single' && response.selectedCardIds.length > 1)
|
|
321
293
|
throw new Error(`slot "${slot.id}" is single-select but received ${response.selectedCardIds.length} card ids`);
|
|
322
|
-
validateComments(slot, response.comments);
|
|
323
294
|
return response;
|
|
324
295
|
}
|
|
325
296
|
throw new Error(`slot "${slot.id}" kind "${slot.kind}" does not accept a response`);
|
|
@@ -344,5 +315,5 @@ function validateResponses(manifest, raw, partial) {
|
|
|
344
315
|
}
|
|
345
316
|
/** Validate a complete final response map. */
|
|
346
317
|
export function validatePageResponses(manifest, responses) { return validateResponses(manifest, responses, false); }
|
|
347
|
-
/** Validate an autosaved response map, permitting omitted response-bearing
|
|
318
|
+
/** Validate an autosaved response map, permitting omitted response-bearing components. */
|
|
348
319
|
export function validatePartialPageResponses(manifest, responses) { return validateResponses(manifest, responses, true); }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Build a complete
|
|
1
|
+
/** Build a complete TSX page from title, subtitle, and body for internal producers. */
|
|
2
2
|
export declare function synthesizedPageDocument(title: string, subtitle: string, body: string, responseBearing: boolean): string;
|
|
3
3
|
/** Materialize an internally generated document into a private temp dir; the caller removes it after submission. */
|
|
4
4
|
export declare function writeSynthesizedPage(document: string): {
|
|
@@ -1,33 +1,30 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
2
|
import { mkdtempSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
function bodyHtml(body) {
|
|
4
|
+
/** Text reaches JSX as a string expression, so arbitrary bytes need no markup escaping. */
|
|
5
|
+
function jsxText(value) { return `{${JSON.stringify(value)}}`; }
|
|
6
|
+
function bodyJsx(body) {
|
|
8
7
|
if (body === '')
|
|
9
8
|
return '';
|
|
10
|
-
|
|
9
|
+
const lines = body.replace(/\r\n/g, '\n').split('\n');
|
|
10
|
+
return ` <p className="whitespace-pre-wrap">${lines.map(jsxText).join('<br />')}</p>\n`;
|
|
11
11
|
}
|
|
12
|
-
/** Build a complete
|
|
12
|
+
/** Build a complete TSX page from title, subtitle, and body for internal producers. */
|
|
13
13
|
export function synthesizedPageDocument(title, subtitle, body, responseBearing) {
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
</head><body>
|
|
23
|
-
${contents}${contents === '' || interactive === '' ? '' : '\n'}${interactive}
|
|
24
|
-
</body></html>
|
|
14
|
+
const interactive = responseBearing ? ` <UserText id="response" initialText="" />\n` : '';
|
|
15
|
+
const subtitleProp = subtitle === '' ? '' : ` subtitle=${jsxText(subtitle)}`;
|
|
16
|
+
return `export default function SynthesizedPage() {
|
|
17
|
+
return (
|
|
18
|
+
<Page title=${jsxText(title)}${subtitleProp}>
|
|
19
|
+
${bodyJsx(body)}${interactive} </Page>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
25
22
|
`;
|
|
26
23
|
}
|
|
27
24
|
/** Materialize an internally generated document into a private temp dir; the caller removes it after submission. */
|
|
28
25
|
export function writeSynthesizedPage(document) {
|
|
29
26
|
const dir = mkdtempSync(join(tmpdir(), 'crtr-human-page-'));
|
|
30
|
-
const path = join(dir, 'page.
|
|
27
|
+
const path = join(dir, 'page.tsx');
|
|
31
28
|
writeFileSync(path, document, { encoding: 'utf8', mode: 0o600 });
|
|
32
29
|
return { dir, path };
|
|
33
30
|
}
|
|
@@ -1,29 +1,14 @@
|
|
|
1
1
|
import type { ProductPageComponents } from '../../types.js';
|
|
2
|
-
import { type
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export type PageSourceProjection = PageSourceBlock[];
|
|
14
|
-
/** A page failed authoring or validation; the caller can report it as bad page input. */
|
|
15
|
-
export declare class PageAuthoringError extends Error {
|
|
16
|
-
constructor(message: string);
|
|
17
|
-
}
|
|
18
|
-
/** Derive the transport manifest from one authored HTML page document. */
|
|
19
|
-
export declare function derivePageManifestFromDocument(document: string, dialect: AuthoredPageDialect, productComponents?: ProductPageComponents, source?: PageSource): AuthoredPageManifest;
|
|
20
|
-
/** Derive the transport manifest from one authored HTML page source file. */
|
|
21
|
-
export declare function derivePageManifest(sourceFile: string, dialect: AuthoredPageDialect, productComponents?: ProductPageComponents, source?: PageSource): AuthoredPageManifest;
|
|
22
|
-
/** Read source files into their built-in slots, returning a self-contained stored manifest. */
|
|
23
|
-
export declare function snapshotPageSources(manifest: AuthoredPageManifest, productComponents?: ProductPageComponents): PageManifest;
|
|
24
|
-
/** Replace every authored slot config with its stored, self-contained config for runtime rendering. */
|
|
25
|
-
export declare function embedPageSlotConfigs(document: string, manifest: PageManifest): string;
|
|
2
|
+
import { type PageDelivery, type PageManifest, type PageSource } from './page-schema.js';
|
|
3
|
+
import { PageAuthoringError } from './page-errors.js';
|
|
4
|
+
export { PageAuthoringError };
|
|
5
|
+
/** Compile one authored TSX page to the CommonJS module the Gateway evaluates.
|
|
6
|
+
* Registry names stay free identifiers; the Gateway supplies them at eval. */
|
|
7
|
+
export declare function compilePage(document: string): string;
|
|
8
|
+
/** Derive the transport manifest from one authored TSX page document. */
|
|
9
|
+
export declare function derivePageManifestFromDocument(document: string, productComponents?: ProductPageComponents, source?: PageSource, delivery?: PageDelivery): PageManifest;
|
|
10
|
+
export declare function deriveHtmlPageManifest(document: string, source?: PageSource, delivery?: PageDelivery): PageManifest;
|
|
11
|
+
/** Derive the transport manifest from one authored TSX page source file. */
|
|
12
|
+
export declare function derivePageManifest(sourceFile: string, productComponents?: ProductPageComponents, source?: PageSource, delivery?: PageDelivery): PageManifest;
|
|
26
13
|
/** Read and validate page.json from a ticket directory. */
|
|
27
|
-
export declare function parsePage(dir: string
|
|
28
|
-
/** Project authored source for local rendering and verify its slot references against the manifest. */
|
|
29
|
-
export declare function parsePageSource(document: string, manifest: PageManifest, productComponents?: ProductPageComponents): PageSourceProjection;
|
|
14
|
+
export declare function parsePage(dir: string): PageManifest;
|