@runtypelabs/sdk 4.15.0 → 4.17.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/index.cjs +742 -137
- package/dist/index.d.cts +1294 -34
- package/dist/index.d.ts +1294 -34
- package/dist/index.mjs +730 -137
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -73,9 +73,15 @@ __export(index_exports, {
|
|
|
73
73
|
STEP_TYPE_TO_METHOD: () => STEP_TYPE_TO_METHOD,
|
|
74
74
|
SchedulesEndpoint: () => SchedulesEndpoint,
|
|
75
75
|
SecretsEndpoint: () => SecretsEndpoint,
|
|
76
|
+
SkillDriftError: () => SkillDriftError,
|
|
77
|
+
SkillEnsureConflictError: () => SkillEnsureConflictError,
|
|
76
78
|
SkillProposalsNamespace: () => SkillProposalsNamespace,
|
|
77
79
|
SkillsNamespace: () => SkillsNamespace,
|
|
80
|
+
SurfaceDriftError: () => SurfaceDriftError,
|
|
81
|
+
SurfaceEnsureConflictError: () => SurfaceEnsureConflictError,
|
|
78
82
|
SurfacesEndpoint: () => SurfacesEndpoint,
|
|
83
|
+
SurfacesNamespace: () => SurfacesNamespace,
|
|
84
|
+
ToolApprovalGrantsEndpoint: () => ToolApprovalGrantsEndpoint,
|
|
79
85
|
ToolDriftError: () => ToolDriftError,
|
|
80
86
|
ToolEnsureConflictError: () => ToolEnsureConflictError,
|
|
81
87
|
ToolsEndpoint: () => ToolsEndpoint,
|
|
@@ -92,6 +98,8 @@ __export(index_exports, {
|
|
|
92
98
|
computeAgentContentHash: () => computeAgentContentHash,
|
|
93
99
|
computeFlowContentHash: () => computeFlowContentHash,
|
|
94
100
|
computeProductContentHash: () => computeProductContentHash,
|
|
101
|
+
computeSkillContentHash: () => computeSkillContentHash,
|
|
102
|
+
computeSurfaceContentHash: () => computeSurfaceContentHash,
|
|
95
103
|
computeToolContentHash: () => computeToolContentHash,
|
|
96
104
|
createClient: () => createClient,
|
|
97
105
|
createExternalTool: () => createExternalTool,
|
|
@@ -101,6 +109,8 @@ __export(index_exports, {
|
|
|
101
109
|
defineFlow: () => defineFlow,
|
|
102
110
|
definePlaybook: () => definePlaybook,
|
|
103
111
|
defineProduct: () => defineProduct,
|
|
112
|
+
defineSkill: () => defineSkill,
|
|
113
|
+
defineSurface: () => defineSurface,
|
|
104
114
|
defineTool: () => defineTool,
|
|
105
115
|
deployWorkflow: () => deployWorkflow,
|
|
106
116
|
ensureDefaultWorkflowHooks: () => ensureDefaultWorkflowHooks,
|
|
@@ -118,6 +128,8 @@ __export(index_exports, {
|
|
|
118
128
|
normalizeAgentDefinition: () => normalizeAgentDefinition,
|
|
119
129
|
normalizeCandidatePath: () => normalizeCandidatePath,
|
|
120
130
|
normalizeProductDefinition: () => normalizeProductDefinition,
|
|
131
|
+
normalizeSkillDefinition: () => normalizeSkillDefinition,
|
|
132
|
+
normalizeSurfaceDefinition: () => normalizeSurfaceDefinition,
|
|
121
133
|
normalizeToolDefinition: () => normalizeToolDefinition,
|
|
122
134
|
parseFinalBuffer: () => parseFinalBuffer,
|
|
123
135
|
parseLedgerArtifactRelativePath: () => parseLedgerArtifactRelativePath,
|
|
@@ -1231,20 +1243,20 @@ var FlowBuilder = class {
|
|
|
1231
1243
|
*/
|
|
1232
1244
|
build() {
|
|
1233
1245
|
const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
|
|
1234
|
-
const
|
|
1246
|
+
const request6 = { flow };
|
|
1235
1247
|
if (this.recordConfig) {
|
|
1236
|
-
|
|
1248
|
+
request6.record = this.recordConfig;
|
|
1237
1249
|
}
|
|
1238
1250
|
if (this.messagesConfig) {
|
|
1239
|
-
|
|
1251
|
+
request6.messages = this.messagesConfig;
|
|
1240
1252
|
}
|
|
1241
1253
|
if (this.inputsConfig) {
|
|
1242
|
-
|
|
1254
|
+
request6.inputs = this.inputsConfig;
|
|
1243
1255
|
}
|
|
1244
1256
|
if (Object.keys(this.optionsConfig).length > 0) {
|
|
1245
|
-
|
|
1257
|
+
request6.options = this.optionsConfig;
|
|
1246
1258
|
}
|
|
1247
|
-
return
|
|
1259
|
+
return request6;
|
|
1248
1260
|
}
|
|
1249
1261
|
/**
|
|
1250
1262
|
* Validate this prospective flow against the public validation endpoint
|
|
@@ -2638,15 +2650,15 @@ var RuntypeFlowBuilder = class {
|
|
|
2638
2650
|
build() {
|
|
2639
2651
|
const flowMode = this.mode === "existing" ? "existing" : this.mode;
|
|
2640
2652
|
const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
|
|
2641
|
-
const
|
|
2653
|
+
const request6 = { flow };
|
|
2642
2654
|
if (this.recordConfig) {
|
|
2643
|
-
|
|
2655
|
+
request6.record = this.recordConfig;
|
|
2644
2656
|
}
|
|
2645
2657
|
if (this.messagesConfig) {
|
|
2646
|
-
|
|
2658
|
+
request6.messages = this.messagesConfig;
|
|
2647
2659
|
}
|
|
2648
2660
|
if (this.inputsConfig) {
|
|
2649
|
-
|
|
2661
|
+
request6.inputs = this.inputsConfig;
|
|
2650
2662
|
}
|
|
2651
2663
|
const options = {
|
|
2652
2664
|
flowMode,
|
|
@@ -2664,8 +2676,8 @@ var RuntypeFlowBuilder = class {
|
|
|
2664
2676
|
if (this.mode === "upsert" && Object.keys(this.upsertOptions).length > 0) {
|
|
2665
2677
|
options.upsertOptions = this.upsertOptions;
|
|
2666
2678
|
}
|
|
2667
|
-
|
|
2668
|
-
return
|
|
2679
|
+
request6.options = options;
|
|
2680
|
+
return request6;
|
|
2669
2681
|
}
|
|
2670
2682
|
/**
|
|
2671
2683
|
* Validate this prospective flow against the public validation endpoint
|
|
@@ -3259,6 +3271,192 @@ var PromptsNamespace = class {
|
|
|
3259
3271
|
}
|
|
3260
3272
|
};
|
|
3261
3273
|
|
|
3274
|
+
// src/skills-ensure.ts
|
|
3275
|
+
function isPlainObject2(value) {
|
|
3276
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3277
|
+
}
|
|
3278
|
+
function normalizeValue(value) {
|
|
3279
|
+
if (Array.isArray(value)) {
|
|
3280
|
+
return value.map((item) => normalizeValue(item));
|
|
3281
|
+
}
|
|
3282
|
+
if (isPlainObject2(value)) {
|
|
3283
|
+
const normalized = {};
|
|
3284
|
+
for (const key of Object.keys(value).sort()) {
|
|
3285
|
+
const entry = value[key];
|
|
3286
|
+
if (entry === void 0 || entry === null) continue;
|
|
3287
|
+
normalized[key] = normalizeValue(entry);
|
|
3288
|
+
}
|
|
3289
|
+
return normalized;
|
|
3290
|
+
}
|
|
3291
|
+
return value;
|
|
3292
|
+
}
|
|
3293
|
+
function normalizeSkillDefinition(definition) {
|
|
3294
|
+
const manifest = isPlainObject2(definition.manifest) ? definition.manifest : {};
|
|
3295
|
+
const rawFrontmatter = isPlainObject2(manifest.frontmatter) ? manifest.frontmatter : {};
|
|
3296
|
+
const frontmatterWithoutName = {};
|
|
3297
|
+
for (const key of Object.keys(rawFrontmatter)) {
|
|
3298
|
+
if (key === "name") continue;
|
|
3299
|
+
frontmatterWithoutName[key] = rawFrontmatter[key];
|
|
3300
|
+
}
|
|
3301
|
+
const frontmatter = normalizeValue(frontmatterWithoutName);
|
|
3302
|
+
const runtype = isPlainObject2(manifest.runtype) ? normalizeValue(manifest.runtype) : {};
|
|
3303
|
+
const body = typeof manifest.body === "string" ? manifest.body : "";
|
|
3304
|
+
return { frontmatter, runtype, body };
|
|
3305
|
+
}
|
|
3306
|
+
async function computeSkillContentHash(definition) {
|
|
3307
|
+
const serialized = JSON.stringify(normalizeSkillDefinition(definition));
|
|
3308
|
+
const encoded = new TextEncoder().encode(serialized);
|
|
3309
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
|
|
3310
|
+
return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3311
|
+
}
|
|
3312
|
+
var DEFINE_SKILL_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "manifest"]);
|
|
3313
|
+
function defineSkill(input) {
|
|
3314
|
+
if (!input || typeof input !== "object") {
|
|
3315
|
+
throw new Error("defineSkill requires a definition object");
|
|
3316
|
+
}
|
|
3317
|
+
if (typeof input.name !== "string" || input.name.length === 0) {
|
|
3318
|
+
throw new Error('defineSkill requires a non-empty string "name"');
|
|
3319
|
+
}
|
|
3320
|
+
if (!isPlainObject2(input.manifest)) {
|
|
3321
|
+
throw new Error('defineSkill requires a "manifest" object ({ frontmatter, runtype, body })');
|
|
3322
|
+
}
|
|
3323
|
+
const unknownKeys = Object.keys(input).filter((key) => !DEFINE_SKILL_TOP_LEVEL_KEYS.has(key));
|
|
3324
|
+
if (unknownKeys.length > 0) {
|
|
3325
|
+
throw new Error(
|
|
3326
|
+
`defineSkill: unknown field(s): ${unknownKeys.join(", ")}. Allowed fields are name and manifest.`
|
|
3327
|
+
);
|
|
3328
|
+
}
|
|
3329
|
+
const frontmatter = input.manifest.frontmatter;
|
|
3330
|
+
if (!isPlainObject2(frontmatter) || typeof frontmatter.name !== "string") {
|
|
3331
|
+
throw new Error("defineSkill: manifest.frontmatter.name is required");
|
|
3332
|
+
}
|
|
3333
|
+
if (frontmatter.name !== input.name) {
|
|
3334
|
+
throw new Error(
|
|
3335
|
+
`defineSkill: manifest.frontmatter.name ("${frontmatter.name}") must match the identity name ("${input.name}").`
|
|
3336
|
+
);
|
|
3337
|
+
}
|
|
3338
|
+
return { name: input.name, manifest: input.manifest };
|
|
3339
|
+
}
|
|
3340
|
+
var SkillEnsureConflictError = class extends Error {
|
|
3341
|
+
constructor(body) {
|
|
3342
|
+
super(body.error ?? `Skill ensure conflict: ${body.code}`);
|
|
3343
|
+
this.name = "SkillEnsureConflictError";
|
|
3344
|
+
this.code = body.code;
|
|
3345
|
+
this.lastModifiedSource = body.lastModifiedSource;
|
|
3346
|
+
this.modifiedAt = body.modifiedAt;
|
|
3347
|
+
this.currentHash = body.currentHash;
|
|
3348
|
+
}
|
|
3349
|
+
};
|
|
3350
|
+
var SkillDriftError = class extends Error {
|
|
3351
|
+
constructor(plan) {
|
|
3352
|
+
super(
|
|
3353
|
+
`Skill "${plan.skillId ?? "definition"}" drifted: plan is '${plan.changes}' (changed: ${plan.changedKeys.join(", ") || "n/a"}). Run client.skills.pull(name) to absorb the remote edit into your repo, or re-run ensure to converge.`
|
|
3354
|
+
);
|
|
3355
|
+
this.name = "SkillDriftError";
|
|
3356
|
+
this.plan = plan;
|
|
3357
|
+
}
|
|
3358
|
+
};
|
|
3359
|
+
function parseRequestError2(err) {
|
|
3360
|
+
if (!(err instanceof Error)) return { status: null, body: null };
|
|
3361
|
+
const match = err.message.match(/^API request failed: (\d{3}) .*? - ([\s\S]*)$/);
|
|
3362
|
+
if (!match) return { status: null, body: null };
|
|
3363
|
+
try {
|
|
3364
|
+
return { status: Number(match[1]), body: JSON.parse(match[2]) };
|
|
3365
|
+
} catch {
|
|
3366
|
+
return { status: Number(match[1]), body: null };
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
function toConflictError2(err) {
|
|
3370
|
+
const { status, body } = parseRequestError2(err);
|
|
3371
|
+
if (status !== 409 || !isPlainObject2(body)) return null;
|
|
3372
|
+
const code = body.code;
|
|
3373
|
+
if (code !== "external_modification" && code !== "remote_changed") return null;
|
|
3374
|
+
return new SkillEnsureConflictError(
|
|
3375
|
+
body
|
|
3376
|
+
);
|
|
3377
|
+
}
|
|
3378
|
+
var serverHashMemo2 = /* @__PURE__ */ new WeakMap();
|
|
3379
|
+
function memoFor2(client) {
|
|
3380
|
+
let memo = serverHashMemo2.get(client);
|
|
3381
|
+
if (!memo) {
|
|
3382
|
+
memo = /* @__PURE__ */ new Map();
|
|
3383
|
+
serverHashMemo2.set(client, memo);
|
|
3384
|
+
}
|
|
3385
|
+
return memo;
|
|
3386
|
+
}
|
|
3387
|
+
function memoize2(memo, memoKey, result) {
|
|
3388
|
+
if (result.result !== "plan") memo.set(memoKey, result.contentHash);
|
|
3389
|
+
}
|
|
3390
|
+
async function request2(client, body) {
|
|
3391
|
+
try {
|
|
3392
|
+
return await client.post(
|
|
3393
|
+
"/skills/ensure",
|
|
3394
|
+
body
|
|
3395
|
+
);
|
|
3396
|
+
} catch (err) {
|
|
3397
|
+
const conflict = toConflictError2(err);
|
|
3398
|
+
if (conflict) throw conflict;
|
|
3399
|
+
throw err;
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
async function ensureSkill(client, definition, options = {}) {
|
|
3403
|
+
const { dryRun, onConflict, release, expectedRemoteHash, expectNoChanges } = options;
|
|
3404
|
+
const passthrough = {
|
|
3405
|
+
...onConflict ? { onConflict } : {},
|
|
3406
|
+
...release ? { release } : {},
|
|
3407
|
+
...expectedRemoteHash ? { expectedRemoteHash } : {}
|
|
3408
|
+
};
|
|
3409
|
+
if (dryRun || expectNoChanges) {
|
|
3410
|
+
const plan = await request2(client, {
|
|
3411
|
+
name: definition.name,
|
|
3412
|
+
definition: manifestToWire(definition),
|
|
3413
|
+
dryRun: true,
|
|
3414
|
+
...passthrough
|
|
3415
|
+
});
|
|
3416
|
+
if (plan.result !== "plan") {
|
|
3417
|
+
throw new Error(`Expected a plan result from dryRun, got '${plan.result}'`);
|
|
3418
|
+
}
|
|
3419
|
+
if (expectNoChanges && plan.changes !== "none") {
|
|
3420
|
+
throw new SkillDriftError(plan);
|
|
3421
|
+
}
|
|
3422
|
+
return plan;
|
|
3423
|
+
}
|
|
3424
|
+
const memo = memoFor2(client);
|
|
3425
|
+
const localHash = await computeSkillContentHash(definition);
|
|
3426
|
+
const memoKey = `${definition.name} ${localHash}`;
|
|
3427
|
+
const contentHash = memo.get(memoKey) ?? localHash;
|
|
3428
|
+
const probe = await request2(client, {
|
|
3429
|
+
name: definition.name,
|
|
3430
|
+
contentHash,
|
|
3431
|
+
...passthrough
|
|
3432
|
+
});
|
|
3433
|
+
if (probe.result !== "definitionRequired") {
|
|
3434
|
+
memoize2(memo, memoKey, probe);
|
|
3435
|
+
return probe;
|
|
3436
|
+
}
|
|
3437
|
+
const converged = await request2(client, {
|
|
3438
|
+
name: definition.name,
|
|
3439
|
+
definition: manifestToWire(definition),
|
|
3440
|
+
...passthrough
|
|
3441
|
+
});
|
|
3442
|
+
if (converged.result === "definitionRequired") {
|
|
3443
|
+
throw new Error("Server reported definitionRequired for a full-definition request");
|
|
3444
|
+
}
|
|
3445
|
+
memoize2(memo, memoKey, converged);
|
|
3446
|
+
return converged;
|
|
3447
|
+
}
|
|
3448
|
+
function manifestToWire(definition) {
|
|
3449
|
+
const manifest = definition.manifest;
|
|
3450
|
+
const frontmatter = { ...manifest.frontmatter };
|
|
3451
|
+
if (manifest.runtype && Object.keys(manifest.runtype).length > 0) {
|
|
3452
|
+
frontmatter.runtype = manifest.runtype;
|
|
3453
|
+
}
|
|
3454
|
+
return { frontmatter, body: manifest.body ?? "" };
|
|
3455
|
+
}
|
|
3456
|
+
async function pullSkill(client, name) {
|
|
3457
|
+
return client.get("/skills/pull", { name });
|
|
3458
|
+
}
|
|
3459
|
+
|
|
3262
3460
|
// src/skills-namespace.ts
|
|
3263
3461
|
var SkillProposalsNamespace = class {
|
|
3264
3462
|
constructor(getClient) {
|
|
@@ -3399,6 +3597,22 @@ var SkillsNamespace = class {
|
|
|
3399
3597
|
const client = this.getClient();
|
|
3400
3598
|
await client.post(`/skills/${skillId}/versions/${versionId}/publish`);
|
|
3401
3599
|
}
|
|
3600
|
+
/**
|
|
3601
|
+
* Statically scan a SKILL.md document for malicious patterns and return a
|
|
3602
|
+
* two-tier verdict — `warning` when a skill appears suspicious (low–medium
|
|
3603
|
+
* confidence), `error` when high-confidence malicious. Does not persist or
|
|
3604
|
+
* gate; use it as a "scan before save" affordance.
|
|
3605
|
+
*
|
|
3606
|
+
* @example
|
|
3607
|
+
* ```typescript
|
|
3608
|
+
* const { verdict } = await Runtype.skills.scan(skillMarkdown)
|
|
3609
|
+
* if (verdict.tier === 'error') console.warn(verdict.summary)
|
|
3610
|
+
* ```
|
|
3611
|
+
*/
|
|
3612
|
+
async scan(markdown) {
|
|
3613
|
+
const client = this.getClient();
|
|
3614
|
+
return client.post("/skills/scan", { markdown });
|
|
3615
|
+
}
|
|
3402
3616
|
/**
|
|
3403
3617
|
* Import a single SKILL.md document. The imported skill lands with
|
|
3404
3618
|
* `trustLevel: 'imported'` and a draft version.
|
|
@@ -3441,6 +3655,40 @@ var SkillsNamespace = class {
|
|
|
3441
3655
|
const res = await client.get("/skills/bindings", { agentId });
|
|
3442
3656
|
return res.data;
|
|
3443
3657
|
}
|
|
3658
|
+
/**
|
|
3659
|
+
* Idempotently converge a `defineSkill` definition onto the platform.
|
|
3660
|
+
* Hash-first: the steady state is one tiny probe request. Creates or appends a
|
|
3661
|
+
* new version; never deletes. Identity is name + account scope. Pass
|
|
3662
|
+
* `release: 'publish'` to publish the converged version.
|
|
3663
|
+
*
|
|
3664
|
+
* @example
|
|
3665
|
+
* ```typescript
|
|
3666
|
+
* const reviewer = defineSkill({
|
|
3667
|
+
* name: 'code_reviewer',
|
|
3668
|
+
* manifest: {
|
|
3669
|
+
* frontmatter: { name: 'code_reviewer', description: 'Reviews pull requests' },
|
|
3670
|
+
* runtype: { trustLevel: 'org' },
|
|
3671
|
+
* body: '# Code Reviewer\n\nReview the diff...',
|
|
3672
|
+
* },
|
|
3673
|
+
* })
|
|
3674
|
+
*
|
|
3675
|
+
* // Converge + publish (CI/deploy).
|
|
3676
|
+
* const result = await Runtype.skills.ensure(reviewer, { release: 'publish' })
|
|
3677
|
+
*
|
|
3678
|
+
* // PR drift gate.
|
|
3679
|
+
* await Runtype.skills.ensure(reviewer, { expectNoChanges: true })
|
|
3680
|
+
* ```
|
|
3681
|
+
*/
|
|
3682
|
+
async ensure(definition, options = {}) {
|
|
3683
|
+
return ensureSkill(this.getClient(), definition, options);
|
|
3684
|
+
}
|
|
3685
|
+
/**
|
|
3686
|
+
* Pull the canonical definition + provenance for a skill by name — the
|
|
3687
|
+
* absorb-drift direction of the ensure protocol.
|
|
3688
|
+
*/
|
|
3689
|
+
async pull(name) {
|
|
3690
|
+
return pullSkill(this.getClient(), name);
|
|
3691
|
+
}
|
|
3444
3692
|
};
|
|
3445
3693
|
|
|
3446
3694
|
// src/agents-namespace.ts
|
|
@@ -3466,19 +3714,19 @@ var AGENT_CONFIG_KEYS = [
|
|
|
3466
3714
|
"memory"
|
|
3467
3715
|
];
|
|
3468
3716
|
var AGENT_CONFIG_KEY_LIST = [...AGENT_CONFIG_KEYS].sort();
|
|
3469
|
-
function
|
|
3717
|
+
function isPlainObject3(value) {
|
|
3470
3718
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3471
3719
|
}
|
|
3472
|
-
function
|
|
3720
|
+
function normalizeValue2(value) {
|
|
3473
3721
|
if (Array.isArray(value)) {
|
|
3474
|
-
return value.map((item) =>
|
|
3722
|
+
return value.map((item) => normalizeValue2(item));
|
|
3475
3723
|
}
|
|
3476
|
-
if (
|
|
3724
|
+
if (isPlainObject3(value)) {
|
|
3477
3725
|
const normalized = {};
|
|
3478
3726
|
for (const key of Object.keys(value).sort()) {
|
|
3479
3727
|
const entry = value[key];
|
|
3480
3728
|
if (entry === void 0 || entry === null) continue;
|
|
3481
|
-
normalized[key] =
|
|
3729
|
+
normalized[key] = normalizeValue2(entry);
|
|
3482
3730
|
}
|
|
3483
3731
|
return normalized;
|
|
3484
3732
|
}
|
|
@@ -3486,11 +3734,11 @@ function normalizeValue(value) {
|
|
|
3486
3734
|
}
|
|
3487
3735
|
function normalizeAgentDefinition(definition) {
|
|
3488
3736
|
const config = {};
|
|
3489
|
-
const rawConfig =
|
|
3737
|
+
const rawConfig = isPlainObject3(definition.config) ? definition.config : {};
|
|
3490
3738
|
for (const key of AGENT_CONFIG_KEY_LIST) {
|
|
3491
3739
|
const value = rawConfig[key];
|
|
3492
3740
|
if (value === void 0 || value === null) continue;
|
|
3493
|
-
config[key] =
|
|
3741
|
+
config[key] = normalizeValue2(value);
|
|
3494
3742
|
}
|
|
3495
3743
|
return {
|
|
3496
3744
|
name: definition.name,
|
|
@@ -3508,7 +3756,7 @@ async function computeAgentContentHash(definition) {
|
|
|
3508
3756
|
var DEFINE_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "description", "icon", ...AGENT_CONFIG_KEYS]);
|
|
3509
3757
|
function collectNonPortableToolRefs(config) {
|
|
3510
3758
|
const tools = config.tools;
|
|
3511
|
-
if (!
|
|
3759
|
+
if (!isPlainObject3(tools)) return [];
|
|
3512
3760
|
const found = [];
|
|
3513
3761
|
const isAccountScoped = (ref) => typeof ref === "string" && ref.startsWith("tool_");
|
|
3514
3762
|
const scanArray = (value, path) => {
|
|
@@ -3518,7 +3766,7 @@ function collectNonPortableToolRefs(config) {
|
|
|
3518
3766
|
});
|
|
3519
3767
|
};
|
|
3520
3768
|
const scanKeys = (value, path) => {
|
|
3521
|
-
if (!
|
|
3769
|
+
if (!isPlainObject3(value)) return;
|
|
3522
3770
|
for (const key of Object.keys(value)) {
|
|
3523
3771
|
if (isAccountScoped(key)) found.push(`${path}.${key}`);
|
|
3524
3772
|
}
|
|
@@ -3526,16 +3774,16 @@ function collectNonPortableToolRefs(config) {
|
|
|
3526
3774
|
scanArray(tools.toolIds, "tools.toolIds");
|
|
3527
3775
|
scanKeys(tools.toolConfigs, "tools.toolConfigs");
|
|
3528
3776
|
scanKeys(tools.perToolLimits, "tools.perToolLimits");
|
|
3529
|
-
if (
|
|
3530
|
-
if (
|
|
3777
|
+
if (isPlainObject3(tools.approval)) scanArray(tools.approval.require, "tools.approval.require");
|
|
3778
|
+
if (isPlainObject3(tools.subagentConfig)) {
|
|
3531
3779
|
scanArray(tools.subagentConfig.toolPool, "tools.subagentConfig.toolPool");
|
|
3532
3780
|
}
|
|
3533
|
-
if (
|
|
3781
|
+
if (isPlainObject3(tools.codeModeConfig)) {
|
|
3534
3782
|
scanArray(tools.codeModeConfig.toolPool, "tools.codeModeConfig.toolPool");
|
|
3535
3783
|
}
|
|
3536
3784
|
if (Array.isArray(tools.runtimeTools)) {
|
|
3537
3785
|
tools.runtimeTools.forEach((runtimeTool, i) => {
|
|
3538
|
-
if (!
|
|
3786
|
+
if (!isPlainObject3(runtimeTool) || !isPlainObject3(runtimeTool.config)) return;
|
|
3539
3787
|
const base = `tools.runtimeTools[${i}].config`;
|
|
3540
3788
|
const rtConfig = runtimeTool.config;
|
|
3541
3789
|
if (runtimeTool.toolType === "subagent" && typeof rtConfig.agentId === "string" && rtConfig.agentId.startsWith("agent_")) {
|
|
@@ -3597,7 +3845,7 @@ var AgentDriftError = class extends Error {
|
|
|
3597
3845
|
this.plan = plan;
|
|
3598
3846
|
}
|
|
3599
3847
|
};
|
|
3600
|
-
function
|
|
3848
|
+
function parseRequestError3(err) {
|
|
3601
3849
|
if (!(err instanceof Error)) return { status: null, body: null };
|
|
3602
3850
|
const match = err.message.match(/^API request failed: (\d{3}) .*? - ([\s\S]*)$/);
|
|
3603
3851
|
if (!match) return { status: null, body: null };
|
|
@@ -3607,21 +3855,21 @@ function parseRequestError2(err) {
|
|
|
3607
3855
|
return { status: Number(match[1]), body: null };
|
|
3608
3856
|
}
|
|
3609
3857
|
}
|
|
3610
|
-
function
|
|
3611
|
-
const { status, body } =
|
|
3612
|
-
if (status !== 409 || !
|
|
3858
|
+
function toConflictError3(err) {
|
|
3859
|
+
const { status, body } = parseRequestError3(err);
|
|
3860
|
+
if (status !== 409 || !isPlainObject3(body)) return null;
|
|
3613
3861
|
const code = body.code;
|
|
3614
3862
|
if (code !== "external_modification" && code !== "remote_changed") return null;
|
|
3615
3863
|
return new AgentEnsureConflictError(
|
|
3616
3864
|
body
|
|
3617
3865
|
);
|
|
3618
3866
|
}
|
|
3619
|
-
var
|
|
3620
|
-
function
|
|
3621
|
-
let memo =
|
|
3867
|
+
var serverHashMemo3 = /* @__PURE__ */ new WeakMap();
|
|
3868
|
+
function memoFor3(client) {
|
|
3869
|
+
let memo = serverHashMemo3.get(client);
|
|
3622
3870
|
if (!memo) {
|
|
3623
3871
|
memo = /* @__PURE__ */ new Map();
|
|
3624
|
-
|
|
3872
|
+
serverHashMemo3.set(client, memo);
|
|
3625
3873
|
}
|
|
3626
3874
|
return memo;
|
|
3627
3875
|
}
|
|
@@ -3658,7 +3906,7 @@ var AgentsNamespace = class {
|
|
|
3658
3906
|
}
|
|
3659
3907
|
return plan;
|
|
3660
3908
|
}
|
|
3661
|
-
const memo =
|
|
3909
|
+
const memo = memoFor3(client);
|
|
3662
3910
|
const localHash = await computeAgentContentHash({
|
|
3663
3911
|
...definition,
|
|
3664
3912
|
config: definition.config
|
|
@@ -3703,7 +3951,7 @@ var AgentsNamespace = class {
|
|
|
3703
3951
|
body
|
|
3704
3952
|
);
|
|
3705
3953
|
} catch (err) {
|
|
3706
|
-
const conflict =
|
|
3954
|
+
const conflict = toConflictError3(err);
|
|
3707
3955
|
if (conflict) throw conflict;
|
|
3708
3956
|
throw err;
|
|
3709
3957
|
}
|
|
@@ -3711,27 +3959,27 @@ var AgentsNamespace = class {
|
|
|
3711
3959
|
};
|
|
3712
3960
|
|
|
3713
3961
|
// src/tools-ensure.ts
|
|
3714
|
-
function
|
|
3962
|
+
function isPlainObject4(value) {
|
|
3715
3963
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3716
3964
|
}
|
|
3717
|
-
function
|
|
3965
|
+
function normalizeValue3(value) {
|
|
3718
3966
|
if (Array.isArray(value)) {
|
|
3719
|
-
return value.map((item) =>
|
|
3967
|
+
return value.map((item) => normalizeValue3(item));
|
|
3720
3968
|
}
|
|
3721
|
-
if (
|
|
3969
|
+
if (isPlainObject4(value)) {
|
|
3722
3970
|
const normalized = {};
|
|
3723
3971
|
for (const key of Object.keys(value).sort()) {
|
|
3724
3972
|
const entry = value[key];
|
|
3725
3973
|
if (entry === void 0 || entry === null) continue;
|
|
3726
|
-
normalized[key] =
|
|
3974
|
+
normalized[key] = normalizeValue3(entry);
|
|
3727
3975
|
}
|
|
3728
3976
|
return normalized;
|
|
3729
3977
|
}
|
|
3730
3978
|
return value;
|
|
3731
3979
|
}
|
|
3732
3980
|
function normalizeToolDefinition(definition) {
|
|
3733
|
-
const parametersSchema =
|
|
3734
|
-
const config =
|
|
3981
|
+
const parametersSchema = isPlainObject4(definition.parametersSchema) ? normalizeValue3(definition.parametersSchema) : {};
|
|
3982
|
+
const config = isPlainObject4(definition.config) ? normalizeValue3(definition.config) : {};
|
|
3735
3983
|
return {
|
|
3736
3984
|
toolType: definition.toolType,
|
|
3737
3985
|
...definition.description ? { description: definition.description } : {},
|
|
@@ -3776,10 +4024,10 @@ function defineTool(input) {
|
|
|
3776
4024
|
`defineTool requires "toolType" to be one of: ${[...TOOL_DEFINITION_TYPES].join(", ")}`
|
|
3777
4025
|
);
|
|
3778
4026
|
}
|
|
3779
|
-
if (!
|
|
4027
|
+
if (!isPlainObject4(input.parametersSchema)) {
|
|
3780
4028
|
throw new Error('defineTool requires a "parametersSchema" object (a JSON Schema)');
|
|
3781
4029
|
}
|
|
3782
|
-
if (!
|
|
4030
|
+
if (!isPlainObject4(input.config)) {
|
|
3783
4031
|
throw new Error('defineTool requires a "config" object');
|
|
3784
4032
|
}
|
|
3785
4033
|
const unknownKeys = Object.keys(input).filter((key) => !DEFINE_TOOL_TOP_LEVEL_KEYS.has(key));
|
|
@@ -3815,7 +4063,7 @@ var ToolDriftError = class extends Error {
|
|
|
3815
4063
|
this.plan = plan;
|
|
3816
4064
|
}
|
|
3817
4065
|
};
|
|
3818
|
-
function
|
|
4066
|
+
function parseRequestError4(err) {
|
|
3819
4067
|
if (!(err instanceof Error)) return { status: null, body: null };
|
|
3820
4068
|
const match = err.message.match(/^API request failed: (\d{3}) .*? - ([\s\S]*)$/);
|
|
3821
4069
|
if (!match) return { status: null, body: null };
|
|
@@ -3825,35 +4073,35 @@ function parseRequestError3(err) {
|
|
|
3825
4073
|
return { status: Number(match[1]), body: null };
|
|
3826
4074
|
}
|
|
3827
4075
|
}
|
|
3828
|
-
function
|
|
3829
|
-
const { status, body } =
|
|
3830
|
-
if (status !== 409 || !
|
|
4076
|
+
function toConflictError4(err) {
|
|
4077
|
+
const { status, body } = parseRequestError4(err);
|
|
4078
|
+
if (status !== 409 || !isPlainObject4(body)) return null;
|
|
3831
4079
|
const code = body.code;
|
|
3832
4080
|
if (code !== "external_modification" && code !== "remote_changed") return null;
|
|
3833
4081
|
return new ToolEnsureConflictError(
|
|
3834
4082
|
body
|
|
3835
4083
|
);
|
|
3836
4084
|
}
|
|
3837
|
-
var
|
|
3838
|
-
function
|
|
3839
|
-
let memo =
|
|
4085
|
+
var serverHashMemo4 = /* @__PURE__ */ new WeakMap();
|
|
4086
|
+
function memoFor4(client) {
|
|
4087
|
+
let memo = serverHashMemo4.get(client);
|
|
3840
4088
|
if (!memo) {
|
|
3841
4089
|
memo = /* @__PURE__ */ new Map();
|
|
3842
|
-
|
|
4090
|
+
serverHashMemo4.set(client, memo);
|
|
3843
4091
|
}
|
|
3844
4092
|
return memo;
|
|
3845
4093
|
}
|
|
3846
|
-
function
|
|
4094
|
+
function memoize3(memo, memoKey, result) {
|
|
3847
4095
|
if (result.result !== "plan") memo.set(memoKey, result.contentHash);
|
|
3848
4096
|
}
|
|
3849
|
-
async function
|
|
4097
|
+
async function request3(client, body) {
|
|
3850
4098
|
try {
|
|
3851
4099
|
return await client.post(
|
|
3852
4100
|
"/tools/ensure",
|
|
3853
4101
|
body
|
|
3854
4102
|
);
|
|
3855
4103
|
} catch (err) {
|
|
3856
|
-
const conflict =
|
|
4104
|
+
const conflict = toConflictError4(err);
|
|
3857
4105
|
if (conflict) throw conflict;
|
|
3858
4106
|
throw err;
|
|
3859
4107
|
}
|
|
@@ -3865,7 +4113,7 @@ async function ensureTool(client, definition, options = {}) {
|
|
|
3865
4113
|
...expectedRemoteHash ? { expectedRemoteHash } : {}
|
|
3866
4114
|
};
|
|
3867
4115
|
if (dryRun || expectNoChanges) {
|
|
3868
|
-
const plan = await
|
|
4116
|
+
const plan = await request3(client, {
|
|
3869
4117
|
name: definition.name,
|
|
3870
4118
|
definition,
|
|
3871
4119
|
dryRun: true,
|
|
@@ -3879,20 +4127,20 @@ async function ensureTool(client, definition, options = {}) {
|
|
|
3879
4127
|
}
|
|
3880
4128
|
return plan;
|
|
3881
4129
|
}
|
|
3882
|
-
const memo =
|
|
4130
|
+
const memo = memoFor4(client);
|
|
3883
4131
|
const localHash = await computeToolContentHash(definition);
|
|
3884
4132
|
const memoKey = `${definition.name} ${localHash}`;
|
|
3885
4133
|
const contentHash = memo.get(memoKey) ?? localHash;
|
|
3886
|
-
const probe = await
|
|
4134
|
+
const probe = await request3(client, {
|
|
3887
4135
|
name: definition.name,
|
|
3888
4136
|
contentHash,
|
|
3889
4137
|
...passthrough
|
|
3890
4138
|
});
|
|
3891
4139
|
if (probe.result !== "definitionRequired") {
|
|
3892
|
-
|
|
4140
|
+
memoize3(memo, memoKey, probe);
|
|
3893
4141
|
return probe;
|
|
3894
4142
|
}
|
|
3895
|
-
const converged = await
|
|
4143
|
+
const converged = await request3(client, {
|
|
3896
4144
|
name: definition.name,
|
|
3897
4145
|
definition,
|
|
3898
4146
|
...passthrough
|
|
@@ -3900,7 +4148,7 @@ async function ensureTool(client, definition, options = {}) {
|
|
|
3900
4148
|
if (converged.result === "definitionRequired") {
|
|
3901
4149
|
throw new Error("Server reported definitionRequired for a full-definition request");
|
|
3902
4150
|
}
|
|
3903
|
-
|
|
4151
|
+
memoize3(memo, memoKey, converged);
|
|
3904
4152
|
return converged;
|
|
3905
4153
|
}
|
|
3906
4154
|
async function pullTool(client, name) {
|
|
@@ -3947,26 +4195,26 @@ var ToolsNamespace = class {
|
|
|
3947
4195
|
};
|
|
3948
4196
|
|
|
3949
4197
|
// src/products-ensure.ts
|
|
3950
|
-
function
|
|
4198
|
+
function isPlainObject5(value) {
|
|
3951
4199
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3952
4200
|
}
|
|
3953
|
-
function
|
|
4201
|
+
function normalizeValue4(value) {
|
|
3954
4202
|
if (Array.isArray(value)) {
|
|
3955
|
-
return value.map((item) =>
|
|
4203
|
+
return value.map((item) => normalizeValue4(item));
|
|
3956
4204
|
}
|
|
3957
|
-
if (
|
|
4205
|
+
if (isPlainObject5(value)) {
|
|
3958
4206
|
const normalized = {};
|
|
3959
4207
|
for (const key of Object.keys(value).sort()) {
|
|
3960
4208
|
const entry = value[key];
|
|
3961
4209
|
if (entry === void 0 || entry === null) continue;
|
|
3962
|
-
normalized[key] =
|
|
4210
|
+
normalized[key] = normalizeValue4(entry);
|
|
3963
4211
|
}
|
|
3964
4212
|
return normalized;
|
|
3965
4213
|
}
|
|
3966
4214
|
return value;
|
|
3967
4215
|
}
|
|
3968
4216
|
function normalizeProductDefinition(definition) {
|
|
3969
|
-
const spec =
|
|
4217
|
+
const spec = isPlainObject5(definition.spec) ? normalizeValue4(definition.spec) : {};
|
|
3970
4218
|
return {
|
|
3971
4219
|
...definition.description ? { description: definition.description } : {},
|
|
3972
4220
|
...definition.icon ? { icon: definition.icon } : {},
|
|
@@ -3993,7 +4241,7 @@ function defineProduct(input) {
|
|
|
3993
4241
|
if (input.icon != null && typeof input.icon !== "string") {
|
|
3994
4242
|
throw new Error('defineProduct "icon" must be a string when provided');
|
|
3995
4243
|
}
|
|
3996
|
-
if (input.spec != null && !
|
|
4244
|
+
if (input.spec != null && !isPlainObject5(input.spec)) {
|
|
3997
4245
|
throw new Error('defineProduct "spec" must be an object when provided');
|
|
3998
4246
|
}
|
|
3999
4247
|
const unknownKeys = Object.keys(input).filter((key) => !DEFINE_PRODUCT_TOP_LEVEL_KEYS.has(key));
|
|
@@ -4028,7 +4276,7 @@ var ProductDriftError = class extends Error {
|
|
|
4028
4276
|
this.plan = plan;
|
|
4029
4277
|
}
|
|
4030
4278
|
};
|
|
4031
|
-
function
|
|
4279
|
+
function parseRequestError5(err) {
|
|
4032
4280
|
if (!(err instanceof Error)) return { status: null, body: null };
|
|
4033
4281
|
const match = err.message.match(/^API request failed: (\d{3}) .*? - ([\s\S]*)$/);
|
|
4034
4282
|
if (!match) return { status: null, body: null };
|
|
@@ -4038,35 +4286,35 @@ function parseRequestError4(err) {
|
|
|
4038
4286
|
return { status: Number(match[1]), body: null };
|
|
4039
4287
|
}
|
|
4040
4288
|
}
|
|
4041
|
-
function
|
|
4042
|
-
const { status, body } =
|
|
4043
|
-
if (status !== 409 || !
|
|
4289
|
+
function toConflictError5(err) {
|
|
4290
|
+
const { status, body } = parseRequestError5(err);
|
|
4291
|
+
if (status !== 409 || !isPlainObject5(body)) return null;
|
|
4044
4292
|
const code = body.code;
|
|
4045
4293
|
if (code !== "external_modification" && code !== "remote_changed") return null;
|
|
4046
4294
|
return new ProductEnsureConflictError(
|
|
4047
4295
|
body
|
|
4048
4296
|
);
|
|
4049
4297
|
}
|
|
4050
|
-
var
|
|
4051
|
-
function
|
|
4052
|
-
let memo =
|
|
4298
|
+
var serverHashMemo5 = /* @__PURE__ */ new WeakMap();
|
|
4299
|
+
function memoFor5(client) {
|
|
4300
|
+
let memo = serverHashMemo5.get(client);
|
|
4053
4301
|
if (!memo) {
|
|
4054
4302
|
memo = /* @__PURE__ */ new Map();
|
|
4055
|
-
|
|
4303
|
+
serverHashMemo5.set(client, memo);
|
|
4056
4304
|
}
|
|
4057
4305
|
return memo;
|
|
4058
4306
|
}
|
|
4059
|
-
function
|
|
4307
|
+
function memoize4(memo, memoKey, result) {
|
|
4060
4308
|
if (result.result !== "plan") memo.set(memoKey, result.contentHash);
|
|
4061
4309
|
}
|
|
4062
|
-
async function
|
|
4310
|
+
async function request4(client, body) {
|
|
4063
4311
|
try {
|
|
4064
4312
|
return await client.post(
|
|
4065
4313
|
"/products/ensure",
|
|
4066
4314
|
body
|
|
4067
4315
|
);
|
|
4068
4316
|
} catch (err) {
|
|
4069
|
-
const conflict =
|
|
4317
|
+
const conflict = toConflictError5(err);
|
|
4070
4318
|
if (conflict) throw conflict;
|
|
4071
4319
|
throw err;
|
|
4072
4320
|
}
|
|
@@ -4078,7 +4326,7 @@ async function ensureProduct(client, definition, options = {}) {
|
|
|
4078
4326
|
...expectedRemoteHash ? { expectedRemoteHash } : {}
|
|
4079
4327
|
};
|
|
4080
4328
|
if (dryRun || expectNoChanges) {
|
|
4081
|
-
const plan = await
|
|
4329
|
+
const plan = await request4(client, {
|
|
4082
4330
|
name: definition.name,
|
|
4083
4331
|
definition,
|
|
4084
4332
|
dryRun: true,
|
|
@@ -4092,20 +4340,20 @@ async function ensureProduct(client, definition, options = {}) {
|
|
|
4092
4340
|
}
|
|
4093
4341
|
return plan;
|
|
4094
4342
|
}
|
|
4095
|
-
const memo =
|
|
4343
|
+
const memo = memoFor5(client);
|
|
4096
4344
|
const localHash = await computeProductContentHash(definition);
|
|
4097
4345
|
const memoKey = `${definition.name} ${localHash}`;
|
|
4098
4346
|
const contentHash = memo.get(memoKey) ?? localHash;
|
|
4099
|
-
const probe = await
|
|
4347
|
+
const probe = await request4(client, {
|
|
4100
4348
|
name: definition.name,
|
|
4101
4349
|
contentHash,
|
|
4102
4350
|
...passthrough
|
|
4103
4351
|
});
|
|
4104
4352
|
if (probe.result !== "definitionRequired") {
|
|
4105
|
-
|
|
4353
|
+
memoize4(memo, memoKey, probe);
|
|
4106
4354
|
return probe;
|
|
4107
4355
|
}
|
|
4108
|
-
const converged = await
|
|
4356
|
+
const converged = await request4(client, {
|
|
4109
4357
|
name: definition.name,
|
|
4110
4358
|
definition,
|
|
4111
4359
|
...passthrough
|
|
@@ -4113,7 +4361,7 @@ async function ensureProduct(client, definition, options = {}) {
|
|
|
4113
4361
|
if (converged.result === "definitionRequired") {
|
|
4114
4362
|
throw new Error("Server reported definitionRequired for a full-definition request");
|
|
4115
4363
|
}
|
|
4116
|
-
|
|
4364
|
+
memoize4(memo, memoKey, converged);
|
|
4117
4365
|
return converged;
|
|
4118
4366
|
}
|
|
4119
4367
|
async function pullProduct(client, name) {
|
|
@@ -4159,6 +4407,262 @@ var ProductsNamespace = class {
|
|
|
4159
4407
|
}
|
|
4160
4408
|
};
|
|
4161
4409
|
|
|
4410
|
+
// src/surfaces-ensure.ts
|
|
4411
|
+
function isPlainObject6(value) {
|
|
4412
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4413
|
+
}
|
|
4414
|
+
function normalizeValue5(value) {
|
|
4415
|
+
if (Array.isArray(value)) {
|
|
4416
|
+
return value.map((item) => normalizeValue5(item));
|
|
4417
|
+
}
|
|
4418
|
+
if (isPlainObject6(value)) {
|
|
4419
|
+
const normalized = {};
|
|
4420
|
+
for (const key of Object.keys(value).sort()) {
|
|
4421
|
+
const entry = value[key];
|
|
4422
|
+
if (entry === void 0 || entry === null) continue;
|
|
4423
|
+
normalized[key] = normalizeValue5(entry);
|
|
4424
|
+
}
|
|
4425
|
+
return normalized;
|
|
4426
|
+
}
|
|
4427
|
+
return value;
|
|
4428
|
+
}
|
|
4429
|
+
function normalizeSurfaceDefinition(definition) {
|
|
4430
|
+
const behavior = isPlainObject6(definition.behavior) ? normalizeValue5(definition.behavior) : { type: definition.type };
|
|
4431
|
+
return {
|
|
4432
|
+
type: definition.type,
|
|
4433
|
+
behavior,
|
|
4434
|
+
status: definition.status || "draft",
|
|
4435
|
+
environment: definition.environment || "development"
|
|
4436
|
+
};
|
|
4437
|
+
}
|
|
4438
|
+
async function computeSurfaceContentHash(definition) {
|
|
4439
|
+
const serialized = JSON.stringify(normalizeSurfaceDefinition(definition));
|
|
4440
|
+
const encoded = new TextEncoder().encode(serialized);
|
|
4441
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
|
|
4442
|
+
return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
4443
|
+
}
|
|
4444
|
+
var DEFINE_SURFACE_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
4445
|
+
"name",
|
|
4446
|
+
"type",
|
|
4447
|
+
"behavior",
|
|
4448
|
+
"inbound",
|
|
4449
|
+
"outbound",
|
|
4450
|
+
"status",
|
|
4451
|
+
"environment"
|
|
4452
|
+
]);
|
|
4453
|
+
var SURFACE_DEFINITION_TYPES = /* @__PURE__ */ new Set([
|
|
4454
|
+
"chat",
|
|
4455
|
+
"mcp",
|
|
4456
|
+
"mcp_code",
|
|
4457
|
+
"api",
|
|
4458
|
+
"webhook",
|
|
4459
|
+
"schedule",
|
|
4460
|
+
"a2a",
|
|
4461
|
+
"email",
|
|
4462
|
+
"slack",
|
|
4463
|
+
"sms",
|
|
4464
|
+
"imessage",
|
|
4465
|
+
"discord",
|
|
4466
|
+
"whatsapp",
|
|
4467
|
+
"telegram",
|
|
4468
|
+
"hosted-page",
|
|
4469
|
+
"chrome_extension"
|
|
4470
|
+
]);
|
|
4471
|
+
function defineSurface(input) {
|
|
4472
|
+
if (!input || typeof input !== "object") {
|
|
4473
|
+
throw new Error("defineSurface requires a definition object");
|
|
4474
|
+
}
|
|
4475
|
+
if (typeof input.name !== "string" || input.name.length === 0) {
|
|
4476
|
+
throw new Error('defineSurface requires a non-empty string "name"');
|
|
4477
|
+
}
|
|
4478
|
+
if (typeof input.type !== "string" || !SURFACE_DEFINITION_TYPES.has(input.type)) {
|
|
4479
|
+
throw new Error(
|
|
4480
|
+
`defineSurface requires "type" to be one of: ${[...SURFACE_DEFINITION_TYPES].join(", ")}`
|
|
4481
|
+
);
|
|
4482
|
+
}
|
|
4483
|
+
if (input.behavior !== void 0 && !isPlainObject6(input.behavior)) {
|
|
4484
|
+
throw new Error('defineSurface "behavior" must be an object when provided');
|
|
4485
|
+
}
|
|
4486
|
+
if (input.inbound !== void 0 && !isPlainObject6(input.inbound)) {
|
|
4487
|
+
throw new Error('defineSurface "inbound" must be an object when provided');
|
|
4488
|
+
}
|
|
4489
|
+
if (input.outbound !== void 0 && !isPlainObject6(input.outbound)) {
|
|
4490
|
+
throw new Error('defineSurface "outbound" must be an object when provided');
|
|
4491
|
+
}
|
|
4492
|
+
if (input.status !== void 0 && !["draft", "active", "paused"].includes(input.status)) {
|
|
4493
|
+
throw new Error('defineSurface "status" must be one of: draft, active, paused');
|
|
4494
|
+
}
|
|
4495
|
+
if (input.environment !== void 0 && !["production", "development"].includes(input.environment)) {
|
|
4496
|
+
throw new Error('defineSurface "environment" must be one of: production, development');
|
|
4497
|
+
}
|
|
4498
|
+
const unknownKeys = Object.keys(input).filter((key) => !DEFINE_SURFACE_TOP_LEVEL_KEYS.has(key));
|
|
4499
|
+
if (unknownKeys.length > 0) {
|
|
4500
|
+
throw new Error(
|
|
4501
|
+
`defineSurface: unknown field(s): ${unknownKeys.join(", ")}. Allowed fields are name, type, behavior, inbound, outbound, status, environment.`
|
|
4502
|
+
);
|
|
4503
|
+
}
|
|
4504
|
+
return {
|
|
4505
|
+
name: input.name,
|
|
4506
|
+
type: input.type,
|
|
4507
|
+
...input.behavior !== void 0 ? { behavior: input.behavior } : {},
|
|
4508
|
+
...input.inbound !== void 0 ? { inbound: input.inbound } : {},
|
|
4509
|
+
...input.outbound !== void 0 ? { outbound: input.outbound } : {},
|
|
4510
|
+
...input.status !== void 0 ? { status: input.status } : {},
|
|
4511
|
+
...input.environment !== void 0 ? { environment: input.environment } : {}
|
|
4512
|
+
};
|
|
4513
|
+
}
|
|
4514
|
+
var SurfaceEnsureConflictError = class extends Error {
|
|
4515
|
+
constructor(body) {
|
|
4516
|
+
super(body.error ?? `Surface ensure conflict: ${body.code}`);
|
|
4517
|
+
this.name = "SurfaceEnsureConflictError";
|
|
4518
|
+
this.code = body.code;
|
|
4519
|
+
this.lastModifiedSource = body.lastModifiedSource;
|
|
4520
|
+
this.modifiedAt = body.modifiedAt;
|
|
4521
|
+
this.currentHash = body.currentHash;
|
|
4522
|
+
}
|
|
4523
|
+
};
|
|
4524
|
+
var SurfaceDriftError = class extends Error {
|
|
4525
|
+
constructor(plan) {
|
|
4526
|
+
super(
|
|
4527
|
+
`Surface "${plan.surfaceId ?? "definition"}" drifted: plan is '${plan.changes}' (changed: ${plan.changedKeys.join(", ") || "n/a"}). Run client.surfaces.pull(productId, name) to absorb the remote edit into your repo, or re-run ensure to converge.`
|
|
4528
|
+
);
|
|
4529
|
+
this.name = "SurfaceDriftError";
|
|
4530
|
+
this.plan = plan;
|
|
4531
|
+
}
|
|
4532
|
+
};
|
|
4533
|
+
function parseRequestError6(err) {
|
|
4534
|
+
if (!(err instanceof Error)) return { status: null, body: null };
|
|
4535
|
+
const match = err.message.match(/^API request failed: (\d{3}) .*? - ([\s\S]*)$/);
|
|
4536
|
+
if (!match) return { status: null, body: null };
|
|
4537
|
+
try {
|
|
4538
|
+
return { status: Number(match[1]), body: JSON.parse(match[2]) };
|
|
4539
|
+
} catch {
|
|
4540
|
+
return { status: Number(match[1]), body: null };
|
|
4541
|
+
}
|
|
4542
|
+
}
|
|
4543
|
+
function toConflictError6(err) {
|
|
4544
|
+
const { status, body } = parseRequestError6(err);
|
|
4545
|
+
if (status !== 409 || !isPlainObject6(body)) return null;
|
|
4546
|
+
const code = body.code;
|
|
4547
|
+
if (code !== "external_modification" && code !== "remote_changed") return null;
|
|
4548
|
+
return new SurfaceEnsureConflictError(
|
|
4549
|
+
body
|
|
4550
|
+
);
|
|
4551
|
+
}
|
|
4552
|
+
var serverHashMemo6 = /* @__PURE__ */ new WeakMap();
|
|
4553
|
+
function memoFor6(client) {
|
|
4554
|
+
let memo = serverHashMemo6.get(client);
|
|
4555
|
+
if (!memo) {
|
|
4556
|
+
memo = /* @__PURE__ */ new Map();
|
|
4557
|
+
serverHashMemo6.set(client, memo);
|
|
4558
|
+
}
|
|
4559
|
+
return memo;
|
|
4560
|
+
}
|
|
4561
|
+
function memoize5(memo, memoKey, result) {
|
|
4562
|
+
if (result.result !== "plan") memo.set(memoKey, result.contentHash);
|
|
4563
|
+
}
|
|
4564
|
+
async function request5(client, productId, body) {
|
|
4565
|
+
try {
|
|
4566
|
+
return await client.post(
|
|
4567
|
+
`/products/${encodeURIComponent(productId)}/surfaces/ensure`,
|
|
4568
|
+
body
|
|
4569
|
+
);
|
|
4570
|
+
} catch (err) {
|
|
4571
|
+
const conflict = toConflictError6(err);
|
|
4572
|
+
if (conflict) throw conflict;
|
|
4573
|
+
throw err;
|
|
4574
|
+
}
|
|
4575
|
+
}
|
|
4576
|
+
async function ensureSurface(client, productId, definition, options = {}) {
|
|
4577
|
+
const { dryRun, onConflict, expectedRemoteHash, expectNoChanges } = options;
|
|
4578
|
+
const passthrough = {
|
|
4579
|
+
...onConflict ? { onConflict } : {},
|
|
4580
|
+
...expectedRemoteHash ? { expectedRemoteHash } : {}
|
|
4581
|
+
};
|
|
4582
|
+
if (dryRun || expectNoChanges) {
|
|
4583
|
+
const plan = await request5(client, productId, {
|
|
4584
|
+
name: definition.name,
|
|
4585
|
+
definition,
|
|
4586
|
+
dryRun: true,
|
|
4587
|
+
...passthrough
|
|
4588
|
+
});
|
|
4589
|
+
if (plan.result !== "plan") {
|
|
4590
|
+
throw new Error(`Expected a plan result from dryRun, got '${plan.result}'`);
|
|
4591
|
+
}
|
|
4592
|
+
if (expectNoChanges && plan.changes !== "none") {
|
|
4593
|
+
throw new SurfaceDriftError(plan);
|
|
4594
|
+
}
|
|
4595
|
+
return plan;
|
|
4596
|
+
}
|
|
4597
|
+
const memo = memoFor6(client);
|
|
4598
|
+
const localHash = await computeSurfaceContentHash(definition);
|
|
4599
|
+
const memoKey = `${productId} ${definition.name} ${localHash}`;
|
|
4600
|
+
const contentHash = memo.get(memoKey) ?? localHash;
|
|
4601
|
+
const probe = await request5(client, productId, {
|
|
4602
|
+
name: definition.name,
|
|
4603
|
+
contentHash,
|
|
4604
|
+
...passthrough
|
|
4605
|
+
});
|
|
4606
|
+
if (probe.result !== "definitionRequired") {
|
|
4607
|
+
memoize5(memo, memoKey, probe);
|
|
4608
|
+
return probe;
|
|
4609
|
+
}
|
|
4610
|
+
const converged = await request5(client, productId, {
|
|
4611
|
+
name: definition.name,
|
|
4612
|
+
definition,
|
|
4613
|
+
...passthrough
|
|
4614
|
+
});
|
|
4615
|
+
if (converged.result === "definitionRequired") {
|
|
4616
|
+
throw new Error("Server reported definitionRequired for a full-definition request");
|
|
4617
|
+
}
|
|
4618
|
+
memoize5(memo, memoKey, converged);
|
|
4619
|
+
return converged;
|
|
4620
|
+
}
|
|
4621
|
+
async function pullSurface(client, productId, name) {
|
|
4622
|
+
return client.get(
|
|
4623
|
+
`/products/${encodeURIComponent(productId)}/surfaces/pull`,
|
|
4624
|
+
{ name }
|
|
4625
|
+
);
|
|
4626
|
+
}
|
|
4627
|
+
|
|
4628
|
+
// src/surfaces-namespace.ts
|
|
4629
|
+
var SurfacesNamespace = class {
|
|
4630
|
+
constructor(getClient) {
|
|
4631
|
+
this.getClient = getClient;
|
|
4632
|
+
}
|
|
4633
|
+
/**
|
|
4634
|
+
* Idempotently converge a `defineSurface` definition onto a product.
|
|
4635
|
+
* Hash-first: the steady state is one tiny probe request. Creates or updates
|
|
4636
|
+
* the surface; never deletes. Identity is name + product.
|
|
4637
|
+
*
|
|
4638
|
+
* @example
|
|
4639
|
+
* ```typescript
|
|
4640
|
+
* const chat = defineSurface({
|
|
4641
|
+
* name: 'Support Chat',
|
|
4642
|
+
* type: 'chat',
|
|
4643
|
+
* behavior: { type: 'chat', greeting: 'Hi there!' },
|
|
4644
|
+
* status: 'active',
|
|
4645
|
+
* })
|
|
4646
|
+
*
|
|
4647
|
+
* // Converge (CI/deploy).
|
|
4648
|
+
* const result = await Runtype.surfaces.ensure('product_abc', chat)
|
|
4649
|
+
*
|
|
4650
|
+
* // PR drift gate.
|
|
4651
|
+
* await Runtype.surfaces.ensure('product_abc', chat, { expectNoChanges: true })
|
|
4652
|
+
* ```
|
|
4653
|
+
*/
|
|
4654
|
+
async ensure(productId, definition, options = {}) {
|
|
4655
|
+
return ensureSurface(this.getClient(), productId, definition, options);
|
|
4656
|
+
}
|
|
4657
|
+
/**
|
|
4658
|
+
* Pull the canonical definition + provenance for a surface by name within a
|
|
4659
|
+
* product — the absorb-drift direction of the ensure protocol.
|
|
4660
|
+
*/
|
|
4661
|
+
async pull(productId, name) {
|
|
4662
|
+
return pullSurface(this.getClient(), productId, name);
|
|
4663
|
+
}
|
|
4664
|
+
};
|
|
4665
|
+
|
|
4162
4666
|
// src/transform.ts
|
|
4163
4667
|
function transformResponse(data) {
|
|
4164
4668
|
return data;
|
|
@@ -4606,6 +5110,35 @@ var Runtype = class {
|
|
|
4606
5110
|
static get products() {
|
|
4607
5111
|
return new ProductsNamespace(() => this.getClient());
|
|
4608
5112
|
}
|
|
5113
|
+
/**
|
|
5114
|
+
* Config-as-code operations for product surfaces. `surfaces.ensure` is the
|
|
5115
|
+
* deploy-time, non-executing converge (create-or-update a surface by name
|
|
5116
|
+
* within a product); `surfaces.pull` is the absorb-drift direction.
|
|
5117
|
+
*
|
|
5118
|
+
* @example
|
|
5119
|
+
* ```typescript
|
|
5120
|
+
* import { Runtype, defineSurface } from '@runtypelabs/sdk'
|
|
5121
|
+
*
|
|
5122
|
+
* const chat = defineSurface({
|
|
5123
|
+
* name: 'Support Chat',
|
|
5124
|
+
* type: 'chat',
|
|
5125
|
+
* behavior: { type: 'chat', greeting: 'Hi there!' },
|
|
5126
|
+
* status: 'active',
|
|
5127
|
+
* })
|
|
5128
|
+
*
|
|
5129
|
+
* // Converge at deploy time (idempotent; one tiny probe in steady state)
|
|
5130
|
+
* await Runtype.surfaces.ensure('product_abc', chat)
|
|
5131
|
+
*
|
|
5132
|
+
* // CI drift gate
|
|
5133
|
+
* await Runtype.surfaces.ensure('product_abc', chat, { expectNoChanges: true })
|
|
5134
|
+
*
|
|
5135
|
+
* // Absorb a dashboard edit back into the repo
|
|
5136
|
+
* const { definition } = await Runtype.surfaces.pull('product_abc', 'Support Chat')
|
|
5137
|
+
* ```
|
|
5138
|
+
*/
|
|
5139
|
+
static get surfaces() {
|
|
5140
|
+
return new SurfacesNamespace(() => this.getClient());
|
|
5141
|
+
}
|
|
4609
5142
|
};
|
|
4610
5143
|
|
|
4611
5144
|
// src/generated-tool-gate.ts
|
|
@@ -4828,8 +5361,8 @@ function buildGeneratedRuntimeToolGateOutput(proposal, options = {}) {
|
|
|
4828
5361
|
...decision.tool ? { tool: decision.tool } : {}
|
|
4829
5362
|
};
|
|
4830
5363
|
}
|
|
4831
|
-
function attachRuntimeToolsToDispatchRequest(
|
|
4832
|
-
const stepList =
|
|
5364
|
+
function attachRuntimeToolsToDispatchRequest(request6, runtimeTools, options = {}) {
|
|
5365
|
+
const stepList = request6.flow.steps;
|
|
4833
5366
|
if (!stepList || !Array.isArray(stepList) || stepList.length === 0) {
|
|
4834
5367
|
throw new Error("Cannot attach runtime tools: dispatch request must include flow.steps");
|
|
4835
5368
|
}
|
|
@@ -4872,9 +5405,9 @@ function attachRuntimeToolsToDispatchRequest(request4, runtimeTools, options = {
|
|
|
4872
5405
|
}
|
|
4873
5406
|
};
|
|
4874
5407
|
return {
|
|
4875
|
-
...
|
|
5408
|
+
...request6,
|
|
4876
5409
|
flow: {
|
|
4877
|
-
...
|
|
5410
|
+
...request6.flow,
|
|
4878
5411
|
// `clonedSteps` is a structural clone of `request.flow.steps` (already
|
|
4879
5412
|
// `FlowStepDefinition[]`); only the prompt step's `config.tools` was
|
|
4880
5413
|
// merged, so every step's `type` discriminant is preserved. The clone is
|
|
@@ -4884,12 +5417,12 @@ function attachRuntimeToolsToDispatchRequest(request4, runtimeTools, options = {
|
|
|
4884
5417
|
}
|
|
4885
5418
|
};
|
|
4886
5419
|
}
|
|
4887
|
-
function applyGeneratedRuntimeToolProposalToDispatchRequest(
|
|
5420
|
+
function applyGeneratedRuntimeToolProposalToDispatchRequest(request6, proposal, options = {}) {
|
|
4888
5421
|
const decision = evaluateGeneratedRuntimeToolProposal(proposal, options.gate);
|
|
4889
5422
|
if (!decision.approved || !decision.tool) {
|
|
4890
|
-
return { decision, request:
|
|
5423
|
+
return { decision, request: request6 };
|
|
4891
5424
|
}
|
|
4892
|
-
const nextRequest = attachRuntimeToolsToDispatchRequest(
|
|
5425
|
+
const nextRequest = attachRuntimeToolsToDispatchRequest(request6, [decision.tool], options.attach);
|
|
4893
5426
|
return {
|
|
4894
5427
|
decision,
|
|
4895
5428
|
request: nextRequest
|
|
@@ -7139,15 +7672,15 @@ var DispatchEndpoint = class {
|
|
|
7139
7672
|
* Attach approved runtime tools to a prompt step in a redispatch request.
|
|
7140
7673
|
* Returns a new request object and does not mutate the original.
|
|
7141
7674
|
*/
|
|
7142
|
-
attachApprovedRuntimeTools(
|
|
7143
|
-
return attachRuntimeToolsToDispatchRequest(
|
|
7675
|
+
attachApprovedRuntimeTools(request6, runtimeTools, options) {
|
|
7676
|
+
return attachRuntimeToolsToDispatchRequest(request6, runtimeTools, options);
|
|
7144
7677
|
}
|
|
7145
7678
|
/**
|
|
7146
7679
|
* Validate a generated runtime tool proposal and attach it to the redispatch
|
|
7147
7680
|
* request if approved, in one call.
|
|
7148
7681
|
*/
|
|
7149
|
-
applyGeneratedRuntimeToolProposal(
|
|
7150
|
-
return applyGeneratedRuntimeToolProposalToDispatchRequest(
|
|
7682
|
+
applyGeneratedRuntimeToolProposal(request6, proposal, options) {
|
|
7683
|
+
return applyGeneratedRuntimeToolProposalToDispatchRequest(request6, proposal, options);
|
|
7151
7684
|
}
|
|
7152
7685
|
};
|
|
7153
7686
|
var ChatEndpoint = class {
|
|
@@ -7699,8 +8232,8 @@ var GENERATED_RUNTIME_TOOL_PROPOSAL_SCHEMA = {
|
|
|
7699
8232
|
},
|
|
7700
8233
|
required: ["name", "description", "toolType", "parametersSchema", "config"]
|
|
7701
8234
|
};
|
|
7702
|
-
function appendRuntimeToolsToAgentRequest(
|
|
7703
|
-
const existing =
|
|
8235
|
+
function appendRuntimeToolsToAgentRequest(request6, runtimeTools) {
|
|
8236
|
+
const existing = request6.tools?.runtimeTools || [];
|
|
7704
8237
|
const existingNames = new Set(existing.map((tool) => tool.name));
|
|
7705
8238
|
const converted = runtimeTools.filter((tool) => !existingNames.has(tool.name)).map((tool) => ({
|
|
7706
8239
|
name: tool.name,
|
|
@@ -7710,9 +8243,9 @@ function appendRuntimeToolsToAgentRequest(request4, runtimeTools) {
|
|
|
7710
8243
|
...tool.config ? { config: tool.config } : {}
|
|
7711
8244
|
}));
|
|
7712
8245
|
return {
|
|
7713
|
-
...
|
|
8246
|
+
...request6,
|
|
7714
8247
|
tools: {
|
|
7715
|
-
...
|
|
8248
|
+
...request6.tools,
|
|
7716
8249
|
runtimeTools: [...existing, ...converted]
|
|
7717
8250
|
}
|
|
7718
8251
|
};
|
|
@@ -7788,21 +8321,21 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7788
8321
|
* Attach approved runtime tools to an agent execute request.
|
|
7789
8322
|
* Returns a new request object and does not mutate the original.
|
|
7790
8323
|
*/
|
|
7791
|
-
attachApprovedRuntimeTools(
|
|
7792
|
-
return appendRuntimeToolsToAgentRequest(
|
|
8324
|
+
attachApprovedRuntimeTools(request6, runtimeTools) {
|
|
8325
|
+
return appendRuntimeToolsToAgentRequest(request6, runtimeTools);
|
|
7793
8326
|
}
|
|
7794
8327
|
/**
|
|
7795
8328
|
* Validate a generated runtime tool proposal and append it to an agent execute
|
|
7796
8329
|
* request if approved, in one call.
|
|
7797
8330
|
*/
|
|
7798
|
-
applyGeneratedRuntimeToolProposal(
|
|
8331
|
+
applyGeneratedRuntimeToolProposal(request6, proposal, options) {
|
|
7799
8332
|
const decision = evaluateGeneratedRuntimeToolProposal(proposal, options);
|
|
7800
8333
|
if (!decision.approved || !decision.tool) {
|
|
7801
|
-
return { decision, request:
|
|
8334
|
+
return { decision, request: request6 };
|
|
7802
8335
|
}
|
|
7803
8336
|
return {
|
|
7804
8337
|
decision,
|
|
7805
|
-
request: appendRuntimeToolsToAgentRequest(
|
|
8338
|
+
request: appendRuntimeToolsToAgentRequest(request6, [decision.tool])
|
|
7806
8339
|
};
|
|
7807
8340
|
}
|
|
7808
8341
|
/**
|
|
@@ -10903,6 +11436,29 @@ var BillingEndpoint = class {
|
|
|
10903
11436
|
return this.client.get("/billing/spend-analytics", params);
|
|
10904
11437
|
}
|
|
10905
11438
|
};
|
|
11439
|
+
var ToolApprovalGrantsEndpoint = class {
|
|
11440
|
+
constructor(client) {
|
|
11441
|
+
this.client = client;
|
|
11442
|
+
}
|
|
11443
|
+
/**
|
|
11444
|
+
* List active remembered tool-approval grants for the authenticated owner,
|
|
11445
|
+
* optionally filtered to a single agent.
|
|
11446
|
+
*/
|
|
11447
|
+
async list(agentId) {
|
|
11448
|
+
const query = agentId ? `?agentId=${encodeURIComponent(agentId)}` : "";
|
|
11449
|
+
const response = await this.client.get(
|
|
11450
|
+
`/tool-approval-grants${query}`
|
|
11451
|
+
);
|
|
11452
|
+
return response.data;
|
|
11453
|
+
}
|
|
11454
|
+
/**
|
|
11455
|
+
* Revoke (soft-delete) a remembered grant so the tool prompts for approval
|
|
11456
|
+
* again on future dispatches.
|
|
11457
|
+
*/
|
|
11458
|
+
async revoke(id) {
|
|
11459
|
+
return this.client.delete(`/tool-approval-grants/${id}`);
|
|
11460
|
+
}
|
|
11461
|
+
};
|
|
10906
11462
|
var AppsEndpoint = class {
|
|
10907
11463
|
constructor(client) {
|
|
10908
11464
|
this.client = client;
|
|
@@ -11000,6 +11556,7 @@ var RuntypeClient2 = class {
|
|
|
11000
11556
|
this.flowVersions = new FlowVersionsEndpoint(this);
|
|
11001
11557
|
this.integrations = new IntegrationsEndpoint(this);
|
|
11002
11558
|
this.billing = new BillingEndpoint(this);
|
|
11559
|
+
this.toolApprovalGrants = new ToolApprovalGrantsEndpoint(this);
|
|
11003
11560
|
}
|
|
11004
11561
|
/**
|
|
11005
11562
|
* Set the API key for authentication
|
|
@@ -11038,7 +11595,7 @@ var RuntypeClient2 = class {
|
|
|
11038
11595
|
clearApiKey() {
|
|
11039
11596
|
delete this.headers.Authorization;
|
|
11040
11597
|
}
|
|
11041
|
-
async runWithLocalTools(
|
|
11598
|
+
async runWithLocalTools(request6, localTools, arg3, arg4) {
|
|
11042
11599
|
const isOptionsObject = (val) => typeof val === "object" && val !== null && "scope" in val;
|
|
11043
11600
|
const callbacks = isOptionsObject(arg3) ? void 0 : arg3;
|
|
11044
11601
|
const options = (isOptionsObject(arg3) ? arg3 : arg4) ?? {};
|
|
@@ -11052,12 +11609,12 @@ var RuntypeClient2 = class {
|
|
|
11052
11609
|
...entry.pageOrigin ? { pageOrigin: entry.pageOrigin } : {}
|
|
11053
11610
|
})) : [];
|
|
11054
11611
|
const modifiedRequest = {
|
|
11055
|
-
...
|
|
11612
|
+
...request6,
|
|
11056
11613
|
...derivedClientTools.length > 0 ? {
|
|
11057
|
-
clientTools: [...
|
|
11614
|
+
clientTools: [...request6.clientTools ?? [], ...derivedClientTools]
|
|
11058
11615
|
} : {},
|
|
11059
11616
|
options: {
|
|
11060
|
-
...
|
|
11617
|
+
...request6.options || {},
|
|
11061
11618
|
streamResponse: isStreaming
|
|
11062
11619
|
}
|
|
11063
11620
|
};
|
|
@@ -11217,6 +11774,30 @@ var RuntypeClient2 = class {
|
|
|
11217
11774
|
});
|
|
11218
11775
|
return transformResponse(response);
|
|
11219
11776
|
}
|
|
11777
|
+
/**
|
|
11778
|
+
* Conditional GET (`ETag` / `If-None-Match`).
|
|
11779
|
+
*
|
|
11780
|
+
* Unlike {@link get}, this does NOT throw on `304` — it surfaces the not-modified
|
|
11781
|
+
* outcome so callers can keep their cached copy. Used by the dashboard's primary
|
|
11782
|
+
* lists to revalidate the canonical first page in a single round trip on both
|
|
11783
|
+
* the changed and unchanged paths. The `304` path returns no body; the `200`
|
|
11784
|
+
* path returns the parsed body plus the server's fresh `ETag`.
|
|
11785
|
+
*/
|
|
11786
|
+
async getConditional(path, params, ifNoneMatch) {
|
|
11787
|
+
const url = this.buildUrl(path, params);
|
|
11788
|
+
const headers = { ...this.headers };
|
|
11789
|
+
if (ifNoneMatch) headers["If-None-Match"] = ifNoneMatch;
|
|
11790
|
+
const response = await this.fetchWithTimeout(url, { method: "GET", headers });
|
|
11791
|
+
const etag = response.headers.get("ETag");
|
|
11792
|
+
if (response.status === 304) {
|
|
11793
|
+
return { notModified: true, etag };
|
|
11794
|
+
}
|
|
11795
|
+
if (!response.ok) {
|
|
11796
|
+
throw await this.createApiError(response);
|
|
11797
|
+
}
|
|
11798
|
+
const data = transformResponse(await response.json());
|
|
11799
|
+
return { notModified: false, etag, data };
|
|
11800
|
+
}
|
|
11220
11801
|
/**
|
|
11221
11802
|
* Generic POST request
|
|
11222
11803
|
*/
|
|
@@ -11335,7 +11916,15 @@ var RuntypeClient2 = class {
|
|
|
11335
11916
|
/**
|
|
11336
11917
|
* Make HTTP request with timeout and error handling
|
|
11337
11918
|
*/
|
|
11338
|
-
|
|
11919
|
+
/**
|
|
11920
|
+
* Run a fetch under the client timeout and return the raw `Response`. Maps a
|
|
11921
|
+
* timeout-driven `AbortError` to a descriptive timeout `Error`; does NOT inspect
|
|
11922
|
+
* status, so callers decide how to treat non-2xx (throw, intercept `304`, etc.).
|
|
11923
|
+
*
|
|
11924
|
+
* `makeRawRequest` keeps its own variant: it additionally composes a
|
|
11925
|
+
* caller-supplied `signal` (user-initiated stream aborts) with the timeout.
|
|
11926
|
+
*/
|
|
11927
|
+
async fetchWithTimeout(url, options) {
|
|
11339
11928
|
const controller = this.timeout === null ? null : new AbortController();
|
|
11340
11929
|
const timeoutId = controller && this.timeout !== null ? setTimeout(() => controller.abort(), this.timeout) : null;
|
|
11341
11930
|
try {
|
|
@@ -11344,17 +11933,7 @@ var RuntypeClient2 = class {
|
|
|
11344
11933
|
...controller ? { signal: controller.signal } : {}
|
|
11345
11934
|
});
|
|
11346
11935
|
if (timeoutId) clearTimeout(timeoutId);
|
|
11347
|
-
|
|
11348
|
-
throw await this.createApiError(response);
|
|
11349
|
-
}
|
|
11350
|
-
if (response.status === 204) {
|
|
11351
|
-
return null;
|
|
11352
|
-
}
|
|
11353
|
-
const contentType = response.headers.get("content-type");
|
|
11354
|
-
if (contentType?.includes("application/json")) {
|
|
11355
|
-
return response.json();
|
|
11356
|
-
}
|
|
11357
|
-
return response.text();
|
|
11936
|
+
return response;
|
|
11358
11937
|
} catch (error) {
|
|
11359
11938
|
if (timeoutId) clearTimeout(timeoutId);
|
|
11360
11939
|
if (timeoutId && error instanceof Error && error.name === "AbortError") {
|
|
@@ -11363,6 +11942,20 @@ var RuntypeClient2 = class {
|
|
|
11363
11942
|
throw error;
|
|
11364
11943
|
}
|
|
11365
11944
|
}
|
|
11945
|
+
async makeRequest(url, options) {
|
|
11946
|
+
const response = await this.fetchWithTimeout(url, options);
|
|
11947
|
+
if (!response.ok) {
|
|
11948
|
+
throw await this.createApiError(response);
|
|
11949
|
+
}
|
|
11950
|
+
if (response.status === 204) {
|
|
11951
|
+
return null;
|
|
11952
|
+
}
|
|
11953
|
+
const contentType = response.headers.get("content-type");
|
|
11954
|
+
if (contentType?.includes("application/json")) {
|
|
11955
|
+
return response.json();
|
|
11956
|
+
}
|
|
11957
|
+
return response.text();
|
|
11958
|
+
}
|
|
11366
11959
|
/**
|
|
11367
11960
|
* Make HTTP request that returns raw Response (for streaming)
|
|
11368
11961
|
*/
|
|
@@ -11495,20 +12088,20 @@ var BatchBuilder = class {
|
|
|
11495
12088
|
if (!this.recordType) {
|
|
11496
12089
|
throw new Error("BatchBuilder: recordType is required. Call .forRecordType(type) first.");
|
|
11497
12090
|
}
|
|
11498
|
-
const
|
|
12091
|
+
const request6 = {
|
|
11499
12092
|
flowId: this.flowId,
|
|
11500
12093
|
recordType: this.recordType
|
|
11501
12094
|
};
|
|
11502
12095
|
if (Object.keys(this.batchOptions).length > 0) {
|
|
11503
|
-
|
|
12096
|
+
request6.options = this.batchOptions;
|
|
11504
12097
|
}
|
|
11505
12098
|
if (this.filterConfig) {
|
|
11506
|
-
|
|
12099
|
+
request6.filter = this.filterConfig;
|
|
11507
12100
|
}
|
|
11508
12101
|
if (this.limitConfig !== void 0) {
|
|
11509
|
-
|
|
12102
|
+
request6.limit = this.limitConfig;
|
|
11510
12103
|
}
|
|
11511
|
-
return
|
|
12104
|
+
return request6;
|
|
11512
12105
|
}
|
|
11513
12106
|
/**
|
|
11514
12107
|
* Execute the batch operation
|
|
@@ -11665,32 +12258,32 @@ var EvalBuilder = class {
|
|
|
11665
12258
|
"EvalBuilder: records are required. Call .forRecordType(type) or .withRecords([...]) first."
|
|
11666
12259
|
);
|
|
11667
12260
|
}
|
|
11668
|
-
const
|
|
12261
|
+
const request6 = {};
|
|
11669
12262
|
if (this.flowId) {
|
|
11670
|
-
|
|
12263
|
+
request6.flowId = this.flowId;
|
|
11671
12264
|
} else if (this.virtualFlow) {
|
|
11672
|
-
|
|
12265
|
+
request6.flow = this.virtualFlow;
|
|
11673
12266
|
}
|
|
11674
12267
|
if (this.recordType) {
|
|
11675
|
-
|
|
12268
|
+
request6.recordType = this.recordType;
|
|
11676
12269
|
} else if (this.inlineRecords) {
|
|
11677
|
-
|
|
12270
|
+
request6.records = this.inlineRecords;
|
|
11678
12271
|
}
|
|
11679
12272
|
if (this.modelOverrides) {
|
|
11680
|
-
|
|
12273
|
+
request6.modelOverrides = this.modelOverrides;
|
|
11681
12274
|
} else if (this.modelConfigs) {
|
|
11682
|
-
|
|
12275
|
+
request6.modelConfigs = this.modelConfigs;
|
|
11683
12276
|
}
|
|
11684
12277
|
if (Object.keys(this.evalOptions).length > 0) {
|
|
11685
|
-
|
|
12278
|
+
request6.options = this.evalOptions;
|
|
11686
12279
|
}
|
|
11687
12280
|
if (this.filterConfig) {
|
|
11688
|
-
|
|
12281
|
+
request6.filter = this.filterConfig;
|
|
11689
12282
|
}
|
|
11690
12283
|
if (this.limitConfig !== void 0) {
|
|
11691
|
-
|
|
12284
|
+
request6.limit = this.limitConfig;
|
|
11692
12285
|
}
|
|
11693
|
-
return
|
|
12286
|
+
return request6;
|
|
11694
12287
|
}
|
|
11695
12288
|
/**
|
|
11696
12289
|
* Execute the evaluation
|
|
@@ -12210,9 +12803,15 @@ var STEP_TYPE_TO_METHOD = {
|
|
|
12210
12803
|
STEP_TYPE_TO_METHOD,
|
|
12211
12804
|
SchedulesEndpoint,
|
|
12212
12805
|
SecretsEndpoint,
|
|
12806
|
+
SkillDriftError,
|
|
12807
|
+
SkillEnsureConflictError,
|
|
12213
12808
|
SkillProposalsNamespace,
|
|
12214
12809
|
SkillsNamespace,
|
|
12810
|
+
SurfaceDriftError,
|
|
12811
|
+
SurfaceEnsureConflictError,
|
|
12215
12812
|
SurfacesEndpoint,
|
|
12813
|
+
SurfacesNamespace,
|
|
12814
|
+
ToolApprovalGrantsEndpoint,
|
|
12216
12815
|
ToolDriftError,
|
|
12217
12816
|
ToolEnsureConflictError,
|
|
12218
12817
|
ToolsEndpoint,
|
|
@@ -12229,6 +12828,8 @@ var STEP_TYPE_TO_METHOD = {
|
|
|
12229
12828
|
computeAgentContentHash,
|
|
12230
12829
|
computeFlowContentHash,
|
|
12231
12830
|
computeProductContentHash,
|
|
12831
|
+
computeSkillContentHash,
|
|
12832
|
+
computeSurfaceContentHash,
|
|
12232
12833
|
computeToolContentHash,
|
|
12233
12834
|
createClient,
|
|
12234
12835
|
createExternalTool,
|
|
@@ -12238,6 +12839,8 @@ var STEP_TYPE_TO_METHOD = {
|
|
|
12238
12839
|
defineFlow,
|
|
12239
12840
|
definePlaybook,
|
|
12240
12841
|
defineProduct,
|
|
12842
|
+
defineSkill,
|
|
12843
|
+
defineSurface,
|
|
12241
12844
|
defineTool,
|
|
12242
12845
|
deployWorkflow,
|
|
12243
12846
|
ensureDefaultWorkflowHooks,
|
|
@@ -12255,6 +12858,8 @@ var STEP_TYPE_TO_METHOD = {
|
|
|
12255
12858
|
normalizeAgentDefinition,
|
|
12256
12859
|
normalizeCandidatePath,
|
|
12257
12860
|
normalizeProductDefinition,
|
|
12861
|
+
normalizeSkillDefinition,
|
|
12862
|
+
normalizeSurfaceDefinition,
|
|
12258
12863
|
normalizeToolDefinition,
|
|
12259
12864
|
parseFinalBuffer,
|
|
12260
12865
|
parseLedgerArtifactRelativePath,
|