@fatagnus/codebuff 1.0.4 → 1.0.6

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/convex.cjs CHANGED
@@ -5459,11 +5459,14 @@ __p += '`;
5459
5459
  // src/convex.ts
5460
5460
  var exports_convex = {};
5461
5461
  __export(exports_convex, {
5462
+ validateSpawnPermission: () => validateSpawnPermission,
5462
5463
  sanitizeErrorMessage: () => sanitizeErrorMessage,
5463
5464
  run: () => run,
5464
5465
  isRetryableStatusCode: () => isRetryableStatusCode,
5466
+ getMatchingSpawn: () => getMatchingSpawn,
5465
5467
  getErrorStatusCode: () => getErrorStatusCode,
5466
5468
  getCustomToolDefinition: () => getCustomToolDefinition,
5469
+ filterUnfinishedToolCalls: () => filterUnfinishedToolCalls,
5467
5470
  createServerError: () => createServerError,
5468
5471
  createPaymentRequiredError: () => createPaymentRequiredError,
5469
5472
  createNetworkError: () => createNetworkError,
@@ -5473,19 +5476,23 @@ __export(exports_convex, {
5473
5476
  convexInitialSessionState: () => convexInitialSessionState,
5474
5477
  convexApplyOverridesToSessionState: () => convexApplyOverridesToSessionState,
5475
5478
  buildUserMessageContent: () => buildUserMessageContent,
5479
+ buildToolsForApi: () => buildToolsForApi,
5480
+ buildSystemPrompt: () => buildSystemPrompt,
5476
5481
  WEBSITE_URL: () => WEBSITE_URL,
5477
5482
  RETRY_BACKOFF_MAX_DELAY_MS: () => RETRY_BACKOFF_MAX_DELAY_MS,
5478
5483
  RETRY_BACKOFF_BASE_DELAY_MS: () => RETRY_BACKOFF_BASE_DELAY_MS,
5479
5484
  RETRYABLE_STATUS_CODES: () => RETRYABLE_STATUS_CODES,
5480
5485
  RECONNECTION_RETRY_DELAY_MS: () => RECONNECTION_RETRY_DELAY_MS,
5481
5486
  RECONNECTION_MESSAGE_DURATION_MS: () => RECONNECTION_MESSAGE_DURATION_MS,
5487
+ MAX_SUBAGENT_DEPTH: () => MAX_SUBAGENT_DEPTH,
5482
5488
  MAX_RETRIES_PER_MESSAGE: () => MAX_RETRIES_PER_MESSAGE,
5483
5489
  IS_TEST: () => IS_TEST,
5484
5490
  IS_PROD: () => IS_PROD,
5485
5491
  IS_DEV: () => IS_DEV,
5486
5492
  ConvexUnsupportedToolError: () => ConvexUnsupportedToolError,
5487
5493
  ConvexCodebuffClient: () => ConvexCodebuffClient,
5488
- CODEBUFF_BINARY: () => CODEBUFF_BINARY
5494
+ CODEBUFF_BINARY: () => CODEBUFF_BINARY,
5495
+ BASE_AGENT_IDS: () => BASE_AGENT_IDS
5489
5496
  });
5490
5497
  module.exports = __toCommonJS(exports_convex);
5491
5498
 
@@ -6104,6 +6111,35 @@ function userMessage(content) {
6104
6111
  sentAt: Date.now()
6105
6112
  };
6106
6113
  }
6114
+ function withSystemTags(text) {
6115
+ return `<system>${text}</system>`;
6116
+ }
6117
+ function filterUnfinishedToolCalls(messages) {
6118
+ const completedToolCallIds = new Set;
6119
+ for (const msg of messages) {
6120
+ if (msg.role === "tool") {
6121
+ completedToolCallIds.add(msg.toolCallId);
6122
+ }
6123
+ }
6124
+ return messages.map((msg) => {
6125
+ if (msg.role !== "assistant") {
6126
+ return msg;
6127
+ }
6128
+ const filteredContent = msg.content.filter((part) => {
6129
+ if (part.type === "tool-call") {
6130
+ return completedToolCallIds.has(part.toolCallId);
6131
+ }
6132
+ return true;
6133
+ });
6134
+ if (filteredContent.length === 0) {
6135
+ return null;
6136
+ }
6137
+ return {
6138
+ ...msg,
6139
+ content: filteredContent
6140
+ };
6141
+ }).filter((msg) => msg !== null);
6142
+ }
6107
6143
  var createAbortError = (signal) => {
6108
6144
  if (signal?.reason instanceof Error) {
6109
6145
  return signal.reason;
@@ -6453,25 +6489,25 @@ async function handleToolCall(context) {
6453
6489
  } = context;
6454
6490
  const customToolHandler = customToolDefinitions[toolName];
6455
6491
  if (customToolHandler) {
6456
- return await customToolHandler.execute(input);
6492
+ return { output: await customToolHandler.execute(input), creditsUsed: 0 };
6457
6493
  }
6458
6494
  let override = overrides[toolName];
6459
6495
  if (!override && toolName === "str_replace") {
6460
6496
  override = overrides["write_file"];
6461
6497
  }
6462
6498
  if (override) {
6463
- return await override(input);
6499
+ return { output: await override(input), creditsUsed: 0 };
6464
6500
  }
6465
6501
  switch (toolName) {
6466
6502
  case "end_turn":
6467
- return [{ type: "json", value: { message: "Turn ended." } }];
6503
+ return { output: [{ type: "json", value: { message: "Turn ended." } }], creditsUsed: 0 };
6468
6504
  case "read_files": {
6469
6505
  const files = await readFiles({
6470
6506
  filePaths: input.paths || input.filePaths || [],
6471
6507
  override: overrides.read_files,
6472
6508
  projectFiles
6473
6509
  });
6474
- return [{ type: "json", value: files }];
6510
+ return { output: [{ type: "json", value: files }], creditsUsed: 0 };
6475
6511
  }
6476
6512
  case "spawn_agents": {
6477
6513
  return await handleSpawnAgents(context);
@@ -6488,10 +6524,13 @@ async function handleToolCall(context) {
6488
6524
  case "glob":
6489
6525
  throw new ConvexUnsupportedToolError("glob", "File system access is not available in Convex");
6490
6526
  case "run_file_change_hooks":
6491
- return [{
6492
- type: "json",
6493
- value: { message: "File change hooks are not supported in Convex mode" }
6494
- }];
6527
+ return {
6528
+ output: [{
6529
+ type: "json",
6530
+ value: { message: "File change hooks are not supported in Convex mode" }
6531
+ }],
6532
+ creditsUsed: 0
6533
+ };
6495
6534
  default:
6496
6535
  throw new Error(`Tool not implemented in Convex SDK: ${toolName}. ` + `Please provide an override or modify your agent to not use this tool.`);
6497
6536
  }
@@ -6519,12 +6558,15 @@ async function handleSpawnAgents(context) {
6519
6558
  throw new Error('spawn_agents requires an "agents" array parameter');
6520
6559
  }
6521
6560
  if (currentDepth >= MAX_SUBAGENT_DEPTH) {
6522
- return [{
6523
- type: "json",
6524
- value: {
6525
- errorMessage: `Maximum subagent depth (${MAX_SUBAGENT_DEPTH}) exceeded. Cannot spawn more subagents.`
6526
- }
6527
- }];
6561
+ return {
6562
+ output: [{
6563
+ type: "json",
6564
+ value: {
6565
+ errorMessage: `Maximum subagent depth (${MAX_SUBAGENT_DEPTH}) exceeded. Cannot spawn more subagents.`
6566
+ }
6567
+ }],
6568
+ creditsUsed: 0
6569
+ };
6528
6570
  }
6529
6571
  const parentSpawnableAgents = parentAgentDefinition?.spawnableAgents ?? [];
6530
6572
  const results = await Promise.allSettled(agents.map(async ({ agent_type: agentTypeStr, prompt, params: spawnParams }) => {
@@ -6543,6 +6585,20 @@ async function handleSpawnAgents(context) {
6543
6585
  prompt
6544
6586
  });
6545
6587
  }
6588
+ let inheritedMessageHistory;
6589
+ if (childAgentDef.includeMessageHistory) {
6590
+ inheritedMessageHistory = filterUnfinishedToolCalls(context.parentMessageHistory ?? []);
6591
+ inheritedMessageHistory.push({
6592
+ role: "user",
6593
+ content: [
6594
+ {
6595
+ type: "text",
6596
+ text: withSystemTags(`Subagent ${childAgentDef.id} has been spawned.`)
6597
+ }
6598
+ ],
6599
+ tags: ["SUBAGENT_SPAWN"]
6600
+ });
6601
+ }
6546
6602
  const result = await executeAgentLoop({
6547
6603
  apiKey,
6548
6604
  runId,
@@ -6556,6 +6612,7 @@ async function handleSpawnAgents(context) {
6556
6612
  currentDepth: currentDepth + 1,
6557
6613
  overrideTools: overrides,
6558
6614
  customToolDefinitions,
6615
+ inheritedMessageHistory,
6559
6616
  handleStreamChunk: handleStreamChunk ? async (chunk) => {
6560
6617
  if (typeof chunk === "string") {
6561
6618
  await handleStreamChunk({
@@ -6587,24 +6644,35 @@ async function handleSpawnAgents(context) {
6587
6644
  creditsUsed: result.creditsUsed
6588
6645
  };
6589
6646
  }));
6647
+ let totalSubagentCredits = 0;
6648
+ for (const result of results) {
6649
+ if (result.status === "fulfilled") {
6650
+ totalSubagentCredits += result.value.creditsUsed;
6651
+ }
6652
+ }
6590
6653
  const reports = results.map((result, index) => {
6591
6654
  if (result.status === "fulfilled") {
6592
- const { agentType, agentName, output } = result.value;
6655
+ const { agentType, agentName, output, creditsUsed } = result.value;
6593
6656
  return {
6594
6657
  agentName,
6595
6658
  agentType,
6596
- value: output
6659
+ value: output,
6660
+ creditsUsed
6597
6661
  };
6598
6662
  } else {
6599
6663
  const agentTypeStr = agents[index].agent_type;
6600
6664
  return {
6601
6665
  agentType: agentTypeStr,
6602
6666
  agentName: agentTypeStr,
6603
- value: { errorMessage: `Error spawning agent: ${result.reason}` }
6667
+ value: { errorMessage: `Error spawning agent: ${result.reason}` },
6668
+ creditsUsed: 0
6604
6669
  };
6605
6670
  }
6606
6671
  });
6607
- return [{ type: "json", value: reports }];
6672
+ return {
6673
+ output: [{ type: "json", value: reports }],
6674
+ creditsUsed: totalSubagentCredits
6675
+ };
6608
6676
  }
6609
6677
  async function executeAgentLoop(options) {
6610
6678
  const {
@@ -6623,17 +6691,19 @@ async function executeAgentLoop(options) {
6623
6691
  handleStreamChunk,
6624
6692
  handleEvent,
6625
6693
  logger,
6626
- signal
6694
+ signal,
6695
+ inheritedMessageHistory
6627
6696
  } = options;
6628
6697
  const systemPrompt = buildSystemPrompt(agentDefinition, projectFiles);
6629
6698
  const tools = buildToolsForApi(agentDefinition, Object.values(customToolDefinitions));
6630
6699
  const model = agentDefinition.model || "anthropic/claude-sonnet-4";
6631
- const messages = [];
6700
+ const messages = inheritedMessageHistory ? [...inheritedMessageHistory] : [];
6632
6701
  if (prompt || params) {
6633
6702
  messages.push(userMessage(buildUserMessageContent(prompt, params, undefined)));
6634
6703
  }
6635
6704
  let totalSteps = 0;
6636
- let creditsUsed = 0;
6705
+ let directCreditsUsed = 0;
6706
+ let subagentCreditsUsed = 0;
6637
6707
  let fullResponse = "";
6638
6708
  while (totalSteps < maxAgentSteps) {
6639
6709
  if (signal?.aborted) {
@@ -6691,7 +6761,7 @@ async function executeAgentLoop(options) {
6691
6761
  }
6692
6762
  try {
6693
6763
  const input = JSON.parse(tc.arguments || "{}");
6694
- const result = await handleToolCall({
6764
+ const toolResult = await handleToolCall({
6695
6765
  toolName: tc.name,
6696
6766
  input,
6697
6767
  overrides: overrideTools,
@@ -6707,13 +6777,15 @@ async function executeAgentLoop(options) {
6707
6777
  handleStreamChunk,
6708
6778
  handleEvent,
6709
6779
  logger,
6710
- signal
6780
+ signal,
6781
+ parentMessageHistory: messages
6711
6782
  });
6783
+ subagentCreditsUsed += toolResult.creditsUsed;
6712
6784
  messages.push({
6713
6785
  role: "tool",
6714
6786
  toolCallId: tc.id,
6715
6787
  toolName: tc.name,
6716
- content: result
6788
+ content: toolResult.output
6717
6789
  });
6718
6790
  } catch (error) {
6719
6791
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -6729,10 +6801,13 @@ async function executeAgentLoop(options) {
6729
6801
  break;
6730
6802
  }
6731
6803
  }
6804
+ const totalCreditsUsed = directCreditsUsed + subagentCreditsUsed;
6732
6805
  return {
6733
6806
  response: fullResponse,
6734
6807
  output: fullResponse || "Agent completed.",
6735
- creditsUsed,
6808
+ creditsUsed: totalCreditsUsed,
6809
+ directCreditsUsed,
6810
+ subagentCreditsUsed,
6736
6811
  messages
6737
6812
  };
6738
6813
  }
@@ -6948,16 +7023,18 @@ async function run(options) {
6948
7023
  messageHistoryLength: initialMessages.length
6949
7024
  });
6950
7025
  }
7026
+ const effectiveAgentDef = agentDefinition ?? {
7027
+ id: agentId,
7028
+ displayName: agentId,
7029
+ systemPrompt: "You are a helpful AI assistant.",
7030
+ toolNames: ["read_files", "end_turn"],
7031
+ model: "anthropic/claude-sonnet-4"
7032
+ };
6951
7033
  const result = await executeAgentLoop({
6952
7034
  apiKey,
6953
7035
  runId,
6954
7036
  agentId: mainAgentId,
6955
- agentDefinition: agentDefinition ?? {
6956
- id: agentId,
6957
- displayName: agentId,
6958
- systemPrompt: "You are a helpful AI assistant.",
6959
- toolNames: ["read_files", "end_turn"]
6960
- },
7037
+ agentDefinition: effectiveAgentDef,
6961
7038
  agentDefinitions,
6962
7039
  projectFiles,
6963
7040
  maxAgentSteps,
@@ -6971,13 +7048,10 @@ async function run(options) {
6971
7048
  logger,
6972
7049
  signal
6973
7050
  });
6974
- const allMessages = [...initialMessages.slice(0, -1), ...result.messages];
6975
- if (initialMessages.length > 0 && result.messages.length === 0) {
6976
- allMessages.push(...initialMessages);
6977
- }
6978
7051
  sessionState.mainAgentState.messageHistory = result.messages.length > 0 ? result.messages : initialMessages;
6979
7052
  sessionState.mainAgentState.creditsUsed = result.creditsUsed;
6980
- await finishAgentRun(apiKey, runId, "completed", Math.ceil(result.messages.length / 2), result.creditsUsed, result.creditsUsed, logger);
7053
+ sessionState.mainAgentState.directCreditsUsed = result.directCreditsUsed;
7054
+ await finishAgentRun(apiKey, runId, "completed", Math.ceil(result.messages.length / 2), result.directCreditsUsed, result.creditsUsed, logger);
6981
7055
  if (handleEvent) {
6982
7056
  await handleEvent({
6983
7057
  type: "finish",
@@ -7046,3 +7120,16 @@ Provide a handleEvent function to handle this error.`);
7046
7120
  }
7047
7121
  }
7048
7122
  }
7123
+
7124
+ // src/convex.ts
7125
+ if (typeof Promise.withResolvers !== "function") {
7126
+ Promise.withResolvers = function() {
7127
+ let resolve;
7128
+ let reject;
7129
+ const promise = new Promise((res, rej) => {
7130
+ resolve = res;
7131
+ reject = rej;
7132
+ });
7133
+ return { promise, resolve, reject };
7134
+ };
7135
+ }
package/dist/convex.mjs CHANGED
@@ -6047,6 +6047,35 @@ function userMessage(content) {
6047
6047
  sentAt: Date.now()
6048
6048
  };
6049
6049
  }
6050
+ function withSystemTags(text) {
6051
+ return `<system>${text}</system>`;
6052
+ }
6053
+ function filterUnfinishedToolCalls(messages) {
6054
+ const completedToolCallIds = new Set;
6055
+ for (const msg of messages) {
6056
+ if (msg.role === "tool") {
6057
+ completedToolCallIds.add(msg.toolCallId);
6058
+ }
6059
+ }
6060
+ return messages.map((msg) => {
6061
+ if (msg.role !== "assistant") {
6062
+ return msg;
6063
+ }
6064
+ const filteredContent = msg.content.filter((part) => {
6065
+ if (part.type === "tool-call") {
6066
+ return completedToolCallIds.has(part.toolCallId);
6067
+ }
6068
+ return true;
6069
+ });
6070
+ if (filteredContent.length === 0) {
6071
+ return null;
6072
+ }
6073
+ return {
6074
+ ...msg,
6075
+ content: filteredContent
6076
+ };
6077
+ }).filter((msg) => msg !== null);
6078
+ }
6050
6079
  var createAbortError = (signal) => {
6051
6080
  if (signal?.reason instanceof Error) {
6052
6081
  return signal.reason;
@@ -6396,25 +6425,25 @@ async function handleToolCall(context) {
6396
6425
  } = context;
6397
6426
  const customToolHandler = customToolDefinitions[toolName];
6398
6427
  if (customToolHandler) {
6399
- return await customToolHandler.execute(input);
6428
+ return { output: await customToolHandler.execute(input), creditsUsed: 0 };
6400
6429
  }
6401
6430
  let override = overrides[toolName];
6402
6431
  if (!override && toolName === "str_replace") {
6403
6432
  override = overrides["write_file"];
6404
6433
  }
6405
6434
  if (override) {
6406
- return await override(input);
6435
+ return { output: await override(input), creditsUsed: 0 };
6407
6436
  }
6408
6437
  switch (toolName) {
6409
6438
  case "end_turn":
6410
- return [{ type: "json", value: { message: "Turn ended." } }];
6439
+ return { output: [{ type: "json", value: { message: "Turn ended." } }], creditsUsed: 0 };
6411
6440
  case "read_files": {
6412
6441
  const files = await readFiles({
6413
6442
  filePaths: input.paths || input.filePaths || [],
6414
6443
  override: overrides.read_files,
6415
6444
  projectFiles
6416
6445
  });
6417
- return [{ type: "json", value: files }];
6446
+ return { output: [{ type: "json", value: files }], creditsUsed: 0 };
6418
6447
  }
6419
6448
  case "spawn_agents": {
6420
6449
  return await handleSpawnAgents(context);
@@ -6431,10 +6460,13 @@ async function handleToolCall(context) {
6431
6460
  case "glob":
6432
6461
  throw new ConvexUnsupportedToolError("glob", "File system access is not available in Convex");
6433
6462
  case "run_file_change_hooks":
6434
- return [{
6435
- type: "json",
6436
- value: { message: "File change hooks are not supported in Convex mode" }
6437
- }];
6463
+ return {
6464
+ output: [{
6465
+ type: "json",
6466
+ value: { message: "File change hooks are not supported in Convex mode" }
6467
+ }],
6468
+ creditsUsed: 0
6469
+ };
6438
6470
  default:
6439
6471
  throw new Error(`Tool not implemented in Convex SDK: ${toolName}. ` + `Please provide an override or modify your agent to not use this tool.`);
6440
6472
  }
@@ -6462,12 +6494,15 @@ async function handleSpawnAgents(context) {
6462
6494
  throw new Error('spawn_agents requires an "agents" array parameter');
6463
6495
  }
6464
6496
  if (currentDepth >= MAX_SUBAGENT_DEPTH) {
6465
- return [{
6466
- type: "json",
6467
- value: {
6468
- errorMessage: `Maximum subagent depth (${MAX_SUBAGENT_DEPTH}) exceeded. Cannot spawn more subagents.`
6469
- }
6470
- }];
6497
+ return {
6498
+ output: [{
6499
+ type: "json",
6500
+ value: {
6501
+ errorMessage: `Maximum subagent depth (${MAX_SUBAGENT_DEPTH}) exceeded. Cannot spawn more subagents.`
6502
+ }
6503
+ }],
6504
+ creditsUsed: 0
6505
+ };
6471
6506
  }
6472
6507
  const parentSpawnableAgents = parentAgentDefinition?.spawnableAgents ?? [];
6473
6508
  const results = await Promise.allSettled(agents.map(async ({ agent_type: agentTypeStr, prompt, params: spawnParams }) => {
@@ -6486,6 +6521,20 @@ async function handleSpawnAgents(context) {
6486
6521
  prompt
6487
6522
  });
6488
6523
  }
6524
+ let inheritedMessageHistory;
6525
+ if (childAgentDef.includeMessageHistory) {
6526
+ inheritedMessageHistory = filterUnfinishedToolCalls(context.parentMessageHistory ?? []);
6527
+ inheritedMessageHistory.push({
6528
+ role: "user",
6529
+ content: [
6530
+ {
6531
+ type: "text",
6532
+ text: withSystemTags(`Subagent ${childAgentDef.id} has been spawned.`)
6533
+ }
6534
+ ],
6535
+ tags: ["SUBAGENT_SPAWN"]
6536
+ });
6537
+ }
6489
6538
  const result = await executeAgentLoop({
6490
6539
  apiKey,
6491
6540
  runId,
@@ -6499,6 +6548,7 @@ async function handleSpawnAgents(context) {
6499
6548
  currentDepth: currentDepth + 1,
6500
6549
  overrideTools: overrides,
6501
6550
  customToolDefinitions,
6551
+ inheritedMessageHistory,
6502
6552
  handleStreamChunk: handleStreamChunk ? async (chunk) => {
6503
6553
  if (typeof chunk === "string") {
6504
6554
  await handleStreamChunk({
@@ -6530,24 +6580,35 @@ async function handleSpawnAgents(context) {
6530
6580
  creditsUsed: result.creditsUsed
6531
6581
  };
6532
6582
  }));
6583
+ let totalSubagentCredits = 0;
6584
+ for (const result of results) {
6585
+ if (result.status === "fulfilled") {
6586
+ totalSubagentCredits += result.value.creditsUsed;
6587
+ }
6588
+ }
6533
6589
  const reports = results.map((result, index) => {
6534
6590
  if (result.status === "fulfilled") {
6535
- const { agentType, agentName, output } = result.value;
6591
+ const { agentType, agentName, output, creditsUsed } = result.value;
6536
6592
  return {
6537
6593
  agentName,
6538
6594
  agentType,
6539
- value: output
6595
+ value: output,
6596
+ creditsUsed
6540
6597
  };
6541
6598
  } else {
6542
6599
  const agentTypeStr = agents[index].agent_type;
6543
6600
  return {
6544
6601
  agentType: agentTypeStr,
6545
6602
  agentName: agentTypeStr,
6546
- value: { errorMessage: `Error spawning agent: ${result.reason}` }
6603
+ value: { errorMessage: `Error spawning agent: ${result.reason}` },
6604
+ creditsUsed: 0
6547
6605
  };
6548
6606
  }
6549
6607
  });
6550
- return [{ type: "json", value: reports }];
6608
+ return {
6609
+ output: [{ type: "json", value: reports }],
6610
+ creditsUsed: totalSubagentCredits
6611
+ };
6551
6612
  }
6552
6613
  async function executeAgentLoop(options) {
6553
6614
  const {
@@ -6566,17 +6627,19 @@ async function executeAgentLoop(options) {
6566
6627
  handleStreamChunk,
6567
6628
  handleEvent,
6568
6629
  logger,
6569
- signal
6630
+ signal,
6631
+ inheritedMessageHistory
6570
6632
  } = options;
6571
6633
  const systemPrompt = buildSystemPrompt(agentDefinition, projectFiles);
6572
6634
  const tools = buildToolsForApi(agentDefinition, Object.values(customToolDefinitions));
6573
6635
  const model = agentDefinition.model || "anthropic/claude-sonnet-4";
6574
- const messages = [];
6636
+ const messages = inheritedMessageHistory ? [...inheritedMessageHistory] : [];
6575
6637
  if (prompt || params) {
6576
6638
  messages.push(userMessage(buildUserMessageContent(prompt, params, undefined)));
6577
6639
  }
6578
6640
  let totalSteps = 0;
6579
- let creditsUsed = 0;
6641
+ let directCreditsUsed = 0;
6642
+ let subagentCreditsUsed = 0;
6580
6643
  let fullResponse = "";
6581
6644
  while (totalSteps < maxAgentSteps) {
6582
6645
  if (signal?.aborted) {
@@ -6634,7 +6697,7 @@ async function executeAgentLoop(options) {
6634
6697
  }
6635
6698
  try {
6636
6699
  const input = JSON.parse(tc.arguments || "{}");
6637
- const result = await handleToolCall({
6700
+ const toolResult = await handleToolCall({
6638
6701
  toolName: tc.name,
6639
6702
  input,
6640
6703
  overrides: overrideTools,
@@ -6650,13 +6713,15 @@ async function executeAgentLoop(options) {
6650
6713
  handleStreamChunk,
6651
6714
  handleEvent,
6652
6715
  logger,
6653
- signal
6716
+ signal,
6717
+ parentMessageHistory: messages
6654
6718
  });
6719
+ subagentCreditsUsed += toolResult.creditsUsed;
6655
6720
  messages.push({
6656
6721
  role: "tool",
6657
6722
  toolCallId: tc.id,
6658
6723
  toolName: tc.name,
6659
- content: result
6724
+ content: toolResult.output
6660
6725
  });
6661
6726
  } catch (error) {
6662
6727
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -6672,10 +6737,13 @@ async function executeAgentLoop(options) {
6672
6737
  break;
6673
6738
  }
6674
6739
  }
6740
+ const totalCreditsUsed = directCreditsUsed + subagentCreditsUsed;
6675
6741
  return {
6676
6742
  response: fullResponse,
6677
6743
  output: fullResponse || "Agent completed.",
6678
- creditsUsed,
6744
+ creditsUsed: totalCreditsUsed,
6745
+ directCreditsUsed,
6746
+ subagentCreditsUsed,
6679
6747
  messages
6680
6748
  };
6681
6749
  }
@@ -6891,16 +6959,18 @@ async function run(options) {
6891
6959
  messageHistoryLength: initialMessages.length
6892
6960
  });
6893
6961
  }
6962
+ const effectiveAgentDef = agentDefinition ?? {
6963
+ id: agentId,
6964
+ displayName: agentId,
6965
+ systemPrompt: "You are a helpful AI assistant.",
6966
+ toolNames: ["read_files", "end_turn"],
6967
+ model: "anthropic/claude-sonnet-4"
6968
+ };
6894
6969
  const result = await executeAgentLoop({
6895
6970
  apiKey,
6896
6971
  runId,
6897
6972
  agentId: mainAgentId,
6898
- agentDefinition: agentDefinition ?? {
6899
- id: agentId,
6900
- displayName: agentId,
6901
- systemPrompt: "You are a helpful AI assistant.",
6902
- toolNames: ["read_files", "end_turn"]
6903
- },
6973
+ agentDefinition: effectiveAgentDef,
6904
6974
  agentDefinitions,
6905
6975
  projectFiles,
6906
6976
  maxAgentSteps,
@@ -6914,13 +6984,10 @@ async function run(options) {
6914
6984
  logger,
6915
6985
  signal
6916
6986
  });
6917
- const allMessages = [...initialMessages.slice(0, -1), ...result.messages];
6918
- if (initialMessages.length > 0 && result.messages.length === 0) {
6919
- allMessages.push(...initialMessages);
6920
- }
6921
6987
  sessionState.mainAgentState.messageHistory = result.messages.length > 0 ? result.messages : initialMessages;
6922
6988
  sessionState.mainAgentState.creditsUsed = result.creditsUsed;
6923
- await finishAgentRun(apiKey, runId, "completed", Math.ceil(result.messages.length / 2), result.creditsUsed, result.creditsUsed, logger);
6989
+ sessionState.mainAgentState.directCreditsUsed = result.directCreditsUsed;
6990
+ await finishAgentRun(apiKey, runId, "completed", Math.ceil(result.messages.length / 2), result.directCreditsUsed, result.creditsUsed, logger);
6924
6991
  if (handleEvent) {
6925
6992
  await handleEvent({
6926
6993
  type: "finish",
@@ -6989,12 +7056,28 @@ Provide a handleEvent function to handle this error.`);
6989
7056
  }
6990
7057
  }
6991
7058
  }
7059
+
7060
+ // src/convex.ts
7061
+ if (typeof Promise.withResolvers !== "function") {
7062
+ Promise.withResolvers = function() {
7063
+ let resolve;
7064
+ let reject;
7065
+ const promise = new Promise((res, rej) => {
7066
+ resolve = res;
7067
+ reject = rej;
7068
+ });
7069
+ return { promise, resolve, reject };
7070
+ };
7071
+ }
6992
7072
  export {
7073
+ validateSpawnPermission,
6993
7074
  sanitizeErrorMessage,
6994
7075
  run,
6995
7076
  isRetryableStatusCode,
7077
+ getMatchingSpawn,
6996
7078
  getErrorStatusCode,
6997
7079
  getCustomToolDefinition,
7080
+ filterUnfinishedToolCalls,
6998
7081
  createServerError,
6999
7082
  createPaymentRequiredError,
7000
7083
  createNetworkError,
@@ -7004,17 +7087,21 @@ export {
7004
7087
  convexInitialSessionState,
7005
7088
  convexApplyOverridesToSessionState,
7006
7089
  buildUserMessageContent,
7090
+ buildToolsForApi,
7091
+ buildSystemPrompt,
7007
7092
  WEBSITE_URL,
7008
7093
  RETRY_BACKOFF_MAX_DELAY_MS,
7009
7094
  RETRY_BACKOFF_BASE_DELAY_MS,
7010
7095
  RETRYABLE_STATUS_CODES,
7011
7096
  RECONNECTION_RETRY_DELAY_MS,
7012
7097
  RECONNECTION_MESSAGE_DURATION_MS,
7098
+ MAX_SUBAGENT_DEPTH,
7013
7099
  MAX_RETRIES_PER_MESSAGE,
7014
7100
  IS_TEST,
7015
7101
  IS_PROD,
7016
7102
  IS_DEV,
7017
7103
  ConvexUnsupportedToolError,
7018
7104
  ConvexCodebuffClient,
7019
- CODEBUFF_BINARY
7105
+ CODEBUFF_BINARY,
7106
+ BASE_AGENT_IDS
7020
7107
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fatagnus/codebuff",
3
3
  "private": false,
4
- "version": "1.0.4",
4
+ "version": "1.0.6",
5
5
  "description": "Official SDK for Codebuff — AI coding agent & framework",
6
6
  "license": "Apache-2.0",
7
7
  "type": "module",
@@ -72,10 +72,7 @@
72
72
  "ws": "^8.18.0",
73
73
  "zod": "^4.2.1"
74
74
  },
75
- "optionalDependencies": {
76
- "@vscode/tree-sitter-wasm": "0.1.4",
77
- "web-tree-sitter": "0.25.6"
78
- },
75
+
79
76
  "devDependencies": {
80
77
  "@types/bun": "^1.3.5",
81
78
  "@types/diff": "8.0.0",