@runtypelabs/sdk 4.9.0 → 4.10.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 +1202 -303
- package/dist/index.d.cts +1626 -20
- package/dist/index.d.ts +1626 -20
- package/dist/index.mjs +1117 -242
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3,9 +3,6 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __esm = (fn, res) => function __init() {
|
|
7
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
-
};
|
|
9
6
|
var __export = (target, all) => {
|
|
10
7
|
for (var name in all)
|
|
11
8
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -20,17 +17,96 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
20
17
|
};
|
|
21
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
19
|
|
|
23
|
-
// src/
|
|
24
|
-
var
|
|
25
|
-
__export(
|
|
26
|
-
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AgentDriftError: () => AgentDriftError,
|
|
24
|
+
AgentEnsureConflictError: () => AgentEnsureConflictError,
|
|
25
|
+
AgentVersionsEndpoint: () => AgentVersionsEndpoint,
|
|
26
|
+
AgentsEndpoint: () => AgentsEndpoint,
|
|
27
|
+
AgentsNamespace: () => AgentsNamespace,
|
|
28
|
+
AnalyticsEndpoint: () => AnalyticsEndpoint,
|
|
29
|
+
ApiKeysEndpoint: () => ApiKeysEndpoint,
|
|
30
|
+
AppsEndpoint: () => AppsEndpoint,
|
|
31
|
+
BatchBuilder: () => BatchBuilder,
|
|
32
|
+
BatchesNamespace: () => BatchesNamespace,
|
|
33
|
+
BillingEndpoint: () => BillingEndpoint,
|
|
34
|
+
ChatEndpoint: () => ChatEndpoint,
|
|
35
|
+
ClientBatchBuilder: () => ClientBatchBuilder,
|
|
36
|
+
ClientEvalBuilder: () => ClientEvalBuilder,
|
|
37
|
+
ClientFlowBuilder: () => ClientFlowBuilder,
|
|
38
|
+
ClientTokensEndpoint: () => ClientTokensEndpoint,
|
|
39
|
+
ContextTemplatesEndpoint: () => ContextTemplatesEndpoint,
|
|
40
|
+
ConversationsEndpoint: () => ConversationsEndpoint,
|
|
41
|
+
DispatchEndpoint: () => DispatchEndpoint,
|
|
42
|
+
EvalBuilder: () => EvalBuilder,
|
|
43
|
+
EvalEndpoint: () => EvalEndpoint,
|
|
44
|
+
EvalRunner: () => EvalRunner,
|
|
45
|
+
EvalsNamespace: () => EvalsNamespace,
|
|
46
|
+
FlowBuilder: () => FlowBuilder,
|
|
47
|
+
FlowDriftError: () => FlowDriftError,
|
|
48
|
+
FlowEnsureConflictError: () => FlowEnsureConflictError,
|
|
49
|
+
FlowResult: () => FlowResult,
|
|
50
|
+
FlowStepsEndpoint: () => FlowStepsEndpoint,
|
|
51
|
+
FlowVersionsEndpoint: () => FlowVersionsEndpoint,
|
|
52
|
+
FlowsEndpoint: () => FlowsEndpoint,
|
|
53
|
+
FlowsNamespace: () => FlowsNamespace,
|
|
54
|
+
IntegrationsEndpoint: () => IntegrationsEndpoint,
|
|
55
|
+
LEDGER_ARTIFACT_LINE_PREFIX: () => LEDGER_ARTIFACT_LINE_PREFIX,
|
|
56
|
+
LogsEndpoint: () => LogsEndpoint,
|
|
57
|
+
ModelConfigsEndpoint: () => ModelConfigsEndpoint,
|
|
58
|
+
PromptRunner: () => PromptRunner,
|
|
59
|
+
PromptsEndpoint: () => PromptsEndpoint,
|
|
60
|
+
PromptsNamespace: () => PromptsNamespace,
|
|
61
|
+
ProviderKeysEndpoint: () => ProviderKeysEndpoint,
|
|
62
|
+
RecordsEndpoint: () => RecordsEndpoint,
|
|
63
|
+
Runtype: () => Runtype,
|
|
64
|
+
RuntypeApiError: () => RuntypeApiError,
|
|
65
|
+
RuntypeClient: () => RuntypeClient2,
|
|
66
|
+
RuntypeFlowBuilder: () => RuntypeFlowBuilder,
|
|
67
|
+
STEP_FIELD_REGISTRY: () => STEP_FIELD_REGISTRY,
|
|
68
|
+
STEP_TYPE_TO_METHOD: () => STEP_TYPE_TO_METHOD,
|
|
69
|
+
SchedulesEndpoint: () => SchedulesEndpoint,
|
|
70
|
+
SecretsEndpoint: () => SecretsEndpoint,
|
|
71
|
+
SkillProposalsNamespace: () => SkillProposalsNamespace,
|
|
72
|
+
SkillsNamespace: () => SkillsNamespace,
|
|
73
|
+
SurfacesEndpoint: () => SurfacesEndpoint,
|
|
74
|
+
ToolsEndpoint: () => ToolsEndpoint,
|
|
75
|
+
UsersEndpoint: () => UsersEndpoint,
|
|
76
|
+
applyGeneratedRuntimeToolProposalToDispatchRequest: () => applyGeneratedRuntimeToolProposalToDispatchRequest,
|
|
77
|
+
attachRuntimeToolsToDispatchRequest: () => attachRuntimeToolsToDispatchRequest,
|
|
78
|
+
buildGeneratedRuntimeToolGateOutput: () => buildGeneratedRuntimeToolGateOutput,
|
|
79
|
+
buildLedgerOffloadReference: () => buildLedgerOffloadReference,
|
|
80
|
+
buildSendViewOffloadMarker: () => buildSendViewOffloadMarker,
|
|
81
|
+
computeAgentContentHash: () => computeAgentContentHash,
|
|
82
|
+
computeFlowContentHash: () => computeFlowContentHash,
|
|
83
|
+
createClient: () => createClient,
|
|
84
|
+
createExternalTool: () => createExternalTool,
|
|
85
|
+
defaultWorkflow: () => defaultWorkflow,
|
|
86
|
+
defineAgent: () => defineAgent,
|
|
87
|
+
defineFlow: () => defineFlow,
|
|
88
|
+
deployWorkflow: () => deployWorkflow,
|
|
89
|
+
evaluateGeneratedRuntimeToolProposal: () => evaluateGeneratedRuntimeToolProposal,
|
|
90
|
+
extractDeclaredToolResultChars: () => extractDeclaredToolResultChars,
|
|
91
|
+
gameWorkflow: () => gameWorkflow,
|
|
92
|
+
getDefaultPlanPath: () => getDefaultPlanPath,
|
|
93
|
+
getLikelySupportingCandidatePaths: () => getLikelySupportingCandidatePaths,
|
|
94
|
+
isDiscoveryToolName: () => isDiscoveryToolName,
|
|
95
|
+
isMarathonArtifactPath: () => isMarathonArtifactPath,
|
|
96
|
+
isPreservationSensitiveTask: () => isPreservationSensitiveTask,
|
|
97
|
+
normalizeAgentDefinition: () => normalizeAgentDefinition,
|
|
98
|
+
normalizeCandidatePath: () => normalizeCandidatePath,
|
|
27
99
|
parseFinalBuffer: () => parseFinalBuffer,
|
|
100
|
+
parseLedgerArtifactRelativePath: () => parseLedgerArtifactRelativePath,
|
|
101
|
+
parseOffloadedOutputId: () => parseOffloadedOutputId,
|
|
28
102
|
parseSSEChunk: () => parseSSEChunk,
|
|
29
103
|
processStream: () => processStream,
|
|
30
|
-
|
|
31
|
-
stepDisplayName: () => stepDisplayName,
|
|
104
|
+
sanitizeTaskSlug: () => sanitizeTaskSlug,
|
|
32
105
|
streamEvents: () => streamEvents
|
|
33
106
|
});
|
|
107
|
+
module.exports = __toCommonJS(index_exports);
|
|
108
|
+
|
|
109
|
+
// src/stream-utils.ts
|
|
34
110
|
function parseSSEChunk(chunk, buffer) {
|
|
35
111
|
buffer += chunk;
|
|
36
112
|
const lines = buffer.split("\n");
|
|
@@ -280,86 +356,8 @@ async function* streamEvents(response) {
|
|
|
280
356
|
reader.releaseLock();
|
|
281
357
|
}
|
|
282
358
|
}
|
|
283
|
-
var init_stream_utils = __esm({
|
|
284
|
-
"src/stream-utils.ts"() {
|
|
285
|
-
"use strict";
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
// src/index.ts
|
|
290
|
-
var index_exports = {};
|
|
291
|
-
__export(index_exports, {
|
|
292
|
-
AgentVersionsEndpoint: () => AgentVersionsEndpoint,
|
|
293
|
-
AgentsEndpoint: () => AgentsEndpoint,
|
|
294
|
-
AnalyticsEndpoint: () => AnalyticsEndpoint,
|
|
295
|
-
ApiKeysEndpoint: () => ApiKeysEndpoint,
|
|
296
|
-
BatchBuilder: () => BatchBuilder,
|
|
297
|
-
BatchesNamespace: () => BatchesNamespace,
|
|
298
|
-
BillingEndpoint: () => BillingEndpoint,
|
|
299
|
-
ChatEndpoint: () => ChatEndpoint,
|
|
300
|
-
ClientBatchBuilder: () => ClientBatchBuilder,
|
|
301
|
-
ClientEvalBuilder: () => ClientEvalBuilder,
|
|
302
|
-
ClientFlowBuilder: () => ClientFlowBuilder,
|
|
303
|
-
ClientTokensEndpoint: () => ClientTokensEndpoint,
|
|
304
|
-
ContextTemplatesEndpoint: () => ContextTemplatesEndpoint,
|
|
305
|
-
ConversationsEndpoint: () => ConversationsEndpoint,
|
|
306
|
-
DispatchEndpoint: () => DispatchEndpoint,
|
|
307
|
-
EvalBuilder: () => EvalBuilder,
|
|
308
|
-
EvalEndpoint: () => EvalEndpoint,
|
|
309
|
-
EvalRunner: () => EvalRunner,
|
|
310
|
-
EvalsNamespace: () => EvalsNamespace,
|
|
311
|
-
FlowBuilder: () => FlowBuilder,
|
|
312
|
-
FlowResult: () => FlowResult,
|
|
313
|
-
FlowStepsEndpoint: () => FlowStepsEndpoint,
|
|
314
|
-
FlowVersionsEndpoint: () => FlowVersionsEndpoint,
|
|
315
|
-
FlowsEndpoint: () => FlowsEndpoint,
|
|
316
|
-
FlowsNamespace: () => FlowsNamespace,
|
|
317
|
-
IntegrationsEndpoint: () => IntegrationsEndpoint,
|
|
318
|
-
LogsEndpoint: () => LogsEndpoint,
|
|
319
|
-
ModelConfigsEndpoint: () => ModelConfigsEndpoint,
|
|
320
|
-
PromptRunner: () => PromptRunner,
|
|
321
|
-
PromptsEndpoint: () => PromptsEndpoint,
|
|
322
|
-
PromptsNamespace: () => PromptsNamespace,
|
|
323
|
-
ProviderKeysEndpoint: () => ProviderKeysEndpoint,
|
|
324
|
-
RecordsEndpoint: () => RecordsEndpoint,
|
|
325
|
-
Runtype: () => Runtype,
|
|
326
|
-
RuntypeApiError: () => RuntypeApiError,
|
|
327
|
-
RuntypeClient: () => RuntypeClient2,
|
|
328
|
-
RuntypeFlowBuilder: () => RuntypeFlowBuilder,
|
|
329
|
-
STEP_FIELD_REGISTRY: () => STEP_FIELD_REGISTRY,
|
|
330
|
-
STEP_TYPE_TO_METHOD: () => STEP_TYPE_TO_METHOD,
|
|
331
|
-
SchedulesEndpoint: () => SchedulesEndpoint,
|
|
332
|
-
SecretsEndpoint: () => SecretsEndpoint,
|
|
333
|
-
SkillProposalsNamespace: () => SkillProposalsNamespace,
|
|
334
|
-
SkillsNamespace: () => SkillsNamespace,
|
|
335
|
-
SurfacesEndpoint: () => SurfacesEndpoint,
|
|
336
|
-
ToolsEndpoint: () => ToolsEndpoint,
|
|
337
|
-
UsersEndpoint: () => UsersEndpoint,
|
|
338
|
-
applyGeneratedRuntimeToolProposalToDispatchRequest: () => applyGeneratedRuntimeToolProposalToDispatchRequest,
|
|
339
|
-
attachRuntimeToolsToDispatchRequest: () => attachRuntimeToolsToDispatchRequest,
|
|
340
|
-
buildGeneratedRuntimeToolGateOutput: () => buildGeneratedRuntimeToolGateOutput,
|
|
341
|
-
createClient: () => createClient,
|
|
342
|
-
createExternalTool: () => createExternalTool,
|
|
343
|
-
defaultWorkflow: () => defaultWorkflow,
|
|
344
|
-
deployWorkflow: () => deployWorkflow,
|
|
345
|
-
evaluateGeneratedRuntimeToolProposal: () => evaluateGeneratedRuntimeToolProposal,
|
|
346
|
-
gameWorkflow: () => gameWorkflow,
|
|
347
|
-
getDefaultPlanPath: () => getDefaultPlanPath,
|
|
348
|
-
getLikelySupportingCandidatePaths: () => getLikelySupportingCandidatePaths,
|
|
349
|
-
isDiscoveryToolName: () => isDiscoveryToolName,
|
|
350
|
-
isMarathonArtifactPath: () => isMarathonArtifactPath,
|
|
351
|
-
isPreservationSensitiveTask: () => isPreservationSensitiveTask,
|
|
352
|
-
normalizeCandidatePath: () => normalizeCandidatePath,
|
|
353
|
-
parseFinalBuffer: () => parseFinalBuffer,
|
|
354
|
-
parseSSEChunk: () => parseSSEChunk,
|
|
355
|
-
processStream: () => processStream,
|
|
356
|
-
sanitizeTaskSlug: () => sanitizeTaskSlug,
|
|
357
|
-
streamEvents: () => streamEvents
|
|
358
|
-
});
|
|
359
|
-
module.exports = __toCommonJS(index_exports);
|
|
360
359
|
|
|
361
360
|
// src/flow-result.ts
|
|
362
|
-
init_stream_utils();
|
|
363
361
|
var FlowResult = class {
|
|
364
362
|
constructor(response, summary) {
|
|
365
363
|
this.consumed = false;
|
|
@@ -495,7 +493,6 @@ var FlowResult = class {
|
|
|
495
493
|
};
|
|
496
494
|
|
|
497
495
|
// src/flow-builder.ts
|
|
498
|
-
init_stream_utils();
|
|
499
496
|
async function validateInlineFlow(client, args, savedFlowHint) {
|
|
500
497
|
if (args.existingFlowId) {
|
|
501
498
|
throw new Error(
|
|
@@ -1205,20 +1202,20 @@ var FlowBuilder = class {
|
|
|
1205
1202
|
*/
|
|
1206
1203
|
build() {
|
|
1207
1204
|
const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
|
|
1208
|
-
const
|
|
1205
|
+
const request2 = { flow };
|
|
1209
1206
|
if (this.recordConfig) {
|
|
1210
|
-
|
|
1207
|
+
request2.record = this.recordConfig;
|
|
1211
1208
|
}
|
|
1212
1209
|
if (this.messagesConfig) {
|
|
1213
|
-
|
|
1210
|
+
request2.messages = this.messagesConfig;
|
|
1214
1211
|
}
|
|
1215
1212
|
if (this.inputsConfig) {
|
|
1216
|
-
|
|
1213
|
+
request2.inputs = this.inputsConfig;
|
|
1217
1214
|
}
|
|
1218
1215
|
if (Object.keys(this.optionsConfig).length > 0) {
|
|
1219
|
-
|
|
1216
|
+
request2.options = this.optionsConfig;
|
|
1220
1217
|
}
|
|
1221
|
-
return
|
|
1218
|
+
return request2;
|
|
1222
1219
|
}
|
|
1223
1220
|
/**
|
|
1224
1221
|
* Validate this prospective flow against the public validation endpoint
|
|
@@ -1455,22 +1452,22 @@ function resolveBatchExecutionId(pausedTools) {
|
|
|
1455
1452
|
return "";
|
|
1456
1453
|
}
|
|
1457
1454
|
|
|
1458
|
-
// src/flows-
|
|
1459
|
-
function
|
|
1455
|
+
// src/flows-ensure.ts
|
|
1456
|
+
function isPlainObject(value) {
|
|
1460
1457
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1461
1458
|
}
|
|
1462
|
-
function
|
|
1463
|
-
if (!
|
|
1459
|
+
function normalizeConfigForHash(config) {
|
|
1460
|
+
if (!isPlainObject(config)) return {};
|
|
1464
1461
|
const normalized = {};
|
|
1465
1462
|
for (const key of Object.keys(config).sort()) {
|
|
1466
1463
|
const value = config[key];
|
|
1467
1464
|
if (value === void 0) continue;
|
|
1468
1465
|
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
1469
|
-
normalized[key] =
|
|
1466
|
+
normalized[key] = normalizeConfigForHash(value);
|
|
1470
1467
|
} else if (Array.isArray(value)) {
|
|
1471
1468
|
normalized[key] = value.map((item) => {
|
|
1472
1469
|
if (item !== null && typeof item === "object" && !Array.isArray(item)) {
|
|
1473
|
-
return
|
|
1470
|
+
return normalizeConfigForHash(item);
|
|
1474
1471
|
}
|
|
1475
1472
|
return item;
|
|
1476
1473
|
});
|
|
@@ -1481,28 +1478,249 @@ function normalizeConfig(config) {
|
|
|
1481
1478
|
return normalized;
|
|
1482
1479
|
}
|
|
1483
1480
|
function normalizeStepForHash(step) {
|
|
1484
|
-
const stepObj =
|
|
1481
|
+
const stepObj = isPlainObject(step) ? step : {};
|
|
1485
1482
|
return {
|
|
1486
1483
|
type: typeof stepObj.type === "string" ? stepObj.type : "",
|
|
1487
1484
|
name: typeof stepObj.name === "string" ? stepObj.name : "",
|
|
1488
1485
|
enabled: stepObj.enabled !== false,
|
|
1489
1486
|
...typeof stepObj.when === "string" ? { when: stepObj.when } : {},
|
|
1490
|
-
config:
|
|
1487
|
+
config: normalizeConfigForHash(stepObj.config),
|
|
1491
1488
|
order: typeof stepObj.order === "number" ? stepObj.order : 0
|
|
1492
1489
|
};
|
|
1493
1490
|
}
|
|
1494
1491
|
async function computeFlowContentHash(steps) {
|
|
1495
1492
|
const normalized = [...steps].sort((a, b) => {
|
|
1496
|
-
const orderA =
|
|
1497
|
-
const orderB =
|
|
1493
|
+
const orderA = isPlainObject(a) && typeof a.order === "number" ? a.order : 0;
|
|
1494
|
+
const orderB = isPlainObject(b) && typeof b.order === "number" ? b.order : 0;
|
|
1498
1495
|
return orderA - orderB;
|
|
1499
1496
|
}).map(normalizeStepForHash);
|
|
1500
1497
|
const serialized = JSON.stringify(normalized);
|
|
1501
1498
|
const encoded = new TextEncoder().encode(serialized);
|
|
1502
1499
|
const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
|
|
1503
|
-
|
|
1504
|
-
return Array.from(hashArray).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1500
|
+
return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1505
1501
|
}
|
|
1502
|
+
var DEFINE_FLOW_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "steps"]);
|
|
1503
|
+
var DEFINE_FLOW_STEP_KEYS = /* @__PURE__ */ new Set([
|
|
1504
|
+
"type",
|
|
1505
|
+
"name",
|
|
1506
|
+
"order",
|
|
1507
|
+
"enabled",
|
|
1508
|
+
"when",
|
|
1509
|
+
"config"
|
|
1510
|
+
]);
|
|
1511
|
+
function collectStepNonPortableToolRefs(config, path) {
|
|
1512
|
+
const found = [];
|
|
1513
|
+
const tools = config.tools;
|
|
1514
|
+
const isAccountScoped = (ref) => typeof ref === "string" && ref.startsWith("tool_");
|
|
1515
|
+
const scanArray = (value, subPath) => {
|
|
1516
|
+
if (!Array.isArray(value)) return;
|
|
1517
|
+
value.forEach((ref, i) => {
|
|
1518
|
+
if (isAccountScoped(ref)) found.push(`${subPath}[${i}]`);
|
|
1519
|
+
});
|
|
1520
|
+
};
|
|
1521
|
+
const scanKeys = (value, subPath) => {
|
|
1522
|
+
if (!isPlainObject(value)) return;
|
|
1523
|
+
for (const key of Object.keys(value)) {
|
|
1524
|
+
if (isAccountScoped(key)) found.push(`${subPath}.${key}`);
|
|
1525
|
+
}
|
|
1526
|
+
};
|
|
1527
|
+
if (isPlainObject(tools)) {
|
|
1528
|
+
scanArray(tools.toolIds, `${path}.tools.toolIds`);
|
|
1529
|
+
scanKeys(tools.toolConfigs, `${path}.tools.toolConfigs`);
|
|
1530
|
+
scanKeys(tools.perToolLimits, `${path}.tools.perToolLimits`);
|
|
1531
|
+
if (isPlainObject(tools.approval)) {
|
|
1532
|
+
scanArray(tools.approval.require, `${path}.tools.approval.require`);
|
|
1533
|
+
}
|
|
1534
|
+
if (isPlainObject(tools.subagentConfig)) {
|
|
1535
|
+
scanArray(tools.subagentConfig.toolPool, `${path}.tools.subagentConfig.toolPool`);
|
|
1536
|
+
}
|
|
1537
|
+
if (isPlainObject(tools.codeModeConfig)) {
|
|
1538
|
+
scanArray(tools.codeModeConfig.toolPool, `${path}.tools.codeModeConfig.toolPool`);
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
for (const branch of ["trueSteps", "falseSteps"]) {
|
|
1542
|
+
const nested = config[branch];
|
|
1543
|
+
if (!Array.isArray(nested)) continue;
|
|
1544
|
+
nested.forEach((nestedStep, i) => {
|
|
1545
|
+
if (isPlainObject(nestedStep) && isPlainObject(nestedStep.config)) {
|
|
1546
|
+
found.push(
|
|
1547
|
+
...collectStepNonPortableToolRefs(
|
|
1548
|
+
nestedStep.config,
|
|
1549
|
+
`${path}.${branch}[${i}].config`
|
|
1550
|
+
)
|
|
1551
|
+
);
|
|
1552
|
+
}
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
return found;
|
|
1556
|
+
}
|
|
1557
|
+
function defineFlow(input) {
|
|
1558
|
+
if (!input || typeof input !== "object") {
|
|
1559
|
+
throw new Error("defineFlow requires a definition object");
|
|
1560
|
+
}
|
|
1561
|
+
if (typeof input.name !== "string" || input.name.length === 0) {
|
|
1562
|
+
throw new Error('defineFlow requires a non-empty string "name"');
|
|
1563
|
+
}
|
|
1564
|
+
const unknownKeys = Object.keys(input).filter((key) => !DEFINE_FLOW_TOP_LEVEL_KEYS.has(key));
|
|
1565
|
+
if (unknownKeys.length > 0) {
|
|
1566
|
+
throw new Error(
|
|
1567
|
+
`defineFlow: unknown field(s): ${unknownKeys.join(", ")}. Allowed fields are name and steps. (Description is not part of the v1 ensure surface.)`
|
|
1568
|
+
);
|
|
1569
|
+
}
|
|
1570
|
+
if (!Array.isArray(input.steps) || input.steps.length === 0) {
|
|
1571
|
+
throw new Error('defineFlow requires a non-empty "steps" array');
|
|
1572
|
+
}
|
|
1573
|
+
const steps = input.steps.map((step, index) => {
|
|
1574
|
+
if (!isPlainObject(step)) {
|
|
1575
|
+
throw new Error(`defineFlow: steps[${index}] must be an object`);
|
|
1576
|
+
}
|
|
1577
|
+
if (typeof step.type !== "string" || step.type.length === 0) {
|
|
1578
|
+
throw new Error(`defineFlow: steps[${index}] requires a non-empty string "type"`);
|
|
1579
|
+
}
|
|
1580
|
+
if (typeof step.name !== "string" || step.name.length === 0) {
|
|
1581
|
+
throw new Error(`defineFlow: steps[${index}] requires a non-empty string "name"`);
|
|
1582
|
+
}
|
|
1583
|
+
const unknownStepKeys = Object.keys(step).filter((key) => !DEFINE_FLOW_STEP_KEYS.has(key));
|
|
1584
|
+
if (unknownStepKeys.length > 0) {
|
|
1585
|
+
throw new Error(
|
|
1586
|
+
`defineFlow: steps[${index}] has unknown field(s): ${unknownStepKeys.join(", ")}. Allowed step fields are type, name, order, enabled, when, config. (Step ids are server artifacts and not part of a portable definition.)`
|
|
1587
|
+
);
|
|
1588
|
+
}
|
|
1589
|
+
const config = isPlainObject(step.config) ? step.config : void 0;
|
|
1590
|
+
if (config) {
|
|
1591
|
+
const nonPortable = collectStepNonPortableToolRefs(config, `steps[${index}].config`);
|
|
1592
|
+
if (nonPortable.length > 0) {
|
|
1593
|
+
throw new Error(
|
|
1594
|
+
`defineFlow: account-scoped tool reference(s) at ${nonPortable.join(", ")}. Definitions must be environment-portable \u2014 tool_\u2026 IDs belong to one account/environment. Use builtin:/platform:/mcp: references instead. Name-based resolution of saved tools is a planned follow-up.`
|
|
1595
|
+
);
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
return {
|
|
1599
|
+
type: step.type,
|
|
1600
|
+
name: step.name,
|
|
1601
|
+
// Explicit 1-based order (the flow builder's convention) so the local
|
|
1602
|
+
// probe hash agrees with the server's persisted step order.
|
|
1603
|
+
order: typeof step.order === "number" ? step.order : index + 1,
|
|
1604
|
+
...step.enabled !== void 0 ? { enabled: step.enabled } : {},
|
|
1605
|
+
...typeof step.when === "string" ? { when: step.when } : {},
|
|
1606
|
+
...config ? { config } : {}
|
|
1607
|
+
};
|
|
1608
|
+
});
|
|
1609
|
+
return { name: input.name, steps };
|
|
1610
|
+
}
|
|
1611
|
+
var FlowEnsureConflictError = class extends Error {
|
|
1612
|
+
constructor(body) {
|
|
1613
|
+
super(body.error ?? `Flow ensure conflict: ${body.code}`);
|
|
1614
|
+
this.name = "FlowEnsureConflictError";
|
|
1615
|
+
this.code = body.code;
|
|
1616
|
+
this.lastModifiedSource = body.lastModifiedSource;
|
|
1617
|
+
this.modifiedAt = body.modifiedAt;
|
|
1618
|
+
this.currentHash = body.currentHash;
|
|
1619
|
+
}
|
|
1620
|
+
};
|
|
1621
|
+
var FlowDriftError = class extends Error {
|
|
1622
|
+
constructor(plan) {
|
|
1623
|
+
super(
|
|
1624
|
+
`Flow "${plan.flowId ?? "definition"}" drifted: plan is '${plan.changes}' (changed: ${plan.changedKeys.join(", ") || "n/a"}). Run client.flows.pull(name) to absorb the remote edit into your repo, or re-run ensure to converge.`
|
|
1625
|
+
);
|
|
1626
|
+
this.name = "FlowDriftError";
|
|
1627
|
+
this.plan = plan;
|
|
1628
|
+
}
|
|
1629
|
+
};
|
|
1630
|
+
function parseRequestError(err) {
|
|
1631
|
+
if (!(err instanceof Error)) return { status: null, body: null };
|
|
1632
|
+
const match = err.message.match(/^API request failed: (\d{3}) .*? - ([\s\S]*)$/);
|
|
1633
|
+
if (!match) return { status: null, body: null };
|
|
1634
|
+
try {
|
|
1635
|
+
return { status: Number(match[1]), body: JSON.parse(match[2]) };
|
|
1636
|
+
} catch {
|
|
1637
|
+
return { status: Number(match[1]), body: null };
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
function toConflictError(err) {
|
|
1641
|
+
const { status, body } = parseRequestError(err);
|
|
1642
|
+
if (status !== 409 || !isPlainObject(body)) return null;
|
|
1643
|
+
const code = body.code;
|
|
1644
|
+
if (code !== "external_modification" && code !== "remote_changed") return null;
|
|
1645
|
+
return new FlowEnsureConflictError(
|
|
1646
|
+
body
|
|
1647
|
+
);
|
|
1648
|
+
}
|
|
1649
|
+
var serverHashMemo = /* @__PURE__ */ new WeakMap();
|
|
1650
|
+
function memoFor(client) {
|
|
1651
|
+
let memo = serverHashMemo.get(client);
|
|
1652
|
+
if (!memo) {
|
|
1653
|
+
memo = /* @__PURE__ */ new Map();
|
|
1654
|
+
serverHashMemo.set(client, memo);
|
|
1655
|
+
}
|
|
1656
|
+
return memo;
|
|
1657
|
+
}
|
|
1658
|
+
function memoize(memo, memoKey, result) {
|
|
1659
|
+
if (result.result !== "plan") memo.set(memoKey, result.contentHash);
|
|
1660
|
+
}
|
|
1661
|
+
async function request(client, body) {
|
|
1662
|
+
try {
|
|
1663
|
+
return await client.post(
|
|
1664
|
+
"/flows/ensure",
|
|
1665
|
+
body
|
|
1666
|
+
);
|
|
1667
|
+
} catch (err) {
|
|
1668
|
+
const conflict = toConflictError(err);
|
|
1669
|
+
if (conflict) throw conflict;
|
|
1670
|
+
throw err;
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
async function ensureFlow(client, definition, options = {}) {
|
|
1674
|
+
const { dryRun, onConflict, release, expectedRemoteHash, expectNoChanges } = options;
|
|
1675
|
+
const passthrough = {
|
|
1676
|
+
...onConflict ? { onConflict } : {},
|
|
1677
|
+
...release ? { release } : {},
|
|
1678
|
+
...expectedRemoteHash ? { expectedRemoteHash } : {}
|
|
1679
|
+
};
|
|
1680
|
+
if (dryRun || expectNoChanges) {
|
|
1681
|
+
const plan = await request(client, {
|
|
1682
|
+
name: definition.name,
|
|
1683
|
+
definition,
|
|
1684
|
+
dryRun: true,
|
|
1685
|
+
...passthrough
|
|
1686
|
+
});
|
|
1687
|
+
if (plan.result !== "plan") {
|
|
1688
|
+
throw new Error(`Expected a plan result from dryRun, got '${plan.result}'`);
|
|
1689
|
+
}
|
|
1690
|
+
if (expectNoChanges && plan.changes !== "none") {
|
|
1691
|
+
throw new FlowDriftError(plan);
|
|
1692
|
+
}
|
|
1693
|
+
return plan;
|
|
1694
|
+
}
|
|
1695
|
+
const memo = memoFor(client);
|
|
1696
|
+
const localHash = await computeFlowContentHash(definition.steps);
|
|
1697
|
+
const memoKey = `${definition.name} ${localHash}`;
|
|
1698
|
+
const contentHash = memo.get(memoKey) ?? localHash;
|
|
1699
|
+
const probe = await request(client, {
|
|
1700
|
+
name: definition.name,
|
|
1701
|
+
contentHash,
|
|
1702
|
+
...passthrough
|
|
1703
|
+
});
|
|
1704
|
+
if (probe.result !== "definitionRequired") {
|
|
1705
|
+
memoize(memo, memoKey, probe);
|
|
1706
|
+
return probe;
|
|
1707
|
+
}
|
|
1708
|
+
const converged = await request(client, {
|
|
1709
|
+
name: definition.name,
|
|
1710
|
+
definition,
|
|
1711
|
+
...passthrough
|
|
1712
|
+
});
|
|
1713
|
+
if (converged.result === "definitionRequired") {
|
|
1714
|
+
throw new Error("Server reported definitionRequired for a full-definition request");
|
|
1715
|
+
}
|
|
1716
|
+
memoize(memo, memoKey, converged);
|
|
1717
|
+
return converged;
|
|
1718
|
+
}
|
|
1719
|
+
async function pullFlow(client, name) {
|
|
1720
|
+
return client.get("/flows/pull", { name });
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
// src/flows-namespace.ts
|
|
1506
1724
|
var FlowsNamespace = class {
|
|
1507
1725
|
constructor(getClient) {
|
|
1508
1726
|
this.getClient = getClient;
|
|
@@ -1510,8 +1728,11 @@ var FlowsNamespace = class {
|
|
|
1510
1728
|
/**
|
|
1511
1729
|
* Create or update a flow by name (upsert mode)
|
|
1512
1730
|
*
|
|
1513
|
-
* The recommended pattern for code-first flow management
|
|
1514
|
-
*
|
|
1731
|
+
* The recommended pattern for code-first flow management when you want to
|
|
1732
|
+
* save AND run in one dispatch. For a deploy-time, non-executing converge
|
|
1733
|
+
* (CI/CD config-as-code), use {@link ensure} instead — upsert and ensure
|
|
1734
|
+
* are siblings, not versions of each other: upsert is the runtime verb
|
|
1735
|
+
* (save-and-run), ensure is the deploy verb (converge only).
|
|
1515
1736
|
*
|
|
1516
1737
|
* @example
|
|
1517
1738
|
* ```typescript
|
|
@@ -1526,6 +1747,33 @@ var FlowsNamespace = class {
|
|
|
1526
1747
|
upsert(config) {
|
|
1527
1748
|
return new RuntypeFlowBuilder(this.getClient, "upsert", config);
|
|
1528
1749
|
}
|
|
1750
|
+
/**
|
|
1751
|
+
* Idempotently converge a `defineFlow` definition onto the platform —
|
|
1752
|
+
* the deploy-time, non-executing sibling of {@link upsert}. Hash-first:
|
|
1753
|
+
* the steady state is one tiny probe request. Creates an immutable version
|
|
1754
|
+
* snapshot on every change; never deletes; never executes the flow.
|
|
1755
|
+
*
|
|
1756
|
+
* @example
|
|
1757
|
+
* ```typescript
|
|
1758
|
+
* const def = defineFlow({ name: 'Onboarding Digest', steps: [...] })
|
|
1759
|
+
*
|
|
1760
|
+
* // Converge (CI/deploy).
|
|
1761
|
+
* const result = await Runtype.flows.ensure(def)
|
|
1762
|
+
*
|
|
1763
|
+
* // PR drift gate.
|
|
1764
|
+
* await Runtype.flows.ensure(def, { expectNoChanges: true })
|
|
1765
|
+
* ```
|
|
1766
|
+
*/
|
|
1767
|
+
async ensure(definition, options = {}) {
|
|
1768
|
+
return ensureFlow(this.getClient(), definition, options);
|
|
1769
|
+
}
|
|
1770
|
+
/**
|
|
1771
|
+
* Pull the canonical definition + provenance for a flow by name — the
|
|
1772
|
+
* absorb-drift direction of the ensure protocol.
|
|
1773
|
+
*/
|
|
1774
|
+
async pull(name) {
|
|
1775
|
+
return pullFlow(this.getClient(), name);
|
|
1776
|
+
}
|
|
1529
1777
|
/**
|
|
1530
1778
|
* Create a virtual flow (one-off, not saved)
|
|
1531
1779
|
*
|
|
@@ -2211,9 +2459,8 @@ var RuntypeFlowBuilder = class {
|
|
|
2211
2459
|
onFlowComplete: (event) => callbacks?.onFlowComplete?.(event),
|
|
2212
2460
|
onError: (error) => callbacks?.onError?.(error)
|
|
2213
2461
|
};
|
|
2214
|
-
const { streamEvents: streamEvents2, stepDeltaText: stepDeltaText2, stepDisplayName: stepDisplayName2, flowErrorMessage: flowErrorMessage2 } = await Promise.resolve().then(() => (init_stream_utils(), stream_utils_exports));
|
|
2215
2462
|
try {
|
|
2216
|
-
for await (const event of
|
|
2463
|
+
for await (const event of streamEvents(response)) {
|
|
2217
2464
|
collectLocalToolAwait(pausedTools, event);
|
|
2218
2465
|
switch (event.type) {
|
|
2219
2466
|
case "flow_start":
|
|
@@ -2223,10 +2470,10 @@ var RuntypeFlowBuilder = class {
|
|
|
2223
2470
|
wrappedCallbacks.onStepStart?.(event);
|
|
2224
2471
|
break;
|
|
2225
2472
|
case "step_delta":
|
|
2226
|
-
wrappedCallbacks.onStepDelta?.(
|
|
2473
|
+
wrappedCallbacks.onStepDelta?.(stepDeltaText(event), event);
|
|
2227
2474
|
break;
|
|
2228
2475
|
case "step_complete": {
|
|
2229
|
-
accumulatedSummary.results?.set(
|
|
2476
|
+
accumulatedSummary.results?.set(stepDisplayName(event), event.result);
|
|
2230
2477
|
wrappedCallbacks.onStepComplete?.(event.result, event);
|
|
2231
2478
|
break;
|
|
2232
2479
|
}
|
|
@@ -2234,7 +2481,7 @@ var RuntypeFlowBuilder = class {
|
|
|
2234
2481
|
wrappedCallbacks.onFlowComplete?.(event);
|
|
2235
2482
|
break;
|
|
2236
2483
|
case "flow_error":
|
|
2237
|
-
wrappedCallbacks.onError?.(new Error(
|
|
2484
|
+
wrappedCallbacks.onError?.(new Error(flowErrorMessage(event)));
|
|
2238
2485
|
break;
|
|
2239
2486
|
}
|
|
2240
2487
|
}
|
|
@@ -2309,7 +2556,8 @@ var RuntypeFlowBuilder = class {
|
|
|
2309
2556
|
return [toolName, await localTools[toolName](parameters)];
|
|
2310
2557
|
} catch (error) {
|
|
2311
2558
|
throw new Error(
|
|
2312
|
-
`Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}
|
|
2559
|
+
`Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`,
|
|
2560
|
+
{ cause: error }
|
|
2313
2561
|
);
|
|
2314
2562
|
}
|
|
2315
2563
|
})
|
|
@@ -2342,15 +2590,15 @@ var RuntypeFlowBuilder = class {
|
|
|
2342
2590
|
build() {
|
|
2343
2591
|
const flowMode = this.mode === "existing" ? "existing" : this.mode;
|
|
2344
2592
|
const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
|
|
2345
|
-
const
|
|
2593
|
+
const request2 = { flow };
|
|
2346
2594
|
if (this.recordConfig) {
|
|
2347
|
-
|
|
2595
|
+
request2.record = this.recordConfig;
|
|
2348
2596
|
}
|
|
2349
2597
|
if (this.messagesConfig) {
|
|
2350
|
-
|
|
2598
|
+
request2.messages = this.messagesConfig;
|
|
2351
2599
|
}
|
|
2352
2600
|
if (this.inputsConfig) {
|
|
2353
|
-
|
|
2601
|
+
request2.inputs = this.inputsConfig;
|
|
2354
2602
|
}
|
|
2355
2603
|
const options = {
|
|
2356
2604
|
flowMode,
|
|
@@ -2368,8 +2616,8 @@ var RuntypeFlowBuilder = class {
|
|
|
2368
2616
|
if (this.mode === "upsert" && Object.keys(this.upsertOptions).length > 0) {
|
|
2369
2617
|
options.upsertOptions = this.upsertOptions;
|
|
2370
2618
|
}
|
|
2371
|
-
|
|
2372
|
-
return
|
|
2619
|
+
request2.options = options;
|
|
2620
|
+
return request2;
|
|
2373
2621
|
}
|
|
2374
2622
|
/**
|
|
2375
2623
|
* Validate this prospective flow against the public validation endpoint
|
|
@@ -3029,6 +3277,8 @@ var SkillsNamespace = class {
|
|
|
3029
3277
|
}
|
|
3030
3278
|
/**
|
|
3031
3279
|
* List skills for the authenticated owner, optionally filtered by status.
|
|
3280
|
+
* Returns just the rows (one page); pass `cursor`/`limit` to page, or use
|
|
3281
|
+
* {@link listPage} when you need the pagination envelope.
|
|
3032
3282
|
*
|
|
3033
3283
|
* @example
|
|
3034
3284
|
* ```typescript
|
|
@@ -3036,10 +3286,23 @@ var SkillsNamespace = class {
|
|
|
3036
3286
|
* ```
|
|
3037
3287
|
*/
|
|
3038
3288
|
async list(params) {
|
|
3039
|
-
const
|
|
3040
|
-
const res = await client.get("/skills", params);
|
|
3289
|
+
const res = await this.listPage(params);
|
|
3041
3290
|
return res.data;
|
|
3042
3291
|
}
|
|
3292
|
+
/**
|
|
3293
|
+
* List skills with the cursor-pagination envelope (mirrors the tools list
|
|
3294
|
+
* shape: `{ data, pagination }`).
|
|
3295
|
+
*
|
|
3296
|
+
* @example
|
|
3297
|
+
* ```typescript
|
|
3298
|
+
* const page1 = await Runtype.skills.listPage({ limit: 50, includeCount: true })
|
|
3299
|
+
* const page2 = await Runtype.skills.listPage({ limit: 50, cursor: page1.pagination?.nextCursor ?? undefined })
|
|
3300
|
+
* ```
|
|
3301
|
+
*/
|
|
3302
|
+
async listPage(params) {
|
|
3303
|
+
const client = this.getClient();
|
|
3304
|
+
return client.get("/skills", params);
|
|
3305
|
+
}
|
|
3043
3306
|
/**
|
|
3044
3307
|
* Get a skill and its full version history.
|
|
3045
3308
|
*
|
|
@@ -3132,6 +3395,260 @@ var SkillsNamespace = class {
|
|
|
3132
3395
|
}
|
|
3133
3396
|
};
|
|
3134
3397
|
|
|
3398
|
+
// src/agents-namespace.ts
|
|
3399
|
+
var AGENT_CONFIG_KEYS = [
|
|
3400
|
+
"model",
|
|
3401
|
+
"systemPrompt",
|
|
3402
|
+
"temperature",
|
|
3403
|
+
"topP",
|
|
3404
|
+
"topK",
|
|
3405
|
+
"frequencyPenalty",
|
|
3406
|
+
"presencePenalty",
|
|
3407
|
+
"seed",
|
|
3408
|
+
"tools",
|
|
3409
|
+
"reasoning",
|
|
3410
|
+
"advisor",
|
|
3411
|
+
"loopConfig",
|
|
3412
|
+
"voice",
|
|
3413
|
+
"errorHandling",
|
|
3414
|
+
"artifacts",
|
|
3415
|
+
"loggingPolicy",
|
|
3416
|
+
"temporal",
|
|
3417
|
+
"memory"
|
|
3418
|
+
];
|
|
3419
|
+
var AGENT_CONFIG_KEY_LIST = [...AGENT_CONFIG_KEYS].sort();
|
|
3420
|
+
function isPlainObject2(value) {
|
|
3421
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3422
|
+
}
|
|
3423
|
+
function normalizeValue(value) {
|
|
3424
|
+
if (Array.isArray(value)) {
|
|
3425
|
+
return value.map((item) => normalizeValue(item));
|
|
3426
|
+
}
|
|
3427
|
+
if (isPlainObject2(value)) {
|
|
3428
|
+
const normalized = {};
|
|
3429
|
+
for (const key of Object.keys(value).sort()) {
|
|
3430
|
+
const entry = value[key];
|
|
3431
|
+
if (entry === void 0 || entry === null) continue;
|
|
3432
|
+
normalized[key] = normalizeValue(entry);
|
|
3433
|
+
}
|
|
3434
|
+
return normalized;
|
|
3435
|
+
}
|
|
3436
|
+
return value;
|
|
3437
|
+
}
|
|
3438
|
+
function normalizeAgentDefinition(definition) {
|
|
3439
|
+
const config = {};
|
|
3440
|
+
const rawConfig = isPlainObject2(definition.config) ? definition.config : {};
|
|
3441
|
+
for (const key of AGENT_CONFIG_KEY_LIST) {
|
|
3442
|
+
const value = rawConfig[key];
|
|
3443
|
+
if (value === void 0 || value === null) continue;
|
|
3444
|
+
config[key] = normalizeValue(value);
|
|
3445
|
+
}
|
|
3446
|
+
return {
|
|
3447
|
+
name: definition.name,
|
|
3448
|
+
...definition.description ? { description: definition.description } : {},
|
|
3449
|
+
...definition.icon ? { icon: definition.icon } : {},
|
|
3450
|
+
config
|
|
3451
|
+
};
|
|
3452
|
+
}
|
|
3453
|
+
async function computeAgentContentHash(definition) {
|
|
3454
|
+
const serialized = JSON.stringify(normalizeAgentDefinition(definition));
|
|
3455
|
+
const encoded = new TextEncoder().encode(serialized);
|
|
3456
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
|
|
3457
|
+
return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3458
|
+
}
|
|
3459
|
+
var DEFINE_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "description", "icon", ...AGENT_CONFIG_KEYS]);
|
|
3460
|
+
function collectNonPortableToolRefs(config) {
|
|
3461
|
+
const tools = config.tools;
|
|
3462
|
+
if (!isPlainObject2(tools)) return [];
|
|
3463
|
+
const found = [];
|
|
3464
|
+
const isAccountScoped = (ref) => typeof ref === "string" && ref.startsWith("tool_");
|
|
3465
|
+
const scanArray = (value, path) => {
|
|
3466
|
+
if (!Array.isArray(value)) return;
|
|
3467
|
+
value.forEach((ref, i) => {
|
|
3468
|
+
if (isAccountScoped(ref)) found.push(`${path}[${i}]`);
|
|
3469
|
+
});
|
|
3470
|
+
};
|
|
3471
|
+
const scanKeys = (value, path) => {
|
|
3472
|
+
if (!isPlainObject2(value)) return;
|
|
3473
|
+
for (const key of Object.keys(value)) {
|
|
3474
|
+
if (isAccountScoped(key)) found.push(`${path}.${key}`);
|
|
3475
|
+
}
|
|
3476
|
+
};
|
|
3477
|
+
scanArray(tools.toolIds, "tools.toolIds");
|
|
3478
|
+
scanKeys(tools.toolConfigs, "tools.toolConfigs");
|
|
3479
|
+
scanKeys(tools.perToolLimits, "tools.perToolLimits");
|
|
3480
|
+
if (isPlainObject2(tools.approval)) scanArray(tools.approval.require, "tools.approval.require");
|
|
3481
|
+
if (isPlainObject2(tools.subagentConfig)) {
|
|
3482
|
+
scanArray(tools.subagentConfig.toolPool, "tools.subagentConfig.toolPool");
|
|
3483
|
+
}
|
|
3484
|
+
if (isPlainObject2(tools.codeModeConfig)) {
|
|
3485
|
+
scanArray(tools.codeModeConfig.toolPool, "tools.codeModeConfig.toolPool");
|
|
3486
|
+
}
|
|
3487
|
+
return found;
|
|
3488
|
+
}
|
|
3489
|
+
function defineAgent(input) {
|
|
3490
|
+
if (!input || typeof input !== "object") {
|
|
3491
|
+
throw new Error("defineAgent requires a definition object");
|
|
3492
|
+
}
|
|
3493
|
+
if (typeof input.name !== "string" || input.name.length === 0) {
|
|
3494
|
+
throw new Error('defineAgent requires a non-empty string "name"');
|
|
3495
|
+
}
|
|
3496
|
+
const unknownKeys = Object.keys(input).filter((key) => !DEFINE_TOP_LEVEL_KEYS.has(key));
|
|
3497
|
+
if (unknownKeys.length > 0) {
|
|
3498
|
+
throw new Error(
|
|
3499
|
+
`defineAgent: unknown field(s): ${unknownKeys.join(", ")}. Allowed fields are name, description, icon, and the agent runtime config surface (${AGENT_CONFIG_KEY_LIST.join(", ")}).`
|
|
3500
|
+
);
|
|
3501
|
+
}
|
|
3502
|
+
const config = {};
|
|
3503
|
+
for (const key of AGENT_CONFIG_KEYS) {
|
|
3504
|
+
const value = input[key];
|
|
3505
|
+
if (value !== void 0) config[key] = value;
|
|
3506
|
+
}
|
|
3507
|
+
const nonPortable = collectNonPortableToolRefs(config);
|
|
3508
|
+
if (nonPortable.length > 0) {
|
|
3509
|
+
throw new Error(
|
|
3510
|
+
`defineAgent: account-scoped tool reference(s) at ${nonPortable.join(", ")}. Definitions must be environment-portable \u2014 tool_\u2026 IDs belong to one account/environment. Use builtin:/platform:/mcp: references instead. Name-based resolution of saved tools is a planned follow-up.`
|
|
3511
|
+
);
|
|
3512
|
+
}
|
|
3513
|
+
return {
|
|
3514
|
+
name: input.name,
|
|
3515
|
+
...input.description !== void 0 ? { description: input.description } : {},
|
|
3516
|
+
...input.icon !== void 0 ? { icon: input.icon } : {},
|
|
3517
|
+
config
|
|
3518
|
+
};
|
|
3519
|
+
}
|
|
3520
|
+
var AgentEnsureConflictError = class extends Error {
|
|
3521
|
+
constructor(body) {
|
|
3522
|
+
super(body.error ?? `Agent ensure conflict: ${body.code}`);
|
|
3523
|
+
this.name = "AgentEnsureConflictError";
|
|
3524
|
+
this.code = body.code;
|
|
3525
|
+
this.lastModifiedSource = body.lastModifiedSource;
|
|
3526
|
+
this.modifiedAt = body.modifiedAt;
|
|
3527
|
+
this.currentHash = body.currentHash;
|
|
3528
|
+
}
|
|
3529
|
+
};
|
|
3530
|
+
var AgentDriftError = class extends Error {
|
|
3531
|
+
constructor(plan) {
|
|
3532
|
+
super(
|
|
3533
|
+
`Agent "${plan.agentId ?? "definition"}" drifted: plan is '${plan.changes}' (changed: ${plan.changedKeys.join(", ") || "n/a"}). Run client.agents.pull(name) to absorb the remote edit into your repo, or re-run ensure to converge.`
|
|
3534
|
+
);
|
|
3535
|
+
this.name = "AgentDriftError";
|
|
3536
|
+
this.plan = plan;
|
|
3537
|
+
}
|
|
3538
|
+
};
|
|
3539
|
+
function parseRequestError2(err) {
|
|
3540
|
+
if (!(err instanceof Error)) return { status: null, body: null };
|
|
3541
|
+
const match = err.message.match(/^API request failed: (\d{3}) .*? - ([\s\S]*)$/);
|
|
3542
|
+
if (!match) return { status: null, body: null };
|
|
3543
|
+
try {
|
|
3544
|
+
return { status: Number(match[1]), body: JSON.parse(match[2]) };
|
|
3545
|
+
} catch {
|
|
3546
|
+
return { status: Number(match[1]), body: null };
|
|
3547
|
+
}
|
|
3548
|
+
}
|
|
3549
|
+
function toConflictError2(err) {
|
|
3550
|
+
const { status, body } = parseRequestError2(err);
|
|
3551
|
+
if (status !== 409 || !isPlainObject2(body)) return null;
|
|
3552
|
+
const code = body.code;
|
|
3553
|
+
if (code !== "external_modification" && code !== "remote_changed") return null;
|
|
3554
|
+
return new AgentEnsureConflictError(
|
|
3555
|
+
body
|
|
3556
|
+
);
|
|
3557
|
+
}
|
|
3558
|
+
var serverHashMemo2 = /* @__PURE__ */ new WeakMap();
|
|
3559
|
+
function memoFor2(client) {
|
|
3560
|
+
let memo = serverHashMemo2.get(client);
|
|
3561
|
+
if (!memo) {
|
|
3562
|
+
memo = /* @__PURE__ */ new Map();
|
|
3563
|
+
serverHashMemo2.set(client, memo);
|
|
3564
|
+
}
|
|
3565
|
+
return memo;
|
|
3566
|
+
}
|
|
3567
|
+
var AgentsNamespace = class {
|
|
3568
|
+
constructor(getClient) {
|
|
3569
|
+
this.getClient = getClient;
|
|
3570
|
+
}
|
|
3571
|
+
/**
|
|
3572
|
+
* Idempotently converge a definition onto the platform. Hash-first: probes
|
|
3573
|
+
* with a content hash, and only ships the full definition when the server
|
|
3574
|
+
* reports a miss (`definitionRequired`). Creates an immutable version
|
|
3575
|
+
* snapshot on every change; never deletes.
|
|
3576
|
+
*/
|
|
3577
|
+
async ensure(definition, options = {}) {
|
|
3578
|
+
const client = this.getClient();
|
|
3579
|
+
const { dryRun, onConflict, release, expectedRemoteHash, expectNoChanges } = options;
|
|
3580
|
+
const passthrough = {
|
|
3581
|
+
...onConflict ? { onConflict } : {},
|
|
3582
|
+
...release ? { release } : {},
|
|
3583
|
+
...expectedRemoteHash ? { expectedRemoteHash } : {}
|
|
3584
|
+
};
|
|
3585
|
+
if (dryRun || expectNoChanges) {
|
|
3586
|
+
const plan = await this.request(client, {
|
|
3587
|
+
name: definition.name,
|
|
3588
|
+
definition,
|
|
3589
|
+
dryRun: true,
|
|
3590
|
+
...passthrough
|
|
3591
|
+
});
|
|
3592
|
+
if (plan.result !== "plan") {
|
|
3593
|
+
throw new Error(`Expected a plan result from dryRun, got '${plan.result}'`);
|
|
3594
|
+
}
|
|
3595
|
+
if (expectNoChanges && plan.changes !== "none") {
|
|
3596
|
+
throw new AgentDriftError(plan);
|
|
3597
|
+
}
|
|
3598
|
+
return plan;
|
|
3599
|
+
}
|
|
3600
|
+
const memo = memoFor2(client);
|
|
3601
|
+
const localHash = await computeAgentContentHash({
|
|
3602
|
+
...definition,
|
|
3603
|
+
config: definition.config
|
|
3604
|
+
});
|
|
3605
|
+
const memoKey = `${definition.name}\0${localHash}`;
|
|
3606
|
+
const contentHash = memo.get(memoKey) ?? localHash;
|
|
3607
|
+
const probe = await this.request(client, {
|
|
3608
|
+
name: definition.name,
|
|
3609
|
+
contentHash,
|
|
3610
|
+
...passthrough
|
|
3611
|
+
});
|
|
3612
|
+
if (probe.result !== "definitionRequired") {
|
|
3613
|
+
this.memoize(memo, memoKey, probe);
|
|
3614
|
+
return probe;
|
|
3615
|
+
}
|
|
3616
|
+
const converged = await this.request(client, {
|
|
3617
|
+
name: definition.name,
|
|
3618
|
+
definition,
|
|
3619
|
+
...passthrough
|
|
3620
|
+
});
|
|
3621
|
+
if (converged.result === "definitionRequired") {
|
|
3622
|
+
throw new Error("Server reported definitionRequired for a full-definition request");
|
|
3623
|
+
}
|
|
3624
|
+
this.memoize(memo, memoKey, converged);
|
|
3625
|
+
return converged;
|
|
3626
|
+
}
|
|
3627
|
+
/**
|
|
3628
|
+
* Pull the canonical definition + provenance for an agent by name — the
|
|
3629
|
+
* absorb-drift direction. The contentHash reflects the live agent state.
|
|
3630
|
+
*/
|
|
3631
|
+
async pull(name) {
|
|
3632
|
+
const client = this.getClient();
|
|
3633
|
+
return client.get("/agents/pull", { name });
|
|
3634
|
+
}
|
|
3635
|
+
memoize(memo, memoKey, result) {
|
|
3636
|
+
if (result.result !== "plan") memo.set(memoKey, result.contentHash);
|
|
3637
|
+
}
|
|
3638
|
+
async request(client, body) {
|
|
3639
|
+
try {
|
|
3640
|
+
return await client.post(
|
|
3641
|
+
"/agents/ensure",
|
|
3642
|
+
body
|
|
3643
|
+
);
|
|
3644
|
+
} catch (err) {
|
|
3645
|
+
const conflict = toConflictError2(err);
|
|
3646
|
+
if (conflict) throw conflict;
|
|
3647
|
+
throw err;
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
};
|
|
3651
|
+
|
|
3135
3652
|
// src/transform.ts
|
|
3136
3653
|
function transformResponse(data) {
|
|
3137
3654
|
return data;
|
|
@@ -3292,7 +3809,7 @@ var RuntypeClient = class {
|
|
|
3292
3809
|
} catch (error) {
|
|
3293
3810
|
clearTimeout(timeoutId);
|
|
3294
3811
|
if (error instanceof Error && error.name === "AbortError") {
|
|
3295
|
-
throw new Error(`Request timeout after ${this.timeout}ms
|
|
3812
|
+
throw new Error(`Request timeout after ${this.timeout}ms`, { cause: error });
|
|
3296
3813
|
}
|
|
3297
3814
|
throw error;
|
|
3298
3815
|
}
|
|
@@ -3319,7 +3836,7 @@ var RuntypeClient = class {
|
|
|
3319
3836
|
} catch (error) {
|
|
3320
3837
|
clearTimeout(timeoutId);
|
|
3321
3838
|
if (error instanceof Error && error.name === "AbortError") {
|
|
3322
|
-
throw new Error(`Request timeout after ${this.timeout}ms
|
|
3839
|
+
throw new Error(`Request timeout after ${this.timeout}ms`, { cause: error });
|
|
3323
3840
|
}
|
|
3324
3841
|
throw error;
|
|
3325
3842
|
}
|
|
@@ -3494,6 +4011,32 @@ var Runtype = class {
|
|
|
3494
4011
|
static get skills() {
|
|
3495
4012
|
return new SkillsNamespace(() => this.getClient());
|
|
3496
4013
|
}
|
|
4014
|
+
/**
|
|
4015
|
+
* Agents namespace - Agent config-as-code (define / ensure / pull)
|
|
4016
|
+
*
|
|
4017
|
+
* @example
|
|
4018
|
+
* ```typescript
|
|
4019
|
+
* import { defineAgent, Runtype } from '@runtypelabs/sdk'
|
|
4020
|
+
*
|
|
4021
|
+
* const assistant = defineAgent({
|
|
4022
|
+
* name: 'Pricing Assistant',
|
|
4023
|
+
* model: 'claude-sonnet-4-6',
|
|
4024
|
+
* systemPrompt: renderPrompt(pricingData),
|
|
4025
|
+
* })
|
|
4026
|
+
*
|
|
4027
|
+
* // Converge at deploy time (idempotent; one tiny probe in steady state)
|
|
4028
|
+
* await Runtype.agents.ensure(assistant)
|
|
4029
|
+
*
|
|
4030
|
+
* // CI drift gate
|
|
4031
|
+
* await Runtype.agents.ensure(assistant, { expectNoChanges: true })
|
|
4032
|
+
*
|
|
4033
|
+
* // Absorb a dashboard edit back into the repo
|
|
4034
|
+
* const { definition } = await Runtype.agents.pull('Pricing Assistant')
|
|
4035
|
+
* ```
|
|
4036
|
+
*/
|
|
4037
|
+
static get agents() {
|
|
4038
|
+
return new AgentsNamespace(() => this.getClient());
|
|
4039
|
+
}
|
|
3497
4040
|
};
|
|
3498
4041
|
|
|
3499
4042
|
// src/generated-tool-gate.ts
|
|
@@ -3716,8 +4259,8 @@ function buildGeneratedRuntimeToolGateOutput(proposal, options = {}) {
|
|
|
3716
4259
|
...decision.tool ? { tool: decision.tool } : {}
|
|
3717
4260
|
};
|
|
3718
4261
|
}
|
|
3719
|
-
function attachRuntimeToolsToDispatchRequest(
|
|
3720
|
-
const stepList =
|
|
4262
|
+
function attachRuntimeToolsToDispatchRequest(request2, runtimeTools, options = {}) {
|
|
4263
|
+
const stepList = request2.flow.steps;
|
|
3721
4264
|
if (!stepList || !Array.isArray(stepList) || stepList.length === 0) {
|
|
3722
4265
|
throw new Error("Cannot attach runtime tools: dispatch request must include flow.steps");
|
|
3723
4266
|
}
|
|
@@ -3760,9 +4303,9 @@ function attachRuntimeToolsToDispatchRequest(request, runtimeTools, options = {}
|
|
|
3760
4303
|
}
|
|
3761
4304
|
};
|
|
3762
4305
|
return {
|
|
3763
|
-
...
|
|
4306
|
+
...request2,
|
|
3764
4307
|
flow: {
|
|
3765
|
-
...
|
|
4308
|
+
...request2.flow,
|
|
3766
4309
|
// `clonedSteps` is a structural clone of `request.flow.steps` (already
|
|
3767
4310
|
// `FlowStepDefinition[]`); only the prompt step's `config.tools` was
|
|
3768
4311
|
// merged, so every step's `type` discriminant is preserved. The clone is
|
|
@@ -3772,18 +4315,56 @@ function attachRuntimeToolsToDispatchRequest(request, runtimeTools, options = {}
|
|
|
3772
4315
|
}
|
|
3773
4316
|
};
|
|
3774
4317
|
}
|
|
3775
|
-
function applyGeneratedRuntimeToolProposalToDispatchRequest(
|
|
4318
|
+
function applyGeneratedRuntimeToolProposalToDispatchRequest(request2, proposal, options = {}) {
|
|
3776
4319
|
const decision = evaluateGeneratedRuntimeToolProposal(proposal, options.gate);
|
|
3777
4320
|
if (!decision.approved || !decision.tool) {
|
|
3778
|
-
return { decision, request };
|
|
4321
|
+
return { decision, request: request2 };
|
|
3779
4322
|
}
|
|
3780
|
-
const nextRequest = attachRuntimeToolsToDispatchRequest(
|
|
4323
|
+
const nextRequest = attachRuntimeToolsToDispatchRequest(request2, [decision.tool], options.attach);
|
|
3781
4324
|
return {
|
|
3782
4325
|
decision,
|
|
3783
4326
|
request: nextRequest
|
|
3784
4327
|
};
|
|
3785
4328
|
}
|
|
3786
4329
|
|
|
4330
|
+
// src/offload-markers.ts
|
|
4331
|
+
var LEDGER_ARTIFACT_LINE_PREFIX = "Ledger artifact: ";
|
|
4332
|
+
function formatChars(charLength) {
|
|
4333
|
+
return charLength.toLocaleString("en-US");
|
|
4334
|
+
}
|
|
4335
|
+
function buildSendViewOffloadMarker(details) {
|
|
4336
|
+
return `[${details.toolName} output (${formatChars(details.charLength)} chars) saved to ${details.filePath} \u2014 use read_file to retrieve if needed]`;
|
|
4337
|
+
}
|
|
4338
|
+
function buildLedgerOffloadReference(details) {
|
|
4339
|
+
return [
|
|
4340
|
+
`[Output offloaded as ${details.outputId} \u2014 ${formatChars(details.charLength)} chars stored in the marathon context ledger]`,
|
|
4341
|
+
`${LEDGER_ARTIFACT_LINE_PREFIX}${details.relativePath}`,
|
|
4342
|
+
`Preview: ${details.preview}${details.truncated ? "..." : ""}`,
|
|
4343
|
+
"",
|
|
4344
|
+
`Use read_offloaded_output with id "${details.outputId}" to retrieve the full output if needed.`
|
|
4345
|
+
].join("\n");
|
|
4346
|
+
}
|
|
4347
|
+
var DECLARED_CHARS_PATTERNS = [
|
|
4348
|
+
/—\s*([\d,]+)\s+chars?\s+(?:stored|saved)/i,
|
|
4349
|
+
/\(([\d,]+)\s+chars?\)\s+saved/i
|
|
4350
|
+
];
|
|
4351
|
+
function extractDeclaredToolResultChars(value) {
|
|
4352
|
+
if (typeof value !== "string") return void 0;
|
|
4353
|
+
for (const pattern of DECLARED_CHARS_PATTERNS) {
|
|
4354
|
+
const match = pattern.exec(value);
|
|
4355
|
+
if (!match?.[1]) continue;
|
|
4356
|
+
const parsed = Number.parseInt(match[1].replace(/,/g, ""), 10);
|
|
4357
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
4358
|
+
}
|
|
4359
|
+
return void 0;
|
|
4360
|
+
}
|
|
4361
|
+
function parseOffloadedOutputId(value) {
|
|
4362
|
+
return /\bread_offloaded_output\s+with\s+id\s+"([^"]+)"/i.exec(value)?.[1] || /\[Output offloaded as\s+([a-zA-Z0-9_-]+)/i.exec(value)?.[1] || void 0;
|
|
4363
|
+
}
|
|
4364
|
+
function parseLedgerArtifactRelativePath(value) {
|
|
4365
|
+
return value.split("\n").find((line) => line.startsWith(LEDGER_ARTIFACT_LINE_PREFIX))?.slice(LEDGER_ARTIFACT_LINE_PREFIX.length).trim();
|
|
4366
|
+
}
|
|
4367
|
+
|
|
3787
4368
|
// src/workflow-utils.ts
|
|
3788
4369
|
function normalizeCandidatePath(candidatePath) {
|
|
3789
4370
|
return candidatePath.trim().replace(/\\/g, "/").replace(/^\.?\//, "").replace(/\/+/g, "/");
|
|
@@ -5515,15 +6096,15 @@ var DispatchEndpoint = class {
|
|
|
5515
6096
|
* Attach approved runtime tools to a prompt step in a redispatch request.
|
|
5516
6097
|
* Returns a new request object and does not mutate the original.
|
|
5517
6098
|
*/
|
|
5518
|
-
attachApprovedRuntimeTools(
|
|
5519
|
-
return attachRuntimeToolsToDispatchRequest(
|
|
6099
|
+
attachApprovedRuntimeTools(request2, runtimeTools, options) {
|
|
6100
|
+
return attachRuntimeToolsToDispatchRequest(request2, runtimeTools, options);
|
|
5520
6101
|
}
|
|
5521
6102
|
/**
|
|
5522
6103
|
* Validate a generated runtime tool proposal and attach it to the redispatch
|
|
5523
6104
|
* request if approved, in one call.
|
|
5524
6105
|
*/
|
|
5525
|
-
applyGeneratedRuntimeToolProposal(
|
|
5526
|
-
return applyGeneratedRuntimeToolProposalToDispatchRequest(
|
|
6106
|
+
applyGeneratedRuntimeToolProposal(request2, proposal, options) {
|
|
6107
|
+
return applyGeneratedRuntimeToolProposalToDispatchRequest(request2, proposal, options);
|
|
5527
6108
|
}
|
|
5528
6109
|
};
|
|
5529
6110
|
var ChatEndpoint = class {
|
|
@@ -6028,6 +6609,22 @@ async function processAgentStream(body, callbacks) {
|
|
|
6028
6609
|
reader.releaseLock();
|
|
6029
6610
|
}
|
|
6030
6611
|
}
|
|
6612
|
+
function sleepWithAbort(delayMs, signal) {
|
|
6613
|
+
return new Promise((resolve) => {
|
|
6614
|
+
const onAbort = () => {
|
|
6615
|
+
clearTimeout(timer);
|
|
6616
|
+
resolve();
|
|
6617
|
+
};
|
|
6618
|
+
const timer = setTimeout(() => {
|
|
6619
|
+
signal?.removeEventListener("abort", onAbort);
|
|
6620
|
+
resolve();
|
|
6621
|
+
}, delayMs);
|
|
6622
|
+
if (signal) {
|
|
6623
|
+
if (signal.aborted) onAbort();
|
|
6624
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
6625
|
+
}
|
|
6626
|
+
});
|
|
6627
|
+
}
|
|
6031
6628
|
var GENERATED_RUNTIME_TOOL_PROPOSAL_SCHEMA = {
|
|
6032
6629
|
type: "object",
|
|
6033
6630
|
properties: {
|
|
@@ -6059,8 +6656,8 @@ var GENERATED_RUNTIME_TOOL_PROPOSAL_SCHEMA = {
|
|
|
6059
6656
|
},
|
|
6060
6657
|
required: ["name", "description", "toolType", "parametersSchema", "config"]
|
|
6061
6658
|
};
|
|
6062
|
-
function appendRuntimeToolsToAgentRequest(
|
|
6063
|
-
const existing =
|
|
6659
|
+
function appendRuntimeToolsToAgentRequest(request2, runtimeTools) {
|
|
6660
|
+
const existing = request2.tools?.runtimeTools || [];
|
|
6064
6661
|
const existingNames = new Set(existing.map((tool) => tool.name));
|
|
6065
6662
|
const converted = runtimeTools.filter((tool) => !existingNames.has(tool.name)).map((tool) => ({
|
|
6066
6663
|
name: tool.name,
|
|
@@ -6070,9 +6667,9 @@ function appendRuntimeToolsToAgentRequest(request, runtimeTools) {
|
|
|
6070
6667
|
...tool.config ? { config: tool.config } : {}
|
|
6071
6668
|
}));
|
|
6072
6669
|
return {
|
|
6073
|
-
...
|
|
6670
|
+
...request2,
|
|
6074
6671
|
tools: {
|
|
6075
|
-
...
|
|
6672
|
+
...request2.tools,
|
|
6076
6673
|
runtimeTools: [...existing, ...converted]
|
|
6077
6674
|
}
|
|
6078
6675
|
};
|
|
@@ -6148,21 +6745,21 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6148
6745
|
* Attach approved runtime tools to an agent execute request.
|
|
6149
6746
|
* Returns a new request object and does not mutate the original.
|
|
6150
6747
|
*/
|
|
6151
|
-
attachApprovedRuntimeTools(
|
|
6152
|
-
return appendRuntimeToolsToAgentRequest(
|
|
6748
|
+
attachApprovedRuntimeTools(request2, runtimeTools) {
|
|
6749
|
+
return appendRuntimeToolsToAgentRequest(request2, runtimeTools);
|
|
6153
6750
|
}
|
|
6154
6751
|
/**
|
|
6155
6752
|
* Validate a generated runtime tool proposal and append it to an agent execute
|
|
6156
6753
|
* request if approved, in one call.
|
|
6157
6754
|
*/
|
|
6158
|
-
applyGeneratedRuntimeToolProposal(
|
|
6755
|
+
applyGeneratedRuntimeToolProposal(request2, proposal, options) {
|
|
6159
6756
|
const decision = evaluateGeneratedRuntimeToolProposal(proposal, options);
|
|
6160
6757
|
if (!decision.approved || !decision.tool) {
|
|
6161
|
-
return { decision, request };
|
|
6758
|
+
return { decision, request: request2 };
|
|
6162
6759
|
}
|
|
6163
6760
|
return {
|
|
6164
6761
|
decision,
|
|
6165
|
-
request: appendRuntimeToolsToAgentRequest(
|
|
6762
|
+
request: appendRuntimeToolsToAgentRequest(request2, [decision.tool])
|
|
6166
6763
|
};
|
|
6167
6764
|
}
|
|
6168
6765
|
/**
|
|
@@ -6192,13 +6789,14 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6192
6789
|
* // ...
|
|
6193
6790
|
* ```
|
|
6194
6791
|
*/
|
|
6195
|
-
async executeStream(id, data) {
|
|
6792
|
+
async executeStream(id, data, init) {
|
|
6196
6793
|
return this.client.requestStream(`/agents/${id}/execute`, {
|
|
6197
6794
|
method: "POST",
|
|
6198
6795
|
body: JSON.stringify({
|
|
6199
6796
|
...data,
|
|
6200
6797
|
streamResponse: true
|
|
6201
|
-
})
|
|
6798
|
+
}),
|
|
6799
|
+
...init?.signal ? { signal: init.signal } : {}
|
|
6202
6800
|
});
|
|
6203
6801
|
}
|
|
6204
6802
|
/**
|
|
@@ -6294,56 +6892,94 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6294
6892
|
runtimeTools: [...data.tools?.runtimeTools || [], ...runtimeTools]
|
|
6295
6893
|
}
|
|
6296
6894
|
};
|
|
6297
|
-
const
|
|
6298
|
-
if (!response.ok) {
|
|
6299
|
-
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
6300
|
-
throw new Error(error.error || `HTTP ${response.status}`);
|
|
6301
|
-
}
|
|
6302
|
-
let currentBody = response.body;
|
|
6895
|
+
const abortSignal = options?.abortSignal;
|
|
6303
6896
|
let accumulatedOutput = "";
|
|
6304
6897
|
let lastKnownCost = 0;
|
|
6305
6898
|
let lastKnownTokens;
|
|
6899
|
+
let lastSeenExecutionId = "";
|
|
6306
6900
|
let pauseCount = 0;
|
|
6307
6901
|
let discoveryPauseCount = 0;
|
|
6308
6902
|
let consecutiveDiscoveryPauseCount = 0;
|
|
6309
6903
|
const toolNameCounts = {};
|
|
6310
6904
|
let recentActionKeys = [];
|
|
6311
6905
|
const toolMessages = [];
|
|
6906
|
+
const finishAborted = (executionId) => {
|
|
6907
|
+
const abortCompleteEvent = {
|
|
6908
|
+
type: "agent_complete",
|
|
6909
|
+
executionId,
|
|
6910
|
+
seq: 0,
|
|
6911
|
+
agentId: id,
|
|
6912
|
+
success: true,
|
|
6913
|
+
iterations: 1,
|
|
6914
|
+
stopReason: "end_turn",
|
|
6915
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6916
|
+
totalCost: lastKnownCost,
|
|
6917
|
+
...lastKnownTokens ? { totalTokens: lastKnownTokens } : {},
|
|
6918
|
+
finalOutput: [accumulatedOutput.trim(), "Session aborted by user request."].filter(Boolean).join("\n\n"),
|
|
6919
|
+
duration: 0
|
|
6920
|
+
};
|
|
6921
|
+
callbacks?.onAgentComplete?.(abortCompleteEvent);
|
|
6922
|
+
return { completeEvent: abortCompleteEvent, toolMessages };
|
|
6923
|
+
};
|
|
6924
|
+
let response;
|
|
6925
|
+
try {
|
|
6926
|
+
response = await this.executeStream(id, requestData, {
|
|
6927
|
+
...abortSignal ? { signal: abortSignal } : {}
|
|
6928
|
+
});
|
|
6929
|
+
} catch (error) {
|
|
6930
|
+
if (abortSignal?.aborted) return finishAborted(lastSeenExecutionId);
|
|
6931
|
+
throw error;
|
|
6932
|
+
}
|
|
6933
|
+
if (!response.ok) {
|
|
6934
|
+
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
6935
|
+
throw new Error(error.error || `HTTP ${response.status}`);
|
|
6936
|
+
}
|
|
6937
|
+
let currentBody = response.body;
|
|
6312
6938
|
while (true) {
|
|
6313
6939
|
let pausedEvent = null;
|
|
6314
6940
|
let completeEvent = null;
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6941
|
+
try {
|
|
6942
|
+
await processAgentStream(currentBody, {
|
|
6943
|
+
...callbacks,
|
|
6944
|
+
onAgentStart: (event) => {
|
|
6945
|
+
lastSeenExecutionId = event.executionId;
|
|
6946
|
+
callbacks?.onAgentStart?.(event);
|
|
6947
|
+
},
|
|
6948
|
+
onTurnDelta: (event) => {
|
|
6949
|
+
if (event.contentType === "text") {
|
|
6950
|
+
accumulatedOutput += event.delta;
|
|
6951
|
+
}
|
|
6952
|
+
callbacks?.onTurnDelta?.(event);
|
|
6953
|
+
},
|
|
6954
|
+
onTurnComplete: (event) => {
|
|
6955
|
+
if (typeof event.cost === "number") {
|
|
6956
|
+
lastKnownCost = event.cost;
|
|
6957
|
+
}
|
|
6958
|
+
if (event.tokens) {
|
|
6959
|
+
lastKnownTokens = event.tokens;
|
|
6960
|
+
}
|
|
6961
|
+
callbacks?.onTurnComplete?.(event);
|
|
6962
|
+
},
|
|
6963
|
+
onAgentPaused: (event) => {
|
|
6964
|
+
pausedEvent = event;
|
|
6965
|
+
callbacks?.onAgentPaused?.(event);
|
|
6966
|
+
},
|
|
6967
|
+
onAgentComplete: (event) => {
|
|
6968
|
+
if (!event.finalOutput && accumulatedOutput) {
|
|
6969
|
+
event.finalOutput = accumulatedOutput;
|
|
6970
|
+
}
|
|
6971
|
+
completeEvent = event;
|
|
6972
|
+
callbacks?.onAgentComplete?.(event);
|
|
6339
6973
|
}
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6974
|
+
});
|
|
6975
|
+
} catch (error) {
|
|
6976
|
+
if (abortSignal?.aborted) return finishAborted(lastSeenExecutionId);
|
|
6977
|
+
throw error;
|
|
6978
|
+
}
|
|
6344
6979
|
if (completeEvent) return { completeEvent, toolMessages };
|
|
6345
6980
|
if (pausedEvent) {
|
|
6346
6981
|
const { toolName, toolId, parameters, executionId } = pausedEvent;
|
|
6982
|
+
lastSeenExecutionId = executionId;
|
|
6347
6983
|
const toolDef = localTools[toolName];
|
|
6348
6984
|
if (!toolDef) {
|
|
6349
6985
|
throw new Error(`Local tool "${toolName}" required but not provided`);
|
|
@@ -6458,6 +7094,19 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6458
7094
|
callbacks?.onAgentComplete?.(forcedCompleteEvent);
|
|
6459
7095
|
return { completeEvent: forcedCompleteEvent, toolMessages };
|
|
6460
7096
|
}
|
|
7097
|
+
if (abortSignal?.aborted) {
|
|
7098
|
+
callbacks?.onLocalToolExecutionComplete?.({
|
|
7099
|
+
executionId,
|
|
7100
|
+
toolCallId: toolId,
|
|
7101
|
+
toolName,
|
|
7102
|
+
parameters: parsedParams,
|
|
7103
|
+
result: toolResult,
|
|
7104
|
+
success: true,
|
|
7105
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7106
|
+
durationMs: Date.now() - localExecutionStartedAtMs
|
|
7107
|
+
});
|
|
7108
|
+
return finishAborted(executionId);
|
|
7109
|
+
}
|
|
6461
7110
|
if (options?.shouldInterrupt?.()) {
|
|
6462
7111
|
callbacks?.onLocalToolExecutionComplete?.({
|
|
6463
7112
|
executionId,
|
|
@@ -6491,15 +7140,22 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6491
7140
|
callbacks?.onAgentComplete?.(interruptCompleteEvent);
|
|
6492
7141
|
return { completeEvent: interruptCompleteEvent, toolMessages };
|
|
6493
7142
|
}
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
7143
|
+
let resumeResponse;
|
|
7144
|
+
try {
|
|
7145
|
+
resumeResponse = await this.client.requestStream(`/agents/${id}/resume`, {
|
|
7146
|
+
method: "POST",
|
|
7147
|
+
body: JSON.stringify({
|
|
7148
|
+
executionId,
|
|
7149
|
+
toolOutputs: { [toolName]: toolResult },
|
|
7150
|
+
streamResponse: true,
|
|
7151
|
+
debugMode: data.debugMode
|
|
7152
|
+
}),
|
|
7153
|
+
...abortSignal ? { signal: abortSignal } : {}
|
|
7154
|
+
});
|
|
7155
|
+
} catch (error) {
|
|
7156
|
+
if (abortSignal?.aborted) return finishAborted(executionId);
|
|
7157
|
+
throw error;
|
|
7158
|
+
}
|
|
6503
7159
|
if (!resumeResponse.ok) {
|
|
6504
7160
|
const error = await resumeResponse.json().catch(() => ({ error: "Unknown error" }));
|
|
6505
7161
|
throw new Error(error.error || `HTTP ${resumeResponse.status}`);
|
|
@@ -6517,6 +7173,7 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6517
7173
|
currentBody = resumeResponse.body;
|
|
6518
7174
|
continue;
|
|
6519
7175
|
}
|
|
7176
|
+
if (abortSignal?.aborted) return finishAborted(lastSeenExecutionId);
|
|
6520
7177
|
return null;
|
|
6521
7178
|
}
|
|
6522
7179
|
}
|
|
@@ -6788,7 +7445,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6788
7445
|
reasons.push("Best candidate file has not been verified (read back after writing)");
|
|
6789
7446
|
}
|
|
6790
7447
|
if (state.verificationRequired && !state.lastVerificationPassed && !trace.verificationPassed) {
|
|
6791
|
-
reasons.push(
|
|
7448
|
+
reasons.push(
|
|
7449
|
+
"Verification has not passed \u2014 run a verification command (run_check) before completing"
|
|
7450
|
+
);
|
|
6792
7451
|
}
|
|
6793
7452
|
return reasons.length > 0 ? reasons.join("; ") : "Completion gates not satisfied for the current workflow phase";
|
|
6794
7453
|
}
|
|
@@ -6831,32 +7490,71 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6831
7490
|
);
|
|
6832
7491
|
}
|
|
6833
7492
|
/**
|
|
6834
|
-
*
|
|
6835
|
-
*
|
|
7493
|
+
* Resolve the replay window: the base index sliced off the full history and
|
|
7494
|
+
* the durable summary message that stands in for everything before it.
|
|
7495
|
+
* The base is honored ONLY when the latest summary actually exists —
|
|
7496
|
+
* slicing history with no summary substitute would silently drop prior
|
|
7497
|
+
* context (defensive against states that carried a base but lost their
|
|
7498
|
+
* summaries). The base is also clamped so a stale pointer (fork truncation,
|
|
7499
|
+
* trimmed legacy state) never slices past the end of the array.
|
|
6836
7500
|
*/
|
|
6837
|
-
|
|
6838
|
-
|
|
7501
|
+
resolveWindowReplay(state, messageCount) {
|
|
7502
|
+
const base = state.contextWindowBaseIndex ?? 0;
|
|
7503
|
+
if (!Number.isFinite(base) || base <= 0) {
|
|
7504
|
+
return { windowBase: 0, windowSummaryMessages: [] };
|
|
7505
|
+
}
|
|
7506
|
+
const summaries = state.contextCompactionSummaries;
|
|
7507
|
+
const latest = summaries?.[summaries.length - 1];
|
|
7508
|
+
if (!latest) {
|
|
7509
|
+
return { windowBase: 0, windowSummaryMessages: [] };
|
|
7510
|
+
}
|
|
7511
|
+
return {
|
|
7512
|
+
windowBase: Math.min(Math.floor(base), messageCount),
|
|
7513
|
+
windowSummaryMessages: [{ role: "system", content: latest.content }]
|
|
7514
|
+
};
|
|
7515
|
+
}
|
|
7516
|
+
/**
|
|
7517
|
+
* Derive the message view sent to the model based on context mode and window
|
|
7518
|
+
* setting. This never mutates persisted marathon history; masking/offloading
|
|
7519
|
+
* is a send-time view over the full-fidelity ledger/history.
|
|
7520
|
+
*/
|
|
7521
|
+
deriveToolContextMessages(messages, taskName, mode, window) {
|
|
7522
|
+
if (mode === "full-inline") return [...messages];
|
|
7523
|
+
const maskMessage = (msg) => ({
|
|
7524
|
+
...msg,
|
|
7525
|
+
toolResults: (msg.toolResults ?? []).map((tr) => this.compactOneResult(tr, taskName, mode))
|
|
7526
|
+
});
|
|
7527
|
+
const view = [...messages];
|
|
6839
7528
|
if (window === "session") {
|
|
6840
|
-
|
|
7529
|
+
const lastUserIndex = view.reduce(
|
|
7530
|
+
(lastIndex, message, index) => message.role === "user" ? index : lastIndex,
|
|
7531
|
+
-1
|
|
7532
|
+
);
|
|
7533
|
+
for (let index = 0; index < view.length; index++) {
|
|
7534
|
+
if (lastUserIndex >= 0 && index > lastUserIndex) continue;
|
|
7535
|
+
const msg = view[index];
|
|
7536
|
+
if (!msg) continue;
|
|
6841
7537
|
if (msg.role === "tool" && msg.toolResults) {
|
|
6842
|
-
|
|
7538
|
+
view[index] = maskMessage(msg);
|
|
6843
7539
|
}
|
|
6844
7540
|
}
|
|
6845
7541
|
} else {
|
|
6846
|
-
const newToolResultCount = newToolMessages.filter((m) => m.role === "tool").length;
|
|
6847
|
-
const keepInlineFromExisting = Math.max(0, window - newToolResultCount);
|
|
6848
7542
|
const toolResultIndices = [];
|
|
6849
|
-
for (let i = 0; i <
|
|
6850
|
-
|
|
7543
|
+
for (let i = 0; i < view.length; i++) {
|
|
7544
|
+
const message = view[i];
|
|
7545
|
+
if (message?.role === "tool" && message.toolResults) {
|
|
6851
7546
|
toolResultIndices.push(i);
|
|
6852
7547
|
}
|
|
6853
7548
|
}
|
|
6854
|
-
const compactUpTo = toolResultIndices.length -
|
|
7549
|
+
const compactUpTo = toolResultIndices.length - window;
|
|
6855
7550
|
for (let j = 0; j < compactUpTo && j < toolResultIndices.length; j++) {
|
|
6856
|
-
const
|
|
6857
|
-
msg
|
|
7551
|
+
const index = toolResultIndices[j];
|
|
7552
|
+
const msg = index === void 0 ? void 0 : view[index];
|
|
7553
|
+
if (!msg) continue;
|
|
7554
|
+
view[index] = maskMessage(msg);
|
|
6858
7555
|
}
|
|
6859
7556
|
}
|
|
7557
|
+
return view;
|
|
6860
7558
|
}
|
|
6861
7559
|
compactOneResult(tr, taskName, mode) {
|
|
6862
7560
|
if (typeof tr.result === "string" && tr.result.startsWith("[")) return tr;
|
|
@@ -6892,10 +7590,20 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6892
7590
|
}
|
|
6893
7591
|
const slug = this.sanitizeTaskSlug(taskName || "task");
|
|
6894
7592
|
const dir = `.runtype/marathons/${slug}/tool-outputs`;
|
|
6895
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
6896
7593
|
const filePath = `${dir}/${toolCallId}.txt`;
|
|
6897
|
-
|
|
6898
|
-
|
|
7594
|
+
try {
|
|
7595
|
+
if (!fs.existsSync(filePath)) {
|
|
7596
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
7597
|
+
fs.writeFileSync(filePath, resultStr, "utf-8");
|
|
7598
|
+
}
|
|
7599
|
+
} catch {
|
|
7600
|
+
return result;
|
|
7601
|
+
}
|
|
7602
|
+
return buildSendViewOffloadMarker({
|
|
7603
|
+
toolName,
|
|
7604
|
+
charLength: resultStr.length,
|
|
7605
|
+
filePath
|
|
7606
|
+
});
|
|
6899
7607
|
}
|
|
6900
7608
|
getDefaultPlanPath(taskName) {
|
|
6901
7609
|
return getDefaultPlanPath(taskName);
|
|
@@ -7017,6 +7725,7 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7017
7725
|
const migratedPlanPath = workflowVariant === "external" && planPath === this.getDefaultPlanPath(taskName) ? this.getDefaultExternalReportPath(taskName) : planPath;
|
|
7018
7726
|
const candidatePaths = this.dedupeNormalizedCandidatePaths(resumeState.candidatePaths);
|
|
7019
7727
|
const recentReadPaths = this.dedupeNormalizedCandidatePaths(resumeState.recentReadPaths);
|
|
7728
|
+
const contextCompactionSummaries = (resumeState.contextCompactionSummaries ?? []).slice(-20);
|
|
7020
7729
|
const normalizedBestCandidatePath = typeof resumeState.bestCandidatePath === "string" && resumeState.bestCandidatePath.trim() ? this.normalizeCandidatePath(resumeState.bestCandidatePath) : void 0;
|
|
7021
7730
|
const bestCandidatePath = normalizedBestCandidatePath && !this.isMarathonArtifactPath(normalizedBestCandidatePath) ? normalizedBestCandidatePath : [...candidatePaths, ...recentReadPaths].sort(
|
|
7022
7731
|
(left, right) => this.scoreCandidatePath(right) - this.scoreCandidatePath(left)
|
|
@@ -7036,10 +7745,14 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7036
7745
|
bestCandidateVerified: Boolean(resumeState.bestCandidateVerified),
|
|
7037
7746
|
...resumeState.verificationRequired !== void 0 ? { verificationRequired: resumeState.verificationRequired } : {},
|
|
7038
7747
|
lastVerificationPassed: Boolean(resumeState.lastVerificationPassed),
|
|
7039
|
-
...resumeState.consecutiveBlockedVerificationSessions !== void 0 ? {
|
|
7748
|
+
...resumeState.consecutiveBlockedVerificationSessions !== void 0 ? {
|
|
7749
|
+
consecutiveBlockedVerificationSessions: resumeState.consecutiveBlockedVerificationSessions
|
|
7750
|
+
} : {},
|
|
7040
7751
|
...resumeState.isCreationTask !== void 0 ? { isCreationTask: resumeState.isCreationTask } : {},
|
|
7041
7752
|
...resumeState.workflowVariant !== void 0 ? { workflowVariant: resumeState.workflowVariant } : {},
|
|
7042
7753
|
...resumeState.workflowState !== void 0 ? { workflowState: resumeState.workflowState } : {},
|
|
7754
|
+
...contextCompactionSummaries.length ? { contextCompactionSummaries } : {},
|
|
7755
|
+
...typeof resumeState.contextWindowBaseIndex === "number" && Number.isFinite(resumeState.contextWindowBaseIndex) && resumeState.contextWindowBaseIndex > 0 ? { contextWindowBaseIndex: Math.floor(resumeState.contextWindowBaseIndex) } : {},
|
|
7043
7756
|
...typeof resumeState.outputRoot === "string" && resumeState.outputRoot.trim() ? { outputRoot: resumeState.outputRoot.trim().replace(/\\/g, "/").replace(/\/+/g, "/") } : {}
|
|
7044
7757
|
};
|
|
7045
7758
|
}
|
|
@@ -7505,8 +8218,13 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7505
8218
|
} : {},
|
|
7506
8219
|
...seededResumeState?.candidatePaths ? { candidatePaths: seededResumeState.candidatePaths } : {},
|
|
7507
8220
|
...seededResumeState?.recentReadPaths ? { recentReadPaths: seededResumeState.recentReadPaths } : {},
|
|
7508
|
-
...seededResumeState?.recentActionKeys ? { recentActionKeys: seededResumeState.recentActionKeys } : {}
|
|
8221
|
+
...seededResumeState?.recentActionKeys ? { recentActionKeys: seededResumeState.recentActionKeys } : {},
|
|
8222
|
+
...seededResumeState?.contextCompactionSummaries?.length ? { contextCompactionSummaries: seededResumeState.contextCompactionSummaries } : {},
|
|
8223
|
+
...typeof seededResumeState?.contextWindowBaseIndex === "number" ? { contextWindowBaseIndex: seededResumeState.contextWindowBaseIndex } : {}
|
|
7509
8224
|
};
|
|
8225
|
+
if (options.previousMessages && options.previousMessages.length > 0) {
|
|
8226
|
+
state.messages = options.previousMessages.map((message) => structuredClone(message));
|
|
8227
|
+
}
|
|
7510
8228
|
state.workflowVariant = classifiedVariant;
|
|
7511
8229
|
state.isCreationTask = seededResumeState?.isCreationTask ?? state.workflowVariant === "create";
|
|
7512
8230
|
state.outputRoot = seededResumeState?.outputRoot ?? (state.isCreationTask ? "public/" : void 0);
|
|
@@ -7539,6 +8257,10 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7539
8257
|
}
|
|
7540
8258
|
}
|
|
7541
8259
|
for (let session = 0; session < maxSessions; session++) {
|
|
8260
|
+
if (options.abortSignal?.aborted) {
|
|
8261
|
+
state.status = "paused";
|
|
8262
|
+
break;
|
|
8263
|
+
}
|
|
7542
8264
|
const phaseAtSessionStart = state.workflowPhase;
|
|
7543
8265
|
const sessionTrace = this.createEmptyToolTrace();
|
|
7544
8266
|
const sessionLocalTools = this.wrapLocalToolsForTrace(
|
|
@@ -7575,7 +8297,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7575
8297
|
localTools: options.localTools,
|
|
7576
8298
|
builtinToolSchemas,
|
|
7577
8299
|
onContextCompaction: options.onContextCompaction,
|
|
7578
|
-
onContextNotice: options.onContextNotice
|
|
8300
|
+
onContextNotice: options.onContextNotice,
|
|
8301
|
+
toolContextMode: options.toolContextMode || "hot-tail",
|
|
8302
|
+
toolWindow: options.toolWindow ?? "session"
|
|
7579
8303
|
},
|
|
7580
8304
|
queuedSteeringMessages
|
|
7581
8305
|
);
|
|
@@ -7605,7 +8329,8 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7605
8329
|
sessionCallbacks,
|
|
7606
8330
|
{
|
|
7607
8331
|
onLocalToolResult: this.createLocalToolLoopGuard(state, sessionTrace, workflow),
|
|
7608
|
-
shouldInterrupt: options.hasQueuedUserMessages
|
|
8332
|
+
shouldInterrupt: options.hasQueuedUserMessages,
|
|
8333
|
+
...options.abortSignal ? { abortSignal: options.abortSignal } : {}
|
|
7609
8334
|
},
|
|
7610
8335
|
state.taskName
|
|
7611
8336
|
);
|
|
@@ -7754,22 +8479,13 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7754
8479
|
}
|
|
7755
8480
|
}
|
|
7756
8481
|
if (!state.messages) state.messages = [];
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
state.messages.push(...newMessages);
|
|
7762
|
-
} else {
|
|
8482
|
+
const sentUserMessage = messages[messages.length - 1];
|
|
8483
|
+
if (sentUserMessage?.role === "user") {
|
|
8484
|
+
state.messages.push(sentUserMessage);
|
|
8485
|
+
} else if (state.messages.length === 0) {
|
|
7763
8486
|
state.messages.push(...messages);
|
|
7764
8487
|
}
|
|
7765
8488
|
if (sessionToolMessages.length > 0) {
|
|
7766
|
-
this.compactToolResults(
|
|
7767
|
-
state.messages,
|
|
7768
|
-
sessionToolMessages,
|
|
7769
|
-
state.taskName,
|
|
7770
|
-
options.toolContextMode || "hot-tail",
|
|
7771
|
-
options.toolWindow ?? "session"
|
|
7772
|
-
);
|
|
7773
8489
|
state.messages.push(...sessionToolMessages);
|
|
7774
8490
|
}
|
|
7775
8491
|
const assistantContent = effectiveSessionOutput || `[Session ${session + 1} completed (${sessionResult.stopReason}). No text output captured.]`;
|
|
@@ -7789,7 +8505,10 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7789
8505
|
workflow
|
|
7790
8506
|
);
|
|
7791
8507
|
if (detectedTaskCompletion && !acceptedTaskCompletion) {
|
|
7792
|
-
state.lastCompletionRejectionReason = this.computeCompletionRejectionReason(
|
|
8508
|
+
state.lastCompletionRejectionReason = this.computeCompletionRejectionReason(
|
|
8509
|
+
state,
|
|
8510
|
+
sessionTrace
|
|
8511
|
+
);
|
|
7793
8512
|
if (state.verificationRequired && !state.lastVerificationPassed && !sessionTrace.verificationPassed && !sessionTrace.verificationAttempted) {
|
|
7794
8513
|
state.consecutiveBlockedVerificationSessions = (state.consecutiveBlockedVerificationSessions || 0) + 1;
|
|
7795
8514
|
if ((state.consecutiveBlockedVerificationSessions || 0) >= 2) {
|
|
@@ -7808,24 +8527,24 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7808
8527
|
}
|
|
7809
8528
|
if (sessionResult.stopReason === "complete" && !detectedTaskCompletion) {
|
|
7810
8529
|
const currentPhase = workflow.phases.find((p) => p.name === state.workflowPhase);
|
|
7811
|
-
const gatesSatisfied = currentPhase?.canAcceptCompletion ? currentPhase.canAcceptCompletion(
|
|
8530
|
+
const gatesSatisfied = currentPhase?.canAcceptCompletion ? currentPhase.canAcceptCompletion(
|
|
8531
|
+
state,
|
|
8532
|
+
sessionTrace
|
|
8533
|
+
) : true;
|
|
7812
8534
|
if (gatesSatisfied) {
|
|
7813
8535
|
state.status = "complete";
|
|
7814
8536
|
}
|
|
7815
8537
|
} else if (sessionResult.stopReason === "error") {
|
|
7816
8538
|
if (_AgentsEndpoint.isRetryableSessionError(sessionResult.error) && consecutiveServerNetworkErrors < maxServerNetworkRetries) {
|
|
7817
8539
|
consecutiveServerNetworkErrors++;
|
|
7818
|
-
const delayMs = Math.min(
|
|
7819
|
-
5e3 * Math.pow(2, consecutiveServerNetworkErrors - 1),
|
|
7820
|
-
3e4
|
|
7821
|
-
);
|
|
8540
|
+
const delayMs = Math.min(5e3 * Math.pow(2, consecutiveServerNetworkErrors - 1), 3e4);
|
|
7822
8541
|
const delaySec = Math.round(delayMs / 1e3);
|
|
7823
8542
|
await this.emitContextNotice(options.onContextNotice, {
|
|
7824
8543
|
kind: "server_network_retry",
|
|
7825
8544
|
sessionIndex: session,
|
|
7826
8545
|
message: `Server network error: ${sessionResult.error}. Retrying in ${delaySec}s (attempt ${consecutiveServerNetworkErrors}/${maxServerNetworkRetries})...`
|
|
7827
8546
|
});
|
|
7828
|
-
await
|
|
8547
|
+
await sleepWithAbort(delayMs, options.abortSignal);
|
|
7829
8548
|
} else {
|
|
7830
8549
|
state.status = "error";
|
|
7831
8550
|
}
|
|
@@ -7840,6 +8559,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7840
8559
|
} else if (session + 1 >= maxSessions) {
|
|
7841
8560
|
state.status = "max_sessions";
|
|
7842
8561
|
}
|
|
8562
|
+
if (options.abortSignal?.aborted) {
|
|
8563
|
+
state.status = "paused";
|
|
8564
|
+
}
|
|
7843
8565
|
if (options.trackProgress) {
|
|
7844
8566
|
recordId = await this.syncProgressRecord(state, recordId);
|
|
7845
8567
|
}
|
|
@@ -7916,6 +8638,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7916
8638
|
return 0;
|
|
7917
8639
|
}
|
|
7918
8640
|
}
|
|
8641
|
+
extractDeclaredToolResultChars(value) {
|
|
8642
|
+
return extractDeclaredToolResultChars(value);
|
|
8643
|
+
}
|
|
7919
8644
|
estimateMessageContentTokens(content) {
|
|
7920
8645
|
if (typeof content === "string") return this.estimateTextTokens(content);
|
|
7921
8646
|
return content.reduce((total, part) => {
|
|
@@ -7934,12 +8659,14 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7934
8659
|
0
|
|
7935
8660
|
);
|
|
7936
8661
|
}
|
|
7937
|
-
estimateToolResultTokens(toolResults) {
|
|
8662
|
+
estimateToolResultTokens(toolResults, options) {
|
|
7938
8663
|
if (!toolResults || toolResults.length === 0) return 0;
|
|
7939
|
-
return toolResults.reduce(
|
|
7940
|
-
|
|
7941
|
-
0
|
|
7942
|
-
|
|
8664
|
+
return toolResults.reduce((sum, toolResult) => {
|
|
8665
|
+
const resultTokens = this.estimateUnknownTokens(toolResult.result);
|
|
8666
|
+
const declaredChars = options?.useDeclaredSize ? this.extractDeclaredToolResultChars(toolResult.result) : void 0;
|
|
8667
|
+
const declaredTokens = typeof declaredChars === "number" ? Math.ceil(declaredChars / 4) : 0;
|
|
8668
|
+
return sum + 12 + this.estimateTextTokens(toolResult.toolName) + Math.max(resultTokens, declaredTokens);
|
|
8669
|
+
}, 0);
|
|
7943
8670
|
}
|
|
7944
8671
|
estimateMessageTokens(message) {
|
|
7945
8672
|
return 6 + this.estimateMessageContentTokens(message.content) + this.estimateToolCallTokens(message.toolCalls) + this.estimateToolResultTokens(message.toolResults);
|
|
@@ -7947,13 +8674,15 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7947
8674
|
estimateConversationTokens(messages) {
|
|
7948
8675
|
return messages.reduce((sum, message) => sum + this.estimateMessageTokens(message), 0);
|
|
7949
8676
|
}
|
|
7950
|
-
estimateConversationBreakdown(messages) {
|
|
8677
|
+
estimateConversationBreakdown(messages, options) {
|
|
7951
8678
|
let historyTokens = 0;
|
|
7952
8679
|
let toolOutputTokens = 0;
|
|
7953
8680
|
for (const message of messages) {
|
|
7954
8681
|
const contentTokens = this.estimateMessageContentTokens(message.content);
|
|
7955
8682
|
const toolCallTokens = this.estimateToolCallTokens(message.toolCalls);
|
|
7956
|
-
const toolResultTokens = this.estimateToolResultTokens(message.toolResults
|
|
8683
|
+
const toolResultTokens = this.estimateToolResultTokens(message.toolResults, {
|
|
8684
|
+
useDeclaredSize: options?.useDeclaredToolResultSizes
|
|
8685
|
+
});
|
|
7957
8686
|
const messageTotal = 6 + contentTokens + toolCallTokens + toolResultTokens;
|
|
7958
8687
|
if (message.role === "tool") {
|
|
7959
8688
|
toolOutputTokens += messageTotal;
|
|
@@ -8007,13 +8736,24 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
8007
8736
|
const compactInstructions = config.compactInstructions;
|
|
8008
8737
|
return typeof compactInstructions === "string" && compactInstructions.trim() ? compactInstructions.trim() : void 0;
|
|
8009
8738
|
}
|
|
8010
|
-
|
|
8739
|
+
extractArtifactReferencesFromMessages(messages = []) {
|
|
8011
8740
|
const references = /* @__PURE__ */ new Set();
|
|
8012
8741
|
const offloadPrefix = "[Output saved to ";
|
|
8013
|
-
|
|
8742
|
+
const ledgerArtifactPrefix = LEDGER_ARTIFACT_LINE_PREFIX;
|
|
8743
|
+
const savedToPattern = /saved to\s+([^—\]\n]+?)(?:\s+—|\]|\n|$)/gi;
|
|
8744
|
+
for (const message of messages) {
|
|
8014
8745
|
if (!message.toolResults) continue;
|
|
8015
8746
|
for (const toolResult of message.toolResults) {
|
|
8016
8747
|
if (typeof toolResult.result !== "string") continue;
|
|
8748
|
+
for (const line of toolResult.result.split("\n")) {
|
|
8749
|
+
if (line.startsWith(ledgerArtifactPrefix)) {
|
|
8750
|
+
references.add(line.slice(ledgerArtifactPrefix.length).trim());
|
|
8751
|
+
}
|
|
8752
|
+
}
|
|
8753
|
+
for (const match of toolResult.result.matchAll(savedToPattern)) {
|
|
8754
|
+
const pathText = match[1]?.trim();
|
|
8755
|
+
if (pathText) references.add(pathText);
|
|
8756
|
+
}
|
|
8017
8757
|
let startIndex = 0;
|
|
8018
8758
|
while (startIndex < toolResult.result.length) {
|
|
8019
8759
|
const prefixIndex = toolResult.result.indexOf(offloadPrefix, startIndex);
|
|
@@ -8031,6 +8771,13 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
8031
8771
|
}
|
|
8032
8772
|
}
|
|
8033
8773
|
}
|
|
8774
|
+
return Array.from(references);
|
|
8775
|
+
}
|
|
8776
|
+
extractArtifactReferences(state, additionalReferences = []) {
|
|
8777
|
+
const references = /* @__PURE__ */ new Set([
|
|
8778
|
+
...this.extractArtifactReferencesFromMessages(state.messages ?? []),
|
|
8779
|
+
...additionalReferences
|
|
8780
|
+
]);
|
|
8034
8781
|
if (state.planPath) {
|
|
8035
8782
|
references.add(state.planPath);
|
|
8036
8783
|
}
|
|
@@ -8038,6 +8785,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
8038
8785
|
}
|
|
8039
8786
|
buildContextBudgetBreakdown(details) {
|
|
8040
8787
|
const conversationBreakdown = this.estimateConversationBreakdown(details.historyMessages);
|
|
8788
|
+
const sourceConversationBreakdown = details.sourceHistoryMessages ? this.estimateConversationBreakdown(details.sourceHistoryMessages, {
|
|
8789
|
+
useDeclaredToolResultSizes: true
|
|
8790
|
+
}) : conversationBreakdown;
|
|
8041
8791
|
const currentTurnTokens = this.estimateTextTokens(details.currentTurnContent);
|
|
8042
8792
|
const toolDefinitionTokens = this.estimateToolDefinitionTokens(
|
|
8043
8793
|
details.localTools,
|
|
@@ -8054,15 +8804,26 @@ ${details.summaryText}
|
|
|
8054
8804
|
|
|
8055
8805
|
Do NOT redo any of the above work.`
|
|
8056
8806
|
) : void 0;
|
|
8807
|
+
const sendEstimatedInputTokens = conversationBreakdown.estimatedInputTokens + currentTurnTokens + toolDefinitionTokens;
|
|
8808
|
+
const estimatedInputTokens = sourceConversationBreakdown.estimatedInputTokens + currentTurnTokens + toolDefinitionTokens;
|
|
8809
|
+
const toolOutputReductionTokens = Math.max(
|
|
8810
|
+
0,
|
|
8811
|
+
sourceConversationBreakdown.toolOutputTokens - conversationBreakdown.toolOutputTokens
|
|
8812
|
+
);
|
|
8057
8813
|
return {
|
|
8058
|
-
historyTokens:
|
|
8059
|
-
toolOutputTokens:
|
|
8814
|
+
historyTokens: sourceConversationBreakdown.historyTokens,
|
|
8815
|
+
toolOutputTokens: sourceConversationBreakdown.toolOutputTokens,
|
|
8060
8816
|
currentTurnTokens,
|
|
8061
8817
|
toolDefinitionTokens,
|
|
8062
8818
|
...summaryTokens ? { summaryTokens } : {},
|
|
8063
8819
|
...reservedOutputTokens ? { reservedOutputTokens } : {},
|
|
8064
8820
|
...effectiveInputBudgetTokens ? { effectiveInputBudgetTokens } : {},
|
|
8065
|
-
|
|
8821
|
+
...toolOutputReductionTokens > 0 ? {
|
|
8822
|
+
sendEstimatedInputTokens,
|
|
8823
|
+
sendToolOutputTokens: conversationBreakdown.toolOutputTokens,
|
|
8824
|
+
toolOutputReductionTokens
|
|
8825
|
+
} : {},
|
|
8826
|
+
estimatedInputTokens
|
|
8066
8827
|
};
|
|
8067
8828
|
}
|
|
8068
8829
|
async emitContextCompactionEvent(onContextCompaction, event) {
|
|
@@ -8102,16 +8863,33 @@ Do NOT redo any of the above work.`
|
|
|
8102
8863
|
state,
|
|
8103
8864
|
userContent,
|
|
8104
8865
|
details.compactInstructions,
|
|
8105
|
-
details.mode
|
|
8866
|
+
details.mode,
|
|
8867
|
+
details.artifactReferences
|
|
8106
8868
|
);
|
|
8869
|
+
const summaryMessage = compactMessages[0];
|
|
8870
|
+
if (summaryMessage?.role === "system" && typeof summaryMessage.content === "string") {
|
|
8871
|
+
const existingSummaries = state.contextCompactionSummaries ?? [];
|
|
8872
|
+
state.contextCompactionSummaries = [
|
|
8873
|
+
...existingSummaries,
|
|
8874
|
+
{
|
|
8875
|
+
id: `ctx_${sessionIndex + 1}_${existingSummaries.length + 1}`,
|
|
8876
|
+
sessionIndex: sessionIndex + 1,
|
|
8877
|
+
mode: details.mode,
|
|
8878
|
+
strategy: details.strategy,
|
|
8879
|
+
content: summaryMessage.content,
|
|
8880
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8881
|
+
}
|
|
8882
|
+
].slice(-20);
|
|
8883
|
+
}
|
|
8884
|
+
state.contextWindowBaseIndex = state.messages?.length ?? 0;
|
|
8107
8885
|
await this.emitContextCompactionEvent(details.onContextCompaction, {
|
|
8108
8886
|
phase: "complete",
|
|
8109
8887
|
...baseEvent
|
|
8110
8888
|
});
|
|
8111
8889
|
return compactMessages;
|
|
8112
8890
|
}
|
|
8113
|
-
buildCompactHistoryMessages(state, userContent, compactInstructions, mode = "auto") {
|
|
8114
|
-
const summary = this.generateCompactSummary(state, compactInstructions);
|
|
8891
|
+
buildCompactHistoryMessages(state, userContent, compactInstructions, mode = "auto", artifactReferences) {
|
|
8892
|
+
const summary = this.generateCompactSummary(state, compactInstructions, artifactReferences);
|
|
8115
8893
|
const prefix = mode === "forced" ? this.getForcedCompactionSummaryPrefix(state) : _AgentsEndpoint.AUTO_COMPACT_SUMMARY_PREFIX;
|
|
8116
8894
|
return [
|
|
8117
8895
|
{
|
|
@@ -8128,16 +8906,11 @@ Do NOT redo any of the above work.`
|
|
|
8128
8906
|
}
|
|
8129
8907
|
];
|
|
8130
8908
|
}
|
|
8131
|
-
isCompactHistoryMessageSet(messages) {
|
|
8132
|
-
if (messages.length === 0) return false;
|
|
8133
|
-
const firstMessage = messages[0];
|
|
8134
|
-
return firstMessage?.role === "system" && typeof firstMessage.content === "string" && (firstMessage.content.startsWith(_AgentsEndpoint.AUTO_COMPACT_SUMMARY_PREFIX) || firstMessage.content.startsWith(_AgentsEndpoint.RESUMED_COMPACT_SUMMARY_PREFIX) || firstMessage.content.startsWith(_AgentsEndpoint.COMPLETED_COMPACT_SUMMARY_PREFIX));
|
|
8135
|
-
}
|
|
8136
8909
|
/**
|
|
8137
8910
|
* Generate a compact summary of prior work for continuation context.
|
|
8138
8911
|
* Used when compact mode is enabled to keep token usage low.
|
|
8139
8912
|
*/
|
|
8140
|
-
generateCompactSummary(state, compactInstructions) {
|
|
8913
|
+
generateCompactSummary(state, compactInstructions, additionalArtifactReferences = []) {
|
|
8141
8914
|
const recentSessions = (state.sessions ?? []).slice(-5);
|
|
8142
8915
|
const sessionSummaries = recentSessions.map(
|
|
8143
8916
|
(session) => `- Session ${session.index}: ${session.stopReason} ($${session.cost.toFixed(4)}) ${session.outputPreview.slice(0, 160)}`
|
|
@@ -8151,7 +8924,7 @@ Do NOT redo any of the above work.`
|
|
|
8151
8924
|
)
|
|
8152
8925
|
).slice(0, 8);
|
|
8153
8926
|
const verificationSummary = state.bestCandidateVerified ? "Latest candidate verified." : state.bestCandidateNeedsVerification ? "Latest candidate still needs verification." : state.lastVerificationPassed ? "Latest verification passed." : state.verificationRequired ? "Verification is still required." : "No verification requirement recorded.";
|
|
8154
|
-
const artifactReferences = this.extractArtifactReferences(state);
|
|
8927
|
+
const artifactReferences = this.extractArtifactReferences(state, additionalArtifactReferences);
|
|
8155
8928
|
const pendingNextStep = state.lastStopReason === "complete" ? "Confirm nothing else remains before declaring the task complete." : `Continue the ${state.workflowPhase || "research"} phase without redoing prior work.`;
|
|
8156
8929
|
const instructions = compactInstructions || this.buildDefaultCompactInstructions();
|
|
8157
8930
|
return [
|
|
@@ -8366,14 +9139,23 @@ Do NOT redo any of the above work.`
|
|
|
8366
9139
|
const phaseBlock = ["", this.buildPhaseInstructions(state, wf)].join("\n");
|
|
8367
9140
|
const candidateBlock = wf.buildCandidateBlock?.(state) ?? "";
|
|
8368
9141
|
const multiSessionInstruction = `This is a multi-session task (session ${sessionIndex + 1}/${maxSessions}). When you have fully completed the task, end your response with TASK_COMPLETE on its own line.`;
|
|
8369
|
-
const steeringLines = steeringMessages && steeringMessages.length > 0 ? [
|
|
8370
|
-
"--- User steering (queued during the previous session) ---",
|
|
8371
|
-
...steeringMessages,
|
|
8372
|
-
""
|
|
8373
|
-
] : [];
|
|
9142
|
+
const steeringLines = steeringMessages && steeringMessages.length > 0 ? ["--- User steering (queued during the previous session) ---", ...steeringMessages, ""] : [];
|
|
8374
9143
|
if (continuationContext && sessionIndex === 0) {
|
|
8375
|
-
const
|
|
8376
|
-
|
|
9144
|
+
const resumeWindow = this.resolveWindowReplay(
|
|
9145
|
+
state,
|
|
9146
|
+
continuationContext.previousMessages.length
|
|
9147
|
+
);
|
|
9148
|
+
const sourceReplayHistoryMessages = [
|
|
9149
|
+
...resumeWindow.windowSummaryMessages,
|
|
9150
|
+
...this.sanitizeReplayHistoryMessages(
|
|
9151
|
+
continuationContext.previousMessages.slice(resumeWindow.windowBase)
|
|
9152
|
+
)
|
|
9153
|
+
];
|
|
9154
|
+
const replayHistoryMessages = this.deriveToolContextMessages(
|
|
9155
|
+
sourceReplayHistoryMessages,
|
|
9156
|
+
state.taskName,
|
|
9157
|
+
compactionOptions?.toolContextMode || "hot-tail",
|
|
9158
|
+
compactionOptions?.toolWindow ?? "session"
|
|
8377
9159
|
);
|
|
8378
9160
|
const continuationGuardrail = this.buildContinuationGuardrail(state);
|
|
8379
9161
|
const defaultContinueMessage = "Continue the task. Review your prior work above and proceed with any remaining work. If everything is already complete, respond with TASK_COMPLETE.";
|
|
@@ -8397,9 +9179,15 @@ Do NOT redo any of the above work.`
|
|
|
8397
9179
|
content: userContent
|
|
8398
9180
|
}
|
|
8399
9181
|
];
|
|
8400
|
-
const
|
|
9182
|
+
const replayArtifactReferences = this.extractArtifactReferencesFromMessages(replayHistoryMessages);
|
|
9183
|
+
const summaryText = this.generateCompactSummary(
|
|
9184
|
+
state,
|
|
9185
|
+
compactInstructions,
|
|
9186
|
+
replayArtifactReferences
|
|
9187
|
+
);
|
|
8401
9188
|
const breakdown = this.buildContextBudgetBreakdown({
|
|
8402
9189
|
historyMessages: replayHistoryMessages,
|
|
9190
|
+
sourceHistoryMessages: sourceReplayHistoryMessages,
|
|
8403
9191
|
currentTurnContent: userContent,
|
|
8404
9192
|
localTools: compactionOptions?.localTools,
|
|
8405
9193
|
builtinToolSchemas: compactionOptions?.builtinToolSchemas || [],
|
|
@@ -8425,7 +9213,8 @@ Do NOT redo any of the above work.`
|
|
|
8425
9213
|
reservedOutputTokens: breakdown.reservedOutputTokens,
|
|
8426
9214
|
breakdown,
|
|
8427
9215
|
onContextCompaction: compactionOptions?.onContextCompaction,
|
|
8428
|
-
compactInstructions
|
|
9216
|
+
compactInstructions,
|
|
9217
|
+
artifactReferences: replayArtifactReferences
|
|
8429
9218
|
}
|
|
8430
9219
|
),
|
|
8431
9220
|
requestContextManagement
|
|
@@ -8449,7 +9238,8 @@ Do NOT redo any of the above work.`
|
|
|
8449
9238
|
reservedOutputTokens: breakdown.reservedOutputTokens,
|
|
8450
9239
|
breakdown,
|
|
8451
9240
|
onContextCompaction: compactionOptions?.onContextCompaction,
|
|
8452
|
-
compactInstructions
|
|
9241
|
+
compactInstructions,
|
|
9242
|
+
artifactReferences: replayArtifactReferences
|
|
8453
9243
|
}
|
|
8454
9244
|
),
|
|
8455
9245
|
requestContextManagement
|
|
@@ -8500,23 +9290,45 @@ Do NOT redo any of the above work.`
|
|
|
8500
9290
|
"Do not redo previous work. If the task is already complete, respond with TASK_COMPLETE."
|
|
8501
9291
|
].join("\n");
|
|
8502
9292
|
const MAX_HISTORY_MESSAGES = 60;
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
9293
|
+
const { windowBase, windowSummaryMessages } = this.resolveWindowReplay(
|
|
9294
|
+
state,
|
|
9295
|
+
state.messages.length
|
|
9296
|
+
);
|
|
9297
|
+
let sourceHistoryMessages = this.sanitizeReplayHistoryMessages(
|
|
9298
|
+
state.messages.slice(windowBase)
|
|
9299
|
+
);
|
|
9300
|
+
if (sourceHistoryMessages.length > MAX_HISTORY_MESSAGES) {
|
|
9301
|
+
const trimmedHistory = this.trimReplayHistoryMessages(
|
|
9302
|
+
sourceHistoryMessages,
|
|
9303
|
+
MAX_HISTORY_MESSAGES
|
|
9304
|
+
);
|
|
9305
|
+
sourceHistoryMessages = trimmedHistory.historyMessages;
|
|
8507
9306
|
if (trimmedHistory.trimmedCount > 0) {
|
|
8508
|
-
|
|
9307
|
+
sourceHistoryMessages = [
|
|
8509
9308
|
{
|
|
8510
9309
|
role: "system",
|
|
8511
9310
|
content: `[${trimmedHistory.trimmedCount} earlier messages trimmed to stay within context limits. Original task: ${(state.originalMessage || originalMessage).slice(0, 500)}]`
|
|
8512
9311
|
},
|
|
8513
|
-
...
|
|
9312
|
+
...sourceHistoryMessages
|
|
8514
9313
|
];
|
|
8515
9314
|
}
|
|
8516
9315
|
}
|
|
8517
|
-
|
|
9316
|
+
sourceHistoryMessages = [...windowSummaryMessages, ...sourceHistoryMessages];
|
|
9317
|
+
const historyMessages = this.deriveToolContextMessages(
|
|
9318
|
+
sourceHistoryMessages,
|
|
9319
|
+
state.taskName,
|
|
9320
|
+
compactionOptions?.toolContextMode || "hot-tail",
|
|
9321
|
+
compactionOptions?.toolWindow ?? "session"
|
|
9322
|
+
);
|
|
9323
|
+
const historyArtifactReferences = this.extractArtifactReferencesFromMessages(historyMessages);
|
|
9324
|
+
const summaryText = this.generateCompactSummary(
|
|
9325
|
+
state,
|
|
9326
|
+
compactInstructions,
|
|
9327
|
+
historyArtifactReferences
|
|
9328
|
+
);
|
|
8518
9329
|
const breakdown = this.buildContextBudgetBreakdown({
|
|
8519
9330
|
historyMessages,
|
|
9331
|
+
sourceHistoryMessages,
|
|
8520
9332
|
currentTurnContent: continuationContent,
|
|
8521
9333
|
localTools: compactionOptions?.localTools,
|
|
8522
9334
|
builtinToolSchemas: compactionOptions?.builtinToolSchemas || [],
|
|
@@ -8543,7 +9355,8 @@ Do NOT redo any of the above work.`
|
|
|
8543
9355
|
reservedOutputTokens: breakdown.reservedOutputTokens,
|
|
8544
9356
|
breakdown,
|
|
8545
9357
|
onContextCompaction: compactionOptions?.onContextCompaction,
|
|
8546
|
-
compactInstructions
|
|
9358
|
+
compactInstructions,
|
|
9359
|
+
artifactReferences: historyArtifactReferences
|
|
8547
9360
|
}
|
|
8548
9361
|
),
|
|
8549
9362
|
requestContextManagement
|
|
@@ -9017,6 +9830,52 @@ var BillingEndpoint = class {
|
|
|
9017
9830
|
return this.client.get("/billing/spend-analytics", params);
|
|
9018
9831
|
}
|
|
9019
9832
|
};
|
|
9833
|
+
var AppsEndpoint = class {
|
|
9834
|
+
constructor(client) {
|
|
9835
|
+
this.client = client;
|
|
9836
|
+
}
|
|
9837
|
+
/** List apps for the authenticated owner, newest first. */
|
|
9838
|
+
async list() {
|
|
9839
|
+
return this.client.get("/apps");
|
|
9840
|
+
}
|
|
9841
|
+
/** Get an app by id, including its URL and active version pointer. */
|
|
9842
|
+
async get(id) {
|
|
9843
|
+
return this.client.get(`/apps/${id}`);
|
|
9844
|
+
}
|
|
9845
|
+
/** Create an app. A client token scoped to the app origin is auto-provisioned. */
|
|
9846
|
+
async create(data) {
|
|
9847
|
+
return this.client.post("/apps", data);
|
|
9848
|
+
}
|
|
9849
|
+
/** Update name, description, visibility, or status (suspended serves 410). */
|
|
9850
|
+
async update(id, data) {
|
|
9851
|
+
return this.client.patch(`/apps/${id}`, data);
|
|
9852
|
+
}
|
|
9853
|
+
/** Delete an app, its versions, and its hosting. Irreversible. */
|
|
9854
|
+
async delete(id) {
|
|
9855
|
+
return this.client.delete(`/apps/${id}`);
|
|
9856
|
+
}
|
|
9857
|
+
/** List an app's versions, newest first. */
|
|
9858
|
+
async listVersions(id) {
|
|
9859
|
+
return this.client.get(`/apps/${id}/versions`);
|
|
9860
|
+
}
|
|
9861
|
+
/** Upload a zipped bundle (raw application/zip body) as a new version. */
|
|
9862
|
+
async uploadVersion(id, zipBytes) {
|
|
9863
|
+
return this.client.postBinary(`/apps/${id}/versions`, zipBytes, "application/zip");
|
|
9864
|
+
}
|
|
9865
|
+
/**
|
|
9866
|
+
* Upload a bundle from in-memory file maps (the API zips server-side).
|
|
9867
|
+
* Text files in `files`, binary files base64-encoded in `filesBase64`.
|
|
9868
|
+
*/
|
|
9869
|
+
async uploadVersionFiles(id, data) {
|
|
9870
|
+
return this.client.post(`/apps/${id}/versions`, data);
|
|
9871
|
+
}
|
|
9872
|
+
/** Activate an uploaded version (deploy or rollback). */
|
|
9873
|
+
async activate(id, versionId) {
|
|
9874
|
+
return this.client.post(`/apps/${id}/activate`, {
|
|
9875
|
+
versionId
|
|
9876
|
+
});
|
|
9877
|
+
}
|
|
9878
|
+
};
|
|
9020
9879
|
|
|
9021
9880
|
// src/client.ts
|
|
9022
9881
|
function isObjectRecord(value) {
|
|
@@ -9059,6 +9918,7 @@ var RuntypeClient2 = class {
|
|
|
9059
9918
|
this.clientTokens = new ClientTokensEndpoint(this);
|
|
9060
9919
|
this.agents = new AgentsEndpoint(this);
|
|
9061
9920
|
this.secrets = new SecretsEndpoint(this);
|
|
9921
|
+
this.apps = new AppsEndpoint(this);
|
|
9062
9922
|
this.schedules = new SchedulesEndpoint(this);
|
|
9063
9923
|
this.surfaces = new SurfacesEndpoint(this);
|
|
9064
9924
|
this.conversations = new ConversationsEndpoint(this);
|
|
@@ -9105,7 +9965,7 @@ var RuntypeClient2 = class {
|
|
|
9105
9965
|
clearApiKey() {
|
|
9106
9966
|
delete this.headers.Authorization;
|
|
9107
9967
|
}
|
|
9108
|
-
async runWithLocalTools(
|
|
9968
|
+
async runWithLocalTools(request2, localTools, arg3, arg4) {
|
|
9109
9969
|
const isOptionsObject = (val) => typeof val === "object" && val !== null && "scope" in val;
|
|
9110
9970
|
const callbacks = isOptionsObject(arg3) ? void 0 : arg3;
|
|
9111
9971
|
const options = (isOptionsObject(arg3) ? arg3 : arg4) ?? {};
|
|
@@ -9119,12 +9979,12 @@ var RuntypeClient2 = class {
|
|
|
9119
9979
|
...entry.pageOrigin ? { pageOrigin: entry.pageOrigin } : {}
|
|
9120
9980
|
})) : [];
|
|
9121
9981
|
const modifiedRequest = {
|
|
9122
|
-
...
|
|
9982
|
+
...request2,
|
|
9123
9983
|
...derivedClientTools.length > 0 ? {
|
|
9124
|
-
clientTools: [...
|
|
9984
|
+
clientTools: [...request2.clientTools ?? [], ...derivedClientTools]
|
|
9125
9985
|
} : {},
|
|
9126
9986
|
options: {
|
|
9127
|
-
...
|
|
9987
|
+
...request2.options || {},
|
|
9128
9988
|
streamResponse: isStreaming
|
|
9129
9989
|
}
|
|
9130
9990
|
};
|
|
@@ -9140,13 +10000,12 @@ var RuntypeClient2 = class {
|
|
|
9140
10000
|
onFlowComplete: (event) => callbacks?.onFlowComplete?.(event),
|
|
9141
10001
|
onError: (error) => callbacks?.onError?.(error)
|
|
9142
10002
|
};
|
|
9143
|
-
const { streamEvents: streamEvents2, stepDeltaText: stepDeltaText2, stepDisplayName: stepDisplayName2, flowErrorMessage: flowErrorMessage2 } = await Promise.resolve().then(() => (init_stream_utils(), stream_utils_exports));
|
|
9144
10003
|
const summary = {
|
|
9145
10004
|
results: /* @__PURE__ */ new Map(),
|
|
9146
10005
|
success: true
|
|
9147
10006
|
};
|
|
9148
10007
|
try {
|
|
9149
|
-
for await (const event of
|
|
10008
|
+
for await (const event of streamEvents(response)) {
|
|
9150
10009
|
collectLocalToolAwait(pausedTools, event);
|
|
9151
10010
|
switch (event.type) {
|
|
9152
10011
|
case "flow_start":
|
|
@@ -9156,10 +10015,10 @@ var RuntypeClient2 = class {
|
|
|
9156
10015
|
wrappedCallbacks.onStepStart?.(event);
|
|
9157
10016
|
break;
|
|
9158
10017
|
case "step_delta":
|
|
9159
|
-
wrappedCallbacks.onStepDelta?.(
|
|
10018
|
+
wrappedCallbacks.onStepDelta?.(stepDeltaText(event), event);
|
|
9160
10019
|
break;
|
|
9161
10020
|
case "step_complete": {
|
|
9162
|
-
summary.results?.set(
|
|
10021
|
+
summary.results?.set(stepDisplayName(event), event.result);
|
|
9163
10022
|
wrappedCallbacks.onStepComplete?.(event.result, event);
|
|
9164
10023
|
break;
|
|
9165
10024
|
}
|
|
@@ -9167,7 +10026,7 @@ var RuntypeClient2 = class {
|
|
|
9167
10026
|
wrappedCallbacks.onFlowComplete?.(event);
|
|
9168
10027
|
break;
|
|
9169
10028
|
case "flow_error":
|
|
9170
|
-
wrappedCallbacks.onError?.(new Error(
|
|
10029
|
+
wrappedCallbacks.onError?.(new Error(flowErrorMessage(event)));
|
|
9171
10030
|
break;
|
|
9172
10031
|
}
|
|
9173
10032
|
}
|
|
@@ -9246,7 +10105,8 @@ var RuntypeClient2 = class {
|
|
|
9246
10105
|
return [toolName, await handler(parameters)];
|
|
9247
10106
|
} catch (error) {
|
|
9248
10107
|
throw new Error(
|
|
9249
|
-
`Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}
|
|
10108
|
+
`Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`,
|
|
10109
|
+
{ cause: error }
|
|
9250
10110
|
);
|
|
9251
10111
|
}
|
|
9252
10112
|
})
|
|
@@ -9310,6 +10170,21 @@ var RuntypeClient2 = class {
|
|
|
9310
10170
|
});
|
|
9311
10171
|
return transformResponse(response);
|
|
9312
10172
|
}
|
|
10173
|
+
/**
|
|
10174
|
+
* POST request with a raw binary body (e.g. application/zip bundle uploads).
|
|
10175
|
+
*/
|
|
10176
|
+
async postBinary(path, body, contentType) {
|
|
10177
|
+
const url = this.buildUrl(path);
|
|
10178
|
+
const headers = { ...this.headers, "Content-Type": contentType };
|
|
10179
|
+
const response = await this.makeRequest(url, {
|
|
10180
|
+
method: "POST",
|
|
10181
|
+
headers,
|
|
10182
|
+
// TS 5.7 types Uint8Array over ArrayBufferLike, which no longer
|
|
10183
|
+
// overlaps DOM BodyInit; the runtime value is a valid fetch body.
|
|
10184
|
+
body
|
|
10185
|
+
});
|
|
10186
|
+
return transformResponse(response);
|
|
10187
|
+
}
|
|
9313
10188
|
/**
|
|
9314
10189
|
* Generic request that returns raw Response for streaming
|
|
9315
10190
|
*/
|
|
@@ -9410,7 +10285,7 @@ var RuntypeClient2 = class {
|
|
|
9410
10285
|
} catch (error) {
|
|
9411
10286
|
if (timeoutId) clearTimeout(timeoutId);
|
|
9412
10287
|
if (timeoutId && error instanceof Error && error.name === "AbortError") {
|
|
9413
|
-
throw new Error(`Request timeout after ${this.timeout}ms
|
|
10288
|
+
throw new Error(`Request timeout after ${this.timeout}ms`, { cause: error });
|
|
9414
10289
|
}
|
|
9415
10290
|
throw error;
|
|
9416
10291
|
}
|
|
@@ -9419,8 +10294,18 @@ var RuntypeClient2 = class {
|
|
|
9419
10294
|
* Make HTTP request that returns raw Response (for streaming)
|
|
9420
10295
|
*/
|
|
9421
10296
|
async makeRawRequest(url, options) {
|
|
9422
|
-
const
|
|
10297
|
+
const callerSignal = options.signal ?? null;
|
|
10298
|
+
const controller = this.timeout === null && !callerSignal ? null : new AbortController();
|
|
9423
10299
|
const timeoutId = controller && this.timeout !== null ? setTimeout(() => controller.abort(), this.timeout) : null;
|
|
10300
|
+
if (callerSignal && controller) {
|
|
10301
|
+
if (callerSignal.aborted) {
|
|
10302
|
+
controller.abort(callerSignal.reason);
|
|
10303
|
+
} else {
|
|
10304
|
+
callerSignal.addEventListener("abort", () => controller.abort(callerSignal.reason), {
|
|
10305
|
+
once: true
|
|
10306
|
+
});
|
|
10307
|
+
}
|
|
10308
|
+
}
|
|
9424
10309
|
try {
|
|
9425
10310
|
const response = await fetch(url, {
|
|
9426
10311
|
...options,
|
|
@@ -9433,8 +10318,8 @@ var RuntypeClient2 = class {
|
|
|
9433
10318
|
return response;
|
|
9434
10319
|
} catch (error) {
|
|
9435
10320
|
if (timeoutId) clearTimeout(timeoutId);
|
|
9436
|
-
if (timeoutId && error instanceof Error && error.name === "AbortError") {
|
|
9437
|
-
throw new Error(`Request timeout after ${this.timeout}ms
|
|
10321
|
+
if (timeoutId && error instanceof Error && error.name === "AbortError" && !callerSignal?.aborted) {
|
|
10322
|
+
throw new Error(`Request timeout after ${this.timeout}ms`, { cause: error });
|
|
9438
10323
|
}
|
|
9439
10324
|
throw error;
|
|
9440
10325
|
}
|
|
@@ -9480,9 +10365,6 @@ function createClient(config) {
|
|
|
9480
10365
|
return new RuntypeClient2(config);
|
|
9481
10366
|
}
|
|
9482
10367
|
|
|
9483
|
-
// src/index.ts
|
|
9484
|
-
init_stream_utils();
|
|
9485
|
-
|
|
9486
10368
|
// src/batch-builder.ts
|
|
9487
10369
|
var BatchBuilder = class {
|
|
9488
10370
|
constructor() {
|
|
@@ -9540,20 +10422,20 @@ var BatchBuilder = class {
|
|
|
9540
10422
|
if (!this.recordType) {
|
|
9541
10423
|
throw new Error("BatchBuilder: recordType is required. Call .forRecordType(type) first.");
|
|
9542
10424
|
}
|
|
9543
|
-
const
|
|
10425
|
+
const request2 = {
|
|
9544
10426
|
flowId: this.flowId,
|
|
9545
10427
|
recordType: this.recordType
|
|
9546
10428
|
};
|
|
9547
10429
|
if (Object.keys(this.batchOptions).length > 0) {
|
|
9548
|
-
|
|
10430
|
+
request2.options = this.batchOptions;
|
|
9549
10431
|
}
|
|
9550
10432
|
if (this.filterConfig) {
|
|
9551
|
-
|
|
10433
|
+
request2.filter = this.filterConfig;
|
|
9552
10434
|
}
|
|
9553
10435
|
if (this.limitConfig !== void 0) {
|
|
9554
|
-
|
|
10436
|
+
request2.limit = this.limitConfig;
|
|
9555
10437
|
}
|
|
9556
|
-
return
|
|
10438
|
+
return request2;
|
|
9557
10439
|
}
|
|
9558
10440
|
/**
|
|
9559
10441
|
* Execute the batch operation
|
|
@@ -9710,32 +10592,32 @@ var EvalBuilder = class {
|
|
|
9710
10592
|
"EvalBuilder: records are required. Call .forRecordType(type) or .withRecords([...]) first."
|
|
9711
10593
|
);
|
|
9712
10594
|
}
|
|
9713
|
-
const
|
|
10595
|
+
const request2 = {};
|
|
9714
10596
|
if (this.flowId) {
|
|
9715
|
-
|
|
10597
|
+
request2.flowId = this.flowId;
|
|
9716
10598
|
} else if (this.virtualFlow) {
|
|
9717
|
-
|
|
10599
|
+
request2.flow = this.virtualFlow;
|
|
9718
10600
|
}
|
|
9719
10601
|
if (this.recordType) {
|
|
9720
|
-
|
|
10602
|
+
request2.recordType = this.recordType;
|
|
9721
10603
|
} else if (this.inlineRecords) {
|
|
9722
|
-
|
|
10604
|
+
request2.records = this.inlineRecords;
|
|
9723
10605
|
}
|
|
9724
10606
|
if (this.modelOverrides) {
|
|
9725
|
-
|
|
10607
|
+
request2.modelOverrides = this.modelOverrides;
|
|
9726
10608
|
} else if (this.modelConfigs) {
|
|
9727
|
-
|
|
10609
|
+
request2.modelConfigs = this.modelConfigs;
|
|
9728
10610
|
}
|
|
9729
10611
|
if (Object.keys(this.evalOptions).length > 0) {
|
|
9730
|
-
|
|
10612
|
+
request2.options = this.evalOptions;
|
|
9731
10613
|
}
|
|
9732
10614
|
if (this.filterConfig) {
|
|
9733
|
-
|
|
10615
|
+
request2.filter = this.filterConfig;
|
|
9734
10616
|
}
|
|
9735
10617
|
if (this.limitConfig !== void 0) {
|
|
9736
|
-
|
|
10618
|
+
request2.limit = this.limitConfig;
|
|
9737
10619
|
}
|
|
9738
|
-
return
|
|
10620
|
+
return request2;
|
|
9739
10621
|
}
|
|
9740
10622
|
/**
|
|
9741
10623
|
* Execute the evaluation
|
|
@@ -10202,10 +11084,14 @@ var STEP_TYPE_TO_METHOD = {
|
|
|
10202
11084
|
};
|
|
10203
11085
|
// Annotate the CommonJS export names for ESM import in node:
|
|
10204
11086
|
0 && (module.exports = {
|
|
11087
|
+
AgentDriftError,
|
|
11088
|
+
AgentEnsureConflictError,
|
|
10205
11089
|
AgentVersionsEndpoint,
|
|
10206
11090
|
AgentsEndpoint,
|
|
11091
|
+
AgentsNamespace,
|
|
10207
11092
|
AnalyticsEndpoint,
|
|
10208
11093
|
ApiKeysEndpoint,
|
|
11094
|
+
AppsEndpoint,
|
|
10209
11095
|
BatchBuilder,
|
|
10210
11096
|
BatchesNamespace,
|
|
10211
11097
|
BillingEndpoint,
|
|
@@ -10222,12 +11108,15 @@ var STEP_TYPE_TO_METHOD = {
|
|
|
10222
11108
|
EvalRunner,
|
|
10223
11109
|
EvalsNamespace,
|
|
10224
11110
|
FlowBuilder,
|
|
11111
|
+
FlowDriftError,
|
|
11112
|
+
FlowEnsureConflictError,
|
|
10225
11113
|
FlowResult,
|
|
10226
11114
|
FlowStepsEndpoint,
|
|
10227
11115
|
FlowVersionsEndpoint,
|
|
10228
11116
|
FlowsEndpoint,
|
|
10229
11117
|
FlowsNamespace,
|
|
10230
11118
|
IntegrationsEndpoint,
|
|
11119
|
+
LEDGER_ARTIFACT_LINE_PREFIX,
|
|
10231
11120
|
LogsEndpoint,
|
|
10232
11121
|
ModelConfigsEndpoint,
|
|
10233
11122
|
PromptRunner,
|
|
@@ -10251,19 +11140,29 @@ var STEP_TYPE_TO_METHOD = {
|
|
|
10251
11140
|
applyGeneratedRuntimeToolProposalToDispatchRequest,
|
|
10252
11141
|
attachRuntimeToolsToDispatchRequest,
|
|
10253
11142
|
buildGeneratedRuntimeToolGateOutput,
|
|
11143
|
+
buildLedgerOffloadReference,
|
|
11144
|
+
buildSendViewOffloadMarker,
|
|
11145
|
+
computeAgentContentHash,
|
|
11146
|
+
computeFlowContentHash,
|
|
10254
11147
|
createClient,
|
|
10255
11148
|
createExternalTool,
|
|
10256
11149
|
defaultWorkflow,
|
|
11150
|
+
defineAgent,
|
|
11151
|
+
defineFlow,
|
|
10257
11152
|
deployWorkflow,
|
|
10258
11153
|
evaluateGeneratedRuntimeToolProposal,
|
|
11154
|
+
extractDeclaredToolResultChars,
|
|
10259
11155
|
gameWorkflow,
|
|
10260
11156
|
getDefaultPlanPath,
|
|
10261
11157
|
getLikelySupportingCandidatePaths,
|
|
10262
11158
|
isDiscoveryToolName,
|
|
10263
11159
|
isMarathonArtifactPath,
|
|
10264
11160
|
isPreservationSensitiveTask,
|
|
11161
|
+
normalizeAgentDefinition,
|
|
10265
11162
|
normalizeCandidatePath,
|
|
10266
11163
|
parseFinalBuffer,
|
|
11164
|
+
parseLedgerArtifactRelativePath,
|
|
11165
|
+
parseOffloadedOutputId,
|
|
10267
11166
|
parseSSEChunk,
|
|
10268
11167
|
processStream,
|
|
10269
11168
|
sanitizeTaskSlug,
|