@tangle-network/agent-runtime 0.50.0 → 0.52.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 (43) hide show
  1. package/dist/agent.js +1 -1
  2. package/dist/{chunk-CM2IK7VS.js → chunk-2OU7ZQPD.js} +38 -8
  3. package/dist/chunk-2OU7ZQPD.js.map +1 -0
  4. package/dist/{chunk-OM3YNZIW.js → chunk-4JI4BCBI.js} +5 -360
  5. package/dist/chunk-4JI4BCBI.js.map +1 -0
  6. package/dist/{chunk-NDM5VXZW.js → chunk-7SP2OVYZ.js} +7 -5
  7. package/dist/{chunk-NDM5VXZW.js.map → chunk-7SP2OVYZ.js.map} +1 -1
  8. package/dist/{chunk-RHW75JW5.js → chunk-BERLUBAP.js} +2 -2
  9. package/dist/{chunk-BKAIVNFA.js → chunk-COAVO6QB.js} +3 -3
  10. package/dist/chunk-G3RGMA7C.js +361 -0
  11. package/dist/chunk-G3RGMA7C.js.map +1 -0
  12. package/dist/{chunk-ML4IXGTV.js → chunk-V2K35HF2.js} +2 -2
  13. package/dist/improvement.d.ts +96 -8
  14. package/dist/improvement.js +191 -9
  15. package/dist/improvement.js.map +1 -1
  16. package/dist/index.d.ts +114 -4
  17. package/dist/index.js +144 -18
  18. package/dist/index.js.map +1 -1
  19. package/dist/intelligence.d.ts +423 -0
  20. package/dist/intelligence.js +427 -0
  21. package/dist/intelligence.js.map +1 -0
  22. package/dist/loop-runner-bin.js +4 -3
  23. package/dist/loops.d.ts +2 -1
  24. package/dist/loops.js +3 -1
  25. package/dist/mcp/bin.js +5 -4
  26. package/dist/mcp/bin.js.map +1 -1
  27. package/dist/mcp/index.js +6 -5
  28. package/dist/mcp/index.js.map +1 -1
  29. package/dist/platform.d.ts +120 -62
  30. package/dist/platform.js +68 -26
  31. package/dist/platform.js.map +1 -1
  32. package/dist/runtime.d.ts +47 -8
  33. package/dist/runtime.js +3 -1
  34. package/dist/workflow.js +1 -1
  35. package/package.json +6 -1
  36. package/skills/agent-runtime-adoption/SKILL.md +41 -26
  37. package/skills/build-with-agent-runtime/SKILL.md +143 -0
  38. package/skills/loop-writer/SKILL.md +6 -7
  39. package/dist/chunk-CM2IK7VS.js.map +0 -1
  40. package/dist/chunk-OM3YNZIW.js.map +0 -1
  41. /package/dist/{chunk-RHW75JW5.js.map → chunk-BERLUBAP.js.map} +0 -0
  42. /package/dist/{chunk-BKAIVNFA.js.map → chunk-COAVO6QB.js.map} +0 -0
  43. /package/dist/{chunk-ML4IXGTV.js.map → chunk-V2K35HF2.js.map} +0 -0
@@ -68,15 +68,17 @@ declare class PlatformAuthClient {
68
68
  }
69
69
 
70
70
  /**
71
- * Server-side client for the Tangle platform's integrations hub
72
- * (`/v1/integrations/*`). Consumer apps use this instead of rolling
73
- * their own OAuth + connection tables.
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
74
  *
75
75
  * Auth: the caller supplies a bearer (either the user's API key from
76
76
  * cross-site exchange, or a platform service token) on construction.
77
- * Per-request override via `headers` is supported.
78
77
  *
79
- * Endpoint contract: `products/platform/api/src/routes/integrations.ts`.
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.
80
82
  */
81
83
  interface PlatformHubClientOptions {
82
84
  /** Platform base URL, e.g. `https://id.tangle.tools`. */
@@ -86,72 +88,112 @@ interface PlatformHubClientOptions {
86
88
  /** Override fetch (tests + edge runtimes). */
87
89
  fetchImpl?: typeof fetch;
88
90
  }
91
+ /** A live integration connection, as returned by `/v1/hub/connections`. */
89
92
  interface PlatformConnection {
90
93
  id: string;
91
94
  providerId: string;
92
- connectorId: string;
93
- status: 'connected' | 'pending' | 'revoked' | 'expired' | string;
94
- grantedScopes?: string[];
95
- account?: {
96
- identity?: string;
97
- displayName?: string;
98
- } & Record<string, unknown>;
99
- metadata?: Record<string, unknown>;
100
- expiresAt?: string | null;
101
- createdAt?: string;
102
- updatedAt?: string;
103
- }
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`). */
104
105
  interface PlatformCatalogProvider {
105
106
  providerId: string;
106
- displayName?: string;
107
- description?: string;
108
- authMode?: string;
109
- connectors?: PlatformCatalogConnector[];
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;
110
116
  [k: string]: unknown;
111
117
  }
112
- interface PlatformCatalogConnector {
113
- connectorId: string;
114
- displayName?: string;
115
- description?: string;
116
- scopes?: string[];
118
+ interface CatalogResult {
119
+ providers: PlatformCatalogProvider[];
120
+ /** Count of substrate-bundled connectors behind the catalog. */
121
+ substrateBundled?: number;
117
122
  [k: string]: unknown;
118
123
  }
119
124
  interface StartAuthInput {
125
+ /** The provider to connect (goes in the URL path). */
120
126
  providerId: string;
121
- connectorId: 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;
122
130
  /** Where the platform redirects the user back to after OAuth. */
123
131
  returnUrl: string;
132
+ /** Accepted for interface compatibility; not consumed by the start endpoint. */
124
133
  requestedScopes?: string[];
125
- state?: string;
126
- metadata?: Record<string, unknown>;
127
- /** Required when the bearer is a service token impersonating a user. */
128
- ownerUserId?: string;
134
+ /** CLI flow flag — affects the platform's post-auth redirect handling. */
135
+ cli?: boolean;
129
136
  }
130
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`. */
131
141
  authorizationUrl: string;
132
142
  state: string;
143
+ expiresAt?: string;
144
+ scopes?: string[];
133
145
  }
134
- interface BundleCapabilityInput {
135
- manifestId?: string;
136
- grantIds?: string[];
137
- subject: {
138
- type: 'user' | 'team' | 'app';
139
- id: string;
146
+ interface ConnectionHealth {
147
+ status: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {});
148
+ checkedAt: string;
149
+ error?: {
150
+ code: string;
151
+ message: string;
140
152
  };
141
- ttlMs: number;
142
153
  }
143
- interface BundleCapabilityResult {
144
- bundle: Record<string, unknown>;
145
- env: Record<string, string>;
154
+ interface ConnectionHealthResult {
155
+ connection: PlatformConnection;
156
+ health: ConnectionHealth;
146
157
  }
158
+ /** Last-known health for a connection, derived from the connection row. */
147
159
  interface HealthCheck {
148
160
  connectionId: string;
149
161
  providerId: string;
150
- connectorId: string;
151
- status: 'ok' | 'degraded' | 'failing' | 'unknown' | string;
152
- checks?: Record<string, unknown>;
162
+ /** Mirrors `PlatformConnection.health`. */
163
+ status: ConnectionHealth['status'];
153
164
  checkedAt?: string;
154
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
+ }
155
197
  declare class PlatformHubError extends Error {
156
198
  readonly status: number;
157
199
  readonly code: string | undefined;
@@ -163,35 +205,51 @@ declare class PlatformHubClient {
163
205
  private readonly bearer;
164
206
  private readonly fetchImpl;
165
207
  constructor(options: PlatformHubClientOptions);
166
- /** List the integration catalog (providers + connectors). */
167
- catalog(): Promise<{
168
- providers: PlatformCatalogProvider[];
169
- } & Record<string, unknown>>;
170
- /** List the calling user's integration connections. */
208
+ /** GET /v1/hub/providers the connectable provider catalog. */
209
+ catalog(): Promise<CatalogResult>;
210
+ /** GET /v1/hub/connections — the calling user's live connections. */
171
211
  listConnections(): Promise<PlatformConnection[]>;
172
- /** Revoke (and disable) a connection by id. */
212
+ /** DELETE /v1/hub/connections/:connectionId — revoke + disable a connection. */
173
213
  revokeConnection(connectionId: string): Promise<{
174
214
  connection: PlatformConnection;
175
- revokedGrants: unknown[];
176
- providerRevocation: {
177
- ok: boolean;
178
- };
179
215
  }>;
180
- /** Begin OAuth — returns the URL to send the user to. */
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
+ */
181
222
  startAuth(input: StartAuthInput): Promise<StartAuthResult>;
182
- /** List connection healthchecks (last known state). */
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
+ */
183
228
  listHealthchecks(): Promise<HealthCheck[]>;
184
- /** Trigger a fresh healthcheck pass. */
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
+ */
185
239
  runHealthchecks(): Promise<{
186
240
  scheduled: number;
187
241
  }>;
242
+ /** GET /v1/hub/status — principal + aggregate connection counts. */
243
+ status(): Promise<PlatformHubStatus>;
188
244
  /**
189
- * Mint a sandbox-injectable capability bundle (env vars + scoped
190
- * capability tokens) so a sandbox can invoke integrations on the
191
- * user's behalf without seeing the underlying provider tokens.
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.
192
248
  */
193
- bundleCapabilities(input: BundleCapabilityInput): Promise<BundleCapabilityResult>;
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>;
194
252
  private request;
195
253
  }
196
254
 
197
- export { type AuthorizeUrlOptions, type BundleCapabilityInput, type BundleCapabilityResult, type ExchangeCodeResult, type HealthCheck, PlatformAuthClient, type PlatformAuthClientOptions, PlatformAuthError, type PlatformCatalogConnector, type PlatformCatalogProvider, type PlatformConnection, PlatformHubClient, type PlatformHubClientOptions, PlatformHubError, type StartAuthInput, type StartAuthResult };
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 CHANGED
@@ -92,48 +92,90 @@ var PlatformHubClient = class {
92
92
  this.bearer = options.bearer;
93
93
  this.fetchImpl = options.fetchImpl ?? ((url, init) => fetch(url, init));
94
94
  }
95
- /** List the integration catalog (providers + connectors). */
95
+ /** GET /v1/hub/providers the connectable provider catalog. */
96
96
  catalog() {
97
- return this.request("GET", "/v1/integrations/catalog");
97
+ return this.request("GET", "/v1/hub/providers");
98
98
  }
99
- /** List the calling user's integration connections. */
99
+ /** GET /v1/hub/connections — the calling user's live connections. */
100
100
  async listConnections() {
101
101
  const data = await this.request(
102
102
  "GET",
103
- "/v1/integrations/connections"
103
+ "/v1/hub/connections"
104
104
  );
105
105
  return data.connections;
106
106
  }
107
- /** Revoke (and disable) a connection by id. */
107
+ /** DELETE /v1/hub/connections/:connectionId — revoke + disable a connection. */
108
108
  revokeConnection(connectionId) {
109
- return this.request(
110
- "DELETE",
111
- `/v1/integrations/connections/${encodeURIComponent(connectionId)}`
112
- );
109
+ return this.request("DELETE", `/v1/hub/connections/${encodeURIComponent(connectionId)}`);
113
110
  }
114
- /** Begin OAuth — returns the URL to send the user to. */
115
- startAuth(input) {
116
- return this.request("POST", "/v1/integrations/auth/start", input);
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 };
117
131
  }
118
- /** List connection healthchecks (last known state). */
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
+ */
119
137
  async listHealthchecks() {
120
- const data = await this.request(
121
- "GET",
122
- "/v1/integrations/healthchecks"
123
- );
124
- return data.healthchecks;
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
+ }));
125
145
  }
126
- /** Trigger a fresh healthcheck pass. */
127
- runHealthchecks() {
128
- return this.request("POST", "/v1/integrations/healthchecks/run", {});
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`);
129
152
  }
130
153
  /**
131
- * Mint a sandbox-injectable capability bundle (env vars + scoped
132
- * capability tokens) so a sandbox can invoke integrations on the
133
- * user's behalf without seeing the underlying provider tokens.
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.
134
157
  */
135
- bundleCapabilities(input) {
136
- return this.request("POST", "/v1/integrations/capabilities/bundle", input);
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;
137
179
  }
138
180
  async request(method, path, body) {
139
181
  const headers = {
@@ -1 +1 @@
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 integrations hub\n * (`/v1/integrations/*`). Consumer apps use this instead of rolling\n * their own 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 * Per-request override via `headers` is supported.\n *\n * Endpoint contract: `products/platform/api/src/routes/integrations.ts`.\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\nexport interface PlatformConnection {\n id: string\n providerId: string\n connectorId: string\n status: 'connected' | 'pending' | 'revoked' | 'expired' | string\n grantedScopes?: string[]\n account?: { identity?: string; displayName?: string } & Record<string, unknown>\n metadata?: Record<string, unknown>\n expiresAt?: string | null\n createdAt?: string\n updatedAt?: string\n}\n\nexport interface PlatformCatalogProvider {\n providerId: string\n displayName?: string\n description?: string\n authMode?: string\n connectors?: PlatformCatalogConnector[]\n [k: string]: unknown\n}\n\nexport interface PlatformCatalogConnector {\n connectorId: string\n displayName?: string\n description?: string\n scopes?: string[]\n [k: string]: unknown\n}\n\nexport interface StartAuthInput {\n providerId: string\n connectorId: string\n /** Where the platform redirects the user back to after OAuth. */\n returnUrl: string\n requestedScopes?: string[]\n state?: string\n metadata?: Record<string, unknown>\n /** Required when the bearer is a service token impersonating a user. */\n ownerUserId?: string\n}\n\nexport interface StartAuthResult {\n authorizationUrl: string\n state: string\n}\n\nexport interface BundleCapabilityInput {\n manifestId?: string\n grantIds?: string[]\n subject: { type: 'user' | 'team' | 'app'; id: string }\n ttlMs: number\n}\n\nexport interface BundleCapabilityResult {\n bundle: Record<string, unknown>\n env: Record<string, string>\n}\n\nexport interface HealthCheck {\n connectionId: string\n providerId: string\n connectorId: string\n status: 'ok' | 'degraded' | 'failing' | 'unknown' | string\n checks?: Record<string, unknown>\n checkedAt?: string\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 /** List the integration catalog (providers + connectors). */\n catalog(): Promise<{ providers: PlatformCatalogProvider[] } & Record<string, unknown>> {\n return this.request('GET', '/v1/integrations/catalog')\n }\n\n /** List the calling user's integration connections. */\n async listConnections(): Promise<PlatformConnection[]> {\n const data = await this.request<{ connections: PlatformConnection[] }>(\n 'GET',\n '/v1/integrations/connections',\n )\n return data.connections\n }\n\n /** Revoke (and disable) a connection by id. */\n revokeConnection(connectionId: string): Promise<{\n connection: PlatformConnection\n revokedGrants: unknown[]\n providerRevocation: { ok: boolean }\n }> {\n return this.request(\n 'DELETE',\n `/v1/integrations/connections/${encodeURIComponent(connectionId)}`,\n )\n }\n\n /** Begin OAuth — returns the URL to send the user to. */\n startAuth(input: StartAuthInput): Promise<StartAuthResult> {\n return this.request('POST', '/v1/integrations/auth/start', input)\n }\n\n /** List connection healthchecks (last known state). */\n async listHealthchecks(): Promise<HealthCheck[]> {\n const data = await this.request<{ healthchecks: HealthCheck[] }>(\n 'GET',\n '/v1/integrations/healthchecks',\n )\n return data.healthchecks\n }\n\n /** Trigger a fresh healthcheck pass. */\n runHealthchecks(): Promise<{ scheduled: number }> {\n return this.request('POST', '/v1/integrations/healthchecks/run', {})\n }\n\n /**\n * Mint a sandbox-injectable capability bundle (env vars + scoped\n * capability tokens) so a sandbox can invoke integrations on the\n * user's behalf without seeing the underlying provider tokens.\n */\n bundleCapabilities(input: BundleCapabilityInput): Promise<BundleCapabilityResult> {\n return this.request('POST', '/v1/integrations/capabilities/bundle', input)\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":"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","names":[]}
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":"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","names":[]}
package/dist/runtime.d.ts CHANGED
@@ -3,7 +3,7 @@ export { AgentProfile, CreateSandboxOptions, SandboxEvent, SandboxInstance } fro
3
3
  import { R as ResultBlobStore, a as SpawnJournal, N as NodeId, b as SpawnEvent, T as TreeView, c as Settled, d as AgentSpec, E as ExecutorRegistry, B as Budget, A as Agent, e as RootHandle, f as SupervisedResult, g as Spend, S as Scope, h as ExecutorFactory, U as UsageEvent, i as Supervisor } from './types-5MGt5KTY.js';
4
4
  export { j as Executor, k as ExecutorContext, l as ExecutorResult, H as Handle, m as NodeSnapshot, n as NodeStatus, o as Restart, p as RootSignal, q as Runtime, r as SpawnOpts, s as SupervisorOpts, W as WidenGate } from './types-5MGt5KTY.js';
5
5
  import { R as RuntimeHooks } from './runtime-hooks-C7JwKb9E.js';
6
- import { ChatClient, AnalystFinding, DefaultVerdict, AgentProfile as AgentProfile$1 } from '@tangle-network/agent-eval';
6
+ import { ChatClient, AnalystFinding, DefaultVerdict, AgentProfile as AgentProfile$1, AnalystRunInputs } from '@tangle-network/agent-eval';
7
7
  export { DefaultVerdict } from '@tangle-network/agent-eval';
8
8
  export { A as AnalyzeInput, a as CompletionAnalyst, b as CompletionEvidence, c as CompletionPolicy, d as CompletionVerdict, C as CreateDriverOptions, D as DriverDecision, P as PlannerContext, e as TopologyMove, T as TopologyPlanner, f as completionAuthorizes, g as createDriver, h as deterministicCompletion, r as renderAnalyses, s as sentinelCompletion, i as stopSentinel } from './driver-DLI1io57.js';
9
9
  import { S as SandboxClient, b as LoopResult, d as LoopTokenUsage, R as RuntimeStreamEvent, A as AgentRunSpec, E as ExecCtx, I as Iteration } from './types-BEQsBhOE.js';
@@ -11,6 +11,7 @@ export { D as Driver, F as LoopDecisionPayload, G as LoopEndedPayload, H as Loop
11
11
  import { Scenario, ProfileDispatchFn } from '@tangle-network/agent-eval/campaign';
12
12
  import { R as RunLoopOptions } from './run-loop-BIineL1T.js';
13
13
  export { c as createSandboxForSpec, d as defaultSelectWinner, r as runLoop } from './run-loop-BIineL1T.js';
14
+ import { b as AnalystRegistryLike } from './types-p8dWBIXL.js';
14
15
 
15
16
  /**
16
17
  * @experimental
@@ -464,6 +465,9 @@ interface ShapeContext<D = unknown> {
464
465
  /** Derive a child `AgentSpec` from the persona's root spec with an overridden profile —
465
466
  * the seam a shape uses to give a worker a narrower role/prompt than the root persona. */
466
467
  childSpec(profile: AgentProfile, harness?: BackendType | null): AgentSpec;
468
+ /** The scope analyst (selector≠judge firewall) the combinator steers from. Absent ⇒ the
469
+ * dormant default (empty findings → gates read deliverables/state only). */
470
+ readonly analyst?: ScopeAnalyst<D>;
467
471
  }
468
472
  /**
469
473
  * A reusable act-body factory. Given the persona's content + seams (`ShapeContext`), it
@@ -521,6 +525,9 @@ interface RunPersonifiedOptions<Task, D> {
521
525
  readonly handle?: RootHandle<Outcome<D>>;
522
526
  readonly now?: () => number;
523
527
  readonly signal?: AbortSignal;
528
+ /** Optional scope analyst threaded into the shape's ShapeContext so loopUntil/widen steer
529
+ * on trace-derived findings instead of the dormant empty default. */
530
+ readonly analyst?: ScopeAnalyst<D>;
524
531
  }
525
532
  /** The composed run signature. */
526
533
  type RunPersonified = <Task, D>(options: RunPersonifiedOptions<Task, D>) => Promise<SupervisedResult<Outcome<D>>>;
@@ -1635,6 +1642,32 @@ interface CreateScopeAnalystOptions<D> {
1635
1642
  * - any finding cites judge-derived metric evidence → `PlannerError` via the firewall
1636
1643
  */
1637
1644
  declare function createScopeAnalyst<D>(scope: Scope<Outcome<D>>, options: CreateScopeAnalystOptions<D>): ScopeAnalyst<D>;
1645
+ /**
1646
+ * Project a `ScopeAnalyzeInput` into the `AnalystRegistry.run` arguments. The registry runs over a
1647
+ * `runId` + `AnalystRunInputs` (a trace store / run record / artifact dir), NOT in-memory scope
1648
+ * settlements — so the CALLER owns the projection from the combinator's drained children to the
1649
+ * registry's inputs (e.g. the trace store the run already wrote). This adapter never invents that
1650
+ * bridge; it only runs the projected inputs and firewalls the merged findings.
1651
+ */
1652
+ interface RegistryAnalyzeProjection {
1653
+ readonly runId: string;
1654
+ readonly inputs: AnalystRunInputs;
1655
+ /** Optional `run` opts (e.g. `priorFindings`) forwarded verbatim to the registry. */
1656
+ readonly opts?: Parameters<AnalystRegistryLike['run']>[2];
1657
+ }
1658
+ /**
1659
+ * A `ScopeAnalyst` backed by an `AnalystRegistry` — the panel-of-analysts seam. The registry merges
1660
+ * N analyst KINDS into one `AnalystRunResult.findings`; `analyze` runs it over the caller-projected
1661
+ * `{ runId, inputs }` and pipes the merged findings through the SAME `assertTraceDerivedFindings`
1662
+ * firewall `createScopeAnalyst` uses (single-sourced selector≠judge). Distinct from `panel()`
1663
+ * (judges-vs-one-artifact) — this is analysts-over-a-trace, the diagnosis side of the wire.
1664
+ *
1665
+ * Fail loud: a registry that throws propagates; a judge-derived finding aborts via the firewall.
1666
+ * The projection is the caller's (`buildInputs`) — if the scope settlements do not cleanly map to
1667
+ * the registry's `AnalystRunInputs`, that is a caller-side contract gap, surfaced there, not papered
1668
+ * over with a fabricated input here.
1669
+ */
1670
+ declare function registryScopeAnalyst<D>(registry: AnalystRegistryLike, buildInputs: (input: ScopeAnalyzeInput<D>) => RegistryAnalyzeProjection): ScopeAnalyst<D>;
1638
1671
  /**
1639
1672
  * Build the `SteerContext` a combinator reads to steer (its `loopUntil.until`, `widen` gate, any
1640
1673
  * future steer). One place enforces the firewall: `findings` is asserted trace-derived before it is
@@ -1693,9 +1726,10 @@ declare function fanout<Task, Item, D>(items: ReadonlyArray<Item>, opts: FanoutO
1693
1726
  * the deployable stop. The conserved pool IS the loop bound: once `spawn` fails closed the loop
1694
1727
  * stops. A loop that exhausted the pool without `until` ever satisfying is a concrete blocker.
1695
1728
  *
1696
- * Findings are threaded through the `SteerContext` firewall in the analyst seam (`analyst.ts`);
1697
- * absent a wired analyst on this surface the firewall stays dormant and `until` is consulted with
1698
- * an empty findings array never a fabricated finding (fail-loud honesty over a silent default).
1729
+ * When `ctx.analyst` is set, each round runs it over the children settled so far and steers
1730
+ * `until` on the resulting trace-derived findings (the analyst spawns into THIS scope, so its
1731
+ * compute is conserved-pooledequal-k holds by construction). Absent an analyst the findings
1732
+ * argument is the empty array — never a fabricated finding (fail-loud honesty over a silent default).
1699
1733
  */
1700
1734
  declare function loopUntil<Task, State, D>(seed: State, spec: LoopUntilSpec<Task, State, D>): CombinatorShape<Task, D>;
1701
1735
  /**
@@ -1721,9 +1755,14 @@ declare function verify<Task, Candidate, D>(spec: VerifySpec<Task, Candidate, D>
1721
1755
  * never a child's raw `verdict` — and the default gate (`flatWidenGate`) never widens, so the R2
1722
1756
  * firewall stays dormant. Terminal selection is `spec.synthesize` over every settled lineage.
1723
1757
  *
1724
- * No analyst is wired on this frozen surface, so `decide` is consulted with an empty findings
1725
- * array; a flat gate ignores it. A non-flat gate that wants findings reads them through the
1726
- * `SteerContext` firewall the analyst seam owns never fabricated here.
1758
+ * When `ctx.analyst` is set, `decide` is consulted with that round's trace-derived findings;
1759
+ * absent an analyst the findings argument is the empty array a flat gate ignores. The analyst
1760
+ * spawns into THIS scope (conserved-pooled, so equal-k holds). Streaming caveat: a wired analyst
1761
+ * drains its own child off the SHARED cursor by id-match, so on a NON-flat gate (which spawns
1762
+ * widen children that are live concurrently) the analyst can consume a sibling's settlement before
1763
+ * the widen loop sees it. The shipped default (`flatWidenGate`) never widens, so no widen child is
1764
+ * ever live when the analyst runs and the wire is exact; a non-flat gate must drive the analyst on
1765
+ * a scope whose siblings are quiesced, or read findings without the shared-cursor drain.
1727
1766
  */
1728
1767
  declare function widen<Task, Seed, D>(spec: WidenSpec<Seed, D>): CombinatorShape<Task, D>;
1729
1768
  /**
@@ -3184,4 +3223,4 @@ declare function gitWorkspace(opts: GitWorkspaceOptions): Workspace;
3184
3223
  * requires `jj` on the `Shell`'s host. */
3185
3224
  declare function jjWorkspace(opts: GitWorkspaceOptions): Workspace;
3186
3225
 
3187
- export { Agent, AgentRunSpec, AgentSpec, type AgenticOptions, type AgenticRunResult, type AgenticSurface, type AgenticTask, type AgenticTool, type AnytimeReport, type AnytimeStrategySummary, type AnytimeTaskCurve, type ArtifactHandle, type AssertTraceDerivedFindings, type AuditIntentInput, type AuditIntentOptions, type AuthorStrategyOptions, type AuthoredStrategy, type BenchmarkCell, type BenchmarkConfig, type BenchmarkLift, type BenchmarkReport, type BenchmarkStrategySummary, type BenchmarkTaskRow, type BridgeSeam, Budget, type BudgetPool, type BudgetReadout, type ChampionPick, type ChampionPolicy, type CheckpointCapableBox, type CliSeam, type CombinatorShape, type Corpus, type CorpusFilter, type CorpusRecord, type CreateScopeAnalystOptions, type CriuCapableClient, type DefinePersona, type DefinePersonaInput, type Deliverable, type Environment, type EqualKArm, type EqualKOnCost, type EqualKOnCostOptions, type EqualKVerdict, type EvolutionArchiveNode, type EvolutionAuthor, type EvolutionBandInfo, type EvolutionCandidate, type EvolutionGeneration, type EvolutionReport, ExecCtx, type ExecutorConfig, ExecutorFactory, ExecutorRegistry, type Fanout, type FanoutOptions, type FanoutSynthesis, FileCorpus, FileResultBlobStore, FileSpawnJournal, type FlatWidenGate, type ForkCapableBox, type GitWorkspaceOptions, type HarvestCorpusOptions, type HarvestFailure, type HarvestReport, InMemoryCorpus, InMemoryResultBlobStore, InMemorySpawnJournal, type IntentAudit, Iteration, type LoopDispatchOptions, type LoopOptionsForDispatch, LoopResult, type LoopShape, LoopTokenUsage, type LoopUntil, type LoopUntilSpec, type LoopUntilState, type McpEndpoint, type McpEnvironmentOptions, NodeId, type Observation, type ObserveInput, type ObserveOptions, type OpenSandboxRunOptions, type Outcome, type Panel, type PanelJudge, type PanelSpec, type PanelVerdict, type Persona, type PersonaContext, type PersonaExecutors, type Pipeline, type PipelineStage, type PromotionGateOptions, type PromotionVerdict, type RenderCorpusToInstructions, type RenderCorpusToInstructionsOptions, type ReservationTicket, ResultBlobStore, RootHandle, type RouterChatResult, type RouterChatToolsResult, type RouterConfig, type RouterSeam, type RouterToolCall, type RouterToolLoopResult, type RouterToolsSeam, type RunAgenticOptions, RunLoopOptions, type RunPersonified, type RunPersonifiedOptions, type SandboxCapabilities, SandboxClient, type SandboxLineage, type SandboxLineageHandle, type SandboxRun, type SandboxSeam, Scope, type ScopeAnalyst, type ScopeAnalyzeInput, type ScopeWidenGate, type SessionCapableBox, Settled, type ShapeBudget, type ShapeContext, type ShapeRegistry, type Shell, type ShotPersona, type ShotSpec, SpawnEvent, SpawnJournal, Spend, type SteerContext, type Strategy, type StrategyCtx, type StrategyEvolutionConfig, type StrategyResult, SupervisedResult, Supervisor, type SurfaceScore, type ToolSpec, type TrajectoryNode, type TrajectoryReport, type TrajectoryReportFn, type TrajectoryReportOptions, TreeView, type TurnResult, UsageEvent, type UsageSink, type VerifierEnvironmentOptions, type Verify, type VerifySpec, type WaterfallCollector, type WaterfallReport, type WaterfallSpan, type Widen, type WidenDecision, type WidenLineage, type WidenSpec, type Workspace, type WorkspaceCommit, acquireSandbox, adaptiveRefine, anytimeReport, assertStrategyContract, assertTraceDerivedFindings, auditIntent, authorStrategy, breadthDriver, buildSteerContext, builtinShapes, contentAddress, createBudgetPool, createExecutor, createExecutorRegistry, createMcpEnvironment, createRootHandle, createSandboxLineage, createScope, createScopeAnalyst, createShapeRegistry, createSupervisor, createVerifierEnvironment, createWaterfallCollector, defaultAnalystInstruction, defaultAuditorInstruction, definePersona, defineStrategy, depthDriver, discriminatingMeans, equalKOnCost, extractLlmCallEvent, fanout, flatWidenGate, gitWorkspace, harvestCorpus, inlineSandboxClient, jjWorkspace, localShell, loopDispatch, loopUntil, mapSandboxEvent, materializeTreeView, observe, openSandboxRun, panel, pickChampion, pipeline, printBenchmarkReport, probeSandboxCapabilities, promotionGate, refine, registerShape, renderAnytimeTable, renderCorpusToInstructions, renderReport, replaySpawnTree, reportLoopUsage, routerChatWithTools, routerChatWithUsage, routerToolLoop, runAgentic, runBenchmark, runPersonified, runStrategyEvolution, sample, sampleThenRefine, selectChampion, settledToIteration, spendFromUsageEvents, strategyAuthorContract, trajectoryReport, verify, widen };
3226
+ export { Agent, AgentRunSpec, AgentSpec, type AgenticOptions, type AgenticRunResult, type AgenticSurface, type AgenticTask, type AgenticTool, type AnytimeReport, type AnytimeStrategySummary, type AnytimeTaskCurve, type ArtifactHandle, type AssertTraceDerivedFindings, type AuditIntentInput, type AuditIntentOptions, type AuthorStrategyOptions, type AuthoredStrategy, type BenchmarkCell, type BenchmarkConfig, type BenchmarkLift, type BenchmarkReport, type BenchmarkStrategySummary, type BenchmarkTaskRow, type BridgeSeam, Budget, type BudgetPool, type BudgetReadout, type ChampionPick, type ChampionPolicy, type CheckpointCapableBox, type CliSeam, type CombinatorShape, type Corpus, type CorpusFilter, type CorpusRecord, type CreateScopeAnalystOptions, type CriuCapableClient, type DefinePersona, type DefinePersonaInput, type Deliverable, type Environment, type EqualKArm, type EqualKOnCost, type EqualKOnCostOptions, type EqualKVerdict, type EvolutionArchiveNode, type EvolutionAuthor, type EvolutionBandInfo, type EvolutionCandidate, type EvolutionGeneration, type EvolutionReport, ExecCtx, type ExecutorConfig, ExecutorFactory, ExecutorRegistry, type Fanout, type FanoutOptions, type FanoutSynthesis, FileCorpus, FileResultBlobStore, FileSpawnJournal, type FlatWidenGate, type ForkCapableBox, type GitWorkspaceOptions, type HarvestCorpusOptions, type HarvestFailure, type HarvestReport, InMemoryCorpus, InMemoryResultBlobStore, InMemorySpawnJournal, type IntentAudit, Iteration, type LoopDispatchOptions, type LoopOptionsForDispatch, LoopResult, type LoopShape, LoopTokenUsage, type LoopUntil, type LoopUntilSpec, type LoopUntilState, type McpEndpoint, type McpEnvironmentOptions, NodeId, type Observation, type ObserveInput, type ObserveOptions, type OpenSandboxRunOptions, type Outcome, type Panel, type PanelJudge, type PanelSpec, type PanelVerdict, type Persona, type PersonaContext, type PersonaExecutors, type Pipeline, type PipelineStage, type PromotionGateOptions, type PromotionVerdict, type RegistryAnalyzeProjection, type RenderCorpusToInstructions, type RenderCorpusToInstructionsOptions, type ReservationTicket, ResultBlobStore, RootHandle, type RouterChatResult, type RouterChatToolsResult, type RouterConfig, type RouterSeam, type RouterToolCall, type RouterToolLoopResult, type RouterToolsSeam, type RunAgenticOptions, RunLoopOptions, type RunPersonified, type RunPersonifiedOptions, type SandboxCapabilities, SandboxClient, type SandboxLineage, type SandboxLineageHandle, type SandboxRun, type SandboxSeam, Scope, type ScopeAnalyst, type ScopeAnalyzeInput, type ScopeWidenGate, type SessionCapableBox, Settled, type ShapeBudget, type ShapeContext, type ShapeRegistry, type Shell, type ShotPersona, type ShotSpec, SpawnEvent, SpawnJournal, Spend, type SteerContext, type Strategy, type StrategyCtx, type StrategyEvolutionConfig, type StrategyResult, SupervisedResult, Supervisor, type SurfaceScore, type ToolSpec, type TrajectoryNode, type TrajectoryReport, type TrajectoryReportFn, type TrajectoryReportOptions, TreeView, type TurnResult, UsageEvent, type UsageSink, type VerifierEnvironmentOptions, type Verify, type VerifySpec, type WaterfallCollector, type WaterfallReport, type WaterfallSpan, type Widen, type WidenDecision, type WidenLineage, type WidenSpec, type Workspace, type WorkspaceCommit, acquireSandbox, adaptiveRefine, anytimeReport, assertStrategyContract, assertTraceDerivedFindings, auditIntent, authorStrategy, breadthDriver, buildSteerContext, builtinShapes, contentAddress, createBudgetPool, createExecutor, createExecutorRegistry, createMcpEnvironment, createRootHandle, createSandboxLineage, createScope, createScopeAnalyst, createShapeRegistry, createSupervisor, createVerifierEnvironment, createWaterfallCollector, defaultAnalystInstruction, defaultAuditorInstruction, definePersona, defineStrategy, depthDriver, discriminatingMeans, equalKOnCost, extractLlmCallEvent, fanout, flatWidenGate, gitWorkspace, harvestCorpus, inlineSandboxClient, jjWorkspace, localShell, loopDispatch, loopUntil, mapSandboxEvent, materializeTreeView, observe, openSandboxRun, panel, pickChampion, pipeline, printBenchmarkReport, probeSandboxCapabilities, promotionGate, refine, registerShape, registryScopeAnalyst, renderAnytimeTable, renderCorpusToInstructions, renderReport, replaySpawnTree, reportLoopUsage, routerChatWithTools, routerChatWithUsage, routerToolLoop, runAgentic, runBenchmark, runPersonified, runStrategyEvolution, sample, sampleThenRefine, selectChampion, settledToIteration, spendFromUsageEvents, strategyAuthorContract, trajectoryReport, verify, widen };
package/dist/runtime.js CHANGED
@@ -60,6 +60,7 @@ import {
60
60
  promotionGate,
61
61
  refine,
62
62
  registerShape,
63
+ registryScopeAnalyst,
63
64
  renderAnalyses,
64
65
  renderAnytimeTable,
65
66
  renderCorpusToInstructions,
@@ -85,7 +86,7 @@ import {
85
86
  trajectoryReport,
86
87
  verify,
87
88
  widen
88
- } from "./chunk-CM2IK7VS.js";
89
+ } from "./chunk-2OU7ZQPD.js";
89
90
  import {
90
91
  extractLlmCallEvent,
91
92
  mapSandboxEvent
@@ -155,6 +156,7 @@ export {
155
156
  promotionGate,
156
157
  refine,
157
158
  registerShape,
159
+ registryScopeAnalyst,
158
160
  renderAnalyses,
159
161
  renderAnytimeTable,
160
162
  renderCorpusToInstructions,
package/dist/workflow.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  createSandboxForSpec,
3
3
  describeSandboxPlacement,
4
4
  runLoop
5
- } from "./chunk-CM2IK7VS.js";
5
+ } from "./chunk-2OU7ZQPD.js";
6
6
  import {
7
7
  ValidationError,
8
8
  extractLlmCallEvent
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-runtime",
3
- "version": "0.50.0",
3
+ "version": "0.52.0",
4
4
  "description": "Shared task-lifecycle skeleton for agents: a recursive loop kernel for chat turns, one-shot tasks, and multi-attempt loops, with trace capture and eval-gated self-improvement. Domain behavior lives in adapters; scoring and ship-gates in @tangle-network/agent-eval.",
5
5
  "homepage": "https://github.com/tangle-network/agent-runtime#readme",
6
6
  "repository": {
@@ -39,6 +39,11 @@
39
39
  "import": "./dist/agent.js",
40
40
  "default": "./dist/agent.js"
41
41
  },
42
+ "./intelligence": {
43
+ "types": "./dist/intelligence.d.ts",
44
+ "import": "./dist/intelligence.js",
45
+ "default": "./dist/intelligence.js"
46
+ },
42
47
  "./runtime": {
43
48
  "types": "./dist/runtime.d.ts",
44
49
  "import": "./dist/runtime.js",