@tangle-network/agent-runtime 0.67.0 → 0.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/agent.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-XRYEZPR6.js";
4
4
  import {
5
5
  createSandboxForSpec
6
- } from "./chunk-J6DAU44N.js";
6
+ } from "./chunk-NLRA6434.js";
7
7
  import "./chunk-WIR4HOOJ.js";
8
8
  import {
9
9
  mapSandboxEvent
@@ -14,7 +14,7 @@ import {
14
14
  DELEGATION_STATUS_DESCRIPTION,
15
15
  DELEGATION_STATUS_INPUT_SCHEMA,
16
16
  DELEGATION_STATUS_TOOL_NAME
17
- } from "./chunk-J6DAU44N.js";
17
+ } from "./chunk-NLRA6434.js";
18
18
 
19
19
  // src/mcp/openai-tools.ts
20
20
  function buildTool(name, description, parameters) {
@@ -61,4 +61,4 @@ export {
61
61
  mcpToolsForRuntimeMcp,
62
62
  mcpToolsForRuntimeMcpSubset
63
63
  };
64
- //# sourceMappingURL=chunk-DUCSSQ23.js.map
64
+ //# sourceMappingURL=chunk-G6U3GVK2.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-FNMGYYSS.js";
4
4
  import {
5
5
  detachedSessionDelegate
6
- } from "./chunk-DXA4XTZ3.js";
6
+ } from "./chunk-RTDI2DHD.js";
7
7
  import {
8
8
  runAnalystLoop
9
9
  } from "./chunk-P5OKDSLB.js";
@@ -12,7 +12,7 @@ import {
12
12
  definePersona,
13
13
  runPersonified,
14
14
  worktreeFanout
15
- } from "./chunk-J6DAU44N.js";
15
+ } from "./chunk-NLRA6434.js";
16
16
  import {
17
17
  ConfigError
18
18
  } from "./chunk-VLF5RHEQ.js";
@@ -211,4 +211,4 @@ export {
211
211
  runLoopRunnerCli,
212
212
  parseLoopRunnerArgv
213
213
  };
214
- //# sourceMappingURL=chunk-RMHASGSA.js.map
214
+ //# sourceMappingURL=chunk-K4FQSEXQ.js.map
@@ -3312,6 +3312,7 @@ function isAgent(value) {
3312
3312
 
3313
3313
  // src/runtime/supervise/runtime.ts
3314
3314
  import { spawn as spawn3 } from "child_process";
3315
+ import { randomUUID as randomUUID2 } from "crypto";
3315
3316
  import { estimateCost as estimateCost2, isModelPriced as isModelPriced2 } from "@tangle-network/agent-eval";
3316
3317
 
3317
3318
  // src/runtime/router-client.ts
@@ -4216,58 +4217,33 @@ var bridgeExecutor = (spec, ctx) => {
4216
4217
  "bridgeExecutor: BridgeSeam.bridgeUrl + bridgeBearer + model required"
4217
4218
  );
4218
4219
  }
4220
+ const maxTurns = seam.maxTurns ?? 200;
4221
+ const sessionId = seam.sessionId ?? `bridge-${spec.profile.name ?? "worker"}-${randomUUID2()}`;
4219
4222
  const controller = new AbortController();
4220
4223
  const abortIfSignalled = () => {
4221
4224
  if (ctx.signal.aborted) controller.abort();
4222
4225
  };
4223
4226
  abortIfSignalled();
4224
4227
  if (!ctx.signal.aborted) ctx.signal.addEventListener("abort", abortIfSignalled, { once: true });
4228
+ const inbox = createInbox();
4225
4229
  let artifact;
4226
4230
  return {
4227
4231
  runtime: "cli",
4228
- async execute(task, signal) {
4229
- const messages = taskToMessages(task, spec);
4230
- const started = Date.now();
4231
- const linked = linkSignals2(signal, controller.signal);
4232
- const timer = seam.timeoutMs ? setTimeout(() => controller.abort(), seam.timeoutMs) : void 0;
4233
- try {
4234
- const res = await fetch(`${seam.bridgeUrl.replace(/\/$/, "")}/v1/chat/completions`, {
4235
- method: "POST",
4236
- headers: {
4237
- "content-type": "application/json",
4238
- authorization: `Bearer ${seam.bridgeBearer}`
4239
- },
4240
- body: JSON.stringify({
4241
- model: seam.model,
4242
- stream: false,
4243
- ...seam.agentProfile ? { agent_profile: seam.agentProfile } : {},
4244
- messages
4245
- }),
4246
- ...linked ? { signal: linked } : {}
4247
- });
4248
- if (!res.ok) {
4249
- throw new ValidationError(
4250
- `bridgeExecutor: bridge ${res.status}: ${(await res.text()).slice(0, 300)}`
4251
- );
4232
+ deliver: (m) => inbox.deliver(m),
4233
+ execute(task, signal) {
4234
+ return streamBridgeSession({
4235
+ task,
4236
+ signal,
4237
+ spec,
4238
+ seam,
4239
+ sessionId,
4240
+ maxTurns,
4241
+ inbox,
4242
+ controller,
4243
+ onArtifact: (a) => {
4244
+ artifact = a;
4252
4245
  }
4253
- const data = await res.json();
4254
- const u = data.usage;
4255
- const usage = u && typeof u.prompt_tokens === "number" && typeof u.completion_tokens === "number" ? { input: u.prompt_tokens, output: u.completion_tokens } : void 0;
4256
- const msg = data.choices?.[0]?.message;
4257
- const content = msg?.content ?? "";
4258
- const toolCalls = (msg?.tool_calls ?? []).map((t) => t.function?.name ?? "unknown");
4259
- const spent = {
4260
- iterations: 1,
4261
- tokens: usage ? { input: usage.input, output: usage.output } : zeroTokenUsage(),
4262
- usd: typeof u?.cost === "number" ? u.cost : 0,
4263
- ms: Date.now() - started
4264
- };
4265
- const out = { content, toolCalls };
4266
- artifact = { outRef: contentRef("bridge", { model: seam.model, content }), out, spent };
4267
- return artifact;
4268
- } finally {
4269
- if (timer) clearTimeout(timer);
4270
- }
4246
+ });
4271
4247
  },
4272
4248
  teardown(_grace) {
4273
4249
  controller.abort();
@@ -4275,12 +4251,179 @@ var bridgeExecutor = (spec, ctx) => {
4275
4251
  },
4276
4252
  resultArtifact() {
4277
4253
  if (!artifact) {
4278
- throw new ValidationError("bridgeExecutor: resultArtifact() read before execute()");
4254
+ throw new ValidationError("bridgeExecutor: resultArtifact() read before stream drained");
4279
4255
  }
4280
4256
  return { ...artifact, spent: artifact.spent };
4281
4257
  }
4282
4258
  };
4283
4259
  };
4260
+ async function* streamBridgeSession(args) {
4261
+ const { seam, inbox } = args;
4262
+ const started = Date.now();
4263
+ const url = `${seam.bridgeUrl.replace(/\/$/, "")}/v1/chat/completions`;
4264
+ const external = mergeAbortSignals(args.signal, args.controller.signal);
4265
+ const tokens = zeroTokenUsage();
4266
+ let usd = 0;
4267
+ let turns = 0;
4268
+ let lastText = "";
4269
+ const toolCalls = [];
4270
+ let nextPrompt = taskToPrompt(args.task);
4271
+ const system = args.spec.profile.prompt?.systemPrompt;
4272
+ for (let t = 0; t < args.maxTurns; t += 1) {
4273
+ const pending = inbox.drain();
4274
+ if (pending.length) {
4275
+ const folded = inbox.fold(pending);
4276
+ nextPrompt = t === 0 && nextPrompt ? `${nextPrompt}
4277
+
4278
+ ${folded}` : folded;
4279
+ }
4280
+ if (nextPrompt === void 0) break;
4281
+ const messages = [];
4282
+ if (t === 0 && typeof system === "string" && system.length > 0) {
4283
+ messages.push({ role: "system", content: system });
4284
+ }
4285
+ messages.push({ role: "user", content: nextPrompt });
4286
+ nextPrompt = void 0;
4287
+ const interruptSig = inbox.freshInterrupt();
4288
+ const turnController = new AbortController();
4289
+ const abortTurn = () => turnController.abort();
4290
+ if (external.aborted) turnController.abort();
4291
+ else external.addEventListener("abort", abortTurn);
4292
+ interruptSig.addEventListener("abort", abortTurn, { once: true });
4293
+ const timer = seam.timeoutMs ? setTimeout(abortTurn, seam.timeoutMs) : void 0;
4294
+ const cleanup = () => {
4295
+ external.removeEventListener("abort", abortTurn);
4296
+ if (timer) clearTimeout(timer);
4297
+ };
4298
+ let res;
4299
+ try {
4300
+ res = await fetch(url, {
4301
+ method: "POST",
4302
+ headers: {
4303
+ "content-type": "application/json",
4304
+ authorization: `Bearer ${seam.bridgeBearer}`,
4305
+ "x-session-id": args.sessionId
4306
+ },
4307
+ body: JSON.stringify({
4308
+ model: seam.model,
4309
+ stream: true,
4310
+ session_id: args.sessionId,
4311
+ ...seam.agentProfile ? { agent_profile: seam.agentProfile } : {},
4312
+ messages
4313
+ }),
4314
+ signal: turnController.signal
4315
+ });
4316
+ } catch (e) {
4317
+ cleanup();
4318
+ const interruptAbort = e instanceof DOMException && e.name === "AbortError" && interruptSig.aborted && !args.signal.aborted && !args.controller.signal.aborted;
4319
+ if (interruptAbort) continue;
4320
+ throw e;
4321
+ }
4322
+ if (!res.ok) {
4323
+ cleanup();
4324
+ throw new ValidationError(
4325
+ `bridgeExecutor: bridge ${res.status}: ${(await res.text()).slice(0, 300)}`
4326
+ );
4327
+ }
4328
+ if (!res.body) {
4329
+ cleanup();
4330
+ throw new ValidationError("bridgeExecutor: bridge response had no body to stream");
4331
+ }
4332
+ let turnText = "";
4333
+ try {
4334
+ for await (const chunk of parseSseChatStream(res.body)) {
4335
+ if (chunk.content) {
4336
+ turnText += chunk.content;
4337
+ yield { kind: "iteration" };
4338
+ }
4339
+ if (chunk.toolCall) toolCalls.push(chunk.toolCall);
4340
+ if (chunk.usage) {
4341
+ tokens.input += chunk.usage.input;
4342
+ tokens.output += chunk.usage.output;
4343
+ yield { kind: "tokens", input: chunk.usage.input, output: chunk.usage.output };
4344
+ }
4345
+ if (typeof chunk.cost === "number" && chunk.cost > 0) {
4346
+ usd += chunk.cost;
4347
+ yield { kind: "cost", usd: chunk.cost };
4348
+ }
4349
+ }
4350
+ } finally {
4351
+ cleanup();
4352
+ }
4353
+ turns += 1;
4354
+ if (turnText) lastText = turnText;
4355
+ if (inbox.pending() === 0) break;
4356
+ }
4357
+ const spent = {
4358
+ iterations: turns,
4359
+ tokens,
4360
+ usd,
4361
+ ms: Date.now() - started
4362
+ };
4363
+ const out = { content: lastText, toolCalls };
4364
+ args.onArtifact({
4365
+ outRef: contentRef("bridge", { model: seam.model, session: args.sessionId, content: lastText }),
4366
+ out,
4367
+ spent
4368
+ });
4369
+ }
4370
+ async function* parseSseChatStream(body) {
4371
+ const reader = body.getReader();
4372
+ const decoder = new TextDecoder();
4373
+ let buf = "";
4374
+ try {
4375
+ for (; ; ) {
4376
+ const { done, value } = await reader.read();
4377
+ if (done) break;
4378
+ buf += decoder.decode(value, { stream: true });
4379
+ let sep = buf.indexOf("\n\n");
4380
+ while (sep !== -1) {
4381
+ const frame = buf.slice(0, sep);
4382
+ buf = buf.slice(sep + 2);
4383
+ const chunk = parseSseFrame(frame);
4384
+ if (chunk === "done") return;
4385
+ if (chunk) yield chunk;
4386
+ sep = buf.indexOf("\n\n");
4387
+ }
4388
+ }
4389
+ } finally {
4390
+ reader.releaseLock();
4391
+ }
4392
+ }
4393
+ function parseSseFrame(frame) {
4394
+ const dataLines = [];
4395
+ for (const rawLine of frame.split("\n")) {
4396
+ const line = rawLine.replace(/\r$/, "");
4397
+ if (!line || line.startsWith(":")) continue;
4398
+ if (line.startsWith("data:")) dataLines.push(line.slice("data:".length).trimStart());
4399
+ }
4400
+ if (dataLines.length === 0) return void 0;
4401
+ const data = dataLines.join("\n");
4402
+ if (data === "[DONE]") return "done";
4403
+ let parsed;
4404
+ try {
4405
+ parsed = JSON.parse(data);
4406
+ } catch {
4407
+ return void 0;
4408
+ }
4409
+ if (parsed.error) {
4410
+ throw new ValidationError(
4411
+ `bridgeExecutor: bridge stream error: ${parsed.error.message ?? "unknown"}`
4412
+ );
4413
+ }
4414
+ const out = {};
4415
+ const choice = parsed.choices?.[0];
4416
+ const content = choice?.delta?.content ?? choice?.message?.content;
4417
+ if (typeof content === "string" && content.length > 0) out.content = content;
4418
+ const toolName = choice?.delta?.tool_calls?.[0]?.function?.name;
4419
+ if (typeof toolName === "string" && toolName.length > 0) out.toolCall = toolName;
4420
+ const u = parsed.usage;
4421
+ if (u && (typeof u.prompt_tokens === "number" || typeof u.completion_tokens === "number")) {
4422
+ out.usage = { input: u.prompt_tokens ?? 0, output: u.completion_tokens ?? 0 };
4423
+ }
4424
+ if (typeof u?.cost === "number") out.cost = u.cost;
4425
+ return Object.keys(out).length > 0 ? out : void 0;
4426
+ }
4284
4427
  var cliWorktreeExecutor = (spec, ctx) => {
4285
4428
  const seam = readSeam(ctx, cliWorktreeSeamKey, "cli-worktree");
4286
4429
  if (!seam.repoRoot || !seam.harness || !seam.taskPrompt) {
@@ -7889,7 +8032,11 @@ var DelegationTaskQueue = class _DelegationTaskQueue {
7889
8032
  * handing the store's backing file to another process.
7890
8033
  */
7891
8034
  async flush() {
7892
- await this.persistTail;
8035
+ let tail2;
8036
+ while (this.persistTail !== tail2) {
8037
+ tail2 = this.persistTail;
8038
+ await tail2;
8039
+ }
7893
8040
  if (this.persistFailure) throw this.persistFailure;
7894
8041
  }
7895
8042
  /** Test-only — number of in-flight (non-terminal) records. */
@@ -10551,4 +10698,4 @@ export {
10551
10698
  jjWorkspace,
10552
10699
  runInWorkspace
10553
10700
  };
10554
- //# sourceMappingURL=chunk-J6DAU44N.js.map
10701
+ //# sourceMappingURL=chunk-NLRA6434.js.map