@tangle-network/agent-runtime 0.105.0 → 0.106.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 (218) hide show
  1. package/README.md +2 -2
  2. package/dist/activation-CRjVfOiy.js +203 -0
  3. package/dist/activation-CRjVfOiy.js.map +1 -0
  4. package/dist/activation-DyWB0K6E.d.ts +98 -0
  5. package/dist/agent.d.ts +216 -234
  6. package/dist/agent.js +615 -547
  7. package/dist/agent.js.map +1 -1
  8. package/dist/analyst-loop-DGdtVENg.js +517 -0
  9. package/dist/analyst-loop-DGdtVENg.js.map +1 -0
  10. package/dist/analyst-loop.d.ts +10 -43
  11. package/dist/analyst-loop.js +2 -11
  12. package/dist/backends-CiOCyRHb.js +743 -0
  13. package/dist/backends-CiOCyRHb.js.map +1 -0
  14. package/dist/candidate-execution/index.d.ts +4 -192
  15. package/dist/candidate-execution/index.js +5 -66
  16. package/dist/candidate-execution-DqMbv1rU.js +488 -0
  17. package/dist/candidate-execution-DqMbv1rU.js.map +1 -0
  18. package/dist/coder-yhVWbdWc.js +40 -0
  19. package/dist/coder-yhVWbdWc.js.map +1 -0
  20. package/dist/conversation-BpLQZGPH.js +1265 -0
  21. package/dist/conversation-BpLQZGPH.js.map +1 -0
  22. package/dist/conversation.d.ts +2 -804
  23. package/dist/conversation.js +2 -55
  24. package/dist/environment-provider-CfLUmKmf.js +1168 -0
  25. package/dist/environment-provider-CfLUmKmf.js.map +1 -0
  26. package/dist/environment-provider-IUGU3epE.d.ts +964 -0
  27. package/dist/environment-provider.d.ts +2 -78
  28. package/dist/environment-provider.js +2 -18
  29. package/dist/errors-DEAvWQPy.js +111 -0
  30. package/dist/errors-DEAvWQPy.js.map +1 -0
  31. package/dist/improvement-adapter-Cr5TBSji.d.ts +166 -0
  32. package/dist/improvement-cycle-C095kS_g.js +2624 -0
  33. package/dist/improvement-cycle-C095kS_g.js.map +1 -0
  34. package/dist/index-BGdxAwfO.d.ts +838 -0
  35. package/dist/index-C-FYUuFG.d.ts +193 -0
  36. package/dist/index-CbNM40xG.d.ts +140 -0
  37. package/dist/index-DruSKs3Z.d.ts +7224 -0
  38. package/dist/index-Efjb3nrQ.d.ts +671 -0
  39. package/dist/index.d.ts +14 -1058
  40. package/dist/index.js +2106 -2082
  41. package/dist/index.js.map +1 -1
  42. package/dist/intelligence.d.ts +768 -889
  43. package/dist/intelligence.js +1466 -1367
  44. package/dist/intelligence.js.map +1 -1
  45. package/dist/{kb-gate-CwHO0vz6.d.ts → kb-gate-C8z2juK8.d.ts} +33 -31
  46. package/dist/kb-gate-DpaSwXVx.js +80 -0
  47. package/dist/kb-gate-DpaSwXVx.js.map +1 -0
  48. package/dist/knowledge-Ku-mPP4f.js +433 -0
  49. package/dist/knowledge-Ku-mPP4f.js.map +1 -0
  50. package/dist/knowledge.d.ts +2 -150
  51. package/dist/knowledge.js +2 -40
  52. package/dist/local-harness-Dh8PJ0ot.d.ts +455 -0
  53. package/dist/loop-runner-bin-BXsFEUcf.d.ts +162 -0
  54. package/dist/loop-runner-bin-CRagyuNb.js +268 -0
  55. package/dist/loop-runner-bin-CRagyuNb.js.map +1 -0
  56. package/dist/loop-runner-bin.d.ts +2 -15
  57. package/dist/loop-runner-bin.js +2 -24
  58. package/dist/loops.d.ts +5 -4164
  59. package/dist/loops.js +8 -419
  60. package/dist/mcp/bin.d.ts +1 -1
  61. package/dist/mcp/bin.js +116 -146
  62. package/dist/mcp/bin.js.map +1 -1
  63. package/dist/mcp/index.d.ts +295 -436
  64. package/dist/mcp/index.js +1242 -1177
  65. package/dist/mcp/index.js.map +1 -1
  66. package/dist/mcp/memory-bin.d.ts +1 -1
  67. package/dist/mcp/memory-bin.js +37 -16
  68. package/dist/mcp/memory-bin.js.map +1 -1
  69. package/dist/memory-server-DL6cE2Ag.js +234 -0
  70. package/dist/memory-server-DL6cE2Ag.js.map +1 -0
  71. package/dist/model-resolution-Btd9iIKV.js +98 -0
  72. package/dist/model-resolution-Btd9iIKV.js.map +1 -0
  73. package/dist/openai-tools-B68JaOCx.d.ts +24 -0
  74. package/dist/openai-tools-CKLy1C7M.js +44 -0
  75. package/dist/openai-tools-CKLy1C7M.js.map +1 -0
  76. package/dist/otel-export-D34IQW1C.js +843 -0
  77. package/dist/otel-export-D34IQW1C.js.map +1 -0
  78. package/dist/platform.d.ts +188 -185
  79. package/dist/platform.js +185 -218
  80. package/dist/platform.js.map +1 -1
  81. package/dist/prepare-B53sPV7M.js +4292 -0
  82. package/dist/prepare-B53sPV7M.js.map +1 -0
  83. package/dist/primeintellect/index.d.ts +149 -145
  84. package/dist/primeintellect/index.js +626 -1003
  85. package/dist/primeintellect/index.js.map +1 -1
  86. package/dist/profiles.d.ts +296 -490
  87. package/dist/profiles.js +722 -749
  88. package/dist/profiles.js.map +1 -1
  89. package/dist/protected-model-port-BLPH5VVv.js +722 -0
  90. package/dist/protected-model-port-BLPH5VVv.js.map +1 -0
  91. package/dist/protected-model-port-BP6Z4eau.d.ts +283 -0
  92. package/dist/protected-redaction--F3v1oo8.js +200 -0
  93. package/dist/protected-redaction--F3v1oo8.js.map +1 -0
  94. package/dist/redact-D-u-rrcn.js +82 -0
  95. package/dist/redact-D-u-rrcn.js.map +1 -0
  96. package/dist/redact-kbIOjfjM.d.ts +452 -0
  97. package/dist/researcher-CoVqNhfI.js +433 -0
  98. package/dist/researcher-CoVqNhfI.js.map +1 -0
  99. package/dist/runtime-5zM5XxLr.js +5408 -0
  100. package/dist/runtime-5zM5XxLr.js.map +1 -0
  101. package/dist/sandbox-events-DeI5xX8P.js +316 -0
  102. package/dist/sandbox-events-DeI5xX8P.js.map +1 -0
  103. package/dist/spawn-journal-CwPvKUTa.js +456 -0
  104. package/dist/spawn-journal-CwPvKUTa.js.map +1 -0
  105. package/dist/structural-rollout-IXUEplky.js +1445 -0
  106. package/dist/structural-rollout-IXUEplky.js.map +1 -0
  107. package/dist/substrate-B0TYNrXn.js +27 -0
  108. package/dist/substrate-B0TYNrXn.js.map +1 -0
  109. package/dist/{substrate-Dyiqmd3o.d.ts → substrate-BcnuSHXm.d.ts} +57 -54
  110. package/dist/supervise-BiRutHS9.js +7321 -0
  111. package/dist/supervise-BiRutHS9.js.map +1 -0
  112. package/dist/supervisor-DTKhF-RV.js +3826 -0
  113. package/dist/supervisor-DTKhF-RV.js.map +1 -0
  114. package/dist/testing.d.ts +4 -3
  115. package/dist/testing.js +2478 -2637
  116. package/dist/testing.js.map +1 -1
  117. package/dist/tool-server-RcWgLIsL.js +141 -0
  118. package/dist/tool-server-RcWgLIsL.js.map +1 -0
  119. package/dist/trace-propagation-CJJC7SVB.js +57 -0
  120. package/dist/trace-propagation-CJJC7SVB.js.map +1 -0
  121. package/dist/types-BaIpb0XT.d.ts +492 -0
  122. package/dist/types-BevOjfTY.d.ts +765 -0
  123. package/dist/types-C9j4qg6l.d.ts +500 -0
  124. package/dist/types-Cja5OTGh.d.ts +190 -0
  125. package/dist/util-MVgdwuIS.js +145 -0
  126. package/dist/util-MVgdwuIS.js.map +1 -0
  127. package/dist/workspace-archive-BosQiotA.js +575 -0
  128. package/dist/workspace-archive-BosQiotA.js.map +1 -0
  129. package/package.json +44 -56
  130. package/skills/build-with-agent-runtime/SKILL.md +1 -0
  131. package/dist/activation-Cm-9MMX1.d.ts +0 -69
  132. package/dist/analyst-loop.js.map +0 -1
  133. package/dist/backends-BO4Jqoe2.d.ts +0 -134
  134. package/dist/candidate-execution/index.js.map +0 -1
  135. package/dist/chunk-2KGAN2HM.js +0 -1256
  136. package/dist/chunk-2KGAN2HM.js.map +0 -1
  137. package/dist/chunk-2VZYRB55.js +0 -834
  138. package/dist/chunk-2VZYRB55.js.map +0 -1
  139. package/dist/chunk-3MDZX7YU.js +0 -125
  140. package/dist/chunk-3MDZX7YU.js.map +0 -1
  141. package/dist/chunk-5IBQAPVB.js +0 -29
  142. package/dist/chunk-5IBQAPVB.js.map +0 -1
  143. package/dist/chunk-5QOB7H74.js +0 -387
  144. package/dist/chunk-5QOB7H74.js.map +0 -1
  145. package/dist/chunk-C5RTIBNZ.js +0 -48
  146. package/dist/chunk-C5RTIBNZ.js.map +0 -1
  147. package/dist/chunk-CTRA64LY.js +0 -680
  148. package/dist/chunk-CTRA64LY.js.map +0 -1
  149. package/dist/chunk-DPEUKJRO.js +0 -27
  150. package/dist/chunk-DPEUKJRO.js.map +0 -1
  151. package/dist/chunk-FD2MBMOH.js +0 -494
  152. package/dist/chunk-FD2MBMOH.js.map +0 -1
  153. package/dist/chunk-H5QPIZNX.js +0 -907
  154. package/dist/chunk-H5QPIZNX.js.map +0 -1
  155. package/dist/chunk-HLKC4UYB.js +0 -3514
  156. package/dist/chunk-HLKC4UYB.js.map +0 -1
  157. package/dist/chunk-HNP72PNU.js +0 -192
  158. package/dist/chunk-HNP72PNU.js.map +0 -1
  159. package/dist/chunk-ISPWRSEC.js +0 -408
  160. package/dist/chunk-ISPWRSEC.js.map +0 -1
  161. package/dist/chunk-KRBFHMV6.js +0 -1228
  162. package/dist/chunk-KRBFHMV6.js.map +0 -1
  163. package/dist/chunk-M22PL4GH.js +0 -171
  164. package/dist/chunk-M22PL4GH.js.map +0 -1
  165. package/dist/chunk-NURIQBJQ.js +0 -72
  166. package/dist/chunk-NURIQBJQ.js.map +0 -1
  167. package/dist/chunk-OPVWXJ2H.js +0 -75
  168. package/dist/chunk-OPVWXJ2H.js.map +0 -1
  169. package/dist/chunk-PZZKQVQV.js +0 -52
  170. package/dist/chunk-PZZKQVQV.js.map +0 -1
  171. package/dist/chunk-Q2JSAVQ3.js +0 -671
  172. package/dist/chunk-Q2JSAVQ3.js.map +0 -1
  173. package/dist/chunk-RDOAVVHY.js +0 -699
  174. package/dist/chunk-RDOAVVHY.js.map +0 -1
  175. package/dist/chunk-SGKPNBXE.js +0 -60
  176. package/dist/chunk-SGKPNBXE.js.map +0 -1
  177. package/dist/chunk-SMQXZGLZ.js +0 -351
  178. package/dist/chunk-SMQXZGLZ.js.map +0 -1
  179. package/dist/chunk-UHEZW5BU.js +0 -2918
  180. package/dist/chunk-UHEZW5BU.js.map +0 -1
  181. package/dist/chunk-UPWGXKXB.js +0 -254
  182. package/dist/chunk-UPWGXKXB.js.map +0 -1
  183. package/dist/chunk-VISA6CI3.js +0 -200
  184. package/dist/chunk-VISA6CI3.js.map +0 -1
  185. package/dist/chunk-WMTCUOQL.js +0 -474
  186. package/dist/chunk-WMTCUOQL.js.map +0 -1
  187. package/dist/chunk-WRTOVNN4.js +0 -4728
  188. package/dist/chunk-WRTOVNN4.js.map +0 -1
  189. package/dist/chunk-WSTRQZYQ.js +0 -5576
  190. package/dist/chunk-WSTRQZYQ.js.map +0 -1
  191. package/dist/chunk-XBG2W2VW.js +0 -6434
  192. package/dist/chunk-XBG2W2VW.js.map +0 -1
  193. package/dist/chunk-YEJR7IXO.js +0 -68
  194. package/dist/chunk-YEJR7IXO.js.map +0 -1
  195. package/dist/chunk-YJZA2BIK.js +0 -1338
  196. package/dist/chunk-YJZA2BIK.js.map +0 -1
  197. package/dist/completion-gate-BMy5LGoP.d.ts +0 -256
  198. package/dist/conversation.js.map +0 -1
  199. package/dist/coordination-BZZSVYpZ.d.ts +0 -2570
  200. package/dist/environment-provider.js.map +0 -1
  201. package/dist/improvement-adapter-HAZz-7vK.d.ts +0 -203
  202. package/dist/knowledge.js.map +0 -1
  203. package/dist/local-harness-BDNcl6jI.d.ts +0 -175
  204. package/dist/loop-runner-bin-68aoM9-7.d.ts +0 -199
  205. package/dist/loop-runner-bin.js.map +0 -1
  206. package/dist/loops.js.map +0 -1
  207. package/dist/openai-tools-fnj6SRVg.d.ts +0 -46
  208. package/dist/protected-model-port-B4t-OQjL.d.ts +0 -271
  209. package/dist/redact-BuFjxBUJ.d.ts +0 -481
  210. package/dist/sanitize-DEbPNtyI.d.ts +0 -328
  211. package/dist/structural-rollout-DEh6CEsa.d.ts +0 -446
  212. package/dist/supervise-4_48wwvy.d.ts +0 -379
  213. package/dist/types-BCoemcXU.d.ts +0 -802
  214. package/dist/types-BwoZWq-i.d.ts +0 -510
  215. package/dist/types-Cbp72qyu.d.ts +0 -491
  216. package/dist/types-CmYCMbFT.d.ts +0 -203
  217. package/dist/types-CvNwMzQt.d.ts +0 -957
  218. package/dist/worktree-fanout-DxhAWr5Z.d.ts +0 -999
package/dist/platform.js CHANGED
@@ -1,227 +1,194 @@
1
- // src/platform/auth.ts
1
+ //#region src/platform/auth.ts
2
+ /** Thrown when a `PlatformAuthClient` request returns a non-success status. */
2
3
  var PlatformAuthError = class extends Error {
3
- constructor(message, status, body) {
4
- super(message);
5
- this.status = status;
6
- this.body = body;
7
- this.name = "PlatformAuthError";
8
- }
9
- status;
10
- body;
4
+ status;
5
+ body;
6
+ constructor(message, status, body) {
7
+ super(message);
8
+ this.status = status;
9
+ this.body = body;
10
+ this.name = "PlatformAuthError";
11
+ }
11
12
  };
13
+ /** HTTP client for the Tangle Platform SSO: builds authorize URLs and exchanges auth codes for API keys. */
12
14
  var PlatformAuthClient = class {
13
- baseUrl;
14
- appId;
15
- fetchImpl;
16
- constructor(options) {
17
- if (!options.baseUrl) throw new Error("PlatformAuthClient: baseUrl is required");
18
- if (!options.appId) throw new Error("PlatformAuthClient: appId is required");
19
- this.baseUrl = options.baseUrl.replace(/\/+$/, "");
20
- this.appId = options.appId;
21
- this.fetchImpl = options.fetchImpl ?? ((url, init) => fetch(url, init));
22
- }
23
- /**
24
- * Build the URL the user is redirected to in order to start SSO.
25
- * The platform redirects back to one of `appId`'s registered
26
- * `redirectUris` with `?code=...&app=...&state=...`.
27
- */
28
- authorizeUrl(options) {
29
- if (!options.state) {
30
- throw new Error("PlatformAuthClient.authorizeUrl: state is required for CSRF");
31
- }
32
- const url = new URL("/cross-site/authorize", this.baseUrl);
33
- url.searchParams.set("app", this.appId);
34
- url.searchParams.set("state", options.state);
35
- if (options.redirectUri) url.searchParams.set("redirect", options.redirectUri);
36
- if (options.prompt) url.searchParams.set("prompt", options.prompt);
37
- if (options.email) url.searchParams.set("email", options.email);
38
- return url.toString();
39
- }
40
- /**
41
- * Exchange a single-use auth code (delivered to the consumer's
42
- * callback by the platform) for an API key + the user's identity.
43
- * Codes are single-use and expire ~5 minutes after issue.
44
- */
45
- async exchange(code) {
46
- if (!code) throw new Error("PlatformAuthClient.exchange: code is required");
47
- const res = await this.fetchImpl(`${this.baseUrl}/cross-site/exchange`, {
48
- method: "POST",
49
- headers: { "content-type": "application/json" },
50
- body: JSON.stringify({ code, app: this.appId })
51
- });
52
- const body = await res.json().catch(() => null);
53
- if (!res.ok) {
54
- const message = body && typeof body === "object" && "error" in body && typeof body.error === "string" ? body.error : `Platform exchange failed (${res.status})`;
55
- throw new PlatformAuthError(message, res.status, body);
56
- }
57
- const result = body;
58
- if (!result.apiKey || !result.user?.id) {
59
- throw new PlatformAuthError(
60
- "Platform exchange response is missing apiKey or user",
61
- res.status,
62
- body
63
- );
64
- }
65
- return result;
66
- }
15
+ baseUrl;
16
+ appId;
17
+ fetchImpl;
18
+ constructor(options) {
19
+ if (!options.baseUrl) throw new Error("PlatformAuthClient: baseUrl is required");
20
+ if (!options.appId) throw new Error("PlatformAuthClient: appId is required");
21
+ this.baseUrl = options.baseUrl.replace(/\/+$/, "");
22
+ this.appId = options.appId;
23
+ this.fetchImpl = options.fetchImpl ?? ((url, init) => fetch(url, init));
24
+ }
25
+ /**
26
+ * Build the URL the user is redirected to in order to start SSO.
27
+ * The platform redirects back to one of `appId`'s registered
28
+ * `redirectUris` with `?code=...&app=...&state=...`.
29
+ */
30
+ authorizeUrl(options) {
31
+ if (!options.state) throw new Error("PlatformAuthClient.authorizeUrl: state is required for CSRF");
32
+ const url = new URL("/cross-site/authorize", this.baseUrl);
33
+ url.searchParams.set("app", this.appId);
34
+ url.searchParams.set("state", options.state);
35
+ if (options.redirectUri) url.searchParams.set("redirect", options.redirectUri);
36
+ if (options.prompt) url.searchParams.set("prompt", options.prompt);
37
+ if (options.email) url.searchParams.set("email", options.email);
38
+ return url.toString();
39
+ }
40
+ /**
41
+ * Exchange a single-use auth code (delivered to the consumer's
42
+ * callback by the platform) for an API key + the user's identity.
43
+ * Codes are single-use and expire ~5 minutes after issue.
44
+ */
45
+ async exchange(code) {
46
+ if (!code) throw new Error("PlatformAuthClient.exchange: code is required");
47
+ const res = await this.fetchImpl(`${this.baseUrl}/cross-site/exchange`, {
48
+ method: "POST",
49
+ headers: { "content-type": "application/json" },
50
+ body: JSON.stringify({
51
+ code,
52
+ app: this.appId
53
+ })
54
+ });
55
+ const body = await res.json().catch(() => null);
56
+ if (!res.ok) throw new PlatformAuthError(body && typeof body === "object" && "error" in body && typeof body.error === "string" ? body.error : `Platform exchange failed (${res.status})`, res.status, body);
57
+ const result = body;
58
+ if (!result.apiKey || !result.user?.id) throw new PlatformAuthError("Platform exchange response is missing apiKey or user", res.status, body);
59
+ return result;
60
+ }
67
61
  };
68
-
69
- // src/platform/integrations.ts
62
+ //#endregion
63
+ //#region src/platform/integrations.ts
64
+ /** Thrown when a `PlatformHubClient` request returns a non-success status. */
70
65
  var PlatformHubError = class extends Error {
71
- constructor(message, status, code, body) {
72
- super(message);
73
- this.status = status;
74
- this.code = code;
75
- this.body = body;
76
- this.name = "PlatformHubError";
77
- }
78
- status;
79
- code;
80
- body;
66
+ status;
67
+ code;
68
+ body;
69
+ constructor(message, status, code, body) {
70
+ super(message);
71
+ this.status = status;
72
+ this.code = code;
73
+ this.body = body;
74
+ this.name = "PlatformHubError";
75
+ }
81
76
  };
77
+ /** HTTP client for the Tangle Platform Hub API: provider catalog, connection flow, and status. */
82
78
  var PlatformHubClient = class {
83
- baseUrl;
84
- bearer;
85
- fetchImpl;
86
- constructor(options) {
87
- if (!options.baseUrl) throw new Error("PlatformHubClient: baseUrl is required");
88
- if (!options.bearer) throw new Error("PlatformHubClient: bearer is required");
89
- this.baseUrl = options.baseUrl.replace(/\/+$/, "");
90
- this.bearer = options.bearer;
91
- this.fetchImpl = options.fetchImpl ?? ((url, init) => fetch(url, init));
92
- }
93
- /** GET /v1/hub/providers — the connectable provider catalog. */
94
- catalog() {
95
- return this.request("GET", "/v1/hub/providers");
96
- }
97
- /** GET /v1/hub/connections — the calling user's live connections. */
98
- async listConnections() {
99
- const data = await this.request(
100
- "GET",
101
- "/v1/hub/connections"
102
- );
103
- return data.connections;
104
- }
105
- /** DELETE /v1/hub/connections/:connectionId — revoke + disable a connection. */
106
- revokeConnection(connectionId) {
107
- return this.request("DELETE", `/v1/hub/connections/${encodeURIComponent(connectionId)}`);
108
- }
109
- /**
110
- * POST /v1/hub/connections/:provider/start — begin OAuth/grant. The provider
111
- * is taken from the URL; the body carries `returnUrl` (+ `cli`). The platform's
112
- * two start branches name the URL field differently (github → `authorizationUrl`,
113
- * substrate `redirectUrl`); this normalizes to `authorizationUrl`.
114
- */
115
- async startAuth(input) {
116
- const body = { returnUrl: input.returnUrl };
117
- if (input.cli !== void 0) body.cli = input.cli;
118
- const data = await this.request("POST", `/v1/hub/connections/${encodeURIComponent(input.providerId)}/start`, body);
119
- const authorizationUrl = data.authorizationUrl ?? data.redirectUrl;
120
- if (!authorizationUrl) {
121
- throw new PlatformHubError(
122
- "Platform hub start response missing an authorization URL",
123
- 502,
124
- "HUB_INVALID_START_RESPONSE",
125
- data
126
- );
127
- }
128
- return { authorizationUrl, state: data.state, expiresAt: data.expiresAt, scopes: data.scopes };
129
- }
130
- /**
131
- * Last-known health for every connection. The platform has no global
132
- * healthcheck listing — health rides on each connection row — so this derives
133
- * the list from `listConnections()` (one request, no extra round-trips).
134
- */
135
- async listHealthchecks() {
136
- const connections = await this.listConnections();
137
- return connections.map((c) => ({
138
- connectionId: c.id,
139
- providerId: c.providerId,
140
- status: c.health,
141
- checkedAt: c.updatedAt
142
- }));
143
- }
144
- /**
145
- * POST /v1/hub/connections/:connectionId/health trigger a fresh health
146
- * probe for one connection and return its updated state.
147
- */
148
- checkConnectionHealth(connectionId) {
149
- return this.request("POST", `/v1/hub/connections/${encodeURIComponent(connectionId)}/health`);
150
- }
151
- /**
152
- * Trigger a fresh health probe across all of the user's connections. The
153
- * platform exposes health per-connection only, so this fans out over
154
- * `listConnections()`. `scheduled` is the number of probes dispatched.
155
- */
156
- async runHealthchecks() {
157
- const connections = await this.listConnections();
158
- await Promise.allSettled(connections.map((c) => this.checkConnectionHealth(c.id)));
159
- return { scheduled: connections.length };
160
- }
161
- /** GET /v1/hub/status principal + aggregate connection counts. */
162
- status() {
163
- return this.request("GET", "/v1/hub/status");
164
- }
165
- /**
166
- * POST /v1/hub/tokensmint a short-lived, action-scoped capability token a
167
- * sandbox can use to invoke one hub action on the user's behalf without
168
- * seeing the underlying provider credential.
169
- */
170
- mintToken(input) {
171
- return this.request("POST", "/v1/hub/tokens", input);
172
- }
173
- /** POST /v1/hub/exec — execute a hub action and return its result. */
174
- async exec(input) {
175
- const data = await this.request("POST", "/v1/hub/exec", input);
176
- return data.result;
177
- }
178
- async request(method, path, body) {
179
- const headers = {
180
- authorization: `Bearer ${this.bearer}`,
181
- accept: "application/json"
182
- };
183
- if (body !== void 0) headers["content-type"] = "application/json";
184
- const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
185
- method,
186
- headers,
187
- body: body !== void 0 ? JSON.stringify(body) : void 0
188
- });
189
- const text = await res.text();
190
- let parsed = null;
191
- if (text) {
192
- try {
193
- parsed = JSON.parse(text);
194
- } catch {
195
- }
196
- }
197
- if (!res.ok || parsed && parsed.success === false) {
198
- const code = parsed?.error && typeof parsed.error === "object" ? parsed.error.code : void 0;
199
- const message = parsed?.error && typeof parsed.error === "object" && parsed.error.message || (typeof parsed?.error === "string" ? parsed.error : `Platform hub error (${res.status})`);
200
- throw new PlatformHubError(message, res.status, code, parsed ?? text);
201
- }
202
- if (!parsed) {
203
- throw new PlatformHubError(
204
- `Platform hub returned non-JSON success (${res.status})`,
205
- res.status,
206
- void 0,
207
- text
208
- );
209
- }
210
- if (parsed.data === void 0) {
211
- throw new PlatformHubError(
212
- "Platform hub envelope missing `data`",
213
- res.status,
214
- void 0,
215
- parsed
216
- );
217
- }
218
- return parsed.data;
219
- }
220
- };
221
- export {
222
- PlatformAuthClient,
223
- PlatformAuthError,
224
- PlatformHubClient,
225
- PlatformHubError
79
+ baseUrl;
80
+ bearer;
81
+ fetchImpl;
82
+ constructor(options) {
83
+ if (!options.baseUrl) throw new Error("PlatformHubClient: baseUrl is required");
84
+ if (!options.bearer) throw new Error("PlatformHubClient: bearer is required");
85
+ this.baseUrl = options.baseUrl.replace(/\/+$/, "");
86
+ this.bearer = options.bearer;
87
+ this.fetchImpl = options.fetchImpl ?? ((url, init) => fetch(url, init));
88
+ }
89
+ /** GET /v1/hub/providers — the connectable provider catalog. */
90
+ catalog() {
91
+ return this.request("GET", "/v1/hub/providers");
92
+ }
93
+ /** GET /v1/hub/connections — the calling user's live connections. */
94
+ async listConnections() {
95
+ return (await this.request("GET", "/v1/hub/connections")).connections;
96
+ }
97
+ /** DELETE /v1/hub/connections/:connectionId — revoke + disable a connection. */
98
+ revokeConnection(connectionId) {
99
+ return this.request("DELETE", `/v1/hub/connections/${encodeURIComponent(connectionId)}`);
100
+ }
101
+ /**
102
+ * POST /v1/hub/connections/:provider/start — begin OAuth/grant. The provider
103
+ * is taken from the URL; the body carries `returnUrl` (+ `cli`). The platform's
104
+ * two start branches name the URL field differently (github → `authorizationUrl`,
105
+ * substrate → `redirectUrl`); this normalizes to `authorizationUrl`.
106
+ */
107
+ async startAuth(input) {
108
+ const body = { returnUrl: input.returnUrl };
109
+ if (input.cli !== void 0) body.cli = input.cli;
110
+ const data = await this.request("POST", `/v1/hub/connections/${encodeURIComponent(input.providerId)}/start`, body);
111
+ const authorizationUrl = data.authorizationUrl ?? data.redirectUrl;
112
+ if (!authorizationUrl) throw new PlatformHubError("Platform hub start response missing an authorization URL", 502, "HUB_INVALID_START_RESPONSE", data);
113
+ return {
114
+ authorizationUrl,
115
+ state: data.state,
116
+ expiresAt: data.expiresAt,
117
+ scopes: data.scopes
118
+ };
119
+ }
120
+ /**
121
+ * Last-known health for every connection. The platform has no global
122
+ * healthcheck listing — health rides on each connection row — so this derives
123
+ * the list from `listConnections()` (one request, no extra round-trips).
124
+ */
125
+ async listHealthchecks() {
126
+ return (await this.listConnections()).map((c) => ({
127
+ connectionId: c.id,
128
+ providerId: c.providerId,
129
+ status: c.health,
130
+ checkedAt: c.updatedAt
131
+ }));
132
+ }
133
+ /**
134
+ * POST /v1/hub/connections/:connectionId/health — trigger a fresh health
135
+ * probe for one connection and return its updated state.
136
+ */
137
+ checkConnectionHealth(connectionId) {
138
+ return this.request("POST", `/v1/hub/connections/${encodeURIComponent(connectionId)}/health`);
139
+ }
140
+ /**
141
+ * Trigger a fresh health probe across all of the user's connections. The
142
+ * platform exposes health per-connection only, so this fans out over
143
+ * `listConnections()`. `scheduled` is the number of probes dispatched.
144
+ */
145
+ async runHealthchecks() {
146
+ const connections = await this.listConnections();
147
+ await Promise.allSettled(connections.map((c) => this.checkConnectionHealth(c.id)));
148
+ return { scheduled: connections.length };
149
+ }
150
+ /** GET /v1/hub/status principal + aggregate connection counts. */
151
+ status() {
152
+ return this.request("GET", "/v1/hub/status");
153
+ }
154
+ /**
155
+ * POST /v1/hub/tokens mint a short-lived, action-scoped capability token a
156
+ * sandbox can use to invoke one hub action on the user's behalf without
157
+ * seeing the underlying provider credential.
158
+ */
159
+ mintToken(input) {
160
+ return this.request("POST", "/v1/hub/tokens", input);
161
+ }
162
+ /** POST /v1/hub/execexecute a hub action and return its result. */
163
+ async exec(input) {
164
+ return (await this.request("POST", "/v1/hub/exec", input)).result;
165
+ }
166
+ async request(method, path, body) {
167
+ const headers = {
168
+ authorization: `Bearer ${this.bearer}`,
169
+ accept: "application/json"
170
+ };
171
+ if (body !== void 0) headers["content-type"] = "application/json";
172
+ const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
173
+ method,
174
+ headers,
175
+ body: body !== void 0 ? JSON.stringify(body) : void 0
176
+ });
177
+ const text = await res.text();
178
+ let parsed = null;
179
+ if (text) try {
180
+ parsed = JSON.parse(text);
181
+ } catch {}
182
+ if (!res.ok || parsed && parsed.success === false) {
183
+ const code = parsed?.error && typeof parsed.error === "object" ? parsed.error.code : void 0;
184
+ throw new PlatformHubError(parsed?.error && typeof parsed.error === "object" && parsed.error.message || (typeof parsed?.error === "string" ? parsed.error : `Platform hub error (${res.status})`), res.status, code, parsed ?? text);
185
+ }
186
+ if (!parsed) throw new PlatformHubError(`Platform hub returned non-JSON success (${res.status})`, res.status, void 0, text);
187
+ if (parsed.data === void 0) throw new PlatformHubError("Platform hub envelope missing `data`", res.status, void 0, parsed);
188
+ return parsed.data;
189
+ }
226
190
  };
191
+ //#endregion
192
+ export { PlatformAuthClient, PlatformAuthError, PlatformHubClient, PlatformHubError };
193
+
227
194
  //# sourceMappingURL=platform.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/platform/auth.ts","../src/platform/integrations.ts"],"sourcesContent":["/**\n * Server-side client for the Tangle platform's cross-site SSO bridge.\n *\n * Consumer apps (gtm-agent, tax-agent, legal-agent, creative-agent, …)\n * use this to:\n * 1. Build an /authorize URL that lands the user on id.tangle.tools\n * and brings them back with a single-use code.\n * 2. Exchange that code for an API key + the user's identity.\n *\n * The platform endpoint contract is documented in\n * `products/platform/api/src/routes/cross-site.ts`. This client only\n * speaks HTTP — no SDK weight, no transitive deps.\n */\n\nexport interface PlatformAuthClientOptions {\n /** Platform base URL, e.g. `https://id.tangle.tools`. */\n baseUrl: string\n /** App id as registered in the platform's TRUSTED_APPS registry. */\n appId: string\n /** Override the global fetch (useful for tests + edge runtimes). */\n fetchImpl?: typeof fetch\n}\n\nexport interface AuthorizeUrlOptions {\n /** Required CSRF token; the consumer verifies it on the callback. */\n state: string\n /**\n * Final redirect URI. Must be one of the URIs registered for `appId`\n * on the platform. Omit to use the first registered URI.\n */\n redirectUri?: string\n /** Force the login screen even if a session is already active. */\n prompt?: 'login'\n /** Pre-fill the email field on the login screen. */\n email?: string\n}\n\nexport interface ExchangeCodeResult {\n apiKey: string\n user: {\n id: string\n email: string\n name?: string\n }\n plan: {\n tier: string\n }\n}\n\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\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 const result = body as Partial<ExchangeCodeResult>\n if (!result.apiKey || !result.user?.id) {\n throw new PlatformAuthError(\n 'Platform exchange response is missing apiKey or user',\n res.status,\n body,\n )\n }\n return result as ExchangeCodeResult\n }\n}\n","/**\n * Server-side client for the Tangle platform's integration hub\n * (`/v1/hub/*`). Consumer apps use this instead of rolling their own\n * OAuth + connection tables.\n *\n * Auth: the caller supplies a bearer (either the user's API key from\n * cross-site exchange, or a platform service token) on construction.\n *\n * Endpoint contract (authoritative): the platform's `src/lib/hub-contract.ts`\n * + `src/routes/hub.ts`. The platform wraps every response in\n * `{ success, data }`; non-2xx or `success:false` surfaces as `PlatformHubError`\n * carrying the real upstream status.\n */\n\nexport interface PlatformHubClientOptions {\n /** Platform base URL, e.g. `https://id.tangle.tools`. */\n baseUrl: string\n /** Bearer credential — user API key or service token. */\n bearer: string\n /** Override fetch (tests + edge runtimes). */\n fetchImpl?: typeof fetch\n}\n\n/** A live integration connection, as returned by `/v1/hub/connections`. */\nexport interface PlatformConnection {\n id: string\n providerId: string\n displayName: string\n accountDisplay: string | null\n scopes: string[]\n status: 'active' | 'revoked' | 'unhealthy' | 'reconnect_required' | (string & {})\n health: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {})\n createdAt: string\n updatedAt: string\n lastUsedAt: string | null\n}\n\n/** A connectable provider in the catalog (`/v1/hub/providers`). */\nexport interface PlatformCatalogProvider {\n providerId: string\n title?: string\n authKind?: string\n category?: string\n scopes?: string[]\n capabilityCount?: number\n native?: boolean\n /** Whether the OAuth app's credentials are wired — the UI offers Connect\n * only when true. */\n configured?: boolean\n [k: string]: unknown\n}\n\nexport interface CatalogResult {\n providers: PlatformCatalogProvider[]\n /** Count of substrate-bundled connectors behind the catalog. */\n substrateBundled?: number\n [k: string]: unknown\n}\n\nexport interface StartAuthInput {\n /** The provider to connect (goes in the URL path). */\n providerId: string\n /** Accepted for interface compatibility; the platform's start endpoint is\n * provider-level and does not consume a connector id. */\n connectorId?: string\n /** Where the platform redirects the user back to after OAuth. */\n returnUrl: string\n /** Accepted for interface compatibility; not consumed by the start endpoint. */\n requestedScopes?: string[]\n /** CLI flow flag — affects the platform's post-auth redirect handling. */\n cli?: boolean\n}\n\nexport interface StartAuthResult {\n /** The URL to send the user to. Normalized across the platform's two start\n * branches: github returns `authorizationUrl`, substrate returns\n * `redirectUrl`. */\n authorizationUrl: string\n state: string\n expiresAt?: string\n scopes?: string[]\n}\n\nexport interface ConnectionHealth {\n status: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {})\n checkedAt: string\n error?: { code: string; message: string }\n}\n\nexport interface ConnectionHealthResult {\n connection: PlatformConnection\n health: ConnectionHealth\n}\n\n/** Last-known health for a connection, derived from the connection row. */\nexport interface HealthCheck {\n connectionId: string\n providerId: string\n /** Mirrors `PlatformConnection.health`. */\n status: ConnectionHealth['status']\n checkedAt?: string\n}\n\nexport interface MintTokenInput {\n /** The hub action the token authorizes (e.g. `slack.chat.postMessage`). */\n actionPath: string\n /** Bind to a specific connection, or … */\n connectionId?: string\n /** … resolve the connection by provider for the calling user. */\n provider?: string\n}\n\nexport interface MintTokenResult {\n tokenId: string\n token: string\n expiresAt: string\n}\n\nexport interface ExecInput {\n /** The hub action path to execute. */\n path: string\n input?: unknown\n connectionId?: string\n}\n\nexport interface PlatformHubStatus {\n contract?: unknown\n principal: { kind: string; userId: string; [k: string]: unknown }\n connections: { connectedProviderCount: number; unhealthyProviderCount: number }\n}\n\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"],"mappings":"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","names":[]}
1
+ {"version":3,"file":"platform.js","names":[],"sources":["../src/platform/auth.ts","../src/platform/integrations.ts"],"sourcesContent":["/**\n * Server-side client for the Tangle platform's cross-site SSO bridge.\n *\n * Consumer apps (gtm-agent, tax-agent, legal-agent, creative-agent, …)\n * use this to:\n * 1. Build an /authorize URL that lands the user on id.tangle.tools\n * and brings them back with a single-use code.\n * 2. Exchange that code for an API key + the user's identity.\n *\n * The platform endpoint contract is documented in\n * `products/platform/api/src/routes/cross-site.ts`. This client only\n * speaks HTTP — no SDK weight, no transitive deps.\n */\n\nexport interface PlatformAuthClientOptions {\n /** Platform base URL, e.g. `https://id.tangle.tools`. */\n baseUrl: string\n /** App id as registered in the platform's TRUSTED_APPS registry. */\n appId: string\n /** Override the global fetch (useful for tests + edge runtimes). */\n fetchImpl?: typeof fetch\n}\n\nexport interface AuthorizeUrlOptions {\n /** Required CSRF token; the consumer verifies it on the callback. */\n state: string\n /**\n * Final redirect URI. Must be one of the URIs registered for `appId`\n * on the platform. Omit to use the first registered URI.\n */\n redirectUri?: string\n /** Force the login screen even if a session is already active. */\n prompt?: 'login'\n /** Pre-fill the email field on the login screen. */\n email?: string\n}\n\nexport interface ExchangeCodeResult {\n apiKey: string\n user: {\n id: string\n email: string\n name?: string\n }\n plan: {\n tier: string\n }\n}\n\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\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 const result = body as Partial<ExchangeCodeResult>\n if (!result.apiKey || !result.user?.id) {\n throw new PlatformAuthError(\n 'Platform exchange response is missing apiKey or user',\n res.status,\n body,\n )\n }\n return result as ExchangeCodeResult\n }\n}\n","/**\n * Server-side client for the Tangle platform's integration hub\n * (`/v1/hub/*`). Consumer apps use this instead of rolling their own\n * OAuth + connection tables.\n *\n * Auth: the caller supplies a bearer (either the user's API key from\n * cross-site exchange, or a platform service token) on construction.\n *\n * Endpoint contract (authoritative): the platform's `src/lib/hub-contract.ts`\n * + `src/routes/hub.ts`. The platform wraps every response in\n * `{ success, data }`; non-2xx or `success:false` surfaces as `PlatformHubError`\n * carrying the real upstream status.\n */\n\nexport interface PlatformHubClientOptions {\n /** Platform base URL, e.g. `https://id.tangle.tools`. */\n baseUrl: string\n /** Bearer credential — user API key or service token. */\n bearer: string\n /** Override fetch (tests + edge runtimes). */\n fetchImpl?: typeof fetch\n}\n\n/** A live integration connection, as returned by `/v1/hub/connections`. */\nexport interface PlatformConnection {\n id: string\n providerId: string\n displayName: string\n accountDisplay: string | null\n scopes: string[]\n status: 'active' | 'revoked' | 'unhealthy' | 'reconnect_required' | (string & {})\n health: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {})\n createdAt: string\n updatedAt: string\n lastUsedAt: string | null\n}\n\n/** A connectable provider in the catalog (`/v1/hub/providers`). */\nexport interface PlatformCatalogProvider {\n providerId: string\n title?: string\n authKind?: string\n category?: string\n scopes?: string[]\n capabilityCount?: number\n native?: boolean\n /** Whether the OAuth app's credentials are wired — the UI offers Connect\n * only when true. */\n configured?: boolean\n [k: string]: unknown\n}\n\nexport interface CatalogResult {\n providers: PlatformCatalogProvider[]\n /** Count of substrate-bundled connectors behind the catalog. */\n substrateBundled?: number\n [k: string]: unknown\n}\n\nexport interface StartAuthInput {\n /** The provider to connect (goes in the URL path). */\n providerId: string\n /** Accepted for interface compatibility; the platform's start endpoint is\n * provider-level and does not consume a connector id. */\n connectorId?: string\n /** Where the platform redirects the user back to after OAuth. */\n returnUrl: string\n /** Accepted for interface compatibility; not consumed by the start endpoint. */\n requestedScopes?: string[]\n /** CLI flow flag — affects the platform's post-auth redirect handling. */\n cli?: boolean\n}\n\nexport interface StartAuthResult {\n /** The URL to send the user to. Normalized across the platform's two start\n * branches: github returns `authorizationUrl`, substrate returns\n * `redirectUrl`. */\n authorizationUrl: string\n state: string\n expiresAt?: string\n scopes?: string[]\n}\n\nexport interface ConnectionHealth {\n status: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {})\n checkedAt: string\n error?: { code: string; message: string }\n}\n\nexport interface ConnectionHealthResult {\n connection: PlatformConnection\n health: ConnectionHealth\n}\n\n/** Last-known health for a connection, derived from the connection row. */\nexport interface HealthCheck {\n connectionId: string\n providerId: string\n /** Mirrors `PlatformConnection.health`. */\n status: ConnectionHealth['status']\n checkedAt?: string\n}\n\nexport interface MintTokenInput {\n /** The hub action the token authorizes (e.g. `slack.chat.postMessage`). */\n actionPath: string\n /** Bind to a specific connection, or … */\n connectionId?: string\n /** … resolve the connection by provider for the calling user. */\n provider?: string\n}\n\nexport interface MintTokenResult {\n tokenId: string\n token: string\n expiresAt: string\n}\n\nexport interface ExecInput {\n /** The hub action path to execute. */\n path: string\n input?: unknown\n connectionId?: string\n}\n\nexport interface PlatformHubStatus {\n contract?: unknown\n principal: { kind: string; userId: string; [k: string]: unknown }\n connections: { connectedProviderCount: number; unhealthyProviderCount: number }\n}\n\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"],"mappings":"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"}