@tangle-network/agent-runtime 0.69.0 → 0.70.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.
Files changed (78) hide show
  1. package/README.md +81 -13
  2. package/dist/agent.d.ts +4 -5
  3. package/dist/agent.js +3 -6
  4. package/dist/agent.js.map +1 -1
  5. package/dist/chunk-BYZCXQHF.js +474 -0
  6. package/dist/chunk-BYZCXQHF.js.map +1 -0
  7. package/dist/{chunk-G6U3GVK2.js → chunk-EDCVUZZC.js} +2 -2
  8. package/dist/{chunk-RTDI2DHD.js → chunk-L5ZFBVT6.js} +6 -6
  9. package/dist/chunk-L5ZFBVT6.js.map +1 -0
  10. package/dist/{chunk-NLRA6434.js → chunk-QXWGSDAQ.js} +716 -535
  11. package/dist/chunk-QXWGSDAQ.js.map +1 -0
  12. package/dist/{chunk-QZ6FA5LM.js → chunk-ZNQVMMR5.js} +3 -3
  13. package/dist/{coordination-Curpzeyc.d.ts → coordination-C7WxwHXq.d.ts} +8 -1
  14. package/dist/{delegates-CLFNAKyi.d.ts → delegates-DqAgo32T.d.ts} +105 -10
  15. package/dist/{improvement-adapter-BC4HhuAR.d.ts → improvement-adapter-BVuMragr.d.ts} +1 -1
  16. package/dist/index.d.ts +439 -100
  17. package/dist/index.js +583 -125
  18. package/dist/index.js.map +1 -1
  19. package/dist/intelligence.d.ts +2 -3
  20. package/dist/{loop-runner-bin-B6dzNZC8.d.ts → loop-runner-bin-B0NeLTRd.d.ts} +4 -4
  21. package/dist/loop-runner-bin.d.ts +7 -10
  22. package/dist/loop-runner-bin.js +4 -7
  23. package/dist/loops.d.ts +3149 -16
  24. package/dist/loops.js +34 -63
  25. package/dist/mcp/bin.js +14 -16
  26. package/dist/mcp/bin.js.map +1 -1
  27. package/dist/mcp/index.d.ts +8 -12
  28. package/dist/mcp/index.js +16 -19
  29. package/dist/mcp/index.js.map +1 -1
  30. package/dist/{openai-tools-CA2N3-Ak.d.ts → openai-tools-DPx9Gzvn.d.ts} +1 -1
  31. package/dist/profiles.d.ts +94 -6
  32. package/dist/profiles.js +320 -9
  33. package/dist/profiles.js.map +1 -1
  34. package/dist/{router-client-30Y_pca8.d.ts → router-client-C7kp_ECN.d.ts} +37 -1
  35. package/dist/{substrate-CUgk7F7s.d.ts → substrate-BoRXgvka.d.ts} +52 -1
  36. package/dist/{types-Crxftafi.d.ts → types-BYa2ZOAx.d.ts} +83 -2
  37. package/dist/{types-p8dWBIXL.d.ts → types-DJu6TBGp.d.ts} +2 -16
  38. package/dist/{worktree-fanout-DUiKPApb.d.ts → worktree-fanout-gNfl0Byj.d.ts} +9 -37
  39. package/package.json +9 -39
  40. package/dist/analyst-loop.d.ts +0 -52
  41. package/dist/analyst-loop.js +0 -11
  42. package/dist/analyst-loop.js.map +0 -1
  43. package/dist/audit.d.ts +0 -93
  44. package/dist/audit.js +0 -312
  45. package/dist/audit.js.map +0 -1
  46. package/dist/chunk-4B6U4CVQ.js +0 -15
  47. package/dist/chunk-4B6U4CVQ.js.map +0 -1
  48. package/dist/chunk-K4FQSEXQ.js +0 -214
  49. package/dist/chunk-K4FQSEXQ.js.map +0 -1
  50. package/dist/chunk-NLRA6434.js.map +0 -1
  51. package/dist/chunk-O2UPHN7X.js +0 -114
  52. package/dist/chunk-O2UPHN7X.js.map +0 -1
  53. package/dist/chunk-P5OKDSLB.js +0 -580
  54. package/dist/chunk-P5OKDSLB.js.map +0 -1
  55. package/dist/chunk-RTDI2DHD.js.map +0 -1
  56. package/dist/chunk-VLF5RHEQ.js +0 -143
  57. package/dist/chunk-VLF5RHEQ.js.map +0 -1
  58. package/dist/coder-2leJPOvC.d.ts +0 -52
  59. package/dist/improvement.d.ts +0 -208
  60. package/dist/improvement.js +0 -343
  61. package/dist/improvement.js.map +0 -1
  62. package/dist/local-harness-BE_h8szs.d.ts +0 -93
  63. package/dist/platform.d.ts +0 -255
  64. package/dist/platform.js +0 -229
  65. package/dist/platform.js.map +0 -1
  66. package/dist/run-loop-D3PwlG7J.d.ts +0 -112
  67. package/dist/runtime-hooks-C7JwKb9E.d.ts +0 -70
  68. package/dist/runtime.d.ts +0 -3120
  69. package/dist/runtime.js +0 -263
  70. package/dist/runtime.js.map +0 -1
  71. package/dist/topology.d.ts +0 -126
  72. package/dist/topology.js +0 -333
  73. package/dist/topology.js.map +0 -1
  74. package/dist/workflow.d.ts +0 -551
  75. package/dist/workflow.js +0 -1781
  76. package/dist/workflow.js.map +0 -1
  77. /package/dist/{chunk-G6U3GVK2.js.map → chunk-EDCVUZZC.js.map} +0 -0
  78. /package/dist/{chunk-QZ6FA5LM.js.map → chunk-ZNQVMMR5.js.map} +0 -0
@@ -1,255 +0,0 @@
1
- /**
2
- * Server-side client for the Tangle platform's cross-site SSO bridge.
3
- *
4
- * Consumer apps (gtm-agent, tax-agent, legal-agent, creative-agent, …)
5
- * use this to:
6
- * 1. Build an /authorize URL that lands the user on id.tangle.tools
7
- * and brings them back with a single-use code.
8
- * 2. Exchange that code for an API key + the user's identity.
9
- *
10
- * The platform endpoint contract is documented in
11
- * `products/platform/api/src/routes/cross-site.ts`. This client only
12
- * speaks HTTP — no SDK weight, no transitive deps.
13
- */
14
- interface PlatformAuthClientOptions {
15
- /** Platform base URL, e.g. `https://id.tangle.tools`. */
16
- baseUrl: string;
17
- /** App id as registered in the platform's TRUSTED_APPS registry. */
18
- appId: string;
19
- /** Override the global fetch (useful for tests + edge runtimes). */
20
- fetchImpl?: typeof fetch;
21
- }
22
- interface AuthorizeUrlOptions {
23
- /** Required CSRF token; the consumer verifies it on the callback. */
24
- state: string;
25
- /**
26
- * Final redirect URI. Must be one of the URIs registered for `appId`
27
- * on the platform. Omit to use the first registered URI.
28
- */
29
- redirectUri?: string;
30
- /** Force the login screen even if a session is already active. */
31
- prompt?: 'login';
32
- /** Pre-fill the email field on the login screen. */
33
- email?: string;
34
- }
35
- interface ExchangeCodeResult {
36
- apiKey: string;
37
- user: {
38
- id: string;
39
- email: string;
40
- name?: string;
41
- };
42
- plan: {
43
- tier: string;
44
- };
45
- }
46
- declare class PlatformAuthError extends Error {
47
- readonly status: number;
48
- readonly body: unknown;
49
- constructor(message: string, status: number, body: unknown);
50
- }
51
- declare class PlatformAuthClient {
52
- private readonly baseUrl;
53
- private readonly appId;
54
- private readonly fetchImpl;
55
- constructor(options: PlatformAuthClientOptions);
56
- /**
57
- * Build the URL the user is redirected to in order to start SSO.
58
- * The platform redirects back to one of `appId`'s registered
59
- * `redirectUris` with `?code=...&app=...&state=...`.
60
- */
61
- authorizeUrl(options: AuthorizeUrlOptions): string;
62
- /**
63
- * Exchange a single-use auth code (delivered to the consumer's
64
- * callback by the platform) for an API key + the user's identity.
65
- * Codes are single-use and expire ~5 minutes after issue.
66
- */
67
- exchange(code: string): Promise<ExchangeCodeResult>;
68
- }
69
-
70
- /**
71
- * Server-side client for the Tangle platform's integration hub
72
- * (`/v1/hub/*`). Consumer apps use this instead of rolling their own
73
- * OAuth + connection tables.
74
- *
75
- * Auth: the caller supplies a bearer (either the user's API key from
76
- * cross-site exchange, or a platform service token) on construction.
77
- *
78
- * Endpoint contract (authoritative): the platform's `src/lib/hub-contract.ts`
79
- * + `src/routes/hub.ts`. The platform wraps every response in
80
- * `{ success, data }`; non-2xx or `success:false` surfaces as `PlatformHubError`
81
- * carrying the real upstream status.
82
- */
83
- interface PlatformHubClientOptions {
84
- /** Platform base URL, e.g. `https://id.tangle.tools`. */
85
- baseUrl: string;
86
- /** Bearer credential — user API key or service token. */
87
- bearer: string;
88
- /** Override fetch (tests + edge runtimes). */
89
- fetchImpl?: typeof fetch;
90
- }
91
- /** A live integration connection, as returned by `/v1/hub/connections`. */
92
- interface PlatformConnection {
93
- id: string;
94
- providerId: string;
95
- displayName: string;
96
- accountDisplay: string | null;
97
- scopes: string[];
98
- status: 'active' | 'revoked' | 'unhealthy' | 'reconnect_required' | (string & {});
99
- health: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {});
100
- createdAt: string;
101
- updatedAt: string;
102
- lastUsedAt: string | null;
103
- }
104
- /** A connectable provider in the catalog (`/v1/hub/providers`). */
105
- interface PlatformCatalogProvider {
106
- providerId: string;
107
- title?: string;
108
- authKind?: string;
109
- category?: string;
110
- scopes?: string[];
111
- capabilityCount?: number;
112
- native?: boolean;
113
- /** Whether the OAuth app's credentials are wired — the UI offers Connect
114
- * only when true. */
115
- configured?: boolean;
116
- [k: string]: unknown;
117
- }
118
- interface CatalogResult {
119
- providers: PlatformCatalogProvider[];
120
- /** Count of substrate-bundled connectors behind the catalog. */
121
- substrateBundled?: number;
122
- [k: string]: unknown;
123
- }
124
- interface StartAuthInput {
125
- /** The provider to connect (goes in the URL path). */
126
- providerId: string;
127
- /** Accepted for interface compatibility; the platform's start endpoint is
128
- * provider-level and does not consume a connector id. */
129
- connectorId?: string;
130
- /** Where the platform redirects the user back to after OAuth. */
131
- returnUrl: string;
132
- /** Accepted for interface compatibility; not consumed by the start endpoint. */
133
- requestedScopes?: string[];
134
- /** CLI flow flag — affects the platform's post-auth redirect handling. */
135
- cli?: boolean;
136
- }
137
- interface StartAuthResult {
138
- /** The URL to send the user to. Normalized across the platform's two start
139
- * branches: github returns `authorizationUrl`, substrate returns
140
- * `redirectUrl`. */
141
- authorizationUrl: string;
142
- state: string;
143
- expiresAt?: string;
144
- scopes?: string[];
145
- }
146
- interface ConnectionHealth {
147
- status: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {});
148
- checkedAt: string;
149
- error?: {
150
- code: string;
151
- message: string;
152
- };
153
- }
154
- interface ConnectionHealthResult {
155
- connection: PlatformConnection;
156
- health: ConnectionHealth;
157
- }
158
- /** Last-known health for a connection, derived from the connection row. */
159
- interface HealthCheck {
160
- connectionId: string;
161
- providerId: string;
162
- /** Mirrors `PlatformConnection.health`. */
163
- status: ConnectionHealth['status'];
164
- checkedAt?: string;
165
- }
166
- interface MintTokenInput {
167
- /** The hub action the token authorizes (e.g. `slack.chat.postMessage`). */
168
- actionPath: string;
169
- /** Bind to a specific connection, or … */
170
- connectionId?: string;
171
- /** … resolve the connection by provider for the calling user. */
172
- provider?: string;
173
- }
174
- interface MintTokenResult {
175
- tokenId: string;
176
- token: string;
177
- expiresAt: string;
178
- }
179
- interface ExecInput {
180
- /** The hub action path to execute. */
181
- path: string;
182
- input?: unknown;
183
- connectionId?: string;
184
- }
185
- interface PlatformHubStatus {
186
- contract?: unknown;
187
- principal: {
188
- kind: string;
189
- userId: string;
190
- [k: string]: unknown;
191
- };
192
- connections: {
193
- connectedProviderCount: number;
194
- unhealthyProviderCount: number;
195
- };
196
- }
197
- declare class PlatformHubError extends Error {
198
- readonly status: number;
199
- readonly code: string | undefined;
200
- readonly body: unknown;
201
- constructor(message: string, status: number, code: string | undefined, body: unknown);
202
- }
203
- declare class PlatformHubClient {
204
- private readonly baseUrl;
205
- private readonly bearer;
206
- private readonly fetchImpl;
207
- constructor(options: PlatformHubClientOptions);
208
- /** GET /v1/hub/providers — the connectable provider catalog. */
209
- catalog(): Promise<CatalogResult>;
210
- /** GET /v1/hub/connections — the calling user's live connections. */
211
- listConnections(): Promise<PlatformConnection[]>;
212
- /** DELETE /v1/hub/connections/:connectionId — revoke + disable a connection. */
213
- revokeConnection(connectionId: string): Promise<{
214
- connection: PlatformConnection;
215
- }>;
216
- /**
217
- * POST /v1/hub/connections/:provider/start — begin OAuth/grant. The provider
218
- * is taken from the URL; the body carries `returnUrl` (+ `cli`). The platform's
219
- * two start branches name the URL field differently (github → `authorizationUrl`,
220
- * substrate → `redirectUrl`); this normalizes to `authorizationUrl`.
221
- */
222
- startAuth(input: StartAuthInput): Promise<StartAuthResult>;
223
- /**
224
- * Last-known health for every connection. The platform has no global
225
- * healthcheck listing — health rides on each connection row — so this derives
226
- * the list from `listConnections()` (one request, no extra round-trips).
227
- */
228
- listHealthchecks(): Promise<HealthCheck[]>;
229
- /**
230
- * POST /v1/hub/connections/:connectionId/health — trigger a fresh health
231
- * probe for one connection and return its updated state.
232
- */
233
- checkConnectionHealth(connectionId: string): Promise<ConnectionHealthResult>;
234
- /**
235
- * Trigger a fresh health probe across all of the user's connections. The
236
- * platform exposes health per-connection only, so this fans out over
237
- * `listConnections()`. `scheduled` is the number of probes dispatched.
238
- */
239
- runHealthchecks(): Promise<{
240
- scheduled: number;
241
- }>;
242
- /** GET /v1/hub/status — principal + aggregate connection counts. */
243
- status(): Promise<PlatformHubStatus>;
244
- /**
245
- * POST /v1/hub/tokens — mint a short-lived, action-scoped capability token a
246
- * sandbox can use to invoke one hub action on the user's behalf without
247
- * seeing the underlying provider credential.
248
- */
249
- mintToken(input: MintTokenInput): Promise<MintTokenResult>;
250
- /** POST /v1/hub/exec — execute a hub action and return its result. */
251
- exec(input: ExecInput): Promise<unknown>;
252
- private request;
253
- }
254
-
255
- export { type AuthorizeUrlOptions, type CatalogResult, type ConnectionHealth, type ConnectionHealthResult, type ExchangeCodeResult, type ExecInput, type HealthCheck, type MintTokenInput, type MintTokenResult, PlatformAuthClient, type PlatformAuthClientOptions, PlatformAuthError, type PlatformCatalogProvider, type PlatformConnection, PlatformHubClient, type PlatformHubClientOptions, PlatformHubError, type PlatformHubStatus, type StartAuthInput, type StartAuthResult };
package/dist/platform.js DELETED
@@ -1,229 +0,0 @@
1
- import "./chunk-DGUM43GV.js";
2
-
3
- // src/platform/auth.ts
4
- var PlatformAuthError = class extends Error {
5
- constructor(message, status, body) {
6
- super(message);
7
- this.status = status;
8
- this.body = body;
9
- this.name = "PlatformAuthError";
10
- }
11
- status;
12
- body;
13
- };
14
- var PlatformAuthClient = class {
15
- baseUrl;
16
- appId;
17
- fetchImpl;
18
- constructor(options) {
19
- if (!options.baseUrl) throw new Error("PlatformAuthClient: baseUrl is required");
20
- if (!options.appId) throw new Error("PlatformAuthClient: appId is required");
21
- this.baseUrl = options.baseUrl.replace(/\/+$/, "");
22
- this.appId = options.appId;
23
- this.fetchImpl = options.fetchImpl ?? ((url, init) => fetch(url, init));
24
- }
25
- /**
26
- * Build the URL the user is redirected to in order to start SSO.
27
- * The platform redirects back to one of `appId`'s registered
28
- * `redirectUris` with `?code=...&app=...&state=...`.
29
- */
30
- authorizeUrl(options) {
31
- if (!options.state) {
32
- throw new Error("PlatformAuthClient.authorizeUrl: state is required for CSRF");
33
- }
34
- const url = new URL("/cross-site/authorize", this.baseUrl);
35
- url.searchParams.set("app", this.appId);
36
- url.searchParams.set("state", options.state);
37
- if (options.redirectUri) url.searchParams.set("redirect", options.redirectUri);
38
- if (options.prompt) url.searchParams.set("prompt", options.prompt);
39
- if (options.email) url.searchParams.set("email", options.email);
40
- return url.toString();
41
- }
42
- /**
43
- * Exchange a single-use auth code (delivered to the consumer's
44
- * callback by the platform) for an API key + the user's identity.
45
- * Codes are single-use and expire ~5 minutes after issue.
46
- */
47
- async exchange(code) {
48
- if (!code) throw new Error("PlatformAuthClient.exchange: code is required");
49
- const res = await this.fetchImpl(`${this.baseUrl}/cross-site/exchange`, {
50
- method: "POST",
51
- headers: { "content-type": "application/json" },
52
- body: JSON.stringify({ code, app: this.appId })
53
- });
54
- const body = await res.json().catch(() => null);
55
- if (!res.ok) {
56
- const message = body && typeof body === "object" && "error" in body && typeof body.error === "string" ? body.error : `Platform exchange failed (${res.status})`;
57
- throw new PlatformAuthError(message, res.status, body);
58
- }
59
- const result = body;
60
- if (!result.apiKey || !result.user?.id) {
61
- throw new PlatformAuthError(
62
- "Platform exchange response is missing apiKey or user",
63
- res.status,
64
- body
65
- );
66
- }
67
- return result;
68
- }
69
- };
70
-
71
- // src/platform/integrations.ts
72
- var PlatformHubError = class extends Error {
73
- constructor(message, status, code, body) {
74
- super(message);
75
- this.status = status;
76
- this.code = code;
77
- this.body = body;
78
- this.name = "PlatformHubError";
79
- }
80
- status;
81
- code;
82
- body;
83
- };
84
- var PlatformHubClient = class {
85
- baseUrl;
86
- bearer;
87
- fetchImpl;
88
- constructor(options) {
89
- if (!options.baseUrl) throw new Error("PlatformHubClient: baseUrl is required");
90
- if (!options.bearer) throw new Error("PlatformHubClient: bearer is required");
91
- this.baseUrl = options.baseUrl.replace(/\/+$/, "");
92
- this.bearer = options.bearer;
93
- this.fetchImpl = options.fetchImpl ?? ((url, init) => fetch(url, init));
94
- }
95
- /** GET /v1/hub/providers — the connectable provider catalog. */
96
- catalog() {
97
- return this.request("GET", "/v1/hub/providers");
98
- }
99
- /** GET /v1/hub/connections — the calling user's live connections. */
100
- async listConnections() {
101
- const data = await this.request(
102
- "GET",
103
- "/v1/hub/connections"
104
- );
105
- return data.connections;
106
- }
107
- /** DELETE /v1/hub/connections/:connectionId — revoke + disable a connection. */
108
- revokeConnection(connectionId) {
109
- return this.request("DELETE", `/v1/hub/connections/${encodeURIComponent(connectionId)}`);
110
- }
111
- /**
112
- * POST /v1/hub/connections/:provider/start — begin OAuth/grant. The provider
113
- * is taken from the URL; the body carries `returnUrl` (+ `cli`). The platform's
114
- * two start branches name the URL field differently (github → `authorizationUrl`,
115
- * substrate → `redirectUrl`); this normalizes to `authorizationUrl`.
116
- */
117
- async startAuth(input) {
118
- const body = { returnUrl: input.returnUrl };
119
- if (input.cli !== void 0) body.cli = input.cli;
120
- const data = await this.request("POST", `/v1/hub/connections/${encodeURIComponent(input.providerId)}/start`, body);
121
- const authorizationUrl = data.authorizationUrl ?? data.redirectUrl;
122
- if (!authorizationUrl) {
123
- throw new PlatformHubError(
124
- "Platform hub start response missing an authorization URL",
125
- 502,
126
- "HUB_INVALID_START_RESPONSE",
127
- data
128
- );
129
- }
130
- return { authorizationUrl, state: data.state, expiresAt: data.expiresAt, scopes: data.scopes };
131
- }
132
- /**
133
- * Last-known health for every connection. The platform has no global
134
- * healthcheck listing — health rides on each connection row — so this derives
135
- * the list from `listConnections()` (one request, no extra round-trips).
136
- */
137
- async listHealthchecks() {
138
- const connections = await this.listConnections();
139
- return connections.map((c) => ({
140
- connectionId: c.id,
141
- providerId: c.providerId,
142
- status: c.health,
143
- checkedAt: c.updatedAt
144
- }));
145
- }
146
- /**
147
- * POST /v1/hub/connections/:connectionId/health — trigger a fresh health
148
- * probe for one connection and return its updated state.
149
- */
150
- checkConnectionHealth(connectionId) {
151
- return this.request("POST", `/v1/hub/connections/${encodeURIComponent(connectionId)}/health`);
152
- }
153
- /**
154
- * Trigger a fresh health probe across all of the user's connections. The
155
- * platform exposes health per-connection only, so this fans out over
156
- * `listConnections()`. `scheduled` is the number of probes dispatched.
157
- */
158
- async runHealthchecks() {
159
- const connections = await this.listConnections();
160
- await Promise.allSettled(connections.map((c) => this.checkConnectionHealth(c.id)));
161
- return { scheduled: connections.length };
162
- }
163
- /** GET /v1/hub/status — principal + aggregate connection counts. */
164
- status() {
165
- return this.request("GET", "/v1/hub/status");
166
- }
167
- /**
168
- * POST /v1/hub/tokens — mint a short-lived, action-scoped capability token a
169
- * sandbox can use to invoke one hub action on the user's behalf without
170
- * seeing the underlying provider credential.
171
- */
172
- mintToken(input) {
173
- return this.request("POST", "/v1/hub/tokens", input);
174
- }
175
- /** POST /v1/hub/exec — execute a hub action and return its result. */
176
- async exec(input) {
177
- const data = await this.request("POST", "/v1/hub/exec", input);
178
- return data.result;
179
- }
180
- async request(method, path, body) {
181
- const headers = {
182
- authorization: `Bearer ${this.bearer}`,
183
- accept: "application/json"
184
- };
185
- if (body !== void 0) headers["content-type"] = "application/json";
186
- const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
187
- method,
188
- headers,
189
- body: body !== void 0 ? JSON.stringify(body) : void 0
190
- });
191
- const text = await res.text();
192
- let parsed = null;
193
- if (text) {
194
- try {
195
- parsed = JSON.parse(text);
196
- } catch {
197
- }
198
- }
199
- if (!res.ok || parsed && parsed.success === false) {
200
- const code = parsed?.error && typeof parsed.error === "object" ? parsed.error.code : void 0;
201
- const message = parsed?.error && typeof parsed.error === "object" && parsed.error.message || (typeof parsed?.error === "string" ? parsed.error : `Platform hub error (${res.status})`);
202
- throw new PlatformHubError(message, res.status, code, parsed ?? text);
203
- }
204
- if (!parsed) {
205
- throw new PlatformHubError(
206
- `Platform hub returned non-JSON success (${res.status})`,
207
- res.status,
208
- void 0,
209
- text
210
- );
211
- }
212
- if (parsed.data === void 0) {
213
- throw new PlatformHubError(
214
- "Platform hub envelope missing `data`",
215
- res.status,
216
- void 0,
217
- parsed
218
- );
219
- }
220
- return parsed.data;
221
- }
222
- };
223
- export {
224
- PlatformAuthClient,
225
- PlatformAuthError,
226
- PlatformHubClient,
227
- PlatformHubError
228
- };
229
- //# sourceMappingURL=platform.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/platform/auth.ts","../src/platform/integrations.ts"],"sourcesContent":["/**\n * Server-side client for the Tangle platform's cross-site SSO bridge.\n *\n * Consumer apps (gtm-agent, tax-agent, legal-agent, creative-agent, …)\n * use this to:\n * 1. Build an /authorize URL that lands the user on id.tangle.tools\n * and brings them back with a single-use code.\n * 2. Exchange that code for an API key + the user's identity.\n *\n * The platform endpoint contract is documented in\n * `products/platform/api/src/routes/cross-site.ts`. This client only\n * speaks HTTP — no SDK weight, no transitive deps.\n */\n\nexport interface PlatformAuthClientOptions {\n /** Platform base URL, e.g. `https://id.tangle.tools`. */\n baseUrl: string\n /** App id as registered in the platform's TRUSTED_APPS registry. */\n appId: string\n /** Override the global fetch (useful for tests + edge runtimes). */\n fetchImpl?: typeof fetch\n}\n\nexport interface AuthorizeUrlOptions {\n /** Required CSRF token; the consumer verifies it on the callback. */\n state: string\n /**\n * Final redirect URI. Must be one of the URIs registered for `appId`\n * on the platform. Omit to use the first registered URI.\n */\n redirectUri?: string\n /** Force the login screen even if a session is already active. */\n prompt?: 'login'\n /** Pre-fill the email field on the login screen. */\n email?: string\n}\n\nexport interface ExchangeCodeResult {\n apiKey: string\n user: {\n id: string\n email: string\n name?: string\n }\n plan: {\n tier: string\n }\n}\n\nexport class PlatformAuthError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly body: unknown,\n ) {\n super(message)\n this.name = 'PlatformAuthError'\n }\n}\n\nexport class PlatformAuthClient {\n private readonly baseUrl: string\n private readonly appId: string\n private readonly fetchImpl: typeof fetch\n\n constructor(options: PlatformAuthClientOptions) {\n if (!options.baseUrl) throw new Error('PlatformAuthClient: baseUrl is required')\n if (!options.appId) throw new Error('PlatformAuthClient: appId is required')\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '')\n this.appId = options.appId\n this.fetchImpl =\n options.fetchImpl ??\n ((url: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => fetch(url, init))\n }\n\n /**\n * Build the URL the user is redirected to in order to start SSO.\n * The platform redirects back to one of `appId`'s registered\n * `redirectUris` with `?code=...&app=...&state=...`.\n */\n authorizeUrl(options: AuthorizeUrlOptions): string {\n if (!options.state) {\n throw new Error('PlatformAuthClient.authorizeUrl: state is required for CSRF')\n }\n const url = new URL('/cross-site/authorize', this.baseUrl)\n url.searchParams.set('app', this.appId)\n url.searchParams.set('state', options.state)\n if (options.redirectUri) url.searchParams.set('redirect', options.redirectUri)\n if (options.prompt) url.searchParams.set('prompt', options.prompt)\n if (options.email) url.searchParams.set('email', options.email)\n return url.toString()\n }\n\n /**\n * Exchange a single-use auth code (delivered to the consumer's\n * callback by the platform) for an API key + the user's identity.\n * Codes are single-use and expire ~5 minutes after issue.\n */\n async exchange(code: string): Promise<ExchangeCodeResult> {\n if (!code) throw new Error('PlatformAuthClient.exchange: code is required')\n const res = await this.fetchImpl(`${this.baseUrl}/cross-site/exchange`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ code, app: this.appId }),\n })\n const body = await res.json().catch(() => null)\n if (!res.ok) {\n const message =\n body && typeof body === 'object' && 'error' in body && typeof body.error === 'string'\n ? body.error\n : `Platform exchange failed (${res.status})`\n throw new PlatformAuthError(message, res.status, body)\n }\n const result = body as Partial<ExchangeCodeResult>\n if (!result.apiKey || !result.user?.id) {\n throw new PlatformAuthError(\n 'Platform exchange response is missing apiKey or user',\n res.status,\n body,\n )\n }\n return result as ExchangeCodeResult\n }\n}\n","/**\n * Server-side client for the Tangle platform's integration hub\n * (`/v1/hub/*`). Consumer apps use this instead of rolling their own\n * OAuth + connection tables.\n *\n * Auth: the caller supplies a bearer (either the user's API key from\n * cross-site exchange, or a platform service token) on construction.\n *\n * Endpoint contract (authoritative): the platform's `src/lib/hub-contract.ts`\n * + `src/routes/hub.ts`. The platform wraps every response in\n * `{ success, data }`; non-2xx or `success:false` surfaces as `PlatformHubError`\n * carrying the real upstream status.\n */\n\nexport interface PlatformHubClientOptions {\n /** Platform base URL, e.g. `https://id.tangle.tools`. */\n baseUrl: string\n /** Bearer credential — user API key or service token. */\n bearer: string\n /** Override fetch (tests + edge runtimes). */\n fetchImpl?: typeof fetch\n}\n\n/** A live integration connection, as returned by `/v1/hub/connections`. */\nexport interface PlatformConnection {\n id: string\n providerId: string\n displayName: string\n accountDisplay: string | null\n scopes: string[]\n status: 'active' | 'revoked' | 'unhealthy' | 'reconnect_required' | (string & {})\n health: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {})\n createdAt: string\n updatedAt: string\n lastUsedAt: string | null\n}\n\n/** A connectable provider in the catalog (`/v1/hub/providers`). */\nexport interface PlatformCatalogProvider {\n providerId: string\n title?: string\n authKind?: string\n category?: string\n scopes?: string[]\n capabilityCount?: number\n native?: boolean\n /** Whether the OAuth app's credentials are wired — the UI offers Connect\n * only when true. */\n configured?: boolean\n [k: string]: unknown\n}\n\nexport interface CatalogResult {\n providers: PlatformCatalogProvider[]\n /** Count of substrate-bundled connectors behind the catalog. */\n substrateBundled?: number\n [k: string]: unknown\n}\n\nexport interface StartAuthInput {\n /** The provider to connect (goes in the URL path). */\n providerId: string\n /** Accepted for interface compatibility; the platform's start endpoint is\n * provider-level and does not consume a connector id. */\n connectorId?: string\n /** Where the platform redirects the user back to after OAuth. */\n returnUrl: string\n /** Accepted for interface compatibility; not consumed by the start endpoint. */\n requestedScopes?: string[]\n /** CLI flow flag — affects the platform's post-auth redirect handling. */\n cli?: boolean\n}\n\nexport interface StartAuthResult {\n /** The URL to send the user to. Normalized across the platform's two start\n * branches: github returns `authorizationUrl`, substrate returns\n * `redirectUrl`. */\n authorizationUrl: string\n state: string\n expiresAt?: string\n scopes?: string[]\n}\n\nexport interface ConnectionHealth {\n status: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {})\n checkedAt: string\n error?: { code: string; message: string }\n}\n\nexport interface ConnectionHealthResult {\n connection: PlatformConnection\n health: ConnectionHealth\n}\n\n/** Last-known health for a connection, derived from the connection row. */\nexport interface HealthCheck {\n connectionId: string\n providerId: string\n /** Mirrors `PlatformConnection.health`. */\n status: ConnectionHealth['status']\n checkedAt?: string\n}\n\nexport interface MintTokenInput {\n /** The hub action the token authorizes (e.g. `slack.chat.postMessage`). */\n actionPath: string\n /** Bind to a specific connection, or … */\n connectionId?: string\n /** … resolve the connection by provider for the calling user. */\n provider?: string\n}\n\nexport interface MintTokenResult {\n tokenId: string\n token: string\n expiresAt: string\n}\n\nexport interface ExecInput {\n /** The hub action path to execute. */\n path: string\n input?: unknown\n connectionId?: string\n}\n\nexport interface PlatformHubStatus {\n contract?: unknown\n principal: { kind: string; userId: string; [k: string]: unknown }\n connections: { connectedProviderCount: number; unhealthyProviderCount: number }\n}\n\nexport class PlatformHubError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly code: string | undefined,\n public readonly body: unknown,\n ) {\n super(message)\n this.name = 'PlatformHubError'\n }\n}\n\ninterface PlatformEnvelope<T> {\n success: boolean\n data?: T\n error?: { code?: string; message?: string } | string\n}\n\nexport class PlatformHubClient {\n private readonly baseUrl: string\n private readonly bearer: string\n private readonly fetchImpl: typeof fetch\n\n constructor(options: PlatformHubClientOptions) {\n if (!options.baseUrl) throw new Error('PlatformHubClient: baseUrl is required')\n if (!options.bearer) throw new Error('PlatformHubClient: bearer is required')\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '')\n this.bearer = options.bearer\n this.fetchImpl =\n options.fetchImpl ??\n ((url: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => fetch(url, init))\n }\n\n /** GET /v1/hub/providers — the connectable provider catalog. */\n catalog(): Promise<CatalogResult> {\n return this.request('GET', '/v1/hub/providers')\n }\n\n /** GET /v1/hub/connections — the calling user's live connections. */\n async listConnections(): Promise<PlatformConnection[]> {\n const data = await this.request<{ connections: PlatformConnection[] }>(\n 'GET',\n '/v1/hub/connections',\n )\n return data.connections\n }\n\n /** DELETE /v1/hub/connections/:connectionId — revoke + disable a connection. */\n revokeConnection(connectionId: string): Promise<{ connection: PlatformConnection }> {\n return this.request('DELETE', `/v1/hub/connections/${encodeURIComponent(connectionId)}`)\n }\n\n /**\n * POST /v1/hub/connections/:provider/start — begin OAuth/grant. The provider\n * is taken from the URL; the body carries `returnUrl` (+ `cli`). The platform's\n * two start branches name the URL field differently (github → `authorizationUrl`,\n * substrate → `redirectUrl`); this normalizes to `authorizationUrl`.\n */\n async startAuth(input: StartAuthInput): Promise<StartAuthResult> {\n const body: { returnUrl: string; cli?: boolean } = { returnUrl: input.returnUrl }\n if (input.cli !== undefined) body.cli = input.cli\n const data = await this.request<{\n authorizationUrl?: string\n redirectUrl?: string\n state: string\n expiresAt?: string\n scopes?: string[]\n }>('POST', `/v1/hub/connections/${encodeURIComponent(input.providerId)}/start`, body)\n const authorizationUrl = data.authorizationUrl ?? data.redirectUrl\n if (!authorizationUrl) {\n throw new PlatformHubError(\n 'Platform hub start response missing an authorization URL',\n 502,\n 'HUB_INVALID_START_RESPONSE',\n data,\n )\n }\n return { authorizationUrl, state: data.state, expiresAt: data.expiresAt, scopes: data.scopes }\n }\n\n /**\n * Last-known health for every connection. The platform has no global\n * healthcheck listing — health rides on each connection row — so this derives\n * the list from `listConnections()` (one request, no extra round-trips).\n */\n async listHealthchecks(): Promise<HealthCheck[]> {\n const connections = await this.listConnections()\n return connections.map((c) => ({\n connectionId: c.id,\n providerId: c.providerId,\n status: c.health,\n checkedAt: c.updatedAt,\n }))\n }\n\n /**\n * POST /v1/hub/connections/:connectionId/health — trigger a fresh health\n * probe for one connection and return its updated state.\n */\n checkConnectionHealth(connectionId: string): Promise<ConnectionHealthResult> {\n return this.request('POST', `/v1/hub/connections/${encodeURIComponent(connectionId)}/health`)\n }\n\n /**\n * Trigger a fresh health probe across all of the user's connections. The\n * platform exposes health per-connection only, so this fans out over\n * `listConnections()`. `scheduled` is the number of probes dispatched.\n */\n async runHealthchecks(): Promise<{ scheduled: number }> {\n const connections = await this.listConnections()\n await Promise.allSettled(connections.map((c) => this.checkConnectionHealth(c.id)))\n return { scheduled: connections.length }\n }\n\n /** GET /v1/hub/status — principal + aggregate connection counts. */\n status(): Promise<PlatformHubStatus> {\n return this.request('GET', '/v1/hub/status')\n }\n\n /**\n * POST /v1/hub/tokens — mint a short-lived, action-scoped capability token a\n * sandbox can use to invoke one hub action on the user's behalf without\n * seeing the underlying provider credential.\n */\n mintToken(input: MintTokenInput): Promise<MintTokenResult> {\n return this.request('POST', '/v1/hub/tokens', input)\n }\n\n /** POST /v1/hub/exec — execute a hub action and return its result. */\n async exec(input: ExecInput): Promise<unknown> {\n const data = await this.request<{ result: unknown }>('POST', '/v1/hub/exec', input)\n return data.result\n }\n\n private async request<T>(\n method: 'GET' | 'POST' | 'DELETE' | 'PUT',\n path: string,\n body?: unknown,\n ): Promise<T> {\n const headers: Record<string, string> = {\n authorization: `Bearer ${this.bearer}`,\n accept: 'application/json',\n }\n if (body !== undefined) headers['content-type'] = 'application/json'\n\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n })\n const text = await res.text()\n let parsed: PlatformEnvelope<T> | null = null\n if (text) {\n try {\n parsed = JSON.parse(text)\n } catch {\n // fall through to error handling below\n }\n }\n if (!res.ok || (parsed && parsed.success === false)) {\n const code = parsed?.error && typeof parsed.error === 'object' ? parsed.error.code : undefined\n const message =\n (parsed?.error && typeof parsed.error === 'object' && parsed.error.message) ||\n (typeof parsed?.error === 'string' ? parsed.error : `Platform hub error (${res.status})`)\n throw new PlatformHubError(message, res.status, code, parsed ?? text)\n }\n if (!parsed) {\n throw new PlatformHubError(\n `Platform hub returned non-JSON success (${res.status})`,\n res.status,\n undefined,\n text,\n )\n }\n if (parsed.data === undefined) {\n throw new PlatformHubError(\n 'Platform hub envelope missing `data`',\n res.status,\n undefined,\n parsed,\n )\n }\n return parsed.data\n }\n}\n"],"mappings":";;;AAiDO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EAC3C,YACE,SACgB,QACA,MAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EALkB;AAAA,EACA;AAKpB;AAEO,IAAM,qBAAN,MAAyB;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAAoC;AAC9C,QAAI,CAAC,QAAQ,QAAS,OAAM,IAAI,MAAM,yCAAyC;AAC/E,QAAI,CAAC,QAAQ,MAAO,OAAM,IAAI,MAAM,uCAAuC;AAC3E,SAAK,UAAU,QAAQ,QAAQ,QAAQ,QAAQ,EAAE;AACjD,SAAK,QAAQ,QAAQ;AACrB,SAAK,YACH,QAAQ,cACP,CAAC,KAAkC,SAAuC,MAAM,KAAK,IAAI;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,SAAsC;AACjD,QAAI,CAAC,QAAQ,OAAO;AAClB,YAAM,IAAI,MAAM,6DAA6D;AAAA,IAC/E;AACA,UAAM,MAAM,IAAI,IAAI,yBAAyB,KAAK,OAAO;AACzD,QAAI,aAAa,IAAI,OAAO,KAAK,KAAK;AACtC,QAAI,aAAa,IAAI,SAAS,QAAQ,KAAK;AAC3C,QAAI,QAAQ,YAAa,KAAI,aAAa,IAAI,YAAY,QAAQ,WAAW;AAC7E,QAAI,QAAQ,OAAQ,KAAI,aAAa,IAAI,UAAU,QAAQ,MAAM;AACjE,QAAI,QAAQ,MAAO,KAAI,aAAa,IAAI,SAAS,QAAQ,KAAK;AAC9D,WAAO,IAAI,SAAS;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAAS,MAA2C;AACxD,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,+CAA+C;AAC1E,UAAM,MAAM,MAAM,KAAK,UAAU,GAAG,KAAK,OAAO,wBAAwB;AAAA,MACtE,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,MAAM,KAAK,KAAK,MAAM,CAAC;AAAA,IAChD,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI;AAC9C,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,UACJ,QAAQ,OAAO,SAAS,YAAY,WAAW,QAAQ,OAAO,KAAK,UAAU,WACzE,KAAK,QACL,6BAA6B,IAAI,MAAM;AAC7C,YAAM,IAAI,kBAAkB,SAAS,IAAI,QAAQ,IAAI;AAAA,IACvD;AACA,UAAM,SAAS;AACf,QAAI,CAAC,OAAO,UAAU,CAAC,OAAO,MAAM,IAAI;AACtC,YAAM,IAAI;AAAA,QACR;AAAA,QACA,IAAI;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;;;ACQO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1C,YACE,SACgB,QACA,MACA,MAChB;AACA,UAAM,OAAO;AAJG;AACA;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EANkB;AAAA,EACA;AAAA,EACA;AAKpB;AAQO,IAAM,oBAAN,MAAwB;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAAmC;AAC7C,QAAI,CAAC,QAAQ,QAAS,OAAM,IAAI,MAAM,wCAAwC;AAC9E,QAAI,CAAC,QAAQ,OAAQ,OAAM,IAAI,MAAM,uCAAuC;AAC5E,SAAK,UAAU,QAAQ,QAAQ,QAAQ,QAAQ,EAAE;AACjD,SAAK,SAAS,QAAQ;AACtB,SAAK,YACH,QAAQ,cACP,CAAC,KAAkC,SAAuC,MAAM,KAAK,IAAI;AAAA,EAC9F;AAAA;AAAA,EAGA,UAAkC;AAChC,WAAO,KAAK,QAAQ,OAAO,mBAAmB;AAAA,EAChD;AAAA;AAAA,EAGA,MAAM,kBAAiD;AACrD,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,MACA;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,iBAAiB,cAAmE;AAClF,WAAO,KAAK,QAAQ,UAAU,uBAAuB,mBAAmB,YAAY,CAAC,EAAE;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAU,OAAiD;AAC/D,UAAM,OAA6C,EAAE,WAAW,MAAM,UAAU;AAChF,QAAI,MAAM,QAAQ,OAAW,MAAK,MAAM,MAAM;AAC9C,UAAM,OAAO,MAAM,KAAK,QAMrB,QAAQ,uBAAuB,mBAAmB,MAAM,UAAU,CAAC,UAAU,IAAI;AACpF,UAAM,mBAAmB,KAAK,oBAAoB,KAAK;AACvD,QAAI,CAAC,kBAAkB;AACrB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,WAAO,EAAE,kBAAkB,OAAO,KAAK,OAAO,WAAW,KAAK,WAAW,QAAQ,KAAK,OAAO;AAAA,EAC/F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mBAA2C;AAC/C,UAAM,cAAc,MAAM,KAAK,gBAAgB;AAC/C,WAAO,YAAY,IAAI,CAAC,OAAO;AAAA,MAC7B,cAAc,EAAE;AAAA,MAChB,YAAY,EAAE;AAAA,MACd,QAAQ,EAAE;AAAA,MACV,WAAW,EAAE;AAAA,IACf,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB,cAAuD;AAC3E,WAAO,KAAK,QAAQ,QAAQ,uBAAuB,mBAAmB,YAAY,CAAC,SAAS;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,kBAAkD;AACtD,UAAM,cAAc,MAAM,KAAK,gBAAgB;AAC/C,UAAM,QAAQ,WAAW,YAAY,IAAI,CAAC,MAAM,KAAK,sBAAsB,EAAE,EAAE,CAAC,CAAC;AACjF,WAAO,EAAE,WAAW,YAAY,OAAO;AAAA,EACzC;AAAA;AAAA,EAGA,SAAqC;AACnC,WAAO,KAAK,QAAQ,OAAO,gBAAgB;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,OAAiD;AACzD,WAAO,KAAK,QAAQ,QAAQ,kBAAkB,KAAK;AAAA,EACrD;AAAA;AAAA,EAGA,MAAM,KAAK,OAAoC;AAC7C,UAAM,OAAO,MAAM,KAAK,QAA6B,QAAQ,gBAAgB,KAAK;AAClF,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,QACZ,QACA,MACA,MACY;AACZ,UAAM,UAAkC;AAAA,MACtC,eAAe,UAAU,KAAK,MAAM;AAAA,MACpC,QAAQ;AAAA,IACV;AACA,QAAI,SAAS,OAAW,SAAQ,cAAc,IAAI;AAElD,UAAM,MAAM,MAAM,KAAK,UAAU,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,MACzD;AAAA,MACA;AAAA,MACA,MAAM,SAAS,SAAY,KAAK,UAAU,IAAI,IAAI;AAAA,IACpD,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,SAAqC;AACzC,QAAI,MAAM;AACR,UAAI;AACF,iBAAS,KAAK,MAAM,IAAI;AAAA,MAC1B,QAAQ;AAAA,MAER;AAAA,IACF;AACA,QAAI,CAAC,IAAI,MAAO,UAAU,OAAO,YAAY,OAAQ;AACnD,YAAM,OAAO,QAAQ,SAAS,OAAO,OAAO,UAAU,WAAW,OAAO,MAAM,OAAO;AACrF,YAAM,UACH,QAAQ,SAAS,OAAO,OAAO,UAAU,YAAY,OAAO,MAAM,YAClE,OAAO,QAAQ,UAAU,WAAW,OAAO,QAAQ,uBAAuB,IAAI,MAAM;AACvF,YAAM,IAAI,iBAAiB,SAAS,IAAI,QAAQ,MAAM,UAAU,IAAI;AAAA,IACtE;AACA,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR,2CAA2C,IAAI,MAAM;AAAA,QACrD,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QAAI,OAAO,SAAS,QAAW;AAC7B,YAAM,IAAI;AAAA,QACR;AAAA,QACA,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,WAAO,OAAO;AAAA,EAChB;AACF;","names":[]}
@@ -1,112 +0,0 @@
1
- import { SandboxInstance } from '@tangle-network/sandbox';
2
- import { D as Driver, A as AgentRunSpec, O as OutputAdapter, V as Validator, E as ExecCtx, I as Iteration, L as LoopWinner, a as LoopLineageOptions, S as SandboxClient, b as LoopResult } from './types-Crxftafi.js';
3
-
4
- /**
5
- * @experimental
6
- *
7
- * `runLoop` — the topology-agnostic kernel built atop the sandbox SDK.
8
- *
9
- * Each iteration:
10
- * 1. `driver.plan(task, history)` → N tasks (1 = refine, N = fanout, 0 = stop)
11
- * 2. For each task (parallel, bounded by `maxConcurrency`):
12
- * a. round-robin an `AgentRunSpec` from `agentRuns`
13
- * b. `sandboxClient.create({ backend: { profile }, ...overrides })`
14
- * c. emit `loop.iteration.dispatch` with the placement
15
- * (`{ sibling, sandboxId }` or `{ fleet, fleetId, machineId, sandboxId }`)
16
- * d. iterate `box.streamPrompt(taskToPrompt(task))` and collect events
17
- * 3. `output.parse(events)` → typed `Output`
18
- * 4. `validator?.validate(output)` → `DefaultVerdict`
19
- * 5. Append `Iteration` to history; emit `loop.iteration.ended`
20
- * 6. `driver.decide(history)` → if terminal, return result + winner
21
- *
22
- * The kernel owns: iteration accounting, per-iteration timing, error
23
- * capture, abort propagation, concurrency cap, cost aggregation, and trace
24
- * emission. The kernel does NOT own: what the agent runs (sandbox SDK +
25
- * profile), how outputs are decoded (output adapter), how outputs are
26
- * scored (validator), or topology (driver).
27
- */
28
-
29
- /** @experimental */
30
- interface RunLoopOptions<Task, Output, Decision> {
31
- driver: Driver<Task, Output, Decision>;
32
- /**
33
- * Single agent spec — every iteration uses this profile. Mutually
34
- * exclusive with `agentRuns`.
35
- */
36
- agentRun?: AgentRunSpec<Task>;
37
- /**
38
- * Multiple specs for heterogeneous fanout. The kernel round-robins
39
- * through them when the driver plans N tasks. Mutually exclusive with
40
- * `agentRun`.
41
- */
42
- agentRuns?: AgentRunSpec<Task>[];
43
- output: OutputAdapter<Output>;
44
- validator?: Validator<Output>;
45
- task: Task;
46
- ctx: ExecCtx;
47
- /** Default 10. Hard cap on total iterations across all `plan()` rounds. */
48
- maxIterations?: number;
49
- /** Default 4. In-flight worker cap within a single `plan()` batch. */
50
- maxConcurrency?: number;
51
- /**
52
- * Pre-allocated id for trace correlation. Default = `loop-${random}`.
53
- * Surfaces as `runId` on every emitted `LoopTraceEvent`.
54
- */
55
- runId?: string;
56
- /**
57
- * Clock override; default `Date.now`. Deterministic tests pass a
58
- * monotonic counter to stabilize iteration timing fields.
59
- */
60
- now?: () => number;
61
- /**
62
- * Override the default winner selector (highest-valid-score, ties broken
63
- * by earliest iteration).
64
- */
65
- selectWinner?: (iterations: Iteration<Task, Output>[]) => LoopWinner<Task, Output> | undefined;
66
- /**
67
- * Same-sandbox driver mode — a kernel→caller out-channel, not a value handed
68
- * in. When set, the kernel keeps each finished worker box alive across the
69
- * `plan()` boundary and hands it here, so a same-sandbox planner
70
- * (one that reuses the worker's box) can stream its move INTO the
71
- * worker's live box — steering from the worker's real filesystem and state,
72
- * not just a history summary. The kernel owns teardown: every box kept alive
73
- * this way is destroyed at loop end (and the callback is invoked with
74
- * `undefined` then as a teardown sentinel). Without it, worker boxes are torn
75
- * down per-iteration (default) and a same-sandbox planner has nothing to
76
- * reuse. Intended for single-worker (refine) loops: under fanout every box is
77
- * still kept for teardown, but only the last-finishing box is handed here, so
78
- * a planner sees an arbitrary branch's filesystem — pair it with refine.
79
- */
80
- onWorkerBox?: (box: SandboxInstance | undefined) => void;
81
- /**
82
- * Opt-in box-lineage controls. Default OFF — unset means every iteration
83
- * acquires a fresh box, streams once, and tears it down (today's behavior,
84
- * byte-identical). With `sessionContinuity` on, a refine round continues the
85
- * parent iteration's session on its live box; with `forkFanout` on (and a
86
- * fork-capable platform), a fanout round forks the parent's checkpoint so the
87
- * branches share a context prefix. The lineage owns every box it starts or
88
- * forks and tears them all down at loop end — so these paths are mutually
89
- * exclusive with `onWorkerBox`, which claims the same box-ownership channel.
90
- * @experimental
91
- */
92
- lineage?: LoopLineageOptions;
93
- }
94
- /** @experimental */
95
- declare function runLoop<Task, Output, Decision>(options: RunLoopOptions<Task, Output, Decision>): Promise<LoopResult<Task, Output, Decision>>;
96
- /**
97
- * Instantiate a sandbox for an `AgentRunSpec`: sets `backend.profile` to the
98
- * spec's profile (inferring the backend type when the spec doesn't override
99
- * it) and merges `sandboxOverrides`. Shared by the loop kernel and the
100
- * `AgentRuntime.act` sandbox bridge so both boot the sandbox identically.
101
- */
102
- declare function createSandboxForSpec<Task>(client: SandboxClient, spec: AgentRunSpec<Task>, signal: AbortSignal): Promise<SandboxInstance>;
103
- /**
104
- * The kernel's winner argmax — best-valid-score, ties broken by earliest index,
105
- * falling back to the best-scoring non-errored output when none is valid. Exported
106
- * so the `runProgram` tree executor selects across merged sub-loop iterations with
107
- * the SAME semantics the kernel uses at a single loop's finalize (one selector, not
108
- * a forked copy).
109
- */
110
- declare function defaultSelectWinner<Task, Output>(iterations: Iteration<Task, Output>[]): LoopWinner<Task, Output> | undefined;
111
-
112
- export { type RunLoopOptions as R, createSandboxForSpec as c, defaultSelectWinner as d, runLoop as r };