omk-adaptorch-wpl 1.4.2 → 1.5.0
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/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [1.5.0] - 2026-10-18
|
|
4
|
+
|
|
5
|
+
- `ADAPTORCH_DEFAULT_API_URL`, used by `createAdaptOrchApiClientFromEnv()` when `ADAPTORCH_API_URL` is unset, is now `https://adaptorch.com`. The previous `https://api.adaptorch.com` does not resolve, so every default-configured request failed before reaching the API.
|
|
6
|
+
|
|
7
|
+
## [1.4.3] - 2026-10-17
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Lockstep version alignment with OMK 1.4.3. No AdaptOrch service or default transport is enabled by this release.
|
|
4
12
|
|
|
5
13
|
## [1.4.2] - 2026-10-16
|
|
6
14
|
|
package/dist/adaptorch-api.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ export declare function resolveAuthHeaders(apiKey: string): Record<string, strin
|
|
|
52
52
|
*/
|
|
53
53
|
export declare function assertSafeApiUrl(baseUrl: string): void;
|
|
54
54
|
/** Default control-plane origin, overridable with `ADAPTORCH_API_URL`. */
|
|
55
|
-
export declare const ADAPTORCH_DEFAULT_API_URL = "https://
|
|
55
|
+
export declare const ADAPTORCH_DEFAULT_API_URL = "https://adaptorch.com";
|
|
56
56
|
/**
|
|
57
57
|
* Build a client from the environment: `ADAPTORCH_API_KEY` and an optional
|
|
58
58
|
* `ADAPTORCH_API_URL`. Returns `undefined` when no key is configured, so a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adaptorch-api.d.ts","sourceRoot":"","sources":["../src/adaptorch-api.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AdaptOrch User API v1 client.\n *\n * This is the hosted path, and it is deliberately separate from\n * `adaptorch-client.ts`: that module wraps the MCP tool surface, which reaches\n * a *local* parent engine, while this one speaks plain HTTPS to the control\n * plane and needs nothing installed beyond an API key.\n *\n * Following the same rule as the MCP wrapper, this package still opens no\n * network I/O of its own. The caller injects `fetch`, so a test never needs a\n * socket and a host application keeps ownership of its HTTP stack.\n */\n\nimport type {\n\tArtifactListResponse,\n\tCapabilitySet,\n\tEvidenceReport,\n\tListRunsQuery,\n\tPrincipal,\n\tRun,\n\tRunListResponse,\n\tRunSubmission,\n} from \"./adaptorch-api-types.ts\";\n\nexport type * from \"./adaptorch-api-types.ts\";\n\nexport interface AdaptOrchRequestInit {\n\treadonly method: string;\n\treadonly headers: Readonly<Record<string, string>>;\n\treadonly body?: string;\n}\n\nexport interface AdaptOrchHttpResponse {\n\treadonly status: number;\n\tjson(): Promise<unknown>;\n\ttext(): Promise<string>;\n}\n\n/** Injected HTTP boundary. `globalThis.fetch` satisfies this shape. */\nexport type AdaptOrchFetch = (url: string, init: AdaptOrchRequestInit) => Promise<AdaptOrchHttpResponse>;\n\nexport interface AdaptOrchApiConfig {\n\treadonly baseUrl: string;\n\treadonly apiKey: string;\n\treadonly fetch: AdaptOrchFetch;\n}\n\n/** A non-2xx response, carrying the server's sanitized code and message. */\nexport class AdaptOrchApiError extends Error {\n\treadonly status: number;\n\treadonly code: string | undefined;\n\n\tconstructor(status: number, code: string | undefined, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"AdaptOrchApiError\";\n\t\tthis.status = status;\n\t\tthis.code = code;\n\t}\n}\n\nconst LOOPBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\n\n/**\n * Choose the credential header.\n *\n * A tenant dashboard key carries the documented `ado_` prefix and must travel\n * only as `X-API-Key`; the contract explicitly forbids also sending it in\n * `Authorization`. Anything else is a non-tenant service credential and uses a\n * bearer token. Sending both would leak a tenant key into a header the control\n * plane does not expect it in.\n */\nexport function resolveAuthHeaders(apiKey: string): Record<string, string> {\n\tconst key = apiKey.trim();\n\tif (key === \"\") throw new Error(\"AdaptOrch API key is required\");\n\treturn key.startsWith(\"ado_\") ? { \"X-API-Key\": key } : { Authorization: `Bearer ${key}` };\n}\n\n/**\n * Reject a base URL that would put a credential on the wire in plaintext.\n * Plain HTTP is allowed only for an exact loopback host, so a lookalike such as\n * `localhost.evil.test` does not slip through a prefix check.\n */\nexport function assertSafeApiUrl(baseUrl: string): void {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(baseUrl);\n\t} catch {\n\t\tthrow new Error(`AdaptOrch base URL is not a valid URL: ${baseUrl}`);\n\t}\n\tif (url.protocol === \"https:\") return;\n\tif (url.protocol === \"http:\" && LOOPBACK_HOSTS.has(url.hostname.replace(/^\\[|\\]$/g, \"\"))) return;\n\tthrow new Error(`AdaptOrch base URL must use https (or http on loopback): ${baseUrl}`);\n}\n\n/** Remove a credential from any text that is about to become an error message. */\nfunction redact(text: string, apiKey: string): string {\n\tconst key = apiKey.trim();\n\treturn key === \"\" ? text : text.split(key).join(\"[REDACTED]\");\n}\n\nfunction readErrorFields(body: unknown): { code?: string; message?: string } {\n\tif (typeof body !== \"object\" || body === null) return {};\n\tconst record = body as Record<string, unknown>;\n\treturn {\n\t\t...(typeof record.code === \"string\" ? { code: record.code } : {}),\n\t\t...(typeof record.message === \"string\" ? { message: record.message } : {}),\n\t};\n}\n\n/** Default control-plane origin, overridable with `ADAPTORCH_API_URL`. */\nexport const ADAPTORCH_DEFAULT_API_URL = \"https://api.adaptorch.com\";\n\n/**\n * Build a client from the environment: `ADAPTORCH_API_KEY` and an optional\n * `ADAPTORCH_API_URL`. Returns `undefined` when no key is configured, so a\n * caller can treat AdaptOrch as an opt-in the operator enables rather than a\n * dependency that must be present.\n */\nexport function createAdaptOrchApiClientFromEnv(\n\tfetchImpl: AdaptOrchFetch,\n\tenv: Readonly<Record<string, string | undefined>> = process.env,\n): AdaptOrchApiClient | undefined {\n\tconst apiKey = env.ADAPTORCH_API_KEY?.trim();\n\tif (!apiKey) return undefined;\n\treturn new AdaptOrchApiClient({\n\t\tbaseUrl: env.ADAPTORCH_API_URL?.trim() || ADAPTORCH_DEFAULT_API_URL,\n\t\tapiKey,\n\t\tfetch: fetchImpl,\n\t});\n}\n\n/** Typed client for the AdaptOrch User API v1. */\nexport class AdaptOrchApiClient {\n\tprivate readonly baseUrl: string;\n\tprivate readonly apiKey: string;\n\tprivate readonly fetch: AdaptOrchFetch;\n\n\tconstructor(config: AdaptOrchApiConfig) {\n\t\tassertSafeApiUrl(config.baseUrl);\n\t\tresolveAuthHeaders(config.apiKey);\n\t\tthis.baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\n\t\tthis.apiKey = config.apiKey;\n\t\tthis.fetch = config.fetch;\n\t}\n\n\tprivate async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n\t\tconst init: AdaptOrchRequestInit = {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/json\",\n\t\t\t\t...resolveAuthHeaders(this.apiKey),\n\t\t\t\t...(body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n\t\t\t},\n\t\t\t...(body === undefined ? {} : { body: JSON.stringify(body) }),\n\t\t};\n\n\t\tlet response: AdaptOrchHttpResponse;\n\t\ttry {\n\t\t\tresponse = await this.fetch(`${this.baseUrl}${path}`, init);\n\t\t} catch (error) {\n\t\t\tconst detail = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`AdaptOrch request failed: ${redact(detail, this.apiKey)}`);\n\t\t}\n\n\t\tlet payload: unknown;\n\t\ttry {\n\t\t\tpayload = await response.json();\n\t\t} catch {\n\t\t\t// A body that is absent or not JSON is not itself a failure: the status\n\t\t\t// still decides, and an error response keeps its generic message.\n\t\t\tpayload = undefined;\n\t\t}\n\t\tif (response.status < 200 || response.status >= 300) {\n\t\t\tconst { code, message } = readErrorFields(payload);\n\t\t\tthrow new AdaptOrchApiError(\n\t\t\t\tresponse.status,\n\t\t\t\tcode,\n\t\t\t\tredact(message ?? `AdaptOrch request failed with status ${response.status}`, this.apiKey),\n\t\t\t);\n\t\t}\n\t\treturn payload as T;\n\t}\n\n\t/** `GET /v1/capabilities` — API version and enabled features. */\n\tcapabilities(): Promise<CapabilitySet> {\n\t\treturn this.request<CapabilitySet>(\"GET\", \"/v1/capabilities\");\n\t}\n\n\t/** `GET /v1/whoami` — the calling principal, for verifying a key works. */\n\twhoami(): Promise<Principal> {\n\t\treturn this.request<Principal>(\"GET\", \"/v1/whoami\");\n\t}\n\n\t/** `POST /v1/runs` — submit work. The contract bounds `subtasks` to 1..50. */\n\tsubmitRun(submission: RunSubmission): Promise<Run> {\n\t\treturn this.request<Run>(\"POST\", \"/v1/runs\", submission);\n\t}\n\n\t/** `GET /v1/runs` — list runs, filtered by the documented parameters only. */\n\tlistRuns(query: ListRunsQuery = {}): Promise<RunListResponse> {\n\t\tconst params = new URLSearchParams();\n\t\tif (query.status !== undefined) params.set(\"status\", query.status);\n\t\tif (query.projectId !== undefined) params.set(\"project_id\", query.projectId);\n\t\tif (query.limit !== undefined) params.set(\"limit\", String(query.limit));\n\t\tif (query.cursor !== undefined) params.set(\"cursor\", query.cursor);\n\t\tconst suffix = params.size === 0 ? \"\" : `?${params.toString()}`;\n\t\treturn this.request<RunListResponse>(\"GET\", `/v1/runs${suffix}`);\n\t}\n\n\t/** `GET /v1/runs/{run_id}` — one run's current state. */\n\tgetRun(runId: string): Promise<Run> {\n\t\treturn this.request<Run>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}`);\n\t}\n\n\t/** `PUT /v1/runs/{run_id}/cancel` — request cancellation. */\n\tcancelRun(runId: string, reason?: string): Promise<Run> {\n\t\treturn this.request<Run>(\n\t\t\t\"PUT\",\n\t\t\t`/v1/runs/${encodeURIComponent(runId)}/cancel`,\n\t\t\treason === undefined ? {} : { reason },\n\t\t);\n\t}\n\n\t/** `GET /v1/runs/{run_id}/evidence` — the graded checks for a run. */\n\tgetEvidence(runId: string): Promise<EvidenceReport> {\n\t\treturn this.request<EvidenceReport>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}/evidence`);\n\t}\n\n\t/** `GET /v1/runs/{run_id}/artifacts` — artifacts a run produced. */\n\tlistArtifacts(runId: string): Promise<ArtifactListResponse> {\n\t\treturn this.request<ArtifactListResponse>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}/artifacts`);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"adaptorch-api.d.ts","sourceRoot":"","sources":["../src/adaptorch-api.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AdaptOrch User API v1 client.\n *\n * This is the hosted path, and it is deliberately separate from\n * `adaptorch-client.ts`: that module wraps the MCP tool surface, which reaches\n * a *local* parent engine, while this one speaks plain HTTPS to the control\n * plane and needs nothing installed beyond an API key.\n *\n * Following the same rule as the MCP wrapper, this package still opens no\n * network I/O of its own. The caller injects `fetch`, so a test never needs a\n * socket and a host application keeps ownership of its HTTP stack.\n */\n\nimport type {\n\tArtifactListResponse,\n\tCapabilitySet,\n\tEvidenceReport,\n\tListRunsQuery,\n\tPrincipal,\n\tRun,\n\tRunListResponse,\n\tRunSubmission,\n} from \"./adaptorch-api-types.ts\";\n\nexport type * from \"./adaptorch-api-types.ts\";\n\nexport interface AdaptOrchRequestInit {\n\treadonly method: string;\n\treadonly headers: Readonly<Record<string, string>>;\n\treadonly body?: string;\n}\n\nexport interface AdaptOrchHttpResponse {\n\treadonly status: number;\n\tjson(): Promise<unknown>;\n\ttext(): Promise<string>;\n}\n\n/** Injected HTTP boundary. `globalThis.fetch` satisfies this shape. */\nexport type AdaptOrchFetch = (url: string, init: AdaptOrchRequestInit) => Promise<AdaptOrchHttpResponse>;\n\nexport interface AdaptOrchApiConfig {\n\treadonly baseUrl: string;\n\treadonly apiKey: string;\n\treadonly fetch: AdaptOrchFetch;\n}\n\n/** A non-2xx response, carrying the server's sanitized code and message. */\nexport class AdaptOrchApiError extends Error {\n\treadonly status: number;\n\treadonly code: string | undefined;\n\n\tconstructor(status: number, code: string | undefined, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"AdaptOrchApiError\";\n\t\tthis.status = status;\n\t\tthis.code = code;\n\t}\n}\n\nconst LOOPBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\n\n/**\n * Choose the credential header.\n *\n * A tenant dashboard key carries the documented `ado_` prefix and must travel\n * only as `X-API-Key`; the contract explicitly forbids also sending it in\n * `Authorization`. Anything else is a non-tenant service credential and uses a\n * bearer token. Sending both would leak a tenant key into a header the control\n * plane does not expect it in.\n */\nexport function resolveAuthHeaders(apiKey: string): Record<string, string> {\n\tconst key = apiKey.trim();\n\tif (key === \"\") throw new Error(\"AdaptOrch API key is required\");\n\treturn key.startsWith(\"ado_\") ? { \"X-API-Key\": key } : { Authorization: `Bearer ${key}` };\n}\n\n/**\n * Reject a base URL that would put a credential on the wire in plaintext.\n * Plain HTTP is allowed only for an exact loopback host, so a lookalike such as\n * `localhost.evil.test` does not slip through a prefix check.\n */\nexport function assertSafeApiUrl(baseUrl: string): void {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(baseUrl);\n\t} catch {\n\t\tthrow new Error(`AdaptOrch base URL is not a valid URL: ${baseUrl}`);\n\t}\n\tif (url.protocol === \"https:\") return;\n\tif (url.protocol === \"http:\" && LOOPBACK_HOSTS.has(url.hostname.replace(/^\\[|\\]$/g, \"\"))) return;\n\tthrow new Error(`AdaptOrch base URL must use https (or http on loopback): ${baseUrl}`);\n}\n\n/** Remove a credential from any text that is about to become an error message. */\nfunction redact(text: string, apiKey: string): string {\n\tconst key = apiKey.trim();\n\treturn key === \"\" ? text : text.split(key).join(\"[REDACTED]\");\n}\n\nfunction readErrorFields(body: unknown): { code?: string; message?: string } {\n\tif (typeof body !== \"object\" || body === null) return {};\n\tconst record = body as Record<string, unknown>;\n\treturn {\n\t\t...(typeof record.code === \"string\" ? { code: record.code } : {}),\n\t\t...(typeof record.message === \"string\" ? { message: record.message } : {}),\n\t};\n}\n\n/** Default control-plane origin, overridable with `ADAPTORCH_API_URL`. */\nexport const ADAPTORCH_DEFAULT_API_URL = \"https://adaptorch.com\";\n\n/**\n * Build a client from the environment: `ADAPTORCH_API_KEY` and an optional\n * `ADAPTORCH_API_URL`. Returns `undefined` when no key is configured, so a\n * caller can treat AdaptOrch as an opt-in the operator enables rather than a\n * dependency that must be present.\n */\nexport function createAdaptOrchApiClientFromEnv(\n\tfetchImpl: AdaptOrchFetch,\n\tenv: Readonly<Record<string, string | undefined>> = process.env,\n): AdaptOrchApiClient | undefined {\n\tconst apiKey = env.ADAPTORCH_API_KEY?.trim();\n\tif (!apiKey) return undefined;\n\treturn new AdaptOrchApiClient({\n\t\tbaseUrl: env.ADAPTORCH_API_URL?.trim() || ADAPTORCH_DEFAULT_API_URL,\n\t\tapiKey,\n\t\tfetch: fetchImpl,\n\t});\n}\n\n/** Typed client for the AdaptOrch User API v1. */\nexport class AdaptOrchApiClient {\n\tprivate readonly baseUrl: string;\n\tprivate readonly apiKey: string;\n\tprivate readonly fetch: AdaptOrchFetch;\n\n\tconstructor(config: AdaptOrchApiConfig) {\n\t\tassertSafeApiUrl(config.baseUrl);\n\t\tresolveAuthHeaders(config.apiKey);\n\t\tthis.baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\n\t\tthis.apiKey = config.apiKey;\n\t\tthis.fetch = config.fetch;\n\t}\n\n\tprivate async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n\t\tconst init: AdaptOrchRequestInit = {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/json\",\n\t\t\t\t...resolveAuthHeaders(this.apiKey),\n\t\t\t\t...(body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n\t\t\t},\n\t\t\t...(body === undefined ? {} : { body: JSON.stringify(body) }),\n\t\t};\n\n\t\tlet response: AdaptOrchHttpResponse;\n\t\ttry {\n\t\t\tresponse = await this.fetch(`${this.baseUrl}${path}`, init);\n\t\t} catch (error) {\n\t\t\tconst detail = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`AdaptOrch request failed: ${redact(detail, this.apiKey)}`);\n\t\t}\n\n\t\tlet payload: unknown;\n\t\ttry {\n\t\t\tpayload = await response.json();\n\t\t} catch {\n\t\t\t// A body that is absent or not JSON is not itself a failure: the status\n\t\t\t// still decides, and an error response keeps its generic message.\n\t\t\tpayload = undefined;\n\t\t}\n\t\tif (response.status < 200 || response.status >= 300) {\n\t\t\tconst { code, message } = readErrorFields(payload);\n\t\t\tthrow new AdaptOrchApiError(\n\t\t\t\tresponse.status,\n\t\t\t\tcode,\n\t\t\t\tredact(message ?? `AdaptOrch request failed with status ${response.status}`, this.apiKey),\n\t\t\t);\n\t\t}\n\t\treturn payload as T;\n\t}\n\n\t/** `GET /v1/capabilities` — API version and enabled features. */\n\tcapabilities(): Promise<CapabilitySet> {\n\t\treturn this.request<CapabilitySet>(\"GET\", \"/v1/capabilities\");\n\t}\n\n\t/** `GET /v1/whoami` — the calling principal, for verifying a key works. */\n\twhoami(): Promise<Principal> {\n\t\treturn this.request<Principal>(\"GET\", \"/v1/whoami\");\n\t}\n\n\t/** `POST /v1/runs` — submit work. The contract bounds `subtasks` to 1..50. */\n\tsubmitRun(submission: RunSubmission): Promise<Run> {\n\t\treturn this.request<Run>(\"POST\", \"/v1/runs\", submission);\n\t}\n\n\t/** `GET /v1/runs` — list runs, filtered by the documented parameters only. */\n\tlistRuns(query: ListRunsQuery = {}): Promise<RunListResponse> {\n\t\tconst params = new URLSearchParams();\n\t\tif (query.status !== undefined) params.set(\"status\", query.status);\n\t\tif (query.projectId !== undefined) params.set(\"project_id\", query.projectId);\n\t\tif (query.limit !== undefined) params.set(\"limit\", String(query.limit));\n\t\tif (query.cursor !== undefined) params.set(\"cursor\", query.cursor);\n\t\tconst suffix = params.size === 0 ? \"\" : `?${params.toString()}`;\n\t\treturn this.request<RunListResponse>(\"GET\", `/v1/runs${suffix}`);\n\t}\n\n\t/** `GET /v1/runs/{run_id}` — one run's current state. */\n\tgetRun(runId: string): Promise<Run> {\n\t\treturn this.request<Run>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}`);\n\t}\n\n\t/** `PUT /v1/runs/{run_id}/cancel` — request cancellation. */\n\tcancelRun(runId: string, reason?: string): Promise<Run> {\n\t\treturn this.request<Run>(\n\t\t\t\"PUT\",\n\t\t\t`/v1/runs/${encodeURIComponent(runId)}/cancel`,\n\t\t\treason === undefined ? {} : { reason },\n\t\t);\n\t}\n\n\t/** `GET /v1/runs/{run_id}/evidence` — the graded checks for a run. */\n\tgetEvidence(runId: string): Promise<EvidenceReport> {\n\t\treturn this.request<EvidenceReport>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}/evidence`);\n\t}\n\n\t/** `GET /v1/runs/{run_id}/artifacts` — artifacts a run produced. */\n\tlistArtifacts(runId: string): Promise<ArtifactListResponse> {\n\t\treturn this.request<ArtifactListResponse>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}/artifacts`);\n\t}\n}\n"]}
|
package/dist/adaptorch-api.js
CHANGED
|
@@ -71,7 +71,7 @@ function readErrorFields(body) {
|
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
/** Default control-plane origin, overridable with `ADAPTORCH_API_URL`. */
|
|
74
|
-
export const ADAPTORCH_DEFAULT_API_URL = "https://
|
|
74
|
+
export const ADAPTORCH_DEFAULT_API_URL = "https://adaptorch.com";
|
|
75
75
|
/**
|
|
76
76
|
* Build a client from the environment: `ADAPTORCH_API_KEY` and an optional
|
|
77
77
|
* `ADAPTORCH_API_URL`. Returns `undefined` when no key is configured, so a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adaptorch-api.js","sourceRoot":"","sources":["../src/adaptorch-api.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AdaptOrch User API v1 client.\n *\n * This is the hosted path, and it is deliberately separate from\n * `adaptorch-client.ts`: that module wraps the MCP tool surface, which reaches\n * a *local* parent engine, while this one speaks plain HTTPS to the control\n * plane and needs nothing installed beyond an API key.\n *\n * Following the same rule as the MCP wrapper, this package still opens no\n * network I/O of its own. The caller injects `fetch`, so a test never needs a\n * socket and a host application keeps ownership of its HTTP stack.\n */\n\nimport type {\n\tArtifactListResponse,\n\tCapabilitySet,\n\tEvidenceReport,\n\tListRunsQuery,\n\tPrincipal,\n\tRun,\n\tRunListResponse,\n\tRunSubmission,\n} from \"./adaptorch-api-types.ts\";\n\nexport type * from \"./adaptorch-api-types.ts\";\n\nexport interface AdaptOrchRequestInit {\n\treadonly method: string;\n\treadonly headers: Readonly<Record<string, string>>;\n\treadonly body?: string;\n}\n\nexport interface AdaptOrchHttpResponse {\n\treadonly status: number;\n\tjson(): Promise<unknown>;\n\ttext(): Promise<string>;\n}\n\n/** Injected HTTP boundary. `globalThis.fetch` satisfies this shape. */\nexport type AdaptOrchFetch = (url: string, init: AdaptOrchRequestInit) => Promise<AdaptOrchHttpResponse>;\n\nexport interface AdaptOrchApiConfig {\n\treadonly baseUrl: string;\n\treadonly apiKey: string;\n\treadonly fetch: AdaptOrchFetch;\n}\n\n/** A non-2xx response, carrying the server's sanitized code and message. */\nexport class AdaptOrchApiError extends Error {\n\treadonly status: number;\n\treadonly code: string | undefined;\n\n\tconstructor(status: number, code: string | undefined, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"AdaptOrchApiError\";\n\t\tthis.status = status;\n\t\tthis.code = code;\n\t}\n}\n\nconst LOOPBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\n\n/**\n * Choose the credential header.\n *\n * A tenant dashboard key carries the documented `ado_` prefix and must travel\n * only as `X-API-Key`; the contract explicitly forbids also sending it in\n * `Authorization`. Anything else is a non-tenant service credential and uses a\n * bearer token. Sending both would leak a tenant key into a header the control\n * plane does not expect it in.\n */\nexport function resolveAuthHeaders(apiKey: string): Record<string, string> {\n\tconst key = apiKey.trim();\n\tif (key === \"\") throw new Error(\"AdaptOrch API key is required\");\n\treturn key.startsWith(\"ado_\") ? { \"X-API-Key\": key } : { Authorization: `Bearer ${key}` };\n}\n\n/**\n * Reject a base URL that would put a credential on the wire in plaintext.\n * Plain HTTP is allowed only for an exact loopback host, so a lookalike such as\n * `localhost.evil.test` does not slip through a prefix check.\n */\nexport function assertSafeApiUrl(baseUrl: string): void {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(baseUrl);\n\t} catch {\n\t\tthrow new Error(`AdaptOrch base URL is not a valid URL: ${baseUrl}`);\n\t}\n\tif (url.protocol === \"https:\") return;\n\tif (url.protocol === \"http:\" && LOOPBACK_HOSTS.has(url.hostname.replace(/^\\[|\\]$/g, \"\"))) return;\n\tthrow new Error(`AdaptOrch base URL must use https (or http on loopback): ${baseUrl}`);\n}\n\n/** Remove a credential from any text that is about to become an error message. */\nfunction redact(text: string, apiKey: string): string {\n\tconst key = apiKey.trim();\n\treturn key === \"\" ? text : text.split(key).join(\"[REDACTED]\");\n}\n\nfunction readErrorFields(body: unknown): { code?: string; message?: string } {\n\tif (typeof body !== \"object\" || body === null) return {};\n\tconst record = body as Record<string, unknown>;\n\treturn {\n\t\t...(typeof record.code === \"string\" ? { code: record.code } : {}),\n\t\t...(typeof record.message === \"string\" ? { message: record.message } : {}),\n\t};\n}\n\n/** Default control-plane origin, overridable with `ADAPTORCH_API_URL`. */\nexport const ADAPTORCH_DEFAULT_API_URL = \"https://api.adaptorch.com\";\n\n/**\n * Build a client from the environment: `ADAPTORCH_API_KEY` and an optional\n * `ADAPTORCH_API_URL`. Returns `undefined` when no key is configured, so a\n * caller can treat AdaptOrch as an opt-in the operator enables rather than a\n * dependency that must be present.\n */\nexport function createAdaptOrchApiClientFromEnv(\n\tfetchImpl: AdaptOrchFetch,\n\tenv: Readonly<Record<string, string | undefined>> = process.env,\n): AdaptOrchApiClient | undefined {\n\tconst apiKey = env.ADAPTORCH_API_KEY?.trim();\n\tif (!apiKey) return undefined;\n\treturn new AdaptOrchApiClient({\n\t\tbaseUrl: env.ADAPTORCH_API_URL?.trim() || ADAPTORCH_DEFAULT_API_URL,\n\t\tapiKey,\n\t\tfetch: fetchImpl,\n\t});\n}\n\n/** Typed client for the AdaptOrch User API v1. */\nexport class AdaptOrchApiClient {\n\tprivate readonly baseUrl: string;\n\tprivate readonly apiKey: string;\n\tprivate readonly fetch: AdaptOrchFetch;\n\n\tconstructor(config: AdaptOrchApiConfig) {\n\t\tassertSafeApiUrl(config.baseUrl);\n\t\tresolveAuthHeaders(config.apiKey);\n\t\tthis.baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\n\t\tthis.apiKey = config.apiKey;\n\t\tthis.fetch = config.fetch;\n\t}\n\n\tprivate async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n\t\tconst init: AdaptOrchRequestInit = {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/json\",\n\t\t\t\t...resolveAuthHeaders(this.apiKey),\n\t\t\t\t...(body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n\t\t\t},\n\t\t\t...(body === undefined ? {} : { body: JSON.stringify(body) }),\n\t\t};\n\n\t\tlet response: AdaptOrchHttpResponse;\n\t\ttry {\n\t\t\tresponse = await this.fetch(`${this.baseUrl}${path}`, init);\n\t\t} catch (error) {\n\t\t\tconst detail = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`AdaptOrch request failed: ${redact(detail, this.apiKey)}`);\n\t\t}\n\n\t\tlet payload: unknown;\n\t\ttry {\n\t\t\tpayload = await response.json();\n\t\t} catch {\n\t\t\t// A body that is absent or not JSON is not itself a failure: the status\n\t\t\t// still decides, and an error response keeps its generic message.\n\t\t\tpayload = undefined;\n\t\t}\n\t\tif (response.status < 200 || response.status >= 300) {\n\t\t\tconst { code, message } = readErrorFields(payload);\n\t\t\tthrow new AdaptOrchApiError(\n\t\t\t\tresponse.status,\n\t\t\t\tcode,\n\t\t\t\tredact(message ?? `AdaptOrch request failed with status ${response.status}`, this.apiKey),\n\t\t\t);\n\t\t}\n\t\treturn payload as T;\n\t}\n\n\t/** `GET /v1/capabilities` — API version and enabled features. */\n\tcapabilities(): Promise<CapabilitySet> {\n\t\treturn this.request<CapabilitySet>(\"GET\", \"/v1/capabilities\");\n\t}\n\n\t/** `GET /v1/whoami` — the calling principal, for verifying a key works. */\n\twhoami(): Promise<Principal> {\n\t\treturn this.request<Principal>(\"GET\", \"/v1/whoami\");\n\t}\n\n\t/** `POST /v1/runs` — submit work. The contract bounds `subtasks` to 1..50. */\n\tsubmitRun(submission: RunSubmission): Promise<Run> {\n\t\treturn this.request<Run>(\"POST\", \"/v1/runs\", submission);\n\t}\n\n\t/** `GET /v1/runs` — list runs, filtered by the documented parameters only. */\n\tlistRuns(query: ListRunsQuery = {}): Promise<RunListResponse> {\n\t\tconst params = new URLSearchParams();\n\t\tif (query.status !== undefined) params.set(\"status\", query.status);\n\t\tif (query.projectId !== undefined) params.set(\"project_id\", query.projectId);\n\t\tif (query.limit !== undefined) params.set(\"limit\", String(query.limit));\n\t\tif (query.cursor !== undefined) params.set(\"cursor\", query.cursor);\n\t\tconst suffix = params.size === 0 ? \"\" : `?${params.toString()}`;\n\t\treturn this.request<RunListResponse>(\"GET\", `/v1/runs${suffix}`);\n\t}\n\n\t/** `GET /v1/runs/{run_id}` — one run's current state. */\n\tgetRun(runId: string): Promise<Run> {\n\t\treturn this.request<Run>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}`);\n\t}\n\n\t/** `PUT /v1/runs/{run_id}/cancel` — request cancellation. */\n\tcancelRun(runId: string, reason?: string): Promise<Run> {\n\t\treturn this.request<Run>(\n\t\t\t\"PUT\",\n\t\t\t`/v1/runs/${encodeURIComponent(runId)}/cancel`,\n\t\t\treason === undefined ? {} : { reason },\n\t\t);\n\t}\n\n\t/** `GET /v1/runs/{run_id}/evidence` — the graded checks for a run. */\n\tgetEvidence(runId: string): Promise<EvidenceReport> {\n\t\treturn this.request<EvidenceReport>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}/evidence`);\n\t}\n\n\t/** `GET /v1/runs/{run_id}/artifacts` — artifacts a run produced. */\n\tlistArtifacts(runId: string): Promise<ArtifactListResponse> {\n\t\treturn this.request<ArtifactListResponse>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}/artifacts`);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"adaptorch-api.js","sourceRoot":"","sources":["../src/adaptorch-api.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AdaptOrch User API v1 client.\n *\n * This is the hosted path, and it is deliberately separate from\n * `adaptorch-client.ts`: that module wraps the MCP tool surface, which reaches\n * a *local* parent engine, while this one speaks plain HTTPS to the control\n * plane and needs nothing installed beyond an API key.\n *\n * Following the same rule as the MCP wrapper, this package still opens no\n * network I/O of its own. The caller injects `fetch`, so a test never needs a\n * socket and a host application keeps ownership of its HTTP stack.\n */\n\nimport type {\n\tArtifactListResponse,\n\tCapabilitySet,\n\tEvidenceReport,\n\tListRunsQuery,\n\tPrincipal,\n\tRun,\n\tRunListResponse,\n\tRunSubmission,\n} from \"./adaptorch-api-types.ts\";\n\nexport type * from \"./adaptorch-api-types.ts\";\n\nexport interface AdaptOrchRequestInit {\n\treadonly method: string;\n\treadonly headers: Readonly<Record<string, string>>;\n\treadonly body?: string;\n}\n\nexport interface AdaptOrchHttpResponse {\n\treadonly status: number;\n\tjson(): Promise<unknown>;\n\ttext(): Promise<string>;\n}\n\n/** Injected HTTP boundary. `globalThis.fetch` satisfies this shape. */\nexport type AdaptOrchFetch = (url: string, init: AdaptOrchRequestInit) => Promise<AdaptOrchHttpResponse>;\n\nexport interface AdaptOrchApiConfig {\n\treadonly baseUrl: string;\n\treadonly apiKey: string;\n\treadonly fetch: AdaptOrchFetch;\n}\n\n/** A non-2xx response, carrying the server's sanitized code and message. */\nexport class AdaptOrchApiError extends Error {\n\treadonly status: number;\n\treadonly code: string | undefined;\n\n\tconstructor(status: number, code: string | undefined, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"AdaptOrchApiError\";\n\t\tthis.status = status;\n\t\tthis.code = code;\n\t}\n}\n\nconst LOOPBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\n\n/**\n * Choose the credential header.\n *\n * A tenant dashboard key carries the documented `ado_` prefix and must travel\n * only as `X-API-Key`; the contract explicitly forbids also sending it in\n * `Authorization`. Anything else is a non-tenant service credential and uses a\n * bearer token. Sending both would leak a tenant key into a header the control\n * plane does not expect it in.\n */\nexport function resolveAuthHeaders(apiKey: string): Record<string, string> {\n\tconst key = apiKey.trim();\n\tif (key === \"\") throw new Error(\"AdaptOrch API key is required\");\n\treturn key.startsWith(\"ado_\") ? { \"X-API-Key\": key } : { Authorization: `Bearer ${key}` };\n}\n\n/**\n * Reject a base URL that would put a credential on the wire in plaintext.\n * Plain HTTP is allowed only for an exact loopback host, so a lookalike such as\n * `localhost.evil.test` does not slip through a prefix check.\n */\nexport function assertSafeApiUrl(baseUrl: string): void {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(baseUrl);\n\t} catch {\n\t\tthrow new Error(`AdaptOrch base URL is not a valid URL: ${baseUrl}`);\n\t}\n\tif (url.protocol === \"https:\") return;\n\tif (url.protocol === \"http:\" && LOOPBACK_HOSTS.has(url.hostname.replace(/^\\[|\\]$/g, \"\"))) return;\n\tthrow new Error(`AdaptOrch base URL must use https (or http on loopback): ${baseUrl}`);\n}\n\n/** Remove a credential from any text that is about to become an error message. */\nfunction redact(text: string, apiKey: string): string {\n\tconst key = apiKey.trim();\n\treturn key === \"\" ? text : text.split(key).join(\"[REDACTED]\");\n}\n\nfunction readErrorFields(body: unknown): { code?: string; message?: string } {\n\tif (typeof body !== \"object\" || body === null) return {};\n\tconst record = body as Record<string, unknown>;\n\treturn {\n\t\t...(typeof record.code === \"string\" ? { code: record.code } : {}),\n\t\t...(typeof record.message === \"string\" ? { message: record.message } : {}),\n\t};\n}\n\n/** Default control-plane origin, overridable with `ADAPTORCH_API_URL`. */\nexport const ADAPTORCH_DEFAULT_API_URL = \"https://adaptorch.com\";\n\n/**\n * Build a client from the environment: `ADAPTORCH_API_KEY` and an optional\n * `ADAPTORCH_API_URL`. Returns `undefined` when no key is configured, so a\n * caller can treat AdaptOrch as an opt-in the operator enables rather than a\n * dependency that must be present.\n */\nexport function createAdaptOrchApiClientFromEnv(\n\tfetchImpl: AdaptOrchFetch,\n\tenv: Readonly<Record<string, string | undefined>> = process.env,\n): AdaptOrchApiClient | undefined {\n\tconst apiKey = env.ADAPTORCH_API_KEY?.trim();\n\tif (!apiKey) return undefined;\n\treturn new AdaptOrchApiClient({\n\t\tbaseUrl: env.ADAPTORCH_API_URL?.trim() || ADAPTORCH_DEFAULT_API_URL,\n\t\tapiKey,\n\t\tfetch: fetchImpl,\n\t});\n}\n\n/** Typed client for the AdaptOrch User API v1. */\nexport class AdaptOrchApiClient {\n\tprivate readonly baseUrl: string;\n\tprivate readonly apiKey: string;\n\tprivate readonly fetch: AdaptOrchFetch;\n\n\tconstructor(config: AdaptOrchApiConfig) {\n\t\tassertSafeApiUrl(config.baseUrl);\n\t\tresolveAuthHeaders(config.apiKey);\n\t\tthis.baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\n\t\tthis.apiKey = config.apiKey;\n\t\tthis.fetch = config.fetch;\n\t}\n\n\tprivate async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n\t\tconst init: AdaptOrchRequestInit = {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/json\",\n\t\t\t\t...resolveAuthHeaders(this.apiKey),\n\t\t\t\t...(body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n\t\t\t},\n\t\t\t...(body === undefined ? {} : { body: JSON.stringify(body) }),\n\t\t};\n\n\t\tlet response: AdaptOrchHttpResponse;\n\t\ttry {\n\t\t\tresponse = await this.fetch(`${this.baseUrl}${path}`, init);\n\t\t} catch (error) {\n\t\t\tconst detail = error instanceof Error ? error.message : String(error);\n\t\t\tthrow new Error(`AdaptOrch request failed: ${redact(detail, this.apiKey)}`);\n\t\t}\n\n\t\tlet payload: unknown;\n\t\ttry {\n\t\t\tpayload = await response.json();\n\t\t} catch {\n\t\t\t// A body that is absent or not JSON is not itself a failure: the status\n\t\t\t// still decides, and an error response keeps its generic message.\n\t\t\tpayload = undefined;\n\t\t}\n\t\tif (response.status < 200 || response.status >= 300) {\n\t\t\tconst { code, message } = readErrorFields(payload);\n\t\t\tthrow new AdaptOrchApiError(\n\t\t\t\tresponse.status,\n\t\t\t\tcode,\n\t\t\t\tredact(message ?? `AdaptOrch request failed with status ${response.status}`, this.apiKey),\n\t\t\t);\n\t\t}\n\t\treturn payload as T;\n\t}\n\n\t/** `GET /v1/capabilities` — API version and enabled features. */\n\tcapabilities(): Promise<CapabilitySet> {\n\t\treturn this.request<CapabilitySet>(\"GET\", \"/v1/capabilities\");\n\t}\n\n\t/** `GET /v1/whoami` — the calling principal, for verifying a key works. */\n\twhoami(): Promise<Principal> {\n\t\treturn this.request<Principal>(\"GET\", \"/v1/whoami\");\n\t}\n\n\t/** `POST /v1/runs` — submit work. The contract bounds `subtasks` to 1..50. */\n\tsubmitRun(submission: RunSubmission): Promise<Run> {\n\t\treturn this.request<Run>(\"POST\", \"/v1/runs\", submission);\n\t}\n\n\t/** `GET /v1/runs` — list runs, filtered by the documented parameters only. */\n\tlistRuns(query: ListRunsQuery = {}): Promise<RunListResponse> {\n\t\tconst params = new URLSearchParams();\n\t\tif (query.status !== undefined) params.set(\"status\", query.status);\n\t\tif (query.projectId !== undefined) params.set(\"project_id\", query.projectId);\n\t\tif (query.limit !== undefined) params.set(\"limit\", String(query.limit));\n\t\tif (query.cursor !== undefined) params.set(\"cursor\", query.cursor);\n\t\tconst suffix = params.size === 0 ? \"\" : `?${params.toString()}`;\n\t\treturn this.request<RunListResponse>(\"GET\", `/v1/runs${suffix}`);\n\t}\n\n\t/** `GET /v1/runs/{run_id}` — one run's current state. */\n\tgetRun(runId: string): Promise<Run> {\n\t\treturn this.request<Run>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}`);\n\t}\n\n\t/** `PUT /v1/runs/{run_id}/cancel` — request cancellation. */\n\tcancelRun(runId: string, reason?: string): Promise<Run> {\n\t\treturn this.request<Run>(\n\t\t\t\"PUT\",\n\t\t\t`/v1/runs/${encodeURIComponent(runId)}/cancel`,\n\t\t\treason === undefined ? {} : { reason },\n\t\t);\n\t}\n\n\t/** `GET /v1/runs/{run_id}/evidence` — the graded checks for a run. */\n\tgetEvidence(runId: string): Promise<EvidenceReport> {\n\t\treturn this.request<EvidenceReport>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}/evidence`);\n\t}\n\n\t/** `GET /v1/runs/{run_id}/artifacts` — artifacts a run produced. */\n\tlistArtifacts(runId: string): Promise<ArtifactListResponse> {\n\t\treturn this.request<ArtifactListResponse>(\"GET\", `/v1/runs/${encodeURIComponent(runId)}/artifacts`);\n\t}\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omk-adaptorch-wpl",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "AdaptOrch-native Work Packet Loop (WPL) — state machine, verification layer, and integration bridge for OMK orchestration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"CHANGELOG.md"
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
|
-
"clean": "
|
|
21
|
+
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
22
22
|
"build": "tsgo -p tsconfig.build.json",
|
|
23
23
|
"test": "vitest --run"
|
|
24
24
|
},
|
|
@@ -39,10 +39,9 @@
|
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "24.12.4",
|
|
42
|
-
"@vitest/coverage-v8": "
|
|
42
|
+
"@vitest/coverage-v8": "4.1.11",
|
|
43
43
|
"fast-check": "4.9.0",
|
|
44
|
-
"shx": "0.4.0",
|
|
45
44
|
"typescript": "5.9.3",
|
|
46
|
-
"vitest": "
|
|
45
|
+
"vitest": "4.1.11"
|
|
47
46
|
}
|
|
48
47
|
}
|