@tangle-network/agent-runtime 0.7.0 → 0.9.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/README.md +42 -13
- package/dist/index.d.ts +235 -35
- package/dist/index.js +282 -3
- package/dist/index.js.map +1 -1
- package/dist/platform.d.ts +197 -0
- package/dist/platform.js +185 -0
- package/dist/platform.js.map +1 -0
- package/package.json +11 -3
- package/docs/domain-agent-runtime-integration-issues.md +0 -165
- package/docs/product-runtime-kernel.md +0 -326
|
@@ -0,0 +1,197 @@
|
|
|
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 integrations hub
|
|
72
|
+
* (`/v1/integrations/*`). Consumer apps use this instead of rolling
|
|
73
|
+
* their own 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
|
+
* Per-request override via `headers` is supported.
|
|
78
|
+
*
|
|
79
|
+
* Endpoint contract: `products/platform/api/src/routes/integrations.ts`.
|
|
80
|
+
*/
|
|
81
|
+
interface PlatformHubClientOptions {
|
|
82
|
+
/** Platform base URL, e.g. `https://id.tangle.tools`. */
|
|
83
|
+
baseUrl: string;
|
|
84
|
+
/** Bearer credential — user API key or service token. */
|
|
85
|
+
bearer: string;
|
|
86
|
+
/** Override fetch (tests + edge runtimes). */
|
|
87
|
+
fetchImpl?: typeof fetch;
|
|
88
|
+
}
|
|
89
|
+
interface PlatformConnection {
|
|
90
|
+
id: string;
|
|
91
|
+
providerId: string;
|
|
92
|
+
connectorId: string;
|
|
93
|
+
status: 'connected' | 'pending' | 'revoked' | 'expired' | string;
|
|
94
|
+
grantedScopes?: string[];
|
|
95
|
+
account?: {
|
|
96
|
+
identity?: string;
|
|
97
|
+
displayName?: string;
|
|
98
|
+
} & Record<string, unknown>;
|
|
99
|
+
metadata?: Record<string, unknown>;
|
|
100
|
+
expiresAt?: string | null;
|
|
101
|
+
createdAt?: string;
|
|
102
|
+
updatedAt?: string;
|
|
103
|
+
}
|
|
104
|
+
interface PlatformCatalogProvider {
|
|
105
|
+
providerId: string;
|
|
106
|
+
displayName?: string;
|
|
107
|
+
description?: string;
|
|
108
|
+
authMode?: string;
|
|
109
|
+
connectors?: PlatformCatalogConnector[];
|
|
110
|
+
[k: string]: unknown;
|
|
111
|
+
}
|
|
112
|
+
interface PlatformCatalogConnector {
|
|
113
|
+
connectorId: string;
|
|
114
|
+
displayName?: string;
|
|
115
|
+
description?: string;
|
|
116
|
+
scopes?: string[];
|
|
117
|
+
[k: string]: unknown;
|
|
118
|
+
}
|
|
119
|
+
interface StartAuthInput {
|
|
120
|
+
providerId: string;
|
|
121
|
+
connectorId: string;
|
|
122
|
+
/** Where the platform redirects the user back to after OAuth. */
|
|
123
|
+
returnUrl: string;
|
|
124
|
+
requestedScopes?: string[];
|
|
125
|
+
state?: string;
|
|
126
|
+
metadata?: Record<string, unknown>;
|
|
127
|
+
/** Required when the bearer is a service token impersonating a user. */
|
|
128
|
+
ownerUserId?: string;
|
|
129
|
+
}
|
|
130
|
+
interface StartAuthResult {
|
|
131
|
+
authorizationUrl: string;
|
|
132
|
+
state: string;
|
|
133
|
+
}
|
|
134
|
+
interface BundleCapabilityInput {
|
|
135
|
+
manifestId?: string;
|
|
136
|
+
grantIds?: string[];
|
|
137
|
+
subject: {
|
|
138
|
+
type: 'user' | 'team' | 'app';
|
|
139
|
+
id: string;
|
|
140
|
+
};
|
|
141
|
+
ttlMs: number;
|
|
142
|
+
}
|
|
143
|
+
interface BundleCapabilityResult {
|
|
144
|
+
bundle: Record<string, unknown>;
|
|
145
|
+
env: Record<string, string>;
|
|
146
|
+
}
|
|
147
|
+
interface HealthCheck {
|
|
148
|
+
connectionId: string;
|
|
149
|
+
providerId: string;
|
|
150
|
+
connectorId: string;
|
|
151
|
+
status: 'ok' | 'degraded' | 'failing' | 'unknown' | string;
|
|
152
|
+
checks?: Record<string, unknown>;
|
|
153
|
+
checkedAt?: string;
|
|
154
|
+
}
|
|
155
|
+
declare class PlatformHubError extends Error {
|
|
156
|
+
readonly status: number;
|
|
157
|
+
readonly code: string | undefined;
|
|
158
|
+
readonly body: unknown;
|
|
159
|
+
constructor(message: string, status: number, code: string | undefined, body: unknown);
|
|
160
|
+
}
|
|
161
|
+
declare class PlatformHubClient {
|
|
162
|
+
private readonly baseUrl;
|
|
163
|
+
private readonly bearer;
|
|
164
|
+
private readonly fetchImpl;
|
|
165
|
+
constructor(options: PlatformHubClientOptions);
|
|
166
|
+
/** List the integration catalog (providers + connectors). */
|
|
167
|
+
catalog(): Promise<{
|
|
168
|
+
providers: PlatformCatalogProvider[];
|
|
169
|
+
} & Record<string, unknown>>;
|
|
170
|
+
/** List the calling user's integration connections. */
|
|
171
|
+
listConnections(): Promise<PlatformConnection[]>;
|
|
172
|
+
/** Revoke (and disable) a connection by id. */
|
|
173
|
+
revokeConnection(connectionId: string): Promise<{
|
|
174
|
+
connection: PlatformConnection;
|
|
175
|
+
revokedGrants: unknown[];
|
|
176
|
+
providerRevocation: {
|
|
177
|
+
ok: boolean;
|
|
178
|
+
};
|
|
179
|
+
}>;
|
|
180
|
+
/** Begin OAuth — returns the URL to send the user to. */
|
|
181
|
+
startAuth(input: StartAuthInput): Promise<StartAuthResult>;
|
|
182
|
+
/** List connection healthchecks (last known state). */
|
|
183
|
+
listHealthchecks(): Promise<HealthCheck[]>;
|
|
184
|
+
/** Trigger a fresh healthcheck pass. */
|
|
185
|
+
runHealthchecks(): Promise<{
|
|
186
|
+
scheduled: number;
|
|
187
|
+
}>;
|
|
188
|
+
/**
|
|
189
|
+
* Mint a sandbox-injectable capability bundle (env vars + scoped
|
|
190
|
+
* capability tokens) so a sandbox can invoke integrations on the
|
|
191
|
+
* user's behalf without seeing the underlying provider tokens.
|
|
192
|
+
*/
|
|
193
|
+
bundleCapabilities(input: BundleCapabilityInput): Promise<BundleCapabilityResult>;
|
|
194
|
+
private request;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export { type AuthorizeUrlOptions, type BundleCapabilityInput, type BundleCapabilityResult, type ExchangeCodeResult, type HealthCheck, PlatformAuthClient, type PlatformAuthClientOptions, PlatformAuthError, type PlatformCatalogConnector, type PlatformCatalogProvider, type PlatformConnection, PlatformHubClient, type PlatformHubClientOptions, PlatformHubError, type StartAuthInput, type StartAuthResult };
|
package/dist/platform.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// src/platform/auth.ts
|
|
2
|
+
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;
|
|
11
|
+
};
|
|
12
|
+
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 ?? fetch;
|
|
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
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// src/platform/integrations.ts
|
|
70
|
+
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;
|
|
81
|
+
};
|
|
82
|
+
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 ?? fetch;
|
|
92
|
+
}
|
|
93
|
+
/** List the integration catalog (providers + connectors). */
|
|
94
|
+
catalog() {
|
|
95
|
+
return this.request("GET", "/v1/integrations/catalog");
|
|
96
|
+
}
|
|
97
|
+
/** List the calling user's integration connections. */
|
|
98
|
+
async listConnections() {
|
|
99
|
+
const data = await this.request(
|
|
100
|
+
"GET",
|
|
101
|
+
"/v1/integrations/connections"
|
|
102
|
+
);
|
|
103
|
+
return data.connections;
|
|
104
|
+
}
|
|
105
|
+
/** Revoke (and disable) a connection by id. */
|
|
106
|
+
revokeConnection(connectionId) {
|
|
107
|
+
return this.request(
|
|
108
|
+
"DELETE",
|
|
109
|
+
`/v1/integrations/connections/${encodeURIComponent(connectionId)}`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
/** Begin OAuth — returns the URL to send the user to. */
|
|
113
|
+
startAuth(input) {
|
|
114
|
+
return this.request("POST", "/v1/integrations/auth/start", input);
|
|
115
|
+
}
|
|
116
|
+
/** List connection healthchecks (last known state). */
|
|
117
|
+
async listHealthchecks() {
|
|
118
|
+
const data = await this.request(
|
|
119
|
+
"GET",
|
|
120
|
+
"/v1/integrations/healthchecks"
|
|
121
|
+
);
|
|
122
|
+
return data.healthchecks;
|
|
123
|
+
}
|
|
124
|
+
/** Trigger a fresh healthcheck pass. */
|
|
125
|
+
runHealthchecks() {
|
|
126
|
+
return this.request("POST", "/v1/integrations/healthchecks/run", {});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Mint a sandbox-injectable capability bundle (env vars + scoped
|
|
130
|
+
* capability tokens) so a sandbox can invoke integrations on the
|
|
131
|
+
* user's behalf without seeing the underlying provider tokens.
|
|
132
|
+
*/
|
|
133
|
+
bundleCapabilities(input) {
|
|
134
|
+
return this.request("POST", "/v1/integrations/capabilities/bundle", input);
|
|
135
|
+
}
|
|
136
|
+
async request(method, path, body) {
|
|
137
|
+
const headers = {
|
|
138
|
+
authorization: `Bearer ${this.bearer}`,
|
|
139
|
+
accept: "application/json"
|
|
140
|
+
};
|
|
141
|
+
if (body !== void 0) headers["content-type"] = "application/json";
|
|
142
|
+
const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
143
|
+
method,
|
|
144
|
+
headers,
|
|
145
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
146
|
+
});
|
|
147
|
+
const text = await res.text();
|
|
148
|
+
let parsed = null;
|
|
149
|
+
if (text) {
|
|
150
|
+
try {
|
|
151
|
+
parsed = JSON.parse(text);
|
|
152
|
+
} catch {
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (!res.ok || parsed && parsed.success === false) {
|
|
156
|
+
const code = parsed?.error && typeof parsed.error === "object" ? parsed.error.code : void 0;
|
|
157
|
+
const message = parsed?.error && typeof parsed.error === "object" && parsed.error.message || (typeof parsed?.error === "string" ? parsed.error : `Platform hub error (${res.status})`);
|
|
158
|
+
throw new PlatformHubError(message, res.status, code, parsed ?? text);
|
|
159
|
+
}
|
|
160
|
+
if (!parsed) {
|
|
161
|
+
throw new PlatformHubError(
|
|
162
|
+
`Platform hub returned non-JSON success (${res.status})`,
|
|
163
|
+
res.status,
|
|
164
|
+
void 0,
|
|
165
|
+
text
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
if (parsed.data === void 0) {
|
|
169
|
+
throw new PlatformHubError(
|
|
170
|
+
"Platform hub envelope missing `data`",
|
|
171
|
+
res.status,
|
|
172
|
+
void 0,
|
|
173
|
+
parsed
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
return parsed.data;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
export {
|
|
180
|
+
PlatformAuthClient,
|
|
181
|
+
PlatformAuthError,
|
|
182
|
+
PlatformHubClient,
|
|
183
|
+
PlatformHubError
|
|
184
|
+
};
|
|
185
|
+
//# 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 = options.fetchImpl ?? fetch\n }\n\n /**\n * Build the URL the user is redirected to in order to start SSO.\n * The platform redirects back to one of `appId`'s registered\n * `redirectUris` with `?code=...&app=...&state=...`.\n */\n authorizeUrl(options: AuthorizeUrlOptions): string {\n if (!options.state) {\n throw new Error('PlatformAuthClient.authorizeUrl: state is required for CSRF')\n }\n const url = new URL('/cross-site/authorize', this.baseUrl)\n url.searchParams.set('app', this.appId)\n url.searchParams.set('state', options.state)\n if (options.redirectUri) url.searchParams.set('redirect', options.redirectUri)\n if (options.prompt) url.searchParams.set('prompt', options.prompt)\n if (options.email) url.searchParams.set('email', options.email)\n return url.toString()\n }\n\n /**\n * Exchange a single-use auth code (delivered to the consumer's\n * callback by the platform) for an API key + the user's identity.\n * Codes are single-use and expire ~5 minutes after issue.\n */\n async exchange(code: string): Promise<ExchangeCodeResult> {\n if (!code) throw new Error('PlatformAuthClient.exchange: code is required')\n const res = await this.fetchImpl(`${this.baseUrl}/cross-site/exchange`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ code, app: this.appId }),\n })\n const body = await res.json().catch(() => null)\n if (!res.ok) {\n const message =\n body && typeof body === 'object' && 'error' in body && typeof body.error === 'string'\n ? body.error\n : `Platform exchange failed (${res.status})`\n throw new PlatformAuthError(message, res.status, body)\n }\n const result = body as Partial<ExchangeCodeResult>\n if (!result.apiKey || !result.user?.id) {\n throw new PlatformAuthError(\n 'Platform exchange response is missing apiKey or user',\n res.status,\n body,\n )\n }\n return result as ExchangeCodeResult\n }\n}\n","/**\n * Server-side client for the Tangle platform's integrations hub\n * (`/v1/integrations/*`). Consumer apps use this instead of rolling\n * their own OAuth + connection tables.\n *\n * Auth: the caller supplies a bearer (either the user's API key from\n * cross-site exchange, or a platform service token) on construction.\n * Per-request override via `headers` is supported.\n *\n * Endpoint contract: `products/platform/api/src/routes/integrations.ts`.\n */\n\nexport interface PlatformHubClientOptions {\n /** Platform base URL, e.g. `https://id.tangle.tools`. */\n baseUrl: string\n /** Bearer credential — user API key or service token. */\n bearer: string\n /** Override fetch (tests + edge runtimes). */\n fetchImpl?: typeof fetch\n}\n\nexport interface PlatformConnection {\n id: string\n providerId: string\n connectorId: string\n status: 'connected' | 'pending' | 'revoked' | 'expired' | string\n grantedScopes?: string[]\n account?: { identity?: string; displayName?: string } & Record<string, unknown>\n metadata?: Record<string, unknown>\n expiresAt?: string | null\n createdAt?: string\n updatedAt?: string\n}\n\nexport interface PlatformCatalogProvider {\n providerId: string\n displayName?: string\n description?: string\n authMode?: string\n connectors?: PlatformCatalogConnector[]\n [k: string]: unknown\n}\n\nexport interface PlatformCatalogConnector {\n connectorId: string\n displayName?: string\n description?: string\n scopes?: string[]\n [k: string]: unknown\n}\n\nexport interface StartAuthInput {\n providerId: string\n connectorId: string\n /** Where the platform redirects the user back to after OAuth. */\n returnUrl: string\n requestedScopes?: string[]\n state?: string\n metadata?: Record<string, unknown>\n /** Required when the bearer is a service token impersonating a user. */\n ownerUserId?: string\n}\n\nexport interface StartAuthResult {\n authorizationUrl: string\n state: string\n}\n\nexport interface BundleCapabilityInput {\n manifestId?: string\n grantIds?: string[]\n subject: { type: 'user' | 'team' | 'app'; id: string }\n ttlMs: number\n}\n\nexport interface BundleCapabilityResult {\n bundle: Record<string, unknown>\n env: Record<string, string>\n}\n\nexport interface HealthCheck {\n connectionId: string\n providerId: string\n connectorId: string\n status: 'ok' | 'degraded' | 'failing' | 'unknown' | string\n checks?: Record<string, unknown>\n checkedAt?: string\n}\n\nexport class PlatformHubError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly code: string | undefined,\n public readonly body: unknown,\n ) {\n super(message)\n this.name = 'PlatformHubError'\n }\n}\n\ninterface PlatformEnvelope<T> {\n success: boolean\n data?: T\n error?: { code?: string; message?: string } | string\n}\n\nexport class PlatformHubClient {\n private readonly baseUrl: string\n private readonly bearer: string\n private readonly fetchImpl: typeof fetch\n\n constructor(options: PlatformHubClientOptions) {\n if (!options.baseUrl) throw new Error('PlatformHubClient: baseUrl is required')\n if (!options.bearer) throw new Error('PlatformHubClient: bearer is required')\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '')\n this.bearer = options.bearer\n this.fetchImpl = options.fetchImpl ?? fetch\n }\n\n /** List the integration catalog (providers + connectors). */\n catalog(): Promise<{ providers: PlatformCatalogProvider[] } & Record<string, unknown>> {\n return this.request('GET', '/v1/integrations/catalog')\n }\n\n /** List the calling user's integration connections. */\n async listConnections(): Promise<PlatformConnection[]> {\n const data = await this.request<{ connections: PlatformConnection[] }>(\n 'GET',\n '/v1/integrations/connections',\n )\n return data.connections\n }\n\n /** Revoke (and disable) a connection by id. */\n revokeConnection(connectionId: string): Promise<{\n connection: PlatformConnection\n revokedGrants: unknown[]\n providerRevocation: { ok: boolean }\n }> {\n return this.request(\n 'DELETE',\n `/v1/integrations/connections/${encodeURIComponent(connectionId)}`,\n )\n }\n\n /** Begin OAuth — returns the URL to send the user to. */\n startAuth(input: StartAuthInput): Promise<StartAuthResult> {\n return this.request('POST', '/v1/integrations/auth/start', input)\n }\n\n /** List connection healthchecks (last known state). */\n async listHealthchecks(): Promise<HealthCheck[]> {\n const data = await this.request<{ healthchecks: HealthCheck[] }>(\n 'GET',\n '/v1/integrations/healthchecks',\n )\n return data.healthchecks\n }\n\n /** Trigger a fresh healthcheck pass. */\n runHealthchecks(): Promise<{ scheduled: number }> {\n return this.request('POST', '/v1/integrations/healthchecks/run', {})\n }\n\n /**\n * Mint a sandbox-injectable capability bundle (env vars + scoped\n * capability tokens) so a sandbox can invoke integrations on the\n * user's behalf without seeing the underlying provider tokens.\n */\n bundleCapabilities(input: BundleCapabilityInput): Promise<BundleCapabilityResult> {\n return this.request('POST', '/v1/integrations/capabilities/bundle', input)\n }\n\n private async request<T>(\n method: 'GET' | 'POST' | 'DELETE' | 'PUT',\n path: string,\n body?: unknown,\n ): Promise<T> {\n const headers: Record<string, string> = {\n authorization: `Bearer ${this.bearer}`,\n accept: 'application/json',\n }\n if (body !== undefined) headers['content-type'] = 'application/json'\n\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n })\n const text = await res.text()\n let parsed: PlatformEnvelope<T> | null = null\n if (text) {\n try {\n parsed = JSON.parse(text)\n } catch {\n // fall through to error handling below\n }\n }\n if (!res.ok || (parsed && parsed.success === false)) {\n const code = parsed?.error && typeof parsed.error === 'object' ? parsed.error.code : undefined\n const message =\n (parsed?.error && typeof parsed.error === 'object' && parsed.error.message) ||\n (typeof parsed?.error === 'string' ? parsed.error : `Platform hub error (${res.status})`)\n throw new PlatformHubError(message, res.status, code, parsed ?? text)\n }\n if (!parsed) {\n throw new PlatformHubError(\n `Platform hub returned non-JSON success (${res.status})`,\n res.status,\n undefined,\n text,\n )\n }\n if (parsed.data === undefined) {\n throw new PlatformHubError(\n 'Platform hub envelope missing `data`',\n res.status,\n undefined,\n parsed,\n )\n }\n return parsed.data\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Reusable runtime lifecycle for domain-specific agents.",
|
|
5
5
|
"homepage": "https://github.com/tangle-network/agent-runtime#readme",
|
|
6
6
|
"repository": {
|
|
@@ -18,12 +18,16 @@
|
|
|
18
18
|
"types": "./dist/index.d.ts",
|
|
19
19
|
"import": "./dist/index.js",
|
|
20
20
|
"default": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./platform": {
|
|
23
|
+
"types": "./dist/platform.d.ts",
|
|
24
|
+
"import": "./dist/platform.js",
|
|
25
|
+
"default": "./dist/platform.js"
|
|
21
26
|
}
|
|
22
27
|
},
|
|
23
28
|
"files": [
|
|
24
29
|
"dist",
|
|
25
|
-
"README.md"
|
|
26
|
-
"docs"
|
|
30
|
+
"README.md"
|
|
27
31
|
],
|
|
28
32
|
"publishConfig": {
|
|
29
33
|
"access": "public"
|
|
@@ -33,6 +37,7 @@
|
|
|
33
37
|
},
|
|
34
38
|
"devDependencies": {
|
|
35
39
|
"@biomejs/biome": "^2.4.0",
|
|
40
|
+
"@tangle-network/sandbox": "0.1.2",
|
|
36
41
|
"@types/node": "^25.6.0",
|
|
37
42
|
"tsup": "^8.0.0",
|
|
38
43
|
"typescript": "^5.7.0",
|
|
@@ -42,6 +47,9 @@
|
|
|
42
47
|
"node": ">=20"
|
|
43
48
|
},
|
|
44
49
|
"license": "MIT",
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"@tangle-network/sandbox": "0.1.2"
|
|
52
|
+
},
|
|
45
53
|
"scripts": {
|
|
46
54
|
"build": "tsup",
|
|
47
55
|
"dev": "tsup --watch",
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
# Domain Agent Runtime Integration Issues
|
|
2
|
-
|
|
3
|
-
GitHub issue creation was blocked in this environment: the GitHub connector returns 404 for the private repos and `gh` is not authenticated. These are the issue drafts to open once repository credentials are available.
|
|
4
|
-
|
|
5
|
-
## tax-agent
|
|
6
|
-
|
|
7
|
-
Title: Integrate tax evals with agent-runtime knowledge readiness
|
|
8
|
-
|
|
9
|
-
`@tangle-network/agent-runtime@0.2.0` provides the shared task harness for domain agents: `runAgentTask`, typed runtime events, `KnowledgeRequirement`, readiness scoring, question/acquisition preflight hooks, and integration with `@tangle-network/agent-eval@0.20.0`.
|
|
10
|
-
|
|
11
|
-
First local implementation:
|
|
12
|
-
|
|
13
|
-
- Bump root `@tangle-network/agent-eval` to `0.20.0`.
|
|
14
|
-
- Add root `@tangle-network/agent-runtime` `^0.2.0`.
|
|
15
|
-
- Bump `server` `@tangle-network/agent-eval` to `0.20.0`.
|
|
16
|
-
- Add `tests/eval/lib/agent-runtime.ts` with `buildTaxKnowledgeRequirements()` and `runTaxAgentTask()`.
|
|
17
|
-
- Add `tests/eval/lib/agent-runtime.test.ts` covering missing-context blocking and ready-context execution.
|
|
18
|
-
|
|
19
|
-
Remaining changes:
|
|
20
|
-
|
|
21
|
-
- Wire the runtime helper into `tests/eval/lib/deterministic-tax-workflow-runner.ts`, `tests/eval/harness/run-product-eval.ts`, `tests/eval/harness/run-workspace-eval.ts`, `tests/eval/optimize.ts`, `tests/eval/lib/agent-eval-runtime.ts`, and `tests/eval/lib/trace-sync.ts`.
|
|
22
|
-
- Canonicalize tax requirements for taxpayer facts, filing year, jurisdiction, source documents, workflow tools, entity classification, elections, accounting method, book/tax reconciliation, payroll, withholding, estimated payments, credits, nexus, apportionment, OCR confidence, current authority, and user-confirmed assumptions.
|
|
23
|
-
- Persist runtime events into traces: `task_start`, `readiness_start/end`, `questions_start/end`, `acquisition_start/end`, `control_start/end`, and `task_end`.
|
|
24
|
-
- Report readiness score, blocking gaps, acquisition mode, evidence IDs, blocked-before-execution status, and optimizer responsible surface.
|
|
25
|
-
- Classify missing documents, missing jurisdiction, stale authority, bad retrieval, insufficient evidence, contradictory evidence, missing credentials, and ambiguous taxpayer intent as knowledge failures rather than prompt failures.
|
|
26
|
-
- Feed gaps into multi-shot optimization as `knowledge-requirements`, `data-acquisition`, `retrieval-policy`, or `user-question-policy`.
|
|
27
|
-
- Add tests for missing taxpayer facts, missing documents, missing jurisdiction, stale authority, and fully ready execution.
|
|
28
|
-
|
|
29
|
-
## legal-agent
|
|
30
|
-
|
|
31
|
-
Title: Integrate legal evals with agent-runtime knowledge readiness
|
|
32
|
-
|
|
33
|
-
First local implementation:
|
|
34
|
-
|
|
35
|
-
- Bump `@tangle-network/agent-eval` dev dependency to `^0.20.0`.
|
|
36
|
-
- Add `@tangle-network/agent-runtime` dev dependency `^0.2.0`.
|
|
37
|
-
- Add `tests/eval/lib/agent-runtime.ts` with `buildLegalKnowledgeRequirements()` and `runLegalAgentTask()`.
|
|
38
|
-
- Add `tests/eval/lib/agent-runtime.test.ts` covering missing matter context and ready execution.
|
|
39
|
-
|
|
40
|
-
Remaining changes:
|
|
41
|
-
|
|
42
|
-
- Wire `runLegalAgentTask()` into `tests/eval/harness/run-product-eval.ts`, `tests/eval/harness/run-dual-agent-eval.ts`, `tests/eval/optimize.ts`, `tests/eval/lib/agent-eval-runtime.ts`, and `tests/eval/lib/trace-sync.ts`.
|
|
43
|
-
- Canonicalize legal requirements for matter facts, parties, dates, jurisdiction, forum, venue, governing law, current authority, uploaded matter documents, knowledge-base search, client credentials, regulated industry constraints, deadlines, and user-approved assumptions.
|
|
44
|
-
- Enforce knowledge-base retrieval before drafting or review, with retrieval evidence saved into the runtime bundle.
|
|
45
|
-
- Persist runtime readiness metadata and events into trace sync and eval reports.
|
|
46
|
-
- Classify missing facts, missing authority, stale law, bad retrieval, insufficient evidence, contradictory authority, missing credentials, and ambiguous user intent as knowledge failures.
|
|
47
|
-
- Extend optimization ASI rows so legal reports recommend data acquisition or authority refresh before prompt rewrites.
|
|
48
|
-
- Add tests for missing jurisdiction, stale authority, missing knowledge-base results, contradictory authority, and ready document review.
|
|
49
|
-
|
|
50
|
-
## gtm-agent
|
|
51
|
-
|
|
52
|
-
Title: Integrate GTM evals with agent-runtime knowledge readiness
|
|
53
|
-
|
|
54
|
-
First local implementation:
|
|
55
|
-
|
|
56
|
-
- Bump `@tangle-network/agent-eval` to `0.20.0`.
|
|
57
|
-
- Add `@tangle-network/agent-runtime` `^0.2.0`.
|
|
58
|
-
- Add `eval/agent-runtime.ts` with `buildGtmKnowledgeRequirements()` and `runGtmAgentTask()`.
|
|
59
|
-
- Add `tests/agent-runtime.test.ts` covering missing company/connector context and ready execution.
|
|
60
|
-
|
|
61
|
-
Remaining changes:
|
|
62
|
-
|
|
63
|
-
- Wire `runGtmAgentTask()` into `eval/business-owner/live-flow.ts`, `eval/discover-brief/run.ts`, `eval/run.ts`, `eval/agent-eval-traces.ts`, and optimizer flows.
|
|
64
|
-
- Canonicalize GTM requirements for company profile, product/offer, ICP/personas, channel history, CRM state, campaign history, analytics, performance metrics, positioning, competitors, integrations, credentials, and workspace vault knowledge.
|
|
65
|
-
- Turn `knowledge/wiki/company.md`, `products.md`, `channels.md`, and `open-questions.md` into runtime evidence inputs.
|
|
66
|
-
- Persist readiness events into existing trace helpers and reports.
|
|
67
|
-
- Classify missing company data, missing market data, stale metrics, missing credentials, bad connector retrieval, insufficient evidence, contradictory positioning, and ambiguous business-owner intent as knowledge failures.
|
|
68
|
-
- Feed knowledge gaps into optimization as data-acquisition/retrieval-policy/user-question-policy issues.
|
|
69
|
-
- Add tests for missing ICP, missing product context, missing connectors, stale metrics, and ready discover-brief execution.
|
|
70
|
-
|
|
71
|
-
## creative-agent
|
|
72
|
-
|
|
73
|
-
Title: Integrate creative evals with agent-runtime knowledge readiness
|
|
74
|
-
|
|
75
|
-
First local implementation:
|
|
76
|
-
|
|
77
|
-
- Bump `@tangle-network/agent-eval` to `^0.20.0`.
|
|
78
|
-
- Add `@tangle-network/agent-runtime` `^0.2.0`.
|
|
79
|
-
- Add `eval/control/agent-runtime.ts` with `buildCreativeKnowledgeRequirements()` and `runCreativeAgentTask()`.
|
|
80
|
-
- Add `tests/agent-runtime.test.ts` covering missing creative intent/rights and ready execution.
|
|
81
|
-
|
|
82
|
-
Remaining changes:
|
|
83
|
-
|
|
84
|
-
- Wire `runCreativeAgentTask()` into `eval/control/creative-onboarding.ts`, `eval/control/creative-workflow-optimization.ts`, `eval/control/creative-multishot-optimization.ts`, `eval/e2e/creative-product-harness.ts`, and trace/report code.
|
|
85
|
-
- Canonicalize creative requirements for intent, audience, taste thesis, references, dislikes, brand system, source rights, generated asset policy, deliverable specs, channel constraints, localization, approval policy, feedback source, and revision budget.
|
|
86
|
-
- Convert onboarding answers and approval feedback into runtime evidence and reusable knowledge requirements.
|
|
87
|
-
- Persist readiness events in control/e2e traces and reports.
|
|
88
|
-
- Classify missing creative intent, missing taste signal, missing brand assets, missing rights, stale source policy, bad asset retrieval, insufficient evidence, contradictory feedback, and ambiguous user intent as knowledge failures.
|
|
89
|
-
- Feed approval/readiness gaps into multi-shot optimization as data or policy surfaces before prompt changes.
|
|
90
|
-
- Add tests for missing intent, missing rights, missing approval policy, contradictory feedback, and ready workflow execution.
|
|
91
|
-
|
|
92
|
-
## blueprint-agent
|
|
93
|
-
|
|
94
|
-
Title: Integrate Blueprint benchmarks with agent-runtime knowledge readiness
|
|
95
|
-
|
|
96
|
-
No implementation was requested for this pass. The repo should adopt the runtime boundary before deeper report polish so benchmark failures separate missing task-world knowledge from coding-agent failures.
|
|
97
|
-
|
|
98
|
-
Remaining changes:
|
|
99
|
-
|
|
100
|
-
- Add `@tangle-network/agent-runtime` to the workspace package(s) that own benchmark execution.
|
|
101
|
-
- Keep existing benchmark database/report terms stable if they still say `vertical`; map to runtime `domain` metadata instead of forcing a broad rename.
|
|
102
|
-
- Define Blueprint requirements for task brief, repo/source checkout, package manager, framework/language, build command, test command, sandbox availability, runtime environment, credentials/secrets, Tangle Blueprint SDK docs, template/plugin docs, deploy target, and benchmark scoring contract.
|
|
103
|
-
- Wrap the benchmark product path with `runAgentTask` so readiness is scored before agent execution.
|
|
104
|
-
- Persist runtime events into agent-eval traces and `bench-report`.
|
|
105
|
-
- Add readiness sections to markdown/HTML/JSON reports: requirement table, missing evidence, acquisition plan, blocked-before-execution runs, and readiness deltas by run/version.
|
|
106
|
-
- Map failures to `knowledge_readiness_blocked`, `missing_codebase_context`, `missing_runtime_context`, `missing_credentials`, `stale_external_data`, `bad_retrieval`, `insufficient_evidence`, `contradictory_evidence`, `reasoning_error`, `tool_selection_error`, `sandbox_failure`, and `budget_exceeded`.
|
|
107
|
-
- Extend holdout/promotion gates so a prompt/topology change is not promoted when observed gain is actually due to different context acquisition.
|
|
108
|
-
- Add tests for missing build command, missing SDK docs, missing sandbox, stale template docs, and fully ready benchmark execution.
|
|
109
|
-
|
|
110
|
-
## agent-builder
|
|
111
|
-
|
|
112
|
-
Title: Integrate agent-builder with agent-runtime knowledge readiness
|
|
113
|
-
|
|
114
|
-
`agent-builder` is the meta-platform for creating, testing, deploying, researching, and monetizing domain-specific agents. It already has the strongest production loop among the app repos: Forge builder sims, per-agent scenarios, feedback trajectories, canaries, auto-research, multi-shot optimization, KB optimization, version history, sandbox execution, marketplace publishing, and Playwright-to-agent-eval reporting.
|
|
115
|
-
|
|
116
|
-
The missing boundary is that generated agents and Forge runs do not yet have a first-class `agent-runtime` preflight. Failures caused by missing build spec context, missing user/business/domain data, unavailable integrations, missing secrets, stale KB evidence, sandbox/runtime gaps, or bad retrieval can still be absorbed as prompt/config failures.
|
|
117
|
-
|
|
118
|
-
Package updates:
|
|
119
|
-
|
|
120
|
-
- Upgrade `@tangle-network/agent-eval` from `^0.19.1` to `^0.20.0`.
|
|
121
|
-
- Upgrade `@tangle-network/agent-knowledge` from `^1.0.0` to `^1.1.0`.
|
|
122
|
-
- Add `@tangle-network/agent-runtime` `^0.2.0`.
|
|
123
|
-
|
|
124
|
-
Required changes:
|
|
125
|
-
|
|
126
|
-
- Add a server-side runtime module: `src/lib/.server/runtime/agent-builder-runtime.ts`, `src/lib/.server/runtime/requirements.ts`, and `src/lib/.server/runtime/events.ts`.
|
|
127
|
-
- Expose helpers: `buildForgeKnowledgeRequirements(input)`, `buildPublishedAgentKnowledgeRequirements(input)`, `runForgeAgentTask(input)`, `runPublishedAgentTask(input)`, and `runtimeEventsToTraceMetadata(events)`.
|
|
128
|
-
- Define Forge build requirements for creator intent, target user, domain/category, BuildSpec completeness and approval, expected artifact, success criteria, tools, integrations, APIs, credentials, secrets, sandbox availability, runtime image, repository/scaffold structure, generated agent config, pricing/marketplace/governance constraints, and user-approved assumptions.
|
|
129
|
-
- Define generated-agent requirements for domain-specific user facts, company/business/product context, regulatory freshness, connected integrations, secrets, vault/knowledge pages, source freshness, scenario fixtures, and fallback policy.
|
|
130
|
-
- Persist generated-agent runtime metadata with agent config/version metadata so forks and marketplace consumers inherit the right contract.
|
|
131
|
-
- Wire `runAgentTask` into Forge builder sims: `src/lib/.server/eval/forge-builder-sim.ts`, `src/routes/api.agents.eval.builder-sim.ts`, and `src/routes/api.admin.builder-sim.run.ts`.
|
|
132
|
-
- Wire scenario and eval runs through runtime: `src/routes/api.agents.$agentId.scenarios.run.ts`, `src/routes/api.agents.$agentId.eval.simulate.ts`, `src/routes/api.agents.$agentId.eval.refine.ts`, and `src/routes/api.agents.$agentId.eval.ts`.
|
|
133
|
-
- Add readiness checks or metadata to production chat/sandbox chat: `src/routes/api.agents.$agentId.chat.ts`, `src/routes/api.agents.$agentId.sandbox.chat.ts`, and `src/routes/api.v1.agents.$slug.chat.completions.ts`.
|
|
134
|
-
- Bridge `agent-knowledge@1.1.0` readiness with `src/routes/api.agents.$agentId.knowledge.index.ts`, `src/routes/api.agents.$agentId.knowledge.search.ts`, `src/routes/api.agents.$agentId.knowledge.discover.ts`, `src/routes/api.agents.$agentId.knowledge.write-blocks.ts`, and `src/lib/.server/kb/optimization.ts`.
|
|
135
|
-
- Persist runtime events into trace/report surfaces: `src/lib/.server/eval/trace-store-d1.ts`, `src/lib/.server/eval/session.ts`, `src/lib/.server/eval/run-record-store.ts`, `src/lib/.server/eval/run-record-fields.ts`, and `e2e/reporters/agent-eval-reporter.ts`.
|
|
136
|
-
- Preserve `task_start`, `readiness_start/end`, `questions_start/end`, `acquisition_start/end`, `control_start/end`, and `task_end`.
|
|
137
|
-
- Report readiness score, blocking gaps, acquisition mode, evidence IDs, user questions, runtime status, and blocked-before-execution status.
|
|
138
|
-
- Map failures to `knowledge_readiness_blocked`, `missing_user_data`, `missing_domain_data`, `missing_codebase_context`, `missing_runtime_context`, `missing_credentials`, `stale_external_data`, `bad_retrieval`, `insufficient_evidence`, `contradictory_evidence`, and `ambiguous_user_intent`.
|
|
139
|
-
- Update `src/lib/.server/eval/failure-inspector.ts`, `src/lib/.server/eval/multi-shot-adapter.ts`, `src/lib/.server/eval/heuristic-researcher.ts`, `src/lib/.server/eval/auto-research-runner.ts`, and `src/lib/.server/eval/canary-cron.ts`.
|
|
140
|
-
- Extend ASI responsible surfaces beyond `agent.config.systemPrompt`: `knowledge-requirements`, `data-acquisition`, `retrieval-policy`, `user-question-policy`, `runtime-environment`, `integration-policy`, `sandbox-policy`, and `agent.config.systemPrompt`.
|
|
141
|
-
- Ensure auto-research does not mutate prompts when the dominant failure is missing KB pages, missing BuildSpec fields, missing secrets, unavailable sandbox, or stale evidence.
|
|
142
|
-
- Persist runtime contracts across versions, publish, and forks: `src/lib/.server/versions.ts`, `src/routes/api.agents.$agentId.versions.ts`, `src/routes/api.agents.$agentId.versions.$versionId.revert.ts`, `src/routes/api.agents.$agentId.fork.ts`, `src/routes/api.agents.$agentId.fork.apply-update.ts`, and `src/routes/api.agents.$agentId.publish.ts`.
|
|
143
|
-
- Add workbench/admin UI visibility for readiness on eval pages, research cycle pages, knowledge pages, chat/workbench blockers, and marketplace/published agent caveats. Do not expose private/secret requirement details to public consumers.
|
|
144
|
-
|
|
145
|
-
Tests:
|
|
146
|
-
|
|
147
|
-
- Forge sim blocks when BuildSpec or intent is incomplete.
|
|
148
|
-
- Forge sim blocks or asks when required integration credentials are missing.
|
|
149
|
-
- Scenario run records readiness metadata.
|
|
150
|
-
- KB optimization reports no pages / too few labels as knowledge readiness failures.
|
|
151
|
-
- Multi-shot ASI points to data-acquisition/retrieval-policy instead of `agent.config.systemPrompt` for missing knowledge.
|
|
152
|
-
- Fork preserves runtime contract.
|
|
153
|
-
- Public chat hides private/secret requirement details.
|
|
154
|
-
- E2E reporter can include runtime readiness metadata.
|
|
155
|
-
|
|
156
|
-
Acceptance criteria:
|
|
157
|
-
|
|
158
|
-
- `agent-builder` depends on `agent-runtime@^0.2.0`, `agent-eval@^0.20.0`, and `agent-knowledge@^1.1.0`.
|
|
159
|
-
- Forge builder sims run through `runAgentTask` or a thin typed wrapper.
|
|
160
|
-
- Per-agent scenario/eval runs attach `KnowledgeReadinessReport` before execution.
|
|
161
|
-
- KB search/optimization feeds readiness into runtime and traces.
|
|
162
|
-
- Missing BuildSpec, missing credentials, missing KB pages, stale evidence, bad retrieval, and sandbox unavailability are classified as knowledge/runtime failures.
|
|
163
|
-
- Multi-shot optimization can recommend acquisition/retrieval/user-question/runtime-policy changes instead of always mutating prompts.
|
|
164
|
-
- Runtime requirements persist across config versions, publish, and fork flows.
|
|
165
|
-
- Workbench/admin reports show readiness score, gaps, acquisition plan, runtime status, and blocked-before-execution runs.
|