@north-light/crouter 0.3.180 → 0.3.182
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 +10 -1
- package/dist/api/client.js +13 -0
- package/dist/api/dto/broker.d.ts +32 -0
- package/dist/api/dto/crons.d.ts +17 -0
- package/dist/api/dto/memory.d.ts +17 -0
- package/dist/api/dto/memory.js +6 -0
- package/dist/api/dto/messages.d.ts +5 -0
- package/dist/api/dto/reviews.d.ts +8 -4
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/routes.d.ts +2 -0
- package/dist/api/routes.js +4 -0
- package/dist/build-root.d.ts +7 -0
- package/dist/build-root.js +21 -0
- package/dist/builtin-memory/insights/init.md +48 -3
- package/dist/builtin-pi-packages/pi-crtr-extensions/__tests__/insights-active-init.test.ts +98 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +7 -50
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +16 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/pi-shell-runner.ts +34 -0
- package/dist/cli.js +1 -2
- package/dist/clients/attach/__tests__/context-message.test.js +5 -2
- package/dist/clients/attach/assets/README.md +7 -0
- package/dist/clients/attach/assets/whip-06.mp3 +0 -0
- package/dist/clients/attach/assets/whip-crack.mp3 +0 -0
- package/dist/clients/attach/assets/whip-snap.mp3 +0 -0
- package/dist/clients/attach/chrome/canvas-panels.d.ts +7 -1
- package/dist/clients/attach/chrome/canvas-panels.js +20 -3
- package/dist/clients/attach/chrome/review-wait.d.ts +6 -0
- package/dist/clients/attach/chrome/review-wait.js +22 -0
- package/dist/clients/attach/chrome/roster.js +23 -2
- package/dist/clients/attach/chrome/widgets.js +1 -1
- package/dist/clients/attach/input/controller.js +4 -3
- package/dist/clients/attach/overlays/mcp.js +3 -1
- package/dist/clients/attach/render/chat-view.js +1 -1
- package/dist/clients/attach/session/whip.d.ts +1 -0
- package/dist/clients/attach/session/whip.js +26 -0
- package/dist/clients/attach/slash/dispatch.js +2 -0
- package/dist/clients/attach/viewer.js +578 -573
- package/dist/clients/inbox/review/document-surface.d.ts +1 -1
- package/dist/clients/inbox/review/document-surface.js +4 -4
- package/dist/clients/inbox/review/launch.js +16 -4
- package/dist/clients/inbox/review/review-client.d.ts +9 -4
- package/dist/clients/inbox/review/review-client.js +3 -0
- package/dist/commands/cron.js +30 -8
- package/dist/commands/human/prompts.d.ts +7 -2
- package/dist/commands/human/prompts.js +15 -10
- package/dist/commands/human.js +1 -2
- package/dist/commands/memory/find.js +11 -8
- package/dist/commands/memory/read.js +111 -11
- package/dist/commands/memory/write.js +1 -1
- package/dist/commands/memory.js +1 -1
- package/dist/commands/pkg/market-manage.d.ts +13 -0
- package/dist/commands/pkg/market-manage.js +39 -33
- package/dist/commands/pkg/plugin-inspect.js +4 -3
- package/dist/commands/pkg/plugin-manage.js +12 -11
- package/dist/commands/surface/node/focus.js +1 -2
- package/dist/commands/sys/doctor.js +4 -4
- package/dist/commands/sys/setup-core.d.ts +14 -7
- package/dist/commands/sys/setup-core.js +66 -11
- package/dist/commands/sys/setup-wizard.js +2 -2
- package/dist/commands/sys/setup.js +1 -1
- package/dist/core/__tests__/cron-held-settlement.test.d.ts +1 -0
- package/dist/core/__tests__/cron-held-settlement.test.js +222 -0
- package/dist/core/__tests__/helpers/harness.js +1 -2
- package/dist/core/__tests__/phase4-review-store.test.js +1 -0
- package/dist/core/__tests__/serial/command-plugins.test.js +88 -1
- package/dist/core/__tests__/session-model.test.js +5 -3
- package/dist/core/bootstrap.d.ts +0 -4
- package/dist/core/bootstrap.js +1 -55
- package/dist/core/canvas/crons.d.ts +54 -2
- package/dist/core/canvas/crons.js +48 -4
- package/dist/core/canvas/db.js +23 -0
- package/dist/core/command-manifests/manifest.d.ts +11 -0
- package/dist/core/command-manifests/manifest.js +45 -4
- package/dist/core/command-manifests/schema.d.ts +1 -1
- package/dist/core/command-plugins/bundle.d.ts +1 -0
- package/dist/core/command-plugins/bundle.js +3 -3
- package/dist/core/command-plugins/discovery.d.ts +5 -2
- package/dist/core/command-plugins/discovery.js +5 -5
- package/dist/core/command-plugins/help-addenda.d.ts +12 -0
- package/dist/core/command-plugins/help-addenda.js +30 -0
- package/dist/core/command.js +25 -2
- package/dist/core/config.js +0 -1
- package/dist/core/human/convention.d.ts +0 -1
- package/dist/core/human/convention.js +0 -6
- package/dist/core/keybindings/inbox.d.ts +6 -8
- package/dist/core/keybindings/inbox.js +6 -15
- package/dist/core/keybindings/index.d.ts +1 -1
- package/dist/core/keybindings/index.js +1 -1
- package/dist/core/memory/doc-link-grammar.js +4 -1
- package/dist/core/memory-resolver.d.ts +28 -4
- package/dist/core/memory-resolver.js +51 -39
- package/dist/core/review/stage.js +1 -0
- package/dist/core/review/store.d.ts +5 -0
- package/dist/core/review/store.js +10 -0
- package/dist/core/review/types.d.ts +4 -0
- package/dist/core/runtime/broker/event-projection.d.ts +8 -1
- package/dist/core/runtime/broker/event-projection.js +25 -1
- package/dist/core/runtime/broker/frame-dispatch.d.ts +2 -0
- package/dist/core/runtime/broker/frame-dispatch.js +50 -8
- package/dist/core/runtime/broker/inbox.d.ts +4 -0
- package/dist/core/runtime/broker/inbox.js +17 -8
- package/dist/core/runtime/broker/message-ledger.d.ts +53 -0
- package/dist/core/runtime/broker/message-ledger.js +143 -0
- package/dist/core/runtime/broker/rebind.js +14 -0
- package/dist/core/runtime/broker-protocol.d.ts +46 -1
- package/dist/core/runtime/broker.js +11 -2
- package/dist/core/runtime/interactive-deliver.d.ts +5 -2
- package/dist/core/runtime/interactive-deliver.js +6 -3
- package/dist/core/runtime/shell-expansion.d.ts +32 -0
- package/dist/core/runtime/shell-expansion.js +102 -0
- package/dist/core/session-model/session-state.d.ts +9 -4
- package/dist/core/session-model/session-state.js +5 -1
- package/dist/daemon/api/handlers/broker-ops.js +8 -0
- package/dist/daemon/api/handlers/crons.js +14 -1
- package/dist/daemon/api/handlers/inbox.js +5 -0
- package/dist/daemon/api/handlers/memory.d.ts +2 -0
- package/dist/daemon/api/handlers/memory.js +48 -0
- package/dist/daemon/api/handlers/messages.js +7 -1
- package/dist/daemon/api/handlers/reviews.js +7 -5
- package/dist/daemon/api/map.js +3 -0
- package/dist/daemon/api/server.js +2 -0
- package/dist/daemon/cron-run.js +71 -3
- package/dist/daemon/crtrd.js +3 -0
- package/dist/daemon/reconcilers/pending-review-submit.d.ts +7 -0
- package/dist/daemon/reconcilers/pending-review-submit.js +35 -0
- package/dist/daemon/review/companion.d.ts +8 -0
- package/dist/daemon/review/companion.js +35 -0
- package/dist/daemon/review/deliver.js +2 -1
- package/dist/daemon/review/finish.d.ts +29 -2
- package/dist/daemon/review/finish.js +75 -2
- package/dist/pi-extensions/canvas-inbox-watcher.js +34 -1
- package/dist/shared/generated-context.d.ts +3 -4
- package/dist/shared/generated-context.js +24 -6
- package/dist/types.d.ts +0 -1
- package/package.json +1 -1
- package/runtime.lock.json +2 -2
package/dist/api/client.d.ts
CHANGED
|
@@ -5,11 +5,12 @@ import type { PushReportRequest, PushReportResultDTO, ReportDTO, ReportsQuery }
|
|
|
5
5
|
import type { CloseRequest, CloseResultDTO, PromoteRequest, RelaunchRootResultDTO, ReviveRequest, ReviveResultDTO, WaitRequest, YieldRequest } from './dto/lifecycle.js';
|
|
6
6
|
import type { SubscribeRequest, SubscriptionDTO } from './dto/subscriptions.js';
|
|
7
7
|
import type { FocusDTO, RegisterFocusRequest, SetFocusPaneRequest } from './dto/focus.js';
|
|
8
|
-
import { type ArmCronRequest, type CancelCronQuery, type CronDTO, type CronRunDTO, type CronScopeQuery, type CronShowDTO, type ListCronsQuery } from './dto/crons.js';
|
|
8
|
+
import { type ArmCronRequest, type CancelCronQuery, type CronDTO, type CronRunDTO, type CronScopeQuery, type CronShowDTO, type ListCronsQuery, type PokeCronsResult } from './dto/crons.js';
|
|
9
9
|
import type { NodeConfigPatch } from './dto/config.js';
|
|
10
10
|
import type { AttachEnsureRequest, AttachEnsureResultDTO } from './dto/attach.js';
|
|
11
11
|
import type { EnsureProfileRequest, ProfileDTO } from './dto/profiles.js';
|
|
12
12
|
import type { FilePeekDTO } from './dto/files.js';
|
|
13
|
+
import type { MemoryDocRefDTO } from './dto/memory.js';
|
|
13
14
|
import type { CredentialRemovalResultDTO, CredentialResultDTO, InstallCredentialRequest, ModelAuthListDTO } from './dto/modelauth.js';
|
|
14
15
|
import type { CreateHumanBridgeRequest, HumanBridgeResultDTO, HumanCancelRequest, HumanCancelResultDTO, HumanResolveRequest, HumanResolveResultDTO } from './dto/human.js';
|
|
15
16
|
import type { CancelReviewRequest, CreateReviewRequest, ListReviewsQuery, ReviewCancelResultDTO, ReviewDocumentBaseDTO, ReviewDTO, ReviewListDTO, ReviewSubmitResultDTO } from './dto/reviews.js';
|
|
@@ -131,6 +132,10 @@ export declare class CrtrClient {
|
|
|
131
132
|
runCron(cronId: string, q?: CronScopeQuery): Promise<CronRunDTO>;
|
|
132
133
|
/** Cancel one cron (`DELETE /v1/crons/:cronId`, idempotent). */
|
|
133
134
|
cancelCron(cronId: string, q?: CancelCronQuery): Promise<void>;
|
|
135
|
+
/** Bare eligibility poke (`POST /v1/crons/poke`): re-dues every held active
|
|
136
|
+
* cron now — "something changed; re-check now". Canvas-wide, label-free,
|
|
137
|
+
* idempotent, and free when nothing is held. */
|
|
138
|
+
pokeCrons(): Promise<PokeCronsResult>;
|
|
134
139
|
ensureAttach(id: string, req?: AttachEnsureRequest): Promise<AttachEnsureResultDTO>;
|
|
135
140
|
getReports(id: string, q?: ReportsQuery): Promise<ReportDTO[]>;
|
|
136
141
|
getTranscript(id: string, q?: TranscriptQuery): Promise<TranscriptDTO>;
|
|
@@ -143,6 +148,10 @@ export declare class CrtrClient {
|
|
|
143
148
|
/** Read an absolute host path as UTF-8 (capped, `truncated` when clipped) for
|
|
144
149
|
* the browser file-peek panel. */
|
|
145
150
|
peekFile(path: string): Promise<FilePeekDTO>;
|
|
151
|
+
/** Resolve a `[[name]]` memory-document link to the absolute path the given
|
|
152
|
+
* node would read — the node's own precedence chain, not this process's.
|
|
153
|
+
* Pair with `peekFile` to render the document. */
|
|
154
|
+
resolveMemoryDoc(name: string, nodeId: string): Promise<MemoryDocRefDTO>;
|
|
146
155
|
ensureProfile(name: string, req?: EnsureProfileRequest): Promise<ProfileDTO>;
|
|
147
156
|
listProfiles(): Promise<ProfileDTO[]>;
|
|
148
157
|
getProfile(name: string): Promise<ProfileDTO>;
|
package/dist/api/client.js
CHANGED
|
@@ -227,6 +227,12 @@ export class CrtrClient {
|
|
|
227
227
|
async cancelCron(cronId, q) {
|
|
228
228
|
await this.request('DELETE', withQuery(routes.cron(this.cronPath(cronId)), q));
|
|
229
229
|
}
|
|
230
|
+
/** Bare eligibility poke (`POST /v1/crons/poke`): re-dues every held active
|
|
231
|
+
* cron now — "something changed; re-check now". Canvas-wide, label-free,
|
|
232
|
+
* idempotent, and free when nothing is held. */
|
|
233
|
+
pokeCrons() {
|
|
234
|
+
return this.request('POST', routes.cronsPoke(), {});
|
|
235
|
+
}
|
|
230
236
|
ensureAttach(id, req) {
|
|
231
237
|
return this.request('POST', routes.nodeAttach(this.nodePath(id)), req ?? {});
|
|
232
238
|
}
|
|
@@ -257,6 +263,13 @@ export class CrtrClient {
|
|
|
257
263
|
peekFile(path) {
|
|
258
264
|
return this.request('GET', withQuery(routes.filePeek(), { path }));
|
|
259
265
|
}
|
|
266
|
+
// ---- Memory documents --------------------------------------------------
|
|
267
|
+
/** Resolve a `[[name]]` memory-document link to the absolute path the given
|
|
268
|
+
* node would read — the node's own precedence chain, not this process's.
|
|
269
|
+
* Pair with `peekFile` to render the document. */
|
|
270
|
+
resolveMemoryDoc(name, nodeId) {
|
|
271
|
+
return this.request('GET', withQuery(routes.memoryResolve(), { name, node: nodeId }));
|
|
272
|
+
}
|
|
260
273
|
// ---- Profiles ----------------------------------------------------------
|
|
261
274
|
ensureProfile(name, req) {
|
|
262
275
|
return this.request('PUT', routes.profile(name), req ?? {});
|
package/dist/api/dto/broker.d.ts
CHANGED
|
@@ -28,6 +28,38 @@ export interface BrokerWelcomeSnapshot<M = unknown> {
|
|
|
28
28
|
export interface BrokerWelcomeFrame<M = unknown> {
|
|
29
29
|
type: 'welcome';
|
|
30
30
|
snapshot?: BrokerWelcomeSnapshot<M>;
|
|
31
|
+
/** The last few id-bearing user-message dispatches from the broker's message
|
|
32
|
+
* ledger, oldest first — so a reattaching follower can key the snapshot's
|
|
33
|
+
* trailing user wakes by id (the id a sender minted via `message_id` on
|
|
34
|
+
* `POST .../messages`) instead of discarding them heuristically. Live-process
|
|
35
|
+
* memory only: a broker restart loses it. Absent on a broker pinned to an
|
|
36
|
+
* older runtime generation. */
|
|
37
|
+
recentUserMessages?: Array<{
|
|
38
|
+
id: string;
|
|
39
|
+
text: string;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The additive identity fields the broker sets on a relayed pi `queue_update`:
|
|
44
|
+
* id arrays PARALLEL to pi's text arrays (`steeringIds[i]` identifies
|
|
45
|
+
* `steering[i]`). Sender-minted when the send carried `message_id`,
|
|
46
|
+
* broker-minted otherwise. Absent on a broker pinned to an older runtime
|
|
47
|
+
* generation — consumers fall back to bare texts. Intersect with the pinned pi
|
|
48
|
+
* `queue_update` event shape to read them typed.
|
|
49
|
+
*/
|
|
50
|
+
export interface RelayedQueueUpdateIdentity {
|
|
51
|
+
steeringIds?: string[];
|
|
52
|
+
followUpIds?: string[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The additive identity field the broker sets on a relayed USER-role
|
|
56
|
+
* `message_start`: the message's crouter id — the `message_id` its sender
|
|
57
|
+
* minted, or a broker-minted one. Absent when the message carries none (an
|
|
58
|
+
* engine-command expansion, a pre-ledger replay, an older broker). Intersect
|
|
59
|
+
* with the pinned pi `message_start` event shape to read it typed.
|
|
60
|
+
*/
|
|
61
|
+
export interface RelayedUserMessageStartIdentity {
|
|
62
|
+
crtrMessageId?: string;
|
|
31
63
|
}
|
|
32
64
|
/**
|
|
33
65
|
* The broker-control frames a relay consumer reads: `welcome` (catch-up snapshot)
|
package/dist/api/dto/crons.d.ts
CHANGED
|
@@ -53,6 +53,14 @@ export interface CronDTO {
|
|
|
53
53
|
sink: string | null;
|
|
54
54
|
tier: string;
|
|
55
55
|
state: CronStateDTO;
|
|
56
|
+
/** True while the row is parked by the exit-75 owed-gate disposition: the
|
|
57
|
+
* last scheduled run declared "owed but not currently eligible", so the
|
|
58
|
+
* occurrence was not spent. A daemon poke re-dues it now; otherwise a
|
|
59
|
+
* recurring row re-checks at its natural `fire_at` slot (the backstop) and
|
|
60
|
+
* a held one-shot waits for a poke until `expires_at` deletes it. `state`
|
|
61
|
+
* stays honest (active|paused) — renderers derive; an active held row must
|
|
62
|
+
* never present as paused. */
|
|
63
|
+
held: boolean;
|
|
56
64
|
run_state: CronRunStateDTO;
|
|
57
65
|
/** Recent health: the most recent settled run, or null if it never ran. */
|
|
58
66
|
last_run: CronLastRunDTO | null;
|
|
@@ -93,6 +101,15 @@ export interface CronRunDTO {
|
|
|
93
101
|
/** What the sink did with this run's output, or why it didn't. */
|
|
94
102
|
delivered: string | null;
|
|
95
103
|
}
|
|
104
|
+
/** `POST /v1/crons/poke` — the bare daemon-level eligibility poke. Re-dues
|
|
105
|
+
* every held active cron now; paused rows keep their held state. Idempotent
|
|
106
|
+
* and free when nothing is held. */
|
|
107
|
+
export interface PokeCronsResult {
|
|
108
|
+
/** How many held rows were re-dued — for the caller's log line. */
|
|
109
|
+
unparked: number;
|
|
110
|
+
/** The poke receipt instant (UTC). */
|
|
111
|
+
at: IsoTime;
|
|
112
|
+
}
|
|
96
113
|
/** `GET /v1/crons/:cronId` — one cron with its run-log ring (most recent first). */
|
|
97
114
|
export interface CronShowDTO {
|
|
98
115
|
cron: CronDTO;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** `GET /v1/memory/resolve?name=<name>&node=<id>` result — where the named
|
|
2
|
+
* document lives for that node. Resolution runs the node's own precedence
|
|
3
|
+
* chain (its context store, its project stack, its profile, user, builtin), so
|
|
4
|
+
* the same name can answer with different documents for different nodes. */
|
|
5
|
+
export interface MemoryDocRefDTO {
|
|
6
|
+
/** The document's canonical identity (its frontmatter `name`, else its
|
|
7
|
+
* path-derived name) — which may differ from the queried name when the query
|
|
8
|
+
* was a bare leaf or a directory whose INDEX resolved. */
|
|
9
|
+
name: string;
|
|
10
|
+
/** Which store it came from: node | project | profile | user | builtin. */
|
|
11
|
+
scope: string;
|
|
12
|
+
/** Absolute path to the `.md` file. */
|
|
13
|
+
path: string;
|
|
14
|
+
/** The owning plugin's name when the doc is mounted from an installed plugin,
|
|
15
|
+
* absent for a native scope doc. */
|
|
16
|
+
plugin?: string;
|
|
17
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Memory-document resolution DTO. Backs `GET /v1/memory/resolve` — a client
|
|
2
|
+
// holding a `[[name]]` link out of a node's transcript turns it into the
|
|
3
|
+
// absolute path of the document that node would read, then peeks that path.
|
|
4
|
+
//
|
|
5
|
+
// PURITY (spec §3.1): Node built-ins + `src/api/*` only.
|
|
6
|
+
export {};
|
|
@@ -26,6 +26,11 @@ export interface SendMessageRequest {
|
|
|
26
26
|
* body only — rejected with fresh/reopen/situational_context/
|
|
27
27
|
* output_schema or tier 'deferred'. Absent → durable inbox (unchanged). */
|
|
28
28
|
delivery?: 'interactive';
|
|
29
|
+
/** Sender-minted message identity for a `delivery:'interactive'` send. The
|
|
30
|
+
* broker mirrors it through pi's queues and echoes it on the relayed user
|
|
31
|
+
* `message_start` (`crtrMessageId`), so an optimistic sender (the gateway)
|
|
32
|
+
* retires its pending entry by exact id. Ignored on the durable-inbox path. */
|
|
33
|
+
message_id?: string;
|
|
29
34
|
}
|
|
30
35
|
/** Result of an immediate message send. */
|
|
31
36
|
export interface MessageResultDTO {
|
|
@@ -38,6 +38,9 @@ export interface ReviewDTO {
|
|
|
38
38
|
created: IsoTime;
|
|
39
39
|
/** Daemon open timestamp, after the companion binds. */
|
|
40
40
|
opened_at?: IsoTime;
|
|
41
|
+
/** When the human submitted a review whose companion was still working. The
|
|
42
|
+
* review remains `open` until the companion goes quiet. */
|
|
43
|
+
submit_requested_at?: IsoTime;
|
|
41
44
|
/** Daemon source-read status at projection time. */
|
|
42
45
|
source_missing: boolean;
|
|
43
46
|
/** Daemon-owned current comment-coordinate source digest. */
|
|
@@ -73,12 +76,13 @@ export interface ListReviewsQuery {
|
|
|
73
76
|
export interface ReviewListDTO {
|
|
74
77
|
reviews: ReviewDTO[];
|
|
75
78
|
}
|
|
76
|
-
/** Daemon-derived result of
|
|
79
|
+
/** Daemon-derived result of review approval, which may still be waiting on the
|
|
80
|
+
* review's companion. */
|
|
77
81
|
export interface ReviewSubmitResultDTO {
|
|
78
82
|
review: ReviewDTO;
|
|
79
|
-
/** Immutable approval result. */
|
|
80
|
-
result
|
|
81
|
-
outcome: 'settled' | 'already_settled';
|
|
83
|
+
/** Immutable approval result; absent while the approval awaits the companion. */
|
|
84
|
+
result?: FeedbackResultDTO;
|
|
85
|
+
outcome: 'settled' | 'already_settled' | 'awaiting_companion';
|
|
82
86
|
}
|
|
83
87
|
/** Daemon-derived result of terminal review cancellation. */
|
|
84
88
|
export interface ReviewCancelResultDTO {
|
package/dist/api/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export * from './dto/canvas.js';
|
|
|
21
21
|
export * from './dto/worktree.js';
|
|
22
22
|
export * from './dto/human.js';
|
|
23
23
|
export * from './dto/files.js';
|
|
24
|
+
export * from './dto/memory.js';
|
|
24
25
|
export * from './dto/inbox.js';
|
|
25
26
|
export * from './dto/reviews.js';
|
|
26
27
|
export * from './dto/review-comments.js';
|
package/dist/api/index.js
CHANGED
|
@@ -22,6 +22,7 @@ export * from './dto/canvas.js';
|
|
|
22
22
|
export * from './dto/worktree.js';
|
|
23
23
|
export * from './dto/human.js';
|
|
24
24
|
export * from './dto/files.js';
|
|
25
|
+
export * from './dto/memory.js';
|
|
25
26
|
export * from './dto/inbox.js';
|
|
26
27
|
export * from './dto/reviews.js';
|
|
27
28
|
export * from './dto/review-comments.js';
|
package/dist/api/routes.d.ts
CHANGED
|
@@ -46,6 +46,7 @@ export declare const routes: {
|
|
|
46
46
|
readonly cronPause: (cronId: string) => string;
|
|
47
47
|
readonly cronResume: (cronId: string) => string;
|
|
48
48
|
readonly cronRun: (cronId: string) => string;
|
|
49
|
+
readonly cronsPoke: () => string;
|
|
49
50
|
readonly canvasAttention: () => string;
|
|
50
51
|
readonly canvasAttentionCounts: () => string;
|
|
51
52
|
readonly canvasHistorySearch: () => string;
|
|
@@ -81,4 +82,5 @@ export declare const routes: {
|
|
|
81
82
|
readonly modelAuths: () => string;
|
|
82
83
|
readonly modelAuth: (provider: string) => string;
|
|
83
84
|
readonly filePeek: () => string;
|
|
85
|
+
readonly memoryResolve: () => string;
|
|
84
86
|
};
|
package/dist/api/routes.js
CHANGED
|
@@ -67,6 +67,7 @@ export const routes = {
|
|
|
67
67
|
cronPause: (cronId) => `${V}/crons/${cronId}/pause`,
|
|
68
68
|
cronResume: (cronId) => `${V}/crons/${cronId}/resume`,
|
|
69
69
|
cronRun: (cronId) => `${V}/crons/${cronId}/run`,
|
|
70
|
+
cronsPoke: () => `${V}/crons/poke`,
|
|
70
71
|
// Canvas maintenance / reads
|
|
71
72
|
canvasAttention: () => `${V}/canvas/attention`,
|
|
72
73
|
canvasAttentionCounts: () => `${V}/canvas/attention/counts`,
|
|
@@ -112,4 +113,7 @@ export const routes = {
|
|
|
112
113
|
// Host file read (browser file-peek panel). The absolute path rides as a
|
|
113
114
|
// `path` query param, not a path segment — it is not a single safe segment.
|
|
114
115
|
filePeek: () => `${V}/files/peek`,
|
|
116
|
+
// Memory-document resolution (a `[[name]]` link in a node's transcript). Both
|
|
117
|
+
// the name and the node it is resolved for ride as query params.
|
|
118
|
+
memoryResolve: () => `${V}/memory/resolve`,
|
|
115
119
|
};
|
package/dist/build-root.d.ts
CHANGED
|
@@ -2,6 +2,13 @@ import type { RootDef } from './core/command.js';
|
|
|
2
2
|
/** Every shipped subtree name. Cheap (no module loading) — the front-door
|
|
3
3
|
* recursion guard and the dispatcher's first-token routing need only names. */
|
|
4
4
|
export declare const SUBTREE_NAMES: readonly string[];
|
|
5
|
+
/** Every core command path, space-joined ("cron", "cron add", …) — the set
|
|
6
|
+
* plugin `helpAddenda` keys are validated against at the strict gates
|
|
7
|
+
* (install, bundle parse, doctor/inspect reports). Loads every core subtree,
|
|
8
|
+
* so call it only from those gates, never on a dispatch path. Passthrough
|
|
9
|
+
* branches are excluded: crtr never renders their help, so an addendum
|
|
10
|
+
* targeting one could never appear. */
|
|
11
|
+
export declare function coreCommandPaths(): Promise<ReadonlySet<string>>;
|
|
5
12
|
/** Build a root that contains only the subtree `first` dispatches into.
|
|
6
13
|
* Returns the FULL root when `first` is not a recognized subtree — bare `crtr`,
|
|
7
14
|
* `-h`/`--help`, `--version`, and any unknown leading token all need the
|
package/dist/build-root.js
CHANGED
|
@@ -23,6 +23,27 @@ const SUBTREE_LOADERS = {
|
|
|
23
23
|
/** Every shipped subtree name. Cheap (no module loading) — the front-door
|
|
24
24
|
* recursion guard and the dispatcher's first-token routing need only names. */
|
|
25
25
|
export const SUBTREE_NAMES = Object.freeze(Object.keys(SUBTREE_LOADERS));
|
|
26
|
+
/** Every core command path, space-joined ("cron", "cron add", …) — the set
|
|
27
|
+
* plugin `helpAddenda` keys are validated against at the strict gates
|
|
28
|
+
* (install, bundle parse, doctor/inspect reports). Loads every core subtree,
|
|
29
|
+
* so call it only from those gates, never on a dispatch path. Passthrough
|
|
30
|
+
* branches are excluded: crtr never renders their help, so an addendum
|
|
31
|
+
* targeting one could never appear. */
|
|
32
|
+
export async function coreCommandPaths() {
|
|
33
|
+
const core = await Promise.all(SUBTREE_NAMES.map((n) => SUBTREE_LOADERS[n]()));
|
|
34
|
+
const paths = new Set();
|
|
35
|
+
const visit = (node, prefix) => {
|
|
36
|
+
if (node.kind === 'branch' && node.passthrough !== undefined)
|
|
37
|
+
return;
|
|
38
|
+
paths.add(prefix);
|
|
39
|
+
if (node.kind === 'branch')
|
|
40
|
+
for (const child of node.children)
|
|
41
|
+
visit(child, `${prefix} ${child.name}`);
|
|
42
|
+
};
|
|
43
|
+
for (const subtree of core)
|
|
44
|
+
visit(subtree, subtree.name);
|
|
45
|
+
return paths;
|
|
46
|
+
}
|
|
26
47
|
/** Build a root that contains only the subtree `first` dispatches into.
|
|
27
48
|
* Returns the FULL root when `first` is not a recognized subtree — bare `crtr`,
|
|
28
49
|
* `-h`/`--help`, `--version`, and any unknown leading token all need the
|
|
@@ -8,11 +8,15 @@ slash: true
|
|
|
8
8
|
rationale: Ordinary conversations, corrections, answers to `crtr human ask`, and review comments carry unique user knowledge that agents inconsistently recognize or save; when agents do infer a deeper principle, they have written it without first letting the user correct the extrapolation.
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
# /insights:init — begin
|
|
11
|
+
# /insights:init — begin domain listening
|
|
12
12
|
|
|
13
|
-
Initialize an ordinary memory directory that listens for user-derived insight about this domain.
|
|
13
|
+
Initialize an ordinary memory directory that listens for user-derived insight about this domain.
|
|
14
14
|
|
|
15
|
-
**Requested domain:** $ARGUMENTS
|
|
15
|
+
**Requested domain and mode:** $ARGUMENTS
|
|
16
|
+
|
|
17
|
+
## Check for --active flag
|
|
18
|
+
|
|
19
|
+
If `$ARGUMENTS` contains `--active`, follow the **active mode** steps below. Otherwise, follow the **passive mode** steps.
|
|
16
20
|
|
|
17
21
|
## Establish the topic and scope
|
|
18
22
|
|
|
@@ -43,3 +47,44 @@ Keep the body short. It contains:
|
|
|
43
47
|
Do not copy the capture workflow into the listener. The link keeps that process in one maintained place. Do not create placeholder principle documents.
|
|
44
48
|
|
|
45
49
|
Run `crtr memory lint`, fix every finding, then report the canonical listener name, selected scope, and the domain boundary. Initialization is complete once the routed listener exists; no independent work follows.
|
|
50
|
+
|
|
51
|
+
## Active mode: research and surface claims
|
|
52
|
+
|
|
53
|
+
When `--active` is present, do not stop after creating the listener. After initialization:
|
|
54
|
+
|
|
55
|
+
### 1. Create the listener first
|
|
56
|
+
|
|
57
|
+
Follow the passive mode steps above through "Initialization is complete." The listener INDEX must exist before spawning the explorer.
|
|
58
|
+
|
|
59
|
+
### 2. Spawn the explorer child
|
|
60
|
+
|
|
61
|
+
Run this exact command, replacing `<topic>` with the topic slug you chose above:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
crtr node new --kind explore --name "explore-<topic>" <<'TASK'
|
|
65
|
+
Investigate the domain "<topic>" thoroughly. Your goal is to surface 3–5 distinct, falsifiable claims or questions about how this domain works, what its gaps are, or what fundamental principles govern it. Each claim should be specific enough that the user can confirm it, refine it, or reject it outright.
|
|
66
|
+
|
|
67
|
+
Gather evidence from code, docs, existing understanding, and project artifacts. Then present your claims clearly:
|
|
68
|
+
|
|
69
|
+
**Claim 1:** [claim text]
|
|
70
|
+
**Evidence:** [why you believe this]
|
|
71
|
+
**Question:** [what would prove or disprove this?]
|
|
72
|
+
|
|
73
|
+
Repeat for each claim. Write findings to $CRTR_CONTEXT_DIR/claims.md and report the absolute path.
|
|
74
|
+
TASK
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Do not wait for the explorer to finish—it runs in parallel. Move to the next step while it works.
|
|
78
|
+
|
|
79
|
+
### 3. Coordinate user responses and capture flow
|
|
80
|
+
|
|
81
|
+
When the explorer reports, share its claims with the user. For each claim, ask:
|
|
82
|
+
- Does this ring true?
|
|
83
|
+
- Is it incomplete or wrong?
|
|
84
|
+
- What's the actual principle?
|
|
85
|
+
|
|
86
|
+
For each user response, use [[insights/capture]] to extract and review the insight. Apply approved insights directly to the listener INDEX's `Approved insights` section.
|
|
87
|
+
|
|
88
|
+
### 4. Report completion
|
|
89
|
+
|
|
90
|
+
Once claims have been surfaced and user guidance has generated approved insights, report that active initialization is complete. The listener INDEX now passively captures this domain as new user material emerges.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import { strict as assert } from 'node:assert';
|
|
3
|
+
|
|
4
|
+
// Integration test: /insights:init --active spawns an explorer and coordinates
|
|
5
|
+
// insight capture flow. This test verifies that:
|
|
6
|
+
// 1. The active mode doc exists and has slash: true
|
|
7
|
+
// 2. The active mode instructions are present and executable
|
|
8
|
+
// 3. A reader following the instructions can spawn an explorer
|
|
9
|
+
|
|
10
|
+
test('insights/init has active mode documentation with executable commands', async () => {
|
|
11
|
+
const { readFileSync } = await import('fs');
|
|
12
|
+
const initPath = new URL('../../../builtin-memory/insights/init.md', import.meta.url);
|
|
13
|
+
const content = readFileSync(initPath, 'utf-8');
|
|
14
|
+
|
|
15
|
+
// Must be marked as a slash command
|
|
16
|
+
assert(content.includes('slash: true'), 'init.md must have slash: true frontmatter');
|
|
17
|
+
|
|
18
|
+
// Must have active mode section
|
|
19
|
+
assert(
|
|
20
|
+
content.includes('## Active mode: research and surface claims'),
|
|
21
|
+
'init.md must document active mode'
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Must have active flag check
|
|
25
|
+
assert(
|
|
26
|
+
content.includes('Check for --active flag') || content.includes('--active'),
|
|
27
|
+
'init.md must explain --active flag'
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
// Must have executable crtr commands for spawning explorer
|
|
31
|
+
assert(
|
|
32
|
+
content.includes('crtr node new --kind explore'),
|
|
33
|
+
'init.md must include crtr command to spawn explorer'
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// Must reference the capture workflow
|
|
37
|
+
assert(
|
|
38
|
+
content.includes('[[insights/capture]]'),
|
|
39
|
+
'init.md must link to capture workflow'
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// Must document waiting for explorer report
|
|
43
|
+
assert(
|
|
44
|
+
content.includes('Wait for the explorer to report') || content.includes('explorer'),
|
|
45
|
+
'init.md must explain waiting for explorer'
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Must document coordinating user responses
|
|
49
|
+
assert(
|
|
50
|
+
content.includes('user response') || content.includes('Turn user responses'),
|
|
51
|
+
'init.md must explain handling user responses'
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('active mode provides concrete bash commands agent can execute', async () => {
|
|
56
|
+
const { readFileSync } = await import('fs');
|
|
57
|
+
const initPath = new URL('../../../builtin-memory/insights/init.md', import.meta.url);
|
|
58
|
+
const content = readFileSync(initPath, 'utf-8');
|
|
59
|
+
|
|
60
|
+
// The active mode section should have a bash code block
|
|
61
|
+
const bashBlockMatch = content.match(/```bash\n([\s\S]*?)\n```/);
|
|
62
|
+
assert(bashBlockMatch, 'active mode must have a bash code block');
|
|
63
|
+
|
|
64
|
+
const bashContent = bashBlockMatch[1];
|
|
65
|
+
|
|
66
|
+
// Must have the crtr node new command
|
|
67
|
+
assert(bashContent.includes('crtr node new'), 'bash block must invoke crtr node new');
|
|
68
|
+
|
|
69
|
+
// Must specify --kind explore
|
|
70
|
+
assert(
|
|
71
|
+
bashContent.includes('--kind explore'),
|
|
72
|
+
'bash command must spawn explore kind'
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// Must have the task heredoc
|
|
76
|
+
assert(
|
|
77
|
+
bashContent.includes('<<') || bashContent.includes('TASK'),
|
|
78
|
+
'bash command must include task definition'
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
// Must document the explorer task
|
|
82
|
+
assert(
|
|
83
|
+
bashContent.includes('investigate') || bashContent.includes('domain'),
|
|
84
|
+
'explorer task must mention domain investigation'
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
// Must ask explorer to surface claims
|
|
88
|
+
assert(
|
|
89
|
+
bashContent.includes('claim') || bashContent.includes('surface'),
|
|
90
|
+
'explorer task must ask for claims/surface evidence'
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// Must reference output location
|
|
94
|
+
assert(
|
|
95
|
+
bashContent.includes('$CRTR_CONTEXT_DIR') || bashContent.includes('context'),
|
|
96
|
+
'explorer task must reference context directory output'
|
|
97
|
+
);
|
|
98
|
+
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { truncateTail, formatSize, DEFAULT_MAX_LINES, DEFAULT_MAX_BYTES } from "@earendil-works/pi-coding-agent";
|
|
3
2
|
import {
|
|
4
3
|
readFileSync,
|
|
5
4
|
readdirSync,
|
|
@@ -14,6 +13,8 @@ import { homedir } from "node:os";
|
|
|
14
13
|
import { join, resolve, dirname } from "node:path";
|
|
15
14
|
import { loadProfileManifest } from "../../../core/profiles/manifest.js";
|
|
16
15
|
import { stripMarkdownComments } from "../../../core/runtime/command-expansion.js";
|
|
16
|
+
import { expandShellBlocks, DEFAULT_SHELL_TIMEOUT_MS } from "../../../core/runtime/shell-expansion.js";
|
|
17
|
+
import { piShellRunner } from "./pi-shell-runner.js";
|
|
17
18
|
|
|
18
19
|
// ---------------------------------------------------------------------------
|
|
19
20
|
// claude-plugin-commands: surfaces Claude Code commands AND skills as pi slash
|
|
@@ -367,57 +368,13 @@ function shellTimeoutMs(fm: string): number {
|
|
|
367
368
|
}
|
|
368
369
|
|
|
369
370
|
// ---- shell execution (mirrors @juicesharp/rpiv-args) -----------------------
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
function truncateForLLM(content: string): string {
|
|
376
|
-
const t = truncateTail(content, { maxLines: DEFAULT_MAX_LINES, maxBytes: DEFAULT_MAX_BYTES });
|
|
377
|
-
let out = t.content;
|
|
378
|
-
if (t.truncated) {
|
|
379
|
-
const limit = t.truncatedBy === "lines" ? `${t.maxLines} lines` : formatSize(t.maxBytes);
|
|
380
|
-
out += `\n[truncated: hit ${limit}]`;
|
|
381
|
-
}
|
|
382
|
-
return out;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
async function runShell(cmd: string, pi: ExtensionAPI, cwd: string, timeoutMs: number): Promise<string> {
|
|
386
|
-
const [sh, flag] = process.platform === "win32" ? ["powershell.exe", "-Command"] : ["sh", "-c"];
|
|
387
|
-
const res: any = await pi.exec(sh, [flag, cmd], { cwd, timeout: timeoutMs });
|
|
388
|
-
if (res.killed) return `[Shell error: timed out after ${Math.max(1, Math.round(timeoutMs / 1000))}s]`;
|
|
389
|
-
if (res.code !== 0) return `[Shell error: exit code ${res.code}]\n${truncateForLLM(res.stderr ?? "")}`;
|
|
390
|
-
let combined = res.stdout ?? "";
|
|
391
|
-
if (res.stderr) {
|
|
392
|
-
const sep = combined.length === 0 || combined.endsWith("\n") ? "" : "\n";
|
|
393
|
-
combined = `${combined}${sep}[stderr]\n${res.stderr}`;
|
|
394
|
-
}
|
|
395
|
-
return truncateForLLM(combined);
|
|
396
|
-
}
|
|
371
|
+
//
|
|
372
|
+
// The `!`cmd`` / ```! grammar and substitution order are shared with every
|
|
373
|
+
// other surface that expands a Markdown body (`core/runtime/shell-expansion`);
|
|
374
|
+
// the pi-engine execution strategy is shared through `pi-shell-runner`.
|
|
397
375
|
|
|
398
376
|
async function executeShell(body: string, pi: ExtensionAPI, cwd: string, timeoutMs: number): Promise<string> {
|
|
399
|
-
|
|
400
|
-
const blockOut: string[] = [];
|
|
401
|
-
let masked = "";
|
|
402
|
-
let last = 0;
|
|
403
|
-
for (const m of body.matchAll(SHELL_BLOCK)) {
|
|
404
|
-
const idx = m.index ?? 0;
|
|
405
|
-
masked += body.slice(last, idx) + `\x00B${blockOut.length}\x00`;
|
|
406
|
-
blockOut.push(await runShell(m[1] ?? "", pi, cwd, timeoutMs));
|
|
407
|
-
last = idx + m[0].length;
|
|
408
|
-
}
|
|
409
|
-
masked += body.slice(last);
|
|
410
|
-
|
|
411
|
-
let inlined = "";
|
|
412
|
-
last = 0;
|
|
413
|
-
for (const m of masked.matchAll(SHELL_INLINE)) {
|
|
414
|
-
const idx = m.index ?? 0;
|
|
415
|
-
inlined += masked.slice(last, idx) + (await runShell(m[1] ?? "", pi, cwd, timeoutMs));
|
|
416
|
-
last = idx + m[0].length;
|
|
417
|
-
}
|
|
418
|
-
inlined += masked.slice(last);
|
|
419
|
-
|
|
420
|
-
return inlined.replace(/\x00B(\d+)\x00/g, (_, n) => blockOut[parseInt(n, 10)] ?? "");
|
|
377
|
+
return expandShellBlocks(body, piShellRunner(pi, cwd, timeoutMs));
|
|
421
378
|
}
|
|
422
379
|
|
|
423
380
|
// ---------------------------------------------------------------------------
|
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
expandDeterministicCommand,
|
|
6
6
|
type DeterministicCommandExpansion,
|
|
7
7
|
} from "../../../core/runtime/command-expansion.js";
|
|
8
|
+
import { expandShellBlocks, hasShellBlocks, DEFAULT_SHELL_TIMEOUT_MS } from "../../../core/runtime/shell-expansion.js";
|
|
9
|
+
import { piShellRunner } from "./pi-shell-runner.js";
|
|
8
10
|
|
|
9
11
|
// ---------------------------------------------------------------------------
|
|
10
12
|
// memory-slash-commands: any memory doc frontmatter-flagged `slash: true`
|
|
@@ -136,10 +138,23 @@ export default async function (pi: ExtensionAPI) {
|
|
|
136
138
|
);
|
|
137
139
|
return;
|
|
138
140
|
}
|
|
141
|
+
// Shell runs HERE and only here. `expandDeterministicCommand` stays
|
|
142
|
+
// inert because it also drives the attach viewer's pre-submit preview,
|
|
143
|
+
// which re-expands on every keystroke — executing there would run the
|
|
144
|
+
// document's commands repeatedly while the user is still typing. This
|
|
145
|
+
// handler fires once, at submit, so the preview shows the command text
|
|
146
|
+
// and the submitted turn carries its output.
|
|
147
|
+
const expanded = expandDeterministicCommand(expansion, args ?? "");
|
|
148
|
+
const content = hasShellBlocks(expanded)
|
|
149
|
+
? await expandShellBlocks(
|
|
150
|
+
expanded,
|
|
151
|
+
piShellRunner(pi, (ctx as { cwd?: string }).cwd ?? process.cwd(), DEFAULT_SHELL_TIMEOUT_MS),
|
|
152
|
+
)
|
|
153
|
+
: expanded;
|
|
139
154
|
pi.sendMessage(
|
|
140
155
|
{
|
|
141
156
|
customType: "memory-slash-command",
|
|
142
|
-
content
|
|
157
|
+
content,
|
|
143
158
|
display: true,
|
|
144
159
|
},
|
|
145
160
|
{ triggerTurn: true },
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { truncateTail, formatSize, DEFAULT_MAX_LINES, DEFAULT_MAX_BYTES } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
|
|
4
|
+
// The broker-side execution strategy for `core/runtime/shell-expansion`. Every
|
|
5
|
+
// command surface that expands a Markdown body inside a pi engine shares it, so
|
|
6
|
+
// the engine owns the subprocess and truncation uses pi's own limits. The
|
|
7
|
+
// grammar and substitution order live in the shared module; only this strategy
|
|
8
|
+
// is pi-specific, and it stays out of that module so CLI leaves can import the
|
|
9
|
+
// expander without loading the pi runtime.
|
|
10
|
+
|
|
11
|
+
function truncateForLLM(content: string): string {
|
|
12
|
+
const t = truncateTail(content, { maxLines: DEFAULT_MAX_LINES, maxBytes: DEFAULT_MAX_BYTES });
|
|
13
|
+
let out = t.content;
|
|
14
|
+
if (t.truncated) {
|
|
15
|
+
const limit = t.truncatedBy === "lines" ? `${t.maxLines} lines` : formatSize(t.maxBytes);
|
|
16
|
+
out += `\n[truncated: hit ${limit}]`;
|
|
17
|
+
}
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function piShellRunner(pi: ExtensionAPI, cwd: string, timeoutMs: number) {
|
|
22
|
+
const [sh, flag] = process.platform === "win32" ? ["powershell.exe", "-Command"] : ["sh", "-c"];
|
|
23
|
+
return async (cmd: string): Promise<string> => {
|
|
24
|
+
const res: any = await pi.exec(sh, [flag, cmd], { cwd, timeout: timeoutMs });
|
|
25
|
+
if (res.killed) return `[Shell error: timed out after ${Math.max(1, Math.round(timeoutMs / 1000))}s]`;
|
|
26
|
+
if (res.code !== 0) return `[Shell error: exit code ${res.code}]\n${truncateForLLM(res.stderr ?? "")}`;
|
|
27
|
+
let combined = res.stdout ?? "";
|
|
28
|
+
if (res.stderr) {
|
|
29
|
+
const sep = combined.length === 0 || combined.endsWith("\n") ? "" : "\n";
|
|
30
|
+
combined = `${combined}${sep}[stderr]\n${res.stderr}`;
|
|
31
|
+
}
|
|
32
|
+
return truncateForLLM(combined);
|
|
33
|
+
};
|
|
34
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import { runCli } from './core/command.js';
|
|
|
7
7
|
import { resolveRoot } from './build-root.js';
|
|
8
8
|
import { maybeBootRoot } from './core/runtime/front-door.js';
|
|
9
9
|
import { maybeAutoUpdate } from './core/auto-update.js';
|
|
10
|
-
import {
|
|
10
|
+
import { ensureProjectScope } from './core/bootstrap.js';
|
|
11
11
|
import { provisionExports, pruneLegacyExports } from './core/host-exports/export.js';
|
|
12
12
|
import { installStdoutErrorPolicy } from './core/stdout-errors.js';
|
|
13
13
|
import { handle } from './core/io.js';
|
|
@@ -54,7 +54,6 @@ async function main() {
|
|
|
54
54
|
const root = await resolveRoot(process.argv[2]);
|
|
55
55
|
mark('cli.root_resolved');
|
|
56
56
|
provisionExports(root, process.argv);
|
|
57
|
-
ensureOfficialMarketplace(process.argv);
|
|
58
57
|
ensureProjectScope(process.argv);
|
|
59
58
|
maybeAutoUpdate(process.argv);
|
|
60
59
|
mark('cli.dispatch_start');
|