@north-light/sdk 0.0.0 → 0.3.415
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/LICENSE +18 -0
- package/README.md +187 -2
- package/dist/client.d.ts +176 -0
- package/dist/client.js +582 -0
- package/dist/crtr.d.ts +24 -0
- package/dist/crtr.js +50 -0
- package/dist/env-command.d.ts +15 -0
- package/dist/env-command.js +138 -0
- package/dist/error-codes.d.ts +7 -0
- package/dist/error-codes.js +43 -0
- package/dist/errors.d.ts +72 -0
- package/dist/errors.js +101 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +17 -0
- package/dist/keygen-cli.d.ts +2 -0
- package/dist/keygen-cli.js +11 -0
- package/dist/keygen-command.d.ts +6 -0
- package/dist/keygen-command.js +131 -0
- package/dist/oauth/index.d.ts +235 -0
- package/dist/oauth/index.js +621 -0
- package/dist/oauth/keygen.d.ts +18 -0
- package/dist/oauth/keygen.js +46 -0
- package/dist/oauth/refusal.d.ts +32 -0
- package/dist/oauth/refusal.js +17 -0
- package/dist/resources/activity.d.ts +22 -0
- package/dist/resources/activity.js +43 -0
- package/dist/resources/attachments.d.ts +15 -0
- package/dist/resources/attachments.js +13 -0
- package/dist/resources/bash.d.ts +9 -0
- package/dist/resources/bash.js +15 -0
- package/dist/resources/canvas/history.d.ts +11 -0
- package/dist/resources/canvas/history.js +20 -0
- package/dist/resources/canvas.d.ts +19 -0
- package/dist/resources/canvas.js +42 -0
- package/dist/resources/crons.d.ts +15 -0
- package/dist/resources/crons.js +33 -0
- package/dist/resources/custom-objects.d.ts +20 -0
- package/dist/resources/custom-objects.js +84 -0
- package/dist/resources/files.d.ts +34 -0
- package/dist/resources/files.js +34 -0
- package/dist/resources/follower.d.ts +71 -0
- package/dist/resources/follower.js +202 -0
- package/dist/resources/forward.d.ts +7 -0
- package/dist/resources/forward.js +67 -0
- package/dist/resources/grant-watcher.d.ts +57 -0
- package/dist/resources/grant-watcher.js +100 -0
- package/dist/resources/human/inbox.d.ts +14 -0
- package/dist/resources/human/inbox.js +30 -0
- package/dist/resources/human/requests.d.ts +13 -0
- package/dist/resources/human/requests.js +26 -0
- package/dist/resources/human.d.ts +8 -0
- package/dist/resources/human.js +10 -0
- package/dist/resources/identifiers.d.ts +8 -0
- package/dist/resources/identifiers.js +33 -0
- package/dist/resources/memory.d.ts +69 -0
- package/dist/resources/memory.js +30 -0
- package/dist/resources/models/config.d.ts +8 -0
- package/dist/resources/models/config.js +9 -0
- package/dist/resources/models/credentials.d.ts +10 -0
- package/dist/resources/models/credentials.js +17 -0
- package/dist/resources/models.d.ts +8 -0
- package/dist/resources/models.js +10 -0
- package/dist/resources/node-stream.d.ts +34 -0
- package/dist/resources/node-stream.js +176 -0
- package/dist/resources/nodes/jobs.d.ts +9 -0
- package/dist/resources/nodes/jobs.js +14 -0
- package/dist/resources/nodes/result.d.ts +8 -0
- package/dist/resources/nodes/result.js +11 -0
- package/dist/resources/nodes/worktree.d.ts +9 -0
- package/dist/resources/nodes/worktree.js +14 -0
- package/dist/resources/nodes.d.ts +23 -0
- package/dist/resources/nodes.js +47 -0
- package/dist/resources/providers.d.ts +51 -0
- package/dist/resources/providers.js +15 -0
- package/dist/resources/questions.d.ts +49 -0
- package/dist/resources/questions.js +21 -0
- package/dist/resources/request.d.ts +12 -0
- package/dist/resources/request.js +50 -0
- package/dist/resources/run-notice.d.ts +34 -0
- package/dist/resources/run-notice.js +67 -0
- package/dist/resources/run-reply.d.ts +79 -0
- package/dist/resources/run-reply.js +93 -0
- package/dist/resources/run-stream.d.ts +65 -0
- package/dist/resources/run-stream.js +243 -0
- package/dist/resources/run-watcher.d.ts +98 -0
- package/dist/resources/run-watcher.js +162 -0
- package/dist/resources/runs.d.ts +199 -0
- package/dist/resources/runs.js +228 -0
- package/dist/resources/shares.d.ts +40 -0
- package/dist/resources/shares.js +19 -0
- package/dist/resources/structured-requests.d.ts +14 -0
- package/dist/resources/structured-requests.js +19 -0
- package/dist/resources/uploads.d.ts +27 -0
- package/dist/resources/uploads.js +11 -0
- package/dist/schema.d.ts +7 -0
- package/dist/schema.js +10 -0
- package/dist/stores/postgres.d.ts +32 -0
- package/dist/stores/postgres.js +92 -0
- package/dist/testing/clock.d.ts +7 -0
- package/dist/testing/clock.js +12 -0
- package/dist/testing/cloud.d.ts +228 -0
- package/dist/testing/cloud.js +914 -0
- package/dist/testing/conformance/index.d.ts +2 -0
- package/dist/testing/conformance/index.js +3 -0
- package/dist/testing/conformance/keyed-write.d.ts +43 -0
- package/dist/testing/conformance/keyed-write.js +124 -0
- package/dist/testing/index.d.ts +7 -0
- package/dist/testing/index.js +4 -0
- package/dist/testing/notices.d.ts +76 -0
- package/dist/testing/notices.js +209 -0
- package/dist/testing/run.d.ts +174 -0
- package/dist/testing/run.js +429 -0
- package/dist/testing/users.d.ts +127 -0
- package/dist/testing/users.js +78 -0
- package/dist/testing/wire.d.ts +62 -0
- package/dist/testing/wire.js +148 -0
- package/dist/types.d.ts +88 -0
- package/dist/types.js +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +3 -0
- package/package.json +60 -5
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import type { ProviderDependency } from '@north-light/api';
|
|
2
|
+
import { Crouter } from '../client.js';
|
|
3
|
+
import { type ConnectionStore } from '../oauth/index.js';
|
|
4
|
+
import { type FakeNotice, type RunNoticeOptions } from './notices.js';
|
|
5
|
+
import { FakeRun } from './run.js';
|
|
6
|
+
import { type FakeRefusalCode, type FakeScope, type FakeUser, type Responder } from './users.js';
|
|
7
|
+
import { type FakeError } from './wire.js';
|
|
8
|
+
/** A runtime operation, named as the daemon's `OPERATIONS` table names it. */
|
|
9
|
+
export type FakeOp = 'grant.get' | 'run.start' | 'run.list' | 'run.get' | 'run.message' | 'run.events' | 'run.interrupt' | 'run.cancel' | 'run.delete' | 'run.rename' | 'question.get' | 'question.answer' | 'trace.get' | 'memory.list' | 'memory.get' | 'provider.tools' | 'provider.call' | 'profile.list';
|
|
10
|
+
/** A directory operation. */
|
|
11
|
+
export type FakeDirectoryOp = 'directory.discovery' | 'directory.token' | 'directory.jwks';
|
|
12
|
+
/** What `intercept` / `failNext` / `gate` match: a runtime operation, `'*'` (every runtime operation), or a directory operation. */
|
|
13
|
+
export type FakeInterceptOp = FakeOp | '*' | FakeDirectoryOp;
|
|
14
|
+
/** One runtime request the fake received. */
|
|
15
|
+
export interface FakeCall {
|
|
16
|
+
/** The bearer token's `sub` when it names a person this cloud knows (whatever their grant or refresh-token state);
|
|
17
|
+
* null when there is no bearer, it does not decode, or its `sub` is a person the cloud has never seen. */
|
|
18
|
+
userId: string | null;
|
|
19
|
+
op: FakeOp;
|
|
20
|
+
/** The run the call addresses: the id in the path of `run.get`/`message`/`events`/`interrupt`/`cancel`/`delete`/
|
|
21
|
+
* `rename` and `trace.get` (as sent, whether or not such a run exists); for `question.get`/`answer`, the run that
|
|
22
|
+
* holds the question (null when no run of the caller does). Null for every other operation. */
|
|
23
|
+
runId: string | null;
|
|
24
|
+
/** The question id in the path of `question.get`/`answer`; null otherwise. */
|
|
25
|
+
questionId: string | null;
|
|
26
|
+
method: string;
|
|
27
|
+
path: string;
|
|
28
|
+
query: Record<string, string>;
|
|
29
|
+
/** Parsed JSON body, or null. */
|
|
30
|
+
body: unknown;
|
|
31
|
+
idempotencyKey: string | null;
|
|
32
|
+
/** The status answered; null while held or before an answer. */
|
|
33
|
+
status: number | null;
|
|
34
|
+
at: number;
|
|
35
|
+
}
|
|
36
|
+
/** One directory request the fake received. */
|
|
37
|
+
export interface FakeDirectoryCall {
|
|
38
|
+
op: FakeDirectoryOp;
|
|
39
|
+
/** The refresh token's owner on `directory.token`; null otherwise. */
|
|
40
|
+
userId: string | null;
|
|
41
|
+
/** `ok`, a refusal code, an HTTP status, or `unreachable`. */
|
|
42
|
+
answer: 'ok' | FakeRefusalCode | number | 'unreachable';
|
|
43
|
+
at: number;
|
|
44
|
+
}
|
|
45
|
+
/** A scripted failure: `'unreachable'` (fetch rejects), an HTTP status, or a `FakeCloud.error(...)` envelope (runtime only). */
|
|
46
|
+
export type FakeAnswer = 'unreachable' | number | FakeError;
|
|
47
|
+
/** Runs before an operation. It may await (a gate), act, or return a replacement answer. */
|
|
48
|
+
export type Intercept = (call: FakeCall | FakeDirectoryCall) => void | FakeAnswer | Promise<void | FakeAnswer>;
|
|
49
|
+
/** A provider tool's handler; its return value is the call's result. Throw `FakeCloud.error(...)` for an envelope. */
|
|
50
|
+
export type FakeToolHandler = (input: {
|
|
51
|
+
userId: string;
|
|
52
|
+
arguments: Record<string, unknown>;
|
|
53
|
+
signal: AbortSignal | null;
|
|
54
|
+
}) => unknown;
|
|
55
|
+
/** `providers.define` input. */
|
|
56
|
+
export interface FakeProvider {
|
|
57
|
+
displayName?: string;
|
|
58
|
+
/** `available` (default), or an install state: listed with `error`, calls answer 503 `provider_unavailable`. */
|
|
59
|
+
status?: 'available' | 'installing' | 'install_failed';
|
|
60
|
+
error?: string;
|
|
61
|
+
tools: Record<string, {
|
|
62
|
+
group?: string;
|
|
63
|
+
description?: string;
|
|
64
|
+
handler: FakeToolHandler;
|
|
65
|
+
}>;
|
|
66
|
+
}
|
|
67
|
+
export interface FakeCloudOptions {
|
|
68
|
+
/** The app registration this cloud serves. */
|
|
69
|
+
clientId: string;
|
|
70
|
+
/** Default `https://directory.test`. */
|
|
71
|
+
issuer?: string;
|
|
72
|
+
/** Default `https://runtime.test`; a function gives each user their own host. */
|
|
73
|
+
runtimeUrl?: string | ((userId: string) => string);
|
|
74
|
+
/** The runtime's identity in run-notice tokens (`act.sub`). Default `runtime:test`. */
|
|
75
|
+
runtimeId?: string;
|
|
76
|
+
/** The runtime's client id in run-notice tokens (`client_id`). Default `runtime-client`. */
|
|
77
|
+
runtimeClientId?: string;
|
|
78
|
+
/** The runtime's release; default `SDK_VERSION`. An older one refuses this SDK with 426. */
|
|
79
|
+
runtimeVersion?: string;
|
|
80
|
+
/** Idle close of a run's event stream. Default 60 000 ms. */
|
|
81
|
+
streamIdleMs?: number;
|
|
82
|
+
/** Discovery's `account_app_uri_template`; default `<issuer>/account/apps/{client_id}`, null omits it. */
|
|
83
|
+
accountAppUriTemplate?: string | null;
|
|
84
|
+
/** Runtime→app run notices; without it nothing is sent. */
|
|
85
|
+
runNotice?: RunNoticeOptions;
|
|
86
|
+
/**
|
|
87
|
+
* Whether the runtime can start an `isolated: true` run. `available` (default) models a crouter cloud guest, where
|
|
88
|
+
* the Linux root launcher always exists: the run starts, `run.params.isolated` is true, and a `cwd` outside the run's
|
|
89
|
+
* root folder (`/apps/<clientId>/nodes/<run id>`) is 400 `invalid_request` `param: cwd`. `unavailable` models a
|
|
90
|
+
* runtime without the launcher (a developer's Mac): every isolated start is 503 `isolated_unavailable`, retryable.
|
|
91
|
+
*/
|
|
92
|
+
isolatedRuns?: 'available' | 'unavailable';
|
|
93
|
+
/**
|
|
94
|
+
* The clock every timestamp the fake writes reads, and the idempotency window runs on (default `Date.now`). Use
|
|
95
|
+
* `manualClock()` to step time. Stream idle, long-poll waits and run-notice retries stay on real timers.
|
|
96
|
+
*/
|
|
97
|
+
clock?: {
|
|
98
|
+
now(): number;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/** `cloud.runs` and `user.runs`: the runs in start order, and the responder for them. */
|
|
102
|
+
export interface FakeRuns {
|
|
103
|
+
/** The runs in start order (deleted ones included, with `deleted` set). */
|
|
104
|
+
readonly all: FakeRun[];
|
|
105
|
+
/** Set the responder (null clears it). On a user's `runs` it overrides the cloud's for that user. */
|
|
106
|
+
respond(fn: Responder | null): void;
|
|
107
|
+
}
|
|
108
|
+
/** A fake crouter cloud: the directory (discovery, refresh, JWKS) and each person's runtime, behind `fetch`. */
|
|
109
|
+
export declare class FakeCloud {
|
|
110
|
+
/** Pass to `OAuth2Client` (and `verifyRunNotice`) as `fetch`. Unique per cloud. */
|
|
111
|
+
readonly fetch: typeof fetch;
|
|
112
|
+
readonly issuer: string;
|
|
113
|
+
readonly clientId: string;
|
|
114
|
+
/** Every runtime request, in order. */
|
|
115
|
+
readonly calls: FakeCall[];
|
|
116
|
+
/** Every directory request, in order. */
|
|
117
|
+
readonly directoryCalls: FakeDirectoryCall[];
|
|
118
|
+
/** Every run-notice attempt, in order. */
|
|
119
|
+
readonly notices: FakeNotice[];
|
|
120
|
+
/** What responders threw. */
|
|
121
|
+
readonly responderErrors: unknown[];
|
|
122
|
+
readonly runs: FakeRuns;
|
|
123
|
+
readonly providers: {
|
|
124
|
+
define(provider: string, definition: FakeProvider): void;
|
|
125
|
+
};
|
|
126
|
+
private readonly options;
|
|
127
|
+
private readonly clock;
|
|
128
|
+
private readonly users;
|
|
129
|
+
private readonly handles;
|
|
130
|
+
private readonly allRuns;
|
|
131
|
+
private readonly providerDefs;
|
|
132
|
+
private intercepts;
|
|
133
|
+
private readonly gates;
|
|
134
|
+
private responder;
|
|
135
|
+
private readonly key;
|
|
136
|
+
private readonly runNotices;
|
|
137
|
+
private readonly host;
|
|
138
|
+
/** Superseded refresh tokens → owner, for `refresh_token_reused`. */
|
|
139
|
+
private readonly superseded;
|
|
140
|
+
private tokenSerial;
|
|
141
|
+
private refreshSerial;
|
|
142
|
+
private runSerial;
|
|
143
|
+
constructor(options: FakeCloudOptions);
|
|
144
|
+
/** A `FakeError` envelope for intercepts, `failNext` and provider handlers. `retryable` defaults to `status === 503`. */
|
|
145
|
+
static error(input: {
|
|
146
|
+
status: number;
|
|
147
|
+
code: string;
|
|
148
|
+
message?: string;
|
|
149
|
+
origin?: string;
|
|
150
|
+
retryable?: boolean;
|
|
151
|
+
details?: unknown;
|
|
152
|
+
param?: string;
|
|
153
|
+
}): FakeError;
|
|
154
|
+
/** The `directory.token` subset of `directoryCalls`. */
|
|
155
|
+
get refreshes(): FakeDirectoryCall[];
|
|
156
|
+
/** That user's handle, created on first use. */
|
|
157
|
+
user(userId: string): FakeUser;
|
|
158
|
+
/**
|
|
159
|
+
* Make `userId`'s grant active and save a stored connection for them in `store`, with its access token expired so
|
|
160
|
+
* the first call refreshes through the directory. Default scopes: `crtr:llm`, `crtr:act`.
|
|
161
|
+
*/
|
|
162
|
+
connect(store: ConnectionStore, userId: string, options?: {
|
|
163
|
+
scopes?: FakeScope[];
|
|
164
|
+
dependencies?: Record<string, ProviderDependency>;
|
|
165
|
+
}): Promise<FakeUser>;
|
|
166
|
+
private activateState;
|
|
167
|
+
/**
|
|
168
|
+
* Make `userId`'s grant active with no stored connection, for an app that mints a per-user runtime token through
|
|
169
|
+
* the directory's `client_credentials` grant. Default scopes: `crtr:llm`, `crtr:act`.
|
|
170
|
+
*/
|
|
171
|
+
activate(userId: string, options?: {
|
|
172
|
+
scopes?: FakeScope[];
|
|
173
|
+
dependencies?: Record<string, ProviderDependency>;
|
|
174
|
+
}): FakeUser;
|
|
175
|
+
/**
|
|
176
|
+
* A real `Crouter` on `userId`'s runtime with a fresh access token and no refresh: refusals never reach it. For
|
|
177
|
+
* code whose production signature takes a `Crouter`; an app that goes through `OAuth2Client` tests through it.
|
|
178
|
+
*/
|
|
179
|
+
crouter(userId: string): Crouter;
|
|
180
|
+
/** Run `fn` before `op`. `times` defaults to Infinity. `user` filters runtime operations and `directory.token`. */
|
|
181
|
+
intercept(op: FakeInterceptOp, fn: Intercept, options?: {
|
|
182
|
+
user?: string;
|
|
183
|
+
times?: number;
|
|
184
|
+
}): () => void;
|
|
185
|
+
/** Answer the next `times` (default 1) matching requests with `answer`. */
|
|
186
|
+
failNext(op: FakeInterceptOp, answer: FakeAnswer, options?: {
|
|
187
|
+
user?: string;
|
|
188
|
+
times?: number;
|
|
189
|
+
}): void;
|
|
190
|
+
/** Hold every matching request until `release()`, which frees them all and removes the gate. */
|
|
191
|
+
gate(op: FakeInterceptOp, options?: {
|
|
192
|
+
user?: string;
|
|
193
|
+
}): () => void;
|
|
194
|
+
/** Clear runs, calls, intercepts (gates are released), responders, memory, idempotency keys and notices. Grants
|
|
195
|
+
* and refresh-token chains stay, so stored connections remain valid. */
|
|
196
|
+
reset(): void;
|
|
197
|
+
/** The exact error the SDK raises when the directory refuses a refresh with `code` (`refusalOf(e)` is set). */
|
|
198
|
+
refusalError(code: FakeRefusalCode): Promise<unknown>;
|
|
199
|
+
private state;
|
|
200
|
+
private runtimeUrlFor;
|
|
201
|
+
private isRuntimeOrigin;
|
|
202
|
+
private headers;
|
|
203
|
+
private route;
|
|
204
|
+
private runIntercepts;
|
|
205
|
+
private directory;
|
|
206
|
+
/** `grant_type=client_credentials` + `sub`: the directory's per-user runtime-token mint. The client assertion is not verified. */
|
|
207
|
+
private mint;
|
|
208
|
+
private refresh;
|
|
209
|
+
private newRefreshToken;
|
|
210
|
+
private accessToken;
|
|
211
|
+
private runtime;
|
|
212
|
+
private ownedRun;
|
|
213
|
+
private respond;
|
|
214
|
+
private idempotencyKey;
|
|
215
|
+
private handle;
|
|
216
|
+
private grantGet;
|
|
217
|
+
private runStart;
|
|
218
|
+
/** An isolated run's root folder on a guest (`appSpace(app).nodes/<run id>`, apps root `/apps`). */
|
|
219
|
+
private isolatedRoot;
|
|
220
|
+
private runMessage;
|
|
221
|
+
private question;
|
|
222
|
+
private memoryStore;
|
|
223
|
+
private memoryVisible;
|
|
224
|
+
private memoryList;
|
|
225
|
+
private providerEntry;
|
|
226
|
+
private providerTools;
|
|
227
|
+
private providerCall;
|
|
228
|
+
}
|