@runtypelabs/sdk 4.9.0 → 4.11.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 +1782 -377
- package/dist/index.d.cts +2003 -87
- package/dist/index.d.ts +2003 -87
- package/dist/index.mjs +1662 -298
- 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,113 @@ 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
|
+
DEFAULT_RECOVERY_AFTER_EMPTY_SESSIONS: () => DEFAULT_RECOVERY_AFTER_EMPTY_SESSIONS,
|
|
42
|
+
DEFAULT_STALL_STOP_AFTER: () => DEFAULT_STALL_STOP_AFTER,
|
|
43
|
+
DispatchEndpoint: () => DispatchEndpoint,
|
|
44
|
+
EvalBuilder: () => EvalBuilder,
|
|
45
|
+
EvalEndpoint: () => EvalEndpoint,
|
|
46
|
+
EvalRunner: () => EvalRunner,
|
|
47
|
+
EvalsNamespace: () => EvalsNamespace,
|
|
48
|
+
FlowBuilder: () => FlowBuilder,
|
|
49
|
+
FlowDriftError: () => FlowDriftError,
|
|
50
|
+
FlowEnsureConflictError: () => FlowEnsureConflictError,
|
|
51
|
+
FlowResult: () => FlowResult,
|
|
52
|
+
FlowStepsEndpoint: () => FlowStepsEndpoint,
|
|
53
|
+
FlowVersionsEndpoint: () => FlowVersionsEndpoint,
|
|
54
|
+
FlowsEndpoint: () => FlowsEndpoint,
|
|
55
|
+
FlowsNamespace: () => FlowsNamespace,
|
|
56
|
+
IntegrationsEndpoint: () => IntegrationsEndpoint,
|
|
57
|
+
LEDGER_ARTIFACT_LINE_PREFIX: () => LEDGER_ARTIFACT_LINE_PREFIX,
|
|
58
|
+
LogsEndpoint: () => LogsEndpoint,
|
|
59
|
+
ModelConfigsEndpoint: () => ModelConfigsEndpoint,
|
|
60
|
+
PromptRunner: () => PromptRunner,
|
|
61
|
+
PromptsEndpoint: () => PromptsEndpoint,
|
|
62
|
+
PromptsNamespace: () => PromptsNamespace,
|
|
63
|
+
ProviderKeysEndpoint: () => ProviderKeysEndpoint,
|
|
64
|
+
RecordsEndpoint: () => RecordsEndpoint,
|
|
65
|
+
Runtype: () => Runtype,
|
|
66
|
+
RuntypeApiError: () => RuntypeApiError,
|
|
67
|
+
RuntypeClient: () => RuntypeClient2,
|
|
68
|
+
RuntypeFlowBuilder: () => RuntypeFlowBuilder,
|
|
69
|
+
STEP_FIELD_REGISTRY: () => STEP_FIELD_REGISTRY,
|
|
70
|
+
STEP_TYPE_TO_METHOD: () => STEP_TYPE_TO_METHOD,
|
|
71
|
+
SchedulesEndpoint: () => SchedulesEndpoint,
|
|
72
|
+
SecretsEndpoint: () => SecretsEndpoint,
|
|
73
|
+
SkillProposalsNamespace: () => SkillProposalsNamespace,
|
|
74
|
+
SkillsNamespace: () => SkillsNamespace,
|
|
75
|
+
SurfacesEndpoint: () => SurfacesEndpoint,
|
|
76
|
+
ToolsEndpoint: () => ToolsEndpoint,
|
|
77
|
+
UsersEndpoint: () => UsersEndpoint,
|
|
78
|
+
applyGeneratedRuntimeToolProposalToDispatchRequest: () => applyGeneratedRuntimeToolProposalToDispatchRequest,
|
|
79
|
+
attachRuntimeToolsToDispatchRequest: () => attachRuntimeToolsToDispatchRequest,
|
|
80
|
+
buildEmptySessionNudge: () => buildEmptySessionNudge,
|
|
81
|
+
buildGeneratedRuntimeToolGateOutput: () => buildGeneratedRuntimeToolGateOutput,
|
|
82
|
+
buildLedgerOffloadReference: () => buildLedgerOffloadReference,
|
|
83
|
+
buildPolicyGuidance: () => buildPolicyGuidance,
|
|
84
|
+
buildSendViewOffloadMarker: () => buildSendViewOffloadMarker,
|
|
85
|
+
compileWorkflowConfig: () => compileWorkflowConfig,
|
|
86
|
+
computeAgentContentHash: () => computeAgentContentHash,
|
|
87
|
+
computeFlowContentHash: () => computeFlowContentHash,
|
|
88
|
+
createClient: () => createClient,
|
|
89
|
+
createExternalTool: () => createExternalTool,
|
|
90
|
+
defaultWorkflow: () => defaultWorkflow,
|
|
91
|
+
defaultWorkflowConfig: () => defaultWorkflowConfig,
|
|
92
|
+
defineAgent: () => defineAgent,
|
|
93
|
+
defineFlow: () => defineFlow,
|
|
94
|
+
definePlaybook: () => definePlaybook,
|
|
95
|
+
deployWorkflow: () => deployWorkflow,
|
|
96
|
+
ensureDefaultWorkflowHooks: () => ensureDefaultWorkflowHooks,
|
|
97
|
+
evaluateGeneratedRuntimeToolProposal: () => evaluateGeneratedRuntimeToolProposal,
|
|
98
|
+
extractDeclaredToolResultChars: () => extractDeclaredToolResultChars,
|
|
99
|
+
gameWorkflow: () => gameWorkflow,
|
|
100
|
+
getDefaultPlanPath: () => getDefaultPlanPath,
|
|
101
|
+
getLikelySupportingCandidatePaths: () => getLikelySupportingCandidatePaths,
|
|
102
|
+
interpolateWorkflowTemplate: () => interpolateWorkflowTemplate,
|
|
103
|
+
isDiscoveryToolName: () => isDiscoveryToolName,
|
|
104
|
+
isMarathonArtifactPath: () => isMarathonArtifactPath,
|
|
105
|
+
isPreservationSensitiveTask: () => isPreservationSensitiveTask,
|
|
106
|
+
isWorkflowHookRef: () => isWorkflowHookRef,
|
|
107
|
+
listWorkflowHooks: () => listWorkflowHooks,
|
|
108
|
+
normalizeAgentDefinition: () => normalizeAgentDefinition,
|
|
109
|
+
normalizeCandidatePath: () => normalizeCandidatePath,
|
|
27
110
|
parseFinalBuffer: () => parseFinalBuffer,
|
|
111
|
+
parseLedgerArtifactRelativePath: () => parseLedgerArtifactRelativePath,
|
|
112
|
+
parseOffloadedOutputId: () => parseOffloadedOutputId,
|
|
28
113
|
parseSSEChunk: () => parseSSEChunk,
|
|
29
114
|
processStream: () => processStream,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
115
|
+
registerWorkflowHook: () => registerWorkflowHook,
|
|
116
|
+
resolveStallStopAfter: () => resolveStallStopAfter,
|
|
117
|
+
resolveWorkflowHook: () => resolveWorkflowHook,
|
|
118
|
+
sanitizeTaskSlug: () => sanitizeTaskSlug,
|
|
119
|
+
shouldInjectEmptySessionNudge: () => shouldInjectEmptySessionNudge,
|
|
120
|
+
shouldRequestModelEscalation: () => shouldRequestModelEscalation,
|
|
121
|
+
streamEvents: () => streamEvents,
|
|
122
|
+
unregisterWorkflowHook: () => unregisterWorkflowHook
|
|
33
123
|
});
|
|
124
|
+
module.exports = __toCommonJS(index_exports);
|
|
125
|
+
|
|
126
|
+
// src/stream-utils.ts
|
|
34
127
|
function parseSSEChunk(chunk, buffer) {
|
|
35
128
|
buffer += chunk;
|
|
36
129
|
const lines = buffer.split("\n");
|
|
@@ -280,86 +373,8 @@ async function* streamEvents(response) {
|
|
|
280
373
|
reader.releaseLock();
|
|
281
374
|
}
|
|
282
375
|
}
|
|
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
376
|
|
|
361
377
|
// src/flow-result.ts
|
|
362
|
-
init_stream_utils();
|
|
363
378
|
var FlowResult = class {
|
|
364
379
|
constructor(response, summary) {
|
|
365
380
|
this.consumed = false;
|
|
@@ -495,7 +510,6 @@ var FlowResult = class {
|
|
|
495
510
|
};
|
|
496
511
|
|
|
497
512
|
// src/flow-builder.ts
|
|
498
|
-
init_stream_utils();
|
|
499
513
|
async function validateInlineFlow(client, args, savedFlowHint) {
|
|
500
514
|
if (args.existingFlowId) {
|
|
501
515
|
throw new Error(
|
|
@@ -1205,20 +1219,20 @@ var FlowBuilder = class {
|
|
|
1205
1219
|
*/
|
|
1206
1220
|
build() {
|
|
1207
1221
|
const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
|
|
1208
|
-
const
|
|
1222
|
+
const request2 = { flow };
|
|
1209
1223
|
if (this.recordConfig) {
|
|
1210
|
-
|
|
1224
|
+
request2.record = this.recordConfig;
|
|
1211
1225
|
}
|
|
1212
1226
|
if (this.messagesConfig) {
|
|
1213
|
-
|
|
1227
|
+
request2.messages = this.messagesConfig;
|
|
1214
1228
|
}
|
|
1215
1229
|
if (this.inputsConfig) {
|
|
1216
|
-
|
|
1230
|
+
request2.inputs = this.inputsConfig;
|
|
1217
1231
|
}
|
|
1218
1232
|
if (Object.keys(this.optionsConfig).length > 0) {
|
|
1219
|
-
|
|
1233
|
+
request2.options = this.optionsConfig;
|
|
1220
1234
|
}
|
|
1221
|
-
return
|
|
1235
|
+
return request2;
|
|
1222
1236
|
}
|
|
1223
1237
|
/**
|
|
1224
1238
|
* Validate this prospective flow against the public validation endpoint
|
|
@@ -1455,22 +1469,22 @@ function resolveBatchExecutionId(pausedTools) {
|
|
|
1455
1469
|
return "";
|
|
1456
1470
|
}
|
|
1457
1471
|
|
|
1458
|
-
// src/flows-
|
|
1459
|
-
function
|
|
1472
|
+
// src/flows-ensure.ts
|
|
1473
|
+
function isPlainObject(value) {
|
|
1460
1474
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1461
1475
|
}
|
|
1462
|
-
function
|
|
1463
|
-
if (!
|
|
1476
|
+
function normalizeConfigForHash(config) {
|
|
1477
|
+
if (!isPlainObject(config)) return {};
|
|
1464
1478
|
const normalized = {};
|
|
1465
1479
|
for (const key of Object.keys(config).sort()) {
|
|
1466
1480
|
const value = config[key];
|
|
1467
1481
|
if (value === void 0) continue;
|
|
1468
1482
|
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
1469
|
-
normalized[key] =
|
|
1483
|
+
normalized[key] = normalizeConfigForHash(value);
|
|
1470
1484
|
} else if (Array.isArray(value)) {
|
|
1471
1485
|
normalized[key] = value.map((item) => {
|
|
1472
1486
|
if (item !== null && typeof item === "object" && !Array.isArray(item)) {
|
|
1473
|
-
return
|
|
1487
|
+
return normalizeConfigForHash(item);
|
|
1474
1488
|
}
|
|
1475
1489
|
return item;
|
|
1476
1490
|
});
|
|
@@ -1481,28 +1495,249 @@ function normalizeConfig(config) {
|
|
|
1481
1495
|
return normalized;
|
|
1482
1496
|
}
|
|
1483
1497
|
function normalizeStepForHash(step) {
|
|
1484
|
-
const stepObj =
|
|
1498
|
+
const stepObj = isPlainObject(step) ? step : {};
|
|
1485
1499
|
return {
|
|
1486
1500
|
type: typeof stepObj.type === "string" ? stepObj.type : "",
|
|
1487
1501
|
name: typeof stepObj.name === "string" ? stepObj.name : "",
|
|
1488
1502
|
enabled: stepObj.enabled !== false,
|
|
1489
1503
|
...typeof stepObj.when === "string" ? { when: stepObj.when } : {},
|
|
1490
|
-
config:
|
|
1504
|
+
config: normalizeConfigForHash(stepObj.config),
|
|
1491
1505
|
order: typeof stepObj.order === "number" ? stepObj.order : 0
|
|
1492
1506
|
};
|
|
1493
1507
|
}
|
|
1494
1508
|
async function computeFlowContentHash(steps) {
|
|
1495
1509
|
const normalized = [...steps].sort((a, b) => {
|
|
1496
|
-
const orderA =
|
|
1497
|
-
const orderB =
|
|
1510
|
+
const orderA = isPlainObject(a) && typeof a.order === "number" ? a.order : 0;
|
|
1511
|
+
const orderB = isPlainObject(b) && typeof b.order === "number" ? b.order : 0;
|
|
1498
1512
|
return orderA - orderB;
|
|
1499
1513
|
}).map(normalizeStepForHash);
|
|
1500
1514
|
const serialized = JSON.stringify(normalized);
|
|
1501
1515
|
const encoded = new TextEncoder().encode(serialized);
|
|
1502
1516
|
const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
|
|
1503
|
-
|
|
1504
|
-
|
|
1517
|
+
return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1518
|
+
}
|
|
1519
|
+
var DEFINE_FLOW_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "steps"]);
|
|
1520
|
+
var DEFINE_FLOW_STEP_KEYS = /* @__PURE__ */ new Set([
|
|
1521
|
+
"type",
|
|
1522
|
+
"name",
|
|
1523
|
+
"order",
|
|
1524
|
+
"enabled",
|
|
1525
|
+
"when",
|
|
1526
|
+
"config"
|
|
1527
|
+
]);
|
|
1528
|
+
function collectStepNonPortableToolRefs(config, path) {
|
|
1529
|
+
const found = [];
|
|
1530
|
+
const tools = config.tools;
|
|
1531
|
+
const isAccountScoped = (ref) => typeof ref === "string" && ref.startsWith("tool_");
|
|
1532
|
+
const scanArray = (value, subPath) => {
|
|
1533
|
+
if (!Array.isArray(value)) return;
|
|
1534
|
+
value.forEach((ref, i) => {
|
|
1535
|
+
if (isAccountScoped(ref)) found.push(`${subPath}[${i}]`);
|
|
1536
|
+
});
|
|
1537
|
+
};
|
|
1538
|
+
const scanKeys = (value, subPath) => {
|
|
1539
|
+
if (!isPlainObject(value)) return;
|
|
1540
|
+
for (const key of Object.keys(value)) {
|
|
1541
|
+
if (isAccountScoped(key)) found.push(`${subPath}.${key}`);
|
|
1542
|
+
}
|
|
1543
|
+
};
|
|
1544
|
+
if (isPlainObject(tools)) {
|
|
1545
|
+
scanArray(tools.toolIds, `${path}.tools.toolIds`);
|
|
1546
|
+
scanKeys(tools.toolConfigs, `${path}.tools.toolConfigs`);
|
|
1547
|
+
scanKeys(tools.perToolLimits, `${path}.tools.perToolLimits`);
|
|
1548
|
+
if (isPlainObject(tools.approval)) {
|
|
1549
|
+
scanArray(tools.approval.require, `${path}.tools.approval.require`);
|
|
1550
|
+
}
|
|
1551
|
+
if (isPlainObject(tools.subagentConfig)) {
|
|
1552
|
+
scanArray(tools.subagentConfig.toolPool, `${path}.tools.subagentConfig.toolPool`);
|
|
1553
|
+
}
|
|
1554
|
+
if (isPlainObject(tools.codeModeConfig)) {
|
|
1555
|
+
scanArray(tools.codeModeConfig.toolPool, `${path}.tools.codeModeConfig.toolPool`);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
for (const branch of ["trueSteps", "falseSteps"]) {
|
|
1559
|
+
const nested = config[branch];
|
|
1560
|
+
if (!Array.isArray(nested)) continue;
|
|
1561
|
+
nested.forEach((nestedStep, i) => {
|
|
1562
|
+
if (isPlainObject(nestedStep) && isPlainObject(nestedStep.config)) {
|
|
1563
|
+
found.push(
|
|
1564
|
+
...collectStepNonPortableToolRefs(
|
|
1565
|
+
nestedStep.config,
|
|
1566
|
+
`${path}.${branch}[${i}].config`
|
|
1567
|
+
)
|
|
1568
|
+
);
|
|
1569
|
+
}
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
return found;
|
|
1573
|
+
}
|
|
1574
|
+
function defineFlow(input) {
|
|
1575
|
+
if (!input || typeof input !== "object") {
|
|
1576
|
+
throw new Error("defineFlow requires a definition object");
|
|
1577
|
+
}
|
|
1578
|
+
if (typeof input.name !== "string" || input.name.length === 0) {
|
|
1579
|
+
throw new Error('defineFlow requires a non-empty string "name"');
|
|
1580
|
+
}
|
|
1581
|
+
const unknownKeys = Object.keys(input).filter((key) => !DEFINE_FLOW_TOP_LEVEL_KEYS.has(key));
|
|
1582
|
+
if (unknownKeys.length > 0) {
|
|
1583
|
+
throw new Error(
|
|
1584
|
+
`defineFlow: unknown field(s): ${unknownKeys.join(", ")}. Allowed fields are name and steps. (Description is not part of the v1 ensure surface.)`
|
|
1585
|
+
);
|
|
1586
|
+
}
|
|
1587
|
+
if (!Array.isArray(input.steps) || input.steps.length === 0) {
|
|
1588
|
+
throw new Error('defineFlow requires a non-empty "steps" array');
|
|
1589
|
+
}
|
|
1590
|
+
const steps = input.steps.map((step, index) => {
|
|
1591
|
+
if (!isPlainObject(step)) {
|
|
1592
|
+
throw new Error(`defineFlow: steps[${index}] must be an object`);
|
|
1593
|
+
}
|
|
1594
|
+
if (typeof step.type !== "string" || step.type.length === 0) {
|
|
1595
|
+
throw new Error(`defineFlow: steps[${index}] requires a non-empty string "type"`);
|
|
1596
|
+
}
|
|
1597
|
+
if (typeof step.name !== "string" || step.name.length === 0) {
|
|
1598
|
+
throw new Error(`defineFlow: steps[${index}] requires a non-empty string "name"`);
|
|
1599
|
+
}
|
|
1600
|
+
const unknownStepKeys = Object.keys(step).filter((key) => !DEFINE_FLOW_STEP_KEYS.has(key));
|
|
1601
|
+
if (unknownStepKeys.length > 0) {
|
|
1602
|
+
throw new Error(
|
|
1603
|
+
`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.)`
|
|
1604
|
+
);
|
|
1605
|
+
}
|
|
1606
|
+
const config = isPlainObject(step.config) ? step.config : void 0;
|
|
1607
|
+
if (config) {
|
|
1608
|
+
const nonPortable = collectStepNonPortableToolRefs(config, `steps[${index}].config`);
|
|
1609
|
+
if (nonPortable.length > 0) {
|
|
1610
|
+
throw new Error(
|
|
1611
|
+
`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.`
|
|
1612
|
+
);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
return {
|
|
1616
|
+
type: step.type,
|
|
1617
|
+
name: step.name,
|
|
1618
|
+
// Explicit 1-based order (the flow builder's convention) so the local
|
|
1619
|
+
// probe hash agrees with the server's persisted step order.
|
|
1620
|
+
order: typeof step.order === "number" ? step.order : index + 1,
|
|
1621
|
+
...step.enabled !== void 0 ? { enabled: step.enabled } : {},
|
|
1622
|
+
...typeof step.when === "string" ? { when: step.when } : {},
|
|
1623
|
+
...config ? { config } : {}
|
|
1624
|
+
};
|
|
1625
|
+
});
|
|
1626
|
+
return { name: input.name, steps };
|
|
1627
|
+
}
|
|
1628
|
+
var FlowEnsureConflictError = class extends Error {
|
|
1629
|
+
constructor(body) {
|
|
1630
|
+
super(body.error ?? `Flow ensure conflict: ${body.code}`);
|
|
1631
|
+
this.name = "FlowEnsureConflictError";
|
|
1632
|
+
this.code = body.code;
|
|
1633
|
+
this.lastModifiedSource = body.lastModifiedSource;
|
|
1634
|
+
this.modifiedAt = body.modifiedAt;
|
|
1635
|
+
this.currentHash = body.currentHash;
|
|
1636
|
+
}
|
|
1637
|
+
};
|
|
1638
|
+
var FlowDriftError = class extends Error {
|
|
1639
|
+
constructor(plan) {
|
|
1640
|
+
super(
|
|
1641
|
+
`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.`
|
|
1642
|
+
);
|
|
1643
|
+
this.name = "FlowDriftError";
|
|
1644
|
+
this.plan = plan;
|
|
1645
|
+
}
|
|
1646
|
+
};
|
|
1647
|
+
function parseRequestError(err) {
|
|
1648
|
+
if (!(err instanceof Error)) return { status: null, body: null };
|
|
1649
|
+
const match = err.message.match(/^API request failed: (\d{3}) .*? - ([\s\S]*)$/);
|
|
1650
|
+
if (!match) return { status: null, body: null };
|
|
1651
|
+
try {
|
|
1652
|
+
return { status: Number(match[1]), body: JSON.parse(match[2]) };
|
|
1653
|
+
} catch {
|
|
1654
|
+
return { status: Number(match[1]), body: null };
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
function toConflictError(err) {
|
|
1658
|
+
const { status, body } = parseRequestError(err);
|
|
1659
|
+
if (status !== 409 || !isPlainObject(body)) return null;
|
|
1660
|
+
const code = body.code;
|
|
1661
|
+
if (code !== "external_modification" && code !== "remote_changed") return null;
|
|
1662
|
+
return new FlowEnsureConflictError(
|
|
1663
|
+
body
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
var serverHashMemo = /* @__PURE__ */ new WeakMap();
|
|
1667
|
+
function memoFor(client) {
|
|
1668
|
+
let memo = serverHashMemo.get(client);
|
|
1669
|
+
if (!memo) {
|
|
1670
|
+
memo = /* @__PURE__ */ new Map();
|
|
1671
|
+
serverHashMemo.set(client, memo);
|
|
1672
|
+
}
|
|
1673
|
+
return memo;
|
|
1674
|
+
}
|
|
1675
|
+
function memoize(memo, memoKey, result) {
|
|
1676
|
+
if (result.result !== "plan") memo.set(memoKey, result.contentHash);
|
|
1677
|
+
}
|
|
1678
|
+
async function request(client, body) {
|
|
1679
|
+
try {
|
|
1680
|
+
return await client.post(
|
|
1681
|
+
"/flows/ensure",
|
|
1682
|
+
body
|
|
1683
|
+
);
|
|
1684
|
+
} catch (err) {
|
|
1685
|
+
const conflict = toConflictError(err);
|
|
1686
|
+
if (conflict) throw conflict;
|
|
1687
|
+
throw err;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
async function ensureFlow(client, definition, options = {}) {
|
|
1691
|
+
const { dryRun, onConflict, release, expectedRemoteHash, expectNoChanges } = options;
|
|
1692
|
+
const passthrough = {
|
|
1693
|
+
...onConflict ? { onConflict } : {},
|
|
1694
|
+
...release ? { release } : {},
|
|
1695
|
+
...expectedRemoteHash ? { expectedRemoteHash } : {}
|
|
1696
|
+
};
|
|
1697
|
+
if (dryRun || expectNoChanges) {
|
|
1698
|
+
const plan = await request(client, {
|
|
1699
|
+
name: definition.name,
|
|
1700
|
+
definition,
|
|
1701
|
+
dryRun: true,
|
|
1702
|
+
...passthrough
|
|
1703
|
+
});
|
|
1704
|
+
if (plan.result !== "plan") {
|
|
1705
|
+
throw new Error(`Expected a plan result from dryRun, got '${plan.result}'`);
|
|
1706
|
+
}
|
|
1707
|
+
if (expectNoChanges && plan.changes !== "none") {
|
|
1708
|
+
throw new FlowDriftError(plan);
|
|
1709
|
+
}
|
|
1710
|
+
return plan;
|
|
1711
|
+
}
|
|
1712
|
+
const memo = memoFor(client);
|
|
1713
|
+
const localHash = await computeFlowContentHash(definition.steps);
|
|
1714
|
+
const memoKey = `${definition.name} ${localHash}`;
|
|
1715
|
+
const contentHash = memo.get(memoKey) ?? localHash;
|
|
1716
|
+
const probe = await request(client, {
|
|
1717
|
+
name: definition.name,
|
|
1718
|
+
contentHash,
|
|
1719
|
+
...passthrough
|
|
1720
|
+
});
|
|
1721
|
+
if (probe.result !== "definitionRequired") {
|
|
1722
|
+
memoize(memo, memoKey, probe);
|
|
1723
|
+
return probe;
|
|
1724
|
+
}
|
|
1725
|
+
const converged = await request(client, {
|
|
1726
|
+
name: definition.name,
|
|
1727
|
+
definition,
|
|
1728
|
+
...passthrough
|
|
1729
|
+
});
|
|
1730
|
+
if (converged.result === "definitionRequired") {
|
|
1731
|
+
throw new Error("Server reported definitionRequired for a full-definition request");
|
|
1732
|
+
}
|
|
1733
|
+
memoize(memo, memoKey, converged);
|
|
1734
|
+
return converged;
|
|
1735
|
+
}
|
|
1736
|
+
async function pullFlow(client, name) {
|
|
1737
|
+
return client.get("/flows/pull", { name });
|
|
1505
1738
|
}
|
|
1739
|
+
|
|
1740
|
+
// src/flows-namespace.ts
|
|
1506
1741
|
var FlowsNamespace = class {
|
|
1507
1742
|
constructor(getClient) {
|
|
1508
1743
|
this.getClient = getClient;
|
|
@@ -1510,8 +1745,11 @@ var FlowsNamespace = class {
|
|
|
1510
1745
|
/**
|
|
1511
1746
|
* Create or update a flow by name (upsert mode)
|
|
1512
1747
|
*
|
|
1513
|
-
* The recommended pattern for code-first flow management
|
|
1514
|
-
*
|
|
1748
|
+
* The recommended pattern for code-first flow management when you want to
|
|
1749
|
+
* save AND run in one dispatch. For a deploy-time, non-executing converge
|
|
1750
|
+
* (CI/CD config-as-code), use {@link ensure} instead — upsert and ensure
|
|
1751
|
+
* are siblings, not versions of each other: upsert is the runtime verb
|
|
1752
|
+
* (save-and-run), ensure is the deploy verb (converge only).
|
|
1515
1753
|
*
|
|
1516
1754
|
* @example
|
|
1517
1755
|
* ```typescript
|
|
@@ -1526,6 +1764,33 @@ var FlowsNamespace = class {
|
|
|
1526
1764
|
upsert(config) {
|
|
1527
1765
|
return new RuntypeFlowBuilder(this.getClient, "upsert", config);
|
|
1528
1766
|
}
|
|
1767
|
+
/**
|
|
1768
|
+
* Idempotently converge a `defineFlow` definition onto the platform —
|
|
1769
|
+
* the deploy-time, non-executing sibling of {@link upsert}. Hash-first:
|
|
1770
|
+
* the steady state is one tiny probe request. Creates an immutable version
|
|
1771
|
+
* snapshot on every change; never deletes; never executes the flow.
|
|
1772
|
+
*
|
|
1773
|
+
* @example
|
|
1774
|
+
* ```typescript
|
|
1775
|
+
* const def = defineFlow({ name: 'Onboarding Digest', steps: [...] })
|
|
1776
|
+
*
|
|
1777
|
+
* // Converge (CI/deploy).
|
|
1778
|
+
* const result = await Runtype.flows.ensure(def)
|
|
1779
|
+
*
|
|
1780
|
+
* // PR drift gate.
|
|
1781
|
+
* await Runtype.flows.ensure(def, { expectNoChanges: true })
|
|
1782
|
+
* ```
|
|
1783
|
+
*/
|
|
1784
|
+
async ensure(definition, options = {}) {
|
|
1785
|
+
return ensureFlow(this.getClient(), definition, options);
|
|
1786
|
+
}
|
|
1787
|
+
/**
|
|
1788
|
+
* Pull the canonical definition + provenance for a flow by name — the
|
|
1789
|
+
* absorb-drift direction of the ensure protocol.
|
|
1790
|
+
*/
|
|
1791
|
+
async pull(name) {
|
|
1792
|
+
return pullFlow(this.getClient(), name);
|
|
1793
|
+
}
|
|
1529
1794
|
/**
|
|
1530
1795
|
* Create a virtual flow (one-off, not saved)
|
|
1531
1796
|
*
|
|
@@ -2211,9 +2476,8 @@ var RuntypeFlowBuilder = class {
|
|
|
2211
2476
|
onFlowComplete: (event) => callbacks?.onFlowComplete?.(event),
|
|
2212
2477
|
onError: (error) => callbacks?.onError?.(error)
|
|
2213
2478
|
};
|
|
2214
|
-
const { streamEvents: streamEvents2, stepDeltaText: stepDeltaText2, stepDisplayName: stepDisplayName2, flowErrorMessage: flowErrorMessage2 } = await Promise.resolve().then(() => (init_stream_utils(), stream_utils_exports));
|
|
2215
2479
|
try {
|
|
2216
|
-
for await (const event of
|
|
2480
|
+
for await (const event of streamEvents(response)) {
|
|
2217
2481
|
collectLocalToolAwait(pausedTools, event);
|
|
2218
2482
|
switch (event.type) {
|
|
2219
2483
|
case "flow_start":
|
|
@@ -2223,10 +2487,10 @@ var RuntypeFlowBuilder = class {
|
|
|
2223
2487
|
wrappedCallbacks.onStepStart?.(event);
|
|
2224
2488
|
break;
|
|
2225
2489
|
case "step_delta":
|
|
2226
|
-
wrappedCallbacks.onStepDelta?.(
|
|
2490
|
+
wrappedCallbacks.onStepDelta?.(stepDeltaText(event), event);
|
|
2227
2491
|
break;
|
|
2228
2492
|
case "step_complete": {
|
|
2229
|
-
accumulatedSummary.results?.set(
|
|
2493
|
+
accumulatedSummary.results?.set(stepDisplayName(event), event.result);
|
|
2230
2494
|
wrappedCallbacks.onStepComplete?.(event.result, event);
|
|
2231
2495
|
break;
|
|
2232
2496
|
}
|
|
@@ -2234,7 +2498,7 @@ var RuntypeFlowBuilder = class {
|
|
|
2234
2498
|
wrappedCallbacks.onFlowComplete?.(event);
|
|
2235
2499
|
break;
|
|
2236
2500
|
case "flow_error":
|
|
2237
|
-
wrappedCallbacks.onError?.(new Error(
|
|
2501
|
+
wrappedCallbacks.onError?.(new Error(flowErrorMessage(event)));
|
|
2238
2502
|
break;
|
|
2239
2503
|
}
|
|
2240
2504
|
}
|
|
@@ -2309,7 +2573,8 @@ var RuntypeFlowBuilder = class {
|
|
|
2309
2573
|
return [toolName, await localTools[toolName](parameters)];
|
|
2310
2574
|
} catch (error) {
|
|
2311
2575
|
throw new Error(
|
|
2312
|
-
`Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}
|
|
2576
|
+
`Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`,
|
|
2577
|
+
{ cause: error }
|
|
2313
2578
|
);
|
|
2314
2579
|
}
|
|
2315
2580
|
})
|
|
@@ -2342,15 +2607,15 @@ var RuntypeFlowBuilder = class {
|
|
|
2342
2607
|
build() {
|
|
2343
2608
|
const flowMode = this.mode === "existing" ? "existing" : this.mode;
|
|
2344
2609
|
const flow = this.existingFlowId ? { id: this.existingFlowId } : { name: this.flowConfig.name, steps: this.steps };
|
|
2345
|
-
const
|
|
2610
|
+
const request2 = { flow };
|
|
2346
2611
|
if (this.recordConfig) {
|
|
2347
|
-
|
|
2612
|
+
request2.record = this.recordConfig;
|
|
2348
2613
|
}
|
|
2349
2614
|
if (this.messagesConfig) {
|
|
2350
|
-
|
|
2615
|
+
request2.messages = this.messagesConfig;
|
|
2351
2616
|
}
|
|
2352
2617
|
if (this.inputsConfig) {
|
|
2353
|
-
|
|
2618
|
+
request2.inputs = this.inputsConfig;
|
|
2354
2619
|
}
|
|
2355
2620
|
const options = {
|
|
2356
2621
|
flowMode,
|
|
@@ -2368,8 +2633,8 @@ var RuntypeFlowBuilder = class {
|
|
|
2368
2633
|
if (this.mode === "upsert" && Object.keys(this.upsertOptions).length > 0) {
|
|
2369
2634
|
options.upsertOptions = this.upsertOptions;
|
|
2370
2635
|
}
|
|
2371
|
-
|
|
2372
|
-
return
|
|
2636
|
+
request2.options = options;
|
|
2637
|
+
return request2;
|
|
2373
2638
|
}
|
|
2374
2639
|
/**
|
|
2375
2640
|
* Validate this prospective flow against the public validation endpoint
|
|
@@ -3029,6 +3294,8 @@ var SkillsNamespace = class {
|
|
|
3029
3294
|
}
|
|
3030
3295
|
/**
|
|
3031
3296
|
* List skills for the authenticated owner, optionally filtered by status.
|
|
3297
|
+
* Returns just the rows (one page); pass `cursor`/`limit` to page, or use
|
|
3298
|
+
* {@link listPage} when you need the pagination envelope.
|
|
3032
3299
|
*
|
|
3033
3300
|
* @example
|
|
3034
3301
|
* ```typescript
|
|
@@ -3036,10 +3303,23 @@ var SkillsNamespace = class {
|
|
|
3036
3303
|
* ```
|
|
3037
3304
|
*/
|
|
3038
3305
|
async list(params) {
|
|
3039
|
-
const
|
|
3040
|
-
const res = await client.get("/skills", params);
|
|
3306
|
+
const res = await this.listPage(params);
|
|
3041
3307
|
return res.data;
|
|
3042
3308
|
}
|
|
3309
|
+
/**
|
|
3310
|
+
* List skills with the cursor-pagination envelope (mirrors the tools list
|
|
3311
|
+
* shape: `{ data, pagination }`).
|
|
3312
|
+
*
|
|
3313
|
+
* @example
|
|
3314
|
+
* ```typescript
|
|
3315
|
+
* const page1 = await Runtype.skills.listPage({ limit: 50, includeCount: true })
|
|
3316
|
+
* const page2 = await Runtype.skills.listPage({ limit: 50, cursor: page1.pagination?.nextCursor ?? undefined })
|
|
3317
|
+
* ```
|
|
3318
|
+
*/
|
|
3319
|
+
async listPage(params) {
|
|
3320
|
+
const client = this.getClient();
|
|
3321
|
+
return client.get("/skills", params);
|
|
3322
|
+
}
|
|
3043
3323
|
/**
|
|
3044
3324
|
* Get a skill and its full version history.
|
|
3045
3325
|
*
|
|
@@ -3132,6 +3412,260 @@ var SkillsNamespace = class {
|
|
|
3132
3412
|
}
|
|
3133
3413
|
};
|
|
3134
3414
|
|
|
3415
|
+
// src/agents-namespace.ts
|
|
3416
|
+
var AGENT_CONFIG_KEYS = [
|
|
3417
|
+
"model",
|
|
3418
|
+
"systemPrompt",
|
|
3419
|
+
"temperature",
|
|
3420
|
+
"topP",
|
|
3421
|
+
"topK",
|
|
3422
|
+
"frequencyPenalty",
|
|
3423
|
+
"presencePenalty",
|
|
3424
|
+
"seed",
|
|
3425
|
+
"tools",
|
|
3426
|
+
"reasoning",
|
|
3427
|
+
"advisor",
|
|
3428
|
+
"loopConfig",
|
|
3429
|
+
"voice",
|
|
3430
|
+
"errorHandling",
|
|
3431
|
+
"artifacts",
|
|
3432
|
+
"loggingPolicy",
|
|
3433
|
+
"temporal",
|
|
3434
|
+
"memory"
|
|
3435
|
+
];
|
|
3436
|
+
var AGENT_CONFIG_KEY_LIST = [...AGENT_CONFIG_KEYS].sort();
|
|
3437
|
+
function isPlainObject2(value) {
|
|
3438
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3439
|
+
}
|
|
3440
|
+
function normalizeValue(value) {
|
|
3441
|
+
if (Array.isArray(value)) {
|
|
3442
|
+
return value.map((item) => normalizeValue(item));
|
|
3443
|
+
}
|
|
3444
|
+
if (isPlainObject2(value)) {
|
|
3445
|
+
const normalized = {};
|
|
3446
|
+
for (const key of Object.keys(value).sort()) {
|
|
3447
|
+
const entry = value[key];
|
|
3448
|
+
if (entry === void 0 || entry === null) continue;
|
|
3449
|
+
normalized[key] = normalizeValue(entry);
|
|
3450
|
+
}
|
|
3451
|
+
return normalized;
|
|
3452
|
+
}
|
|
3453
|
+
return value;
|
|
3454
|
+
}
|
|
3455
|
+
function normalizeAgentDefinition(definition) {
|
|
3456
|
+
const config = {};
|
|
3457
|
+
const rawConfig = isPlainObject2(definition.config) ? definition.config : {};
|
|
3458
|
+
for (const key of AGENT_CONFIG_KEY_LIST) {
|
|
3459
|
+
const value = rawConfig[key];
|
|
3460
|
+
if (value === void 0 || value === null) continue;
|
|
3461
|
+
config[key] = normalizeValue(value);
|
|
3462
|
+
}
|
|
3463
|
+
return {
|
|
3464
|
+
name: definition.name,
|
|
3465
|
+
...definition.description ? { description: definition.description } : {},
|
|
3466
|
+
...definition.icon ? { icon: definition.icon } : {},
|
|
3467
|
+
config
|
|
3468
|
+
};
|
|
3469
|
+
}
|
|
3470
|
+
async function computeAgentContentHash(definition) {
|
|
3471
|
+
const serialized = JSON.stringify(normalizeAgentDefinition(definition));
|
|
3472
|
+
const encoded = new TextEncoder().encode(serialized);
|
|
3473
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
|
|
3474
|
+
return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3475
|
+
}
|
|
3476
|
+
var DEFINE_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set(["name", "description", "icon", ...AGENT_CONFIG_KEYS]);
|
|
3477
|
+
function collectNonPortableToolRefs(config) {
|
|
3478
|
+
const tools = config.tools;
|
|
3479
|
+
if (!isPlainObject2(tools)) return [];
|
|
3480
|
+
const found = [];
|
|
3481
|
+
const isAccountScoped = (ref) => typeof ref === "string" && ref.startsWith("tool_");
|
|
3482
|
+
const scanArray = (value, path) => {
|
|
3483
|
+
if (!Array.isArray(value)) return;
|
|
3484
|
+
value.forEach((ref, i) => {
|
|
3485
|
+
if (isAccountScoped(ref)) found.push(`${path}[${i}]`);
|
|
3486
|
+
});
|
|
3487
|
+
};
|
|
3488
|
+
const scanKeys = (value, path) => {
|
|
3489
|
+
if (!isPlainObject2(value)) return;
|
|
3490
|
+
for (const key of Object.keys(value)) {
|
|
3491
|
+
if (isAccountScoped(key)) found.push(`${path}.${key}`);
|
|
3492
|
+
}
|
|
3493
|
+
};
|
|
3494
|
+
scanArray(tools.toolIds, "tools.toolIds");
|
|
3495
|
+
scanKeys(tools.toolConfigs, "tools.toolConfigs");
|
|
3496
|
+
scanKeys(tools.perToolLimits, "tools.perToolLimits");
|
|
3497
|
+
if (isPlainObject2(tools.approval)) scanArray(tools.approval.require, "tools.approval.require");
|
|
3498
|
+
if (isPlainObject2(tools.subagentConfig)) {
|
|
3499
|
+
scanArray(tools.subagentConfig.toolPool, "tools.subagentConfig.toolPool");
|
|
3500
|
+
}
|
|
3501
|
+
if (isPlainObject2(tools.codeModeConfig)) {
|
|
3502
|
+
scanArray(tools.codeModeConfig.toolPool, "tools.codeModeConfig.toolPool");
|
|
3503
|
+
}
|
|
3504
|
+
return found;
|
|
3505
|
+
}
|
|
3506
|
+
function defineAgent(input) {
|
|
3507
|
+
if (!input || typeof input !== "object") {
|
|
3508
|
+
throw new Error("defineAgent requires a definition object");
|
|
3509
|
+
}
|
|
3510
|
+
if (typeof input.name !== "string" || input.name.length === 0) {
|
|
3511
|
+
throw new Error('defineAgent requires a non-empty string "name"');
|
|
3512
|
+
}
|
|
3513
|
+
const unknownKeys = Object.keys(input).filter((key) => !DEFINE_TOP_LEVEL_KEYS.has(key));
|
|
3514
|
+
if (unknownKeys.length > 0) {
|
|
3515
|
+
throw new Error(
|
|
3516
|
+
`defineAgent: unknown field(s): ${unknownKeys.join(", ")}. Allowed fields are name, description, icon, and the agent runtime config surface (${AGENT_CONFIG_KEY_LIST.join(", ")}).`
|
|
3517
|
+
);
|
|
3518
|
+
}
|
|
3519
|
+
const config = {};
|
|
3520
|
+
for (const key of AGENT_CONFIG_KEYS) {
|
|
3521
|
+
const value = input[key];
|
|
3522
|
+
if (value !== void 0) config[key] = value;
|
|
3523
|
+
}
|
|
3524
|
+
const nonPortable = collectNonPortableToolRefs(config);
|
|
3525
|
+
if (nonPortable.length > 0) {
|
|
3526
|
+
throw new Error(
|
|
3527
|
+
`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.`
|
|
3528
|
+
);
|
|
3529
|
+
}
|
|
3530
|
+
return {
|
|
3531
|
+
name: input.name,
|
|
3532
|
+
...input.description !== void 0 ? { description: input.description } : {},
|
|
3533
|
+
...input.icon !== void 0 ? { icon: input.icon } : {},
|
|
3534
|
+
config
|
|
3535
|
+
};
|
|
3536
|
+
}
|
|
3537
|
+
var AgentEnsureConflictError = class extends Error {
|
|
3538
|
+
constructor(body) {
|
|
3539
|
+
super(body.error ?? `Agent ensure conflict: ${body.code}`);
|
|
3540
|
+
this.name = "AgentEnsureConflictError";
|
|
3541
|
+
this.code = body.code;
|
|
3542
|
+
this.lastModifiedSource = body.lastModifiedSource;
|
|
3543
|
+
this.modifiedAt = body.modifiedAt;
|
|
3544
|
+
this.currentHash = body.currentHash;
|
|
3545
|
+
}
|
|
3546
|
+
};
|
|
3547
|
+
var AgentDriftError = class extends Error {
|
|
3548
|
+
constructor(plan) {
|
|
3549
|
+
super(
|
|
3550
|
+
`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.`
|
|
3551
|
+
);
|
|
3552
|
+
this.name = "AgentDriftError";
|
|
3553
|
+
this.plan = plan;
|
|
3554
|
+
}
|
|
3555
|
+
};
|
|
3556
|
+
function parseRequestError2(err) {
|
|
3557
|
+
if (!(err instanceof Error)) return { status: null, body: null };
|
|
3558
|
+
const match = err.message.match(/^API request failed: (\d{3}) .*? - ([\s\S]*)$/);
|
|
3559
|
+
if (!match) return { status: null, body: null };
|
|
3560
|
+
try {
|
|
3561
|
+
return { status: Number(match[1]), body: JSON.parse(match[2]) };
|
|
3562
|
+
} catch {
|
|
3563
|
+
return { status: Number(match[1]), body: null };
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
function toConflictError2(err) {
|
|
3567
|
+
const { status, body } = parseRequestError2(err);
|
|
3568
|
+
if (status !== 409 || !isPlainObject2(body)) return null;
|
|
3569
|
+
const code = body.code;
|
|
3570
|
+
if (code !== "external_modification" && code !== "remote_changed") return null;
|
|
3571
|
+
return new AgentEnsureConflictError(
|
|
3572
|
+
body
|
|
3573
|
+
);
|
|
3574
|
+
}
|
|
3575
|
+
var serverHashMemo2 = /* @__PURE__ */ new WeakMap();
|
|
3576
|
+
function memoFor2(client) {
|
|
3577
|
+
let memo = serverHashMemo2.get(client);
|
|
3578
|
+
if (!memo) {
|
|
3579
|
+
memo = /* @__PURE__ */ new Map();
|
|
3580
|
+
serverHashMemo2.set(client, memo);
|
|
3581
|
+
}
|
|
3582
|
+
return memo;
|
|
3583
|
+
}
|
|
3584
|
+
var AgentsNamespace = class {
|
|
3585
|
+
constructor(getClient) {
|
|
3586
|
+
this.getClient = getClient;
|
|
3587
|
+
}
|
|
3588
|
+
/**
|
|
3589
|
+
* Idempotently converge a definition onto the platform. Hash-first: probes
|
|
3590
|
+
* with a content hash, and only ships the full definition when the server
|
|
3591
|
+
* reports a miss (`definitionRequired`). Creates an immutable version
|
|
3592
|
+
* snapshot on every change; never deletes.
|
|
3593
|
+
*/
|
|
3594
|
+
async ensure(definition, options = {}) {
|
|
3595
|
+
const client = this.getClient();
|
|
3596
|
+
const { dryRun, onConflict, release, expectedRemoteHash, expectNoChanges } = options;
|
|
3597
|
+
const passthrough = {
|
|
3598
|
+
...onConflict ? { onConflict } : {},
|
|
3599
|
+
...release ? { release } : {},
|
|
3600
|
+
...expectedRemoteHash ? { expectedRemoteHash } : {}
|
|
3601
|
+
};
|
|
3602
|
+
if (dryRun || expectNoChanges) {
|
|
3603
|
+
const plan = await this.request(client, {
|
|
3604
|
+
name: definition.name,
|
|
3605
|
+
definition,
|
|
3606
|
+
dryRun: true,
|
|
3607
|
+
...passthrough
|
|
3608
|
+
});
|
|
3609
|
+
if (plan.result !== "plan") {
|
|
3610
|
+
throw new Error(`Expected a plan result from dryRun, got '${plan.result}'`);
|
|
3611
|
+
}
|
|
3612
|
+
if (expectNoChanges && plan.changes !== "none") {
|
|
3613
|
+
throw new AgentDriftError(plan);
|
|
3614
|
+
}
|
|
3615
|
+
return plan;
|
|
3616
|
+
}
|
|
3617
|
+
const memo = memoFor2(client);
|
|
3618
|
+
const localHash = await computeAgentContentHash({
|
|
3619
|
+
...definition,
|
|
3620
|
+
config: definition.config
|
|
3621
|
+
});
|
|
3622
|
+
const memoKey = `${definition.name}\0${localHash}`;
|
|
3623
|
+
const contentHash = memo.get(memoKey) ?? localHash;
|
|
3624
|
+
const probe = await this.request(client, {
|
|
3625
|
+
name: definition.name,
|
|
3626
|
+
contentHash,
|
|
3627
|
+
...passthrough
|
|
3628
|
+
});
|
|
3629
|
+
if (probe.result !== "definitionRequired") {
|
|
3630
|
+
this.memoize(memo, memoKey, probe);
|
|
3631
|
+
return probe;
|
|
3632
|
+
}
|
|
3633
|
+
const converged = await this.request(client, {
|
|
3634
|
+
name: definition.name,
|
|
3635
|
+
definition,
|
|
3636
|
+
...passthrough
|
|
3637
|
+
});
|
|
3638
|
+
if (converged.result === "definitionRequired") {
|
|
3639
|
+
throw new Error("Server reported definitionRequired for a full-definition request");
|
|
3640
|
+
}
|
|
3641
|
+
this.memoize(memo, memoKey, converged);
|
|
3642
|
+
return converged;
|
|
3643
|
+
}
|
|
3644
|
+
/**
|
|
3645
|
+
* Pull the canonical definition + provenance for an agent by name — the
|
|
3646
|
+
* absorb-drift direction. The contentHash reflects the live agent state.
|
|
3647
|
+
*/
|
|
3648
|
+
async pull(name) {
|
|
3649
|
+
const client = this.getClient();
|
|
3650
|
+
return client.get("/agents/pull", { name });
|
|
3651
|
+
}
|
|
3652
|
+
memoize(memo, memoKey, result) {
|
|
3653
|
+
if (result.result !== "plan") memo.set(memoKey, result.contentHash);
|
|
3654
|
+
}
|
|
3655
|
+
async request(client, body) {
|
|
3656
|
+
try {
|
|
3657
|
+
return await client.post(
|
|
3658
|
+
"/agents/ensure",
|
|
3659
|
+
body
|
|
3660
|
+
);
|
|
3661
|
+
} catch (err) {
|
|
3662
|
+
const conflict = toConflictError2(err);
|
|
3663
|
+
if (conflict) throw conflict;
|
|
3664
|
+
throw err;
|
|
3665
|
+
}
|
|
3666
|
+
}
|
|
3667
|
+
};
|
|
3668
|
+
|
|
3135
3669
|
// src/transform.ts
|
|
3136
3670
|
function transformResponse(data) {
|
|
3137
3671
|
return data;
|
|
@@ -3292,7 +3826,7 @@ var RuntypeClient = class {
|
|
|
3292
3826
|
} catch (error) {
|
|
3293
3827
|
clearTimeout(timeoutId);
|
|
3294
3828
|
if (error instanceof Error && error.name === "AbortError") {
|
|
3295
|
-
throw new Error(`Request timeout after ${this.timeout}ms
|
|
3829
|
+
throw new Error(`Request timeout after ${this.timeout}ms`, { cause: error });
|
|
3296
3830
|
}
|
|
3297
3831
|
throw error;
|
|
3298
3832
|
}
|
|
@@ -3319,7 +3853,7 @@ var RuntypeClient = class {
|
|
|
3319
3853
|
} catch (error) {
|
|
3320
3854
|
clearTimeout(timeoutId);
|
|
3321
3855
|
if (error instanceof Error && error.name === "AbortError") {
|
|
3322
|
-
throw new Error(`Request timeout after ${this.timeout}ms
|
|
3856
|
+
throw new Error(`Request timeout after ${this.timeout}ms`, { cause: error });
|
|
3323
3857
|
}
|
|
3324
3858
|
throw error;
|
|
3325
3859
|
}
|
|
@@ -3494,6 +4028,32 @@ var Runtype = class {
|
|
|
3494
4028
|
static get skills() {
|
|
3495
4029
|
return new SkillsNamespace(() => this.getClient());
|
|
3496
4030
|
}
|
|
4031
|
+
/**
|
|
4032
|
+
* Agents namespace - Agent config-as-code (define / ensure / pull)
|
|
4033
|
+
*
|
|
4034
|
+
* @example
|
|
4035
|
+
* ```typescript
|
|
4036
|
+
* import { defineAgent, Runtype } from '@runtypelabs/sdk'
|
|
4037
|
+
*
|
|
4038
|
+
* const assistant = defineAgent({
|
|
4039
|
+
* name: 'Pricing Assistant',
|
|
4040
|
+
* model: 'claude-sonnet-4-6',
|
|
4041
|
+
* systemPrompt: renderPrompt(pricingData),
|
|
4042
|
+
* })
|
|
4043
|
+
*
|
|
4044
|
+
* // Converge at deploy time (idempotent; one tiny probe in steady state)
|
|
4045
|
+
* await Runtype.agents.ensure(assistant)
|
|
4046
|
+
*
|
|
4047
|
+
* // CI drift gate
|
|
4048
|
+
* await Runtype.agents.ensure(assistant, { expectNoChanges: true })
|
|
4049
|
+
*
|
|
4050
|
+
* // Absorb a dashboard edit back into the repo
|
|
4051
|
+
* const { definition } = await Runtype.agents.pull('Pricing Assistant')
|
|
4052
|
+
* ```
|
|
4053
|
+
*/
|
|
4054
|
+
static get agents() {
|
|
4055
|
+
return new AgentsNamespace(() => this.getClient());
|
|
4056
|
+
}
|
|
3497
4057
|
};
|
|
3498
4058
|
|
|
3499
4059
|
// src/generated-tool-gate.ts
|
|
@@ -3716,8 +4276,8 @@ function buildGeneratedRuntimeToolGateOutput(proposal, options = {}) {
|
|
|
3716
4276
|
...decision.tool ? { tool: decision.tool } : {}
|
|
3717
4277
|
};
|
|
3718
4278
|
}
|
|
3719
|
-
function attachRuntimeToolsToDispatchRequest(
|
|
3720
|
-
const stepList =
|
|
4279
|
+
function attachRuntimeToolsToDispatchRequest(request2, runtimeTools, options = {}) {
|
|
4280
|
+
const stepList = request2.flow.steps;
|
|
3721
4281
|
if (!stepList || !Array.isArray(stepList) || stepList.length === 0) {
|
|
3722
4282
|
throw new Error("Cannot attach runtime tools: dispatch request must include flow.steps");
|
|
3723
4283
|
}
|
|
@@ -3760,9 +4320,9 @@ function attachRuntimeToolsToDispatchRequest(request, runtimeTools, options = {}
|
|
|
3760
4320
|
}
|
|
3761
4321
|
};
|
|
3762
4322
|
return {
|
|
3763
|
-
...
|
|
4323
|
+
...request2,
|
|
3764
4324
|
flow: {
|
|
3765
|
-
...
|
|
4325
|
+
...request2.flow,
|
|
3766
4326
|
// `clonedSteps` is a structural clone of `request.flow.steps` (already
|
|
3767
4327
|
// `FlowStepDefinition[]`); only the prompt step's `config.tools` was
|
|
3768
4328
|
// merged, so every step's `type` discriminant is preserved. The clone is
|
|
@@ -3772,18 +4332,56 @@ function attachRuntimeToolsToDispatchRequest(request, runtimeTools, options = {}
|
|
|
3772
4332
|
}
|
|
3773
4333
|
};
|
|
3774
4334
|
}
|
|
3775
|
-
function applyGeneratedRuntimeToolProposalToDispatchRequest(
|
|
4335
|
+
function applyGeneratedRuntimeToolProposalToDispatchRequest(request2, proposal, options = {}) {
|
|
3776
4336
|
const decision = evaluateGeneratedRuntimeToolProposal(proposal, options.gate);
|
|
3777
4337
|
if (!decision.approved || !decision.tool) {
|
|
3778
|
-
return { decision, request };
|
|
4338
|
+
return { decision, request: request2 };
|
|
3779
4339
|
}
|
|
3780
|
-
const nextRequest = attachRuntimeToolsToDispatchRequest(
|
|
4340
|
+
const nextRequest = attachRuntimeToolsToDispatchRequest(request2, [decision.tool], options.attach);
|
|
3781
4341
|
return {
|
|
3782
4342
|
decision,
|
|
3783
4343
|
request: nextRequest
|
|
3784
4344
|
};
|
|
3785
4345
|
}
|
|
3786
4346
|
|
|
4347
|
+
// src/offload-markers.ts
|
|
4348
|
+
var LEDGER_ARTIFACT_LINE_PREFIX = "Ledger artifact: ";
|
|
4349
|
+
function formatChars(charLength) {
|
|
4350
|
+
return charLength.toLocaleString("en-US");
|
|
4351
|
+
}
|
|
4352
|
+
function buildSendViewOffloadMarker(details) {
|
|
4353
|
+
return `[${details.toolName} output (${formatChars(details.charLength)} chars) saved to ${details.filePath} \u2014 use read_file to retrieve if needed]`;
|
|
4354
|
+
}
|
|
4355
|
+
function buildLedgerOffloadReference(details) {
|
|
4356
|
+
return [
|
|
4357
|
+
`[Output offloaded as ${details.outputId} \u2014 ${formatChars(details.charLength)} chars stored in the marathon context ledger]`,
|
|
4358
|
+
`${LEDGER_ARTIFACT_LINE_PREFIX}${details.relativePath}`,
|
|
4359
|
+
`Preview: ${details.preview}${details.truncated ? "..." : ""}`,
|
|
4360
|
+
"",
|
|
4361
|
+
`Use read_offloaded_output with id "${details.outputId}" to retrieve the full output if needed.`
|
|
4362
|
+
].join("\n");
|
|
4363
|
+
}
|
|
4364
|
+
var DECLARED_CHARS_PATTERNS = [
|
|
4365
|
+
/—\s*([\d,]+)\s+chars?\s+(?:stored|saved)/i,
|
|
4366
|
+
/\(([\d,]+)\s+chars?\)\s+saved/i
|
|
4367
|
+
];
|
|
4368
|
+
function extractDeclaredToolResultChars(value) {
|
|
4369
|
+
if (typeof value !== "string") return void 0;
|
|
4370
|
+
for (const pattern of DECLARED_CHARS_PATTERNS) {
|
|
4371
|
+
const match = pattern.exec(value);
|
|
4372
|
+
if (!match?.[1]) continue;
|
|
4373
|
+
const parsed = Number.parseInt(match[1].replace(/,/g, ""), 10);
|
|
4374
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
4375
|
+
}
|
|
4376
|
+
return void 0;
|
|
4377
|
+
}
|
|
4378
|
+
function parseOffloadedOutputId(value) {
|
|
4379
|
+
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;
|
|
4380
|
+
}
|
|
4381
|
+
function parseLedgerArtifactRelativePath(value) {
|
|
4382
|
+
return value.split("\n").find((line) => line.startsWith(LEDGER_ARTIFACT_LINE_PREFIX))?.slice(LEDGER_ARTIFACT_LINE_PREFIX.length).trim();
|
|
4383
|
+
}
|
|
4384
|
+
|
|
3787
4385
|
// src/workflow-utils.ts
|
|
3788
4386
|
function normalizeCandidatePath(candidatePath) {
|
|
3789
4387
|
return candidatePath.trim().replace(/\\/g, "/").replace(/^\.?\//, "").replace(/\/+/g, "/");
|
|
@@ -3815,26 +4413,281 @@ function isPreservationSensitiveTask(state) {
|
|
|
3815
4413
|
"visual"
|
|
3816
4414
|
].some((keyword) => prompt.includes(keyword));
|
|
3817
4415
|
}
|
|
3818
|
-
function getLikelySupportingCandidatePaths(bestCandidatePath, candidatePaths) {
|
|
3819
|
-
if (!bestCandidatePath || !candidatePaths || candidatePaths.length === 0) return [];
|
|
3820
|
-
const normalizedBestCandidatePath = normalizeCandidatePath(bestCandidatePath);
|
|
3821
|
-
const bestCandidateSegments = normalizedBestCandidatePath.split("/").filter(Boolean);
|
|
3822
|
-
const relatedRoot = bestCandidateSegments.length >= 2 ? `${bestCandidateSegments[0]}/${bestCandidateSegments[1]}/` : bestCandidateSegments.length === 1 ? `${bestCandidateSegments[0]}/` : "";
|
|
3823
|
-
const bestCandidateDir = normalizedBestCandidatePath.includes("/") ? `${normalizedBestCandidatePath.slice(0, normalizedBestCandidatePath.lastIndexOf("/"))}/` : "";
|
|
3824
|
-
return candidatePaths.map((candidatePath) => normalizeCandidatePath(candidatePath)).filter(
|
|
3825
|
-
(candidatePath) => candidatePath && candidatePath !== normalizedBestCandidatePath && !isMarathonArtifactPath(candidatePath) && (bestCandidateDir && candidatePath.startsWith(bestCandidateDir) || relatedRoot && candidatePath.startsWith(relatedRoot))
|
|
3826
|
-
);
|
|
4416
|
+
function getLikelySupportingCandidatePaths(bestCandidatePath, candidatePaths) {
|
|
4417
|
+
if (!bestCandidatePath || !candidatePaths || candidatePaths.length === 0) return [];
|
|
4418
|
+
const normalizedBestCandidatePath = normalizeCandidatePath(bestCandidatePath);
|
|
4419
|
+
const bestCandidateSegments = normalizedBestCandidatePath.split("/").filter(Boolean);
|
|
4420
|
+
const relatedRoot = bestCandidateSegments.length >= 2 ? `${bestCandidateSegments[0]}/${bestCandidateSegments[1]}/` : bestCandidateSegments.length === 1 ? `${bestCandidateSegments[0]}/` : "";
|
|
4421
|
+
const bestCandidateDir = normalizedBestCandidatePath.includes("/") ? `${normalizedBestCandidatePath.slice(0, normalizedBestCandidatePath.lastIndexOf("/"))}/` : "";
|
|
4422
|
+
return candidatePaths.map((candidatePath) => normalizeCandidatePath(candidatePath)).filter(
|
|
4423
|
+
(candidatePath) => candidatePath && candidatePath !== normalizedBestCandidatePath && !isMarathonArtifactPath(candidatePath) && (bestCandidateDir && candidatePath.startsWith(bestCandidateDir) || relatedRoot && candidatePath.startsWith(relatedRoot))
|
|
4424
|
+
);
|
|
4425
|
+
}
|
|
4426
|
+
function getDefaultPlanPath(taskName) {
|
|
4427
|
+
const slug = sanitizeTaskSlug(taskName || "task");
|
|
4428
|
+
return `.runtype/marathons/${slug}/plan.md`;
|
|
4429
|
+
}
|
|
4430
|
+
function getDefaultExternalReportPath(taskName) {
|
|
4431
|
+
const slug = sanitizeTaskSlug(taskName || "task");
|
|
4432
|
+
return `${slug}.md`;
|
|
4433
|
+
}
|
|
4434
|
+
function sanitizeTaskSlug(taskName) {
|
|
4435
|
+
return taskName.toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
4436
|
+
}
|
|
4437
|
+
|
|
4438
|
+
// src/workflows/hook-registry.ts
|
|
4439
|
+
var BUILTIN_NAMESPACE = "builtin";
|
|
4440
|
+
var HOOK_REF_PATTERN = /^[a-z0-9_-]+:[a-z0-9_-]+$/;
|
|
4441
|
+
function isWorkflowHookRef(value) {
|
|
4442
|
+
return typeof value === "string" && HOOK_REF_PATTERN.test(value);
|
|
4443
|
+
}
|
|
4444
|
+
var registry = /* @__PURE__ */ new Map();
|
|
4445
|
+
function registerWorkflowHook(name, entry) {
|
|
4446
|
+
if (!isWorkflowHookRef(name)) {
|
|
4447
|
+
throw new Error(
|
|
4448
|
+
`Invalid workflow hook name "${name}": must be "<namespace>:<id>" using lowercase letters, digits, "-" or "_" (e.g. "acme:my-completion").`
|
|
4449
|
+
);
|
|
4450
|
+
}
|
|
4451
|
+
if (name.startsWith(`${BUILTIN_NAMESPACE}:`)) {
|
|
4452
|
+
throw new Error(
|
|
4453
|
+
`Cannot register "${name}": the "builtin:" namespace is reserved. Register under your own namespace and reference it from the workflow config instead.`
|
|
4454
|
+
);
|
|
4455
|
+
}
|
|
4456
|
+
registry.set(name, entry);
|
|
4457
|
+
}
|
|
4458
|
+
function registerBuiltinWorkflowHook(name, entry) {
|
|
4459
|
+
if (!name.startsWith(`${BUILTIN_NAMESPACE}:`) || !isWorkflowHookRef(name)) {
|
|
4460
|
+
throw new Error(`Builtin workflow hooks must be named "builtin:<id>" (got "${name}").`);
|
|
4461
|
+
}
|
|
4462
|
+
if (registry.has(name)) return;
|
|
4463
|
+
registry.set(name, entry);
|
|
4464
|
+
}
|
|
4465
|
+
function resolveWorkflowHook(name, expectedKind) {
|
|
4466
|
+
const entry = registry.get(name);
|
|
4467
|
+
if (!entry) {
|
|
4468
|
+
const known = listWorkflowHooks().filter((hook) => hook.kind === expectedKind).map((hook) => hook.name);
|
|
4469
|
+
throw new Error(
|
|
4470
|
+
`Unknown workflow hook "${name}". ` + (known.length > 0 ? `Registered '${expectedKind}' hooks: ${known.join(", ")}.` : `No '${expectedKind}' hooks are registered.`) + " Custom hooks must be registered (e.g. via a playbook plugin) before the workflow is compiled."
|
|
4471
|
+
);
|
|
4472
|
+
}
|
|
4473
|
+
if (entry.kind !== expectedKind) {
|
|
4474
|
+
throw new Error(
|
|
4475
|
+
`Workflow hook "${name}" is registered as '${entry.kind}' but referenced from a '${expectedKind}' slot.`
|
|
4476
|
+
);
|
|
4477
|
+
}
|
|
4478
|
+
return entry.fn;
|
|
4479
|
+
}
|
|
4480
|
+
function listWorkflowHooks() {
|
|
4481
|
+
return [...registry.entries()].map(([name, entry]) => ({ name, kind: entry.kind }));
|
|
4482
|
+
}
|
|
4483
|
+
function unregisterWorkflowHook(name) {
|
|
4484
|
+
if (name.startsWith(`${BUILTIN_NAMESPACE}:`)) return false;
|
|
4485
|
+
return registry.delete(name);
|
|
4486
|
+
}
|
|
4487
|
+
|
|
4488
|
+
// src/workflows/workflow-config.ts
|
|
4489
|
+
var DISCOVERY_TOOLS = /* @__PURE__ */ new Set([
|
|
4490
|
+
"search_repo",
|
|
4491
|
+
"glob_files",
|
|
4492
|
+
"tree_directory",
|
|
4493
|
+
"list_directory"
|
|
4494
|
+
]);
|
|
4495
|
+
var DEFAULT_RECOVERY_AFTER_EMPTY_SESSIONS = 2;
|
|
4496
|
+
function definePlaybook(playbook) {
|
|
4497
|
+
return playbook;
|
|
4498
|
+
}
|
|
4499
|
+
function interpolateWorkflowTemplate(template, state) {
|
|
4500
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_match, key) => {
|
|
4501
|
+
const value = state[key];
|
|
4502
|
+
if (value === void 0 || value === null) return `{{${key}}}`;
|
|
4503
|
+
return String(value);
|
|
4504
|
+
});
|
|
4505
|
+
}
|
|
4506
|
+
function buildIsComplete(criteria, configName, milestoneName) {
|
|
4507
|
+
if (!criteria) return () => false;
|
|
4508
|
+
switch (criteria.type) {
|
|
4509
|
+
case "evidence":
|
|
4510
|
+
return (ctx) => {
|
|
4511
|
+
const minFiles = criteria.minReadFiles ?? 1;
|
|
4512
|
+
return (ctx.state.recentReadPaths?.length ?? 0) >= minFiles;
|
|
4513
|
+
};
|
|
4514
|
+
case "sessions": {
|
|
4515
|
+
let baselineSessionCount;
|
|
4516
|
+
return (ctx) => {
|
|
4517
|
+
const minSessions = criteria.minSessions ?? 1;
|
|
4518
|
+
if (baselineSessionCount === void 0) {
|
|
4519
|
+
baselineSessionCount = ctx.state.sessions.length;
|
|
4520
|
+
}
|
|
4521
|
+
return ctx.state.sessions.length - baselineSessionCount >= minSessions;
|
|
4522
|
+
};
|
|
4523
|
+
}
|
|
4524
|
+
case "planWritten":
|
|
4525
|
+
return (ctx) => {
|
|
4526
|
+
return ctx.trace.planWritten;
|
|
4527
|
+
};
|
|
4528
|
+
case "never":
|
|
4529
|
+
return () => false;
|
|
4530
|
+
default: {
|
|
4531
|
+
if (isWorkflowHookRef(criteria.type)) {
|
|
4532
|
+
return resolveWorkflowHook(criteria.type, "completion");
|
|
4533
|
+
}
|
|
4534
|
+
throw new Error(
|
|
4535
|
+
`Workflow config '${configName}': milestone '${milestoneName}' has unknown completionCriteria.type "${criteria.type}" (expected evidence | sessions | planWritten | never, or a 'completion' hook reference).`
|
|
4536
|
+
);
|
|
4537
|
+
}
|
|
4538
|
+
}
|
|
4539
|
+
}
|
|
4540
|
+
function buildPolicyIntercept(policy, configName, deps) {
|
|
4541
|
+
if (!policy.blockedTools?.length && !policy.blockDiscoveryTools && !policy.allowedReadGlobs?.length && !policy.allowedWriteGlobs?.length && !policy.requirePlanBeforeWrite) {
|
|
4542
|
+
return void 0;
|
|
4543
|
+
}
|
|
4544
|
+
const blockedSet = new Set(
|
|
4545
|
+
(policy.blockedTools ?? []).map((t) => t.trim()).filter(Boolean)
|
|
4546
|
+
);
|
|
4547
|
+
const readGlobs = policy.allowedReadGlobs ?? [];
|
|
4548
|
+
const writeGlobs = policy.allowedWriteGlobs ?? [];
|
|
4549
|
+
const matchPathGlobs = deps.matchPathGlobs;
|
|
4550
|
+
if ((readGlobs.length > 0 || writeGlobs.length > 0) && !matchPathGlobs) {
|
|
4551
|
+
throw new Error(
|
|
4552
|
+
`Workflow config '${configName}': policy uses allowedReadGlobs/allowedWriteGlobs but no glob matcher was provided to compileWorkflowConfig (pass deps.matchPathGlobs).`
|
|
4553
|
+
);
|
|
4554
|
+
}
|
|
4555
|
+
return (toolName, args, ctx) => {
|
|
4556
|
+
if (blockedSet.has(toolName)) {
|
|
4557
|
+
return `Blocked by playbook policy: ${toolName} is not allowed for this task.`;
|
|
4558
|
+
}
|
|
4559
|
+
if (policy.blockDiscoveryTools && DISCOVERY_TOOLS.has(toolName)) {
|
|
4560
|
+
return `Blocked by playbook policy: discovery tools are disabled for this task.`;
|
|
4561
|
+
}
|
|
4562
|
+
const pathArg = typeof args.path === "string" && args.path.trim() ? ctx.normalizePath(String(args.path)) : void 0;
|
|
4563
|
+
if (pathArg) {
|
|
4564
|
+
const isWrite = toolName === "write_file" || toolName === "restore_file_checkpoint";
|
|
4565
|
+
const isRead = toolName === "read_file";
|
|
4566
|
+
if (isRead && readGlobs.length > 0) {
|
|
4567
|
+
const allowed = matchPathGlobs(pathArg, readGlobs);
|
|
4568
|
+
if (!allowed) {
|
|
4569
|
+
return `Blocked by playbook policy: ${toolName} path "${pathArg}" is outside allowed read globs: ${readGlobs.join(", ")}`;
|
|
4570
|
+
}
|
|
4571
|
+
}
|
|
4572
|
+
if (isWrite && writeGlobs.length > 0) {
|
|
4573
|
+
const planPath = ctx.state.planPath ? ctx.normalizePath(ctx.state.planPath) : void 0;
|
|
4574
|
+
if (planPath && pathArg === planPath) {
|
|
4575
|
+
} else {
|
|
4576
|
+
const allowed = matchPathGlobs(pathArg, writeGlobs);
|
|
4577
|
+
if (!allowed) {
|
|
4578
|
+
return `Blocked by playbook policy: ${toolName} path "${pathArg}" is outside allowed write globs: ${writeGlobs.join(", ")}`;
|
|
4579
|
+
}
|
|
4580
|
+
}
|
|
4581
|
+
}
|
|
4582
|
+
if (isWrite && policy.requirePlanBeforeWrite && !ctx.state.planWritten && !ctx.trace.planWritten) {
|
|
4583
|
+
const planPath = ctx.state.planPath ? ctx.normalizePath(ctx.state.planPath) : void 0;
|
|
4584
|
+
if (!planPath || pathArg !== planPath) {
|
|
4585
|
+
return `Blocked by playbook policy: write the plan before creating other files.`;
|
|
4586
|
+
}
|
|
4587
|
+
}
|
|
4588
|
+
}
|
|
4589
|
+
return void 0;
|
|
4590
|
+
};
|
|
4591
|
+
}
|
|
4592
|
+
function buildPolicyGuidance(policy) {
|
|
4593
|
+
if (!policy) return [];
|
|
4594
|
+
const lines = [];
|
|
4595
|
+
if (policy.requirePlanBeforeWrite) {
|
|
4596
|
+
lines.push(
|
|
4597
|
+
"Policy: write the plan file before any other file. Once the plan is written, other writes are allowed in the same turn."
|
|
4598
|
+
);
|
|
4599
|
+
}
|
|
4600
|
+
if (policy.allowedWriteGlobs?.length) {
|
|
4601
|
+
lines.push(
|
|
4602
|
+
`Policy: file writes are only allowed for paths matching: ${policy.allowedWriteGlobs.join(", ")} (the plan file is always allowed).`
|
|
4603
|
+
);
|
|
4604
|
+
}
|
|
4605
|
+
if (policy.outputRoot) {
|
|
4606
|
+
lines.push(`Policy: create new files under "${policy.outputRoot.replace(/\/$/, "")}/".`);
|
|
4607
|
+
}
|
|
4608
|
+
if (policy.allowedReadGlobs?.length) {
|
|
4609
|
+
lines.push(
|
|
4610
|
+
`Policy: file reads are only allowed for paths matching: ${policy.allowedReadGlobs.join(", ")}.`
|
|
4611
|
+
);
|
|
4612
|
+
}
|
|
4613
|
+
if (policy.blockDiscoveryTools) {
|
|
4614
|
+
lines.push(
|
|
4615
|
+
"Policy: broad discovery tools (search_repo, glob_files, tree_directory, list_directory) are disabled for this task."
|
|
4616
|
+
);
|
|
4617
|
+
}
|
|
4618
|
+
if (policy.blockedTools?.length) {
|
|
4619
|
+
lines.push(`Policy: these tools are disabled for this task: ${policy.blockedTools.join(", ")}.`);
|
|
4620
|
+
}
|
|
4621
|
+
return lines;
|
|
3827
4622
|
}
|
|
3828
|
-
function
|
|
3829
|
-
|
|
3830
|
-
return
|
|
4623
|
+
function resolveSlotHook(value, kind) {
|
|
4624
|
+
if (value === void 0) return void 0;
|
|
4625
|
+
if (typeof value === "function") return value;
|
|
4626
|
+
return resolveWorkflowHook(value, kind);
|
|
3831
4627
|
}
|
|
3832
|
-
function
|
|
3833
|
-
const
|
|
3834
|
-
|
|
4628
|
+
function compileMilestone(milestone, config, policyIntercept, policyGuidance) {
|
|
4629
|
+
const buildInstructions = typeof milestone.instructions === "function" ? milestone.instructions : isWorkflowHookRef(milestone.instructions) ? resolveWorkflowHook(milestone.instructions, "instructions") : (state) => {
|
|
4630
|
+
const header = `--- Workflow Phase: ${milestone.name} ---`;
|
|
4631
|
+
const desc = milestone.description ? `
|
|
4632
|
+
${milestone.description}` : "";
|
|
4633
|
+
const instructions = interpolateWorkflowTemplate(
|
|
4634
|
+
milestone.instructions,
|
|
4635
|
+
state
|
|
4636
|
+
);
|
|
4637
|
+
return `${header}${desc}
|
|
4638
|
+
${instructions}`;
|
|
4639
|
+
};
|
|
4640
|
+
const guidanceHook = typeof milestone.toolGuidance === "function" ? milestone.toolGuidance : milestone.toolGuidance !== void 0 && isWorkflowHookRef(milestone.toolGuidance) ? resolveWorkflowHook(milestone.toolGuidance, "toolGuidance") : void 0;
|
|
4641
|
+
const buildToolGuidance = (state) => {
|
|
4642
|
+
const base = guidanceHook ? guidanceHook(state) : milestone.toolGuidance ?? [];
|
|
4643
|
+
return policyGuidance.length > 0 ? [...base, ...policyGuidance] : base;
|
|
4644
|
+
};
|
|
4645
|
+
const customIntercept = resolveSlotHook(milestone.intercept, "intercept");
|
|
4646
|
+
const interceptToolCall = policyIntercept && customIntercept ? (toolName, args, ctx) => policyIntercept(toolName, args, ctx) ?? customIntercept(toolName, args, ctx) : policyIntercept ?? customIntercept;
|
|
4647
|
+
const transitionHook = typeof milestone.transitionSummary === "function" ? milestone.transitionSummary : milestone.transitionSummary !== void 0 && isWorkflowHookRef(milestone.transitionSummary) ? resolveWorkflowHook(milestone.transitionSummary, "transitionSummary") : void 0;
|
|
4648
|
+
const buildTransitionSummary = milestone.transitionSummary === void 0 ? void 0 : transitionHook ?? ((state, nextPhaseName) => interpolateWorkflowTemplate(milestone.transitionSummary, state).replace(
|
|
4649
|
+
/\{\{nextPhase\}\}/g,
|
|
4650
|
+
nextPhaseName
|
|
4651
|
+
));
|
|
4652
|
+
const recoveryHook = typeof milestone.recovery === "function" ? milestone.recovery : milestone.recovery !== void 0 && isWorkflowHookRef(milestone.recovery) ? resolveWorkflowHook(milestone.recovery, "recovery") : void 0;
|
|
4653
|
+
const buildRecoveryMessage = milestone.recovery === void 0 ? void 0 : recoveryHook ?? ((state) => {
|
|
4654
|
+
const inline = milestone.recovery;
|
|
4655
|
+
const threshold = inline.afterEmptySessions ?? DEFAULT_RECOVERY_AFTER_EMPTY_SESSIONS;
|
|
4656
|
+
if ((state.consecutiveEmptySessions ?? 0) < threshold) return void 0;
|
|
4657
|
+
return interpolateWorkflowTemplate(inline.message, state);
|
|
4658
|
+
});
|
|
4659
|
+
const canAcceptCompletion = milestone.canAcceptCompletion === void 0 ? void 0 : typeof milestone.canAcceptCompletion === "function" ? milestone.canAcceptCompletion : isWorkflowHookRef(milestone.canAcceptCompletion) ? resolveWorkflowHook(milestone.canAcceptCompletion, "acceptCompletion") : () => milestone.canAcceptCompletion;
|
|
4660
|
+
const isComplete = typeof milestone.completionCriteria === "function" ? milestone.completionCriteria : buildIsComplete(milestone.completionCriteria, config.name, milestone.name);
|
|
4661
|
+
return {
|
|
4662
|
+
name: milestone.name,
|
|
4663
|
+
description: milestone.description,
|
|
4664
|
+
buildInstructions,
|
|
4665
|
+
buildToolGuidance,
|
|
4666
|
+
isComplete,
|
|
4667
|
+
...interceptToolCall ? { interceptToolCall } : {},
|
|
4668
|
+
...buildTransitionSummary ? { buildTransitionSummary } : {},
|
|
4669
|
+
...buildRecoveryMessage ? { buildRecoveryMessage } : {},
|
|
4670
|
+
...milestone.forceEndTurn ? { shouldForceEndTurn: resolveSlotHook(milestone.forceEndTurn, "forceEndTurn") } : {},
|
|
4671
|
+
...canAcceptCompletion ? { canAcceptCompletion } : {}
|
|
4672
|
+
};
|
|
3835
4673
|
}
|
|
3836
|
-
function
|
|
3837
|
-
|
|
4674
|
+
function compileWorkflowConfig(config, deps = {}) {
|
|
4675
|
+
const policyIntercept = config.policy ? buildPolicyIntercept(config.policy, config.name, deps) : void 0;
|
|
4676
|
+
const policyGuidance = buildPolicyGuidance(config.policy);
|
|
4677
|
+
const phases = config.milestones.map(
|
|
4678
|
+
(milestone) => compileMilestone(milestone, config, policyIntercept, policyGuidance)
|
|
4679
|
+
);
|
|
4680
|
+
const classifyVariant4 = resolveSlotHook(config.classifyVariant, "classify");
|
|
4681
|
+
const generateBootstrapContext2 = resolveSlotHook(config.bootstrap, "bootstrap");
|
|
4682
|
+
const buildCandidateBlock2 = resolveSlotHook(config.candidateBlock, "candidateBlock");
|
|
4683
|
+
return {
|
|
4684
|
+
name: config.name,
|
|
4685
|
+
phases,
|
|
4686
|
+
...config.stallPolicy ? { stallPolicy: config.stallPolicy } : {},
|
|
4687
|
+
...classifyVariant4 ? { classifyVariant: classifyVariant4 } : {},
|
|
4688
|
+
...generateBootstrapContext2 ? { generateBootstrapContext: generateBootstrapContext2 } : {},
|
|
4689
|
+
...buildCandidateBlock2 ? { buildCandidateBlock: buildCandidateBlock2 } : {}
|
|
4690
|
+
};
|
|
3838
4691
|
}
|
|
3839
4692
|
|
|
3840
4693
|
// src/workflows/default-workflow.ts
|
|
@@ -3986,6 +4839,45 @@ function summarizeTextBlock(value, maxLines = 4) {
|
|
|
3986
4839
|
if (!text) return "";
|
|
3987
4840
|
return text.split("\n").map((line) => line.trim()).filter(Boolean).slice(0, maxLines).join(" | ").slice(0, 240);
|
|
3988
4841
|
}
|
|
4842
|
+
function interceptProductWriteTarget(toolName, normalizedPathArg, ctx, guardLabel) {
|
|
4843
|
+
const normalizedPlanPath = ctx.state.planPath ? ctx.normalizePath(ctx.state.planPath) : void 0;
|
|
4844
|
+
const normalizedBestCandidatePath = ctx.state.bestCandidatePath ? ctx.normalizePath(ctx.state.bestCandidatePath) : void 0;
|
|
4845
|
+
if (!ctx.state.isCreationTask && normalizedPathArg && normalizedPathArg !== normalizedPlanPath) {
|
|
4846
|
+
const allowedWriteTargets = new Set(
|
|
4847
|
+
[
|
|
4848
|
+
normalizedPlanPath,
|
|
4849
|
+
normalizedBestCandidatePath,
|
|
4850
|
+
...(ctx.state.recentReadPaths || []).map((readPath) => ctx.normalizePath(readPath)),
|
|
4851
|
+
...ctx.trace.readPaths.map((readPath) => ctx.normalizePath(readPath))
|
|
4852
|
+
].filter((value) => Boolean(value))
|
|
4853
|
+
);
|
|
4854
|
+
if (!allowedWriteTargets.has(normalizedPathArg)) {
|
|
4855
|
+
return [
|
|
4856
|
+
`Blocked by marathon ${guardLabel}: ${toolName} is limited to the confirmed target, the plan file, or files already discovered/read for this task.`,
|
|
4857
|
+
`Do not create scratch files like "${normalizedPathArg}".`,
|
|
4858
|
+
normalizedBestCandidatePath ? `Edit "${normalizedBestCandidatePath}" or another previously discovered repo file instead.` : "Read the current target file before writing."
|
|
4859
|
+
].join(" ");
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4862
|
+
if (ctx.state.isCreationTask && normalizedPathArg && normalizedPathArg !== normalizedPlanPath) {
|
|
4863
|
+
const outputRoot = ctx.state.outputRoot ? ctx.state.outputRoot.trim().replace(/\\/g, "/").replace(/\/+/g, "/").replace(/\/$/, "") || void 0 : void 0;
|
|
4864
|
+
if (!outputRoot) {
|
|
4865
|
+
return [
|
|
4866
|
+
`Blocked by marathon ${guardLabel}: creation tasks require outputRoot. Writes outside the plan are not allowed.`,
|
|
4867
|
+
`Plan path: "${normalizedPlanPath}". Create files only under the configured output root.`
|
|
4868
|
+
].join(" ");
|
|
4869
|
+
}
|
|
4870
|
+
const rootPrefix = outputRoot + "/";
|
|
4871
|
+
const isUnderRoot = normalizedPathArg === outputRoot || normalizedPathArg.startsWith(rootPrefix);
|
|
4872
|
+
if (!isUnderRoot) {
|
|
4873
|
+
return [
|
|
4874
|
+
`Blocked by marathon ${guardLabel}: ${toolName} must target the plan or paths under outputRoot "${outputRoot}/".`,
|
|
4875
|
+
`"${normalizedPathArg}" is outside the allowed output root.`
|
|
4876
|
+
].join(" ");
|
|
4877
|
+
}
|
|
4878
|
+
}
|
|
4879
|
+
return void 0;
|
|
4880
|
+
}
|
|
3989
4881
|
var researchPhase = {
|
|
3990
4882
|
name: "research",
|
|
3991
4883
|
description: "Inspect the repo and identify the correct target file",
|
|
@@ -4070,11 +4962,15 @@ var researchPhase = {
|
|
|
4070
4962
|
const normalizedPathArg2 = typeof _args.path === "string" && _args.path.trim() ? ctx.normalizePath(String(_args.path)) : void 0;
|
|
4071
4963
|
const normalizedPlanPath = ctx.state.planPath ? ctx.normalizePath(ctx.state.planPath) : void 0;
|
|
4072
4964
|
if (normalizedPathArg2 && normalizedPlanPath && normalizedPathArg2 !== normalizedPlanPath) {
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4965
|
+
const planWritten = ctx.trace.planWritten || Boolean(ctx.state.planWritten);
|
|
4966
|
+
if (!planWritten) {
|
|
4967
|
+
return [
|
|
4968
|
+
`Blocked by marathon research guard: ${toolName} cannot create product files during the research phase.`,
|
|
4969
|
+
"Complete research first, then the system will advance you to planning.",
|
|
4970
|
+
`You may write the plan to "${normalizedPlanPath}" once research is complete.`
|
|
4971
|
+
].join(" ");
|
|
4972
|
+
}
|
|
4973
|
+
return interceptProductWriteTarget(toolName, normalizedPathArg2, ctx, "research guard");
|
|
4078
4974
|
}
|
|
4079
4975
|
}
|
|
4080
4976
|
return void 0;
|
|
@@ -4197,19 +5093,24 @@ var planningPhase = {
|
|
|
4197
5093
|
"Research is complete. Write the implementation plan for building this from scratch.",
|
|
4198
5094
|
`Write the plan markdown to exactly: ${planPath}`,
|
|
4199
5095
|
"List the files you will create, their locations, purpose, and any dependencies to install.",
|
|
5096
|
+
...state.outputRoot ? [
|
|
5097
|
+
`All new files must be created under "${state.outputRoot}" \u2014 writes outside that directory are blocked, so plan every file location inside it.`
|
|
5098
|
+
] : [],
|
|
4200
5099
|
'Include a "Verification steps" section listing the concrete checks you will run before TASK_COMPLETE.',
|
|
4201
|
-
"If the plan already exists, update that same plan file instead of creating a different one."
|
|
5100
|
+
"If the plan already exists, update that same plan file instead of creating a different one.",
|
|
5101
|
+
"Once the plan is written, you may begin creating the planned files in the same turn."
|
|
4202
5102
|
].join("\n");
|
|
4203
5103
|
}
|
|
4204
5104
|
return [
|
|
4205
5105
|
"--- Workflow Phase: Planning ---",
|
|
4206
5106
|
"Research is complete. Your current job is to write the implementation plan before any product-file edits.",
|
|
4207
5107
|
`Write the plan markdown to exactly: ${planPath}`,
|
|
4208
|
-
"Do NOT edit the target product file
|
|
5108
|
+
"Do NOT edit the target product file before the plan exists.",
|
|
4209
5109
|
"The plan should summarize UX findings, explain why the current best candidate is the right file, and list concrete execution steps.",
|
|
4210
5110
|
'The plan must include a "Preserve existing functionality" section that lists current behaviors, linked files, integrations, and constraints that must keep working.',
|
|
4211
5111
|
'The plan must include a "Verification steps" section listing the concrete checks you will run before TASK_COMPLETE.',
|
|
4212
|
-
"If the plan already exists, update that same plan file instead of creating a different one."
|
|
5112
|
+
"If the plan already exists, update that same plan file instead of creating a different one.",
|
|
5113
|
+
"Once the plan is written, you may begin editing the target file in the same turn."
|
|
4213
5114
|
].join("\n");
|
|
4214
5115
|
},
|
|
4215
5116
|
buildToolGuidance(state) {
|
|
@@ -4237,10 +5138,14 @@ var planningPhase = {
|
|
|
4237
5138
|
const normalizedPlanPath = ctx.state.planPath ? ctx.normalizePath(ctx.state.planPath) : void 0;
|
|
4238
5139
|
const isWriteLikeTool = toolName === "write_file" || toolName === "edit_file" || toolName === "restore_file_checkpoint";
|
|
4239
5140
|
if (isWriteLikeTool && normalizedPathArg && normalizedPlanPath && normalizedPathArg !== normalizedPlanPath) {
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
5141
|
+
const planWritten = ctx.trace.planWritten || Boolean(ctx.state.planWritten);
|
|
5142
|
+
if (!planWritten) {
|
|
5143
|
+
return [
|
|
5144
|
+
`Blocked by marathon planning guard: ${toolName} must target the exact plan path during planning.`,
|
|
5145
|
+
`Write the plan to "${normalizedPlanPath}" before editing any product files.`
|
|
5146
|
+
].join(" ");
|
|
5147
|
+
}
|
|
5148
|
+
return interceptProductWriteTarget(toolName, normalizedPathArg, ctx, "planning guard");
|
|
4244
5149
|
}
|
|
4245
5150
|
return void 0;
|
|
4246
5151
|
},
|
|
@@ -4300,6 +5205,9 @@ var executionPhase = {
|
|
|
4300
5205
|
},
|
|
4301
5206
|
buildToolGuidance(state) {
|
|
4302
5207
|
return [
|
|
5208
|
+
...state.isCreationTask && state.outputRoot ? [
|
|
5209
|
+
`Creation guard: create new files under "${state.outputRoot}". Writes outside it are blocked \u2014 the plan file is the only exception.`
|
|
5210
|
+
] : [],
|
|
4303
5211
|
...state.bestCandidatePath ? [
|
|
4304
5212
|
`Execution-phase guard: broad discovery tools (search_repo, glob_files, tree_directory, list_directory) are locked while executing against "${state.bestCandidatePath}".`
|
|
4305
5213
|
] : [
|
|
@@ -4341,40 +5249,13 @@ var executionPhase = {
|
|
|
4341
5249
|
`After that, you may update "${normalizedPlanPath}" with progress.`
|
|
4342
5250
|
].join(" ");
|
|
4343
5251
|
}
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
].filter((value) => Boolean(value))
|
|
4352
|
-
);
|
|
4353
|
-
if (!allowedWriteTargets.has(normalizedPathArg)) {
|
|
4354
|
-
return [
|
|
4355
|
-
`Blocked by marathon execution guard: ${toolName} is limited to the confirmed target, the plan file, or files already discovered/read for this task.`,
|
|
4356
|
-
`Do not create scratch files like "${normalizedPathArg}".`,
|
|
4357
|
-
normalizedBestCandidatePath ? `Edit "${normalizedBestCandidatePath}" or another previously discovered repo file instead.` : "Read the current target file before writing."
|
|
4358
|
-
].join(" ");
|
|
4359
|
-
}
|
|
4360
|
-
}
|
|
4361
|
-
if (ctx.state.isCreationTask && normalizedPathArg && normalizedPathArg !== normalizedPlanPath) {
|
|
4362
|
-
const outputRoot = ctx.state.outputRoot ? ctx.state.outputRoot.trim().replace(/\\/g, "/").replace(/\/+/g, "/").replace(/\/$/, "") || void 0 : void 0;
|
|
4363
|
-
if (!outputRoot) {
|
|
4364
|
-
return [
|
|
4365
|
-
`Blocked by marathon execution guard: creation tasks require outputRoot. Writes outside the plan are not allowed.`,
|
|
4366
|
-
`Plan path: "${normalizedPlanPath}". Create files only under the configured output root.`
|
|
4367
|
-
].join(" ");
|
|
4368
|
-
}
|
|
4369
|
-
const rootPrefix = outputRoot + "/";
|
|
4370
|
-
const isUnderRoot = normalizedPathArg === outputRoot || normalizedPathArg.startsWith(rootPrefix);
|
|
4371
|
-
if (!isUnderRoot) {
|
|
4372
|
-
return [
|
|
4373
|
-
`Blocked by marathon execution guard: ${toolName} must target the plan or paths under outputRoot "${outputRoot}/".`,
|
|
4374
|
-
`"${normalizedPathArg}" is outside the allowed output root.`
|
|
4375
|
-
].join(" ");
|
|
4376
|
-
}
|
|
4377
|
-
}
|
|
5252
|
+
const writeTargetBlock = interceptProductWriteTarget(
|
|
5253
|
+
toolName,
|
|
5254
|
+
normalizedPathArg,
|
|
5255
|
+
ctx,
|
|
5256
|
+
"execution guard"
|
|
5257
|
+
);
|
|
5258
|
+
if (writeTargetBlock) return writeTargetBlock;
|
|
4378
5259
|
}
|
|
4379
5260
|
return void 0;
|
|
4380
5261
|
},
|
|
@@ -4607,13 +5488,163 @@ function buildCandidateBlock(state) {
|
|
|
4607
5488
|
...state.bestCandidateReason ? [`Why: ${state.bestCandidateReason}`] : []
|
|
4608
5489
|
].join("\n");
|
|
4609
5490
|
}
|
|
4610
|
-
var
|
|
5491
|
+
var builtinHooksRegistered = false;
|
|
5492
|
+
function ensureDefaultWorkflowHooks() {
|
|
5493
|
+
if (builtinHooksRegistered) return;
|
|
5494
|
+
builtinHooksRegistered = true;
|
|
5495
|
+
registerBuiltinWorkflowHook("builtin:classify-task-variant", {
|
|
5496
|
+
kind: "classify",
|
|
5497
|
+
fn: classifyVariant
|
|
5498
|
+
});
|
|
5499
|
+
registerBuiltinWorkflowHook("builtin:repo-bootstrap-discovery", {
|
|
5500
|
+
kind: "bootstrap",
|
|
5501
|
+
fn: generateBootstrapContext
|
|
5502
|
+
});
|
|
5503
|
+
registerBuiltinWorkflowHook("builtin:best-candidate-block", {
|
|
5504
|
+
kind: "candidateBlock",
|
|
5505
|
+
fn: buildCandidateBlock
|
|
5506
|
+
});
|
|
5507
|
+
registerBuiltinWorkflowHook("builtin:research-instructions", {
|
|
5508
|
+
kind: "instructions",
|
|
5509
|
+
fn: researchPhase.buildInstructions
|
|
5510
|
+
});
|
|
5511
|
+
registerBuiltinWorkflowHook("builtin:research-tool-guidance", {
|
|
5512
|
+
kind: "toolGuidance",
|
|
5513
|
+
fn: researchPhase.buildToolGuidance
|
|
5514
|
+
});
|
|
5515
|
+
registerBuiltinWorkflowHook("builtin:research-complete", {
|
|
5516
|
+
kind: "completion",
|
|
5517
|
+
fn: researchPhase.isComplete
|
|
5518
|
+
});
|
|
5519
|
+
registerBuiltinWorkflowHook("builtin:research-transition-summary", {
|
|
5520
|
+
kind: "transitionSummary",
|
|
5521
|
+
fn: researchPhase.buildTransitionSummary
|
|
5522
|
+
});
|
|
5523
|
+
registerBuiltinWorkflowHook("builtin:research-guard", {
|
|
5524
|
+
kind: "intercept",
|
|
5525
|
+
fn: researchPhase.interceptToolCall
|
|
5526
|
+
});
|
|
5527
|
+
registerBuiltinWorkflowHook("builtin:research-recovery", {
|
|
5528
|
+
kind: "recovery",
|
|
5529
|
+
fn: researchPhase.buildRecoveryMessage
|
|
5530
|
+
});
|
|
5531
|
+
registerBuiltinWorkflowHook("builtin:research-force-end-turn", {
|
|
5532
|
+
kind: "forceEndTurn",
|
|
5533
|
+
fn: researchPhase.shouldForceEndTurn
|
|
5534
|
+
});
|
|
5535
|
+
registerBuiltinWorkflowHook("builtin:research-accept-completion", {
|
|
5536
|
+
kind: "acceptCompletion",
|
|
5537
|
+
fn: researchPhase.canAcceptCompletion
|
|
5538
|
+
});
|
|
5539
|
+
registerBuiltinWorkflowHook("builtin:planning-instructions", {
|
|
5540
|
+
kind: "instructions",
|
|
5541
|
+
fn: planningPhase.buildInstructions
|
|
5542
|
+
});
|
|
5543
|
+
registerBuiltinWorkflowHook("builtin:planning-tool-guidance", {
|
|
5544
|
+
kind: "toolGuidance",
|
|
5545
|
+
fn: planningPhase.buildToolGuidance
|
|
5546
|
+
});
|
|
5547
|
+
registerBuiltinWorkflowHook("builtin:planning-complete", {
|
|
5548
|
+
kind: "completion",
|
|
5549
|
+
fn: planningPhase.isComplete
|
|
5550
|
+
});
|
|
5551
|
+
registerBuiltinWorkflowHook("builtin:planning-transition-summary", {
|
|
5552
|
+
kind: "transitionSummary",
|
|
5553
|
+
fn: planningPhase.buildTransitionSummary
|
|
5554
|
+
});
|
|
5555
|
+
registerBuiltinWorkflowHook("builtin:planning-guard", {
|
|
5556
|
+
kind: "intercept",
|
|
5557
|
+
fn: planningPhase.interceptToolCall
|
|
5558
|
+
});
|
|
5559
|
+
registerBuiltinWorkflowHook("builtin:planning-recovery", {
|
|
5560
|
+
kind: "recovery",
|
|
5561
|
+
fn: planningPhase.buildRecoveryMessage
|
|
5562
|
+
});
|
|
5563
|
+
registerBuiltinWorkflowHook("builtin:planning-force-end-turn", {
|
|
5564
|
+
kind: "forceEndTurn",
|
|
5565
|
+
fn: planningPhase.shouldForceEndTurn
|
|
5566
|
+
});
|
|
5567
|
+
registerBuiltinWorkflowHook("builtin:execution-instructions", {
|
|
5568
|
+
kind: "instructions",
|
|
5569
|
+
fn: executionPhase.buildInstructions
|
|
5570
|
+
});
|
|
5571
|
+
registerBuiltinWorkflowHook("builtin:execution-tool-guidance", {
|
|
5572
|
+
kind: "toolGuidance",
|
|
5573
|
+
fn: executionPhase.buildToolGuidance
|
|
5574
|
+
});
|
|
5575
|
+
registerBuiltinWorkflowHook("builtin:execution-guard", {
|
|
5576
|
+
kind: "intercept",
|
|
5577
|
+
fn: executionPhase.interceptToolCall
|
|
5578
|
+
});
|
|
5579
|
+
registerBuiltinWorkflowHook("builtin:execution-recovery", {
|
|
5580
|
+
kind: "recovery",
|
|
5581
|
+
fn: executionPhase.buildRecoveryMessage
|
|
5582
|
+
});
|
|
5583
|
+
registerBuiltinWorkflowHook("builtin:execution-force-end-turn", {
|
|
5584
|
+
kind: "forceEndTurn",
|
|
5585
|
+
fn: executionPhase.shouldForceEndTurn
|
|
5586
|
+
});
|
|
5587
|
+
registerBuiltinWorkflowHook("builtin:execution-accept-completion", {
|
|
5588
|
+
kind: "acceptCompletion",
|
|
5589
|
+
fn: executionPhase.canAcceptCompletion
|
|
5590
|
+
});
|
|
5591
|
+
}
|
|
5592
|
+
var defaultWorkflowConfig = {
|
|
4611
5593
|
name: "default",
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
5594
|
+
// Empty-session escalation. The counter only counts tool actions, so
|
|
5595
|
+
// narration-only sessions ("I'll create the files now" with no tool calls)
|
|
5596
|
+
// escalate here even though the phase recovery conditions keyed on
|
|
5597
|
+
// hadTextOutput skip them: nudge after the first actionless session, signal
|
|
5598
|
+
// model escalation after the second (a no-op unless the caller configured a
|
|
5599
|
+
// fallback model), and stop as 'stalled' after the third — the same total
|
|
5600
|
+
// session budget as before stallPolicy existed.
|
|
5601
|
+
stallPolicy: { nudgeAfter: 1, escalateModelAfter: 2, stopAfter: 3 },
|
|
5602
|
+
classifyVariant: "builtin:classify-task-variant",
|
|
5603
|
+
bootstrap: "builtin:repo-bootstrap-discovery",
|
|
5604
|
+
candidateBlock: "builtin:best-candidate-block",
|
|
5605
|
+
milestones: [
|
|
5606
|
+
{
|
|
5607
|
+
name: "research",
|
|
5608
|
+
description: "Inspect the repo and identify the correct target file",
|
|
5609
|
+
instructions: "builtin:research-instructions",
|
|
5610
|
+
toolGuidance: "builtin:research-tool-guidance",
|
|
5611
|
+
completionCriteria: { type: "builtin:research-complete" },
|
|
5612
|
+
intercept: "builtin:research-guard",
|
|
5613
|
+
transitionSummary: "builtin:research-transition-summary",
|
|
5614
|
+
recovery: "builtin:research-recovery",
|
|
5615
|
+
forceEndTurn: "builtin:research-force-end-turn",
|
|
5616
|
+
canAcceptCompletion: "builtin:research-accept-completion"
|
|
5617
|
+
},
|
|
5618
|
+
{
|
|
5619
|
+
name: "planning",
|
|
5620
|
+
description: "Write the implementation plan before editing product files",
|
|
5621
|
+
instructions: "builtin:planning-instructions",
|
|
5622
|
+
toolGuidance: "builtin:planning-tool-guidance",
|
|
5623
|
+
completionCriteria: { type: "builtin:planning-complete" },
|
|
5624
|
+
intercept: "builtin:planning-guard",
|
|
5625
|
+
transitionSummary: "builtin:planning-transition-summary",
|
|
5626
|
+
recovery: "builtin:planning-recovery",
|
|
5627
|
+
forceEndTurn: "builtin:planning-force-end-turn"
|
|
5628
|
+
// canAcceptCompletion intentionally absent: the hand-written planning
|
|
5629
|
+
// phase never defined it, and the SDK accepts completion when the slot
|
|
5630
|
+
// is undefined. Keep parity.
|
|
5631
|
+
},
|
|
5632
|
+
{
|
|
5633
|
+
name: "execution",
|
|
5634
|
+
description: "Execute the plan by editing target files",
|
|
5635
|
+
instructions: "builtin:execution-instructions",
|
|
5636
|
+
toolGuidance: "builtin:execution-tool-guidance",
|
|
5637
|
+
// Execution never auto-advances; completion is agent-driven via TASK_COMPLETE
|
|
5638
|
+
completionCriteria: { type: "never" },
|
|
5639
|
+
intercept: "builtin:execution-guard",
|
|
5640
|
+
recovery: "builtin:execution-recovery",
|
|
5641
|
+
forceEndTurn: "builtin:execution-force-end-turn",
|
|
5642
|
+
canAcceptCompletion: "builtin:execution-accept-completion"
|
|
5643
|
+
}
|
|
5644
|
+
]
|
|
4616
5645
|
};
|
|
5646
|
+
ensureDefaultWorkflowHooks();
|
|
5647
|
+
var defaultWorkflow = compileWorkflowConfig(defaultWorkflowConfig);
|
|
4617
5648
|
|
|
4618
5649
|
// src/workflows/deploy-workflow.ts
|
|
4619
5650
|
var scaffoldPhase = {
|
|
@@ -5025,6 +6056,34 @@ var gameWorkflow = {
|
|
|
5025
6056
|
}
|
|
5026
6057
|
};
|
|
5027
6058
|
|
|
6059
|
+
// src/workflows/stall-policy.ts
|
|
6060
|
+
var DEFAULT_STALL_STOP_AFTER = 3;
|
|
6061
|
+
function isPositiveInteger(value) {
|
|
6062
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 1;
|
|
6063
|
+
}
|
|
6064
|
+
function resolveStallStopAfter(policy) {
|
|
6065
|
+
return isPositiveInteger(policy?.stopAfter) ? policy.stopAfter : DEFAULT_STALL_STOP_AFTER;
|
|
6066
|
+
}
|
|
6067
|
+
function shouldRequestModelEscalation(policy, consecutiveEmptySessions) {
|
|
6068
|
+
const threshold = policy?.escalateModelAfter;
|
|
6069
|
+
if (!isPositiveInteger(threshold)) return false;
|
|
6070
|
+
return consecutiveEmptySessions === threshold;
|
|
6071
|
+
}
|
|
6072
|
+
function shouldInjectEmptySessionNudge(policy, consecutiveEmptySessions) {
|
|
6073
|
+
const threshold = policy?.nudgeAfter;
|
|
6074
|
+
if (!isPositiveInteger(threshold)) return false;
|
|
6075
|
+
return consecutiveEmptySessions >= threshold;
|
|
6076
|
+
}
|
|
6077
|
+
function buildEmptySessionNudge(consecutiveEmptySessions) {
|
|
6078
|
+
const sessionPhrase = consecutiveEmptySessions === 1 ? "Your previous session ended" : `Your previous ${consecutiveEmptySessions} sessions ended`;
|
|
6079
|
+
return [
|
|
6080
|
+
"Recovery instruction:",
|
|
6081
|
+
`${sessionPhrase} without a single tool call. Describing what you plan to do does nothing \u2014 only tool calls make progress.`,
|
|
6082
|
+
"Your next response MUST include at least one tool call (for example write_file, edit_file, read_file, or run_check) that advances the task.",
|
|
6083
|
+
"If a previous tool call was blocked, re-read the block message and satisfy its requirement instead of ending the turn."
|
|
6084
|
+
].join("\n");
|
|
6085
|
+
}
|
|
6086
|
+
|
|
5028
6087
|
// src/endpoints.ts
|
|
5029
6088
|
var FlowsEndpoint = class {
|
|
5030
6089
|
constructor(client) {
|
|
@@ -5515,15 +6574,15 @@ var DispatchEndpoint = class {
|
|
|
5515
6574
|
* Attach approved runtime tools to a prompt step in a redispatch request.
|
|
5516
6575
|
* Returns a new request object and does not mutate the original.
|
|
5517
6576
|
*/
|
|
5518
|
-
attachApprovedRuntimeTools(
|
|
5519
|
-
return attachRuntimeToolsToDispatchRequest(
|
|
6577
|
+
attachApprovedRuntimeTools(request2, runtimeTools, options) {
|
|
6578
|
+
return attachRuntimeToolsToDispatchRequest(request2, runtimeTools, options);
|
|
5520
6579
|
}
|
|
5521
6580
|
/**
|
|
5522
6581
|
* Validate a generated runtime tool proposal and attach it to the redispatch
|
|
5523
6582
|
* request if approved, in one call.
|
|
5524
6583
|
*/
|
|
5525
|
-
applyGeneratedRuntimeToolProposal(
|
|
5526
|
-
return applyGeneratedRuntimeToolProposalToDispatchRequest(
|
|
6584
|
+
applyGeneratedRuntimeToolProposal(request2, proposal, options) {
|
|
6585
|
+
return applyGeneratedRuntimeToolProposalToDispatchRequest(request2, proposal, options);
|
|
5527
6586
|
}
|
|
5528
6587
|
};
|
|
5529
6588
|
var ChatEndpoint = class {
|
|
@@ -6028,6 +7087,22 @@ async function processAgentStream(body, callbacks) {
|
|
|
6028
7087
|
reader.releaseLock();
|
|
6029
7088
|
}
|
|
6030
7089
|
}
|
|
7090
|
+
function sleepWithAbort(delayMs, signal) {
|
|
7091
|
+
return new Promise((resolve) => {
|
|
7092
|
+
const onAbort = () => {
|
|
7093
|
+
clearTimeout(timer);
|
|
7094
|
+
resolve();
|
|
7095
|
+
};
|
|
7096
|
+
const timer = setTimeout(() => {
|
|
7097
|
+
signal?.removeEventListener("abort", onAbort);
|
|
7098
|
+
resolve();
|
|
7099
|
+
}, delayMs);
|
|
7100
|
+
if (signal) {
|
|
7101
|
+
if (signal.aborted) onAbort();
|
|
7102
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
7103
|
+
}
|
|
7104
|
+
});
|
|
7105
|
+
}
|
|
6031
7106
|
var GENERATED_RUNTIME_TOOL_PROPOSAL_SCHEMA = {
|
|
6032
7107
|
type: "object",
|
|
6033
7108
|
properties: {
|
|
@@ -6059,8 +7134,8 @@ var GENERATED_RUNTIME_TOOL_PROPOSAL_SCHEMA = {
|
|
|
6059
7134
|
},
|
|
6060
7135
|
required: ["name", "description", "toolType", "parametersSchema", "config"]
|
|
6061
7136
|
};
|
|
6062
|
-
function appendRuntimeToolsToAgentRequest(
|
|
6063
|
-
const existing =
|
|
7137
|
+
function appendRuntimeToolsToAgentRequest(request2, runtimeTools) {
|
|
7138
|
+
const existing = request2.tools?.runtimeTools || [];
|
|
6064
7139
|
const existingNames = new Set(existing.map((tool) => tool.name));
|
|
6065
7140
|
const converted = runtimeTools.filter((tool) => !existingNames.has(tool.name)).map((tool) => ({
|
|
6066
7141
|
name: tool.name,
|
|
@@ -6070,9 +7145,9 @@ function appendRuntimeToolsToAgentRequest(request, runtimeTools) {
|
|
|
6070
7145
|
...tool.config ? { config: tool.config } : {}
|
|
6071
7146
|
}));
|
|
6072
7147
|
return {
|
|
6073
|
-
...
|
|
7148
|
+
...request2,
|
|
6074
7149
|
tools: {
|
|
6075
|
-
...
|
|
7150
|
+
...request2.tools,
|
|
6076
7151
|
runtimeTools: [...existing, ...converted]
|
|
6077
7152
|
}
|
|
6078
7153
|
};
|
|
@@ -6148,21 +7223,21 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6148
7223
|
* Attach approved runtime tools to an agent execute request.
|
|
6149
7224
|
* Returns a new request object and does not mutate the original.
|
|
6150
7225
|
*/
|
|
6151
|
-
attachApprovedRuntimeTools(
|
|
6152
|
-
return appendRuntimeToolsToAgentRequest(
|
|
7226
|
+
attachApprovedRuntimeTools(request2, runtimeTools) {
|
|
7227
|
+
return appendRuntimeToolsToAgentRequest(request2, runtimeTools);
|
|
6153
7228
|
}
|
|
6154
7229
|
/**
|
|
6155
7230
|
* Validate a generated runtime tool proposal and append it to an agent execute
|
|
6156
7231
|
* request if approved, in one call.
|
|
6157
7232
|
*/
|
|
6158
|
-
applyGeneratedRuntimeToolProposal(
|
|
7233
|
+
applyGeneratedRuntimeToolProposal(request2, proposal, options) {
|
|
6159
7234
|
const decision = evaluateGeneratedRuntimeToolProposal(proposal, options);
|
|
6160
7235
|
if (!decision.approved || !decision.tool) {
|
|
6161
|
-
return { decision, request };
|
|
7236
|
+
return { decision, request: request2 };
|
|
6162
7237
|
}
|
|
6163
7238
|
return {
|
|
6164
7239
|
decision,
|
|
6165
|
-
request: appendRuntimeToolsToAgentRequest(
|
|
7240
|
+
request: appendRuntimeToolsToAgentRequest(request2, [decision.tool])
|
|
6166
7241
|
};
|
|
6167
7242
|
}
|
|
6168
7243
|
/**
|
|
@@ -6192,13 +7267,14 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6192
7267
|
* // ...
|
|
6193
7268
|
* ```
|
|
6194
7269
|
*/
|
|
6195
|
-
async executeStream(id, data) {
|
|
7270
|
+
async executeStream(id, data, init) {
|
|
6196
7271
|
return this.client.requestStream(`/agents/${id}/execute`, {
|
|
6197
7272
|
method: "POST",
|
|
6198
7273
|
body: JSON.stringify({
|
|
6199
7274
|
...data,
|
|
6200
7275
|
streamResponse: true
|
|
6201
|
-
})
|
|
7276
|
+
}),
|
|
7277
|
+
...init?.signal ? { signal: init.signal } : {}
|
|
6202
7278
|
});
|
|
6203
7279
|
}
|
|
6204
7280
|
/**
|
|
@@ -6294,56 +7370,94 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6294
7370
|
runtimeTools: [...data.tools?.runtimeTools || [], ...runtimeTools]
|
|
6295
7371
|
}
|
|
6296
7372
|
};
|
|
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;
|
|
7373
|
+
const abortSignal = options?.abortSignal;
|
|
6303
7374
|
let accumulatedOutput = "";
|
|
6304
7375
|
let lastKnownCost = 0;
|
|
6305
7376
|
let lastKnownTokens;
|
|
7377
|
+
let lastSeenExecutionId = "";
|
|
6306
7378
|
let pauseCount = 0;
|
|
6307
7379
|
let discoveryPauseCount = 0;
|
|
6308
7380
|
let consecutiveDiscoveryPauseCount = 0;
|
|
6309
7381
|
const toolNameCounts = {};
|
|
6310
7382
|
let recentActionKeys = [];
|
|
6311
7383
|
const toolMessages = [];
|
|
7384
|
+
const finishAborted = (executionId) => {
|
|
7385
|
+
const abortCompleteEvent = {
|
|
7386
|
+
type: "agent_complete",
|
|
7387
|
+
executionId,
|
|
7388
|
+
seq: 0,
|
|
7389
|
+
agentId: id,
|
|
7390
|
+
success: true,
|
|
7391
|
+
iterations: 1,
|
|
7392
|
+
stopReason: "end_turn",
|
|
7393
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7394
|
+
totalCost: lastKnownCost,
|
|
7395
|
+
...lastKnownTokens ? { totalTokens: lastKnownTokens } : {},
|
|
7396
|
+
finalOutput: [accumulatedOutput.trim(), "Session aborted by user request."].filter(Boolean).join("\n\n"),
|
|
7397
|
+
duration: 0
|
|
7398
|
+
};
|
|
7399
|
+
callbacks?.onAgentComplete?.(abortCompleteEvent);
|
|
7400
|
+
return { completeEvent: abortCompleteEvent, toolMessages };
|
|
7401
|
+
};
|
|
7402
|
+
let response;
|
|
7403
|
+
try {
|
|
7404
|
+
response = await this.executeStream(id, requestData, {
|
|
7405
|
+
...abortSignal ? { signal: abortSignal } : {}
|
|
7406
|
+
});
|
|
7407
|
+
} catch (error) {
|
|
7408
|
+
if (abortSignal?.aborted) return finishAborted(lastSeenExecutionId);
|
|
7409
|
+
throw error;
|
|
7410
|
+
}
|
|
7411
|
+
if (!response.ok) {
|
|
7412
|
+
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
7413
|
+
throw new Error(error.error || `HTTP ${response.status}`);
|
|
7414
|
+
}
|
|
7415
|
+
let currentBody = response.body;
|
|
6312
7416
|
while (true) {
|
|
6313
7417
|
let pausedEvent = null;
|
|
6314
7418
|
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
|
-
|
|
7419
|
+
try {
|
|
7420
|
+
await processAgentStream(currentBody, {
|
|
7421
|
+
...callbacks,
|
|
7422
|
+
onAgentStart: (event) => {
|
|
7423
|
+
lastSeenExecutionId = event.executionId;
|
|
7424
|
+
callbacks?.onAgentStart?.(event);
|
|
7425
|
+
},
|
|
7426
|
+
onTurnDelta: (event) => {
|
|
7427
|
+
if (event.contentType === "text") {
|
|
7428
|
+
accumulatedOutput += event.delta;
|
|
7429
|
+
}
|
|
7430
|
+
callbacks?.onTurnDelta?.(event);
|
|
7431
|
+
},
|
|
7432
|
+
onTurnComplete: (event) => {
|
|
7433
|
+
if (typeof event.cost === "number") {
|
|
7434
|
+
lastKnownCost = event.cost;
|
|
7435
|
+
}
|
|
7436
|
+
if (event.tokens) {
|
|
7437
|
+
lastKnownTokens = event.tokens;
|
|
7438
|
+
}
|
|
7439
|
+
callbacks?.onTurnComplete?.(event);
|
|
7440
|
+
},
|
|
7441
|
+
onAgentPaused: (event) => {
|
|
7442
|
+
pausedEvent = event;
|
|
7443
|
+
callbacks?.onAgentPaused?.(event);
|
|
7444
|
+
},
|
|
7445
|
+
onAgentComplete: (event) => {
|
|
7446
|
+
if (!event.finalOutput && accumulatedOutput) {
|
|
7447
|
+
event.finalOutput = accumulatedOutput;
|
|
7448
|
+
}
|
|
7449
|
+
completeEvent = event;
|
|
7450
|
+
callbacks?.onAgentComplete?.(event);
|
|
6339
7451
|
}
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
7452
|
+
});
|
|
7453
|
+
} catch (error) {
|
|
7454
|
+
if (abortSignal?.aborted) return finishAborted(lastSeenExecutionId);
|
|
7455
|
+
throw error;
|
|
7456
|
+
}
|
|
6344
7457
|
if (completeEvent) return { completeEvent, toolMessages };
|
|
6345
7458
|
if (pausedEvent) {
|
|
6346
7459
|
const { toolName, toolId, parameters, executionId } = pausedEvent;
|
|
7460
|
+
lastSeenExecutionId = executionId;
|
|
6347
7461
|
const toolDef = localTools[toolName];
|
|
6348
7462
|
if (!toolDef) {
|
|
6349
7463
|
throw new Error(`Local tool "${toolName}" required but not provided`);
|
|
@@ -6458,6 +7572,19 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6458
7572
|
callbacks?.onAgentComplete?.(forcedCompleteEvent);
|
|
6459
7573
|
return { completeEvent: forcedCompleteEvent, toolMessages };
|
|
6460
7574
|
}
|
|
7575
|
+
if (abortSignal?.aborted) {
|
|
7576
|
+
callbacks?.onLocalToolExecutionComplete?.({
|
|
7577
|
+
executionId,
|
|
7578
|
+
toolCallId: toolId,
|
|
7579
|
+
toolName,
|
|
7580
|
+
parameters: parsedParams,
|
|
7581
|
+
result: toolResult,
|
|
7582
|
+
success: true,
|
|
7583
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7584
|
+
durationMs: Date.now() - localExecutionStartedAtMs
|
|
7585
|
+
});
|
|
7586
|
+
return finishAborted(executionId);
|
|
7587
|
+
}
|
|
6461
7588
|
if (options?.shouldInterrupt?.()) {
|
|
6462
7589
|
callbacks?.onLocalToolExecutionComplete?.({
|
|
6463
7590
|
executionId,
|
|
@@ -6491,15 +7618,22 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6491
7618
|
callbacks?.onAgentComplete?.(interruptCompleteEvent);
|
|
6492
7619
|
return { completeEvent: interruptCompleteEvent, toolMessages };
|
|
6493
7620
|
}
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
7621
|
+
let resumeResponse;
|
|
7622
|
+
try {
|
|
7623
|
+
resumeResponse = await this.client.requestStream(`/agents/${id}/resume`, {
|
|
7624
|
+
method: "POST",
|
|
7625
|
+
body: JSON.stringify({
|
|
7626
|
+
executionId,
|
|
7627
|
+
toolOutputs: { [toolName]: toolResult },
|
|
7628
|
+
streamResponse: true,
|
|
7629
|
+
debugMode: data.debugMode
|
|
7630
|
+
}),
|
|
7631
|
+
...abortSignal ? { signal: abortSignal } : {}
|
|
7632
|
+
});
|
|
7633
|
+
} catch (error) {
|
|
7634
|
+
if (abortSignal?.aborted) return finishAborted(executionId);
|
|
7635
|
+
throw error;
|
|
7636
|
+
}
|
|
6503
7637
|
if (!resumeResponse.ok) {
|
|
6504
7638
|
const error = await resumeResponse.json().catch(() => ({ error: "Unknown error" }));
|
|
6505
7639
|
throw new Error(error.error || `HTTP ${resumeResponse.status}`);
|
|
@@ -6517,6 +7651,7 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6517
7651
|
currentBody = resumeResponse.body;
|
|
6518
7652
|
continue;
|
|
6519
7653
|
}
|
|
7654
|
+
if (abortSignal?.aborted) return finishAborted(lastSeenExecutionId);
|
|
6520
7655
|
return null;
|
|
6521
7656
|
}
|
|
6522
7657
|
}
|
|
@@ -6788,7 +7923,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6788
7923
|
reasons.push("Best candidate file has not been verified (read back after writing)");
|
|
6789
7924
|
}
|
|
6790
7925
|
if (state.verificationRequired && !state.lastVerificationPassed && !trace.verificationPassed) {
|
|
6791
|
-
reasons.push(
|
|
7926
|
+
reasons.push(
|
|
7927
|
+
"Verification has not passed \u2014 run a verification command (run_check) before completing"
|
|
7928
|
+
);
|
|
6792
7929
|
}
|
|
6793
7930
|
return reasons.length > 0 ? reasons.join("; ") : "Completion gates not satisfied for the current workflow phase";
|
|
6794
7931
|
}
|
|
@@ -6831,32 +7968,71 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6831
7968
|
);
|
|
6832
7969
|
}
|
|
6833
7970
|
/**
|
|
6834
|
-
*
|
|
6835
|
-
*
|
|
7971
|
+
* Resolve the replay window: the base index sliced off the full history and
|
|
7972
|
+
* the durable summary message that stands in for everything before it.
|
|
7973
|
+
* The base is honored ONLY when the latest summary actually exists —
|
|
7974
|
+
* slicing history with no summary substitute would silently drop prior
|
|
7975
|
+
* context (defensive against states that carried a base but lost their
|
|
7976
|
+
* summaries). The base is also clamped so a stale pointer (fork truncation,
|
|
7977
|
+
* trimmed legacy state) never slices past the end of the array.
|
|
6836
7978
|
*/
|
|
6837
|
-
|
|
6838
|
-
|
|
7979
|
+
resolveWindowReplay(state, messageCount) {
|
|
7980
|
+
const base = state.contextWindowBaseIndex ?? 0;
|
|
7981
|
+
if (!Number.isFinite(base) || base <= 0) {
|
|
7982
|
+
return { windowBase: 0, windowSummaryMessages: [] };
|
|
7983
|
+
}
|
|
7984
|
+
const summaries = state.contextCompactionSummaries;
|
|
7985
|
+
const latest = summaries?.[summaries.length - 1];
|
|
7986
|
+
if (!latest) {
|
|
7987
|
+
return { windowBase: 0, windowSummaryMessages: [] };
|
|
7988
|
+
}
|
|
7989
|
+
return {
|
|
7990
|
+
windowBase: Math.min(Math.floor(base), messageCount),
|
|
7991
|
+
windowSummaryMessages: [{ role: "system", content: latest.content }]
|
|
7992
|
+
};
|
|
7993
|
+
}
|
|
7994
|
+
/**
|
|
7995
|
+
* Derive the message view sent to the model based on context mode and window
|
|
7996
|
+
* setting. This never mutates persisted marathon history; masking/offloading
|
|
7997
|
+
* is a send-time view over the full-fidelity ledger/history.
|
|
7998
|
+
*/
|
|
7999
|
+
deriveToolContextMessages(messages, taskName, mode, window) {
|
|
8000
|
+
if (mode === "full-inline") return [...messages];
|
|
8001
|
+
const maskMessage = (msg) => ({
|
|
8002
|
+
...msg,
|
|
8003
|
+
toolResults: (msg.toolResults ?? []).map((tr) => this.compactOneResult(tr, taskName, mode))
|
|
8004
|
+
});
|
|
8005
|
+
const view = [...messages];
|
|
6839
8006
|
if (window === "session") {
|
|
6840
|
-
|
|
8007
|
+
const lastUserIndex = view.reduce(
|
|
8008
|
+
(lastIndex, message, index) => message.role === "user" ? index : lastIndex,
|
|
8009
|
+
-1
|
|
8010
|
+
);
|
|
8011
|
+
for (let index = 0; index < view.length; index++) {
|
|
8012
|
+
if (lastUserIndex >= 0 && index > lastUserIndex) continue;
|
|
8013
|
+
const msg = view[index];
|
|
8014
|
+
if (!msg) continue;
|
|
6841
8015
|
if (msg.role === "tool" && msg.toolResults) {
|
|
6842
|
-
|
|
8016
|
+
view[index] = maskMessage(msg);
|
|
6843
8017
|
}
|
|
6844
8018
|
}
|
|
6845
8019
|
} else {
|
|
6846
|
-
const newToolResultCount = newToolMessages.filter((m) => m.role === "tool").length;
|
|
6847
|
-
const keepInlineFromExisting = Math.max(0, window - newToolResultCount);
|
|
6848
8020
|
const toolResultIndices = [];
|
|
6849
|
-
for (let i = 0; i <
|
|
6850
|
-
|
|
8021
|
+
for (let i = 0; i < view.length; i++) {
|
|
8022
|
+
const message = view[i];
|
|
8023
|
+
if (message?.role === "tool" && message.toolResults) {
|
|
6851
8024
|
toolResultIndices.push(i);
|
|
6852
8025
|
}
|
|
6853
8026
|
}
|
|
6854
|
-
const compactUpTo = toolResultIndices.length -
|
|
8027
|
+
const compactUpTo = toolResultIndices.length - window;
|
|
6855
8028
|
for (let j = 0; j < compactUpTo && j < toolResultIndices.length; j++) {
|
|
6856
|
-
const
|
|
6857
|
-
msg
|
|
8029
|
+
const index = toolResultIndices[j];
|
|
8030
|
+
const msg = index === void 0 ? void 0 : view[index];
|
|
8031
|
+
if (!msg) continue;
|
|
8032
|
+
view[index] = maskMessage(msg);
|
|
6858
8033
|
}
|
|
6859
8034
|
}
|
|
8035
|
+
return view;
|
|
6860
8036
|
}
|
|
6861
8037
|
compactOneResult(tr, taskName, mode) {
|
|
6862
8038
|
if (typeof tr.result === "string" && tr.result.startsWith("[")) return tr;
|
|
@@ -6892,10 +8068,20 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
6892
8068
|
}
|
|
6893
8069
|
const slug = this.sanitizeTaskSlug(taskName || "task");
|
|
6894
8070
|
const dir = `.runtype/marathons/${slug}/tool-outputs`;
|
|
6895
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
6896
8071
|
const filePath = `${dir}/${toolCallId}.txt`;
|
|
6897
|
-
|
|
6898
|
-
|
|
8072
|
+
try {
|
|
8073
|
+
if (!fs.existsSync(filePath)) {
|
|
8074
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
8075
|
+
fs.writeFileSync(filePath, resultStr, "utf-8");
|
|
8076
|
+
}
|
|
8077
|
+
} catch {
|
|
8078
|
+
return result;
|
|
8079
|
+
}
|
|
8080
|
+
return buildSendViewOffloadMarker({
|
|
8081
|
+
toolName,
|
|
8082
|
+
charLength: resultStr.length,
|
|
8083
|
+
filePath
|
|
8084
|
+
});
|
|
6899
8085
|
}
|
|
6900
8086
|
getDefaultPlanPath(taskName) {
|
|
6901
8087
|
return getDefaultPlanPath(taskName);
|
|
@@ -7017,6 +8203,7 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7017
8203
|
const migratedPlanPath = workflowVariant === "external" && planPath === this.getDefaultPlanPath(taskName) ? this.getDefaultExternalReportPath(taskName) : planPath;
|
|
7018
8204
|
const candidatePaths = this.dedupeNormalizedCandidatePaths(resumeState.candidatePaths);
|
|
7019
8205
|
const recentReadPaths = this.dedupeNormalizedCandidatePaths(resumeState.recentReadPaths);
|
|
8206
|
+
const contextCompactionSummaries = (resumeState.contextCompactionSummaries ?? []).slice(-20);
|
|
7020
8207
|
const normalizedBestCandidatePath = typeof resumeState.bestCandidatePath === "string" && resumeState.bestCandidatePath.trim() ? this.normalizeCandidatePath(resumeState.bestCandidatePath) : void 0;
|
|
7021
8208
|
const bestCandidatePath = normalizedBestCandidatePath && !this.isMarathonArtifactPath(normalizedBestCandidatePath) ? normalizedBestCandidatePath : [...candidatePaths, ...recentReadPaths].sort(
|
|
7022
8209
|
(left, right) => this.scoreCandidatePath(right) - this.scoreCandidatePath(left)
|
|
@@ -7036,10 +8223,14 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7036
8223
|
bestCandidateVerified: Boolean(resumeState.bestCandidateVerified),
|
|
7037
8224
|
...resumeState.verificationRequired !== void 0 ? { verificationRequired: resumeState.verificationRequired } : {},
|
|
7038
8225
|
lastVerificationPassed: Boolean(resumeState.lastVerificationPassed),
|
|
7039
|
-
...resumeState.consecutiveBlockedVerificationSessions !== void 0 ? {
|
|
8226
|
+
...resumeState.consecutiveBlockedVerificationSessions !== void 0 ? {
|
|
8227
|
+
consecutiveBlockedVerificationSessions: resumeState.consecutiveBlockedVerificationSessions
|
|
8228
|
+
} : {},
|
|
7040
8229
|
...resumeState.isCreationTask !== void 0 ? { isCreationTask: resumeState.isCreationTask } : {},
|
|
7041
8230
|
...resumeState.workflowVariant !== void 0 ? { workflowVariant: resumeState.workflowVariant } : {},
|
|
7042
8231
|
...resumeState.workflowState !== void 0 ? { workflowState: resumeState.workflowState } : {},
|
|
8232
|
+
...contextCompactionSummaries.length ? { contextCompactionSummaries } : {},
|
|
8233
|
+
...typeof resumeState.contextWindowBaseIndex === "number" && Number.isFinite(resumeState.contextWindowBaseIndex) && resumeState.contextWindowBaseIndex > 0 ? { contextWindowBaseIndex: Math.floor(resumeState.contextWindowBaseIndex) } : {},
|
|
7043
8234
|
...typeof resumeState.outputRoot === "string" && resumeState.outputRoot.trim() ? { outputRoot: resumeState.outputRoot.trim().replace(/\\/g, "/").replace(/\/+/g, "/") } : {}
|
|
7044
8235
|
};
|
|
7045
8236
|
}
|
|
@@ -7439,8 +8630,11 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7439
8630
|
}
|
|
7440
8631
|
buildStuckTurnRecoveryMessage(state, workflow) {
|
|
7441
8632
|
const currentPhase = workflow.phases.find((p) => p.name === state.workflowPhase);
|
|
7442
|
-
|
|
7443
|
-
|
|
8633
|
+
const phaseMessage = currentPhase?.buildRecoveryMessage?.(state);
|
|
8634
|
+
if (phaseMessage) return phaseMessage;
|
|
8635
|
+
const emptySessions = state.consecutiveEmptySessions || 0;
|
|
8636
|
+
if (shouldInjectEmptySessionNudge(workflow.stallPolicy, emptySessions)) {
|
|
8637
|
+
return buildEmptySessionNudge(emptySessions);
|
|
7444
8638
|
}
|
|
7445
8639
|
return void 0;
|
|
7446
8640
|
}
|
|
@@ -7505,8 +8699,13 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7505
8699
|
} : {},
|
|
7506
8700
|
...seededResumeState?.candidatePaths ? { candidatePaths: seededResumeState.candidatePaths } : {},
|
|
7507
8701
|
...seededResumeState?.recentReadPaths ? { recentReadPaths: seededResumeState.recentReadPaths } : {},
|
|
7508
|
-
...seededResumeState?.recentActionKeys ? { recentActionKeys: seededResumeState.recentActionKeys } : {}
|
|
8702
|
+
...seededResumeState?.recentActionKeys ? { recentActionKeys: seededResumeState.recentActionKeys } : {},
|
|
8703
|
+
...seededResumeState?.contextCompactionSummaries?.length ? { contextCompactionSummaries: seededResumeState.contextCompactionSummaries } : {},
|
|
8704
|
+
...typeof seededResumeState?.contextWindowBaseIndex === "number" ? { contextWindowBaseIndex: seededResumeState.contextWindowBaseIndex } : {}
|
|
7509
8705
|
};
|
|
8706
|
+
if (options.previousMessages && options.previousMessages.length > 0) {
|
|
8707
|
+
state.messages = options.previousMessages.map((message) => structuredClone(message));
|
|
8708
|
+
}
|
|
7510
8709
|
state.workflowVariant = classifiedVariant;
|
|
7511
8710
|
state.isCreationTask = seededResumeState?.isCreationTask ?? state.workflowVariant === "create";
|
|
7512
8711
|
state.outputRoot = seededResumeState?.outputRoot ?? (state.isCreationTask ? "public/" : void 0);
|
|
@@ -7539,6 +8738,10 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7539
8738
|
}
|
|
7540
8739
|
}
|
|
7541
8740
|
for (let session = 0; session < maxSessions; session++) {
|
|
8741
|
+
if (options.abortSignal?.aborted) {
|
|
8742
|
+
state.status = "paused";
|
|
8743
|
+
break;
|
|
8744
|
+
}
|
|
7542
8745
|
const phaseAtSessionStart = state.workflowPhase;
|
|
7543
8746
|
const sessionTrace = this.createEmptyToolTrace();
|
|
7544
8747
|
const sessionLocalTools = this.wrapLocalToolsForTrace(
|
|
@@ -7557,6 +8760,10 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7557
8760
|
state.originalMessage = options.message;
|
|
7558
8761
|
}
|
|
7559
8762
|
const queuedSteeringMessages = options.getQueuedUserMessages?.() ?? [];
|
|
8763
|
+
if (queuedSteeringMessages.length > 0) {
|
|
8764
|
+
state.consecutiveEmptySessions = 0;
|
|
8765
|
+
state.stallEscalationRequested = void 0;
|
|
8766
|
+
}
|
|
7560
8767
|
const preparedSession = await this.prepareSessionContext(
|
|
7561
8768
|
options.message,
|
|
7562
8769
|
state,
|
|
@@ -7575,7 +8782,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7575
8782
|
localTools: options.localTools,
|
|
7576
8783
|
builtinToolSchemas,
|
|
7577
8784
|
onContextCompaction: options.onContextCompaction,
|
|
7578
|
-
onContextNotice: options.onContextNotice
|
|
8785
|
+
onContextNotice: options.onContextNotice,
|
|
8786
|
+
toolContextMode: options.toolContextMode || "hot-tail",
|
|
8787
|
+
toolWindow: options.toolWindow ?? "session"
|
|
7579
8788
|
},
|
|
7580
8789
|
queuedSteeringMessages
|
|
7581
8790
|
);
|
|
@@ -7605,7 +8814,8 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7605
8814
|
sessionCallbacks,
|
|
7606
8815
|
{
|
|
7607
8816
|
onLocalToolResult: this.createLocalToolLoopGuard(state, sessionTrace, workflow),
|
|
7608
|
-
shouldInterrupt: options.hasQueuedUserMessages
|
|
8817
|
+
shouldInterrupt: options.hasQueuedUserMessages,
|
|
8818
|
+
...options.abortSignal ? { abortSignal: options.abortSignal } : {}
|
|
7609
8819
|
},
|
|
7610
8820
|
state.taskName
|
|
7611
8821
|
);
|
|
@@ -7754,22 +8964,13 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7754
8964
|
}
|
|
7755
8965
|
}
|
|
7756
8966
|
if (!state.messages) state.messages = [];
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
state.messages.push(...newMessages);
|
|
7762
|
-
} else {
|
|
8967
|
+
const sentUserMessage = messages[messages.length - 1];
|
|
8968
|
+
if (sentUserMessage?.role === "user") {
|
|
8969
|
+
state.messages.push(sentUserMessage);
|
|
8970
|
+
} else if (state.messages.length === 0) {
|
|
7763
8971
|
state.messages.push(...messages);
|
|
7764
8972
|
}
|
|
7765
8973
|
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
8974
|
state.messages.push(...sessionToolMessages);
|
|
7774
8975
|
}
|
|
7775
8976
|
const assistantContent = effectiveSessionOutput || `[Session ${session + 1} completed (${sessionResult.stopReason}). No text output captured.]`;
|
|
@@ -7789,7 +8990,10 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7789
8990
|
workflow
|
|
7790
8991
|
);
|
|
7791
8992
|
if (detectedTaskCompletion && !acceptedTaskCompletion) {
|
|
7792
|
-
state.lastCompletionRejectionReason = this.computeCompletionRejectionReason(
|
|
8993
|
+
state.lastCompletionRejectionReason = this.computeCompletionRejectionReason(
|
|
8994
|
+
state,
|
|
8995
|
+
sessionTrace
|
|
8996
|
+
);
|
|
7793
8997
|
if (state.verificationRequired && !state.lastVerificationPassed && !sessionTrace.verificationPassed && !sessionTrace.verificationAttempted) {
|
|
7794
8998
|
state.consecutiveBlockedVerificationSessions = (state.consecutiveBlockedVerificationSessions || 0) + 1;
|
|
7795
8999
|
if ((state.consecutiveBlockedVerificationSessions || 0) >= 2) {
|
|
@@ -7800,32 +9004,36 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7800
9004
|
} else {
|
|
7801
9005
|
state.lastCompletionRejectionReason = void 0;
|
|
7802
9006
|
}
|
|
7803
|
-
const sessionHadActions = sessionTrace.wroteFiles || sessionTrace.readFiles || sessionTrace.discoveryPerformed || sessionTrace.verificationAttempted;
|
|
9007
|
+
const sessionHadActions = sessionTrace.wroteFiles || sessionTrace.readFiles || sessionTrace.discoveryPerformed || sessionTrace.verificationAttempted || options.hasQueuedUserMessages?.() === true;
|
|
7804
9008
|
if (sessionHadActions) {
|
|
7805
9009
|
state.consecutiveEmptySessions = 0;
|
|
9010
|
+
state.stallEscalationRequested = void 0;
|
|
7806
9011
|
} else {
|
|
7807
9012
|
state.consecutiveEmptySessions = (state.consecutiveEmptySessions || 0) + 1;
|
|
9013
|
+
if (shouldRequestModelEscalation(workflow.stallPolicy, state.consecutiveEmptySessions)) {
|
|
9014
|
+
state.stallEscalationRequested = true;
|
|
9015
|
+
}
|
|
7808
9016
|
}
|
|
7809
9017
|
if (sessionResult.stopReason === "complete" && !detectedTaskCompletion) {
|
|
7810
9018
|
const currentPhase = workflow.phases.find((p) => p.name === state.workflowPhase);
|
|
7811
|
-
const gatesSatisfied = currentPhase?.canAcceptCompletion ? currentPhase.canAcceptCompletion(
|
|
9019
|
+
const gatesSatisfied = currentPhase?.canAcceptCompletion ? currentPhase.canAcceptCompletion(
|
|
9020
|
+
state,
|
|
9021
|
+
sessionTrace
|
|
9022
|
+
) : true;
|
|
7812
9023
|
if (gatesSatisfied) {
|
|
7813
9024
|
state.status = "complete";
|
|
7814
9025
|
}
|
|
7815
9026
|
} else if (sessionResult.stopReason === "error") {
|
|
7816
9027
|
if (_AgentsEndpoint.isRetryableSessionError(sessionResult.error) && consecutiveServerNetworkErrors < maxServerNetworkRetries) {
|
|
7817
9028
|
consecutiveServerNetworkErrors++;
|
|
7818
|
-
const delayMs = Math.min(
|
|
7819
|
-
5e3 * Math.pow(2, consecutiveServerNetworkErrors - 1),
|
|
7820
|
-
3e4
|
|
7821
|
-
);
|
|
9029
|
+
const delayMs = Math.min(5e3 * Math.pow(2, consecutiveServerNetworkErrors - 1), 3e4);
|
|
7822
9030
|
const delaySec = Math.round(delayMs / 1e3);
|
|
7823
9031
|
await this.emitContextNotice(options.onContextNotice, {
|
|
7824
9032
|
kind: "server_network_retry",
|
|
7825
9033
|
sessionIndex: session,
|
|
7826
9034
|
message: `Server network error: ${sessionResult.error}. Retrying in ${delaySec}s (attempt ${consecutiveServerNetworkErrors}/${maxServerNetworkRetries})...`
|
|
7827
9035
|
});
|
|
7828
|
-
await
|
|
9036
|
+
await sleepWithAbort(delayMs, options.abortSignal);
|
|
7829
9037
|
} else {
|
|
7830
9038
|
state.status = "error";
|
|
7831
9039
|
}
|
|
@@ -7833,13 +9041,16 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7833
9041
|
state.status = "budget_exceeded";
|
|
7834
9042
|
} else if (acceptedTaskCompletion) {
|
|
7835
9043
|
state.status = "complete";
|
|
7836
|
-
} else if ((state.consecutiveEmptySessions || 0) >=
|
|
9044
|
+
} else if ((state.consecutiveEmptySessions || 0) >= resolveStallStopAfter(workflow.stallPolicy)) {
|
|
7837
9045
|
state.status = "stalled";
|
|
7838
9046
|
} else if (maxCost && state.totalCost >= maxCost) {
|
|
7839
9047
|
state.status = "budget_exceeded";
|
|
7840
9048
|
} else if (session + 1 >= maxSessions) {
|
|
7841
9049
|
state.status = "max_sessions";
|
|
7842
9050
|
}
|
|
9051
|
+
if (options.abortSignal?.aborted) {
|
|
9052
|
+
state.status = "paused";
|
|
9053
|
+
}
|
|
7843
9054
|
if (options.trackProgress) {
|
|
7844
9055
|
recordId = await this.syncProgressRecord(state, recordId);
|
|
7845
9056
|
}
|
|
@@ -7916,6 +9127,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7916
9127
|
return 0;
|
|
7917
9128
|
}
|
|
7918
9129
|
}
|
|
9130
|
+
extractDeclaredToolResultChars(value) {
|
|
9131
|
+
return extractDeclaredToolResultChars(value);
|
|
9132
|
+
}
|
|
7919
9133
|
estimateMessageContentTokens(content) {
|
|
7920
9134
|
if (typeof content === "string") return this.estimateTextTokens(content);
|
|
7921
9135
|
return content.reduce((total, part) => {
|
|
@@ -7934,12 +9148,14 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7934
9148
|
0
|
|
7935
9149
|
);
|
|
7936
9150
|
}
|
|
7937
|
-
estimateToolResultTokens(toolResults) {
|
|
9151
|
+
estimateToolResultTokens(toolResults, options) {
|
|
7938
9152
|
if (!toolResults || toolResults.length === 0) return 0;
|
|
7939
|
-
return toolResults.reduce(
|
|
7940
|
-
|
|
7941
|
-
0
|
|
7942
|
-
|
|
9153
|
+
return toolResults.reduce((sum, toolResult) => {
|
|
9154
|
+
const resultTokens = this.estimateUnknownTokens(toolResult.result);
|
|
9155
|
+
const declaredChars = options?.useDeclaredSize ? this.extractDeclaredToolResultChars(toolResult.result) : void 0;
|
|
9156
|
+
const declaredTokens = typeof declaredChars === "number" ? Math.ceil(declaredChars / 4) : 0;
|
|
9157
|
+
return sum + 12 + this.estimateTextTokens(toolResult.toolName) + Math.max(resultTokens, declaredTokens);
|
|
9158
|
+
}, 0);
|
|
7943
9159
|
}
|
|
7944
9160
|
estimateMessageTokens(message) {
|
|
7945
9161
|
return 6 + this.estimateMessageContentTokens(message.content) + this.estimateToolCallTokens(message.toolCalls) + this.estimateToolResultTokens(message.toolResults);
|
|
@@ -7947,13 +9163,15 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
7947
9163
|
estimateConversationTokens(messages) {
|
|
7948
9164
|
return messages.reduce((sum, message) => sum + this.estimateMessageTokens(message), 0);
|
|
7949
9165
|
}
|
|
7950
|
-
estimateConversationBreakdown(messages) {
|
|
9166
|
+
estimateConversationBreakdown(messages, options) {
|
|
7951
9167
|
let historyTokens = 0;
|
|
7952
9168
|
let toolOutputTokens = 0;
|
|
7953
9169
|
for (const message of messages) {
|
|
7954
9170
|
const contentTokens = this.estimateMessageContentTokens(message.content);
|
|
7955
9171
|
const toolCallTokens = this.estimateToolCallTokens(message.toolCalls);
|
|
7956
|
-
const toolResultTokens = this.estimateToolResultTokens(message.toolResults
|
|
9172
|
+
const toolResultTokens = this.estimateToolResultTokens(message.toolResults, {
|
|
9173
|
+
useDeclaredSize: options?.useDeclaredToolResultSizes
|
|
9174
|
+
});
|
|
7957
9175
|
const messageTotal = 6 + contentTokens + toolCallTokens + toolResultTokens;
|
|
7958
9176
|
if (message.role === "tool") {
|
|
7959
9177
|
toolOutputTokens += messageTotal;
|
|
@@ -8007,13 +9225,24 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
8007
9225
|
const compactInstructions = config.compactInstructions;
|
|
8008
9226
|
return typeof compactInstructions === "string" && compactInstructions.trim() ? compactInstructions.trim() : void 0;
|
|
8009
9227
|
}
|
|
8010
|
-
|
|
9228
|
+
extractArtifactReferencesFromMessages(messages = []) {
|
|
8011
9229
|
const references = /* @__PURE__ */ new Set();
|
|
8012
9230
|
const offloadPrefix = "[Output saved to ";
|
|
8013
|
-
|
|
9231
|
+
const ledgerArtifactPrefix = LEDGER_ARTIFACT_LINE_PREFIX;
|
|
9232
|
+
const savedToPattern = /saved to\s+([^—\]\n]+?)(?:\s+—|\]|\n|$)/gi;
|
|
9233
|
+
for (const message of messages) {
|
|
8014
9234
|
if (!message.toolResults) continue;
|
|
8015
9235
|
for (const toolResult of message.toolResults) {
|
|
8016
9236
|
if (typeof toolResult.result !== "string") continue;
|
|
9237
|
+
for (const line of toolResult.result.split("\n")) {
|
|
9238
|
+
if (line.startsWith(ledgerArtifactPrefix)) {
|
|
9239
|
+
references.add(line.slice(ledgerArtifactPrefix.length).trim());
|
|
9240
|
+
}
|
|
9241
|
+
}
|
|
9242
|
+
for (const match of toolResult.result.matchAll(savedToPattern)) {
|
|
9243
|
+
const pathText = match[1]?.trim();
|
|
9244
|
+
if (pathText) references.add(pathText);
|
|
9245
|
+
}
|
|
8017
9246
|
let startIndex = 0;
|
|
8018
9247
|
while (startIndex < toolResult.result.length) {
|
|
8019
9248
|
const prefixIndex = toolResult.result.indexOf(offloadPrefix, startIndex);
|
|
@@ -8031,6 +9260,13 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
8031
9260
|
}
|
|
8032
9261
|
}
|
|
8033
9262
|
}
|
|
9263
|
+
return Array.from(references);
|
|
9264
|
+
}
|
|
9265
|
+
extractArtifactReferences(state, additionalReferences = []) {
|
|
9266
|
+
const references = /* @__PURE__ */ new Set([
|
|
9267
|
+
...this.extractArtifactReferencesFromMessages(state.messages ?? []),
|
|
9268
|
+
...additionalReferences
|
|
9269
|
+
]);
|
|
8034
9270
|
if (state.planPath) {
|
|
8035
9271
|
references.add(state.planPath);
|
|
8036
9272
|
}
|
|
@@ -8038,6 +9274,9 @@ var _AgentsEndpoint = class _AgentsEndpoint {
|
|
|
8038
9274
|
}
|
|
8039
9275
|
buildContextBudgetBreakdown(details) {
|
|
8040
9276
|
const conversationBreakdown = this.estimateConversationBreakdown(details.historyMessages);
|
|
9277
|
+
const sourceConversationBreakdown = details.sourceHistoryMessages ? this.estimateConversationBreakdown(details.sourceHistoryMessages, {
|
|
9278
|
+
useDeclaredToolResultSizes: true
|
|
9279
|
+
}) : conversationBreakdown;
|
|
8041
9280
|
const currentTurnTokens = this.estimateTextTokens(details.currentTurnContent);
|
|
8042
9281
|
const toolDefinitionTokens = this.estimateToolDefinitionTokens(
|
|
8043
9282
|
details.localTools,
|
|
@@ -8054,15 +9293,26 @@ ${details.summaryText}
|
|
|
8054
9293
|
|
|
8055
9294
|
Do NOT redo any of the above work.`
|
|
8056
9295
|
) : void 0;
|
|
9296
|
+
const sendEstimatedInputTokens = conversationBreakdown.estimatedInputTokens + currentTurnTokens + toolDefinitionTokens;
|
|
9297
|
+
const estimatedInputTokens = sourceConversationBreakdown.estimatedInputTokens + currentTurnTokens + toolDefinitionTokens;
|
|
9298
|
+
const toolOutputReductionTokens = Math.max(
|
|
9299
|
+
0,
|
|
9300
|
+
sourceConversationBreakdown.toolOutputTokens - conversationBreakdown.toolOutputTokens
|
|
9301
|
+
);
|
|
8057
9302
|
return {
|
|
8058
|
-
historyTokens:
|
|
8059
|
-
toolOutputTokens:
|
|
9303
|
+
historyTokens: sourceConversationBreakdown.historyTokens,
|
|
9304
|
+
toolOutputTokens: sourceConversationBreakdown.toolOutputTokens,
|
|
8060
9305
|
currentTurnTokens,
|
|
8061
9306
|
toolDefinitionTokens,
|
|
8062
9307
|
...summaryTokens ? { summaryTokens } : {},
|
|
8063
9308
|
...reservedOutputTokens ? { reservedOutputTokens } : {},
|
|
8064
9309
|
...effectiveInputBudgetTokens ? { effectiveInputBudgetTokens } : {},
|
|
8065
|
-
|
|
9310
|
+
...toolOutputReductionTokens > 0 ? {
|
|
9311
|
+
sendEstimatedInputTokens,
|
|
9312
|
+
sendToolOutputTokens: conversationBreakdown.toolOutputTokens,
|
|
9313
|
+
toolOutputReductionTokens
|
|
9314
|
+
} : {},
|
|
9315
|
+
estimatedInputTokens
|
|
8066
9316
|
};
|
|
8067
9317
|
}
|
|
8068
9318
|
async emitContextCompactionEvent(onContextCompaction, event) {
|
|
@@ -8102,16 +9352,33 @@ Do NOT redo any of the above work.`
|
|
|
8102
9352
|
state,
|
|
8103
9353
|
userContent,
|
|
8104
9354
|
details.compactInstructions,
|
|
8105
|
-
details.mode
|
|
9355
|
+
details.mode,
|
|
9356
|
+
details.artifactReferences
|
|
8106
9357
|
);
|
|
9358
|
+
const summaryMessage = compactMessages[0];
|
|
9359
|
+
if (summaryMessage?.role === "system" && typeof summaryMessage.content === "string") {
|
|
9360
|
+
const existingSummaries = state.contextCompactionSummaries ?? [];
|
|
9361
|
+
state.contextCompactionSummaries = [
|
|
9362
|
+
...existingSummaries,
|
|
9363
|
+
{
|
|
9364
|
+
id: `ctx_${sessionIndex + 1}_${existingSummaries.length + 1}`,
|
|
9365
|
+
sessionIndex: sessionIndex + 1,
|
|
9366
|
+
mode: details.mode,
|
|
9367
|
+
strategy: details.strategy,
|
|
9368
|
+
content: summaryMessage.content,
|
|
9369
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9370
|
+
}
|
|
9371
|
+
].slice(-20);
|
|
9372
|
+
}
|
|
9373
|
+
state.contextWindowBaseIndex = state.messages?.length ?? 0;
|
|
8107
9374
|
await this.emitContextCompactionEvent(details.onContextCompaction, {
|
|
8108
9375
|
phase: "complete",
|
|
8109
9376
|
...baseEvent
|
|
8110
9377
|
});
|
|
8111
9378
|
return compactMessages;
|
|
8112
9379
|
}
|
|
8113
|
-
buildCompactHistoryMessages(state, userContent, compactInstructions, mode = "auto") {
|
|
8114
|
-
const summary = this.generateCompactSummary(state, compactInstructions);
|
|
9380
|
+
buildCompactHistoryMessages(state, userContent, compactInstructions, mode = "auto", artifactReferences) {
|
|
9381
|
+
const summary = this.generateCompactSummary(state, compactInstructions, artifactReferences);
|
|
8115
9382
|
const prefix = mode === "forced" ? this.getForcedCompactionSummaryPrefix(state) : _AgentsEndpoint.AUTO_COMPACT_SUMMARY_PREFIX;
|
|
8116
9383
|
return [
|
|
8117
9384
|
{
|
|
@@ -8128,16 +9395,11 @@ Do NOT redo any of the above work.`
|
|
|
8128
9395
|
}
|
|
8129
9396
|
];
|
|
8130
9397
|
}
|
|
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
9398
|
/**
|
|
8137
9399
|
* Generate a compact summary of prior work for continuation context.
|
|
8138
9400
|
* Used when compact mode is enabled to keep token usage low.
|
|
8139
9401
|
*/
|
|
8140
|
-
generateCompactSummary(state, compactInstructions) {
|
|
9402
|
+
generateCompactSummary(state, compactInstructions, additionalArtifactReferences = []) {
|
|
8141
9403
|
const recentSessions = (state.sessions ?? []).slice(-5);
|
|
8142
9404
|
const sessionSummaries = recentSessions.map(
|
|
8143
9405
|
(session) => `- Session ${session.index}: ${session.stopReason} ($${session.cost.toFixed(4)}) ${session.outputPreview.slice(0, 160)}`
|
|
@@ -8151,7 +9413,7 @@ Do NOT redo any of the above work.`
|
|
|
8151
9413
|
)
|
|
8152
9414
|
).slice(0, 8);
|
|
8153
9415
|
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);
|
|
9416
|
+
const artifactReferences = this.extractArtifactReferences(state, additionalArtifactReferences);
|
|
8155
9417
|
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
9418
|
const instructions = compactInstructions || this.buildDefaultCompactInstructions();
|
|
8157
9419
|
return [
|
|
@@ -8366,14 +9628,23 @@ Do NOT redo any of the above work.`
|
|
|
8366
9628
|
const phaseBlock = ["", this.buildPhaseInstructions(state, wf)].join("\n");
|
|
8367
9629
|
const candidateBlock = wf.buildCandidateBlock?.(state) ?? "";
|
|
8368
9630
|
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
|
-
] : [];
|
|
9631
|
+
const steeringLines = steeringMessages && steeringMessages.length > 0 ? ["--- User steering (queued during the previous session) ---", ...steeringMessages, ""] : [];
|
|
8374
9632
|
if (continuationContext && sessionIndex === 0) {
|
|
8375
|
-
const
|
|
8376
|
-
|
|
9633
|
+
const resumeWindow = this.resolveWindowReplay(
|
|
9634
|
+
state,
|
|
9635
|
+
continuationContext.previousMessages.length
|
|
9636
|
+
);
|
|
9637
|
+
const sourceReplayHistoryMessages = [
|
|
9638
|
+
...resumeWindow.windowSummaryMessages,
|
|
9639
|
+
...this.sanitizeReplayHistoryMessages(
|
|
9640
|
+
continuationContext.previousMessages.slice(resumeWindow.windowBase)
|
|
9641
|
+
)
|
|
9642
|
+
];
|
|
9643
|
+
const replayHistoryMessages = this.deriveToolContextMessages(
|
|
9644
|
+
sourceReplayHistoryMessages,
|
|
9645
|
+
state.taskName,
|
|
9646
|
+
compactionOptions?.toolContextMode || "hot-tail",
|
|
9647
|
+
compactionOptions?.toolWindow ?? "session"
|
|
8377
9648
|
);
|
|
8378
9649
|
const continuationGuardrail = this.buildContinuationGuardrail(state);
|
|
8379
9650
|
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 +9668,15 @@ Do NOT redo any of the above work.`
|
|
|
8397
9668
|
content: userContent
|
|
8398
9669
|
}
|
|
8399
9670
|
];
|
|
8400
|
-
const
|
|
9671
|
+
const replayArtifactReferences = this.extractArtifactReferencesFromMessages(replayHistoryMessages);
|
|
9672
|
+
const summaryText = this.generateCompactSummary(
|
|
9673
|
+
state,
|
|
9674
|
+
compactInstructions,
|
|
9675
|
+
replayArtifactReferences
|
|
9676
|
+
);
|
|
8401
9677
|
const breakdown = this.buildContextBudgetBreakdown({
|
|
8402
9678
|
historyMessages: replayHistoryMessages,
|
|
9679
|
+
sourceHistoryMessages: sourceReplayHistoryMessages,
|
|
8403
9680
|
currentTurnContent: userContent,
|
|
8404
9681
|
localTools: compactionOptions?.localTools,
|
|
8405
9682
|
builtinToolSchemas: compactionOptions?.builtinToolSchemas || [],
|
|
@@ -8425,7 +9702,8 @@ Do NOT redo any of the above work.`
|
|
|
8425
9702
|
reservedOutputTokens: breakdown.reservedOutputTokens,
|
|
8426
9703
|
breakdown,
|
|
8427
9704
|
onContextCompaction: compactionOptions?.onContextCompaction,
|
|
8428
|
-
compactInstructions
|
|
9705
|
+
compactInstructions,
|
|
9706
|
+
artifactReferences: replayArtifactReferences
|
|
8429
9707
|
}
|
|
8430
9708
|
),
|
|
8431
9709
|
requestContextManagement
|
|
@@ -8449,7 +9727,8 @@ Do NOT redo any of the above work.`
|
|
|
8449
9727
|
reservedOutputTokens: breakdown.reservedOutputTokens,
|
|
8450
9728
|
breakdown,
|
|
8451
9729
|
onContextCompaction: compactionOptions?.onContextCompaction,
|
|
8452
|
-
compactInstructions
|
|
9730
|
+
compactInstructions,
|
|
9731
|
+
artifactReferences: replayArtifactReferences
|
|
8453
9732
|
}
|
|
8454
9733
|
),
|
|
8455
9734
|
requestContextManagement
|
|
@@ -8500,23 +9779,45 @@ Do NOT redo any of the above work.`
|
|
|
8500
9779
|
"Do not redo previous work. If the task is already complete, respond with TASK_COMPLETE."
|
|
8501
9780
|
].join("\n");
|
|
8502
9781
|
const MAX_HISTORY_MESSAGES = 60;
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
9782
|
+
const { windowBase, windowSummaryMessages } = this.resolveWindowReplay(
|
|
9783
|
+
state,
|
|
9784
|
+
state.messages.length
|
|
9785
|
+
);
|
|
9786
|
+
let sourceHistoryMessages = this.sanitizeReplayHistoryMessages(
|
|
9787
|
+
state.messages.slice(windowBase)
|
|
9788
|
+
);
|
|
9789
|
+
if (sourceHistoryMessages.length > MAX_HISTORY_MESSAGES) {
|
|
9790
|
+
const trimmedHistory = this.trimReplayHistoryMessages(
|
|
9791
|
+
sourceHistoryMessages,
|
|
9792
|
+
MAX_HISTORY_MESSAGES
|
|
9793
|
+
);
|
|
9794
|
+
sourceHistoryMessages = trimmedHistory.historyMessages;
|
|
8507
9795
|
if (trimmedHistory.trimmedCount > 0) {
|
|
8508
|
-
|
|
9796
|
+
sourceHistoryMessages = [
|
|
8509
9797
|
{
|
|
8510
9798
|
role: "system",
|
|
8511
9799
|
content: `[${trimmedHistory.trimmedCount} earlier messages trimmed to stay within context limits. Original task: ${(state.originalMessage || originalMessage).slice(0, 500)}]`
|
|
8512
9800
|
},
|
|
8513
|
-
...
|
|
9801
|
+
...sourceHistoryMessages
|
|
8514
9802
|
];
|
|
8515
9803
|
}
|
|
8516
9804
|
}
|
|
8517
|
-
|
|
9805
|
+
sourceHistoryMessages = [...windowSummaryMessages, ...sourceHistoryMessages];
|
|
9806
|
+
const historyMessages = this.deriveToolContextMessages(
|
|
9807
|
+
sourceHistoryMessages,
|
|
9808
|
+
state.taskName,
|
|
9809
|
+
compactionOptions?.toolContextMode || "hot-tail",
|
|
9810
|
+
compactionOptions?.toolWindow ?? "session"
|
|
9811
|
+
);
|
|
9812
|
+
const historyArtifactReferences = this.extractArtifactReferencesFromMessages(historyMessages);
|
|
9813
|
+
const summaryText = this.generateCompactSummary(
|
|
9814
|
+
state,
|
|
9815
|
+
compactInstructions,
|
|
9816
|
+
historyArtifactReferences
|
|
9817
|
+
);
|
|
8518
9818
|
const breakdown = this.buildContextBudgetBreakdown({
|
|
8519
9819
|
historyMessages,
|
|
9820
|
+
sourceHistoryMessages,
|
|
8520
9821
|
currentTurnContent: continuationContent,
|
|
8521
9822
|
localTools: compactionOptions?.localTools,
|
|
8522
9823
|
builtinToolSchemas: compactionOptions?.builtinToolSchemas || [],
|
|
@@ -8543,7 +9844,8 @@ Do NOT redo any of the above work.`
|
|
|
8543
9844
|
reservedOutputTokens: breakdown.reservedOutputTokens,
|
|
8544
9845
|
breakdown,
|
|
8545
9846
|
onContextCompaction: compactionOptions?.onContextCompaction,
|
|
8546
|
-
compactInstructions
|
|
9847
|
+
compactInstructions,
|
|
9848
|
+
artifactReferences: historyArtifactReferences
|
|
8547
9849
|
}
|
|
8548
9850
|
),
|
|
8549
9851
|
requestContextManagement
|
|
@@ -9017,6 +10319,52 @@ var BillingEndpoint = class {
|
|
|
9017
10319
|
return this.client.get("/billing/spend-analytics", params);
|
|
9018
10320
|
}
|
|
9019
10321
|
};
|
|
10322
|
+
var AppsEndpoint = class {
|
|
10323
|
+
constructor(client) {
|
|
10324
|
+
this.client = client;
|
|
10325
|
+
}
|
|
10326
|
+
/** List apps for the authenticated owner, newest first. */
|
|
10327
|
+
async list() {
|
|
10328
|
+
return this.client.get("/apps");
|
|
10329
|
+
}
|
|
10330
|
+
/** Get an app by id, including its URL and active version pointer. */
|
|
10331
|
+
async get(id) {
|
|
10332
|
+
return this.client.get(`/apps/${id}`);
|
|
10333
|
+
}
|
|
10334
|
+
/** Create an app. A client token scoped to the app origin is auto-provisioned. */
|
|
10335
|
+
async create(data) {
|
|
10336
|
+
return this.client.post("/apps", data);
|
|
10337
|
+
}
|
|
10338
|
+
/** Update name, description, visibility, or status (suspended serves 410). */
|
|
10339
|
+
async update(id, data) {
|
|
10340
|
+
return this.client.patch(`/apps/${id}`, data);
|
|
10341
|
+
}
|
|
10342
|
+
/** Delete an app, its versions, and its hosting. Irreversible. */
|
|
10343
|
+
async delete(id) {
|
|
10344
|
+
return this.client.delete(`/apps/${id}`);
|
|
10345
|
+
}
|
|
10346
|
+
/** List an app's versions, newest first. */
|
|
10347
|
+
async listVersions(id) {
|
|
10348
|
+
return this.client.get(`/apps/${id}/versions`);
|
|
10349
|
+
}
|
|
10350
|
+
/** Upload a zipped bundle (raw application/zip body) as a new version. */
|
|
10351
|
+
async uploadVersion(id, zipBytes) {
|
|
10352
|
+
return this.client.postBinary(`/apps/${id}/versions`, zipBytes, "application/zip");
|
|
10353
|
+
}
|
|
10354
|
+
/**
|
|
10355
|
+
* Upload a bundle from in-memory file maps (the API zips server-side).
|
|
10356
|
+
* Text files in `files`, binary files base64-encoded in `filesBase64`.
|
|
10357
|
+
*/
|
|
10358
|
+
async uploadVersionFiles(id, data) {
|
|
10359
|
+
return this.client.post(`/apps/${id}/versions`, data);
|
|
10360
|
+
}
|
|
10361
|
+
/** Activate an uploaded version (deploy or rollback). */
|
|
10362
|
+
async activate(id, versionId) {
|
|
10363
|
+
return this.client.post(`/apps/${id}/activate`, {
|
|
10364
|
+
versionId
|
|
10365
|
+
});
|
|
10366
|
+
}
|
|
10367
|
+
};
|
|
9020
10368
|
|
|
9021
10369
|
// src/client.ts
|
|
9022
10370
|
function isObjectRecord(value) {
|
|
@@ -9059,6 +10407,7 @@ var RuntypeClient2 = class {
|
|
|
9059
10407
|
this.clientTokens = new ClientTokensEndpoint(this);
|
|
9060
10408
|
this.agents = new AgentsEndpoint(this);
|
|
9061
10409
|
this.secrets = new SecretsEndpoint(this);
|
|
10410
|
+
this.apps = new AppsEndpoint(this);
|
|
9062
10411
|
this.schedules = new SchedulesEndpoint(this);
|
|
9063
10412
|
this.surfaces = new SurfacesEndpoint(this);
|
|
9064
10413
|
this.conversations = new ConversationsEndpoint(this);
|
|
@@ -9105,7 +10454,7 @@ var RuntypeClient2 = class {
|
|
|
9105
10454
|
clearApiKey() {
|
|
9106
10455
|
delete this.headers.Authorization;
|
|
9107
10456
|
}
|
|
9108
|
-
async runWithLocalTools(
|
|
10457
|
+
async runWithLocalTools(request2, localTools, arg3, arg4) {
|
|
9109
10458
|
const isOptionsObject = (val) => typeof val === "object" && val !== null && "scope" in val;
|
|
9110
10459
|
const callbacks = isOptionsObject(arg3) ? void 0 : arg3;
|
|
9111
10460
|
const options = (isOptionsObject(arg3) ? arg3 : arg4) ?? {};
|
|
@@ -9119,12 +10468,12 @@ var RuntypeClient2 = class {
|
|
|
9119
10468
|
...entry.pageOrigin ? { pageOrigin: entry.pageOrigin } : {}
|
|
9120
10469
|
})) : [];
|
|
9121
10470
|
const modifiedRequest = {
|
|
9122
|
-
...
|
|
10471
|
+
...request2,
|
|
9123
10472
|
...derivedClientTools.length > 0 ? {
|
|
9124
|
-
clientTools: [...
|
|
10473
|
+
clientTools: [...request2.clientTools ?? [], ...derivedClientTools]
|
|
9125
10474
|
} : {},
|
|
9126
10475
|
options: {
|
|
9127
|
-
...
|
|
10476
|
+
...request2.options || {},
|
|
9128
10477
|
streamResponse: isStreaming
|
|
9129
10478
|
}
|
|
9130
10479
|
};
|
|
@@ -9140,13 +10489,12 @@ var RuntypeClient2 = class {
|
|
|
9140
10489
|
onFlowComplete: (event) => callbacks?.onFlowComplete?.(event),
|
|
9141
10490
|
onError: (error) => callbacks?.onError?.(error)
|
|
9142
10491
|
};
|
|
9143
|
-
const { streamEvents: streamEvents2, stepDeltaText: stepDeltaText2, stepDisplayName: stepDisplayName2, flowErrorMessage: flowErrorMessage2 } = await Promise.resolve().then(() => (init_stream_utils(), stream_utils_exports));
|
|
9144
10492
|
const summary = {
|
|
9145
10493
|
results: /* @__PURE__ */ new Map(),
|
|
9146
10494
|
success: true
|
|
9147
10495
|
};
|
|
9148
10496
|
try {
|
|
9149
|
-
for await (const event of
|
|
10497
|
+
for await (const event of streamEvents(response)) {
|
|
9150
10498
|
collectLocalToolAwait(pausedTools, event);
|
|
9151
10499
|
switch (event.type) {
|
|
9152
10500
|
case "flow_start":
|
|
@@ -9156,10 +10504,10 @@ var RuntypeClient2 = class {
|
|
|
9156
10504
|
wrappedCallbacks.onStepStart?.(event);
|
|
9157
10505
|
break;
|
|
9158
10506
|
case "step_delta":
|
|
9159
|
-
wrappedCallbacks.onStepDelta?.(
|
|
10507
|
+
wrappedCallbacks.onStepDelta?.(stepDeltaText(event), event);
|
|
9160
10508
|
break;
|
|
9161
10509
|
case "step_complete": {
|
|
9162
|
-
summary.results?.set(
|
|
10510
|
+
summary.results?.set(stepDisplayName(event), event.result);
|
|
9163
10511
|
wrappedCallbacks.onStepComplete?.(event.result, event);
|
|
9164
10512
|
break;
|
|
9165
10513
|
}
|
|
@@ -9167,7 +10515,7 @@ var RuntypeClient2 = class {
|
|
|
9167
10515
|
wrappedCallbacks.onFlowComplete?.(event);
|
|
9168
10516
|
break;
|
|
9169
10517
|
case "flow_error":
|
|
9170
|
-
wrappedCallbacks.onError?.(new Error(
|
|
10518
|
+
wrappedCallbacks.onError?.(new Error(flowErrorMessage(event)));
|
|
9171
10519
|
break;
|
|
9172
10520
|
}
|
|
9173
10521
|
}
|
|
@@ -9246,7 +10594,8 @@ var RuntypeClient2 = class {
|
|
|
9246
10594
|
return [toolName, await handler(parameters)];
|
|
9247
10595
|
} catch (error) {
|
|
9248
10596
|
throw new Error(
|
|
9249
|
-
`Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}
|
|
10597
|
+
`Error executing local tool "${toolName}": ${error instanceof Error ? error.message : String(error)}`,
|
|
10598
|
+
{ cause: error }
|
|
9250
10599
|
);
|
|
9251
10600
|
}
|
|
9252
10601
|
})
|
|
@@ -9310,6 +10659,21 @@ var RuntypeClient2 = class {
|
|
|
9310
10659
|
});
|
|
9311
10660
|
return transformResponse(response);
|
|
9312
10661
|
}
|
|
10662
|
+
/**
|
|
10663
|
+
* POST request with a raw binary body (e.g. application/zip bundle uploads).
|
|
10664
|
+
*/
|
|
10665
|
+
async postBinary(path, body, contentType) {
|
|
10666
|
+
const url = this.buildUrl(path);
|
|
10667
|
+
const headers = { ...this.headers, "Content-Type": contentType };
|
|
10668
|
+
const response = await this.makeRequest(url, {
|
|
10669
|
+
method: "POST",
|
|
10670
|
+
headers,
|
|
10671
|
+
// TS 5.7 types Uint8Array over ArrayBufferLike, which no longer
|
|
10672
|
+
// overlaps DOM BodyInit; the runtime value is a valid fetch body.
|
|
10673
|
+
body
|
|
10674
|
+
});
|
|
10675
|
+
return transformResponse(response);
|
|
10676
|
+
}
|
|
9313
10677
|
/**
|
|
9314
10678
|
* Generic request that returns raw Response for streaming
|
|
9315
10679
|
*/
|
|
@@ -9410,7 +10774,7 @@ var RuntypeClient2 = class {
|
|
|
9410
10774
|
} catch (error) {
|
|
9411
10775
|
if (timeoutId) clearTimeout(timeoutId);
|
|
9412
10776
|
if (timeoutId && error instanceof Error && error.name === "AbortError") {
|
|
9413
|
-
throw new Error(`Request timeout after ${this.timeout}ms
|
|
10777
|
+
throw new Error(`Request timeout after ${this.timeout}ms`, { cause: error });
|
|
9414
10778
|
}
|
|
9415
10779
|
throw error;
|
|
9416
10780
|
}
|
|
@@ -9419,8 +10783,18 @@ var RuntypeClient2 = class {
|
|
|
9419
10783
|
* Make HTTP request that returns raw Response (for streaming)
|
|
9420
10784
|
*/
|
|
9421
10785
|
async makeRawRequest(url, options) {
|
|
9422
|
-
const
|
|
10786
|
+
const callerSignal = options.signal ?? null;
|
|
10787
|
+
const controller = this.timeout === null && !callerSignal ? null : new AbortController();
|
|
9423
10788
|
const timeoutId = controller && this.timeout !== null ? setTimeout(() => controller.abort(), this.timeout) : null;
|
|
10789
|
+
if (callerSignal && controller) {
|
|
10790
|
+
if (callerSignal.aborted) {
|
|
10791
|
+
controller.abort(callerSignal.reason);
|
|
10792
|
+
} else {
|
|
10793
|
+
callerSignal.addEventListener("abort", () => controller.abort(callerSignal.reason), {
|
|
10794
|
+
once: true
|
|
10795
|
+
});
|
|
10796
|
+
}
|
|
10797
|
+
}
|
|
9424
10798
|
try {
|
|
9425
10799
|
const response = await fetch(url, {
|
|
9426
10800
|
...options,
|
|
@@ -9433,8 +10807,8 @@ var RuntypeClient2 = class {
|
|
|
9433
10807
|
return response;
|
|
9434
10808
|
} catch (error) {
|
|
9435
10809
|
if (timeoutId) clearTimeout(timeoutId);
|
|
9436
|
-
if (timeoutId && error instanceof Error && error.name === "AbortError") {
|
|
9437
|
-
throw new Error(`Request timeout after ${this.timeout}ms
|
|
10810
|
+
if (timeoutId && error instanceof Error && error.name === "AbortError" && !callerSignal?.aborted) {
|
|
10811
|
+
throw new Error(`Request timeout after ${this.timeout}ms`, { cause: error });
|
|
9438
10812
|
}
|
|
9439
10813
|
throw error;
|
|
9440
10814
|
}
|
|
@@ -9480,9 +10854,6 @@ function createClient(config) {
|
|
|
9480
10854
|
return new RuntypeClient2(config);
|
|
9481
10855
|
}
|
|
9482
10856
|
|
|
9483
|
-
// src/index.ts
|
|
9484
|
-
init_stream_utils();
|
|
9485
|
-
|
|
9486
10857
|
// src/batch-builder.ts
|
|
9487
10858
|
var BatchBuilder = class {
|
|
9488
10859
|
constructor() {
|
|
@@ -9540,20 +10911,20 @@ var BatchBuilder = class {
|
|
|
9540
10911
|
if (!this.recordType) {
|
|
9541
10912
|
throw new Error("BatchBuilder: recordType is required. Call .forRecordType(type) first.");
|
|
9542
10913
|
}
|
|
9543
|
-
const
|
|
10914
|
+
const request2 = {
|
|
9544
10915
|
flowId: this.flowId,
|
|
9545
10916
|
recordType: this.recordType
|
|
9546
10917
|
};
|
|
9547
10918
|
if (Object.keys(this.batchOptions).length > 0) {
|
|
9548
|
-
|
|
10919
|
+
request2.options = this.batchOptions;
|
|
9549
10920
|
}
|
|
9550
10921
|
if (this.filterConfig) {
|
|
9551
|
-
|
|
10922
|
+
request2.filter = this.filterConfig;
|
|
9552
10923
|
}
|
|
9553
10924
|
if (this.limitConfig !== void 0) {
|
|
9554
|
-
|
|
10925
|
+
request2.limit = this.limitConfig;
|
|
9555
10926
|
}
|
|
9556
|
-
return
|
|
10927
|
+
return request2;
|
|
9557
10928
|
}
|
|
9558
10929
|
/**
|
|
9559
10930
|
* Execute the batch operation
|
|
@@ -9710,32 +11081,32 @@ var EvalBuilder = class {
|
|
|
9710
11081
|
"EvalBuilder: records are required. Call .forRecordType(type) or .withRecords([...]) first."
|
|
9711
11082
|
);
|
|
9712
11083
|
}
|
|
9713
|
-
const
|
|
11084
|
+
const request2 = {};
|
|
9714
11085
|
if (this.flowId) {
|
|
9715
|
-
|
|
11086
|
+
request2.flowId = this.flowId;
|
|
9716
11087
|
} else if (this.virtualFlow) {
|
|
9717
|
-
|
|
11088
|
+
request2.flow = this.virtualFlow;
|
|
9718
11089
|
}
|
|
9719
11090
|
if (this.recordType) {
|
|
9720
|
-
|
|
11091
|
+
request2.recordType = this.recordType;
|
|
9721
11092
|
} else if (this.inlineRecords) {
|
|
9722
|
-
|
|
11093
|
+
request2.records = this.inlineRecords;
|
|
9723
11094
|
}
|
|
9724
11095
|
if (this.modelOverrides) {
|
|
9725
|
-
|
|
11096
|
+
request2.modelOverrides = this.modelOverrides;
|
|
9726
11097
|
} else if (this.modelConfigs) {
|
|
9727
|
-
|
|
11098
|
+
request2.modelConfigs = this.modelConfigs;
|
|
9728
11099
|
}
|
|
9729
11100
|
if (Object.keys(this.evalOptions).length > 0) {
|
|
9730
|
-
|
|
11101
|
+
request2.options = this.evalOptions;
|
|
9731
11102
|
}
|
|
9732
11103
|
if (this.filterConfig) {
|
|
9733
|
-
|
|
11104
|
+
request2.filter = this.filterConfig;
|
|
9734
11105
|
}
|
|
9735
11106
|
if (this.limitConfig !== void 0) {
|
|
9736
|
-
|
|
11107
|
+
request2.limit = this.limitConfig;
|
|
9737
11108
|
}
|
|
9738
|
-
return
|
|
11109
|
+
return request2;
|
|
9739
11110
|
}
|
|
9740
11111
|
/**
|
|
9741
11112
|
* Execute the evaluation
|
|
@@ -10202,10 +11573,14 @@ var STEP_TYPE_TO_METHOD = {
|
|
|
10202
11573
|
};
|
|
10203
11574
|
// Annotate the CommonJS export names for ESM import in node:
|
|
10204
11575
|
0 && (module.exports = {
|
|
11576
|
+
AgentDriftError,
|
|
11577
|
+
AgentEnsureConflictError,
|
|
10205
11578
|
AgentVersionsEndpoint,
|
|
10206
11579
|
AgentsEndpoint,
|
|
11580
|
+
AgentsNamespace,
|
|
10207
11581
|
AnalyticsEndpoint,
|
|
10208
11582
|
ApiKeysEndpoint,
|
|
11583
|
+
AppsEndpoint,
|
|
10209
11584
|
BatchBuilder,
|
|
10210
11585
|
BatchesNamespace,
|
|
10211
11586
|
BillingEndpoint,
|
|
@@ -10216,18 +11591,23 @@ var STEP_TYPE_TO_METHOD = {
|
|
|
10216
11591
|
ClientTokensEndpoint,
|
|
10217
11592
|
ContextTemplatesEndpoint,
|
|
10218
11593
|
ConversationsEndpoint,
|
|
11594
|
+
DEFAULT_RECOVERY_AFTER_EMPTY_SESSIONS,
|
|
11595
|
+
DEFAULT_STALL_STOP_AFTER,
|
|
10219
11596
|
DispatchEndpoint,
|
|
10220
11597
|
EvalBuilder,
|
|
10221
11598
|
EvalEndpoint,
|
|
10222
11599
|
EvalRunner,
|
|
10223
11600
|
EvalsNamespace,
|
|
10224
11601
|
FlowBuilder,
|
|
11602
|
+
FlowDriftError,
|
|
11603
|
+
FlowEnsureConflictError,
|
|
10225
11604
|
FlowResult,
|
|
10226
11605
|
FlowStepsEndpoint,
|
|
10227
11606
|
FlowVersionsEndpoint,
|
|
10228
11607
|
FlowsEndpoint,
|
|
10229
11608
|
FlowsNamespace,
|
|
10230
11609
|
IntegrationsEndpoint,
|
|
11610
|
+
LEDGER_ARTIFACT_LINE_PREFIX,
|
|
10231
11611
|
LogsEndpoint,
|
|
10232
11612
|
ModelConfigsEndpoint,
|
|
10233
11613
|
PromptRunner,
|
|
@@ -10250,22 +11630,47 @@ var STEP_TYPE_TO_METHOD = {
|
|
|
10250
11630
|
UsersEndpoint,
|
|
10251
11631
|
applyGeneratedRuntimeToolProposalToDispatchRequest,
|
|
10252
11632
|
attachRuntimeToolsToDispatchRequest,
|
|
11633
|
+
buildEmptySessionNudge,
|
|
10253
11634
|
buildGeneratedRuntimeToolGateOutput,
|
|
11635
|
+
buildLedgerOffloadReference,
|
|
11636
|
+
buildPolicyGuidance,
|
|
11637
|
+
buildSendViewOffloadMarker,
|
|
11638
|
+
compileWorkflowConfig,
|
|
11639
|
+
computeAgentContentHash,
|
|
11640
|
+
computeFlowContentHash,
|
|
10254
11641
|
createClient,
|
|
10255
11642
|
createExternalTool,
|
|
10256
11643
|
defaultWorkflow,
|
|
11644
|
+
defaultWorkflowConfig,
|
|
11645
|
+
defineAgent,
|
|
11646
|
+
defineFlow,
|
|
11647
|
+
definePlaybook,
|
|
10257
11648
|
deployWorkflow,
|
|
11649
|
+
ensureDefaultWorkflowHooks,
|
|
10258
11650
|
evaluateGeneratedRuntimeToolProposal,
|
|
11651
|
+
extractDeclaredToolResultChars,
|
|
10259
11652
|
gameWorkflow,
|
|
10260
11653
|
getDefaultPlanPath,
|
|
10261
11654
|
getLikelySupportingCandidatePaths,
|
|
11655
|
+
interpolateWorkflowTemplate,
|
|
10262
11656
|
isDiscoveryToolName,
|
|
10263
11657
|
isMarathonArtifactPath,
|
|
10264
11658
|
isPreservationSensitiveTask,
|
|
11659
|
+
isWorkflowHookRef,
|
|
11660
|
+
listWorkflowHooks,
|
|
11661
|
+
normalizeAgentDefinition,
|
|
10265
11662
|
normalizeCandidatePath,
|
|
10266
11663
|
parseFinalBuffer,
|
|
11664
|
+
parseLedgerArtifactRelativePath,
|
|
11665
|
+
parseOffloadedOutputId,
|
|
10267
11666
|
parseSSEChunk,
|
|
10268
11667
|
processStream,
|
|
11668
|
+
registerWorkflowHook,
|
|
11669
|
+
resolveStallStopAfter,
|
|
11670
|
+
resolveWorkflowHook,
|
|
10269
11671
|
sanitizeTaskSlug,
|
|
10270
|
-
|
|
11672
|
+
shouldInjectEmptySessionNudge,
|
|
11673
|
+
shouldRequestModelEscalation,
|
|
11674
|
+
streamEvents,
|
|
11675
|
+
unregisterWorkflowHook
|
|
10271
11676
|
});
|