@north-light/crouter-api 0.3.281 → 0.3.283
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 +19 -3
- package/dist/api/client.js +34 -0
- package/dist/api/dto/broker-ops.d.ts +11 -0
- package/dist/api/dto/broker.d.ts +3 -8
- package/dist/api/dto/common.d.ts +1 -1
- package/dist/api/dto/messages.d.ts +2 -2
- package/dist/api/dto/node-outcomes.d.ts +80 -0
- package/dist/api/dto/node-outcomes.js +2 -0
- package/dist/api/dto/nodes.d.ts +9 -0
- package/dist/api/dto/profiles.d.ts +5 -0
- package/dist/api/dto/reports.d.ts +45 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/plugin-manifest-schema.d.ts +208 -0
- package/dist/api/plugin-manifest-schema.js +23 -0
- package/dist/api/routes.d.ts +7 -0
- package/dist/api/routes.js +7 -0
- package/dist/shared/env.d.ts +3 -0
- package/dist/shared/env.js +6 -0
- package/dist/shared/generated-context.d.ts +3 -9
- package/dist/shared/generated-context.js +8 -16
- package/package.json +8 -2
package/dist/api/client.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { DaemonRestartDTO, HealthDTO, StatusDTO } from './dto/health.js';
|
|
2
2
|
import type { BashJobStatusDTO, BashJobStopResultDTO } from './dto/bash-jobs.js';
|
|
3
3
|
import type { ArtifactListDTO, ArtifactsQuery, ContextListDTO, CreateNodeRequest, ListNodesQuery, NodeDetailDTO, NodeMessagesPageDTO, NodeMessagesQuery, NodeSessionDTO, NodeSnapshotDTO, NodeSubjectDTO, NodeSummaryDTO, TranscriptDTO, TranscriptQuery } from './dto/nodes.js';
|
|
4
|
+
import type { NodeOutcomeResponseDTO, OutcomeDeliveryDTO, RegisterOutcomeDeliveryRequest } from './dto/node-outcomes.js';
|
|
4
5
|
import type { InterruptResultDTO, MessageResultDTO, SendMessageRequest } from './dto/messages.js';
|
|
5
|
-
import type { PushReportRequest, PushReportResultDTO, ReportDTO, ReportsQuery } from './dto/reports.js';
|
|
6
|
+
import type { PushReportRequest, PushReportResultDTO, ReportDTO, ReportsQuery, SubmitResultDTO, SubmitResultRequest } from './dto/reports.js';
|
|
6
7
|
import type { CloseRequest, CloseResultDTO, PromoteRequest, RelaunchRootResultDTO, ReviveRequest, ReviveResultDTO, WaitRequest, YieldRequest } from './dto/lifecycle.js';
|
|
7
8
|
import type { SubscribeRequest, SubscriptionDTO } from './dto/subscriptions.js';
|
|
8
9
|
import type { FocusDTO, RegisterFocusRequest, SetFocusPaneRequest } from './dto/focus.js';
|
|
9
10
|
import { type ArmCronRequest, type CancelCronQuery, type CronDTO, type CronRunDTO, type CronScopeQuery, type CronShowDTO, type ListCronsQuery, type PokeCronsResult } from './dto/crons.js';
|
|
10
11
|
import type { NodeConfigPatch } from './dto/config.js';
|
|
11
12
|
import type { AttachEnsureRequest, AttachEnsureResultDTO } from './dto/attach.js';
|
|
12
|
-
import type { DeleteProfileRequest, DeleteProfileResultDTO, EnsureProfileRequest, ProfileDTO, UpdateProfileMetadataRequest } from './dto/profiles.js';
|
|
13
|
+
import type { DeleteProfileRequest, DeleteProfileResultDTO, EnsureProfileRequest, ProfileDTO, ProfilePauseResultDTO, UpdateProfileMetadataRequest } from './dto/profiles.js';
|
|
13
14
|
import type { FilePeekDTO } from './dto/files.js';
|
|
14
15
|
import type { MemoryDocRefDTO } from './dto/memory.js';
|
|
15
16
|
import type { ChatInventoryDTO, ProspectiveChatInventoryDTO, ProspectiveChatInventoryQuery } from './dto/chat-inventory.js';
|
|
@@ -21,7 +22,7 @@ import type { CancelInboxTicketRequest, CanceledTicketResultDTO, InboxListDTO, I
|
|
|
21
22
|
import type { CreateHumanRequestDTO, CreateHumanRequestRequest, HumanRequestDTO, HumanRequestIdDTO, ReplaceHumanRequestRequest, RespondHumanRequestRequest, SettleHumanRequestRequest } from './dto/human-requests.js';
|
|
22
23
|
import type { AttentionCountsDTO, AttentionDTO, DashboardDTO, DashboardQuery, HistoryGrepQuery, HistoryGrepResultDTO, HistoryReadQuery, HistoryStatsQuery, HistoryStatsResultDTO, HistoryReadResultDTO, HistorySearchQuery, HistorySearchResultDTO, PruneRequest, PruneResultDTO, RebuildIndexResultDTO, RosterDTO, SnapshotDTO } from './dto/canvas.js';
|
|
23
24
|
import type { AbandonWorktreeRequest, AbandonWorktreeResultDTO, CloseWorktreeResultDTO, QuarantinedWorktreeDTO } from './dto/worktree.js';
|
|
24
|
-
import type { BrokerExtensionStateDTO, BrokerGeneratedNameRequest, BrokerGeneratedNameResultDTO, BrokerInboxCursorDirective, BrokerInboxCursorRequest, BrokerModelCommitRequest, BrokerModelCommitResultDTO, BrokerPersonaAckRequest, BrokerPersonaAckResultDTO, BrokerSessionBoundRequest, BrokerSessionBoundResultDTO, BrokerSettleDirective, BrokerSettleRequest } from './dto/broker-ops.js';
|
|
25
|
+
import type { BrokerExtensionStateDTO, BrokerGeneratedNameRequest, BrokerGeneratedNameResultDTO, BrokerInboxCursorDirective, BrokerInboxCursorRequest, BrokerModelCommitRequest, BrokerModelCommitResultDTO, BrokerParkActivityResultDTO, BrokerParkCompleteRequest, BrokerPersonaAckRequest, BrokerPersonaAckResultDTO, BrokerSessionBoundRequest, BrokerSessionBoundResultDTO, BrokerSettleDirective, BrokerSettleRequest } from './dto/broker-ops.js';
|
|
25
26
|
export interface CrtrClientOptions {
|
|
26
27
|
/** Unix socket path (default local transport). Exactly one of socketPath|baseUrl. */
|
|
27
28
|
socketPath?: string;
|
|
@@ -95,6 +96,16 @@ export declare class CrtrClient {
|
|
|
95
96
|
* latest/canonical reports and pending-human counts in the same response. */
|
|
96
97
|
listNodes(q?: ListNodesQuery): Promise<NodeSummaryDTO[]>;
|
|
97
98
|
getNode(id: string): Promise<NodeDetailDTO>;
|
|
99
|
+
/** Read a node outcome, optionally awaiting it for at most 25 seconds. This
|
|
100
|
+
* is a GET so the client can safely replay it across daemon handover. */
|
|
101
|
+
getNodeOutcome(id: string, { waitSeconds }?: {
|
|
102
|
+
waitSeconds?: number;
|
|
103
|
+
}): Promise<NodeOutcomeResponseDTO>;
|
|
104
|
+
/** Register or replace an armed target for terminal-outcome delivery. */
|
|
105
|
+
registerOutcomeDelivery(id: string, req: RegisterOutcomeDeliveryRequest): Promise<OutcomeDeliveryDTO>;
|
|
106
|
+
getOutcomeDelivery(id: string): Promise<OutcomeDeliveryDTO>;
|
|
107
|
+
/** Disarm an unsettled outcome-delivery registration. */
|
|
108
|
+
disarmOutcomeDelivery(id: string): Promise<void>;
|
|
98
109
|
listBashJobs(id: string): Promise<BashJobStatusDTO[]>;
|
|
99
110
|
stopBashJob(id: string, jobId: string): Promise<BashJobStopResultDTO>;
|
|
100
111
|
sendMessage(id: string, req: SendMessageRequest): Promise<MessageResultDTO>;
|
|
@@ -103,11 +114,14 @@ export declare class CrtrClient {
|
|
|
103
114
|
* revives a dormant target. */
|
|
104
115
|
interruptNode(id: string): Promise<InterruptResultDTO>;
|
|
105
116
|
pushReport(id: string, req: PushReportRequest): Promise<PushReportResultDTO>;
|
|
117
|
+
submitResult(id: string, req: SubmitResultRequest): Promise<SubmitResultDTO>;
|
|
106
118
|
forkNode(id: string): Promise<NodeDetailDTO>;
|
|
107
119
|
reviveNode(id: string, req?: ReviveRequest): Promise<ReviveResultDTO>;
|
|
108
120
|
relaunchRoot(id: string): Promise<RelaunchRootResultDTO>;
|
|
109
121
|
bindBrokerSession(id: string, req: BrokerSessionBoundRequest): Promise<BrokerSessionBoundResultDTO>;
|
|
110
122
|
settleBroker(id: string, req: BrokerSettleRequest): Promise<BrokerSettleDirective>;
|
|
123
|
+
completeBrokerPark(id: string, req: BrokerParkCompleteRequest): Promise<BrokerSettleDirective>;
|
|
124
|
+
recordBrokerParkActivity(id: string): Promise<BrokerParkActivityResultDTO>;
|
|
111
125
|
advanceBrokerInboxCursor(id: string, req: BrokerInboxCursorRequest): Promise<BrokerInboxCursorDirective>;
|
|
112
126
|
commitBrokerModel(id: string, req: BrokerModelCommitRequest): Promise<BrokerModelCommitResultDTO>;
|
|
113
127
|
brokerExtensionState(id: string): Promise<BrokerExtensionStateDTO>;
|
|
@@ -187,6 +201,8 @@ export declare class CrtrClient {
|
|
|
187
201
|
ensureProfile(name: string, req?: EnsureProfileRequest): Promise<ProfileDTO>;
|
|
188
202
|
listProfiles(): Promise<ProfileDTO[]>;
|
|
189
203
|
getProfile(name: string): Promise<ProfileDTO>;
|
|
204
|
+
pauseProfile(name: string): Promise<ProfilePauseResultDTO>;
|
|
205
|
+
resumeProfile(name: string): Promise<ProfilePauseResultDTO>;
|
|
190
206
|
/** Merge and remove entries in a profile's metadata map. */
|
|
191
207
|
updateProfileMetadata(name: string, req: UpdateProfileMetadataRequest): Promise<ProfileDTO>;
|
|
192
208
|
/** Force-delete or detach one profile by exact id or unique name. */
|
package/dist/api/client.js
CHANGED
|
@@ -104,6 +104,25 @@ export class CrtrClient {
|
|
|
104
104
|
getNode(id) {
|
|
105
105
|
return this.request('GET', routes.node(this.nodePath(id)));
|
|
106
106
|
}
|
|
107
|
+
/** Read a node outcome, optionally awaiting it for at most 25 seconds. This
|
|
108
|
+
* is a GET so the client can safely replay it across daemon handover. */
|
|
109
|
+
getNodeOutcome(id, { waitSeconds } = {}) {
|
|
110
|
+
if (waitSeconds !== undefined && (!Number.isInteger(waitSeconds) || waitSeconds < 0 || waitSeconds > 25)) {
|
|
111
|
+
throw new RangeError('waitSeconds must be an integer between 0 and 25');
|
|
112
|
+
}
|
|
113
|
+
return this.request('GET', withQuery(routes.nodeOutcome(this.nodePath(id)), { wait: waitSeconds }));
|
|
114
|
+
}
|
|
115
|
+
/** Register or replace an armed target for terminal-outcome delivery. */
|
|
116
|
+
registerOutcomeDelivery(id, req) {
|
|
117
|
+
return this.request('PUT', routes.nodeOutcomeDelivery(this.nodePath(id)), req);
|
|
118
|
+
}
|
|
119
|
+
getOutcomeDelivery(id) {
|
|
120
|
+
return this.request('GET', routes.nodeOutcomeDelivery(this.nodePath(id)));
|
|
121
|
+
}
|
|
122
|
+
/** Disarm an unsettled outcome-delivery registration. */
|
|
123
|
+
async disarmOutcomeDelivery(id) {
|
|
124
|
+
await this.request('DELETE', routes.nodeOutcomeDelivery(this.nodePath(id)));
|
|
125
|
+
}
|
|
107
126
|
listBashJobs(id) {
|
|
108
127
|
return this.request('GET', routes.nodeJobs(this.nodePath(id)));
|
|
109
128
|
}
|
|
@@ -122,6 +141,9 @@ export class CrtrClient {
|
|
|
122
141
|
pushReport(id, req) {
|
|
123
142
|
return this.request('POST', routes.nodeReports(this.nodePath(id)), req);
|
|
124
143
|
}
|
|
144
|
+
submitResult(id, req) {
|
|
145
|
+
return this.request('POST', routes.nodeResult(this.nodePath(id)), req);
|
|
146
|
+
}
|
|
125
147
|
forkNode(id) {
|
|
126
148
|
return this.request('POST', routes.nodeFork(this.nodePath(id)), {});
|
|
127
149
|
}
|
|
@@ -137,6 +159,12 @@ export class CrtrClient {
|
|
|
137
159
|
settleBroker(id, req) {
|
|
138
160
|
return this.request('POST', routes.nodeBrokerSettle(this.nodePath(id)), req);
|
|
139
161
|
}
|
|
162
|
+
completeBrokerPark(id, req) {
|
|
163
|
+
return this.request('POST', routes.nodeBrokerParkComplete(this.nodePath(id)), req);
|
|
164
|
+
}
|
|
165
|
+
recordBrokerParkActivity(id) {
|
|
166
|
+
return this.request('POST', routes.nodeBrokerParkActivity(this.nodePath(id)), {});
|
|
167
|
+
}
|
|
140
168
|
advanceBrokerInboxCursor(id, req) {
|
|
141
169
|
return this.request('POST', routes.nodeBrokerInboxCursor(this.nodePath(id)), req);
|
|
142
170
|
}
|
|
@@ -319,6 +347,12 @@ export class CrtrClient {
|
|
|
319
347
|
getProfile(name) {
|
|
320
348
|
return this.request('GET', routes.profile(name));
|
|
321
349
|
}
|
|
350
|
+
pauseProfile(name) {
|
|
351
|
+
return this.request('POST', routes.profilePause(name), {});
|
|
352
|
+
}
|
|
353
|
+
resumeProfile(name) {
|
|
354
|
+
return this.request('POST', routes.profileResume(name), {});
|
|
355
|
+
}
|
|
322
356
|
/** Merge and remove entries in a profile's metadata map. */
|
|
323
357
|
updateProfileMetadata(name, req) {
|
|
324
358
|
return this.request('PATCH', routes.profileMetadata(name), req);
|
|
@@ -36,6 +36,17 @@ export type BrokerSettleDirective = {
|
|
|
36
36
|
} | {
|
|
37
37
|
action: 'shutdown';
|
|
38
38
|
};
|
|
39
|
+
/** A main-engine input has won broker admission while a parking summary may be
|
|
40
|
+
* in flight. crtrd records it against the process-local pending marker before
|
|
41
|
+
* Pi begins the input, making parking completion and input admission atomic. */
|
|
42
|
+
export interface BrokerParkActivityResultDTO {
|
|
43
|
+
activity: 'recorded' | 'none';
|
|
44
|
+
}
|
|
45
|
+
/** `POST /v1/nodes/{id}/broker/park-complete` body. The isolated parking turn
|
|
46
|
+
* has ended; crtrd alone decides whether its pending park still applies. */
|
|
47
|
+
export interface BrokerParkCompleteRequest {
|
|
48
|
+
outcome: 'completed' | 'failed';
|
|
49
|
+
}
|
|
39
50
|
/** `POST /v1/nodes/{id}/broker/inbox-cursor` body. The watcher advances this
|
|
40
51
|
* only after Pi has settled every handoff through the supplied physical entry.
|
|
41
52
|
* `brokerPid` binds the commit to the broker generation crtrd currently owns. */
|
package/dist/api/dto/broker.d.ts
CHANGED
|
@@ -46,11 +46,6 @@ export interface BrokerWelcomeFrame<M = unknown> {
|
|
|
46
46
|
type: 'welcome';
|
|
47
47
|
snapshot?: BrokerWelcomeSnapshot<M>;
|
|
48
48
|
}
|
|
49
|
-
/** The presentation classification of the run whose native events follow. */
|
|
50
|
-
export interface BrokerTurnVisibilityFrame {
|
|
51
|
-
type: 'turn_visibility';
|
|
52
|
-
visibility: 'visible' | 'internal';
|
|
53
|
-
}
|
|
54
49
|
/**
|
|
55
50
|
* The crtrd broker `node_named` control frame — the node's generated name at the
|
|
56
51
|
* instant crtrd committed it.
|
|
@@ -76,12 +71,12 @@ export interface BrokerNodeNamedFrame {
|
|
|
76
71
|
editorLabel: string;
|
|
77
72
|
}
|
|
78
73
|
/**
|
|
79
|
-
* The broker-control frames a relay consumer reads: `welcome`
|
|
80
|
-
* `
|
|
74
|
+
* The broker-control frames a relay consumer reads: `welcome`, `error`, and
|
|
75
|
+
* `node_named`. The broker interleaves others (display_*, ack, …)
|
|
81
76
|
* under non-colliding `type` discriminants; a relay mapper drops those through its
|
|
82
77
|
* `default` arm untyped, so they are not enumerated here.
|
|
83
78
|
*/
|
|
84
|
-
export type BrokerControlFrame<M = unknown> = BrokerWelcomeFrame<M> |
|
|
79
|
+
export type BrokerControlFrame<M = unknown> = BrokerWelcomeFrame<M> | BrokerErrorFrame | BrokerNodeNamedFrame;
|
|
85
80
|
/**
|
|
86
81
|
* What the crtrd broker attach delivers to a relay consumer: the live engine
|
|
87
82
|
* event stream (`E` — pi's `AgentSessionEvent`, relayed verbatim) unioned with the
|
package/dist/api/dto/common.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export type ModeDTO = 'base' | 'orchestrator';
|
|
|
20
20
|
/** Why a node last stopped (mirrors the runtime `ExitIntent` union). */
|
|
21
21
|
export type ExitIntentDTO = 'done' | 'refresh' | 'idle-release' | 'parked' | null;
|
|
22
22
|
/** Why a terminal node ended (mirrors the runtime `TerminalReason` union). */
|
|
23
|
-
export type TerminalReasonDTO = 'finalized' | 'finished' | 'parked' | 'closed' | 'retired' | 'crashed' | 'stranded';
|
|
23
|
+
export type TerminalReasonDTO = 'finalized' | 'finished' | 'parked' | 'closed' | 'retired' | 'crashed' | 'stranded' | 'boot_failed' | 'crash_looped' | 'launch_failed' | 'context_overflow' | 'deadline_exceeded' | 'provider_fatal' | 'declined';
|
|
24
24
|
/** Inbox urgency tier for a delivered message (mirrors feed/inbox `InboxTier`). */
|
|
25
25
|
export type InboxTierDTO = 'critical' | 'urgent' | 'normal' | 'deferred';
|
|
26
26
|
/** Whether a node id is a safe single filesystem path segment. Re-declared here
|
|
@@ -36,8 +36,8 @@ export interface SendMessageRequest {
|
|
|
36
36
|
/** One-shot runtime cards for this turn only — never persisted. Delivered in
|
|
37
37
|
* array order, after `situational_card` and ahead of the body. */
|
|
38
38
|
context_cards?: RuntimeCardRequest[];
|
|
39
|
-
/** Raw JSON-schema string
|
|
40
|
-
* (`--output-schema`)
|
|
39
|
+
/** Raw JSON-schema string installing a one-off output schema before delivery
|
|
40
|
+
* (`--output-schema`); the target answers with `crtr push result`. Immediate only. */
|
|
41
41
|
output_schema?: string;
|
|
42
42
|
/** `'interactive'`: deliver via the target's LIVE broker engine (prompt/steer
|
|
43
43
|
* on its one serialized frame loop — the same ordering a tmux viewer gets)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { IsoTime, NodeIdDTO, NodeStatusDTO, TerminalReasonDTO } from './common.js';
|
|
2
|
+
import type { DeclinedResultDTO } from './reports.js';
|
|
3
|
+
export type OutcomeKindDTO = 'result' | 'failure';
|
|
4
|
+
/** Bounded diagnostics recorded for a failed node outcome. */
|
|
5
|
+
export interface NodeOutcomeDetailV1 {
|
|
6
|
+
schema: 'crtr.node-outcome-detail/v1';
|
|
7
|
+
message?: string;
|
|
8
|
+
fault_kind?: 'rate-limit' | 'overloaded' | 'connection' | 'auth' | 'protocol' | 'context-overflow' | 'other' | 'wedged' | 'model-not-found';
|
|
9
|
+
error_class?: 'rate_limit' | 'overloaded' | 'connection' | 'auth' | 'protocol' | 'context_overflow' | 'wedged' | 'model_not_found' | 'unknown';
|
|
10
|
+
respawn_failures?: number;
|
|
11
|
+
deadline?: {
|
|
12
|
+
deadline_at: string;
|
|
13
|
+
elapsed_ms: number;
|
|
14
|
+
};
|
|
15
|
+
/** Present only for reason `declined`: what the node gave `crtr push result --decline`. */
|
|
16
|
+
declined?: DeclinedResultDTO;
|
|
17
|
+
truncated?: true;
|
|
18
|
+
}
|
|
19
|
+
interface NodeOutcomeBaseDTO {
|
|
20
|
+
node_id: NodeIdDTO;
|
|
21
|
+
revision: number;
|
|
22
|
+
settled_at: IsoTime;
|
|
23
|
+
/** Canonical final report basename; set for kind='result' and for a declined structured result (kind='failure', reason='declined'); else null. */
|
|
24
|
+
final_report: string | null;
|
|
25
|
+
/** Absolute path of the canonical final report; null whenever `final_report` is. */
|
|
26
|
+
final_report_path: string | null;
|
|
27
|
+
/** Parsed context/result.json when the node ran under --output-schema; else null. */
|
|
28
|
+
structured_result: unknown | null;
|
|
29
|
+
/** Bounded diagnostics; null for kind='result'. */
|
|
30
|
+
detail: NodeOutcomeDetailV1 | null;
|
|
31
|
+
}
|
|
32
|
+
/** A settled outcome. Narrowing on `kind` then `reason` makes a declined
|
|
33
|
+
* structured result (`failure`/`declined`) a case a consumer must handle:
|
|
34
|
+
* only that case carries `declined`; every other outcome has it null. */
|
|
35
|
+
export type NodeOutcomeDTO = (NodeOutcomeBaseDTO & {
|
|
36
|
+
kind: 'result';
|
|
37
|
+
reason: TerminalReasonDTO;
|
|
38
|
+
declined: null;
|
|
39
|
+
}) | (NodeOutcomeBaseDTO & {
|
|
40
|
+
kind: 'failure';
|
|
41
|
+
reason: 'declined';
|
|
42
|
+
declined: DeclinedResultDTO;
|
|
43
|
+
}) | (NodeOutcomeBaseDTO & {
|
|
44
|
+
kind: 'failure';
|
|
45
|
+
reason: Exclude<TerminalReasonDTO, 'declined'>;
|
|
46
|
+
declined: null;
|
|
47
|
+
});
|
|
48
|
+
export interface NodeOutcomeResponseDTO {
|
|
49
|
+
node_id: NodeIdDTO;
|
|
50
|
+
state: 'pending' | 'settled';
|
|
51
|
+
outcome: NodeOutcomeDTO | null;
|
|
52
|
+
node_status: NodeStatusDTO;
|
|
53
|
+
deadline_at: IsoTime | null;
|
|
54
|
+
}
|
|
55
|
+
export interface RegisterOutcomeDeliveryRequest {
|
|
56
|
+
/** A name declared in the humanActions map of scope config. */
|
|
57
|
+
action: string;
|
|
58
|
+
/** Opaque, frozen at registration, echoed verbatim in the document. */
|
|
59
|
+
payload?: unknown;
|
|
60
|
+
}
|
|
61
|
+
export type OutcomeDeliveryStateDTO = 'armed' | 'pending' | 'running' | 'accepted' | 'permanent_failed';
|
|
62
|
+
export interface OutcomeDeliveryDTO {
|
|
63
|
+
node_id: NodeIdDTO;
|
|
64
|
+
state: OutcomeDeliveryStateDTO;
|
|
65
|
+
action: string;
|
|
66
|
+
attempt: number;
|
|
67
|
+
/** ISO-8601 time of the next retry, or null before the row is scheduled. */
|
|
68
|
+
next_attempt_at: IsoTime | null;
|
|
69
|
+
accepted_at: IsoTime | null;
|
|
70
|
+
permanent_failed_at: IsoTime | null;
|
|
71
|
+
last_failure: {
|
|
72
|
+
kind: string;
|
|
73
|
+
exit_code?: number;
|
|
74
|
+
signal?: string;
|
|
75
|
+
message?: string;
|
|
76
|
+
} | null;
|
|
77
|
+
created_at: IsoTime;
|
|
78
|
+
updated_at: IsoTime;
|
|
79
|
+
}
|
|
80
|
+
export {};
|
package/dist/api/dto/nodes.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Cursor, ExitIntentDTO, IsoTime, LifecycleDTO, ModeDTO, NodeIdDTO, NodeStatusDTO, TerminalReasonDTO } from './common.js';
|
|
2
2
|
import type { ReportDTO } from './reports.js';
|
|
3
|
+
import type { NodeOutcomeDTO, RegisterOutcomeDeliveryRequest } from './node-outcomes.js';
|
|
3
4
|
/** `GET /v1/nodes/{id}/subject` — the node-config subject substrate gate
|
|
4
5
|
* predicates evaluate against. Mirrors `NodeConfigSubject`; this narrow
|
|
5
6
|
* endpoint exists so a CLI process (the `memory read` leaf) can gate-check
|
|
@@ -51,6 +52,10 @@ export interface CreateNodeRequest {
|
|
|
51
52
|
situational_context?: string;
|
|
52
53
|
no_kickoff?: boolean;
|
|
53
54
|
output_schema?: string;
|
|
55
|
+
/** Wall-clock bound from spawn, e.g. "45m", "2h", "1h30m". Expiry cancels the node and synthesizes a failure outcome with reason 'deadline_exceeded'. */
|
|
56
|
+
deadline?: string;
|
|
57
|
+
/** Arm outcome delivery atomically with node birth. */
|
|
58
|
+
outcome_delivery?: RegisterOutcomeDeliveryRequest;
|
|
54
59
|
/** Spawn AT this exact node id instead of a runtime-minted one — format-
|
|
55
60
|
* validated and duplicate-rejected server-side (`NodeIdConflictError` →
|
|
56
61
|
* HTTP 409 `node_id_exists`). See `crtr node new --node-id`. */
|
|
@@ -80,6 +85,8 @@ export interface NodeSummaryDTO {
|
|
|
80
85
|
cwd: string;
|
|
81
86
|
host_kind: 'tmux' | 'broker' | null;
|
|
82
87
|
profile_id: string | null;
|
|
88
|
+
/** Whether the node's profile is currently paused. */
|
|
89
|
+
profile_paused: boolean;
|
|
83
90
|
parent: NodeIdDTO | null;
|
|
84
91
|
created: IsoTime;
|
|
85
92
|
intent: ExitIntentDTO;
|
|
@@ -96,6 +103,8 @@ export interface NodeSummaryDTO {
|
|
|
96
103
|
/** Basename of the canonical final report, or null when this node has not finalized. */
|
|
97
104
|
final_report: string | null;
|
|
98
105
|
finalized_at: IsoTime | null;
|
|
106
|
+
deadline_at: IsoTime | null;
|
|
107
|
+
outcome: NodeOutcomeDTO | null;
|
|
99
108
|
/** Present only when requested with `include=activity`. */
|
|
100
109
|
activity?: NodeActivityDTO;
|
|
101
110
|
}
|
|
@@ -28,6 +28,11 @@ export interface UpdateProfileMetadataRequest {
|
|
|
28
28
|
set?: Record<string, string>;
|
|
29
29
|
unset?: string[];
|
|
30
30
|
}
|
|
31
|
+
/** The daemon-owned result of pausing or resuming one profile. */
|
|
32
|
+
export interface ProfilePauseResultDTO {
|
|
33
|
+
profile_id: string;
|
|
34
|
+
paused_at: string | null;
|
|
35
|
+
}
|
|
31
36
|
/** `DELETE /v1/profiles/{name}` body. Destructive deletion is never implicit. */
|
|
32
37
|
export interface DeleteProfileRequest {
|
|
33
38
|
force: boolean;
|
|
@@ -31,6 +31,51 @@ export interface PushReportResultDTO {
|
|
|
31
31
|
/** Present only alongside `worktree_auto_dropped`: the checkout path dropped. */
|
|
32
32
|
worktree_auto_dropped_path?: string;
|
|
33
33
|
}
|
|
34
|
+
/** Why a node declined a structured result. `reason` is one plain sentence
|
|
35
|
+
* for a reader; `code` is an opaque token the requester classifies on and
|
|
36
|
+
* validates itself — crouter only carries it; `retryable` is the node's
|
|
37
|
+
* claim that the same request could succeed later. */
|
|
38
|
+
export interface DeclinedResultDTO {
|
|
39
|
+
reason: string;
|
|
40
|
+
code: string;
|
|
41
|
+
retryable: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** `POST /v1/nodes/{id}/result` body ({id} = the submitting node). Either the
|
|
44
|
+
* structured result to validate against the node's pending output schema —
|
|
45
|
+
* `value` must be present; any JSON value (including null) is legal input to
|
|
46
|
+
* validation — or a decline: `decline` is the reason sentence, `code` the
|
|
47
|
+
* requester-classified token, `retryable` the node's retry claim. A decline
|
|
48
|
+
* records a `failure` outcome with reason `declined` carrying all three and
|
|
49
|
+
* clears the request without validating anything. */
|
|
50
|
+
export type SubmitResultRequest = {
|
|
51
|
+
value: unknown;
|
|
52
|
+
} | {
|
|
53
|
+
decline: string;
|
|
54
|
+
code: string;
|
|
55
|
+
retryable: boolean;
|
|
56
|
+
};
|
|
57
|
+
/** Result of a structured-result submission (`crtr push result`). Terminal
|
|
58
|
+
* mode reuses the final-push machinery, so `transitioned` and the worktree
|
|
59
|
+
* auto-drop fields carry the same meaning as on PushReportResultDTO. */
|
|
60
|
+
export interface SubmitResultDTO {
|
|
61
|
+
/** Which request this answered: `terminal` finished the node; `oneoff` left it working. */
|
|
62
|
+
mode: 'terminal' | 'oneoff';
|
|
63
|
+
/** Absolute path of the recorded artifact: context/result.json for an
|
|
64
|
+
* answered request, context/declined.json for a declined one. */
|
|
65
|
+
result_path: string;
|
|
66
|
+
/** Present only when the request was declined. */
|
|
67
|
+
declined?: DeclinedResultDTO;
|
|
68
|
+
/** Absolute path of the report pushed alongside the result. */
|
|
69
|
+
report_path: string;
|
|
70
|
+
/** Subscriber node ids that received an inbox entry. */
|
|
71
|
+
notified: NodeIdDTO[];
|
|
72
|
+
transitioned?: {
|
|
73
|
+
from: string;
|
|
74
|
+
to: string;
|
|
75
|
+
};
|
|
76
|
+
worktree_auto_dropped?: boolean;
|
|
77
|
+
worktree_auto_dropped_path?: string;
|
|
78
|
+
}
|
|
34
79
|
/** `GET /v1/nodes/{id}/reports` query filters. */
|
|
35
80
|
export interface ReportsQuery {
|
|
36
81
|
tier?: ReportTierDTO;
|
package/dist/api/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from '../shared/generated-context.js';
|
|
|
7
7
|
export * from './dto/common.js';
|
|
8
8
|
export * from './dto/health.js';
|
|
9
9
|
export * from './dto/nodes.js';
|
|
10
|
+
export * from './dto/node-outcomes.js';
|
|
10
11
|
export * from './dto/bash-jobs.js';
|
|
11
12
|
export * from './dto/messages.js';
|
|
12
13
|
export * from './dto/reports.js';
|
package/dist/api/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export * from '../shared/generated-context.js';
|
|
|
8
8
|
export * from './dto/common.js';
|
|
9
9
|
export * from './dto/health.js';
|
|
10
10
|
export * from './dto/nodes.js';
|
|
11
|
+
export * from './dto/node-outcomes.js';
|
|
11
12
|
export * from './dto/bash-jobs.js';
|
|
12
13
|
export * from './dto/messages.js';
|
|
13
14
|
export * from './dto/reports.js';
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/** How prominently a node surfaces in ancestor `-h` listings. Default 'normal'. */
|
|
2
|
+
export type ManifestTier = 'normal' | 'common' | 'important';
|
|
3
|
+
/** Root-entry prose for a top-level branch — what every agent reads before it
|
|
4
|
+
* has engaged the command at all. Required on a plugin's top-level branch. */
|
|
5
|
+
export interface ManifestRootEntry {
|
|
6
|
+
concept: string;
|
|
7
|
+
description: string;
|
|
8
|
+
whenToUse: string;
|
|
9
|
+
}
|
|
10
|
+
/** One declared output field of a leaf's result. */
|
|
11
|
+
export interface ManifestField {
|
|
12
|
+
name: string;
|
|
13
|
+
type: string;
|
|
14
|
+
required: boolean;
|
|
15
|
+
/** Inline semantic constraint — bounds, enum, token caps. */
|
|
16
|
+
constraint: string;
|
|
17
|
+
}
|
|
18
|
+
/** How a local file named by a `path` param is encoded into the request: 'text'
|
|
19
|
+
* as UTF-8, 'base64' as the base64 of its raw bytes. The path string itself
|
|
20
|
+
* never crosses the wire. */
|
|
21
|
+
export type ManifestFileEncoding = 'text' | 'base64';
|
|
22
|
+
export interface ManifestPositionalParam {
|
|
23
|
+
kind: 'positional';
|
|
24
|
+
name: string;
|
|
25
|
+
/** Display hint only; always parsed as string. */
|
|
26
|
+
type?: 'string' | 'path';
|
|
27
|
+
required: boolean;
|
|
28
|
+
constraint: string;
|
|
29
|
+
/** Collect every remaining positional token into an array, in argv order.
|
|
30
|
+
* Only an `in: 'body'` REST mapping can carry an array. */
|
|
31
|
+
repeatable?: boolean;
|
|
32
|
+
/** Valid only on a `path` param. */
|
|
33
|
+
encoding?: ManifestFileEncoding;
|
|
34
|
+
/** See {@link ManifestFlagParam.defaultFromEnv}. */
|
|
35
|
+
defaultFromEnv?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface ManifestFlagParam {
|
|
38
|
+
kind: 'flag';
|
|
39
|
+
name: string;
|
|
40
|
+
/** 'bool' flags take no value — presence is true. */
|
|
41
|
+
type: 'string' | 'int' | 'bool' | 'path' | 'enum';
|
|
42
|
+
/** Required, and only valid, when type is 'enum'. */
|
|
43
|
+
choices?: string[];
|
|
44
|
+
required: boolean;
|
|
45
|
+
constraint: string;
|
|
46
|
+
default?: string | number | boolean;
|
|
47
|
+
/** Repeat the flag to accumulate an array value. Valid only on string/int/enum,
|
|
48
|
+
* only with an `in: 'body'` REST mapping, and never alongside `default`. */
|
|
49
|
+
repeatable?: boolean;
|
|
50
|
+
/** Valid only on a `path` flag. */
|
|
51
|
+
encoding?: ManifestFileEncoding;
|
|
52
|
+
/** UPPER_SNAKE_CASE environment variable on the CALLING machine whose value
|
|
53
|
+
* fills this param when the caller omits it. An env-sourced value counts as
|
|
54
|
+
* SUPPLIED — it satisfies `required` and ships on the wire — unlike a static
|
|
55
|
+
* `default`, which does neither. Valid only on string/path params, never
|
|
56
|
+
* alongside `default` or `repeatable`. */
|
|
57
|
+
defaultFromEnv?: string;
|
|
58
|
+
}
|
|
59
|
+
/** Raw stdin content blob — piped text, not parsed as JSON. */
|
|
60
|
+
export interface ManifestStdinParam {
|
|
61
|
+
kind: 'stdin';
|
|
62
|
+
name: string;
|
|
63
|
+
required: boolean;
|
|
64
|
+
constraint: string;
|
|
65
|
+
}
|
|
66
|
+
/** `--context-file PATH`: reads and JSON-parses the file at PATH. */
|
|
67
|
+
export interface ManifestContextFileParam {
|
|
68
|
+
kind: 'context-file';
|
|
69
|
+
name: string;
|
|
70
|
+
required: boolean;
|
|
71
|
+
constraint: string;
|
|
72
|
+
/** Description of the expected JSON shape. */
|
|
73
|
+
shape?: string;
|
|
74
|
+
}
|
|
75
|
+
export type ManifestInputParam = ManifestPositionalParam | ManifestFlagParam | ManifestStdinParam | ManifestContextFileParam;
|
|
76
|
+
export type RestMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
77
|
+
export type RestParamPlacement = 'path' | 'query' | 'body' | 'header';
|
|
78
|
+
export interface RestParamMapping {
|
|
79
|
+
in: RestParamPlacement;
|
|
80
|
+
/** Rename for query/body; required for header; forbidden for path. */
|
|
81
|
+
as?: string;
|
|
82
|
+
}
|
|
83
|
+
export interface RestMapping {
|
|
84
|
+
method: RestMethod;
|
|
85
|
+
/** Absolute path template; each `{param}` placeholder names an `in: 'path'` param. */
|
|
86
|
+
path: string;
|
|
87
|
+
/** Default false. true means the response is an NDJSON stream relayed verbatim. */
|
|
88
|
+
streaming?: boolean;
|
|
89
|
+
/** Constant body fields merged into the request body verbatim (e.g. the `op`
|
|
90
|
+
* discriminator on a single-endpoint invoke surface) — never sourced from a
|
|
91
|
+
* declared param, and forbidden on GET. */
|
|
92
|
+
body?: Record<string, string | number | boolean>;
|
|
93
|
+
/** When set, every `in: 'body'` param value nests under this key instead of
|
|
94
|
+
* sitting top-level (`bodyRoot: 'args'` → `{ args: { name, url } }`);
|
|
95
|
+
* `body` constants stay top-level regardless. Forbidden on GET. */
|
|
96
|
+
bodyRoot?: string;
|
|
97
|
+
/** Keyed by declared param name; every declared param appears exactly once. */
|
|
98
|
+
params: Record<string, RestParamMapping>;
|
|
99
|
+
}
|
|
100
|
+
export interface ManifestTimeouts {
|
|
101
|
+
connectMs?: number;
|
|
102
|
+
requestMs?: number;
|
|
103
|
+
streamIdleMs?: number;
|
|
104
|
+
}
|
|
105
|
+
/** Exec transport only: forward every argv token after this branch to an
|
|
106
|
+
* external binary instead of parsing children. A passthrough branch is
|
|
107
|
+
* childless by construction; an HTTP manifest rejects it, because an HTTP
|
|
108
|
+
* transport must not name a local binary to execute. */
|
|
109
|
+
export interface ManifestPassthrough {
|
|
110
|
+
bin: string;
|
|
111
|
+
installHint: string;
|
|
112
|
+
}
|
|
113
|
+
export interface ManifestLeafBase {
|
|
114
|
+
kind: 'leaf';
|
|
115
|
+
name: string;
|
|
116
|
+
description: string;
|
|
117
|
+
whenToUse: string;
|
|
118
|
+
tier?: ManifestTier;
|
|
119
|
+
summary: string;
|
|
120
|
+
params: ManifestInputParam[];
|
|
121
|
+
output: ManifestField[];
|
|
122
|
+
/** Non-empty; `["None. Read-only."]` for a read-only leaf. Read-only, so a
|
|
123
|
+
* server assembling a manifest may hand over a frozen or `as const` list. */
|
|
124
|
+
effects: readonly string[];
|
|
125
|
+
}
|
|
126
|
+
/** Exec-transport leaf. */
|
|
127
|
+
export interface ManifestExecLeaf extends ManifestLeafBase {
|
|
128
|
+
outputKind: 'object';
|
|
129
|
+
}
|
|
130
|
+
/** HTTP-transport leaf; `outputKind` derives from `rest.streaming`. */
|
|
131
|
+
export interface ManifestHttpLeaf extends ManifestLeafBase {
|
|
132
|
+
rest: RestMapping;
|
|
133
|
+
}
|
|
134
|
+
export type ManifestLeaf = ManifestExecLeaf | ManifestHttpLeaf;
|
|
135
|
+
export interface ManifestBranch<L extends ManifestLeafBase = ManifestLeaf> {
|
|
136
|
+
kind: 'branch';
|
|
137
|
+
name: string;
|
|
138
|
+
description: string;
|
|
139
|
+
whenToUse: string;
|
|
140
|
+
tier?: ManifestTier;
|
|
141
|
+
/** Required on a top-level branch, forbidden on a nested one. */
|
|
142
|
+
rootEntry?: ManifestRootEntry;
|
|
143
|
+
/** Allows the nearest repository fragment to contribute children below this
|
|
144
|
+
* top-level branch. */
|
|
145
|
+
extensible?: true;
|
|
146
|
+
summary: string;
|
|
147
|
+
model?: string;
|
|
148
|
+
/** Exec dialect only, and the type says so rather than leaving it to the
|
|
149
|
+
* runtime validator: an HTTP-transport manifest naming a local binary to run
|
|
150
|
+
* is the one shape a served manifest must never be able to express. `never`
|
|
151
|
+
* on the HTTP leaf dialect makes `passthrough: {...}` a compile error in a
|
|
152
|
+
* `ManifestBranch<ManifestHttpLeaf>`, and the conditional distributes over
|
|
153
|
+
* the default union so a plain `ManifestBranch` still accepts it. */
|
|
154
|
+
passthrough?: L extends ManifestExecLeaf ? ManifestPassthrough : never;
|
|
155
|
+
children: ManifestNode<L>[];
|
|
156
|
+
}
|
|
157
|
+
/** A branch or a leaf. The parameter fixes which leaf dialect the whole subtree
|
|
158
|
+
* may use, so an HTTP manifest cannot smuggle an exec leaf into a child slot. */
|
|
159
|
+
export type ManifestNode<L extends ManifestLeafBase = ManifestLeaf> = ManifestBranch<L> | L;
|
|
160
|
+
/** One mount point in the manifest's self-contained forest. */
|
|
161
|
+
export interface ManifestMount<L extends ManifestLeafBase = ManifestLeaf> {
|
|
162
|
+
/** `[]` mounts `node` as a new top-level command; a non-empty path names a
|
|
163
|
+
* branch this SAME manifest already contributes. */
|
|
164
|
+
parent: string[];
|
|
165
|
+
node: ManifestNode<L>;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* A whole `commands.json` for an HTTP-transport plugin whose endpoint and auth
|
|
169
|
+
* live in the bundle's `bundle.json` rather than the manifest.
|
|
170
|
+
*/
|
|
171
|
+
export interface HttpPluginCommandManifest {
|
|
172
|
+
schemaVersion: 1;
|
|
173
|
+
/** Overrides the registration endpoint as the base for every leaf's REST path. */
|
|
174
|
+
baseUrl?: string;
|
|
175
|
+
timeouts?: ManifestTimeouts;
|
|
176
|
+
mounts: ManifestMount<ManifestHttpLeaf>[];
|
|
177
|
+
/** Core command path (space-joined, e.g. "cron add") → product addendum
|
|
178
|
+
* appended to that command's help, rendered by crtr as an attributed
|
|
179
|
+
* `<plugin-help plugin="...">` block after the core body. Append-only by
|
|
180
|
+
* contract: an addendum adds product meaning beneath substrate help, never
|
|
181
|
+
* replaces it. A key naming no core command path fails validation at guest
|
|
182
|
+
* install. */
|
|
183
|
+
helpAddenda?: Record<string, string>;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The one field a plugin's HTTP backend adds to an error envelope to say the
|
|
187
|
+
* client parsed this call from an out-of-date description of its commands.
|
|
188
|
+
*
|
|
189
|
+
* crtr acts on it by refetching that plugin's bundle and re-running the
|
|
190
|
+
* caller's ORIGINAL argv against the refreshed command tree, exactly once. Two
|
|
191
|
+
* preconditions follow from that, and a server that cannot meet both must not
|
|
192
|
+
* set the field:
|
|
193
|
+
*
|
|
194
|
+
* 1. The manifest the server serves at its bundle endpoint must already
|
|
195
|
+
* describe the operation it is complaining about. A refetch that hands back
|
|
196
|
+
* the same description turns the retry into a second identical failure.
|
|
197
|
+
* 2. The original call must be safe to send again. crtr replays the argv, not
|
|
198
|
+
* the request, but a leaf that already committed a side effect before the
|
|
199
|
+
* backend rejected the op would commit it twice.
|
|
200
|
+
*
|
|
201
|
+
* Declared here, in the format both sides compile against, so the field name
|
|
202
|
+
* has one owner: rename it and every reader and writer fails to build. A type
|
|
203
|
+
* rather than a value — a const would force a CJS consumer to `require()` an
|
|
204
|
+
* ESM module.
|
|
205
|
+
*/
|
|
206
|
+
export interface ManifestStaleEnvelope {
|
|
207
|
+
manifest_stale?: true;
|
|
208
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// The command-plugin manifest wire format — the exact JSON shape crtr's manifest
|
|
2
|
+
// validator accepts in a plugin bundle's `commands.json`.
|
|
3
|
+
//
|
|
4
|
+
// This is the canonical, cross-repo declaration of that format. It is published
|
|
5
|
+
// as `@north-light/crouter-api/plugin-manifest` so a server that SERVES a plugin
|
|
6
|
+
// bundle (Northlight Core serves the `northlight` plugin over an authenticated
|
|
7
|
+
// endpoint) compiles its manifest against the same types crtr validates it with,
|
|
8
|
+
// instead of hand-mirroring them and discovering drift at guest install time.
|
|
9
|
+
//
|
|
10
|
+
// Types only. This file imports nothing — not even Node built-ins — so consuming
|
|
11
|
+
// it costs a dependent nothing at runtime.
|
|
12
|
+
//
|
|
13
|
+
// Relationship to `src/core/help.ts`: these param and output types are the
|
|
14
|
+
// JSON-expressible SUBSET of that module's `InputParam` and `Field`. A validated
|
|
15
|
+
// manifest node's params flow straight into `defineLeaf`'s help descriptor
|
|
16
|
+
// (`src/core/command-plugins/compose.ts`), so that assignment is what keeps the
|
|
17
|
+
// two in step — widen a type here beyond what `help.ts` accepts and the build
|
|
18
|
+
// fails at that site. Fields that cannot survive a JSON round trip (a flag's
|
|
19
|
+
// `focusedHelp`, whose `dynamicState` is a function) are deliberately absent.
|
|
20
|
+
//
|
|
21
|
+
// Validators for this format live in `src/core/command-manifests/`, which imports
|
|
22
|
+
// these types rather than redeclaring them.
|
|
23
|
+
export {};
|
package/dist/api/routes.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export declare const routes: {
|
|
|
8
8
|
readonly nodes: () => string;
|
|
9
9
|
readonly reviveAll: () => string;
|
|
10
10
|
readonly node: (id: string) => string;
|
|
11
|
+
readonly nodeOutcome: (id: string) => string;
|
|
12
|
+
readonly nodeOutcomeDelivery: (id: string) => string;
|
|
11
13
|
readonly nodeSnapshot: (id: string) => string;
|
|
12
14
|
readonly nodeSubject: (id: string) => string;
|
|
13
15
|
readonly nodeSession: (id: string) => string;
|
|
@@ -17,6 +19,7 @@ export declare const routes: {
|
|
|
17
19
|
readonly nodeContext: (id: string) => string;
|
|
18
20
|
readonly nodeArtifacts: (id: string) => string;
|
|
19
21
|
readonly nodeReports: (id: string) => string;
|
|
22
|
+
readonly nodeResult: (id: string) => string;
|
|
20
23
|
readonly nodeJobs: (id: string) => string;
|
|
21
24
|
readonly nodeJob: (id: string, jobId: string) => string;
|
|
22
25
|
readonly nodeMessages: (id: string) => string;
|
|
@@ -26,6 +29,8 @@ export declare const routes: {
|
|
|
26
29
|
readonly nodeRelaunchRoot: (id: string) => string;
|
|
27
30
|
readonly nodeBrokerSessionBound: (id: string) => string;
|
|
28
31
|
readonly nodeBrokerSettle: (id: string) => string;
|
|
32
|
+
readonly nodeBrokerParkComplete: (id: string) => string;
|
|
33
|
+
readonly nodeBrokerParkActivity: (id: string) => string;
|
|
29
34
|
readonly nodeBrokerInboxCursor: (id: string) => string;
|
|
30
35
|
readonly nodeBrokerModel: (id: string) => string;
|
|
31
36
|
readonly nodeBrokerExtensionState: (id: string) => string;
|
|
@@ -96,6 +101,8 @@ export declare const routes: {
|
|
|
96
101
|
readonly humanRequestCancel: (requestId: string) => string;
|
|
97
102
|
readonly profiles: () => string;
|
|
98
103
|
readonly profile: (name: string) => string;
|
|
104
|
+
readonly profilePause: (name: string) => string;
|
|
105
|
+
readonly profileResume: (name: string) => string;
|
|
99
106
|
readonly profileMetadata: (name: string) => string;
|
|
100
107
|
readonly modelAuths: () => string;
|
|
101
108
|
readonly modelAuth: (provider: string) => string;
|
package/dist/api/routes.js
CHANGED
|
@@ -23,6 +23,8 @@ export const routes = {
|
|
|
23
23
|
nodes: () => `${V}/nodes`,
|
|
24
24
|
reviveAll: () => `${V}/nodes/revive-all`,
|
|
25
25
|
node: (id) => `${V}/nodes/${id}`,
|
|
26
|
+
nodeOutcome: (id) => `${V}/nodes/${id}/outcome`,
|
|
27
|
+
nodeOutcomeDelivery: (id) => `${V}/nodes/${id}/outcome-delivery`,
|
|
26
28
|
// Node reads
|
|
27
29
|
nodeSnapshot: (id) => `${V}/nodes/${id}/snapshot`,
|
|
28
30
|
nodeSubject: (id) => `${V}/nodes/${id}/subject`,
|
|
@@ -33,6 +35,7 @@ export const routes = {
|
|
|
33
35
|
nodeContext: (id) => `${V}/nodes/${id}/context`,
|
|
34
36
|
nodeArtifacts: (id) => `${V}/nodes/${id}/artifacts`,
|
|
35
37
|
nodeReports: (id) => `${V}/nodes/${id}/reports`,
|
|
38
|
+
nodeResult: (id) => `${V}/nodes/${id}/result`,
|
|
36
39
|
nodeJobs: (id) => `${V}/nodes/${id}/jobs`,
|
|
37
40
|
nodeJob: (id, jobId) => `${V}/nodes/${id}/jobs/${jobId}`,
|
|
38
41
|
// Node messages / feed
|
|
@@ -44,6 +47,8 @@ export const routes = {
|
|
|
44
47
|
nodeRelaunchRoot: (id) => `${V}/nodes/${id}/relaunch-root`,
|
|
45
48
|
nodeBrokerSessionBound: (id) => `${V}/nodes/${id}/broker/session-bound`,
|
|
46
49
|
nodeBrokerSettle: (id) => `${V}/nodes/${id}/broker/settle`,
|
|
50
|
+
nodeBrokerParkComplete: (id) => `${V}/nodes/${id}/broker/park-complete`,
|
|
51
|
+
nodeBrokerParkActivity: (id) => `${V}/nodes/${id}/broker/park-activity`,
|
|
47
52
|
nodeBrokerInboxCursor: (id) => `${V}/nodes/${id}/broker/inbox-cursor`,
|
|
48
53
|
nodeBrokerModel: (id) => `${V}/nodes/${id}/broker/model`,
|
|
49
54
|
nodeBrokerExtensionState: (id) => `${V}/nodes/${id}/broker/extension-state`,
|
|
@@ -127,6 +132,8 @@ export const routes = {
|
|
|
127
132
|
// Profiles (deletion is daemon-owned because it crosses canvas state)
|
|
128
133
|
profiles: () => `${V}/profiles`,
|
|
129
134
|
profile: (name) => `${V}/profiles/${name}`,
|
|
135
|
+
profilePause: (name) => `${V}/profiles/${name}/pause`,
|
|
136
|
+
profileResume: (name) => `${V}/profiles/${name}/resume`,
|
|
130
137
|
profileMetadata: (name) => `${V}/profiles/${name}/metadata`,
|
|
131
138
|
// Model auth
|
|
132
139
|
modelAuths: () => `${V}/model-auth`,
|
package/dist/shared/env.d.ts
CHANGED
|
@@ -82,3 +82,6 @@ export declare function envUnattendedParkMs(): number | undefined;
|
|
|
82
82
|
/** Test-only park-summary grace-period override
|
|
83
83
|
* (`CRTR_TEST_PARK_SUMMARY_GRACE_MS`); no production default. */
|
|
84
84
|
export declare function envTestParkSummaryGraceMs(): number | undefined;
|
|
85
|
+
/** The bounded lifetime shared by the daemon's pending-park sweep and its
|
|
86
|
+
* in-broker isolated turn. */
|
|
87
|
+
export declare function parkSummaryGraceMs(): number;
|
package/dist/shared/env.js
CHANGED
|
@@ -195,3 +195,9 @@ export function envUnattendedParkMs() {
|
|
|
195
195
|
export function envTestParkSummaryGraceMs() {
|
|
196
196
|
return parsePositiveMsNoDefault(process.env['CRTR_TEST_PARK_SUMMARY_GRACE_MS']);
|
|
197
197
|
}
|
|
198
|
+
const DEFAULT_PARK_SUMMARY_GRACE_MS = 5 * 60_000;
|
|
199
|
+
/** The bounded lifetime shared by the daemon's pending-park sweep and its
|
|
200
|
+
* in-broker isolated turn. */
|
|
201
|
+
export function parkSummaryGraceMs() {
|
|
202
|
+
return envTestParkSummaryGraceMs() ?? DEFAULT_PARK_SUMMARY_GRACE_MS;
|
|
203
|
+
}
|
|
@@ -8,15 +8,9 @@ export declare const CONTEXT_NUDGE_CUSTOM_TYPE = "crtr-context-nudge";
|
|
|
8
8
|
export declare const REVIEW_BOUNDARY_CUSTOM_TYPE = "crtr-review-boundary";
|
|
9
9
|
/** Generic completion mandate issued by the terminal-node stop guard. */
|
|
10
10
|
export declare const STALL_REPROMPT: string;
|
|
11
|
-
/** The daemon's parking mandate
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* one update for subscribers and history, then a brief completion reply.
|
|
15
|
-
*
|
|
16
|
-
* The durable inheritance shares a CONTRACT with `node yield`'s pre-invocation
|
|
17
|
-
* guide (roadmap current, short and shrinking; context dir for in-progress
|
|
18
|
-
* material; memory only for gated permanent lessons) but not a string: yield is
|
|
19
|
-
* read by an agent choosing to refresh, this by an agent being told to conclude. */
|
|
11
|
+
/** The daemon's parking mandate for an isolated turn. It leaves current truth,
|
|
12
|
+
* supporting material when needed, lasting lessons, and one deferred update;
|
|
13
|
+
* the main conversation remains untouched and resumes without a fresh cycle. */
|
|
20
14
|
export declare const PARK_SUMMARY_PROMPT: string;
|
|
21
15
|
/** Static recovery prompts shared by the broker producer and display classifier. */
|
|
22
16
|
export declare const AUTH_FAULT_RECOVERY_BODY = "Provider credentials were just updated (a new login landed). Your previous turn stopped on a provider authentication failure. Continue from where you left off and retry the work that failed.";
|
|
@@ -13,22 +13,14 @@ export const REVIEW_BOUNDARY_CUSTOM_TYPE = 'crtr-review-boundary';
|
|
|
13
13
|
/** Generic completion mandate issued by the terminal-node stop guard. */
|
|
14
14
|
export const STALL_REPROMPT = "You've stopped but you're not waiting on anyone and haven't finished. " +
|
|
15
15
|
"Pipe the result to `crtr push final` through a single-quoted heredoc if the work is done, or use `crtr human send` if you are blocked or need the user.";
|
|
16
|
-
/** The daemon's parking mandate
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
* The durable inheritance shares a CONTRACT with `node yield`'s pre-invocation
|
|
22
|
-
* guide (roadmap current, short and shrinking; context dir for in-progress
|
|
23
|
-
* material; memory only for gated permanent lessons) but not a string: yield is
|
|
24
|
-
* read by an agent choosing to refresh, this by an agent being told to conclude. */
|
|
25
|
-
export const PARK_SUMMARY_PROMPT = 'This conversation has been idle with nothing left to wake it, so it is being concluded. This is your last turn. Use it to leave a trustworthy inheritance, not to restart or broaden the work. Do these six things now, then stop.\n\n'
|
|
16
|
+
/** The daemon's parking mandate for an isolated turn. It leaves current truth,
|
|
17
|
+
* supporting material when needed, lasting lessons, and one deferred update;
|
|
18
|
+
* the main conversation remains untouched and resumes without a fresh cycle. */
|
|
19
|
+
export const PARK_SUMMARY_PROMPT = 'This conversation has been idle with nothing left to wake it, so it is being concluded. This is your last turn. Use it to leave a trustworthy inheritance, not to restart or broaden the work. Do these four things now, then stop.\n\n'
|
|
26
20
|
+ '1. Establish current truth. Check only state that may have changed outside the transcript and matters to resuming—such as the working tree, a remote run, or an external decision. Do not start new work; perform only a quick check needed to avoid recording an unverified claim. If no mandate or work ever began, record that plainly in the inheritance and keep every artifact minimal.\n\n'
|
|
27
|
-
+ '2.
|
|
28
|
-
+ '3.
|
|
29
|
-
+ '4.
|
|
30
|
-
+ '5. Push exactly one regular update with `crtr push update --tier deferred`, never `crtr push final`. Write for someone who has not seen this conversation: name the work in plain terms, say where it stands, and say what remains or is blocked. Put the current outcome in the first line; include only needed decisions and recovery handles. This concludes the conversation, not the mandate.\n\n'
|
|
31
|
-
+ '6. When finished, reply with exactly `done`.';
|
|
21
|
+
+ '2. Put supporting material in your context directory only when it is needed to keep the inheritance concise. Rewrite existing living documents rather than leave superseded versions. Task state, identifiers, and recovery detail belong here, not in memory.\n\n'
|
|
22
|
+
+ '3. Use memory only for a non-obvious, reusable lesson that should survive this task and is not already recorded. Read `crtr memory write -h`, find before writing, and choose the narrowest scope that will reach the next agent who needs it. Do not put a conversation recap, task status, recovery handles, or facts already captured in code or docs into memory.\n\n'
|
|
23
|
+
+ '4. Push exactly one regular update with `crtr push update --tier deferred`, never `crtr push final`. Write for someone who has not seen this conversation: name the work in plain terms, say where it stands, and say what remains or is blocked. Put the current outcome in the first line; include only needed decisions and recovery handles, then stop.';
|
|
32
24
|
/** Static recovery prompts shared by the broker producer and display classifier. */
|
|
33
25
|
export const AUTH_FAULT_RECOVERY_BODY = 'Provider credentials were just updated (a new login landed). Your previous turn stopped on a provider authentication failure. Continue from where you left off and retry the work that failed.';
|
|
34
26
|
export const CONNECTION_FAULT_RECOVERY_BODY = 'The network connection is back online. Your previous turn stopped on a connection error (the network was down). Continue from where you left off and retry the work that failed.';
|
|
@@ -37,7 +29,7 @@ const REVIEW_APPROVAL_OPEN = '<crtr-review-approval>';
|
|
|
37
29
|
const REVIEW_APPROVAL_CLOSE = '</crtr-review-approval>';
|
|
38
30
|
const MODEL_FALLBACK_RECOVERY_OPEN = '<model-fallback-recovery>';
|
|
39
31
|
const MODEL_FALLBACK_RECOVERY_CLOSE = '</model-fallback-recovery>';
|
|
40
|
-
const STRUCTURED_OUTPUT_REPROMPT_PREFIX = 'You must
|
|
32
|
+
const STRUCTURED_OUTPUT_REPROMPT_PREFIX = 'You must submit a result matching the required schema with `crtr push result` before you can stop, or decline it with `crtr push result --decline "<reason>" --code <token>` when the schema cannot be honestly satisfied. You cannot finish or go dormant any other way while this request is pending.\n\nRequired schema:\n\n```json\n';
|
|
41
33
|
const STRUCTURED_OUTPUT_REPROMPT_SUFFIX = '\n```';
|
|
42
34
|
/** Format the stop guard's dynamic structured-output mandate. */
|
|
43
35
|
export function formatStructuredOutputReprompt(schema) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/crouter-api",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "Typed crtrd /v1 API contract — DTOs, route builders, the error contract, and the
|
|
3
|
+
"version": "0.3.283",
|
|
4
|
+
"description": "Typed crtrd /v1 API contract — DTOs, route builders, the error contract, the CrtrClient, and the command-plugin manifest format. Zero runtime dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/api/index.js",
|
|
7
7
|
"types": "./dist/api/index.d.ts",
|
|
@@ -12,6 +12,12 @@
|
|
|
12
12
|
"require": "./dist/api/index.js",
|
|
13
13
|
"default": "./dist/api/index.js"
|
|
14
14
|
},
|
|
15
|
+
"./plugin-manifest": {
|
|
16
|
+
"types": "./dist/api/plugin-manifest-schema.d.ts",
|
|
17
|
+
"import": "./dist/api/plugin-manifest-schema.js",
|
|
18
|
+
"require": "./dist/api/plugin-manifest-schema.js",
|
|
19
|
+
"default": "./dist/api/plugin-manifest-schema.js"
|
|
20
|
+
},
|
|
15
21
|
"./cards": {
|
|
16
22
|
"types": "./dist/shared/generated-context.d.ts",
|
|
17
23
|
"import": "./dist/shared/generated-context.js",
|