@tangle-network/agent-runtime 0.70.0 → 0.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +4 -4
- package/dist/agent.js +5 -3
- package/dist/agent.js.map +1 -1
- package/dist/analyst-loop.d.ts +51 -0
- package/dist/analyst-loop.js +11 -0
- package/dist/analyst-loop.js.map +1 -0
- package/dist/{chunk-EDCVUZZC.js → chunk-4KGQHS7U.js} +2 -2
- package/dist/{chunk-QXWGSDAQ.js → chunk-5ISW5JUF.js} +287 -286
- package/dist/chunk-5ISW5JUF.js.map +1 -0
- package/dist/{chunk-ZNQVMMR5.js → chunk-74UAWZXE.js} +4 -4
- package/dist/{chunk-L5ZFBVT6.js → chunk-INXDNX2W.js} +2 -2
- package/dist/chunk-K3RM4MPM.js +214 -0
- package/dist/chunk-K3RM4MPM.js.map +1 -0
- package/dist/chunk-P5OKDSLB.js +580 -0
- package/dist/chunk-P5OKDSLB.js.map +1 -0
- package/dist/chunk-VLF5RHEQ.js +143 -0
- package/dist/chunk-VLF5RHEQ.js.map +1 -0
- package/dist/{chunk-G3RGMA7C.js → chunk-VMNEQHJR.js} +6 -1
- package/dist/chunk-VMNEQHJR.js.map +1 -0
- package/dist/{coordination-C7WxwHXq.d.ts → coordination-BPQmuwv8.d.ts} +280 -2
- package/dist/{delegates-DqAgo32T.d.ts → delegates-CsXJPZDH.d.ts} +48 -2
- package/dist/{improvement-adapter-BVuMragr.d.ts → improvement-adapter-CioiEE2z.d.ts} +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.js +20 -17
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +1 -1
- package/dist/intelligence.js +1 -1
- package/dist/{loop-runner-bin-B0NeLTRd.d.ts → loop-runner-bin-DLM_bVQO.d.ts} +4 -4
- package/dist/loop-runner-bin.d.ts +5 -5
- package/dist/loop-runner-bin.js +6 -4
- package/dist/loops.d.ts +121 -242
- package/dist/loops.js +10 -4
- package/dist/mcp/bin.js +8 -7
- package/dist/mcp/bin.js.map +1 -1
- package/dist/mcp/index.d.ts +7 -6
- package/dist/mcp/index.js +23 -12
- package/dist/mcp/index.js.map +1 -1
- package/dist/{openai-tools-DPx9Gzvn.d.ts → openai-tools-kdCS-T12.d.ts} +1 -1
- package/dist/platform.d.ts +255 -0
- package/dist/platform.js +229 -0
- package/dist/platform.js.map +1 -0
- package/dist/profiles.d.ts +1 -1
- package/dist/{types-DJu6TBGp.d.ts → types-BC3bZpH0.d.ts} +15 -1
- package/dist/{types-BYa2ZOAx.d.ts → types-CdnEAE3U.d.ts} +1 -1
- package/dist/{worktree-fanout-gNfl0Byj.d.ts → worktree-fanout-CK2ypmEm.d.ts} +3 -45
- package/package.json +11 -1
- package/dist/chunk-BYZCXQHF.js +0 -474
- package/dist/chunk-BYZCXQHF.js.map +0 -1
- package/dist/chunk-G3RGMA7C.js.map +0 -1
- package/dist/chunk-QXWGSDAQ.js.map +0 -1
- /package/dist/{chunk-EDCVUZZC.js.map → chunk-4KGQHS7U.js.map} +0 -0
- /package/dist/{chunk-ZNQVMMR5.js.map → chunk-74UAWZXE.js.map} +0 -0
- /package/dist/{chunk-L5ZFBVT6.js.map → chunk-INXDNX2W.js.map} +0 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side client for the Tangle platform's cross-site SSO bridge.
|
|
3
|
+
*
|
|
4
|
+
* Consumer apps (gtm-agent, tax-agent, legal-agent, creative-agent, …)
|
|
5
|
+
* use this to:
|
|
6
|
+
* 1. Build an /authorize URL that lands the user on id.tangle.tools
|
|
7
|
+
* and brings them back with a single-use code.
|
|
8
|
+
* 2. Exchange that code for an API key + the user's identity.
|
|
9
|
+
*
|
|
10
|
+
* The platform endpoint contract is documented in
|
|
11
|
+
* `products/platform/api/src/routes/cross-site.ts`. This client only
|
|
12
|
+
* speaks HTTP — no SDK weight, no transitive deps.
|
|
13
|
+
*/
|
|
14
|
+
interface PlatformAuthClientOptions {
|
|
15
|
+
/** Platform base URL, e.g. `https://id.tangle.tools`. */
|
|
16
|
+
baseUrl: string;
|
|
17
|
+
/** App id as registered in the platform's TRUSTED_APPS registry. */
|
|
18
|
+
appId: string;
|
|
19
|
+
/** Override the global fetch (useful for tests + edge runtimes). */
|
|
20
|
+
fetchImpl?: typeof fetch;
|
|
21
|
+
}
|
|
22
|
+
interface AuthorizeUrlOptions {
|
|
23
|
+
/** Required CSRF token; the consumer verifies it on the callback. */
|
|
24
|
+
state: string;
|
|
25
|
+
/**
|
|
26
|
+
* Final redirect URI. Must be one of the URIs registered for `appId`
|
|
27
|
+
* on the platform. Omit to use the first registered URI.
|
|
28
|
+
*/
|
|
29
|
+
redirectUri?: string;
|
|
30
|
+
/** Force the login screen even if a session is already active. */
|
|
31
|
+
prompt?: 'login';
|
|
32
|
+
/** Pre-fill the email field on the login screen. */
|
|
33
|
+
email?: string;
|
|
34
|
+
}
|
|
35
|
+
interface ExchangeCodeResult {
|
|
36
|
+
apiKey: string;
|
|
37
|
+
user: {
|
|
38
|
+
id: string;
|
|
39
|
+
email: string;
|
|
40
|
+
name?: string;
|
|
41
|
+
};
|
|
42
|
+
plan: {
|
|
43
|
+
tier: string;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
declare class PlatformAuthError extends Error {
|
|
47
|
+
readonly status: number;
|
|
48
|
+
readonly body: unknown;
|
|
49
|
+
constructor(message: string, status: number, body: unknown);
|
|
50
|
+
}
|
|
51
|
+
declare class PlatformAuthClient {
|
|
52
|
+
private readonly baseUrl;
|
|
53
|
+
private readonly appId;
|
|
54
|
+
private readonly fetchImpl;
|
|
55
|
+
constructor(options: PlatformAuthClientOptions);
|
|
56
|
+
/**
|
|
57
|
+
* Build the URL the user is redirected to in order to start SSO.
|
|
58
|
+
* The platform redirects back to one of `appId`'s registered
|
|
59
|
+
* `redirectUris` with `?code=...&app=...&state=...`.
|
|
60
|
+
*/
|
|
61
|
+
authorizeUrl(options: AuthorizeUrlOptions): string;
|
|
62
|
+
/**
|
|
63
|
+
* Exchange a single-use auth code (delivered to the consumer's
|
|
64
|
+
* callback by the platform) for an API key + the user's identity.
|
|
65
|
+
* Codes are single-use and expire ~5 minutes after issue.
|
|
66
|
+
*/
|
|
67
|
+
exchange(code: string): Promise<ExchangeCodeResult>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Server-side client for the Tangle platform's integration hub
|
|
72
|
+
* (`/v1/hub/*`). Consumer apps use this instead of rolling their own
|
|
73
|
+
* OAuth + connection tables.
|
|
74
|
+
*
|
|
75
|
+
* Auth: the caller supplies a bearer (either the user's API key from
|
|
76
|
+
* cross-site exchange, or a platform service token) on construction.
|
|
77
|
+
*
|
|
78
|
+
* Endpoint contract (authoritative): the platform's `src/lib/hub-contract.ts`
|
|
79
|
+
* + `src/routes/hub.ts`. The platform wraps every response in
|
|
80
|
+
* `{ success, data }`; non-2xx or `success:false` surfaces as `PlatformHubError`
|
|
81
|
+
* carrying the real upstream status.
|
|
82
|
+
*/
|
|
83
|
+
interface PlatformHubClientOptions {
|
|
84
|
+
/** Platform base URL, e.g. `https://id.tangle.tools`. */
|
|
85
|
+
baseUrl: string;
|
|
86
|
+
/** Bearer credential — user API key or service token. */
|
|
87
|
+
bearer: string;
|
|
88
|
+
/** Override fetch (tests + edge runtimes). */
|
|
89
|
+
fetchImpl?: typeof fetch;
|
|
90
|
+
}
|
|
91
|
+
/** A live integration connection, as returned by `/v1/hub/connections`. */
|
|
92
|
+
interface PlatformConnection {
|
|
93
|
+
id: string;
|
|
94
|
+
providerId: string;
|
|
95
|
+
displayName: string;
|
|
96
|
+
accountDisplay: string | null;
|
|
97
|
+
scopes: string[];
|
|
98
|
+
status: 'active' | 'revoked' | 'unhealthy' | 'reconnect_required' | (string & {});
|
|
99
|
+
health: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {});
|
|
100
|
+
createdAt: string;
|
|
101
|
+
updatedAt: string;
|
|
102
|
+
lastUsedAt: string | null;
|
|
103
|
+
}
|
|
104
|
+
/** A connectable provider in the catalog (`/v1/hub/providers`). */
|
|
105
|
+
interface PlatformCatalogProvider {
|
|
106
|
+
providerId: string;
|
|
107
|
+
title?: string;
|
|
108
|
+
authKind?: string;
|
|
109
|
+
category?: string;
|
|
110
|
+
scopes?: string[];
|
|
111
|
+
capabilityCount?: number;
|
|
112
|
+
native?: boolean;
|
|
113
|
+
/** Whether the OAuth app's credentials are wired — the UI offers Connect
|
|
114
|
+
* only when true. */
|
|
115
|
+
configured?: boolean;
|
|
116
|
+
[k: string]: unknown;
|
|
117
|
+
}
|
|
118
|
+
interface CatalogResult {
|
|
119
|
+
providers: PlatformCatalogProvider[];
|
|
120
|
+
/** Count of substrate-bundled connectors behind the catalog. */
|
|
121
|
+
substrateBundled?: number;
|
|
122
|
+
[k: string]: unknown;
|
|
123
|
+
}
|
|
124
|
+
interface StartAuthInput {
|
|
125
|
+
/** The provider to connect (goes in the URL path). */
|
|
126
|
+
providerId: string;
|
|
127
|
+
/** Accepted for interface compatibility; the platform's start endpoint is
|
|
128
|
+
* provider-level and does not consume a connector id. */
|
|
129
|
+
connectorId?: string;
|
|
130
|
+
/** Where the platform redirects the user back to after OAuth. */
|
|
131
|
+
returnUrl: string;
|
|
132
|
+
/** Accepted for interface compatibility; not consumed by the start endpoint. */
|
|
133
|
+
requestedScopes?: string[];
|
|
134
|
+
/** CLI flow flag — affects the platform's post-auth redirect handling. */
|
|
135
|
+
cli?: boolean;
|
|
136
|
+
}
|
|
137
|
+
interface StartAuthResult {
|
|
138
|
+
/** The URL to send the user to. Normalized across the platform's two start
|
|
139
|
+
* branches: github returns `authorizationUrl`, substrate returns
|
|
140
|
+
* `redirectUrl`. */
|
|
141
|
+
authorizationUrl: string;
|
|
142
|
+
state: string;
|
|
143
|
+
expiresAt?: string;
|
|
144
|
+
scopes?: string[];
|
|
145
|
+
}
|
|
146
|
+
interface ConnectionHealth {
|
|
147
|
+
status: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {});
|
|
148
|
+
checkedAt: string;
|
|
149
|
+
error?: {
|
|
150
|
+
code: string;
|
|
151
|
+
message: string;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
interface ConnectionHealthResult {
|
|
155
|
+
connection: PlatformConnection;
|
|
156
|
+
health: ConnectionHealth;
|
|
157
|
+
}
|
|
158
|
+
/** Last-known health for a connection, derived from the connection row. */
|
|
159
|
+
interface HealthCheck {
|
|
160
|
+
connectionId: string;
|
|
161
|
+
providerId: string;
|
|
162
|
+
/** Mirrors `PlatformConnection.health`. */
|
|
163
|
+
status: ConnectionHealth['status'];
|
|
164
|
+
checkedAt?: string;
|
|
165
|
+
}
|
|
166
|
+
interface MintTokenInput {
|
|
167
|
+
/** The hub action the token authorizes (e.g. `slack.chat.postMessage`). */
|
|
168
|
+
actionPath: string;
|
|
169
|
+
/** Bind to a specific connection, or … */
|
|
170
|
+
connectionId?: string;
|
|
171
|
+
/** … resolve the connection by provider for the calling user. */
|
|
172
|
+
provider?: string;
|
|
173
|
+
}
|
|
174
|
+
interface MintTokenResult {
|
|
175
|
+
tokenId: string;
|
|
176
|
+
token: string;
|
|
177
|
+
expiresAt: string;
|
|
178
|
+
}
|
|
179
|
+
interface ExecInput {
|
|
180
|
+
/** The hub action path to execute. */
|
|
181
|
+
path: string;
|
|
182
|
+
input?: unknown;
|
|
183
|
+
connectionId?: string;
|
|
184
|
+
}
|
|
185
|
+
interface PlatformHubStatus {
|
|
186
|
+
contract?: unknown;
|
|
187
|
+
principal: {
|
|
188
|
+
kind: string;
|
|
189
|
+
userId: string;
|
|
190
|
+
[k: string]: unknown;
|
|
191
|
+
};
|
|
192
|
+
connections: {
|
|
193
|
+
connectedProviderCount: number;
|
|
194
|
+
unhealthyProviderCount: number;
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
declare class PlatformHubError extends Error {
|
|
198
|
+
readonly status: number;
|
|
199
|
+
readonly code: string | undefined;
|
|
200
|
+
readonly body: unknown;
|
|
201
|
+
constructor(message: string, status: number, code: string | undefined, body: unknown);
|
|
202
|
+
}
|
|
203
|
+
declare class PlatformHubClient {
|
|
204
|
+
private readonly baseUrl;
|
|
205
|
+
private readonly bearer;
|
|
206
|
+
private readonly fetchImpl;
|
|
207
|
+
constructor(options: PlatformHubClientOptions);
|
|
208
|
+
/** GET /v1/hub/providers — the connectable provider catalog. */
|
|
209
|
+
catalog(): Promise<CatalogResult>;
|
|
210
|
+
/** GET /v1/hub/connections — the calling user's live connections. */
|
|
211
|
+
listConnections(): Promise<PlatformConnection[]>;
|
|
212
|
+
/** DELETE /v1/hub/connections/:connectionId — revoke + disable a connection. */
|
|
213
|
+
revokeConnection(connectionId: string): Promise<{
|
|
214
|
+
connection: PlatformConnection;
|
|
215
|
+
}>;
|
|
216
|
+
/**
|
|
217
|
+
* POST /v1/hub/connections/:provider/start — begin OAuth/grant. The provider
|
|
218
|
+
* is taken from the URL; the body carries `returnUrl` (+ `cli`). The platform's
|
|
219
|
+
* two start branches name the URL field differently (github → `authorizationUrl`,
|
|
220
|
+
* substrate → `redirectUrl`); this normalizes to `authorizationUrl`.
|
|
221
|
+
*/
|
|
222
|
+
startAuth(input: StartAuthInput): Promise<StartAuthResult>;
|
|
223
|
+
/**
|
|
224
|
+
* Last-known health for every connection. The platform has no global
|
|
225
|
+
* healthcheck listing — health rides on each connection row — so this derives
|
|
226
|
+
* the list from `listConnections()` (one request, no extra round-trips).
|
|
227
|
+
*/
|
|
228
|
+
listHealthchecks(): Promise<HealthCheck[]>;
|
|
229
|
+
/**
|
|
230
|
+
* POST /v1/hub/connections/:connectionId/health — trigger a fresh health
|
|
231
|
+
* probe for one connection and return its updated state.
|
|
232
|
+
*/
|
|
233
|
+
checkConnectionHealth(connectionId: string): Promise<ConnectionHealthResult>;
|
|
234
|
+
/**
|
|
235
|
+
* Trigger a fresh health probe across all of the user's connections. The
|
|
236
|
+
* platform exposes health per-connection only, so this fans out over
|
|
237
|
+
* `listConnections()`. `scheduled` is the number of probes dispatched.
|
|
238
|
+
*/
|
|
239
|
+
runHealthchecks(): Promise<{
|
|
240
|
+
scheduled: number;
|
|
241
|
+
}>;
|
|
242
|
+
/** GET /v1/hub/status — principal + aggregate connection counts. */
|
|
243
|
+
status(): Promise<PlatformHubStatus>;
|
|
244
|
+
/**
|
|
245
|
+
* POST /v1/hub/tokens — mint a short-lived, action-scoped capability token a
|
|
246
|
+
* sandbox can use to invoke one hub action on the user's behalf without
|
|
247
|
+
* seeing the underlying provider credential.
|
|
248
|
+
*/
|
|
249
|
+
mintToken(input: MintTokenInput): Promise<MintTokenResult>;
|
|
250
|
+
/** POST /v1/hub/exec — execute a hub action and return its result. */
|
|
251
|
+
exec(input: ExecInput): Promise<unknown>;
|
|
252
|
+
private request;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export { type AuthorizeUrlOptions, type CatalogResult, type ConnectionHealth, type ConnectionHealthResult, type ExchangeCodeResult, type ExecInput, type HealthCheck, type MintTokenInput, type MintTokenResult, PlatformAuthClient, type PlatformAuthClientOptions, PlatformAuthError, type PlatformCatalogProvider, type PlatformConnection, PlatformHubClient, type PlatformHubClientOptions, PlatformHubError, type PlatformHubStatus, type StartAuthInput, type StartAuthResult };
|
package/dist/platform.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import "./chunk-DGUM43GV.js";
|
|
2
|
+
|
|
3
|
+
// src/platform/auth.ts
|
|
4
|
+
var PlatformAuthError = class extends Error {
|
|
5
|
+
constructor(message, status, body) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.body = body;
|
|
9
|
+
this.name = "PlatformAuthError";
|
|
10
|
+
}
|
|
11
|
+
status;
|
|
12
|
+
body;
|
|
13
|
+
};
|
|
14
|
+
var PlatformAuthClient = class {
|
|
15
|
+
baseUrl;
|
|
16
|
+
appId;
|
|
17
|
+
fetchImpl;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
if (!options.baseUrl) throw new Error("PlatformAuthClient: baseUrl is required");
|
|
20
|
+
if (!options.appId) throw new Error("PlatformAuthClient: appId is required");
|
|
21
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
22
|
+
this.appId = options.appId;
|
|
23
|
+
this.fetchImpl = options.fetchImpl ?? ((url, init) => fetch(url, init));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Build the URL the user is redirected to in order to start SSO.
|
|
27
|
+
* The platform redirects back to one of `appId`'s registered
|
|
28
|
+
* `redirectUris` with `?code=...&app=...&state=...`.
|
|
29
|
+
*/
|
|
30
|
+
authorizeUrl(options) {
|
|
31
|
+
if (!options.state) {
|
|
32
|
+
throw new Error("PlatformAuthClient.authorizeUrl: state is required for CSRF");
|
|
33
|
+
}
|
|
34
|
+
const url = new URL("/cross-site/authorize", this.baseUrl);
|
|
35
|
+
url.searchParams.set("app", this.appId);
|
|
36
|
+
url.searchParams.set("state", options.state);
|
|
37
|
+
if (options.redirectUri) url.searchParams.set("redirect", options.redirectUri);
|
|
38
|
+
if (options.prompt) url.searchParams.set("prompt", options.prompt);
|
|
39
|
+
if (options.email) url.searchParams.set("email", options.email);
|
|
40
|
+
return url.toString();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Exchange a single-use auth code (delivered to the consumer's
|
|
44
|
+
* callback by the platform) for an API key + the user's identity.
|
|
45
|
+
* Codes are single-use and expire ~5 minutes after issue.
|
|
46
|
+
*/
|
|
47
|
+
async exchange(code) {
|
|
48
|
+
if (!code) throw new Error("PlatformAuthClient.exchange: code is required");
|
|
49
|
+
const res = await this.fetchImpl(`${this.baseUrl}/cross-site/exchange`, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers: { "content-type": "application/json" },
|
|
52
|
+
body: JSON.stringify({ code, app: this.appId })
|
|
53
|
+
});
|
|
54
|
+
const body = await res.json().catch(() => null);
|
|
55
|
+
if (!res.ok) {
|
|
56
|
+
const message = body && typeof body === "object" && "error" in body && typeof body.error === "string" ? body.error : `Platform exchange failed (${res.status})`;
|
|
57
|
+
throw new PlatformAuthError(message, res.status, body);
|
|
58
|
+
}
|
|
59
|
+
const result = body;
|
|
60
|
+
if (!result.apiKey || !result.user?.id) {
|
|
61
|
+
throw new PlatformAuthError(
|
|
62
|
+
"Platform exchange response is missing apiKey or user",
|
|
63
|
+
res.status,
|
|
64
|
+
body
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// src/platform/integrations.ts
|
|
72
|
+
var PlatformHubError = class extends Error {
|
|
73
|
+
constructor(message, status, code, body) {
|
|
74
|
+
super(message);
|
|
75
|
+
this.status = status;
|
|
76
|
+
this.code = code;
|
|
77
|
+
this.body = body;
|
|
78
|
+
this.name = "PlatformHubError";
|
|
79
|
+
}
|
|
80
|
+
status;
|
|
81
|
+
code;
|
|
82
|
+
body;
|
|
83
|
+
};
|
|
84
|
+
var PlatformHubClient = class {
|
|
85
|
+
baseUrl;
|
|
86
|
+
bearer;
|
|
87
|
+
fetchImpl;
|
|
88
|
+
constructor(options) {
|
|
89
|
+
if (!options.baseUrl) throw new Error("PlatformHubClient: baseUrl is required");
|
|
90
|
+
if (!options.bearer) throw new Error("PlatformHubClient: bearer is required");
|
|
91
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
92
|
+
this.bearer = options.bearer;
|
|
93
|
+
this.fetchImpl = options.fetchImpl ?? ((url, init) => fetch(url, init));
|
|
94
|
+
}
|
|
95
|
+
/** GET /v1/hub/providers — the connectable provider catalog. */
|
|
96
|
+
catalog() {
|
|
97
|
+
return this.request("GET", "/v1/hub/providers");
|
|
98
|
+
}
|
|
99
|
+
/** GET /v1/hub/connections — the calling user's live connections. */
|
|
100
|
+
async listConnections() {
|
|
101
|
+
const data = await this.request(
|
|
102
|
+
"GET",
|
|
103
|
+
"/v1/hub/connections"
|
|
104
|
+
);
|
|
105
|
+
return data.connections;
|
|
106
|
+
}
|
|
107
|
+
/** DELETE /v1/hub/connections/:connectionId — revoke + disable a connection. */
|
|
108
|
+
revokeConnection(connectionId) {
|
|
109
|
+
return this.request("DELETE", `/v1/hub/connections/${encodeURIComponent(connectionId)}`);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* POST /v1/hub/connections/:provider/start — begin OAuth/grant. The provider
|
|
113
|
+
* is taken from the URL; the body carries `returnUrl` (+ `cli`). The platform's
|
|
114
|
+
* two start branches name the URL field differently (github → `authorizationUrl`,
|
|
115
|
+
* substrate → `redirectUrl`); this normalizes to `authorizationUrl`.
|
|
116
|
+
*/
|
|
117
|
+
async startAuth(input) {
|
|
118
|
+
const body = { returnUrl: input.returnUrl };
|
|
119
|
+
if (input.cli !== void 0) body.cli = input.cli;
|
|
120
|
+
const data = await this.request("POST", `/v1/hub/connections/${encodeURIComponent(input.providerId)}/start`, body);
|
|
121
|
+
const authorizationUrl = data.authorizationUrl ?? data.redirectUrl;
|
|
122
|
+
if (!authorizationUrl) {
|
|
123
|
+
throw new PlatformHubError(
|
|
124
|
+
"Platform hub start response missing an authorization URL",
|
|
125
|
+
502,
|
|
126
|
+
"HUB_INVALID_START_RESPONSE",
|
|
127
|
+
data
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
return { authorizationUrl, state: data.state, expiresAt: data.expiresAt, scopes: data.scopes };
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Last-known health for every connection. The platform has no global
|
|
134
|
+
* healthcheck listing — health rides on each connection row — so this derives
|
|
135
|
+
* the list from `listConnections()` (one request, no extra round-trips).
|
|
136
|
+
*/
|
|
137
|
+
async listHealthchecks() {
|
|
138
|
+
const connections = await this.listConnections();
|
|
139
|
+
return connections.map((c) => ({
|
|
140
|
+
connectionId: c.id,
|
|
141
|
+
providerId: c.providerId,
|
|
142
|
+
status: c.health,
|
|
143
|
+
checkedAt: c.updatedAt
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* POST /v1/hub/connections/:connectionId/health — trigger a fresh health
|
|
148
|
+
* probe for one connection and return its updated state.
|
|
149
|
+
*/
|
|
150
|
+
checkConnectionHealth(connectionId) {
|
|
151
|
+
return this.request("POST", `/v1/hub/connections/${encodeURIComponent(connectionId)}/health`);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Trigger a fresh health probe across all of the user's connections. The
|
|
155
|
+
* platform exposes health per-connection only, so this fans out over
|
|
156
|
+
* `listConnections()`. `scheduled` is the number of probes dispatched.
|
|
157
|
+
*/
|
|
158
|
+
async runHealthchecks() {
|
|
159
|
+
const connections = await this.listConnections();
|
|
160
|
+
await Promise.allSettled(connections.map((c) => this.checkConnectionHealth(c.id)));
|
|
161
|
+
return { scheduled: connections.length };
|
|
162
|
+
}
|
|
163
|
+
/** GET /v1/hub/status — principal + aggregate connection counts. */
|
|
164
|
+
status() {
|
|
165
|
+
return this.request("GET", "/v1/hub/status");
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* POST /v1/hub/tokens — mint a short-lived, action-scoped capability token a
|
|
169
|
+
* sandbox can use to invoke one hub action on the user's behalf without
|
|
170
|
+
* seeing the underlying provider credential.
|
|
171
|
+
*/
|
|
172
|
+
mintToken(input) {
|
|
173
|
+
return this.request("POST", "/v1/hub/tokens", input);
|
|
174
|
+
}
|
|
175
|
+
/** POST /v1/hub/exec — execute a hub action and return its result. */
|
|
176
|
+
async exec(input) {
|
|
177
|
+
const data = await this.request("POST", "/v1/hub/exec", input);
|
|
178
|
+
return data.result;
|
|
179
|
+
}
|
|
180
|
+
async request(method, path, body) {
|
|
181
|
+
const headers = {
|
|
182
|
+
authorization: `Bearer ${this.bearer}`,
|
|
183
|
+
accept: "application/json"
|
|
184
|
+
};
|
|
185
|
+
if (body !== void 0) headers["content-type"] = "application/json";
|
|
186
|
+
const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
187
|
+
method,
|
|
188
|
+
headers,
|
|
189
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
190
|
+
});
|
|
191
|
+
const text = await res.text();
|
|
192
|
+
let parsed = null;
|
|
193
|
+
if (text) {
|
|
194
|
+
try {
|
|
195
|
+
parsed = JSON.parse(text);
|
|
196
|
+
} catch {
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (!res.ok || parsed && parsed.success === false) {
|
|
200
|
+
const code = parsed?.error && typeof parsed.error === "object" ? parsed.error.code : void 0;
|
|
201
|
+
const message = parsed?.error && typeof parsed.error === "object" && parsed.error.message || (typeof parsed?.error === "string" ? parsed.error : `Platform hub error (${res.status})`);
|
|
202
|
+
throw new PlatformHubError(message, res.status, code, parsed ?? text);
|
|
203
|
+
}
|
|
204
|
+
if (!parsed) {
|
|
205
|
+
throw new PlatformHubError(
|
|
206
|
+
`Platform hub returned non-JSON success (${res.status})`,
|
|
207
|
+
res.status,
|
|
208
|
+
void 0,
|
|
209
|
+
text
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
if (parsed.data === void 0) {
|
|
213
|
+
throw new PlatformHubError(
|
|
214
|
+
"Platform hub envelope missing `data`",
|
|
215
|
+
res.status,
|
|
216
|
+
void 0,
|
|
217
|
+
parsed
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
return parsed.data;
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
export {
|
|
224
|
+
PlatformAuthClient,
|
|
225
|
+
PlatformAuthError,
|
|
226
|
+
PlatformHubClient,
|
|
227
|
+
PlatformHubError
|
|
228
|
+
};
|
|
229
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/platform/auth.ts","../src/platform/integrations.ts"],"sourcesContent":["/**\n * Server-side client for the Tangle platform's cross-site SSO bridge.\n *\n * Consumer apps (gtm-agent, tax-agent, legal-agent, creative-agent, …)\n * use this to:\n * 1. Build an /authorize URL that lands the user on id.tangle.tools\n * and brings them back with a single-use code.\n * 2. Exchange that code for an API key + the user's identity.\n *\n * The platform endpoint contract is documented in\n * `products/platform/api/src/routes/cross-site.ts`. This client only\n * speaks HTTP — no SDK weight, no transitive deps.\n */\n\nexport interface PlatformAuthClientOptions {\n /** Platform base URL, e.g. `https://id.tangle.tools`. */\n baseUrl: string\n /** App id as registered in the platform's TRUSTED_APPS registry. */\n appId: string\n /** Override the global fetch (useful for tests + edge runtimes). */\n fetchImpl?: typeof fetch\n}\n\nexport interface AuthorizeUrlOptions {\n /** Required CSRF token; the consumer verifies it on the callback. */\n state: string\n /**\n * Final redirect URI. Must be one of the URIs registered for `appId`\n * on the platform. Omit to use the first registered URI.\n */\n redirectUri?: string\n /** Force the login screen even if a session is already active. */\n prompt?: 'login'\n /** Pre-fill the email field on the login screen. */\n email?: string\n}\n\nexport interface ExchangeCodeResult {\n apiKey: string\n user: {\n id: string\n email: string\n name?: string\n }\n plan: {\n tier: string\n }\n}\n\nexport class PlatformAuthError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly body: unknown,\n ) {\n super(message)\n this.name = 'PlatformAuthError'\n }\n}\n\nexport class PlatformAuthClient {\n private readonly baseUrl: string\n private readonly appId: string\n private readonly fetchImpl: typeof fetch\n\n constructor(options: PlatformAuthClientOptions) {\n if (!options.baseUrl) throw new Error('PlatformAuthClient: baseUrl is required')\n if (!options.appId) throw new Error('PlatformAuthClient: appId is required')\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '')\n this.appId = options.appId\n this.fetchImpl =\n options.fetchImpl ??\n ((url: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => fetch(url, init))\n }\n\n /**\n * Build the URL the user is redirected to in order to start SSO.\n * The platform redirects back to one of `appId`'s registered\n * `redirectUris` with `?code=...&app=...&state=...`.\n */\n authorizeUrl(options: AuthorizeUrlOptions): string {\n if (!options.state) {\n throw new Error('PlatformAuthClient.authorizeUrl: state is required for CSRF')\n }\n const url = new URL('/cross-site/authorize', this.baseUrl)\n url.searchParams.set('app', this.appId)\n url.searchParams.set('state', options.state)\n if (options.redirectUri) url.searchParams.set('redirect', options.redirectUri)\n if (options.prompt) url.searchParams.set('prompt', options.prompt)\n if (options.email) url.searchParams.set('email', options.email)\n return url.toString()\n }\n\n /**\n * Exchange a single-use auth code (delivered to the consumer's\n * callback by the platform) for an API key + the user's identity.\n * Codes are single-use and expire ~5 minutes after issue.\n */\n async exchange(code: string): Promise<ExchangeCodeResult> {\n if (!code) throw new Error('PlatformAuthClient.exchange: code is required')\n const res = await this.fetchImpl(`${this.baseUrl}/cross-site/exchange`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ code, app: this.appId }),\n })\n const body = await res.json().catch(() => null)\n if (!res.ok) {\n const message =\n body && typeof body === 'object' && 'error' in body && typeof body.error === 'string'\n ? body.error\n : `Platform exchange failed (${res.status})`\n throw new PlatformAuthError(message, res.status, body)\n }\n const result = body as Partial<ExchangeCodeResult>\n if (!result.apiKey || !result.user?.id) {\n throw new PlatformAuthError(\n 'Platform exchange response is missing apiKey or user',\n res.status,\n body,\n )\n }\n return result as ExchangeCodeResult\n }\n}\n","/**\n * Server-side client for the Tangle platform's integration hub\n * (`/v1/hub/*`). Consumer apps use this instead of rolling their own\n * OAuth + connection tables.\n *\n * Auth: the caller supplies a bearer (either the user's API key from\n * cross-site exchange, or a platform service token) on construction.\n *\n * Endpoint contract (authoritative): the platform's `src/lib/hub-contract.ts`\n * + `src/routes/hub.ts`. The platform wraps every response in\n * `{ success, data }`; non-2xx or `success:false` surfaces as `PlatformHubError`\n * carrying the real upstream status.\n */\n\nexport interface PlatformHubClientOptions {\n /** Platform base URL, e.g. `https://id.tangle.tools`. */\n baseUrl: string\n /** Bearer credential — user API key or service token. */\n bearer: string\n /** Override fetch (tests + edge runtimes). */\n fetchImpl?: typeof fetch\n}\n\n/** A live integration connection, as returned by `/v1/hub/connections`. */\nexport interface PlatformConnection {\n id: string\n providerId: string\n displayName: string\n accountDisplay: string | null\n scopes: string[]\n status: 'active' | 'revoked' | 'unhealthy' | 'reconnect_required' | (string & {})\n health: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {})\n createdAt: string\n updatedAt: string\n lastUsedAt: string | null\n}\n\n/** A connectable provider in the catalog (`/v1/hub/providers`). */\nexport interface PlatformCatalogProvider {\n providerId: string\n title?: string\n authKind?: string\n category?: string\n scopes?: string[]\n capabilityCount?: number\n native?: boolean\n /** Whether the OAuth app's credentials are wired — the UI offers Connect\n * only when true. */\n configured?: boolean\n [k: string]: unknown\n}\n\nexport interface CatalogResult {\n providers: PlatformCatalogProvider[]\n /** Count of substrate-bundled connectors behind the catalog. */\n substrateBundled?: number\n [k: string]: unknown\n}\n\nexport interface StartAuthInput {\n /** The provider to connect (goes in the URL path). */\n providerId: string\n /** Accepted for interface compatibility; the platform's start endpoint is\n * provider-level and does not consume a connector id. */\n connectorId?: string\n /** Where the platform redirects the user back to after OAuth. */\n returnUrl: string\n /** Accepted for interface compatibility; not consumed by the start endpoint. */\n requestedScopes?: string[]\n /** CLI flow flag — affects the platform's post-auth redirect handling. */\n cli?: boolean\n}\n\nexport interface StartAuthResult {\n /** The URL to send the user to. Normalized across the platform's two start\n * branches: github returns `authorizationUrl`, substrate returns\n * `redirectUrl`. */\n authorizationUrl: string\n state: string\n expiresAt?: string\n scopes?: string[]\n}\n\nexport interface ConnectionHealth {\n status: 'unknown' | 'healthy' | 'unhealthy' | 'rate_limited' | (string & {})\n checkedAt: string\n error?: { code: string; message: string }\n}\n\nexport interface ConnectionHealthResult {\n connection: PlatformConnection\n health: ConnectionHealth\n}\n\n/** Last-known health for a connection, derived from the connection row. */\nexport interface HealthCheck {\n connectionId: string\n providerId: string\n /** Mirrors `PlatformConnection.health`. */\n status: ConnectionHealth['status']\n checkedAt?: string\n}\n\nexport interface MintTokenInput {\n /** The hub action the token authorizes (e.g. `slack.chat.postMessage`). */\n actionPath: string\n /** Bind to a specific connection, or … */\n connectionId?: string\n /** … resolve the connection by provider for the calling user. */\n provider?: string\n}\n\nexport interface MintTokenResult {\n tokenId: string\n token: string\n expiresAt: string\n}\n\nexport interface ExecInput {\n /** The hub action path to execute. */\n path: string\n input?: unknown\n connectionId?: string\n}\n\nexport interface PlatformHubStatus {\n contract?: unknown\n principal: { kind: string; userId: string; [k: string]: unknown }\n connections: { connectedProviderCount: number; unhealthyProviderCount: number }\n}\n\nexport class PlatformHubError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly code: string | undefined,\n public readonly body: unknown,\n ) {\n super(message)\n this.name = 'PlatformHubError'\n }\n}\n\ninterface PlatformEnvelope<T> {\n success: boolean\n data?: T\n error?: { code?: string; message?: string } | string\n}\n\nexport class PlatformHubClient {\n private readonly baseUrl: string\n private readonly bearer: string\n private readonly fetchImpl: typeof fetch\n\n constructor(options: PlatformHubClientOptions) {\n if (!options.baseUrl) throw new Error('PlatformHubClient: baseUrl is required')\n if (!options.bearer) throw new Error('PlatformHubClient: bearer is required')\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '')\n this.bearer = options.bearer\n this.fetchImpl =\n options.fetchImpl ??\n ((url: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => fetch(url, init))\n }\n\n /** GET /v1/hub/providers — the connectable provider catalog. */\n catalog(): Promise<CatalogResult> {\n return this.request('GET', '/v1/hub/providers')\n }\n\n /** GET /v1/hub/connections — the calling user's live connections. */\n async listConnections(): Promise<PlatformConnection[]> {\n const data = await this.request<{ connections: PlatformConnection[] }>(\n 'GET',\n '/v1/hub/connections',\n )\n return data.connections\n }\n\n /** DELETE /v1/hub/connections/:connectionId — revoke + disable a connection. */\n revokeConnection(connectionId: string): Promise<{ connection: PlatformConnection }> {\n return this.request('DELETE', `/v1/hub/connections/${encodeURIComponent(connectionId)}`)\n }\n\n /**\n * POST /v1/hub/connections/:provider/start — begin OAuth/grant. The provider\n * is taken from the URL; the body carries `returnUrl` (+ `cli`). The platform's\n * two start branches name the URL field differently (github → `authorizationUrl`,\n * substrate → `redirectUrl`); this normalizes to `authorizationUrl`.\n */\n async startAuth(input: StartAuthInput): Promise<StartAuthResult> {\n const body: { returnUrl: string; cli?: boolean } = { returnUrl: input.returnUrl }\n if (input.cli !== undefined) body.cli = input.cli\n const data = await this.request<{\n authorizationUrl?: string\n redirectUrl?: string\n state: string\n expiresAt?: string\n scopes?: string[]\n }>('POST', `/v1/hub/connections/${encodeURIComponent(input.providerId)}/start`, body)\n const authorizationUrl = data.authorizationUrl ?? data.redirectUrl\n if (!authorizationUrl) {\n throw new PlatformHubError(\n 'Platform hub start response missing an authorization URL',\n 502,\n 'HUB_INVALID_START_RESPONSE',\n data,\n )\n }\n return { authorizationUrl, state: data.state, expiresAt: data.expiresAt, scopes: data.scopes }\n }\n\n /**\n * Last-known health for every connection. The platform has no global\n * healthcheck listing — health rides on each connection row — so this derives\n * the list from `listConnections()` (one request, no extra round-trips).\n */\n async listHealthchecks(): Promise<HealthCheck[]> {\n const connections = await this.listConnections()\n return connections.map((c) => ({\n connectionId: c.id,\n providerId: c.providerId,\n status: c.health,\n checkedAt: c.updatedAt,\n }))\n }\n\n /**\n * POST /v1/hub/connections/:connectionId/health — trigger a fresh health\n * probe for one connection and return its updated state.\n */\n checkConnectionHealth(connectionId: string): Promise<ConnectionHealthResult> {\n return this.request('POST', `/v1/hub/connections/${encodeURIComponent(connectionId)}/health`)\n }\n\n /**\n * Trigger a fresh health probe across all of the user's connections. The\n * platform exposes health per-connection only, so this fans out over\n * `listConnections()`. `scheduled` is the number of probes dispatched.\n */\n async runHealthchecks(): Promise<{ scheduled: number }> {\n const connections = await this.listConnections()\n await Promise.allSettled(connections.map((c) => this.checkConnectionHealth(c.id)))\n return { scheduled: connections.length }\n }\n\n /** GET /v1/hub/status — principal + aggregate connection counts. */\n status(): Promise<PlatformHubStatus> {\n return this.request('GET', '/v1/hub/status')\n }\n\n /**\n * POST /v1/hub/tokens — mint a short-lived, action-scoped capability token a\n * sandbox can use to invoke one hub action on the user's behalf without\n * seeing the underlying provider credential.\n */\n mintToken(input: MintTokenInput): Promise<MintTokenResult> {\n return this.request('POST', '/v1/hub/tokens', input)\n }\n\n /** POST /v1/hub/exec — execute a hub action and return its result. */\n async exec(input: ExecInput): Promise<unknown> {\n const data = await this.request<{ result: unknown }>('POST', '/v1/hub/exec', input)\n return data.result\n }\n\n private async request<T>(\n method: 'GET' | 'POST' | 'DELETE' | 'PUT',\n path: string,\n body?: unknown,\n ): Promise<T> {\n const headers: Record<string, string> = {\n authorization: `Bearer ${this.bearer}`,\n accept: 'application/json',\n }\n if (body !== undefined) headers['content-type'] = 'application/json'\n\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n })\n const text = await res.text()\n let parsed: PlatformEnvelope<T> | null = null\n if (text) {\n try {\n parsed = JSON.parse(text)\n } catch {\n // fall through to error handling below\n }\n }\n if (!res.ok || (parsed && parsed.success === false)) {\n const code = parsed?.error && typeof parsed.error === 'object' ? parsed.error.code : undefined\n const message =\n (parsed?.error && typeof parsed.error === 'object' && parsed.error.message) ||\n (typeof parsed?.error === 'string' ? parsed.error : `Platform hub error (${res.status})`)\n throw new PlatformHubError(message, res.status, code, parsed ?? text)\n }\n if (!parsed) {\n throw new PlatformHubError(\n `Platform hub returned non-JSON success (${res.status})`,\n res.status,\n undefined,\n text,\n )\n }\n if (parsed.data === undefined) {\n throw new PlatformHubError(\n 'Platform hub envelope missing `data`',\n res.status,\n undefined,\n parsed,\n )\n }\n return parsed.data\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/profiles.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { U as UiFinding, a as UiLens } from './substrate-BoRXgvka.js';
|
|
2
2
|
export { C as CoderTask, D as DEFAULT_CODER_SYSTEM_PROMPT, b as UI_FINDING_SEVERITIES, c as UI_LENSES, d as UiFindingScreenshot, e as UiFindingSeverity, f as coderProfile, g as coderTaskToPrompt } from './substrate-BoRXgvka.js';
|
|
3
|
-
import { S as SandboxClient, a as OutputAdapter, V as Validator, A as AgentRunSpec } from './types-
|
|
3
|
+
import { S as SandboxClient, a as OutputAdapter, V as Validator, A as AgentRunSpec } from './types-CdnEAE3U.js';
|
|
4
4
|
import { SandboxEvent } from '@tangle-network/sandbox';
|
|
5
5
|
import { AgentProfile } from '@tangle-network/agent-interface';
|
|
6
6
|
import '@tangle-network/agent-eval';
|
|
@@ -168,6 +168,20 @@ interface FindingsStoreLike {
|
|
|
168
168
|
append(runId: string, findings: ReadonlyArray<AnalystFinding>): Promise<void>;
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Narrow the `AnalystRegistryLike` further when we need streaming: the
|
|
173
|
+
* loop checks if the registry exposes `runStream` and uses it when
|
|
174
|
+
* present, falling back to `run()` otherwise. This keeps the type
|
|
175
|
+
* surface backwards-compatible — older registry shims that only
|
|
176
|
+
* implement `run` still work; they just don't forward per-analyst
|
|
177
|
+
* events.
|
|
178
|
+
*/
|
|
179
|
+
interface AnalystRegistryStreamingLike extends AnalystRegistryLike {
|
|
180
|
+
runStream?(runId: string, inputs: AnalystRunInputs, opts?: {
|
|
181
|
+
priorFindings?: ReadonlyArray<AnalystFinding> | Record<string, ReadonlyArray<AnalystFinding>>;
|
|
182
|
+
[k: string]: unknown;
|
|
183
|
+
}): AsyncIterable<AnalystRunEvent>;
|
|
184
|
+
}
|
|
171
185
|
/**
|
|
172
186
|
* Events emitted by `runAnalystLoop` via `opts.onEvent`. UIs and
|
|
173
187
|
* JSONL tail-sinks consume this stream. The loop awaits each
|
|
@@ -228,4 +242,4 @@ type AnalystLoopEvent = {
|
|
|
228
242
|
durationMs: number;
|
|
229
243
|
};
|
|
230
244
|
|
|
231
|
-
export type {
|
|
245
|
+
export type { AnalystLoopEvent as A, FindingsStoreLike as F, ImprovementAdapter as I, KnowledgeAdapter as K, RunAnalystLoopOpts as R, RunAnalystLoopResult as a, AnalystRegistryLike as b, AnalystRegistryStreamingLike as c, AutoApplyPolicy as d, ImprovementEditBatch as e, ImprovementReport as f, KnowledgeProposalBatch as g, KnowledgeReport as h };
|
|
@@ -1178,4 +1178,4 @@ interface ExecCtx {
|
|
|
1178
1178
|
parentSpanId?: string;
|
|
1179
1179
|
}
|
|
1180
1180
|
|
|
1181
|
-
export { type LoopIterationDispatchPayload as $, type AgentRunSpec as A, type BackendErrorDetail as B, type RuntimeHookEvent as C, type RuntimeHookPhase as D, type
|
|
1181
|
+
export { type LoopIterationDispatchPayload as $, type AgentRunSpec as A, type BackendErrorDetail as B, type RuntimeHookEvent as C, type RuntimeHookPhase as D, type ExecCtx as E, type RuntimeHookTarget as F, type RuntimeRunHandle as G, type RuntimeRunPersistenceAdapter as H, type Iteration as I, type RuntimeRunRow as J, type KnowledgeReadinessDecision as K, type LoopTraceEvent as L, composeRuntimeHooks as M, defineRuntimeHooks as N, type OpenAIChatTool as O, notifyRuntimeDecisionPoint as P, notifyRuntimeHookEvent as Q, type RuntimeStreamEvent as R, type SandboxClient as S, startRuntimeRun as T, type Driver as U, type Validator as V, type LoopWinner as W, type LoopLineageOptions as X, type LoopResult as Y, type LoopDecisionPayload as Z, type LoopEndedPayload as _, type OutputAdapter as a, type LoopIterationEndedPayload as a0, type LoopIterationStartedPayload as a1, type LoopPlanDescription as a2, type LoopPlanPayload as a3, type LoopStartedPayload as a4, type LoopTeardownFailedPayload as a5, type ValidationCtx as a6, type RuntimeHooks as b, type LoopSandboxPlacement as c, type LoopTokenUsage as d, type LoopTraceEmitter as e, type AgentBackendInput as f, type AgentExecutionBackend as g, type OpenAIChatToolChoice as h, type AgentBackendContext as i, type RunAgentTaskOptions as j, type AgentTaskRunResult as k, type RunAgentTaskStreamOptions as l, type AgentRuntimeEvent as m, type AgentTaskStatus as n, type RuntimeSessionStore as o, type RuntimeSession as p, type AgentAdapter as q, type AgentKnowledgeProvider as r, type AgentRuntimeEventSink as s, type AgentTaskContext as t, type AgentTaskSpec as u, type RuntimeDecisionEvidenceRef as v, type RuntimeDecisionKind as w, type RuntimeDecisionPoint as x, type RuntimeHookContext as y, type RuntimeHookErrorContext as z };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AgentProfile } from '@tangle-network/agent-interface';
|
|
2
2
|
import { AnalystFinding, DefaultVerdict } from '@tangle-network/agent-eval';
|
|
3
|
-
import {
|
|
4
|
-
import { b as RuntimeHooks, I as Iteration } from './types-
|
|
3
|
+
import { k as AgentSpec, e as ExecutorRegistry, B as Budget, A as Agent, l as SpawnJournal, j as ResultBlobStore, m as RootHandle, n as SupervisedResult, N as NodeId, o as Settled, S as Spend, i as Scope, L as LocalHarness, G as GitRunner, r as runLocalHarness, p as Executor, f as DeliverableSpec } from './delegates-CsXJPZDH.js';
|
|
4
|
+
import { b as RuntimeHooks, I as Iteration } from './types-CdnEAE3U.js';
|
|
5
5
|
import { BackendType } from '@tangle-network/sandbox';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -763,48 +763,6 @@ interface EqualKOnCostOptions {
|
|
|
763
763
|
/** `equalKOnCost(arms, opts)` — the cross-arm equal-compute check on conserved cost. */
|
|
764
764
|
type EqualKOnCost = (arms: ReadonlyArray<EqualKArm>, options?: EqualKOnCostOptions) => EqualKVerdict;
|
|
765
765
|
|
|
766
|
-
/**
|
|
767
|
-
* @experimental
|
|
768
|
-
*
|
|
769
|
-
* The completion-oracle: **settled ⟺ DELIVERED.**
|
|
770
|
-
*
|
|
771
|
-
* Foreman's one hard lesson (0/18 self-improvement deliverables) — "done" must mean a check
|
|
772
|
-
* PASSED, not the agent's say-so. `gateOnDeliverable` wraps an `Executor` so its settlement
|
|
773
|
-
* is `valid` ONLY when the deliverable check passes. The child still RUNS and settles (its
|
|
774
|
-
* spend is conserved into the pool either way), but a child that ran WITHOUT delivering
|
|
775
|
-
* settles `valid:false` — so a keep-best driver never counts it as done, and a gate never
|
|
776
|
-
* inflates with self-judged wins.
|
|
777
|
-
*
|
|
778
|
-
* Dual-purpose by construction:
|
|
779
|
-
* - product: the agent fleet only advances on real, checked deliverables.
|
|
780
|
-
* - proof: the gate's `valid` is the honest settle — equal-k comparisons can't be gamed by an
|
|
781
|
-
* arm that "ran" without producing the artifact.
|
|
782
|
-
*
|
|
783
|
-
* The check is a DEPLOYABLE oracle — a test command, a state verifier, the commit0 judge —
|
|
784
|
-
* read off the child's output, never the model judging itself. A throwing check is
|
|
785
|
-
* fail-closed (not delivered), never a crash.
|
|
786
|
-
*/
|
|
787
|
-
|
|
788
|
-
/**
|
|
789
|
-
* The deployable completion oracle passed to {@link gateOnDeliverable}: a `check` that
|
|
790
|
-
* decides DELIVERED (settles `valid` ⟺ it resolves true) plus an optional `describe` of
|
|
791
|
-
* what the spawn was supposed to produce. The check reads the child's output — never the
|
|
792
|
-
* model judging itself.
|
|
793
|
-
*/
|
|
794
|
-
interface DeliverableSpec<Out = unknown> {
|
|
795
|
-
/** The deployable check that decides DELIVERED. `settled.valid ⟺ this resolves true`. */
|
|
796
|
-
check: (out: Out) => boolean | Promise<boolean>;
|
|
797
|
-
/** What the spawn was supposed to produce — surfaced in traces/reports. */
|
|
798
|
-
describe?: string;
|
|
799
|
-
}
|
|
800
|
-
/**
|
|
801
|
-
* Wrap an `Executor` so its settlement `valid` reflects the deliverable check, not the
|
|
802
|
-
* inner verdict. Handles both `execute` shapes (one-shot `Promise<ExecutorResult>` and
|
|
803
|
-
* streaming `AsyncIterable<UsageEvent>` + `resultArtifact()`); the check runs once the inner
|
|
804
|
-
* executor has produced its output. The inner `score` is preserved; only `valid` is gated.
|
|
805
|
-
*/
|
|
806
|
-
declare function gateOnDeliverable<Out>(inner: Executor<Out>, deliverable: DeliverableSpec<Out>): Executor<Out>;
|
|
807
|
-
|
|
808
766
|
/**
|
|
809
767
|
* @experimental
|
|
810
768
|
*
|
|
@@ -1068,4 +1026,4 @@ interface WorktreeFanoutOptions extends PatchDeliverableOptions {
|
|
|
1068
1026
|
*/
|
|
1069
1027
|
declare function worktreeFanout<Task>(options: WorktreeFanoutOptions): CombinatorShape<Task, WorktreePatchArtifact>;
|
|
1070
1028
|
|
|
1071
|
-
export { type
|
|
1029
|
+
export { type Widen as $, type AuthoredHarness as A, type Panel as B, type CorpusRecord as C, type DefinePersonaInput as D, type EqualKArm as E, type FanoutOptions as F, type PanelJudge as G, type PanelVerdict as H, type PatchDeliverableOptions as I, type PersonaContext as J, type PersonaExecutors as K, type LoopUntilSpec as L, type Pipeline as M, type RenderCorpusToInstructions as N, type Outcome as O, type PanelSpec as P, type RunPersonified as Q, type RenderCorpusToInstructionsOptions as R, type ScopeAnalyzeInput as S, type TrajectoryReportOptions as T, type ShapeBudget as U, type VerifySpec as V, type WinnerStrategy as W, type ShapeContext as X, type TrajectoryNode as Y, type TrajectoryReportFn as Z, type Verify as _, type WorktreeFanoutOptions as a, type WidenDecision as a0, type WidenLineage as a1, type WorktreeCliExecutorOptions as a2, type WorktreeCommandResult as a3, createWorktreeCliExecutor as a4, patchDelivered as a5, worktreeFanout as a6, type WorktreePatchArtifact as b, type Corpus as c, type AssertTraceDerivedFindings as d, type SteerContext as e, type ScopeAnalyst as f, type CombinatorShape as g, type ScopeWidenGate as h, type PipelineStage as i, type FanoutWinnerSelector as j, type WidenSpec as k, type CorpusFilter as l, type Persona as m, type RunPersonifiedOptions as n, type ShapeRegistry as o, type LoopShape as p, type EqualKOnCostOptions as q, type EqualKVerdict as r, type TrajectoryReport as s, type DefinePersona as t, type EqualKOnCost as u, type Fanout as v, type FanoutSynthesis as w, type FlatWidenGate as x, type LoopUntil as y, type LoopUntilState as z };
|