@north-light/api 0.3.453 → 0.3.455
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/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/error-codes.d.ts +25 -0
- package/dist/api/error-codes.js +10 -0
- package/dist/core/command-plugins/bundle.d.ts +3 -10
- package/dist/core/command-plugins/bundle.js +4 -4
- package/dist/core/command-plugins/endpoint.d.ts +12 -0
- package/dist/core/command-plugins/endpoint.js +7 -0
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
package/dist/api/contract.d.ts
CHANGED
|
@@ -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.
|
|
2
|
+
export declare const CONTRACT_LEVEL = "1.4";
|
|
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`. */
|
package/dist/api/contract.js
CHANGED
|
@@ -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.
|
|
15
|
+
export const CONTRACT_LEVEL = '1.4';
|
|
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`. */
|
|
@@ -134,6 +134,31 @@ export declare const errorCodes: {
|
|
|
134
134
|
readonly status: 409;
|
|
135
135
|
readonly retryable: false;
|
|
136
136
|
};
|
|
137
|
+
readonly invalid_argument: {
|
|
138
|
+
readonly type: "invalid_request_error";
|
|
139
|
+
readonly status: 400;
|
|
140
|
+
readonly retryable: false;
|
|
141
|
+
};
|
|
142
|
+
readonly machine_required: {
|
|
143
|
+
readonly type: "invalid_request_error";
|
|
144
|
+
readonly status: 409;
|
|
145
|
+
readonly retryable: false;
|
|
146
|
+
};
|
|
147
|
+
readonly device_offline: {
|
|
148
|
+
readonly type: "server_error";
|
|
149
|
+
readonly status: 503;
|
|
150
|
+
readonly retryable: true;
|
|
151
|
+
};
|
|
152
|
+
readonly device_timeout: {
|
|
153
|
+
readonly type: "server_error";
|
|
154
|
+
readonly status: 504;
|
|
155
|
+
readonly retryable: true;
|
|
156
|
+
};
|
|
157
|
+
readonly device_disconnected: {
|
|
158
|
+
readonly type: "server_error";
|
|
159
|
+
readonly status: 503;
|
|
160
|
+
readonly retryable: false;
|
|
161
|
+
};
|
|
137
162
|
readonly not_found: {
|
|
138
163
|
readonly type: "invalid_request_error";
|
|
139
164
|
readonly status: 404;
|
package/dist/api/error-codes.js
CHANGED
|
@@ -37,6 +37,16 @@ export const errorCodes = {
|
|
|
37
37
|
// A peer machine runs a crtr release below the peer-protocol floor; details `{ peer_version, floor, receiver_version }`. Update it with `crtr sys update`.
|
|
38
38
|
peer_version_too_old: { type: 'invalid_request_error', status: 426, retryable: false },
|
|
39
39
|
conflict: { type: 'invalid_request_error', status: 409, retryable: false },
|
|
40
|
+
// `provider.call` input that cannot apply: `machine` on a provider that is not served by a machine.
|
|
41
|
+
invalid_argument: { type: 'invalid_request_error', status: 400, retryable: false },
|
|
42
|
+
// A device call names no machine and the account has several (or the named one is not a device); details `{ candidates: [{ machine_id, name, last_seen }] }`.
|
|
43
|
+
machine_required: { type: 'invalid_request_error', status: 409, retryable: false },
|
|
44
|
+
// The device machine is offline, unreachable, or its Desktop is signed out.
|
|
45
|
+
device_offline: { type: 'server_error', status: 503, retryable: true },
|
|
46
|
+
// The device did not answer within the call's deadline.
|
|
47
|
+
device_timeout: { type: 'server_error', status: 504, retryable: true },
|
|
48
|
+
// The device's relay connection dropped mid-call; the action may have run, so it is not retryable.
|
|
49
|
+
device_disconnected: { type: 'server_error', status: 503, retryable: false },
|
|
40
50
|
not_found: { type: 'invalid_request_error', status: 404, retryable: false },
|
|
41
51
|
model_unavailable: { type: 'invalid_request_error', status: 404, retryable: false },
|
|
42
52
|
upstream_model_unavailable: { type: 'server_error', status: 503, retryable: true },
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ValidatedCommandManifest } from '../../api/command-manifest/manifest.js';
|
|
2
2
|
import type { KindConfig, MemoryExtensionDeclarations, PageComponentRegistration, PluginBundle, PluginManifest, Scope } from '../../types.js';
|
|
3
|
+
import { type BundleTransport } from './endpoint.js';
|
|
3
4
|
/** Who may call a capability provider's tool group (contract 3). */
|
|
4
5
|
export type ProviderGroupWho = 'own' | 'user' | 'allowlist' | 'any';
|
|
5
6
|
/** One tool group a capability provider declares in `bundle.json`. */
|
|
@@ -34,11 +35,7 @@ export interface ValidatedBundle {
|
|
|
34
35
|
version?: number;
|
|
35
36
|
/** The transport `bundle.json` declares, when it declares one (a bundle the
|
|
36
37
|
* directory emits for a capability provider always does). */
|
|
37
|
-
transport?:
|
|
38
|
-
kind: 'http';
|
|
39
|
-
endpoint: string;
|
|
40
|
-
authEnv?: string;
|
|
41
|
-
};
|
|
38
|
+
transport?: BundleTransport;
|
|
42
39
|
/** The capability-provider block: present only on a provider bundle. */
|
|
43
40
|
provider?: ProviderBlock;
|
|
44
41
|
/** Kind-registry contributions declared in `bundle.json` (optional). The
|
|
@@ -82,11 +79,7 @@ export declare function validatePluginBundle(archive: Uint8Array, options: {
|
|
|
82
79
|
extensibleCoreBranches?: ReadonlySet<string>;
|
|
83
80
|
}): Promise<PluginBundleValidation>;
|
|
84
81
|
/** An archive install's invocation transport. */
|
|
85
|
-
export type BundleInvocationTransport =
|
|
86
|
-
kind: 'http';
|
|
87
|
-
endpoint: string;
|
|
88
|
-
authEnv?: string;
|
|
89
|
-
};
|
|
82
|
+
export type BundleInvocationTransport = BundleTransport;
|
|
90
83
|
/** The hash recorded as a bundle package's `version`: the exact archive bytes
|
|
91
84
|
* unpacked at its root. Same bytes, same version — which is what lets a
|
|
92
85
|
* re-sent archive be recognized as the generation already installed. */
|
|
@@ -8,7 +8,7 @@ import { general } from '../errors.js';
|
|
|
8
8
|
import { atomicWriteJson, atomicWriteText, ensureDir, nowIso, pathExists, removePath, syncDirectory, syncTree } from '../fs-utils.js';
|
|
9
9
|
import { invalidPageComponentsReasons, normalizePageComponents } from '../human/page-catalog.js';
|
|
10
10
|
import { validateMemoryExtensionDeclarations } from '../plugin-extensions.js';
|
|
11
|
-
import {
|
|
11
|
+
import { validateBundleTransport } from './endpoint.js';
|
|
12
12
|
/** A capability provider id or tool group id: contract 1's `<id>` grammar. */
|
|
13
13
|
const PROVIDER_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
14
14
|
const PROVIDER_KEYS = new Set(['id', 'major', 'groups']);
|
|
@@ -240,7 +240,7 @@ function providerBundleIssue(metadata, commands) {
|
|
|
240
240
|
if (metadata.transport === undefined) {
|
|
241
241
|
return bundleInvalid('a provider bundle must declare its transport', '(missing)', 'transport { kind: "http", endpoint } in bundle.json', 'Add the provider endpoint as bundle.json transport.', 'bundle.json.transport');
|
|
242
242
|
}
|
|
243
|
-
if (metadata.transport.authEnv !== undefined) {
|
|
243
|
+
if (metadata.transport.kind === 'http' && metadata.transport.authEnv !== undefined) {
|
|
244
244
|
return bundleInvalid('a provider bundle must not declare authEnv', metadata.transport.authEnv, 'no authEnv: the runtime presents its own outbound token', 'Remove transport.authEnv from bundle.json.', 'bundle.json.transport.authEnv');
|
|
245
245
|
}
|
|
246
246
|
const declared = new Set(provider.groups.map((g) => g.group));
|
|
@@ -315,10 +315,10 @@ function parseBundleMetadata(bytes) {
|
|
|
315
315
|
}
|
|
316
316
|
let transport;
|
|
317
317
|
if (record['transport'] !== undefined) {
|
|
318
|
-
const t =
|
|
318
|
+
const t = validateBundleTransport(record['transport']);
|
|
319
319
|
if (t.transport === undefined) {
|
|
320
320
|
return {
|
|
321
|
-
issue: bundleInvalid('bundle.json transport is invalid', t.errors.join('; '), '{ kind: "http", endpoint, authEnv? }', 'Fix transport in bundle.json.', 'bundle.json.transport'),
|
|
321
|
+
issue: bundleInvalid('bundle.json transport is invalid', t.errors.join('; '), '{ kind: "http", endpoint, authEnv? } or { kind: "machine" }', 'Fix transport in bundle.json.', 'bundle.json.transport'),
|
|
322
322
|
};
|
|
323
323
|
}
|
|
324
324
|
transport = t.transport;
|
|
@@ -22,3 +22,15 @@ export declare function validateHttpPluginTransport(raw: unknown): {
|
|
|
22
22
|
};
|
|
23
23
|
errors: string[];
|
|
24
24
|
};
|
|
25
|
+
/** The transport a served provider bundle declares: HTTP (the provider's endpoint) or `{ kind: "machine" }` (calls go to a device machine). */
|
|
26
|
+
export type BundleTransport = {
|
|
27
|
+
kind: 'http';
|
|
28
|
+
endpoint: string;
|
|
29
|
+
authEnv?: string;
|
|
30
|
+
} | {
|
|
31
|
+
kind: 'machine';
|
|
32
|
+
};
|
|
33
|
+
export declare function validateBundleTransport(raw: unknown): {
|
|
34
|
+
transport?: BundleTransport;
|
|
35
|
+
errors: string[];
|
|
36
|
+
};
|
|
@@ -49,3 +49,10 @@ export function validateHttpPluginTransport(raw) {
|
|
|
49
49
|
errors.push(...validateEnvVarName(transport.authEnv).errors);
|
|
50
50
|
return errors.length ? { errors } : { transport: { kind: 'http', endpoint: normalizeEndpoint(transport.endpoint), ...(transport.authEnv !== undefined ? { authEnv: transport.authEnv } : {}) }, errors };
|
|
51
51
|
}
|
|
52
|
+
export function validateBundleTransport(raw) {
|
|
53
|
+
if (typeof raw === 'object' && raw !== null && !Array.isArray(raw) && raw.kind === 'machine') {
|
|
54
|
+
const unknown = Object.keys(raw).filter((key) => key !== 'kind');
|
|
55
|
+
return unknown.length ? { errors: [`transport has unknown keys: ${unknown.join(', ')}`] } : { transport: { kind: 'machine' }, errors: [] };
|
|
56
|
+
}
|
|
57
|
+
return validateHttpPluginTransport(raw);
|
|
58
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ export type PluginTransport = {
|
|
|
23
23
|
kind: 'http';
|
|
24
24
|
endpoint: string;
|
|
25
25
|
authEnv?: string;
|
|
26
|
+
}
|
|
27
|
+
/** A provider whose calls go to one of the account's `kind = device` machines over the relay; there is no endpoint. */
|
|
28
|
+
| {
|
|
29
|
+
kind: 'machine';
|
|
26
30
|
};
|
|
27
31
|
/** Provenance for a crouter-materialized HTTP plugin directory archive. */
|
|
28
32
|
export interface PluginBundle {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/api",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.455",
|
|
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",
|