@north-light/crouter 0.3.221 → 0.3.223
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 +21 -1
- package/dist/api/client.js +34 -0
- package/dist/api/dto/chat-inventory.d.ts +13 -0
- package/dist/api/dto/human-requests.d.ts +88 -0
- package/dist/api/dto/human-requests.js +4 -0
- package/dist/api/dto/human.d.ts +3 -0
- package/dist/api/dto/reviews.d.ts +2 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/routes.d.ts +7 -0
- package/dist/api/routes.js +10 -0
- package/dist/builtin-memory/00-runtime-base/00-authoring.md +31 -0
- package/dist/builtin-memory/00-runtime-base/01-escalation.md +14 -0
- package/dist/builtin-memory/{insights/listen.md → 00-runtime-base/02-insight-capture.md} +1 -0
- package/dist/builtin-memory/02-turn-lifecycle/00-ending-a-turn.md +27 -0
- package/dist/builtin-memory/{02-lifecycle/01-resident.md → 02-turn-lifecycle/02-resident.md} +5 -0
- package/dist/builtin-memory/04-base-worker.md +4 -8
- package/dist/builtin-memory/04-orchestration-kernel.md +1 -1
- package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +1 -0
- package/dist/builtin-memory/05-kinds/advisor/advice-contract.md +1 -0
- package/dist/builtin-memory/05-kinds/design/00-base.md +2 -1
- package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +2 -1
- package/dist/builtin-memory/05-kinds/design/design-contract.md +19 -0
- package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -0
- package/dist/builtin-memory/05-kinds/developer/01-orchestrator.md +1 -0
- package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -0
- package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +1 -0
- package/dist/builtin-memory/05-kinds/general/00-base.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/00-base.md +2 -1
- package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +2 -1
- package/dist/builtin-memory/05-kinds/plan/plan-contract.md +28 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/lens-contract.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +1 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +1 -0
- package/dist/builtin-memory/05-kinds/review/00-base.md +1 -0
- package/dist/builtin-memory/05-kinds/review/01-orchestrator.md +1 -0
- package/dist/builtin-memory/05-kinds/review/companion/00-base.md +1 -0
- package/dist/builtin-memory/05-kinds/review/security-findings.md +1 -0
- package/dist/builtin-memory/05-kinds/spec/00-base.md +4 -3
- package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +1 -0
- package/dist/builtin-memory/05-kinds/spec/requirements.md +1 -0
- package/dist/builtin-memory/design/guide.md +35 -0
- package/dist/builtin-memory/design/roadmap.md +21 -0
- package/dist/builtin-memory/insights/capture.md +1 -1
- package/dist/builtin-memory/internal/memory-loading.md +4 -4
- package/dist/builtin-memory/internal/plugins.md +10 -1
- package/dist/builtin-memory/internal/storage-tiers.md +1 -1
- package/dist/builtin-memory/plan/roadmap.md +6 -28
- package/dist/builtin-memory/spec/guide.md +19 -8
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +28 -15
- package/dist/clients/attach/render/markdown-source.js +106 -1
- package/dist/clients/attach/session/file-links.d.ts +13 -4
- package/dist/clients/attach/session/file-links.js +54 -58
- package/dist/clients/attach/viewer.js +545 -543
- package/dist/clients/inbox/controller.js +1 -1
- package/dist/clients/inbox/page-adapter.js +2 -1
- package/dist/clients/inbox/resolve.d.ts +1 -0
- package/dist/clients/inbox/review/review-client.js +3 -1
- package/dist/clients/inbox/tui/panel.js +23 -4
- package/dist/clients/inbox/tui/render.js +6 -0
- package/dist/clients/inbox/tui/types.d.ts +8 -0
- package/dist/commands/__tests__/human.test.js +2 -2
- package/dist/commands/human/request.d.ts +2 -0
- package/dist/commands/human/request.js +281 -0
- package/dist/commands/human.js +5 -2
- package/dist/commands/memory/shared.d.ts +2 -2
- package/dist/commands/memory/shared.js +11 -6
- package/dist/commands/pkg/browse/doc-view.js +2 -0
- package/dist/commands/sys/config.js +2 -2
- package/dist/commands/sys/doctor.js +54 -2
- package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +7 -4
- package/dist/core/__tests__/fixtures/memory-slash-live-probe.d.ts +1 -0
- package/dist/core/__tests__/fixtures/memory-slash-live-probe.js +71 -0
- package/dist/core/__tests__/human-action-delivery.test.d.ts +1 -0
- package/dist/core/__tests__/human-action-delivery.test.js +140 -0
- package/dist/core/__tests__/human-actions.test.d.ts +1 -0
- package/dist/core/__tests__/human-actions.test.js +116 -0
- package/dist/core/__tests__/inline-memory-refs.test.js +1 -1
- package/dist/core/__tests__/profile-project-memory-delivery.test.js +70 -3
- package/dist/core/__tests__/prospective-inventory-capability-parity.test.d.ts +1 -0
- package/dist/core/__tests__/prospective-inventory-capability-parity.test.js +91 -0
- package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.d.ts +1 -0
- package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.js +127 -0
- package/dist/core/__tests__/seam/prospective-inventory-stdout.test.d.ts +1 -0
- package/dist/core/__tests__/seam/prospective-inventory-stdout.test.js +31 -0
- package/dist/core/canvas/db.js +23 -0
- package/dist/core/canvas/human-deliveries.d.ts +53 -0
- package/dist/core/canvas/human-deliveries.js +75 -0
- package/dist/core/config.d.ts +13 -1
- package/dist/core/config.js +51 -1
- package/dist/core/feed/inbox.d.ts +6 -0
- package/dist/core/feed/inbox.js +9 -1
- package/dist/core/human/action-binding.d.ts +21 -0
- package/dist/core/human/action-binding.js +40 -0
- package/dist/core/human/completion.d.ts +38 -0
- package/dist/core/human/completion.js +27 -0
- package/dist/core/human/convention.d.ts +2 -0
- package/dist/core/human/convention.js +2 -0
- package/dist/core/human/tickets.d.ts +25 -6
- package/dist/core/human/tickets.js +19 -13
- package/dist/core/human/types.d.ts +5 -0
- package/dist/core/human-actions.d.ts +25 -0
- package/dist/core/human-actions.js +101 -0
- package/dist/core/memory-resolver.js +1 -1
- package/dist/core/profiles/select.d.ts +2 -0
- package/dist/core/profiles/select.js +21 -4
- package/dist/core/runtime/broker/frame-dispatch.js +2 -5
- package/dist/core/runtime/broker-inventory.d.ts +1 -2
- package/dist/core/runtime/broker-inventory.js +2 -77
- package/dist/core/runtime/broker-persona-guidance.js +1 -1
- package/dist/core/runtime/broker.js +4 -4
- package/dist/core/runtime/chat-inventory-rows.d.ts +8 -0
- package/dist/core/runtime/chat-inventory-rows.js +105 -0
- package/dist/core/runtime/command-surface.d.ts +8 -3
- package/dist/core/runtime/command-surface.js +42 -6
- package/dist/core/runtime/launch-target.d.ts +25 -0
- package/dist/core/runtime/launch-target.js +54 -0
- package/dist/core/runtime/persona.js +3 -3
- package/dist/core/runtime/prospective-inventory-cli.d.ts +1 -0
- package/dist/core/runtime/prospective-inventory-cli.js +61 -0
- package/dist/core/runtime/prospective-inventory.d.ts +10 -0
- package/dist/core/runtime/prospective-inventory.js +88 -0
- package/dist/core/runtime/spawn.d.ts +3 -1
- package/dist/core/runtime/spawn.js +5 -3
- package/dist/core/substrate/frontmatter-validation.d.ts +2 -5
- package/dist/core/substrate/frontmatter-validation.js +8 -4
- package/dist/core/substrate/gate.d.ts +4 -1
- package/dist/core/substrate/gate.js +5 -0
- package/dist/core/substrate/on-read.js +21 -32
- package/dist/core/substrate/render-node.d.ts +3 -2
- package/dist/core/substrate/render-node.js +3 -2
- package/dist/core/substrate/render.js +64 -37
- package/dist/core/substrate/schema.d.ts +17 -8
- package/dist/core/substrate/schema.js +14 -10
- package/dist/core/substrate/surface-match.d.ts +8 -7
- package/dist/core/substrate/surface-match.js +15 -14
- package/dist/core/user-settings.d.ts +4 -0
- package/dist/core/user-settings.js +1 -0
- package/dist/daemon/api/__tests__/profile-launch-gates.test.js +52 -3
- package/dist/daemon/api/handlers/human-requests.d.ts +2 -0
- package/dist/daemon/api/handlers/human-requests.js +409 -0
- package/dist/daemon/api/handlers/human.js +3 -0
- package/dist/daemon/api/handlers/inbox.js +3 -0
- package/dist/daemon/api/handlers/nodes.d.ts +1 -3
- package/dist/daemon/api/handlers/nodes.js +11 -46
- package/dist/daemon/api/handlers/prospective-chat-inventory.d.ts +2 -0
- package/dist/daemon/api/handlers/prospective-chat-inventory.js +59 -0
- package/dist/daemon/api/handlers/reviews.js +10 -2
- package/dist/daemon/api/server.js +4 -0
- package/dist/daemon/crtrd.js +6 -0
- package/dist/daemon/human/deliver-action.d.ts +16 -0
- package/dist/daemon/human/deliver-action.js +168 -0
- package/dist/daemon/human/finish.d.ts +8 -5
- package/dist/daemon/human/finish.js +45 -6
- package/dist/daemon/human/sweep.js +4 -1
- package/dist/daemon/reconcilers/human-delivery-lane.d.ts +10 -0
- package/dist/daemon/reconcilers/human-delivery-lane.js +41 -0
- package/dist/daemon/review/finish.d.ts +8 -3
- package/dist/daemon/review/finish.js +19 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.js +1 -0
- package/package.json +1 -1
- package/runtime.lock.json +2 -2
- package/dist/builtin-memory/00-runtime-base.md +0 -55
- package/dist/builtin-memory/design.md +0 -55
- /package/dist/builtin-memory/{02-lifecycle/00-terminal.md → 02-turn-lifecycle/01-terminal.md} +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// The `crtr.human-completion/v1` document handed to a completion action on
|
|
2
|
+
// stdin. Composed at settlement from the canonical terminal result, so the
|
|
3
|
+
// delivered document reflects the settlement instant and the delivery lane
|
|
4
|
+
// never reads ticket storage.
|
|
5
|
+
/** The one place a cancellation record without `disposition` reads as
|
|
6
|
+
* `canceled`. Every other reader treats both dispositions alike. */
|
|
7
|
+
export function completionEventFor(result) {
|
|
8
|
+
if (result.kind === 'canceled')
|
|
9
|
+
return result.disposition ?? 'canceled';
|
|
10
|
+
return 'answered';
|
|
11
|
+
}
|
|
12
|
+
/** Build the complete document with `delivery.attempt` as the lane's placeholder. */
|
|
13
|
+
export function composeHumanCompletion(args) {
|
|
14
|
+
const { requestId, result, binding, source } = args;
|
|
15
|
+
const event = completionEventFor(result);
|
|
16
|
+
const actor = result.actor;
|
|
17
|
+
return {
|
|
18
|
+
schema: 'crtr.human-completion/v1',
|
|
19
|
+
requestId,
|
|
20
|
+
event,
|
|
21
|
+
settledAt: result.kind === 'page' ? result.completedAt : result.canceledAt,
|
|
22
|
+
...(result.kind === 'page' ? { responses: result.responses } : {}),
|
|
23
|
+
action: { name: binding.name, payload: binding.payload },
|
|
24
|
+
provenance: { source, ...(actor === undefined ? {} : { actor }) },
|
|
25
|
+
delivery: { attempt: 0 },
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -8,6 +8,8 @@ export declare function responsePath(dir: string): string;
|
|
|
8
8
|
export declare function progressPath(dir: string): string;
|
|
9
9
|
export declare function claimPath(dir: string): string;
|
|
10
10
|
export declare function replyRoutePath(dir: string): string;
|
|
11
|
+
/** The frozen completion-action binding, written once at request creation. */
|
|
12
|
+
export declare function actionBindingPath(dir: string): string;
|
|
11
13
|
export interface TicketReplyRoute {
|
|
12
14
|
bridge_node_id: string;
|
|
13
15
|
}
|
|
@@ -10,6 +10,8 @@ export function responsePath(dir) { return `${dir}/response.json`; }
|
|
|
10
10
|
export function progressPath(dir) { return `${dir}/progress.json`; }
|
|
11
11
|
export function claimPath(dir) { return `${dir}/claim.json`; }
|
|
12
12
|
export function replyRoutePath(dir) { return `${dir}/reply-route.json`; }
|
|
13
|
+
/** The frozen completion-action binding, written once at request creation. */
|
|
14
|
+
export function actionBindingPath(dir) { return `${dir}/action.json`; }
|
|
13
15
|
/** A reply route exists only when completing the ticket must finish a human
|
|
14
16
|
* bridge and fan its result back to subscribers. Its absence is the complete
|
|
15
17
|
* representation of a standalone page. */
|
|
@@ -19,9 +19,22 @@ export interface PreparedPage {
|
|
|
19
19
|
module?: string;
|
|
20
20
|
manifest: PageManifest;
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
export interface PreparePageSourceOptions {
|
|
23
|
+
/** `jsx` carries .tsx semantics; `html` is a complete document. */
|
|
24
|
+
dialect: 'jsx' | 'html';
|
|
25
|
+
/** The complete authored page text, inline. */
|
|
26
|
+
document: string;
|
|
27
|
+
source?: PageSource;
|
|
28
|
+
productKinds?: ProductPageComponents;
|
|
29
|
+
delivery?: PageDelivery;
|
|
30
|
+
}
|
|
31
|
+
/** Validate one authored page document into publishable form. The single
|
|
32
|
+
* validation path: `preparePage` reads a file and lands here, and a
|
|
33
|
+
* programmatic request supplies the same text inline. */
|
|
34
|
+
export declare function preparePageSource(opts: PreparePageSourceOptions): PreparedPage;
|
|
35
|
+
/** Validate one authored page source file into publishable form. Reads only: a
|
|
36
|
+
* page that fails authoring leaves nothing behind, so a caller that must create
|
|
37
|
+
* a bridge node prepares first and creates it only once the page is known good.
|
|
25
38
|
* The source is read exactly once, so the published document is the same bytes
|
|
26
39
|
* the manifest was derived from even if the file changes underneath. */
|
|
27
40
|
export declare function preparePage(opts: Omit<SubmitPageOptions, 'dir'>): PreparedPage;
|
|
@@ -81,6 +94,8 @@ export interface PageTicket {
|
|
|
81
94
|
export declare function readPageTicket(dir: string): PageTicket;
|
|
82
95
|
export interface CompletePageOptions {
|
|
83
96
|
completedAt?: string;
|
|
97
|
+
/** Recorded when an authorized programmatic writer answered instead of a person. */
|
|
98
|
+
actor?: string;
|
|
84
99
|
}
|
|
85
100
|
export declare function completePage(dir: string, responses: unknown, claimToken: string, opts?: CompletePageOptions): {
|
|
86
101
|
won: boolean;
|
|
@@ -94,11 +109,15 @@ export declare function takeoverAndCompletePage(dir: string, responses: unknown,
|
|
|
94
109
|
won: boolean;
|
|
95
110
|
result: TicketResult;
|
|
96
111
|
};
|
|
97
|
-
|
|
98
|
-
export declare function cancelTicket(dir: string, opts?: {
|
|
112
|
+
export interface CancelTicketOptions {
|
|
99
113
|
reason?: string;
|
|
100
114
|
actor?: string;
|
|
101
|
-
|
|
115
|
+
/** The recipient closing it writes `dismissed`; the requester withdrawing it
|
|
116
|
+
* writes `canceled`. Omitted where the caller is neither. */
|
|
117
|
+
disposition?: 'canceled' | 'dismissed';
|
|
118
|
+
}
|
|
119
|
+
/** Cancellation races finalization but never requires or removes another claim. */
|
|
120
|
+
export declare function cancelTicket(dir: string, opts?: CancelTicketOptions): {
|
|
102
121
|
status: 'canceled' | 'already_resolved';
|
|
103
122
|
result: TicketResult;
|
|
104
123
|
};
|
|
@@ -23,10 +23,10 @@ const feedbackSchema = z.object({ file: z.string().min(1).refine(isAbsolute, 'fi
|
|
|
23
23
|
});
|
|
24
24
|
});
|
|
25
25
|
const slotResponseSchema = z.record(z.string(), z.unknown());
|
|
26
|
-
const pageResultSchema = z.object({ schema: z.literal('crtr.page-response/v1'), kind: z.literal('page'), responses: z.record(z.string(), slotResponseSchema), summary: z.string(), completedAt: iso }).strict();
|
|
26
|
+
const pageResultSchema = z.object({ schema: z.literal('crtr.page-response/v1'), kind: z.literal('page'), responses: z.record(z.string(), slotResponseSchema), summary: z.string(), completedAt: iso, actor: z.string().optional() }).strict();
|
|
27
27
|
const pageProgressSchema = z.object({ kind: z.literal('page'), responses: z.record(z.string(), slotResponseSchema), savedAt: iso }).strict();
|
|
28
28
|
const reviewResultSchema = z.object({ schema: z.literal('humanloop.review-response/v1'), kind: z.literal('review'), result: feedbackSchema, completedAt: iso }).strict();
|
|
29
|
-
const canceledResultSchema = z.object({ schema: z.literal('humanloop.cancel/v1'), kind: z.literal('canceled'), canceledAt: iso, reason: z.string().optional(), actor: z.string().optional() }).strict();
|
|
29
|
+
const canceledResultSchema = z.object({ schema: z.literal('humanloop.cancel/v1'), kind: z.literal('canceled'), canceledAt: iso, reason: z.string().optional(), actor: z.string().optional(), disposition: z.enum(['canceled', 'dismissed']).optional() }).strict();
|
|
30
30
|
/** Strict decoder for the only canonical final marker. */
|
|
31
31
|
export function readTicketResult(dir) {
|
|
32
32
|
let raw;
|
|
@@ -52,9 +52,19 @@ function publishRequest(path, value) {
|
|
|
52
52
|
if (!publishJsonExclusive(path, value))
|
|
53
53
|
throw new Error(`ticket request already exists: ${path}`);
|
|
54
54
|
}
|
|
55
|
-
/** Validate one authored page
|
|
56
|
-
*
|
|
57
|
-
*
|
|
55
|
+
/** Validate one authored page document into publishable form. The single
|
|
56
|
+
* validation path: `preparePage` reads a file and lands here, and a
|
|
57
|
+
* programmatic request supplies the same text inline. */
|
|
58
|
+
export function preparePageSource(opts) {
|
|
59
|
+
const stamped = { ...(opts.source ?? {}), emittedAt: opts.source?.emittedAt ?? new Date().toISOString() };
|
|
60
|
+
const delivery = opts.delivery ?? { placement: 'inline', inbox: false, reply: false };
|
|
61
|
+
if (opts.dialect === 'html')
|
|
62
|
+
return { document: opts.document, manifest: deriveHtmlPageManifest(opts.document, stamped, delivery) };
|
|
63
|
+
return { document: opts.document, module: compilePage(opts.document), manifest: derivePageManifestFromDocument(opts.document, opts.productKinds ?? [], stamped, delivery) };
|
|
64
|
+
}
|
|
65
|
+
/** Validate one authored page source file into publishable form. Reads only: a
|
|
66
|
+
* page that fails authoring leaves nothing behind, so a caller that must create
|
|
67
|
+
* a bridge node prepares first and creates it only once the page is known good.
|
|
58
68
|
* The source is read exactly once, so the published document is the same bytes
|
|
59
69
|
* the manifest was derived from even if the file changes underneath. */
|
|
60
70
|
export function preparePage(opts) {
|
|
@@ -63,12 +73,8 @@ export function preparePage(opts) {
|
|
|
63
73
|
throw new PageAuthoringError(`page source file must be .tsx, .html, or .htm: ${opts.sourceFile}`);
|
|
64
74
|
if (!existsSync(opts.sourceFile))
|
|
65
75
|
throw new PageAuthoringError(`page source file does not exist: ${opts.sourceFile}`);
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
const delivery = opts.delivery ?? { placement: 'inline', inbox: false, reply: false };
|
|
69
|
-
if (html)
|
|
70
|
-
return { document, manifest: deriveHtmlPageManifest(document, stamped, delivery) };
|
|
71
|
-
return { document, module: compilePage(document), manifest: derivePageManifestFromDocument(document, opts.productKinds ?? [], stamped, delivery) };
|
|
76
|
+
const { sourceFile: _sourceFile, ...rest } = opts;
|
|
77
|
+
return preparePageSource({ ...rest, dialect: html ? 'html' : 'jsx', document: readFileSync(opts.sourceFile, 'utf8') });
|
|
72
78
|
}
|
|
73
79
|
/** Remove a stale generation file. The manifest always switches first, so a
|
|
74
80
|
* failed cleanup leaves one valid current record plus harmless old source. */
|
|
@@ -237,7 +243,7 @@ function completePageLocked(dir, responses, claimToken, opts) {
|
|
|
237
243
|
requireClaimOwnership(dir, claimToken);
|
|
238
244
|
const manifest = requirePage(dir);
|
|
239
245
|
const parsedResponses = validateFinalPageTicketResponses(dir, responses);
|
|
240
|
-
const result = { schema: 'crtr.page-response/v1', kind: 'page', responses: parsedResponses, summary: buildPageSummary(manifest, parsedResponses), completedAt: opts.completedAt ?? new Date().toISOString() };
|
|
246
|
+
const result = { schema: 'crtr.page-response/v1', kind: 'page', responses: parsedResponses, summary: buildPageSummary(manifest, parsedResponses), completedAt: opts.completedAt ?? new Date().toISOString(), ...(opts.actor === undefined ? {} : { actor: opts.actor }) };
|
|
241
247
|
const won = exclusiveResult(dir, result);
|
|
242
248
|
clearOwnedWork(dir, claimToken);
|
|
243
249
|
return { won, result: won ? result : readTicketResult(dir) ?? result };
|
|
@@ -280,7 +286,7 @@ export function cancelTicket(dir, opts = {}) {
|
|
|
280
286
|
const canceled = withTicketLock(ticket, () => {
|
|
281
287
|
if (existsSync(pageManifestPath(ticket)))
|
|
282
288
|
requireCancelablePage(ticket);
|
|
283
|
-
const result = { schema: 'humanloop.cancel/v1', kind: 'canceled', canceledAt: new Date().toISOString(), ...(opts.reason === undefined ? {} : { reason: opts.reason }), ...(opts.actor === undefined ? {} : { actor: opts.actor }) };
|
|
289
|
+
const result = { schema: 'humanloop.cancel/v1', kind: 'canceled', canceledAt: new Date().toISOString(), ...(opts.reason === undefined ? {} : { reason: opts.reason }), ...(opts.actor === undefined ? {} : { actor: opts.actor }), ...(opts.disposition === undefined ? {} : { disposition: opts.disposition }) };
|
|
284
290
|
const won = exclusiveResult(ticket, result);
|
|
285
291
|
return { status: won ? 'canceled' : 'already_resolved', result: won ? result : readTicketResult(ticket) ?? result };
|
|
286
292
|
});
|
|
@@ -89,6 +89,8 @@ export interface PageTicketResult {
|
|
|
89
89
|
responses: PageResponses;
|
|
90
90
|
summary: string;
|
|
91
91
|
completedAt: string;
|
|
92
|
+
/** Recorded when an authorized programmatic writer answered instead of a person. */
|
|
93
|
+
actor?: string;
|
|
92
94
|
}
|
|
93
95
|
export interface ReviewTicketResult {
|
|
94
96
|
schema: 'humanloop.review-response/v1';
|
|
@@ -102,6 +104,9 @@ export interface CanceledTicketResult {
|
|
|
102
104
|
canceledAt: string;
|
|
103
105
|
reason?: string;
|
|
104
106
|
actor?: string;
|
|
107
|
+
/** Who ended it without an answer: the recipient (`dismissed`) or the
|
|
108
|
+
* requester (`canceled`). Absent on records written before the field. */
|
|
109
|
+
disposition?: 'canceled' | 'dismissed';
|
|
105
110
|
}
|
|
106
111
|
/** The sole canonical response.json union. */
|
|
107
112
|
export type TicketResult = PageTicketResult | ReviewTicketResult | CanceledTicketResult;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface ResolvedHumanAction {
|
|
2
|
+
name: string;
|
|
3
|
+
/** Absolute path of the config file that won resolution. */
|
|
4
|
+
configOrigin: string;
|
|
5
|
+
/** Fully resolved argv; argv[0] is an absolute executable path. */
|
|
6
|
+
argv: string[];
|
|
7
|
+
/** Fully resolved absolute working directory. */
|
|
8
|
+
cwd: string;
|
|
9
|
+
}
|
|
10
|
+
export type HumanActionIssue = {
|
|
11
|
+
kind: 'unknown_action';
|
|
12
|
+
name: string;
|
|
13
|
+
} | {
|
|
14
|
+
kind: 'invalid_action';
|
|
15
|
+
name: string;
|
|
16
|
+
configOrigin: string;
|
|
17
|
+
reason: string;
|
|
18
|
+
block?: true;
|
|
19
|
+
};
|
|
20
|
+
/** Resolve one declared action from a creator's absolute cwd: nearest project
|
|
21
|
+
* ancestor first, then farther project ancestors, then user scope. Never
|
|
22
|
+
* consults plugin or profile config. Read-only; never executes anything. */
|
|
23
|
+
export declare function resolveHumanAction(name: string, creatorCwd: string): ResolvedHumanAction | HumanActionIssue;
|
|
24
|
+
/** Every declared action reachable from a cwd, with its issues, for doctor. */
|
|
25
|
+
export declare function inspectHumanActions(creatorCwd: string): Array<ResolvedHumanAction | HumanActionIssue>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { statSync } from 'node:fs';
|
|
2
|
+
import { dirname, join, resolve } from 'node:path';
|
|
3
|
+
import { CONFIG_FILE } from '../types.js';
|
|
4
|
+
import { humanActionDeclarationIssues, readRawConfigAtRoot } from './config.js';
|
|
5
|
+
import { findProjectScopeRoots, scopeRoot } from './scope.js';
|
|
6
|
+
function actionContributors(creatorCwd) {
|
|
7
|
+
const contributors = [];
|
|
8
|
+
for (const scopeRootPath of findProjectScopeRoots(creatorCwd, null)) {
|
|
9
|
+
const raw = readRawConfigAtRoot(scopeRootPath)?.humanActions;
|
|
10
|
+
if (raw !== undefined) {
|
|
11
|
+
contributors.push({
|
|
12
|
+
configOrigin: join(scopeRootPath, CONFIG_FILE),
|
|
13
|
+
authoringRoot: dirname(scopeRootPath),
|
|
14
|
+
raw,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const userRoot = scopeRoot('user');
|
|
19
|
+
if (userRoot !== null) {
|
|
20
|
+
const raw = readRawConfigAtRoot(userRoot)?.humanActions;
|
|
21
|
+
if (raw !== undefined) {
|
|
22
|
+
contributors.push({ configOrigin: join(userRoot, CONFIG_FILE), authoringRoot: userRoot, raw });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return contributors;
|
|
26
|
+
}
|
|
27
|
+
function declarationIssue(name, raw) {
|
|
28
|
+
return humanActionDeclarationIssues({ [name]: raw }).find((issue) => issue.name === name)?.reason;
|
|
29
|
+
}
|
|
30
|
+
function resolveDeclaredAction(name, declaration, contributor) {
|
|
31
|
+
const cwd = resolve(contributor.authoringRoot, declaration.cwd);
|
|
32
|
+
try {
|
|
33
|
+
if (!statSync(cwd).isDirectory()) {
|
|
34
|
+
return { kind: 'invalid_action', name, configOrigin: contributor.configOrigin, reason: `cwd is not a directory: ${cwd}` };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return { kind: 'invalid_action', name, configOrigin: contributor.configOrigin, reason: `cwd does not exist: ${cwd}` };
|
|
39
|
+
}
|
|
40
|
+
const executable = resolve(contributor.authoringRoot, declaration.argv[0]);
|
|
41
|
+
try {
|
|
42
|
+
const stat = statSync(executable);
|
|
43
|
+
if (!stat.isFile()) {
|
|
44
|
+
return { kind: 'invalid_action', name, configOrigin: contributor.configOrigin, reason: `argv[0] is not a regular file: ${executable}` };
|
|
45
|
+
}
|
|
46
|
+
if ((stat.mode & 0o111) === 0) {
|
|
47
|
+
return { kind: 'invalid_action', name, configOrigin: contributor.configOrigin, reason: `argv[0] lacks the POSIX exec bit: ${executable}` };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return { kind: 'invalid_action', name, configOrigin: contributor.configOrigin, reason: `argv[0] does not exist: ${executable}` };
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
name,
|
|
55
|
+
configOrigin: contributor.configOrigin,
|
|
56
|
+
argv: [executable, ...declaration.argv.slice(1)],
|
|
57
|
+
cwd,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Resolve one declared action from a creator's absolute cwd: nearest project
|
|
61
|
+
* ancestor first, then farther project ancestors, then user scope. Never
|
|
62
|
+
* consults plugin or profile config. Read-only; never executes anything. */
|
|
63
|
+
export function resolveHumanAction(name, creatorCwd) {
|
|
64
|
+
for (const contributor of actionContributors(creatorCwd)) {
|
|
65
|
+
if (contributor.raw === null || typeof contributor.raw !== 'object' || Array.isArray(contributor.raw))
|
|
66
|
+
continue;
|
|
67
|
+
const declarations = contributor.raw;
|
|
68
|
+
if (!Object.hasOwn(declarations, name))
|
|
69
|
+
continue;
|
|
70
|
+
const raw = declarations[name];
|
|
71
|
+
const issue = declarationIssue(name, raw);
|
|
72
|
+
if (issue !== undefined) {
|
|
73
|
+
return { kind: 'invalid_action', name, configOrigin: contributor.configOrigin, reason: issue };
|
|
74
|
+
}
|
|
75
|
+
return resolveDeclaredAction(name, raw, contributor);
|
|
76
|
+
}
|
|
77
|
+
return { kind: 'unknown_action', name };
|
|
78
|
+
}
|
|
79
|
+
/** Every declared action reachable from a cwd, with its issues, for doctor. */
|
|
80
|
+
export function inspectHumanActions(creatorCwd) {
|
|
81
|
+
const results = [];
|
|
82
|
+
for (const contributor of actionContributors(creatorCwd)) {
|
|
83
|
+
const issues = humanActionDeclarationIssues(contributor.raw);
|
|
84
|
+
const invalid = new Map(issues.map((issue) => [issue.name, issue.reason]));
|
|
85
|
+
if (contributor.raw === null || typeof contributor.raw !== 'object' || Array.isArray(contributor.raw)) {
|
|
86
|
+
for (const issue of issues) {
|
|
87
|
+
results.push({ kind: 'invalid_action', name: issue.name, configOrigin: contributor.configOrigin, reason: issue.reason, ...(issue.block === true ? { block: true } : {}) });
|
|
88
|
+
}
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
for (const [name, raw] of Object.entries(contributor.raw)) {
|
|
92
|
+
const issue = invalid.get(name);
|
|
93
|
+
if (issue !== undefined) {
|
|
94
|
+
results.push({ kind: 'invalid_action', name, configOrigin: contributor.configOrigin, reason: issue });
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
results.push(resolveDeclaredAction(name, raw, contributor));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return results;
|
|
101
|
+
}
|
|
@@ -313,7 +313,7 @@ function matchNormalizedChild(dir, segment, want, ext = '.md') {
|
|
|
313
313
|
* directory by normalized name, then resolve the final segment as either a
|
|
314
314
|
* `.md` file or a directory. Either half is null when
|
|
315
315
|
* the segment path does not resolve that way. This is what makes
|
|
316
|
-
* `00-runtime-base.md` findable as `runtime-base` and `01-spine/00-has-manager`
|
|
316
|
+
* `00-runtime-base/00-authoring.md` findable as `runtime-base/authoring` and `01-spine/00-has-manager`
|
|
317
317
|
* findable as `spine/has-manager` — the physical path keeps its pins, only
|
|
318
318
|
* lookup is prefix-blind. */
|
|
319
319
|
function resolveNormalizedPath(baseDir, segments, ext = '.md') {
|
|
@@ -9,6 +9,8 @@ export declare function resolveProfileSearchAction(bindings: BindingResolution<B
|
|
|
9
9
|
* `crtr profile default set`, which rejects pinning a profile that doesn't
|
|
10
10
|
* cover cwd (the selector would ignore/self-heal such a pin anyway). */
|
|
11
11
|
export declare function profileCoversCwd(entry: ProfileEntry, cwd: string): boolean;
|
|
12
|
+
/** Resolve the headless selector against existing state without changing it. */
|
|
13
|
+
export declare function selectProfileForCwdReadOnly(cwd: string): string;
|
|
12
14
|
/** Select the profile a node about to boot at `cwd` should run under.
|
|
13
15
|
*
|
|
14
16
|
* 1. `explicitProfile` present → resolve id/name via `loadProfileManifest`. If
|
|
@@ -93,6 +93,26 @@ function isMoreRecent(a, b) {
|
|
|
93
93
|
function pickMostRecent(entries) {
|
|
94
94
|
return entries.reduce((best, cur) => isMoreRecent(cur.manifest.last_used_at, best.manifest.last_used_at) ? cur : best);
|
|
95
95
|
}
|
|
96
|
+
function profileSelectionState(cwd) {
|
|
97
|
+
const resolvedCwd = resolveCwd(cwd);
|
|
98
|
+
const covering = listProfiles().filter((profile) => profileCoversCwd(profile, resolvedCwd));
|
|
99
|
+
const exact = covering.filter((profile) => profile.manifest.projects.some((project) => project.path === resolvedCwd));
|
|
100
|
+
const pinnedId = getDefaultProfileId(resolvedCwd);
|
|
101
|
+
const pinned = pinnedId === null ? null : covering.find((profile) => profile.profileId === pinnedId) ?? null;
|
|
102
|
+
return { covering, exact, pinnedId, pinned };
|
|
103
|
+
}
|
|
104
|
+
/** Resolve the headless selector against existing state without changing it. */
|
|
105
|
+
export function selectProfileForCwdReadOnly(cwd) {
|
|
106
|
+
const { covering, exact, pinned } = profileSelectionState(cwd);
|
|
107
|
+
if (pinned !== null)
|
|
108
|
+
return pinned.profileId;
|
|
109
|
+
if (exact.length === 1)
|
|
110
|
+
return exact[0].profileId;
|
|
111
|
+
const pool = exact.length > 0 ? exact : covering;
|
|
112
|
+
if (pool.length > 0)
|
|
113
|
+
return pickMostRecent(pool).profileId;
|
|
114
|
+
return ROOT_PROFILE_ID;
|
|
115
|
+
}
|
|
96
116
|
function isInteractive() {
|
|
97
117
|
return Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY);
|
|
98
118
|
}
|
|
@@ -620,14 +640,11 @@ export async function selectProfileForCwd(cwd, explicitProfile, forcePicker = fa
|
|
|
620
640
|
updateProfileLastUsed(entry.profileId);
|
|
621
641
|
return entry.profileId;
|
|
622
642
|
}
|
|
623
|
-
const covering
|
|
624
|
-
const exact = covering.filter((p) => p.manifest.projects.some((proj) => proj.path === resolvedCwd));
|
|
643
|
+
const { covering, exact, pinnedId, pinned } = profileSelectionState(resolvedCwd);
|
|
625
644
|
// A per-cwd pinned default (set from the menu with `d`) is the user's
|
|
626
645
|
// explicit "default to THIS profile HERE". It outranks both the exact-single
|
|
627
646
|
// auto-pick and global-MRU, so long as it still covers cwd; a stale pin
|
|
628
647
|
// (profile deleted, or its dir removed from purview) is self-healed away.
|
|
629
|
-
const pinnedId = getDefaultProfileId(resolvedCwd);
|
|
630
|
-
const pinned = pinnedId !== null ? covering.find((p) => p.profileId === pinnedId) ?? null : null;
|
|
631
648
|
if (pinnedId !== null && pinned === null)
|
|
632
649
|
clearDefaultProfile(resolvedCwd);
|
|
633
650
|
// A valid pin decides it outright and STOPS ASKING — the whole point of
|
|
@@ -9,7 +9,7 @@ import { operationIdContext } from '../../events/operation-id.js';
|
|
|
9
9
|
import { buildRefInventory } from '../../memory/inline-ref-inventory.js';
|
|
10
10
|
import { buildGuidance } from '../../memory/inline-ref-guidance.js';
|
|
11
11
|
import { clearSessionCache } from '../../substrate/session-cache.js';
|
|
12
|
-
import {
|
|
12
|
+
import { captureSessionChatCapabilities } from '../command-surface.js';
|
|
13
13
|
import { promptWithAdvertisedCommandInvocation } from '../advertised-command-invocation.js';
|
|
14
14
|
export { promptWithAdvertisedCommandInvocation } from '../advertised-command-invocation.js';
|
|
15
15
|
import { configuredLadderProviders, isProviderPinnedModelToken, nextLadderModel, normalizeModel, } from '../launch.js';
|
|
@@ -1210,7 +1210,7 @@ export function createFrameDispatchContext(deps) {
|
|
|
1210
1210
|
// cached docs. A FAILED reload (`.catch`) leaves both untouched: nothing
|
|
1211
1211
|
// about the corpus is known to have changed.
|
|
1212
1212
|
void currentSession()
|
|
1213
|
-
.reload()
|
|
1213
|
+
.reload({ beforeSessionStart: () => captureSessionChatCapabilities(currentSession()) })
|
|
1214
1214
|
.then(() => {
|
|
1215
1215
|
// pi's reload() re-syncs queue modes from the shared settings.json
|
|
1216
1216
|
// (its ONE post-bind syncQueueModesFromSettings call site) —
|
|
@@ -1221,9 +1221,6 @@ export function createFrameDispatchContext(deps) {
|
|
|
1221
1221
|
agent.steeringMode = 'all';
|
|
1222
1222
|
agent.followUpMode = 'all';
|
|
1223
1223
|
}
|
|
1224
|
-
// `session.reload()` has replaced pi's loaded template objects;
|
|
1225
|
-
// capture their crouter-only metadata before any observer refresh.
|
|
1226
|
-
captureSessionPromptTemplateChatSurfaces(currentSession());
|
|
1227
1224
|
memoizedRefInventory = null;
|
|
1228
1225
|
clearSessionCache();
|
|
1229
1226
|
registry.forEachHelloed((observer) => {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { ChatInventoryDTO
|
|
2
|
-
export declare function gatewayMemoryRows(refs: unknown): ChatInventoryMemoryRefDTO[];
|
|
1
|
+
import type { ChatInventoryDTO } from '../../api/dto/chat-inventory.js';
|
|
3
2
|
/** Collect the chat inventories for one node. Always resolves — every failure
|
|
4
3
|
* mode is expressed in the returned document, not thrown. */
|
|
5
4
|
export declare function readChatInventory(nodeId: string): Promise<ChatInventoryDTO>;
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import { randomUUID } from 'node:crypto';
|
|
25
25
|
import { getNode } from '../canvas/canvas.js';
|
|
26
26
|
import { BrokerClient } from '../broker-client/index.js';
|
|
27
|
-
import {
|
|
27
|
+
import { gatewayCommandRowsFromDetail, gatewayMemoryRows } from './chat-inventory-rows.js';
|
|
28
28
|
import { isBrokerLive } from './model-swap.js';
|
|
29
29
|
/** Same budget as `broker-request.ts`: this is local engine work, so it is
|
|
30
30
|
* generous slack rather than a tuned deadline. One budget covers BOTH answers —
|
|
@@ -36,81 +36,6 @@ const READ_TIMEOUT_MS = 15_000;
|
|
|
36
36
|
* throws away — on every activation and reconnect, worst on the longest
|
|
37
37
|
* conversations. One entry is the smallest legal request. */
|
|
38
38
|
const SNAPSHOT_TAIL = 1;
|
|
39
|
-
const MEMORY_KINDS = new Set(['knowledge', 'preference']);
|
|
40
|
-
const MEMORY_SCOPES = new Set(['node', 'project', 'profile', 'user', 'builtin']);
|
|
41
|
-
function nonEmptyString(value) {
|
|
42
|
-
return typeof value === 'string' && value !== '';
|
|
43
|
-
}
|
|
44
|
-
/** Keep the rows a chat surface can actually use and drop the rest. Malformed
|
|
45
|
-
* rows are discarded individually so one bad registration cannot take down the
|
|
46
|
-
* whole inventory.
|
|
47
|
-
*
|
|
48
|
-
* This validation lives here rather than reusing the attach viewer's parser:
|
|
49
|
-
* `src/core` does not import `src/clients`, and adding that import would invert
|
|
50
|
-
* the layering. */
|
|
51
|
-
function commandRows(detail) {
|
|
52
|
-
if (detail === undefined)
|
|
53
|
-
return [];
|
|
54
|
-
let parsed;
|
|
55
|
-
try {
|
|
56
|
-
parsed = JSON.parse(detail);
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
return [];
|
|
60
|
-
}
|
|
61
|
-
if (!Array.isArray(parsed))
|
|
62
|
-
return [];
|
|
63
|
-
const out = [];
|
|
64
|
-
for (const row of parsed) {
|
|
65
|
-
if (typeof row !== 'object' || row === null)
|
|
66
|
-
continue;
|
|
67
|
-
const record = row;
|
|
68
|
-
if (record['gatewayCapable'] !== true)
|
|
69
|
-
continue;
|
|
70
|
-
const source = record['source'];
|
|
71
|
-
if (source !== 'command' && source !== 'template')
|
|
72
|
-
continue;
|
|
73
|
-
if (!nonEmptyString(record['name']) || typeof record['description'] !== 'string')
|
|
74
|
-
continue;
|
|
75
|
-
const expansion = record['expansion'];
|
|
76
|
-
const template = record['template'];
|
|
77
|
-
const argumentHint = record['argumentHint'];
|
|
78
|
-
out.push({
|
|
79
|
-
name: record['name'],
|
|
80
|
-
description: record['description'],
|
|
81
|
-
source,
|
|
82
|
-
...(nonEmptyString(argumentHint) ? { argument_hint: argumentHint } : {}),
|
|
83
|
-
...(isDeterministicCommandExpansion(expansion) ? { expansion } : {}),
|
|
84
|
-
...(typeof template === 'string' ? { template } : {}),
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
return out;
|
|
88
|
-
}
|
|
89
|
-
export function gatewayMemoryRows(refs) {
|
|
90
|
-
if (!Array.isArray(refs))
|
|
91
|
-
return [];
|
|
92
|
-
const out = [];
|
|
93
|
-
for (const row of refs) {
|
|
94
|
-
if (typeof row !== 'object' || row === null)
|
|
95
|
-
continue;
|
|
96
|
-
const record = row;
|
|
97
|
-
if (record['gatewayVisible'] !== true)
|
|
98
|
-
continue;
|
|
99
|
-
if (!nonEmptyString(record['name']) || typeof record['shortForm'] !== 'string')
|
|
100
|
-
continue;
|
|
101
|
-
if (typeof record['kind'] !== 'string' || !MEMORY_KINDS.has(record['kind']))
|
|
102
|
-
continue;
|
|
103
|
-
if (typeof record['scope'] !== 'string' || !MEMORY_SCOPES.has(record['scope']))
|
|
104
|
-
continue;
|
|
105
|
-
out.push({
|
|
106
|
-
name: record['name'],
|
|
107
|
-
kind: record['kind'],
|
|
108
|
-
scope: record['scope'],
|
|
109
|
-
shortForm: record['shortForm'],
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
return out;
|
|
113
|
-
}
|
|
114
39
|
const empty = (nodeId) => ({
|
|
115
40
|
node_id: nodeId,
|
|
116
41
|
broker_live: false,
|
|
@@ -174,7 +99,7 @@ export function readChatInventory(nodeId) {
|
|
|
174
99
|
client.on('frame', (frame) => {
|
|
175
100
|
// `get_commands` carries no id, so its ack is matched on `for` alone.
|
|
176
101
|
if (frame.type === 'ack' && frame.for === 'get_commands') {
|
|
177
|
-
commands = frame.ok ?
|
|
102
|
+
commands = frame.ok ? gatewayCommandRowsFromDetail(frame.detail) : [];
|
|
178
103
|
settleWhenComplete();
|
|
179
104
|
return;
|
|
180
105
|
}
|
|
@@ -44,7 +44,7 @@ export function transitionGuidanceFromBrokerState(node, from, to) {
|
|
|
44
44
|
sections.push(to.mode === 'orchestrator' ? orchestrationGuidance(node) : baseModeGuidance());
|
|
45
45
|
}
|
|
46
46
|
if (from.lifecycle !== to.lifecycle) {
|
|
47
|
-
sections.push(loadMemoryBody(to.lifecycle === 'resident' ? 'lifecycle/resident' : 'lifecycle/terminal'));
|
|
47
|
+
sections.push(loadMemoryBody(to.lifecycle === 'resident' ? 'turn-lifecycle/resident' : 'turn-lifecycle/terminal'));
|
|
48
48
|
}
|
|
49
49
|
return sections.join('\n\n');
|
|
50
50
|
}
|
|
@@ -31,7 +31,7 @@ import { FRONT_DOOR_ENV } from './front-door.js';
|
|
|
31
31
|
import { CANVAS_EXTENSIONS, piInvocationToSdkConfig, } from './launch.js';
|
|
32
32
|
import { assertEngineVersion, loadBrokerEngine } from './broker-sdk.js';
|
|
33
33
|
import { resolveBundledPiPackageDir } from './pi-cli.js';
|
|
34
|
-
import {
|
|
34
|
+
import { captureSessionChatCapabilities } from './command-surface.js';
|
|
35
35
|
import { PoolCredentialStore } from '../pool-credential-store.js';
|
|
36
36
|
import { clearCleanAbort, markBusy, markCleanAbort } from './busy.js';
|
|
37
37
|
import { recordFaultForCurrentNode } from './fault.js';
|
|
@@ -899,9 +899,9 @@ export async function buildBrokerSession(engine, cfg) {
|
|
|
899
899
|
sessionStartEvent: o.sessionStartEvent,
|
|
900
900
|
});
|
|
901
901
|
installAdvertisedCommandInvocationContract(created.session);
|
|
902
|
-
// The resource loader has completed its initial
|
|
903
|
-
//
|
|
904
|
-
|
|
902
|
+
// The resource loader has completed its initial load, but extensions have
|
|
903
|
+
// not received session_start yet. Freeze the Gateway capability boundary.
|
|
904
|
+
captureSessionChatCapabilities(created.session);
|
|
905
905
|
// CONSTRUCTION-ONLY MASK — see modelLessRegistry: reveal now that model
|
|
906
906
|
// selection (construction-time only) is done, so a later /login re-drive's
|
|
907
907
|
// list_models/cycle_model/provider-rotation see the real registry.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ChatInventoryCommandDTO, ChatInventoryMemoryRefDTO } from '../../api/dto/chat-inventory.js';
|
|
2
|
+
/** Keep the command rows a Gateway can use. Malformed registrations are
|
|
3
|
+
* discarded individually so one producer cannot take down the inventory. */
|
|
4
|
+
export declare function gatewayCommandRows(rows: unknown): ChatInventoryCommandDTO[];
|
|
5
|
+
export declare function chatInventoryCommandRows(rows: unknown): ChatInventoryCommandDTO[];
|
|
6
|
+
export declare function gatewayCommandRowsFromDetail(detail: string | undefined): ChatInventoryCommandDTO[];
|
|
7
|
+
export declare function chatInventoryMemoryRows(rows: unknown): ChatInventoryMemoryRefDTO[];
|
|
8
|
+
export declare function gatewayMemoryRows(refs: unknown): ChatInventoryMemoryRefDTO[];
|