@tangle-network/agent-runtime 0.349.0 → 0.352.1

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 (139) hide show
  1. package/dist/{activation-wBipBkCf.d.ts → activation-BidzGkUQ.d.ts} +2 -24
  2. package/dist/{activation-tNGW73Y9.js → activation-C6zNC2kx.js} +12 -14
  3. package/dist/{activation-tNGW73Y9.js.map → activation-C6zNC2kx.js.map} +1 -1
  4. package/dist/agent.d.ts +8 -12
  5. package/dist/agent.js +9 -12
  6. package/dist/agent.js.map +1 -1
  7. package/dist/{analyst-loop-DZw5QWT9.js → analyst-loop-BZvXCDKy.js} +2 -3
  8. package/dist/{analyst-loop-DZw5QWT9.js.map → analyst-loop-BZvXCDKy.js.map} +1 -1
  9. package/dist/analyst-loop.d.ts +3 -5
  10. package/dist/analyst-loop.js +1 -2
  11. package/dist/{bundle-1xaJEgjq.js → bundle-DeDkJbsr.js} +3 -4
  12. package/dist/{bundle-1xaJEgjq.js.map → bundle-DeDkJbsr.js.map} +1 -1
  13. package/dist/candidate-execution/index.d.ts +13 -33
  14. package/dist/candidate-execution/index.js +16 -18
  15. package/dist/candidate-execution/index.js.map +1 -1
  16. package/dist/chat-turn.d.ts +2 -0
  17. package/dist/chat-turn.js +1 -0
  18. package/dist/{coordination-manager-B2Z_MmL9.js → coordination-manager-B7QadgrI.js} +101 -132
  19. package/dist/{coordination-manager-B2Z_MmL9.js.map → coordination-manager-B7QadgrI.js.map} +1 -1
  20. package/dist/{delegate-Dr-63jFl.js → delegate-CoscoyEo.js} +19 -21
  21. package/dist/delegate-CoscoyEo.js.map +1 -0
  22. package/dist/durable.d.ts +16 -149
  23. package/dist/durable.js +57 -980
  24. package/dist/durable.js.map +1 -1
  25. package/dist/{errors-DodWX-cb.js → errors-AzSuGI23.js} +5 -3
  26. package/dist/errors-AzSuGI23.js.map +1 -0
  27. package/dist/execution-handle-Bd2_nUB6.js +167 -0
  28. package/dist/execution-handle-Bd2_nUB6.js.map +1 -0
  29. package/dist/execution-handle-CujvqgCn.d.ts +130 -0
  30. package/dist/{graph-DPejYB3C.js → graph-mojMML8e.js} +192 -14
  31. package/dist/graph-mojMML8e.js.map +1 -0
  32. package/dist/{improve-DwSahPi1.js → improve-Dm5ZE8mr.js} +36 -53
  33. package/dist/{improve-DwSahPi1.js.map → improve-Dm5ZE8mr.js.map} +1 -1
  34. package/dist/{improvement-adapter-sIthWkcN.d.ts → improvement-adapter-D5GRU1eY.d.ts} +2 -6
  35. package/dist/index.d.ts +41 -89
  36. package/dist/index.js +45 -61
  37. package/dist/index.js.map +1 -1
  38. package/dist/intelligence.d.ts +39 -59
  39. package/dist/intelligence.js +24 -33
  40. package/dist/intelligence.js.map +1 -1
  41. package/dist/journal-store-BJPMUydp.js +3925 -0
  42. package/dist/journal-store-BJPMUydp.js.map +1 -0
  43. package/dist/kernel.d.ts +5 -5
  44. package/dist/kernel.js +12 -11
  45. package/dist/{loop-runner-CP6MfO1b.js → loop-runner-5cL_vZi0.js} +5 -6
  46. package/dist/{loop-runner-CP6MfO1b.js.map → loop-runner-5cL_vZi0.js.map} +1 -1
  47. package/dist/{loop-runner-C6pGq-2l.d.ts → loop-runner-DyLD-aNb.d.ts} +3 -5
  48. package/dist/loop-runner-bin.d.ts +5 -8
  49. package/dist/loop-runner-bin.js +2 -3
  50. package/dist/mcp/bin.js +6 -8
  51. package/dist/mcp/bin.js.map +1 -1
  52. package/dist/mcp/index.d.ts +8 -18
  53. package/dist/mcp/index.js +17 -25
  54. package/dist/mcp/index.js.map +1 -1
  55. package/dist/mcp/memory-bin.js +4 -6
  56. package/dist/mcp/memory-bin.js.map +1 -1
  57. package/dist/{model-policy-CyCUwHed.js → model-policy-C-RGAUW4.js} +11 -13
  58. package/dist/{model-policy-CyCUwHed.js.map → model-policy-C-RGAUW4.js.map} +1 -1
  59. package/dist/placement.d.ts +12 -14
  60. package/dist/placement.js +1 -2
  61. package/dist/platform.d.ts +7 -13
  62. package/dist/platform.js +3 -6
  63. package/dist/platform.js.map +1 -1
  64. package/dist/{prepare-B9wWffjO.js → prepare-XWwsOh8O.js} +50 -69
  65. package/dist/{prepare-B9wWffjO.js.map → prepare-XWwsOh8O.js.map} +1 -1
  66. package/dist/{profile-JLJd2wFG.js → profile-C01SQZKa.js} +58 -92
  67. package/dist/profile-C01SQZKa.js.map +1 -0
  68. package/dist/{profile-materialization-bPm0gGLO.d.ts → profile-materialization-BRY22Oh8.d.ts} +1 -3
  69. package/dist/profiles.d.ts +25 -12
  70. package/dist/profiles.js +52 -11
  71. package/dist/profiles.js.map +1 -1
  72. package/dist/{protected-model-port-DVVh-hEk.d.ts → protected-model-port-IKqhTypD.d.ts} +2 -14
  73. package/dist/{protected-redaction-DFCeo4vg.js → protected-redaction-DilFZch5.js} +2 -3
  74. package/dist/{protected-redaction-DFCeo4vg.js.map → protected-redaction-DilFZch5.js.map} +1 -1
  75. package/dist/{provision-supervisor-C4v2vqDo.js → provision-supervisor-D9pO-iPl.js} +11 -15
  76. package/dist/{provision-supervisor-C4v2vqDo.js.map → provision-supervisor-D9pO-iPl.js.map} +1 -1
  77. package/dist/{run-cancellation-CzFhQGMa.js → run-cancellation-CoJRKvih.js} +6 -7
  78. package/dist/{run-cancellation-CzFhQGMa.js.map → run-cancellation-CoJRKvih.js.map} +1 -1
  79. package/dist/{runtime-CsvGCQpl.js → runtime-BJPXHWbc.js} +652 -215
  80. package/dist/runtime-BJPXHWbc.js.map +1 -0
  81. package/dist/{runtime-hooks-tXpAarhW.js → runtime-hooks-CsW2pfFk.js} +2 -3
  82. package/dist/{runtime-hooks-tXpAarhW.js.map → runtime-hooks-CsW2pfFk.js.map} +1 -1
  83. package/dist/{runtime-hooks-nsqxSUFL.d.ts → runtime-hooks-ZQqPw-0g.d.ts} +1 -3
  84. package/dist/{sandbox-profile-compat-DtuJWFrM.js → sandbox-profile-compat-CXjozdWL.js} +52 -653
  85. package/dist/sandbox-profile-compat-CXjozdWL.js.map +1 -0
  86. package/dist/{search-executor-CCb82Umc.js → search-executor-CQEHMXoT.js} +12 -15
  87. package/dist/{search-executor-CCb82Umc.js.map → search-executor-CQEHMXoT.js.map} +1 -1
  88. package/dist/{server-CKPwZU-I.js → server-U9NGgudQ.js} +19 -30
  89. package/dist/{server-CKPwZU-I.js.map → server-U9NGgudQ.js.map} +1 -1
  90. package/dist/{structural-rollout-DylC_fwU.js → structural-rollout-wMSxE7bn.js} +71 -70
  91. package/dist/structural-rollout-wMSxE7bn.js.map +1 -0
  92. package/dist/{substrate-CGDFTSRh.js → substrate-Db2pp6y3.js} +2 -3
  93. package/dist/{substrate-CGDFTSRh.js.map → substrate-Db2pp6y3.js.map} +1 -1
  94. package/dist/{supervise-BGfm2GlY.js → supervise-CNNhX0ab.js} +460 -195
  95. package/dist/supervise-CNNhX0ab.js.map +1 -0
  96. package/dist/supervision-discovery-CewADdEs.js +772 -0
  97. package/dist/supervision-discovery-CewADdEs.js.map +1 -0
  98. package/dist/{supervisor-wS9Ehz_x.js → supervisor-rK5Y8en6.js} +521 -4320
  99. package/dist/supervisor-rK5Y8en6.js.map +1 -0
  100. package/dist/{task-queue-0fKkoweu.d.ts → task-queue-kefGy79U.d.ts} +1 -3
  101. package/dist/task-queue.d.ts +1 -1
  102. package/dist/task-queue.js +1 -2
  103. package/dist/testing.d.ts +7 -15
  104. package/dist/testing.js +241 -244
  105. package/dist/testing.js.map +1 -1
  106. package/dist/tool-loop.d.ts +16 -19
  107. package/dist/tool-loop.js +2 -3
  108. package/dist/{tool-server-XV4aJwoQ.js → tool-server-CZWd_Opp.js} +3 -4
  109. package/dist/{tool-server-XV4aJwoQ.js.map → tool-server-CZWd_Opp.js.map} +1 -1
  110. package/dist/{top-snapshot-CflmaDgk.js → top-snapshot-DcV7VG4m.js} +179 -163
  111. package/dist/top-snapshot-DcV7VG4m.js.map +1 -0
  112. package/dist/tui/bin.js +50 -81
  113. package/dist/tui/bin.js.map +1 -1
  114. package/dist/tui/index.d.ts +27 -58
  115. package/dist/tui/index.js +2 -2
  116. package/dist/{types-C8BGOCBn.d.ts → types-0uzVKtFW.d.ts} +388 -484
  117. package/dist/{types-Cwrea-bU.d.ts → types-qsqfyQoY.d.ts} +1 -3
  118. package/dist/util-ebWMWzY0.js +624 -0
  119. package/dist/util-ebWMWzY0.js.map +1 -0
  120. package/dist/workspace-store/index.d.ts +12 -22
  121. package/dist/workspace-store/index.js +13 -10
  122. package/dist/workspace-store/index.js.map +1 -1
  123. package/dist/{workspace-streams-BiS4ABah.d.ts → workspace-streams-Dq2Fzk3c.d.ts} +1 -11
  124. package/package.json +31 -26
  125. package/skills/agent-graphs/SKILL.md +17 -4
  126. package/skills/be-ambitious/SKILL.md +46 -0
  127. package/skills/graph-designer/SKILL.md +9 -2
  128. package/dist/delegate-Dr-63jFl.js.map +0 -1
  129. package/dist/errors-DodWX-cb.js.map +0 -1
  130. package/dist/graph-DPejYB3C.js.map +0 -1
  131. package/dist/profile-JLJd2wFG.js.map +0 -1
  132. package/dist/record-events-D93DkpAx.js +0 -263
  133. package/dist/record-events-D93DkpAx.js.map +0 -1
  134. package/dist/runtime-CsvGCQpl.js.map +0 -1
  135. package/dist/sandbox-profile-compat-DtuJWFrM.js.map +0 -1
  136. package/dist/structural-rollout-DylC_fwU.js.map +0 -1
  137. package/dist/supervise-BGfm2GlY.js.map +0 -1
  138. package/dist/supervisor-wS9Ehz_x.js.map +0 -1
  139. package/dist/top-snapshot-CflmaDgk.js.map +0 -1
package/dist/platform.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { isRecord } from "@tangle-network/agent-core";
2
- //#region src/platform/auth.ts
2
+ // src/platform/auth.ts
3
3
  /**
4
4
  * Server-side client for the Tangle platform's cross-site SSO bridge.
5
5
  *
@@ -101,8 +101,7 @@ var PlatformAuthClient = class {
101
101
  return parseExchangeResult(body, res.status);
102
102
  }
103
103
  };
104
- //#endregion
105
- //#region src/platform/integrations.ts
104
+ // src/platform/integrations.ts
106
105
  /** Thrown when a `PlatformHubClient` request returns a non-success status. */
107
106
  var PlatformHubError = class extends Error {
108
107
  status;
@@ -230,8 +229,7 @@ var PlatformHubClient = class {
230
229
  return parsed.data;
231
230
  }
232
231
  };
233
- //#endregion
234
- //#region src/platform/oidc.ts
232
+ // src/platform/oidc.ts
235
233
  /**
236
234
  * OpenID Connect client for the Tangle authorization server. Identity tokens
237
235
  * are not platform API keys. Resource scopes and audiences must be registered
@@ -476,7 +474,6 @@ var PlatformOidcClient = class {
476
474
  });
477
475
  }
478
476
  };
479
- //#endregion
480
477
  export { PlatformAuthClient, PlatformAuthError, PlatformHubClient, PlatformHubError, PlatformOidcClient, createPkcePair };
481
478
 
482
479
  //# sourceMappingURL=platform.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform.js","names":["isNonemptyString"],"sources":["../src/platform/auth.ts","../src/platform/integrations.ts","../src/platform/oidc.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 * the cross-site route in agent-container's platform API. This client only\n * speaks HTTP — no SDK weight, no transitive deps.\n */\n\nimport { isRecord } from '@tangle-network/agent-core'\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 emailVerified: true\n user: {\n id: string\n email: string\n name?: string | null\n }\n /** Null when the platform could not provide a subscription. This is not a paid-access grant. */\n plan: {\n tier: string\n } | null\n}\n\n/** Thrown when a `PlatformAuthClient` request returns a non-success status. */\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\nfunction isNonemptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0\n}\n\n/** Validate the platform's verified identity before consumers create a local session. */\nfunction parseExchangeResult(body: unknown, status: number): ExchangeCodeResult {\n const invalid = (): never => {\n // A successful but malformed response can contain the one-time API secret.\n throw new PlatformAuthError(\n 'Platform exchange response has no valid verified identity',\n status,\n { code: 'INVALID_EXCHANGE_RESPONSE' },\n )\n }\n if (\n !isRecord(body) ||\n !isNonemptyString(body.apiKey) ||\n body.emailVerified !== true ||\n !isRecord(body.user)\n )\n return invalid()\n const user = body.user\n if (!isNonemptyString(user.id) || !isNonemptyString(user.email)) return invalid()\n const email = user.email.trim()\n if (\n email.length > 320 ||\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email) ||\n /(?:@users\\.noreply\\.tangle\\.tools$|^0x[a-f0-9]{40}@tangle\\.tools$)/i.test(email)\n )\n return invalid()\n if (user.name !== undefined && user.name !== null && typeof user.name !== 'string')\n return invalid()\n let plan: ExchangeCodeResult['plan'] = null\n if (body.subscription !== undefined) {\n if (!isRecord(body.subscription) || !isNonemptyString(body.subscription.plan)) return invalid()\n plan = { tier: body.subscription.plan }\n }\n return {\n apiKey: body.apiKey,\n emailVerified: true,\n user: { id: user.id, email, ...(user.name !== undefined ? { name: user.name } : {}) },\n plan,\n }\n}\n\n/** HTTP client for the Tangle Platform SSO: builds authorize URLs and exchanges auth codes for API keys. */\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 return parseExchangeResult(body, res.status)\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 API's hub contract\n * and hub route (both in agent-container's platform API). 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\n/** Thrown when a `PlatformHubClient` request returns a non-success status. */\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\n/** HTTP client for the Tangle Platform Hub API: provider catalog, connection flow, and status. */\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","/**\n * OpenID Connect client for the Tangle authorization server. Identity tokens\n * are not platform API keys. Resource scopes and audiences must be registered\n * by the provider before a consumer can use these tokens at a paid API.\n */\n\nimport { isRecord } from '@tangle-network/agent-core'\nimport { PlatformAuthError } from './auth.js'\n\nexport interface PlatformOidcClientOptions {\n baseUrl: string\n clientId: string\n /** Omit only for clients registered with token_endpoint_auth_method=none. */\n clientSecret?: string\n /** Required for authorization code; not required for the device grant. */\n redirectUri?: string\n scope?: string\n /** RFC 8707 resource identifiers registered at the authorization server. */\n resources?: readonly string[]\n fetchImpl?: typeof fetch\n}\n\nexport interface OidcAuthorizeUrlOptions {\n state: string\n codeChallenge: string\n /** Only supply a nonce when the consumer also validates the ID token. */\n nonce?: string\n prompt?: 'login' | 'consent' | 'none'\n loginHint?: string\n}\n\nexport interface OidcTokens {\n accessToken: string\n tokenType: string\n expiresIn?: number\n refreshToken?: string\n idToken?: string\n scope?: string\n}\n\nexport interface OidcUser {\n id: string\n email: string\n emailVerified: true\n name?: string\n}\n\nexport interface OidcExchangeResult {\n tokens: OidcTokens\n user: OidcUser\n}\n\n/** Keep deviceCode secret. Only userCode and the verification URLs are displayed. */\nexport interface OidcDeviceAuthorization {\n deviceCode: string\n userCode: string\n verificationUri: string\n verificationUriComplete?: string\n expiresIn: number\n /** Absolute deadline preserves expiry when a polling process resumes. */\n expiresAt: number\n interval: number\n}\n\nconst DEFAULT_SCOPE = 'openid profile email offline_access'\nconst DEVICE_GRANT = 'urn:ietf:params:oauth:grant-type:device_code'\n\nfunction isNonemptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0\n}\n\nfunction base64url(bytes: Uint8Array): string {\n let binary = ''\n for (const byte of bytes) binary += String.fromCharCode(byte)\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/** Create an RFC 7636 verifier and its S256 challenge with Web Crypto. */\nexport async function createPkcePair(): Promise<{ verifier: string; challenge: string }> {\n const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)))\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))\n return { verifier, challenge: base64url(new Uint8Array(digest)) }\n}\n\nfunction oauthError(body: unknown, fallback: string): string {\n if (!isRecord(body)) return fallback\n if (isNonemptyString(body.error_description)) return body.error_description\n if (isNonemptyString(body.error)) return body.error\n return fallback\n}\n\nfunction parseTokens(body: unknown, status: number): OidcTokens {\n if (!isRecord(body) || !isNonemptyString(body.access_token)) {\n throw new PlatformAuthError('Platform token response is malformed', status, {\n code: 'INVALID_TOKEN_RESPONSE',\n })\n }\n return {\n accessToken: body.access_token,\n tokenType: isNonemptyString(body.token_type) ? body.token_type : 'Bearer',\n ...(typeof body.expires_in === 'number' ? { expiresIn: body.expires_in } : {}),\n ...(isNonemptyString(body.refresh_token) ? { refreshToken: body.refresh_token } : {}),\n ...(isNonemptyString(body.id_token) ? { idToken: body.id_token } : {}),\n ...(isNonemptyString(body.scope) ? { scope: body.scope } : {}),\n }\n}\n\nfunction formComponent(value: string): string {\n return new URLSearchParams({ v: value }).toString().slice(2)\n}\n\nfunction pause(ms: number, signal?: AbortSignal): Promise<void> {\n signal?.throwIfAborted()\n return new Promise((resolve, reject) => {\n const finish = () => {\n signal?.removeEventListener('abort', abort)\n resolve()\n }\n const timer = setTimeout(finish, ms)\n const abort = () => {\n clearTimeout(timer)\n signal?.removeEventListener('abort', abort)\n reject(signal?.reason ?? new Error('Device authorization cancelled'))\n }\n signal?.addEventListener('abort', abort, { once: true })\n })\n}\n\n/** OIDC code + PKCE, refresh/revoke and discovery-bound RFC 8628 device grants. */\nexport class PlatformOidcClient {\n private readonly baseUrl: string\n private readonly clientId: string\n private readonly clientSecret: string | undefined\n private readonly redirectUri: string | undefined\n private readonly scope: string\n private readonly resources: readonly string[]\n private readonly fetchImpl: typeof fetch\n\n constructor(options: PlatformOidcClientOptions) {\n if (!options.baseUrl) throw new Error('PlatformOidcClient: baseUrl is required')\n if (!options.clientId) throw new Error('PlatformOidcClient: clientId is required')\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '')\n this.clientId = options.clientId\n this.clientSecret = options.clientSecret || undefined\n this.redirectUri = options.redirectUri\n this.scope = options.scope ?? DEFAULT_SCOPE\n this.resources = [...new Set(options.resources ?? [])]\n for (const resource of this.resources) {\n const url = new URL(resource)\n if (url.hash || url.username || url.password) {\n throw new Error('PlatformOidcClient: resource must not contain a fragment or credentials')\n }\n }\n this.fetchImpl = options.fetchImpl ?? ((input, init) => fetch(input, init))\n }\n\n authorizeUrl(options: OidcAuthorizeUrlOptions): string {\n if (!this.redirectUri)\n throw new Error('PlatformOidcClient: redirectUri is required for authorization code')\n if (!options.state)\n throw new Error('PlatformOidcClient.authorizeUrl: state is required for CSRF')\n if (!options.codeChallenge)\n throw new Error('PlatformOidcClient.authorizeUrl: codeChallenge is required for PKCE')\n const url = new URL('/api/auth/oauth2/authorize', this.baseUrl)\n url.searchParams.set('client_id', this.clientId)\n url.searchParams.set('redirect_uri', this.redirectUri)\n url.searchParams.set('response_type', 'code')\n url.searchParams.set('scope', this.scope)\n url.searchParams.set('state', options.state)\n url.searchParams.set('code_challenge', options.codeChallenge)\n url.searchParams.set('code_challenge_method', 'S256')\n for (const resource of this.resources) url.searchParams.append('resource', resource)\n if (options.nonce) url.searchParams.set('nonce', options.nonce)\n if (options.prompt) url.searchParams.set('prompt', options.prompt)\n if (options.loginHint) url.searchParams.set('login_hint', options.loginHint)\n return url.toString()\n }\n\n async exchange(code: string, codeVerifier: string): Promise<OidcExchangeResult> {\n if (!this.redirectUri)\n throw new Error('PlatformOidcClient: redirectUri is required for authorization code')\n if (!code) throw new Error('PlatformOidcClient.exchange: code is required')\n if (!codeVerifier)\n throw new Error('PlatformOidcClient.exchange: codeVerifier is required for PKCE')\n const tokens = await this.token({\n grant_type: 'authorization_code',\n code,\n redirect_uri: this.redirectUri,\n code_verifier: codeVerifier,\n })\n return { tokens, user: await this.userinfo(tokens.accessToken) }\n }\n\n /** Save the replacement refresh token. Never retry an old token as a new grant. */\n async refresh(refreshToken: string): Promise<OidcTokens> {\n if (!refreshToken) throw new Error('PlatformOidcClient.refresh: refreshToken is required')\n return this.token({ grant_type: 'refresh_token', refresh_token: refreshToken })\n }\n\n async userinfo(accessToken: string): Promise<OidcUser> {\n if (!accessToken) throw new Error('PlatformOidcClient.userinfo: accessToken is required')\n const res = await this.fetchImpl(`${this.baseUrl}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${accessToken}` },\n redirect: 'error',\n })\n const body: unknown = await res.json().catch(() => null)\n if (!res.ok)\n throw new PlatformAuthError(\n oauthError(body, `Platform userinfo failed (${res.status})`),\n res.status,\n body,\n )\n if (\n !isRecord(body) ||\n !isNonemptyString(body.sub) ||\n !isNonemptyString(body.email) ||\n body.email_verified !== true\n ) {\n throw new PlatformAuthError('Platform userinfo has no verified identity', res.status, {\n code: 'INVALID_USERINFO_RESPONSE',\n })\n }\n return {\n id: body.sub,\n email: body.email,\n emailVerified: true,\n ...(isNonemptyString(body.name) ? { name: body.name } : {}),\n }\n }\n\n /** RFC 7009. A local logout alone is not a provider disconnect. */\n async revoke(token: string, tokenTypeHint?: 'access_token' | 'refresh_token'): Promise<void> {\n if (!token) throw new Error('PlatformOidcClient.revoke: token is required')\n const res = await this.post(\n `${this.baseUrl}/api/auth/oauth2/revoke`,\n {\n token,\n ...(tokenTypeHint ? { token_type_hint: tokenTypeHint } : {}),\n },\n undefined,\n false,\n )\n if (!res.ok) {\n const body: unknown = await res.json().catch(() => null)\n throw new PlatformAuthError(\n oauthError(body, `Platform revoke failed (${res.status})`),\n res.status,\n body,\n )\n }\n }\n\n /**\n * Start a device grant only when this issuer advertises the OAuth-integrated\n * device endpoint. No fallback to /cross-site/device or a standalone session\n * device endpoint: those issue different credentials.\n */\n async deviceAuthorize(options: { signal?: AbortSignal } = {}): Promise<OidcDeviceAuthorization> {\n const discovery = await this.fetchImpl(\n `${this.baseUrl}/api/auth/.well-known/openid-configuration`,\n {\n redirect: 'error',\n signal: options.signal,\n },\n )\n const metadata: unknown = await discovery.json().catch(() => null)\n const issuer = `${this.baseUrl}/api/auth`\n if (\n !discovery.ok ||\n !isRecord(metadata) ||\n metadata.issuer !== issuer ||\n metadata.token_endpoint !== `${issuer}/oauth2/token` ||\n !Array.isArray(metadata.grant_types_supported) ||\n !metadata.grant_types_supported.includes(DEVICE_GRANT) ||\n !isNonemptyString(metadata.device_authorization_endpoint)\n ) {\n throw new PlatformAuthError(\n 'Issuer does not advertise an OAuth device grant',\n discovery.status,\n { code: 'OAUTH_DEVICE_GRANT_UNAVAILABLE' },\n )\n }\n const endpoint = new URL(metadata.device_authorization_endpoint)\n const origin = new URL(this.baseUrl).origin\n if (endpoint.origin !== origin || endpoint.username || endpoint.password || endpoint.hash) {\n throw new PlatformAuthError('Device endpoint is outside the configured issuer', 400, {\n code: 'INVALID_DEVICE_ENDPOINT',\n })\n }\n const startedAt = Date.now()\n const res = await this.post(endpoint.href, { scope: this.scope }, options.signal)\n const body: unknown = await res.json().catch(() => null)\n if (!res.ok)\n throw new PlatformAuthError(\n oauthError(body, `Device authorization failed (${res.status})`),\n res.status,\n body,\n )\n if (\n !isRecord(body) ||\n !isNonemptyString(body.device_code) ||\n !isNonemptyString(body.user_code) ||\n !isNonemptyString(body.verification_uri) ||\n typeof body.expires_in !== 'number' ||\n !Number.isSafeInteger(body.expires_in) ||\n body.expires_in <= 0 ||\n (body.interval !== undefined &&\n (typeof body.interval !== 'number' ||\n !Number.isSafeInteger(body.interval) ||\n body.interval <= 0))\n ) {\n throw new PlatformAuthError('Malformed device authorization response', res.status, {\n code: 'INVALID_DEVICE_RESPONSE',\n })\n }\n for (const value of [body.verification_uri, body.verification_uri_complete]) {\n if (value === undefined) continue\n if (!isNonemptyString(value))\n throw new PlatformAuthError('Invalid device verification URI', 400, {\n code: 'INVALID_DEVICE_RESPONSE',\n })\n const uri = new URL(value)\n if (uri.origin !== origin || uri.username || uri.password || uri.hash) {\n throw new PlatformAuthError('Device verification URI is outside the issuer', 400, {\n code: 'INVALID_DEVICE_RESPONSE',\n })\n }\n }\n return {\n deviceCode: body.device_code,\n userCode: body.user_code,\n verificationUri: body.verification_uri,\n ...(isNonemptyString(body.verification_uri_complete)\n ? { verificationUriComplete: body.verification_uri_complete }\n : {}),\n expiresIn: body.expires_in,\n expiresAt: startedAt + body.expires_in * 1000,\n interval: typeof body.interval === 'number' ? body.interval : 5,\n }\n }\n\n /** RFC 8628 pending/slow_down handling, expiry, cancellation and timeout backoff. */\n async pollDeviceAuthorization(\n grant: OidcDeviceAuthorization,\n options: { signal?: AbortSignal } = {},\n ): Promise<OidcTokens> {\n if (\n !grant.deviceCode ||\n !Number.isFinite(grant.expiresAt) ||\n !Number.isFinite(grant.interval) ||\n grant.interval <= 0\n ) {\n throw new Error('PlatformOidcClient.pollDeviceAuthorization: invalid device grant')\n }\n let intervalMs = grant.interval * 1000\n while (Date.now() < grant.expiresAt) {\n options.signal?.throwIfAborted()\n await pause(Math.min(intervalMs, Math.max(0, grant.expiresAt - Date.now())), options.signal)\n const remaining = grant.expiresAt - Date.now()\n if (remaining <= 0) break\n const timeout = AbortSignal.timeout(Math.max(1, Math.min(30_000, Math.floor(remaining))))\n const signal = options.signal ? AbortSignal.any([options.signal, timeout]) : timeout\n try {\n return await this.token({ grant_type: DEVICE_GRANT, device_code: grant.deviceCode }, signal)\n } catch (error) {\n options.signal?.throwIfAborted()\n if (timeout.aborted) {\n intervalMs *= 2\n continue\n }\n if (!(error instanceof PlatformAuthError) || !isRecord(error.body)) throw error\n if (error.body.error === 'authorization_pending') continue\n if (error.body.error === 'slow_down') {\n intervalMs += 5_000\n continue\n }\n throw error\n }\n }\n throw new PlatformAuthError('Device authorization expired', 400, { error: 'expired_token' })\n }\n\n private async token(params: Record<string, string>, signal?: AbortSignal): Promise<OidcTokens> {\n const res = await this.post(`${this.baseUrl}/api/auth/oauth2/token`, params, signal)\n const body: unknown = await res.json().catch(() => null)\n if (!res.ok)\n throw new PlatformAuthError(\n oauthError(body, `Platform token request failed (${res.status})`),\n res.status,\n body,\n )\n return parseTokens(body, res.status)\n }\n\n private post(\n url: string,\n params: Record<string, string>,\n signal?: AbortSignal,\n includeResources = true,\n ): Promise<Response> {\n const body = new URLSearchParams(params)\n const headers: Record<string, string> = { 'content-type': 'application/x-www-form-urlencoded' }\n if (this.clientSecret) {\n // RFC 6749 section 2.3.1: form-encode each component before HTTP Basic.\n headers.authorization = `Basic ${btoa(`${formComponent(this.clientId)}:${formComponent(this.clientSecret)}`)}`\n } else body.set('client_id', this.clientId)\n if (includeResources) for (const resource of this.resources) body.append('resource', resource)\n return this.fetchImpl(url, { method: 'POST', headers, body, redirect: 'error', signal })\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"platform.js","names":["isNonemptyString"],"sources":["../src/platform/auth.ts","../src/platform/integrations.ts","../src/platform/oidc.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 * the cross-site route in agent-container's platform API. This client only\n * speaks HTTP — no SDK weight, no transitive deps.\n */\n\nimport { isRecord } from '@tangle-network/agent-core'\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 emailVerified: true\n user: {\n id: string\n email: string\n name?: string | null\n }\n /** Null when the platform could not provide a subscription. This is not a paid-access grant. */\n plan: {\n tier: string\n } | null\n}\n\n/** Thrown when a `PlatformAuthClient` request returns a non-success status. */\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\nfunction isNonemptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0\n}\n\n/** Validate the platform's verified identity before consumers create a local session. */\nfunction parseExchangeResult(body: unknown, status: number): ExchangeCodeResult {\n const invalid = (): never => {\n // A successful but malformed response can contain the one-time API secret.\n throw new PlatformAuthError(\n 'Platform exchange response has no valid verified identity',\n status,\n { code: 'INVALID_EXCHANGE_RESPONSE' },\n )\n }\n if (\n !isRecord(body) ||\n !isNonemptyString(body.apiKey) ||\n body.emailVerified !== true ||\n !isRecord(body.user)\n )\n return invalid()\n const user = body.user\n if (!isNonemptyString(user.id) || !isNonemptyString(user.email)) return invalid()\n const email = user.email.trim()\n if (\n email.length > 320 ||\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email) ||\n /(?:@users\\.noreply\\.tangle\\.tools$|^0x[a-f0-9]{40}@tangle\\.tools$)/i.test(email)\n )\n return invalid()\n if (user.name !== undefined && user.name !== null && typeof user.name !== 'string')\n return invalid()\n let plan: ExchangeCodeResult['plan'] = null\n if (body.subscription !== undefined) {\n if (!isRecord(body.subscription) || !isNonemptyString(body.subscription.plan)) return invalid()\n plan = { tier: body.subscription.plan }\n }\n return {\n apiKey: body.apiKey,\n emailVerified: true,\n user: { id: user.id, email, ...(user.name !== undefined ? { name: user.name } : {}) },\n plan,\n }\n}\n\n/** HTTP client for the Tangle Platform SSO: builds authorize URLs and exchanges auth codes for API keys. */\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 return parseExchangeResult(body, res.status)\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 API's hub contract\n * and hub route (both in agent-container's platform API). 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\n/** Thrown when a `PlatformHubClient` request returns a non-success status. */\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\n/** HTTP client for the Tangle Platform Hub API: provider catalog, connection flow, and status. */\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","/**\n * OpenID Connect client for the Tangle authorization server. Identity tokens\n * are not platform API keys. Resource scopes and audiences must be registered\n * by the provider before a consumer can use these tokens at a paid API.\n */\n\nimport { isRecord } from '@tangle-network/agent-core'\nimport { PlatformAuthError } from './auth.js'\n\nexport interface PlatformOidcClientOptions {\n baseUrl: string\n clientId: string\n /** Omit only for clients registered with token_endpoint_auth_method=none. */\n clientSecret?: string\n /** Required for authorization code; not required for the device grant. */\n redirectUri?: string\n scope?: string\n /** RFC 8707 resource identifiers registered at the authorization server. */\n resources?: readonly string[]\n fetchImpl?: typeof fetch\n}\n\nexport interface OidcAuthorizeUrlOptions {\n state: string\n codeChallenge: string\n /** Only supply a nonce when the consumer also validates the ID token. */\n nonce?: string\n prompt?: 'login' | 'consent' | 'none'\n loginHint?: string\n}\n\nexport interface OidcTokens {\n accessToken: string\n tokenType: string\n expiresIn?: number\n refreshToken?: string\n idToken?: string\n scope?: string\n}\n\nexport interface OidcUser {\n id: string\n email: string\n emailVerified: true\n name?: string\n}\n\nexport interface OidcExchangeResult {\n tokens: OidcTokens\n user: OidcUser\n}\n\n/** Keep deviceCode secret. Only userCode and the verification URLs are displayed. */\nexport interface OidcDeviceAuthorization {\n deviceCode: string\n userCode: string\n verificationUri: string\n verificationUriComplete?: string\n expiresIn: number\n /** Absolute deadline preserves expiry when a polling process resumes. */\n expiresAt: number\n interval: number\n}\n\nconst DEFAULT_SCOPE = 'openid profile email offline_access'\nconst DEVICE_GRANT = 'urn:ietf:params:oauth:grant-type:device_code'\n\nfunction isNonemptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0\n}\n\nfunction base64url(bytes: Uint8Array): string {\n let binary = ''\n for (const byte of bytes) binary += String.fromCharCode(byte)\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/** Create an RFC 7636 verifier and its S256 challenge with Web Crypto. */\nexport async function createPkcePair(): Promise<{ verifier: string; challenge: string }> {\n const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)))\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))\n return { verifier, challenge: base64url(new Uint8Array(digest)) }\n}\n\nfunction oauthError(body: unknown, fallback: string): string {\n if (!isRecord(body)) return fallback\n if (isNonemptyString(body.error_description)) return body.error_description\n if (isNonemptyString(body.error)) return body.error\n return fallback\n}\n\nfunction parseTokens(body: unknown, status: number): OidcTokens {\n if (!isRecord(body) || !isNonemptyString(body.access_token)) {\n throw new PlatformAuthError('Platform token response is malformed', status, {\n code: 'INVALID_TOKEN_RESPONSE',\n })\n }\n return {\n accessToken: body.access_token,\n tokenType: isNonemptyString(body.token_type) ? body.token_type : 'Bearer',\n ...(typeof body.expires_in === 'number' ? { expiresIn: body.expires_in } : {}),\n ...(isNonemptyString(body.refresh_token) ? { refreshToken: body.refresh_token } : {}),\n ...(isNonemptyString(body.id_token) ? { idToken: body.id_token } : {}),\n ...(isNonemptyString(body.scope) ? { scope: body.scope } : {}),\n }\n}\n\nfunction formComponent(value: string): string {\n return new URLSearchParams({ v: value }).toString().slice(2)\n}\n\nfunction pause(ms: number, signal?: AbortSignal): Promise<void> {\n signal?.throwIfAborted()\n return new Promise((resolve, reject) => {\n const finish = () => {\n signal?.removeEventListener('abort', abort)\n resolve()\n }\n const timer = setTimeout(finish, ms)\n const abort = () => {\n clearTimeout(timer)\n signal?.removeEventListener('abort', abort)\n reject(signal?.reason ?? new Error('Device authorization cancelled'))\n }\n signal?.addEventListener('abort', abort, { once: true })\n })\n}\n\n/** OIDC code + PKCE, refresh/revoke and discovery-bound RFC 8628 device grants. */\nexport class PlatformOidcClient {\n private readonly baseUrl: string\n private readonly clientId: string\n private readonly clientSecret: string | undefined\n private readonly redirectUri: string | undefined\n private readonly scope: string\n private readonly resources: readonly string[]\n private readonly fetchImpl: typeof fetch\n\n constructor(options: PlatformOidcClientOptions) {\n if (!options.baseUrl) throw new Error('PlatformOidcClient: baseUrl is required')\n if (!options.clientId) throw new Error('PlatformOidcClient: clientId is required')\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '')\n this.clientId = options.clientId\n this.clientSecret = options.clientSecret || undefined\n this.redirectUri = options.redirectUri\n this.scope = options.scope ?? DEFAULT_SCOPE\n this.resources = [...new Set(options.resources ?? [])]\n for (const resource of this.resources) {\n const url = new URL(resource)\n if (url.hash || url.username || url.password) {\n throw new Error('PlatformOidcClient: resource must not contain a fragment or credentials')\n }\n }\n this.fetchImpl = options.fetchImpl ?? ((input, init) => fetch(input, init))\n }\n\n authorizeUrl(options: OidcAuthorizeUrlOptions): string {\n if (!this.redirectUri)\n throw new Error('PlatformOidcClient: redirectUri is required for authorization code')\n if (!options.state)\n throw new Error('PlatformOidcClient.authorizeUrl: state is required for CSRF')\n if (!options.codeChallenge)\n throw new Error('PlatformOidcClient.authorizeUrl: codeChallenge is required for PKCE')\n const url = new URL('/api/auth/oauth2/authorize', this.baseUrl)\n url.searchParams.set('client_id', this.clientId)\n url.searchParams.set('redirect_uri', this.redirectUri)\n url.searchParams.set('response_type', 'code')\n url.searchParams.set('scope', this.scope)\n url.searchParams.set('state', options.state)\n url.searchParams.set('code_challenge', options.codeChallenge)\n url.searchParams.set('code_challenge_method', 'S256')\n for (const resource of this.resources) url.searchParams.append('resource', resource)\n if (options.nonce) url.searchParams.set('nonce', options.nonce)\n if (options.prompt) url.searchParams.set('prompt', options.prompt)\n if (options.loginHint) url.searchParams.set('login_hint', options.loginHint)\n return url.toString()\n }\n\n async exchange(code: string, codeVerifier: string): Promise<OidcExchangeResult> {\n if (!this.redirectUri)\n throw new Error('PlatformOidcClient: redirectUri is required for authorization code')\n if (!code) throw new Error('PlatformOidcClient.exchange: code is required')\n if (!codeVerifier)\n throw new Error('PlatformOidcClient.exchange: codeVerifier is required for PKCE')\n const tokens = await this.token({\n grant_type: 'authorization_code',\n code,\n redirect_uri: this.redirectUri,\n code_verifier: codeVerifier,\n })\n return { tokens, user: await this.userinfo(tokens.accessToken) }\n }\n\n /** Save the replacement refresh token. Never retry an old token as a new grant. */\n async refresh(refreshToken: string): Promise<OidcTokens> {\n if (!refreshToken) throw new Error('PlatformOidcClient.refresh: refreshToken is required')\n return this.token({ grant_type: 'refresh_token', refresh_token: refreshToken })\n }\n\n async userinfo(accessToken: string): Promise<OidcUser> {\n if (!accessToken) throw new Error('PlatformOidcClient.userinfo: accessToken is required')\n const res = await this.fetchImpl(`${this.baseUrl}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${accessToken}` },\n redirect: 'error',\n })\n const body: unknown = await res.json().catch(() => null)\n if (!res.ok)\n throw new PlatformAuthError(\n oauthError(body, `Platform userinfo failed (${res.status})`),\n res.status,\n body,\n )\n if (\n !isRecord(body) ||\n !isNonemptyString(body.sub) ||\n !isNonemptyString(body.email) ||\n body.email_verified !== true\n ) {\n throw new PlatformAuthError('Platform userinfo has no verified identity', res.status, {\n code: 'INVALID_USERINFO_RESPONSE',\n })\n }\n return {\n id: body.sub,\n email: body.email,\n emailVerified: true,\n ...(isNonemptyString(body.name) ? { name: body.name } : {}),\n }\n }\n\n /** RFC 7009. A local logout alone is not a provider disconnect. */\n async revoke(token: string, tokenTypeHint?: 'access_token' | 'refresh_token'): Promise<void> {\n if (!token) throw new Error('PlatformOidcClient.revoke: token is required')\n const res = await this.post(\n `${this.baseUrl}/api/auth/oauth2/revoke`,\n {\n token,\n ...(tokenTypeHint ? { token_type_hint: tokenTypeHint } : {}),\n },\n undefined,\n false,\n )\n if (!res.ok) {\n const body: unknown = await res.json().catch(() => null)\n throw new PlatformAuthError(\n oauthError(body, `Platform revoke failed (${res.status})`),\n res.status,\n body,\n )\n }\n }\n\n /**\n * Start a device grant only when this issuer advertises the OAuth-integrated\n * device endpoint. No fallback to /cross-site/device or a standalone session\n * device endpoint: those issue different credentials.\n */\n async deviceAuthorize(options: { signal?: AbortSignal } = {}): Promise<OidcDeviceAuthorization> {\n const discovery = await this.fetchImpl(\n `${this.baseUrl}/api/auth/.well-known/openid-configuration`,\n {\n redirect: 'error',\n signal: options.signal,\n },\n )\n const metadata: unknown = await discovery.json().catch(() => null)\n const issuer = `${this.baseUrl}/api/auth`\n if (\n !discovery.ok ||\n !isRecord(metadata) ||\n metadata.issuer !== issuer ||\n metadata.token_endpoint !== `${issuer}/oauth2/token` ||\n !Array.isArray(metadata.grant_types_supported) ||\n !metadata.grant_types_supported.includes(DEVICE_GRANT) ||\n !isNonemptyString(metadata.device_authorization_endpoint)\n ) {\n throw new PlatformAuthError(\n 'Issuer does not advertise an OAuth device grant',\n discovery.status,\n { code: 'OAUTH_DEVICE_GRANT_UNAVAILABLE' },\n )\n }\n const endpoint = new URL(metadata.device_authorization_endpoint)\n const origin = new URL(this.baseUrl).origin\n if (endpoint.origin !== origin || endpoint.username || endpoint.password || endpoint.hash) {\n throw new PlatformAuthError('Device endpoint is outside the configured issuer', 400, {\n code: 'INVALID_DEVICE_ENDPOINT',\n })\n }\n const startedAt = Date.now()\n const res = await this.post(endpoint.href, { scope: this.scope }, options.signal)\n const body: unknown = await res.json().catch(() => null)\n if (!res.ok)\n throw new PlatformAuthError(\n oauthError(body, `Device authorization failed (${res.status})`),\n res.status,\n body,\n )\n if (\n !isRecord(body) ||\n !isNonemptyString(body.device_code) ||\n !isNonemptyString(body.user_code) ||\n !isNonemptyString(body.verification_uri) ||\n typeof body.expires_in !== 'number' ||\n !Number.isSafeInteger(body.expires_in) ||\n body.expires_in <= 0 ||\n (body.interval !== undefined &&\n (typeof body.interval !== 'number' ||\n !Number.isSafeInteger(body.interval) ||\n body.interval <= 0))\n ) {\n throw new PlatformAuthError('Malformed device authorization response', res.status, {\n code: 'INVALID_DEVICE_RESPONSE',\n })\n }\n for (const value of [body.verification_uri, body.verification_uri_complete]) {\n if (value === undefined) continue\n if (!isNonemptyString(value))\n throw new PlatformAuthError('Invalid device verification URI', 400, {\n code: 'INVALID_DEVICE_RESPONSE',\n })\n const uri = new URL(value)\n if (uri.origin !== origin || uri.username || uri.password || uri.hash) {\n throw new PlatformAuthError('Device verification URI is outside the issuer', 400, {\n code: 'INVALID_DEVICE_RESPONSE',\n })\n }\n }\n return {\n deviceCode: body.device_code,\n userCode: body.user_code,\n verificationUri: body.verification_uri,\n ...(isNonemptyString(body.verification_uri_complete)\n ? { verificationUriComplete: body.verification_uri_complete }\n : {}),\n expiresIn: body.expires_in,\n expiresAt: startedAt + body.expires_in * 1000,\n interval: typeof body.interval === 'number' ? body.interval : 5,\n }\n }\n\n /** RFC 8628 pending/slow_down handling, expiry, cancellation and timeout backoff. */\n async pollDeviceAuthorization(\n grant: OidcDeviceAuthorization,\n options: { signal?: AbortSignal } = {},\n ): Promise<OidcTokens> {\n if (\n !grant.deviceCode ||\n !Number.isFinite(grant.expiresAt) ||\n !Number.isFinite(grant.interval) ||\n grant.interval <= 0\n ) {\n throw new Error('PlatformOidcClient.pollDeviceAuthorization: invalid device grant')\n }\n let intervalMs = grant.interval * 1000\n while (Date.now() < grant.expiresAt) {\n options.signal?.throwIfAborted()\n await pause(Math.min(intervalMs, Math.max(0, grant.expiresAt - Date.now())), options.signal)\n const remaining = grant.expiresAt - Date.now()\n if (remaining <= 0) break\n const timeout = AbortSignal.timeout(Math.max(1, Math.min(30_000, Math.floor(remaining))))\n const signal = options.signal ? AbortSignal.any([options.signal, timeout]) : timeout\n try {\n return await this.token({ grant_type: DEVICE_GRANT, device_code: grant.deviceCode }, signal)\n } catch (error) {\n options.signal?.throwIfAborted()\n if (timeout.aborted) {\n intervalMs *= 2\n continue\n }\n if (!(error instanceof PlatformAuthError) || !isRecord(error.body)) throw error\n if (error.body.error === 'authorization_pending') continue\n if (error.body.error === 'slow_down') {\n intervalMs += 5_000\n continue\n }\n throw error\n }\n }\n throw new PlatformAuthError('Device authorization expired', 400, { error: 'expired_token' })\n }\n\n private async token(params: Record<string, string>, signal?: AbortSignal): Promise<OidcTokens> {\n const res = await this.post(`${this.baseUrl}/api/auth/oauth2/token`, params, signal)\n const body: unknown = await res.json().catch(() => null)\n if (!res.ok)\n throw new PlatformAuthError(\n oauthError(body, `Platform token request failed (${res.status})`),\n res.status,\n body,\n )\n return parseTokens(body, res.status)\n }\n\n private post(\n url: string,\n params: Record<string, string>,\n signal?: AbortSignal,\n includeResources = true,\n ): Promise<Response> {\n const body = new URLSearchParams(params)\n const headers: Record<string, string> = { 'content-type': 'application/x-www-form-urlencoded' }\n if (this.clientSecret) {\n // RFC 6749 section 2.3.1: form-encode each component before HTTP Basic.\n headers.authorization = `Basic ${btoa(`${formComponent(this.clientId)}:${formComponent(this.clientSecret)}`)}`\n } else body.set('client_id', this.clientId)\n if (includeResources) for (const resource of this.resources) body.append('resource', resource)\n return this.fetchImpl(url, { method: 'POST', headers, body, redirect: 'error', signal })\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
- import { A as verifyMaterializedProfileWorkspace, B as sha256Bytes$1, D as readMaterializedWorkspaceFiles, F as canonicalCandidateDocument, H as hasControlCharacter, I as deepFreezeCandidate, L as embeddedCandidateArtifact, M as verifyWorkspaceSnapshotArtifacts, N as canonicalCandidateBytes$1, O as readVerifiedArtifact, P as canonicalCandidateDigest$1, R as immutableCandidateValue, S as isWellFormedUnicode, X as errorMessage, b as persistCandidateOutputArtifact, d as readCandidateGitHubResource, f as verifyCandidateCode, j as verifyMaterializedWorkspace, k as verifyBytes, m as verifyTaskOutcomePatch, p as verifyTaskCheckout, w as artifactCacheKey, x as assertExactObjectKeys, z as omitTopLevelDigest } from "./sandbox-profile-compat-DtuJWFrM.js";
2
- import { _ as parseAgentCandidateProfileActivation, c as buildLaunch, f as exactProfileExecutorFiles, h as modelRoutes, l as candidateEntrypointReceipt, m as materializeAgentCandidateProfilePlan, n as PI_CANDIDATE_SESSION_DIR_ENV, r as absoluteExecutionCwd, s as assertCandidateProfileExecutionSupport, t as PI_CANDIDATE_AGENT_DIR_ENV, u as candidateProfileAgentPaths, x as requirePublicCandidateConfigValue } from "./profile-JLJd2wFG.js";
3
- import { i as redactProtectedValue, n as createProtectedRecordRedactor, r as redactProtectedReason, t as assertNoProtectedBytes } from "./protected-redaction-DFCeo4vg.js";
1
+ import { c as errorMessage } from "./util-ebWMWzY0.js";
2
+ import { A as verifyMaterializedProfileWorkspace, B as sha256Bytes$1, D as readMaterializedWorkspaceFiles, F as canonicalCandidateDocument, H as hasControlCharacter, I as deepFreezeCandidate, L as embeddedCandidateArtifact, M as verifyWorkspaceSnapshotArtifacts, N as canonicalCandidateBytes$1, O as readVerifiedArtifact, P as canonicalCandidateDigest$1, R as immutableCandidateValue, S as isWellFormedUnicode, b as persistCandidateOutputArtifact, d as readCandidateGitHubResource, f as verifyCandidateCode, j as verifyMaterializedWorkspace, k as verifyBytes, m as verifyTaskOutcomePatch, p as verifyTaskCheckout, w as artifactCacheKey, x as assertExactObjectKeys, z as omitTopLevelDigest } from "./sandbox-profile-compat-CXjozdWL.js";
3
+ import { _ as parseAgentCandidateProfileActivation, c as buildLaunch, f as exactProfileExecutorFiles, h as modelRoutes, l as candidateEntrypointReceipt, m as materializeAgentCandidateProfilePlan, n as PI_CANDIDATE_SESSION_DIR_ENV, r as absoluteExecutionCwd, s as assertCandidateProfileExecutionSupport, t as PI_CANDIDATE_AGENT_DIR_ENV, u as candidateProfileAgentPaths, x as requirePublicCandidateConfigValue } from "./profile-C01SQZKa.js";
4
+ import { i as redactProtectedValue, n as createProtectedRecordRedactor, r as redactProtectedReason, t as assertNoProtectedBytes } from "./protected-redaction-DilFZch5.js";
4
5
  import { agentCandidateArtifactRefSchema, agentCandidateBenchmarkResultEvidenceSchema, agentCandidateBenchmarkSuiteSchema, agentCandidateBenchmarkTaskSchema, agentCandidateBundleSchema, agentCandidateContainerSchema, agentCandidateExecutionLimitsSchema, agentCandidateExecutionPlanEvidenceSchema, agentCandidateExecutionPlanMaterialSchema, agentCandidateMaterializationReceiptSchema, agentCandidateModelAccessNetworkSchema, agentCandidateModelSettlementEvidenceSchema, agentCandidateProfilePlanEvidenceSchema, agentCandidateResolvedModelSchema, agentCandidateRunCellSchema, agentCandidateRunReceiptSchema, agentCandidateTaskOutcomeEvidenceSchema, agentCandidateTaskOutcomeSpecSchema, agentCandidateTerminationSchema, agentCandidateWorkspaceManifestMaterialSchema, agentCandidateWorkspaceSnapshotEvidenceSchema, sha256DigestSchema } from "@tangle-network/agent-interface";
5
6
  import { REDACTION_VERSION, isLlmSpan } from "@tangle-network/agent-eval";
6
7
  import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
@@ -10,7 +11,7 @@ import { applyAgentCandidateWorkspacePlan } from "@tangle-network/agent-profile-
10
11
  import { isDeepStrictEqual } from "node:util";
11
12
  import { tmpdir } from "node:os";
12
13
  import { hashKnowledgeBase } from "@tangle-network/agent-knowledge";
13
- //#region src/candidate-execution/execution-roots.ts
14
+ // src/candidate-execution/execution-roots.ts
14
15
  /** Validate the canonical identity and isolation boundary for execution roots. */
15
16
  function assertAgentCandidateExecutionRoots(roots) {
16
17
  const entries = [
@@ -40,8 +41,7 @@ function executionPathsOverlap(left, right) {
40
41
  const b = posix.normalize(right);
41
42
  return a === b || b.startsWith(a === "/" ? "/" : `${a}/`) || a.startsWith(b === "/" ? "/" : `${b}/`);
42
43
  }
43
- //#endregion
44
- //#region src/candidate-execution/types.ts
44
+ // src/candidate-execution/types.ts
45
45
  const verifiedCandidateBrand = Symbol("verifiedAgentCandidate");
46
46
  const preparedCandidateBrand = Symbol("preparedAgentCandidate");
47
47
  const verifiedTaskOutcomeBrand = Symbol("verifiedTaskOutcome");
@@ -60,8 +60,7 @@ const CANDIDATE_TRACE_ENV = {
60
60
  materializationReceiptDigest: "TANGLE_CANDIDATE_MATERIALIZATION_RECEIPT_DIGEST",
61
61
  traceRunId: "TANGLE_TRACE_RUN_ID"
62
62
  };
63
- //#endregion
64
- //#region src/candidate-execution/verify.ts
63
+ // src/candidate-execution/verify.ts
65
64
  const verifiedCandidateState = /* @__PURE__ */ new WeakMap();
66
65
  /** Surfaces admitted by Runtime's verifier before an environment adapter is selected. */
67
66
  const AGENT_CANDIDATE_EXECUTION_SUPPORT = Object.freeze({
@@ -174,8 +173,7 @@ function candidateResources(bundle) {
174
173
  function resourceKey(resource) {
175
174
  return canonicalCandidateDigest$1(resource);
176
175
  }
177
- //#endregion
178
- //#region src/candidate-execution/knowledge.ts
176
+ // src/candidate-execution/knowledge.ts
179
177
  /** Environment variable containing the materialized candidate knowledge root. */
180
178
  const CANDIDATE_KNOWLEDGE_ROOT_ENV = "TANGLE_CANDIDATE_KNOWLEDGE_ROOT";
181
179
  /** Environment variable containing the materialized retrieval configuration path. */
@@ -225,10 +223,9 @@ async function prepareAgentCandidateKnowledge(candidate, ports, arm) {
225
223
  });
226
224
  }
227
225
  }
228
- //#endregion
229
- //#region src/candidate-execution/exact-process-executor.ts
226
+ // src/candidate-execution/exact-process-executor.ts
230
227
  const DEFAULT_PROVISION_TIMEOUT_MS = 12e4;
231
- const DEFAULT_RECOVERY_RETENTION_MS = 15 * 6e4;
228
+ const DEFAULT_RECOVERY_RETENTION_MS = 9e5;
232
229
  /** Adapt one neutral exact-process provider to Runtime's trusted candidate boundary. */
233
230
  function exactProcessProviderAsCandidateExecutor(options) {
234
231
  return new ExactProcessAgentCandidateExecutor(options);
@@ -266,7 +263,7 @@ var ExactProcessAgentCandidateExecutor = class {
266
263
  if (this.states.has(key)) throw new Error("candidate execution environment is already active");
267
264
  const image = exactImage(request.executionPlan.value.material.container.image, request.executionPlan.value.material.container.manifestDigest);
268
265
  const maxLifetimeMs = environmentLifetimeMs(request.hardLimits.timeoutMs, this.recoveryRetentionMs);
269
- const createInputDigest = canonicalCandidateDigest$1(immutableCandidateValue({
266
+ const createMaterial = immutableCandidateValue({
270
267
  kind: "agent-candidate-exact-process-create",
271
268
  provider: this.options.provider.name,
272
269
  executionId: request.executionId,
@@ -281,7 +278,8 @@ var ExactProcessAgentCandidateExecutor = class {
281
278
  maxBytes: outcome.maxBytes
282
279
  },
283
280
  ...this.providerOptions ? { providerOptions: this.providerOptions } : {}
284
- }));
281
+ });
282
+ const createInputDigest = canonicalCandidateDigest$1(createMaterial);
285
283
  const metadata = immutableCandidateValue({
286
284
  kind: "agent-candidate-execution",
287
285
  provider: this.options.provider.name,
@@ -689,8 +687,7 @@ function beneath(root, relativePath) {
689
687
  function isSha256Digest$1(value) {
690
688
  return typeof value === "string" && /^sha256:[a-f0-9]{64}$/.test(value);
691
689
  }
692
- //#endregion
693
- //#region src/candidate-execution/model-settlement.ts
690
+ // src/candidate-execution/model-settlement.ts
694
691
  const USD_NANOS = 1e9;
695
692
  /** Validate and detach the evaluator gateway's terminal, revoked call ledger. */
696
693
  function sealAgentCandidateModelSettlement(settlement, expected) {
@@ -877,10 +874,9 @@ function safeAdd(left, right, label) {
877
874
  if (!Number.isSafeInteger(total)) throw new Error(`${label} exceeds safe integer range`);
878
875
  return total;
879
876
  }
880
- //#endregion
881
- //#region src/candidate-execution/protected-model-port.ts
877
+ // src/candidate-execution/protected-model-port.ts
882
878
  const MAX_RECENT_SETTLEMENTS = 4096;
883
- const RECOVERED_SETTLEMENT_RETENTION_MS = 900 * 1e3;
879
+ const RECOVERED_SETTLEMENT_RETENTION_MS = 9e5;
884
880
  /**
885
881
  * Bind a protected model-grant service to the immutable candidate runtime.
886
882
  *
@@ -897,7 +893,8 @@ function createProtectedAgentCandidateModelPort(options) {
897
893
  return {
898
894
  resolve: async (input) => {
899
895
  const request = immutableCandidateValue(input);
900
- return immutableCandidateValue(validateResolvedModel(await options.resolveModel(request), request));
896
+ const resolved = validateResolvedModel(await options.resolveModel(request), request);
897
+ return immutableCandidateValue(resolved);
901
898
  },
902
899
  reserveGrant: async (input) => {
903
900
  pruneExpiredState(reservations, expiredReservations, recentSettlements, Date.now());
@@ -1179,8 +1176,7 @@ function modelLimits(limits) {
1179
1176
  maxCostUsd: limits.maxCostUsd
1180
1177
  };
1181
1178
  }
1182
- //#endregion
1183
- //#region src/candidate-execution/claim-file-formats.ts
1179
+ // src/candidate-execution/claim-file-formats.ts
1184
1180
  function sealCandidatePreparationEvidence(value, executionPlanDigest) {
1185
1181
  if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("candidate execution preparation evidence must be an object");
1186
1182
  const record = value;
@@ -1193,8 +1189,7 @@ function sealCandidatePreparationEvidence(value, executionPlanDigest) {
1193
1189
  materializationReceipt
1194
1190
  });
1195
1191
  }
1196
- //#endregion
1197
- //#region src/candidate-execution/claim-terminal.ts
1192
+ // src/candidate-execution/claim-terminal.ts
1198
1193
  const SHA256_PATTERN$1 = /^sha256:[a-f0-9]{64}$/;
1199
1194
  function terminalRecord(claim, result) {
1200
1195
  const terminal = sealTerminalResult(result);
@@ -1476,8 +1471,7 @@ function assertSha256Digest$1(value, field) {
1476
1471
  function assertCount(value, label) {
1477
1472
  if (!Number.isSafeInteger(value) || value < 0) throw new Error(`candidate execution ${label} must be a non-negative safe integer`);
1478
1473
  }
1479
- //#endregion
1480
- //#region src/candidate-execution/cleanup.ts
1474
+ // src/candidate-execution/cleanup.ts
1481
1475
  const DEFAULT_CANDIDATE_CLEANUP_TIMEOUT_MS = 3e4;
1482
1476
  function candidateCleanupTimeout(timeoutMs) {
1483
1477
  const effective = timeoutMs ?? DEFAULT_CANDIDATE_CLEANUP_TIMEOUT_MS;
@@ -1539,8 +1533,7 @@ var CandidateResultTimeoutError = class extends Error {
1539
1533
  this.name = "CandidateResultTimeoutError";
1540
1534
  }
1541
1535
  };
1542
- //#endregion
1543
- //#region src/candidate-execution/claim.ts
1536
+ // src/candidate-execution/claim.ts
1544
1537
  /** Durable one-shot lifecycle for candidate execution attempts. */
1545
1538
  function attemptRecord(claim, phase, staged, terminal) {
1546
1539
  return Object.freeze({
@@ -1879,8 +1872,7 @@ const candidateClaimFileInternals = Object.freeze({
1879
1872
  sealClaim,
1880
1873
  sealLease
1881
1874
  });
1882
- //#endregion
1883
- //#region src/candidate-execution/execution-window.ts
1875
+ // src/candidate-execution/execution-window.ts
1884
1876
  const CANDIDATE_TERMINAL_PERSISTENCE_MARGIN_MS = 1e4;
1885
1877
  const CANDIDATE_POST_RUN_CLEANUP_PHASES = 4;
1886
1878
  /** Process stop, access closure, model evidence, and task/result evidence. */
@@ -1901,8 +1893,7 @@ function candidateTerminalWindowMs(cleanupTimeoutMs) {
1901
1893
  if (!Number.isSafeInteger(windowMs) || windowMs > 2147483647) throw new Error("candidate terminal window exceeds the supported timer range");
1902
1894
  return windowMs;
1903
1895
  }
1904
- //#endregion
1905
- //#region src/candidate-execution/prepared-state.ts
1896
+ // src/candidate-execution/prepared-state.ts
1906
1897
  const stateByExecution = /* @__PURE__ */ new WeakMap();
1907
1898
  const lifecycleByExecution = /* @__PURE__ */ new WeakMap();
1908
1899
  function createPreparedCandidateExecution(input) {
@@ -2037,7 +2028,8 @@ function detachPreparedCandidateState(input) {
2037
2028
  const profilePlan = immutableCandidateValue(agentCandidateProfilePlanEvidenceSchema.parse(input.profilePlan.value));
2038
2029
  const profileActivation = parseAgentCandidateProfileActivation(input.profileActivation, profilePlan.digest);
2039
2030
  const executionPlan = immutableCandidateValue(agentCandidateExecutionPlanEvidenceSchema.parse(input.executionPlan.value));
2040
- const materializationReceipt = canonicalCandidateDocument(omitTopLevelDigest(immutableCandidateValue(agentCandidateMaterializationReceiptSchema.parse(input.materializationReceipt.value))));
2031
+ const receiptValue = immutableCandidateValue(agentCandidateMaterializationReceiptSchema.parse(input.materializationReceipt.value));
2032
+ const materializationReceipt = canonicalCandidateDocument(omitTopLevelDigest(receiptValue));
2041
2033
  if (materializationReceipt.digest !== input.materializationReceipt.digest) throw new Error("materialization receipt digest changed while sealing prepared execution");
2042
2034
  return Object.freeze({
2043
2035
  ports: input.ports,
@@ -2087,7 +2079,8 @@ function detachPreparedCandidateState(input) {
2087
2079
  }
2088
2080
  function assertPrivateCandidateIntegrity(state) {
2089
2081
  assertAgentCandidateExecutionRoots(state.roots.execution);
2090
- if (canonicalCandidateDigest$1(omitTopLevelDigest(state.bundle)) !== state.bundle.digest) throw new Error("prepared candidate bundle no longer matches its digest");
2082
+ const bundleMaterial = omitTopLevelDigest(state.bundle);
2083
+ if (canonicalCandidateDigest$1(bundleMaterial) !== state.bundle.digest) throw new Error("prepared candidate bundle no longer matches its digest");
2091
2084
  assertPlanEvidence(state.profilePlan.value, state.profilePlan.bytes, "profile plan");
2092
2085
  parseAgentCandidateProfileActivation(state.profileActivation, state.profilePlan.value.digest);
2093
2086
  assertPlanEvidence(state.executionPlan.value, state.executionPlan.bytes, "execution plan");
@@ -2248,8 +2241,7 @@ function assertProtectedEnvironment(state, modelEnvironment, memoryEnvironment)
2248
2241
  seen.add(name);
2249
2242
  }
2250
2243
  }
2251
- //#endregion
2252
- //#region src/candidate-execution/claim-plan.ts
2244
+ // src/candidate-execution/claim-plan.ts
2253
2245
  /** Extract the complete durable claim from a prepared execution. */
2254
2246
  function candidateExecutionClaim(prepared, preparationEvidence) {
2255
2247
  const state = assertPreparedCandidateIntegrity(prepared);
@@ -2333,8 +2325,7 @@ function retryLineageDigest(prepared, resultTimeoutMs) {
2333
2325
  }
2334
2326
  });
2335
2327
  }
2336
- //#endregion
2337
- //#region src/candidate-execution/finalize.ts
2328
+ // src/candidate-execution/finalize.ts
2338
2329
  /** Builds a candidate run receipt exclusively from protected trace and memory evidence. */
2339
2330
  async function finalizeAgentCandidateRun(state, capture, traceStore, traceIdentity, settlement, evidence, protectedValues, writeRedactionReport, signal) {
2340
2331
  let termination;
@@ -2373,7 +2364,7 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, traceIdenti
2373
2364
  }, protectedValues);
2374
2365
  const combinedByRule = { ...writeRedactionReport?.byRule ?? {} };
2375
2366
  for (const [rule, count] of Object.entries(redacted.report.byRule)) combinedByRule[rule] = (combinedByRule[rule] ?? 0) + count;
2376
- const traceBytes = canonicalCandidateBytes$1({
2367
+ const traceMaterial = {
2377
2368
  ...redacted.value,
2378
2369
  evaluatorLimits: { resultTimeoutMs: state.resultTimeoutMs },
2379
2370
  redaction: {
@@ -2381,7 +2372,8 @@ async function finalizeAgentCandidateRun(state, capture, traceStore, traceIdenti
2381
2372
  redactionCount: (writeRedactionReport?.redactionCount ?? 0) + redacted.report.redactionCount,
2382
2373
  byRule: combinedByRule
2383
2374
  }
2384
- });
2375
+ };
2376
+ const traceBytes = canonicalCandidateBytes$1(traceMaterial);
2385
2377
  assertNoProtectedBytes(traceBytes, protectedValues);
2386
2378
  const trace = {
2387
2379
  artifact: await persistCandidateOutputArtifact(evidence.outputArtifacts, {
@@ -2514,8 +2506,7 @@ function failedAgentCandidateRun(state, reason, termination, usage = null) {
2514
2506
  function compareStrings(a, b) {
2515
2507
  return a < b ? -1 : a > b ? 1 : 0;
2516
2508
  }
2517
- //#endregion
2518
- //#region src/candidate-execution/benchmark-grader.ts
2509
+ // src/candidate-execution/benchmark-grader.ts
2519
2510
  /**
2520
2511
  * Admit verified grader bytes to the evaluator runner and reject any result
2521
2512
  * that is not bound to those bytes, the exact task outcome, and its raw output.
@@ -2560,12 +2551,13 @@ async function runBoundCandidateBenchmarkGrader(input) {
2560
2551
  }
2561
2552
  function snapshotGraderDescriptor(grader, expected) {
2562
2553
  if (!grader.name || !grader.version) throw new Error("candidate benchmark grader name and version must be non-empty");
2563
- if (canonicalCandidateDigest$1({
2554
+ const actual = {
2564
2555
  name: grader.name,
2565
2556
  version: grader.version,
2566
2557
  format: "tangle-grader",
2567
2558
  artifact: grader.artifact
2568
- }) !== canonicalCandidateDigest$1(expected)) throw new Error("candidate benchmark grader does not match the signed task grader");
2559
+ };
2560
+ if (canonicalCandidateDigest$1(actual) !== canonicalCandidateDigest$1(expected)) throw new Error("candidate benchmark grader does not match the signed task grader");
2569
2561
  return immutableCandidateValue(expected);
2570
2562
  }
2571
2563
  function emptyFixedSpend() {
@@ -2598,8 +2590,7 @@ function assertExactRunnerResult(value) {
2598
2590
  const bindingKeys = Object.keys(result.binding).sort();
2599
2591
  if (bindingKeys.length !== 3 || bindingKeys[0] !== "implementationDigest" || bindingKeys[1] !== "outputDigest" || bindingKeys[2] !== "taskOutcomeDigest") throw new Error("candidate benchmark grader binding returned unknown or missing fields");
2600
2592
  }
2601
- //#endregion
2602
- //#region src/candidate-execution/executor-capture-evidence.ts
2593
+ // src/candidate-execution/executor-capture-evidence.ts
2603
2594
  /** Persist structurally valid post-stop bytes without claiming they passed outcome verification. */
2604
2595
  async function persistAgentCandidateExecutorCapture(identity, expected, capture, outputArtifacts, signal) {
2605
2596
  const executorEvidence = capture.evidence ? await persistCandidateOutputArtifact(outputArtifacts, {
@@ -2681,8 +2672,7 @@ async function persistWorkspaceCapture(executionId, manifestPurpose, archivePurp
2681
2672
  archive
2682
2673
  };
2683
2674
  }
2684
- //#endregion
2685
- //#region src/candidate-execution/outcome-evidence.ts
2675
+ // src/candidate-execution/outcome-evidence.ts
2686
2676
  /** Persist the closed evaluator model ledger as canonical receipt evidence. */
2687
2677
  async function persistCandidateModelSettlement(state, settlement, outputArtifacts) {
2688
2678
  return await persistCandidateModelSettlementEvidence({
@@ -3033,8 +3023,7 @@ async function persistFailureEvidence(state, reason, failureClass, termination,
3033
3023
  bytes
3034
3024
  });
3035
3025
  }
3036
- //#endregion
3037
- //#region src/candidate-execution/execute-cleanup.ts
3026
+ // src/candidate-execution/execute-cleanup.ts
3038
3027
  /**
3039
3028
  * Failure and cleanup paths of an execution: closing isolated memory, settling the model grant,
3040
3029
  * recording a failed attempt's terminal result, and reporting why a run failed.
@@ -3129,8 +3118,7 @@ function protectedEnvironmentValues(activation, memoryActivation) {
3129
3118
  function joinErrors(...errors) {
3130
3119
  return errors.filter((error) => error !== void 0).map(errorMessage).join("; ");
3131
3120
  }
3132
- //#endregion
3133
- //#region src/candidate-execution/executor-capture.ts
3121
+ // src/candidate-execution/executor-capture.ts
3134
3122
  const sealedFinalCaptureBrand = Symbol("sealedAgentCandidateExecutorFinalCapture");
3135
3123
  /** Validate and detach the only candidate-authored fields accepted from execution. */
3136
3124
  function sealAgentCandidateProtectedRunCapture(value) {
@@ -3212,8 +3200,7 @@ function requireRecord(value, label) {
3212
3200
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
3213
3201
  return value;
3214
3202
  }
3215
- //#endregion
3216
- //#region src/candidate-execution/execute-executor.ts
3203
+ // src/candidate-execution/execute-executor.ts
3217
3204
  /** Run the executor until it returns or the deadline passes, then stop and capture it. */
3218
3205
  async function runAndStopExecutor(executor, request, expectedOutcome, traceStore, deadlineAtMs, cleanupTimeoutMs) {
3219
3206
  const timeoutMs = request.hardLimits.timeoutMs;
@@ -3385,8 +3372,7 @@ var CandidateExecutionDeadlineError = class extends Error {
3385
3372
  this.name = "CandidateExecutionDeadlineError";
3386
3373
  }
3387
3374
  };
3388
- //#endregion
3389
- //#region src/candidate-execution/protected-trace-store.ts
3375
+ // src/candidate-execution/protected-trace-store.ts
3390
3376
  /** Keep the identity key in evaluator-owned closures and expose only the redacting store to code. */
3391
3377
  function createProtectedAgentCandidateTraceAccess(inner, protectedValues) {
3392
3378
  const redactor = createProtectedRecordRedactor(protectedValues);
@@ -3436,8 +3422,7 @@ function createProtectedAgentCandidateTraceAccess(inner, protectedValues) {
3436
3422
  report: () => redactor.report()
3437
3423
  });
3438
3424
  }
3439
- //#endregion
3440
- //#region src/candidate-execution/execute.ts
3425
+ // src/candidate-execution/execute.ts
3441
3426
  /** Executes and finalizes one durably claimed candidate without exposing an unproven result. */
3442
3427
  async function executePreparedAgentCandidate(prepared, options) {
3443
3428
  const initialState = assertPreparedCandidateIntegrity(prepared);
@@ -3698,8 +3683,7 @@ async function finalizeEvidence(run, options, claimed, settled, modelSettlement)
3698
3683
  return failedAgentCandidateRun(state, redactProtectedReason(errorMessage(error), protectedValues), execution.termination, settlement.usage);
3699
3684
  }
3700
3685
  }
3701
- //#endregion
3702
- //#region src/candidate-execution/prepare-plan.ts
3686
+ // src/candidate-execution/prepare-plan.ts
3703
3687
  /**
3704
3688
  * The evaluator-owned documents of a preparation: the launch environment, the execution plan,
3705
3689
  * the materialization receipt, and the trace bindings that tie a run back to them.
@@ -3867,8 +3851,7 @@ function assertEnvironmentDisjoint(publicEnv, traceEnv) {
3867
3851
  seen.add(name);
3868
3852
  }
3869
3853
  }
3870
- //#endregion
3871
- //#region src/candidate-execution/prepare-workspaces.ts
3854
+ // src/candidate-execution/prepare-workspaces.ts
3872
3855
  /**
3873
3856
  * The three host staging roots of a preparation: the task workspace, the candidate workspace,
3874
3857
  * and the profile workspace, each materialized and verified against its signed material.
@@ -3946,10 +3929,9 @@ async function assertEmptyDirectory(path) {
3946
3929
  if (!stats.isDirectory() || stats.isSymbolicLink()) throw new Error("profile staging root must be a real directory");
3947
3930
  if ((await readdir(path)).length !== 0) throw new Error("profile staging root must be empty before materialization");
3948
3931
  }
3949
- //#endregion
3950
- //#region src/candidate-execution/prepare.ts
3951
- const MIN_RESERVATION_TTL_MS = 15 * 6e4;
3952
- const PREPARED_HOLD_MARGIN_MS = 5 * 6e4;
3932
+ // src/candidate-execution/prepare.ts
3933
+ const MIN_RESERVATION_TTL_MS = 9e5;
3934
+ const PREPARED_HOLD_MARGIN_MS = 3e5;
3953
3935
  /** Materializes a verified candidate into one immutable evaluator-owned execution plan. */
3954
3936
  async function prepareAgentCandidateExecution(candidate, task, ports, options = {}) {
3955
3937
  const { cleanupTimeoutMs, resultTimeoutMs, reservationWindowMs } = checkPreparation(candidate, task, ports, options);
@@ -4335,7 +4317,6 @@ async function cleanupFailedPreparation(held, error) {
4335
4317
  const cleanupErrors = (await Promise.allSettled(cleanup)).filter((result) => result.status === "rejected").map((result) => result.reason);
4336
4318
  if (cleanupErrors.length > 0) throw new Error(`candidate preparation failed and protected access cleanup failed: ${cleanupErrors.map(errorMessage).join("; ")}`, { cause: error });
4337
4319
  }
4338
- //#endregion
4339
4320
  export { verifiedResourceTextByDigest as C, AGENT_CANDIDATE_EXECUTION_SUPPORT as S, sealTerminalDigest as _, consumePreparedCandidateExecution as a, sealAgentCandidateModelSettlement as b, withinCandidateCleanupDeadline as c, assertTerminalMatchesClaim as d, assertTerminalMatchesStaged as f, requireStagedTerminal as g, rejectedStage as h, beginPreparedCandidateDisposal as i, assertRecoveryMatchesStaged as l, rejectedFinish as m, executePreparedAgentCandidate as n, candidateClaimFileInternals as o, recoveredTerminalRecord as p, assertPreparedCandidateIntegrity as r, candidateCleanupDeadline as s, prepareAgentCandidateExecution as t, assertTerminalAllowedInPhase as u, terminalRecord as v, verifyAgentCandidateBundle as w, exactProcessProviderAsCandidateExecutor as x, createProtectedAgentCandidateModelPort as y };
4340
4321
 
4341
- //# sourceMappingURL=prepare-B9wWffjO.js.map
4322
+ //# sourceMappingURL=prepare-XWwsOh8O.js.map