@north-light/api 0.3.534 → 0.3.536

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.
@@ -65,6 +65,8 @@ export interface CrtrClientOptions {
65
65
  * started has terminally failed (it exited before becoming ready), so the
66
66
  * wait ends immediately with that text instead of polling out the window. */
67
67
  coldStartFailure?: () => string | undefined;
68
+ /** A local relay that was deliberately released ends an availability wait. */
69
+ availabilityFailure?: () => Error | undefined;
68
70
  /** Strict wall-clock window (ms) for local API availability after a cold
69
71
  * socket or interrupted response. Each probe is capped to the remaining
70
72
  * budget. Defaults to `HEALTHZ_POLL_WINDOW_MS`. */
@@ -113,6 +115,7 @@ export declare class CrtrClient {
113
115
  private readonly onColdSocket?;
114
116
  private readonly coldStartDiagnostic?;
115
117
  private readonly coldStartFailure?;
118
+ private readonly availabilityFailure?;
116
119
  private readonly coldStartPollWindowMs;
117
120
  /** Set when the last availability wait ended on a daemon startup failure, whose message already says why. */
118
121
  private startupFailureReported;
@@ -61,6 +61,7 @@ export class CrtrClient {
61
61
  onColdSocket;
62
62
  coldStartDiagnostic;
63
63
  coldStartFailure;
64
+ availabilityFailure;
64
65
  coldStartPollWindowMs;
65
66
  /** Set when the last availability wait ended on a daemon startup failure, whose message already says why. */
66
67
  startupFailureReported = false;
@@ -82,6 +83,8 @@ export class CrtrClient {
82
83
  this.coldStartDiagnostic = opts.coldStartDiagnostic;
83
84
  if (opts.coldStartFailure !== undefined)
84
85
  this.coldStartFailure = opts.coldStartFailure;
86
+ if (opts.availabilityFailure !== undefined)
87
+ this.availabilityFailure = opts.availabilityFailure;
85
88
  this.coldStartPollWindowMs = opts.coldStartPollWindowMs ?? HEALTHZ_POLL_WINDOW_MS;
86
89
  }
87
90
  // Health / status
@@ -898,6 +901,11 @@ export class CrtrClient {
898
901
  response = await this.transport(method, path, body, opts);
899
902
  }
900
903
  catch (err) {
904
+ if (this.isColdSocketError(err) || this.isInterruptedSocketError(err)) {
905
+ const released = this.availabilityFailure?.();
906
+ if (released !== undefined)
907
+ throw released;
908
+ }
901
909
  if (this.isColdSocketError(err)) {
902
910
  try {
903
911
  await this.handleColdSocket(err, opts.deadlineAt);
@@ -1143,12 +1151,18 @@ export class CrtrClient {
1143
1151
  if (remainingBudgetMs !== undefined && remainingBudgetMs <= 0)
1144
1152
  throw budgetExhausted(deadlineAt);
1145
1153
  let startupFailure;
1154
+ let releaseFailure;
1146
1155
  try {
1147
1156
  await waitForDaemonAvailability({
1148
1157
  windowMs: Math.min(this.coldStartPollWindowMs, remainingBudgetMs ?? this.coldStartPollWindowMs),
1149
1158
  initialError,
1150
- retry: (error) => error !== startupFailure,
1159
+ retry: (error) => error !== startupFailure && error !== releaseFailure,
1151
1160
  probe: async (timeoutMs) => {
1161
+ const unavailable = this.availabilityFailure?.();
1162
+ if (unavailable !== undefined) {
1163
+ releaseFailure = unavailable;
1164
+ throw unavailable;
1165
+ }
1152
1166
  const failure = this.coldStartFailure?.();
1153
1167
  if (failure !== undefined) {
1154
1168
  startupFailure = new ApiError(503, 'daemon_unavailable', `crtrd failed to start: ${failure}`);
@@ -1,5 +1,5 @@
1
1
  /** The contract level this build serves and requires. Written by `scripts/contract.mjs release`; never edit by hand. */
2
- export declare const CONTRACT_LEVEL = "1.26";
2
+ export declare const CONTRACT_LEVEL = "1.27";
3
3
  /** Request header naming the one contract level the caller needs, e.g. `1.3`. Optional: absent means no check. */
4
4
  export declare const REQUIRED_CONTRACT_HEADER = "Crouter-Required-Contract";
5
5
  /** Response header listing the contract levels the server serves, comma-separated, one per major, e.g. `1.3`. */
@@ -12,7 +12,7 @@
12
12
  //
13
13
  // PURITY (spec §3.1): Node built-ins + `src/api/*` only.
14
14
  /** The contract level this build serves and requires. Written by `scripts/contract.mjs release`; never edit by hand. */
15
- export const CONTRACT_LEVEL = '1.26';
15
+ export const CONTRACT_LEVEL = '1.27';
16
16
  /** Request header naming the one contract level the caller needs, e.g. `1.3`. Optional: absent means no check. */
17
17
  export const REQUIRED_CONTRACT_HEADER = 'Crouter-Required-Contract';
18
18
  /** Response header listing the contract levels the server serves, comma-separated, one per major, e.g. `1.3`. */
@@ -273,6 +273,8 @@ export interface ListNodesQuery {
273
273
  top_level?: boolean;
274
274
  /** Restrict to the subtree under this node. */
275
275
  under?: NodeIdDTO;
276
+ /** With `under`: also return the node itself and the human ask nodes below it, which the plain subtree leaves out. */
277
+ under_inclusive?: boolean;
276
278
  /** Only nodes with a dangling/hanging manager edge. */
277
279
  hanging?: boolean;
278
280
  /** Opt into richer per-node payloads that require filesystem reads. */
@@ -85,10 +85,11 @@ export interface BrokerProviderRetryResultDTO {
85
85
  }
86
86
  export interface BrokerProviderRetryRequest {
87
87
  expected_execution_id: string;
88
- op: 'record-pending' | 'admit' | 'reopen' | 'invalidate' | 'clear';
88
+ op: 'record-pending' | 'admit' | 'reopen' | 'invalidate' | 'clear' | 'settle-rejected';
89
89
  session_id: string;
90
90
  fault_id?: string;
91
91
  retry?: FaultRetry;
92
+ reopen?: boolean;
92
93
  input?: BrokerFaultInputDTO;
93
94
  }
94
95
  export interface RecoveryStateDTO {
@@ -39,6 +39,11 @@ export declare function isolatedNodeHome(nodeId: string, grantee: string): strin
39
39
  /** The HOME a node's processes get: its own home in an isolated run, else the app's. */
40
40
  export declare function nodeHome(nodeId: string, grantee: string, isolated: boolean): string;
41
41
  export declare function nodeRunDir(nodeId: string): string;
42
+ /** File the daemon leaves in a node's run folder when its broker was released on purpose (idle-release, park,
43
+ * finish, cancel) and removes when the broker is launched again. A background job's `crtr` call that finds its
44
+ * relay socket gone reads it, without asking the daemon, to tell a release from a restart. */
45
+ export declare const BROKER_RELEASED_MARKER = "broker-released";
46
+ export declare const BROKER_RELAY_GENERATION = "cli-relay-generation";
42
47
  /** The run's scope allow-list as a JSON array, beside `broker-launch.json`. */
43
48
  export declare function scopesFilePath(nodeId: string): string;
44
49
  export declare function contextDir(nodeId: string, grantee?: string): string;
@@ -96,6 +96,11 @@ export function nodeRunDir(nodeId) {
96
96
  assertSafeNodeId(nodeId);
97
97
  return process.platform === 'linux' ? join(socketDir(), 'nodes', nodeId) : join(nodeRecordDir(nodeId), 'run');
98
98
  }
99
+ /** File the daemon leaves in a node's run folder when its broker was released on purpose (idle-release, park,
100
+ * finish, cancel) and removes when the broker is launched again. A background job's `crtr` call that finds its
101
+ * relay socket gone reads it, without asking the daemon, to tell a release from a restart. */
102
+ export const BROKER_RELEASED_MARKER = 'broker-released';
103
+ export const BROKER_RELAY_GENERATION = 'cli-relay-generation';
99
104
  /** The run's scope allow-list as a JSON array, beside `broker-launch.json`. */
100
105
  export function scopesFilePath(nodeId) {
101
106
  return join(nodeRunDir(nodeId), 'scopes.json');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/api",
3
- "version": "0.3.534",
3
+ "version": "0.3.536",
4
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",