anycodex 0.0.24 → 0.0.25

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/bin.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  Skill,
8
8
  Tool,
9
9
  ToolRegistry
10
- } from "./chunk-ILSZBQFJ.js";
10
+ } from "./chunk-2X6YJUFL.js";
11
11
  import {
12
12
  AISDKError,
13
13
  APICallError,
@@ -26,7 +26,6 @@ import {
26
26
  ProviderID,
27
27
  Session,
28
28
  SessionService,
29
- Token,
30
29
  TooManyEmbeddingValuesForCallError,
31
30
  TypeValidationError,
32
31
  UnsupportedFunctionalityError,
@@ -59,7 +58,7 @@ import {
59
58
  withoutTrailingSlash,
60
59
  wrapLanguageModel,
61
60
  zodSchema
62
- } from "./chunk-TYWHGJLT.js";
61
+ } from "./chunk-4SPBQLA5.js";
63
62
  import "./chunk-DU4BGORD.js";
64
63
  import {
65
64
  MessageID,
@@ -754,7 +753,7 @@ import fs2 from "fs";
754
753
  import readline from "readline";
755
754
  import { fileURLToPath as fileURLToPath3 } from "url";
756
755
 
757
- // ../server/dist/chunk-XOJJG3D2.js
756
+ // ../server/dist/chunk-GNHGIOCL.js
758
757
  import http from "http";
759
758
  import https from "https";
760
759
  import { fileURLToPath as fileURLToPath2 } from "url";
@@ -11614,7 +11613,7 @@ var OpenAIResponsesLanguageModel = class {
11614
11613
  abortSignal: options.abortSignal,
11615
11614
  fetch: this.config.fetch
11616
11615
  });
11617
- const self = this;
11616
+ const self2 = this;
11618
11617
  const providerKey = this.config.provider.replace(".responses", "");
11619
11618
  let finishReason = "unknown";
11620
11619
  const usage = {
@@ -12028,7 +12027,7 @@ var OpenAIResponsesLanguageModel = class {
12028
12027
  controller.enqueue({
12029
12028
  type: "source",
12030
12029
  sourceType: "url",
12031
- id: (_p = (_o = (_n = self.config).generateId) == null ? void 0 : _o.call(_n)) != null ? _p : generateId(),
12030
+ id: (_p = (_o = (_n = self2.config).generateId) == null ? void 0 : _o.call(_n)) != null ? _p : generateId(),
12032
12031
  url: value.annotation.url,
12033
12032
  title: value.annotation.title
12034
12033
  });
@@ -12036,7 +12035,7 @@ var OpenAIResponsesLanguageModel = class {
12036
12035
  controller.enqueue({
12037
12036
  type: "source",
12038
12037
  sourceType: "document",
12039
- id: (_s = (_r = (_q = self.config).generateId) == null ? void 0 : _r.call(_q)) != null ? _s : generateId(),
12038
+ id: (_s = (_r = (_q = self2.config).generateId) == null ? void 0 : _r.call(_q)) != null ? _s : generateId(),
12040
12039
  mediaType: "text/plain",
12041
12040
  title: (_u = (_t = value.annotation.quote) != null ? _t : value.annotation.filename) != null ? _u : "Document",
12042
12041
  filename: (_v = value.annotation.filename) != null ? _v : value.annotation.file_id,
@@ -13920,6 +13919,103 @@ function createOpenAICompatible(options) {
13920
13919
  import { spawn } from "child_process";
13921
13920
  import { pathToFileURL, fileURLToPath } from "url";
13922
13921
  var import_fuzzysort = __toESM(require_fuzzysort(), 1);
13922
+
13923
+ // ../../node_modules/.pnpm/ulid@3.0.1/node_modules/ulid/dist/node/index.js
13924
+ import crypto from "crypto";
13925
+ var ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
13926
+ var ENCODING_LEN = 32;
13927
+ var RANDOM_LEN = 16;
13928
+ var TIME_LEN = 10;
13929
+ var TIME_MAX = 281474976710655;
13930
+ var ULIDErrorCode;
13931
+ (function(ULIDErrorCode2) {
13932
+ ULIDErrorCode2["Base32IncorrectEncoding"] = "B32_ENC_INVALID";
13933
+ ULIDErrorCode2["DecodeTimeInvalidCharacter"] = "DEC_TIME_CHAR";
13934
+ ULIDErrorCode2["DecodeTimeValueMalformed"] = "DEC_TIME_MALFORMED";
13935
+ ULIDErrorCode2["EncodeTimeNegative"] = "ENC_TIME_NEG";
13936
+ ULIDErrorCode2["EncodeTimeSizeExceeded"] = "ENC_TIME_SIZE_EXCEED";
13937
+ ULIDErrorCode2["EncodeTimeValueMalformed"] = "ENC_TIME_MALFORMED";
13938
+ ULIDErrorCode2["PRNGDetectFailure"] = "PRNG_DETECT";
13939
+ ULIDErrorCode2["ULIDInvalid"] = "ULID_INVALID";
13940
+ ULIDErrorCode2["Unexpected"] = "UNEXPECTED";
13941
+ ULIDErrorCode2["UUIDInvalid"] = "UUID_INVALID";
13942
+ })(ULIDErrorCode || (ULIDErrorCode = {}));
13943
+ var ULIDError = class extends Error {
13944
+ constructor(errorCode, message) {
13945
+ super(`${message} (${errorCode})`);
13946
+ this.name = "ULIDError";
13947
+ this.code = errorCode;
13948
+ }
13949
+ };
13950
+ function randomChar(prng) {
13951
+ const randomPosition = Math.floor(prng() * ENCODING_LEN) % ENCODING_LEN;
13952
+ return ENCODING.charAt(randomPosition);
13953
+ }
13954
+ function detectPRNG(root) {
13955
+ const rootLookup = detectRoot();
13956
+ const globalCrypto = rootLookup && (rootLookup.crypto || rootLookup.msCrypto) || (typeof crypto !== "undefined" ? crypto : null);
13957
+ if (typeof globalCrypto?.getRandomValues === "function") {
13958
+ return () => {
13959
+ const buffer = new Uint8Array(1);
13960
+ globalCrypto.getRandomValues(buffer);
13961
+ return buffer[0] / 255;
13962
+ };
13963
+ } else if (typeof globalCrypto?.randomBytes === "function") {
13964
+ return () => globalCrypto.randomBytes(1).readUInt8() / 255;
13965
+ } else if (crypto?.randomBytes) {
13966
+ return () => crypto.randomBytes(1).readUInt8() / 255;
13967
+ }
13968
+ throw new ULIDError(ULIDErrorCode.PRNGDetectFailure, "Failed to find a reliable PRNG");
13969
+ }
13970
+ function detectRoot() {
13971
+ if (inWebWorker())
13972
+ return self;
13973
+ if (typeof window !== "undefined") {
13974
+ return window;
13975
+ }
13976
+ if (typeof global !== "undefined") {
13977
+ return global;
13978
+ }
13979
+ if (typeof globalThis !== "undefined") {
13980
+ return globalThis;
13981
+ }
13982
+ return null;
13983
+ }
13984
+ function encodeRandom(len, prng) {
13985
+ let str = "";
13986
+ for (; len > 0; len--) {
13987
+ str = randomChar(prng) + str;
13988
+ }
13989
+ return str;
13990
+ }
13991
+ function encodeTime(now, len = TIME_LEN) {
13992
+ if (isNaN(now)) {
13993
+ throw new ULIDError(ULIDErrorCode.EncodeTimeValueMalformed, `Time must be a number: ${now}`);
13994
+ } else if (now > TIME_MAX) {
13995
+ throw new ULIDError(ULIDErrorCode.EncodeTimeSizeExceeded, `Cannot encode a time larger than ${TIME_MAX}: ${now}`);
13996
+ } else if (now < 0) {
13997
+ throw new ULIDError(ULIDErrorCode.EncodeTimeNegative, `Time must be positive: ${now}`);
13998
+ } else if (Number.isInteger(now) === false) {
13999
+ throw new ULIDError(ULIDErrorCode.EncodeTimeValueMalformed, `Time must be an integer: ${now}`);
14000
+ }
14001
+ let mod, str = "";
14002
+ for (let currentLen = len; currentLen > 0; currentLen--) {
14003
+ mod = now % ENCODING_LEN;
14004
+ str = ENCODING.charAt(mod) + str;
14005
+ now = (now - mod) / ENCODING_LEN;
14006
+ }
14007
+ return str;
14008
+ }
14009
+ function inWebWorker() {
14010
+ return typeof WorkerGlobalScope !== "undefined" && self instanceof WorkerGlobalScope;
14011
+ }
14012
+ function ulid(seedTime, prng) {
14013
+ const currentPRNG = prng || detectPRNG();
14014
+ const seed = !seedTime || isNaN(seedTime) ? Date.now() : seedTime;
14015
+ return encodeTime(seed, TIME_LEN) + encodeRandom(RANDOM_LEN, currentPRNG);
14016
+ }
14017
+
14018
+ // ../agent/dist/index.js
13923
14019
  var EnvService = class {
13924
14020
  env;
13925
14021
  constructor(initialEnv = {}) {
@@ -14007,41 +14103,41 @@ var Log = class {
14007
14103
  return cached;
14008
14104
  }
14009
14105
  }
14010
- const self = this;
14106
+ const self2 = this;
14011
14107
  function build(message, extra) {
14012
14108
  const prefix = Object.entries({
14013
14109
  ...tags,
14014
14110
  ...extra
14015
14111
  }).filter(([_, value]) => value !== void 0 && value !== null).map(([key, value]) => {
14016
14112
  const prefix2 = `${key}=`;
14017
- if (value instanceof Error) return prefix2 + self.formatError(value);
14113
+ if (value instanceof Error) return prefix2 + self2.formatError(value);
14018
14114
  if (typeof value === "object") return prefix2 + JSON.stringify(value);
14019
14115
  return prefix2 + value;
14020
14116
  }).join(" ");
14021
14117
  const next = /* @__PURE__ */ new Date();
14022
- const diff = next.getTime() - self.last;
14023
- self.last = next.getTime();
14118
+ const diff = next.getTime() - self2.last;
14119
+ self2.last = next.getTime();
14024
14120
  return [next.toISOString().split(".")[0], "+" + diff + "ms", prefix, message].filter(Boolean).join(" ") + "\n";
14025
14121
  }
14026
14122
  const result = {
14027
14123
  debug(message, extra) {
14028
- if (self.shouldLog("DEBUG")) {
14029
- self.write("DEBUG " + build(message, extra));
14124
+ if (self2.shouldLog("DEBUG")) {
14125
+ self2.write("DEBUG " + build(message, extra));
14030
14126
  }
14031
14127
  },
14032
14128
  info(message, extra) {
14033
- if (self.shouldLog("INFO")) {
14034
- self.write("INFO " + build(message, extra));
14129
+ if (self2.shouldLog("INFO")) {
14130
+ self2.write("INFO " + build(message, extra));
14035
14131
  }
14036
14132
  },
14037
14133
  error(message, extra) {
14038
- if (self.shouldLog("ERROR")) {
14039
- self.write("ERROR " + build(message, extra));
14134
+ if (self2.shouldLog("ERROR")) {
14135
+ self2.write("ERROR " + build(message, extra));
14040
14136
  }
14041
14137
  },
14042
14138
  warn(message, extra) {
14043
- if (self.shouldLog("WARN")) {
14044
- self.write("WARN " + build(message, extra));
14139
+ if (self2.shouldLog("WARN")) {
14140
+ self2.write("WARN " + build(message, extra));
14045
14141
  }
14046
14142
  },
14047
14143
  tag(key, value) {
@@ -14049,7 +14145,7 @@ var Log = class {
14049
14145
  return result;
14050
14146
  },
14051
14147
  clone() {
14052
- return self.create({ ...tags });
14148
+ return self2.create({ ...tags });
14053
14149
  },
14054
14150
  time(message, extra) {
14055
14151
  const now = Date.now();
@@ -15506,6 +15602,7 @@ var SessionPrompt;
15506
15602
  SessionPrompt2.PromptInput = zod_default.object({
15507
15603
  sessionID: SessionID.zod,
15508
15604
  messageID: MessageID.zod.optional(),
15605
+ chatId: zod_default.string().optional(),
15509
15606
  model: zod_default.object({
15510
15607
  providerID: ProviderID.zod,
15511
15608
  modelID: ModelID.zod
@@ -15716,7 +15813,8 @@ var SessionPrompt;
15716
15813
  model,
15717
15814
  system: input.system,
15718
15815
  format: input.format,
15719
- variant
15816
+ variant,
15817
+ ...input.chatId ? { chatId: input.chatId } : {}
15720
15818
  };
15721
15819
  const assign = (part) => ({
15722
15820
  ...part,
@@ -17041,7 +17139,7 @@ var LLMRunner;
17041
17139
  state: {
17042
17140
  status: "completed",
17043
17141
  input: value.input ?? match.state.input,
17044
- output: value.output.output,
17142
+ output: ContextCompaction.truncateToolOutput(value.output.output),
17045
17143
  metadata: value.output.metadata,
17046
17144
  title: value.output.title,
17047
17145
  time: {
@@ -17091,8 +17189,6 @@ var LLMRunner;
17091
17189
  metadata: value.providerMetadata
17092
17190
  });
17093
17191
  input.assistantMessage.finish = value.finishReason;
17094
- input.assistantMessage.cost += usage.cost;
17095
- input.assistantMessage.tokens = usage.tokens;
17096
17192
  await input.context.session.updatePart({
17097
17193
  id: PartID.ascending(),
17098
17194
  reason: value.finishReason,
@@ -17221,63 +17317,68 @@ Do not respond to any questions in the conversation, only output the summary.
17221
17317
  var ContextCompaction;
17222
17318
  ((ContextCompaction2) => {
17223
17319
  const COMPACTION_BUFFER = 2e4;
17320
+ const MAX_TOOL_OUTPUT_TOKENS = 4e4;
17321
+ const CHARS_PER_TOKEN = 4;
17322
+ function truncateToolOutput(output) {
17323
+ const maxChars = MAX_TOOL_OUTPUT_TOKENS * CHARS_PER_TOKEN;
17324
+ if (output.length <= maxChars) return output;
17325
+ return output.slice(0, maxChars) + "\n\n[TRUNCATED - Content exceeds " + MAX_TOOL_OUTPUT_TOKENS.toLocaleString() + " token limit]";
17326
+ }
17327
+ ContextCompaction2.truncateToolOutput = truncateToolOutput;
17328
+ function getLimits(model, config) {
17329
+ const contextLimit = model.limit.context ?? 0;
17330
+ const modelProvider = VendorRegistry.getModelProvider({ model });
17331
+ const reserved = config.compaction?.reserved ?? Math.min(COMPACTION_BUFFER, modelProvider.getMaxOutputTokens());
17332
+ const compactionThreshold = model.limit.input ? model.limit.input - reserved : contextLimit - modelProvider.getMaxOutputTokens();
17333
+ return { contextLimit, compactionThreshold };
17334
+ }
17335
+ function countInputTokens(tokens) {
17336
+ return tokens.total || tokens.input + tokens.output + tokens.cache.read + tokens.cache.write;
17337
+ }
17224
17338
  async function isOverflow(input) {
17225
- const config = input.context.config;
17226
- if (config.compaction?.auto === false) return false;
17227
- const contextLimit = input.model.limit.context;
17339
+ if (input.context.config.compaction?.auto === false) return false;
17340
+ const { contextLimit, compactionThreshold } = getLimits(input.model, input.context.config);
17228
17341
  if (contextLimit === 0) return false;
17229
- const count = input.tokens.total || input.tokens.input + input.tokens.output + input.tokens.cache.read + input.tokens.cache.write;
17230
- const modelProvider = VendorRegistry.getModelProvider({ model: input.model });
17231
- const reserved = config.compaction?.reserved ?? Math.min(COMPACTION_BUFFER, modelProvider.getMaxOutputTokens());
17232
- const usable = input.model.limit.input ? input.model.limit.input - reserved : contextLimit - modelProvider.getMaxOutputTokens();
17233
- return count >= usable;
17342
+ return countInputTokens(input.tokens) >= compactionThreshold;
17234
17343
  }
17235
17344
  ContextCompaction2.isOverflow = isOverflow;
17236
- ContextCompaction2.PRUNE_MINIMUM = 2e4;
17237
- ContextCompaction2.PRUNE_PROTECT = 4e4;
17238
- const PRUNE_PROTECTED_TOOLS = ["skill"];
17239
- async function prune(context, input) {
17240
- const config = context.config;
17241
- if (config.compaction?.prune === false) return;
17242
- context.log.create({ service: "context.compaction" }).info("pruning");
17243
- const msgs = await context.memory.messages({ sessionID: input.sessionID });
17244
- let total = 0;
17245
- let pruned = 0;
17246
- const toPrune = [];
17247
- let turns = 0;
17248
- loop: for (let msgIndex = msgs.length - 1; msgIndex >= 0; msgIndex--) {
17249
- const msg = msgs[msgIndex];
17250
- if (msg.info.role === "user") turns++;
17251
- if (turns < 2) continue;
17252
- if (msg.info.role === "assistant" && msg.info.summary) break loop;
17253
- for (let partIndex = msg.parts.length - 1; partIndex >= 0; partIndex--) {
17254
- const part = msg.parts[partIndex];
17255
- if (part.type === "tool") {
17256
- if (part.state.status === "completed") {
17257
- if (PRUNE_PROTECTED_TOOLS.includes(part.tool)) continue;
17258
- if (part.state.time.compacted) break loop;
17259
- const estimate = Token.estimate(part.state.output);
17260
- total += estimate;
17261
- if (total > ContextCompaction2.PRUNE_PROTECT) {
17262
- pruned += estimate;
17263
- toPrune.push(part);
17264
- }
17265
- }
17266
- }
17267
- }
17345
+ function getLastStepTokens(context, sessionID) {
17346
+ const parts = context.db.findMany("part", {
17347
+ filter: { op: "eq", field: "session_id", value: sessionID },
17348
+ orderBy: [{ field: "id", direction: "desc" }]
17349
+ });
17350
+ for (const row of parts) {
17351
+ if (row.data?.type === "step-finish" && row.data.tokens) return row.data.tokens;
17268
17352
  }
17269
- context.log.create({ service: "context.compaction" }).info("found", { pruned, total });
17270
- if (pruned > ContextCompaction2.PRUNE_MINIMUM) {
17271
- for (const part of toPrune) {
17272
- if (part.state.status === "completed") {
17273
- part.state.time.compacted = Date.now();
17274
- await context.memory.updatePart(part);
17275
- }
17353
+ return void 0;
17354
+ }
17355
+ async function isOverflowForSession(context, sessionID, model) {
17356
+ const tokens = getLastStepTokens(context, sessionID);
17357
+ if (!tokens) return false;
17358
+ return isOverflow({ tokens, model, context });
17359
+ }
17360
+ ContextCompaction2.isOverflowForSession = isOverflowForSession;
17361
+ async function getStatus(context, sessionID) {
17362
+ const msgs = await context.memory.messages({ sessionID });
17363
+ let compactions = 0;
17364
+ for (const msg of msgs) {
17365
+ if (msg.info.role === "assistant" && msg.info.summary) compactions++;
17366
+ }
17367
+ const tokens = getLastStepTokens(context, sessionID);
17368
+ const contextUsed = tokens ? (tokens.input ?? 0) + (tokens.cache?.read ?? 0) + (tokens.cache?.write ?? 0) : 0;
17369
+ let contextLimit = 0;
17370
+ let compactionThreshold = 0;
17371
+ const lastUser = msgs.findLast((m2) => m2.info.role === "user");
17372
+ if (lastUser?.info?.model) {
17373
+ try {
17374
+ const model = await context.provider.getModel(lastUser.info.model.providerID, lastUser.info.model.modelID);
17375
+ ({ contextLimit, compactionThreshold } = getLimits(model, context.config));
17376
+ } catch {
17276
17377
  }
17277
- context.log.create({ service: "context.compaction" }).info("pruned", { count: toPrune.length });
17278
17378
  }
17379
+ return { contextUsed, contextLimit, compactionThreshold, compactions };
17279
17380
  }
17280
- ContextCompaction2.prune = prune;
17381
+ ContextCompaction2.getStatus = getStatus;
17281
17382
  async function process2(context, input) {
17282
17383
  const userMessage = input.messages.findLast((m2) => m2.info.id === input.parentID).info;
17283
17384
  let messages = input.messages;
@@ -17313,13 +17414,6 @@ var ContextCompaction;
17313
17414
  cwd: input.context.directory,
17314
17415
  root: input.context.worktree
17315
17416
  },
17316
- cost: 0,
17317
- tokens: {
17318
- output: 0,
17319
- input: 0,
17320
- reasoning: 0,
17321
- cache: { read: 0, write: 0 }
17322
- },
17323
17417
  modelID: model.id,
17324
17418
  providerID: model.providerID,
17325
17419
  time: {
@@ -17596,7 +17690,7 @@ var CodeAgent = class extends EventEmitter {
17596
17690
  configOverrides: this.options.config,
17597
17691
  instructions: this.options.instructions,
17598
17692
  db: this._dbClient,
17599
- extraTools: [...this.options.extraTools ?? [], ...this.options.tools ? Object.values(this.options.tools) : []],
17693
+ tools: [...this.options.tools ?? []],
17600
17694
  containsPath: (filepath) => {
17601
17695
  const normalized = resolve(filepath);
17602
17696
  return normalized.startsWith(resolve(worktree)) || normalized.startsWith(resolve(this.options.dataPath));
@@ -17631,25 +17725,6 @@ var CodeAgent = class extends EventEmitter {
17631
17725
  ctx.skill = new Skill.SkillService(ctx);
17632
17726
  ctx.provider.bind(ctx);
17633
17727
  this._context = ctx;
17634
- if (this.options.tools) {
17635
- for (const [name2, def] of Object.entries(this.options.tools)) {
17636
- this._context.toolRegistry.register({
17637
- id: name2,
17638
- init: async () => ({
17639
- parameters: zod_default.object(def.args),
17640
- description: def.description,
17641
- execute: async (args2, toolCtx) => {
17642
- const result = await def.execute(args2, toolCtx);
17643
- return {
17644
- title: "",
17645
- output: typeof result === "string" ? result : JSON.stringify(result),
17646
- metadata: {}
17647
- };
17648
- }
17649
- })
17650
- });
17651
- }
17652
- }
17653
17728
  if (!this._dbClient.findOne("project", { op: "eq", field: "id", value: "global" })) {
17654
17729
  this._dbClient.insert("project", {
17655
17730
  id: "global",
@@ -17687,12 +17762,13 @@ var CodeAgent = class extends EventEmitter {
17687
17762
  /**
17688
17763
  * Send a message to the agent and receive streaming responses.
17689
17764
  */
17690
- async *chat(message) {
17765
+ async *chat(message, options) {
17691
17766
  this.assertInitialized();
17692
17767
  if (this._chatPromise) {
17693
17768
  throw new Error("chat() is already running. Call abort() and await it first.");
17694
17769
  }
17695
17770
  const sessionId = this._currentSessionId;
17771
+ const chatId = options?.chatId ?? ulid();
17696
17772
  const events = [];
17697
17773
  let resolve22 = null;
17698
17774
  let done = false;
@@ -17823,6 +17899,7 @@ var CodeAgent = class extends EventEmitter {
17823
17899
  const modelID = this.options.provider.model;
17824
17900
  await this.runLoop({
17825
17901
  sessionID: sessionId,
17902
+ chatId,
17826
17903
  model: {
17827
17904
  providerID,
17828
17905
  modelID
@@ -17856,7 +17933,6 @@ var CodeAgent = class extends EventEmitter {
17856
17933
  while (!done || events.length > 0) {
17857
17934
  if (events.length > 0) {
17858
17935
  const event = events.shift();
17859
- this.recordEvent(event);
17860
17936
  yield event;
17861
17937
  if (event.type === "done") return;
17862
17938
  } else {
@@ -17892,29 +17968,16 @@ var CodeAgent = class extends EventEmitter {
17892
17968
  });
17893
17969
  }
17894
17970
  /**
17895
- * Register a custom tool at runtime
17971
+ * Register a custom tool at runtime.
17972
+ * Tool must follow the Tool.Info format: { id, init }.
17896
17973
  */
17897
- async registerTool(name2, tool3) {
17974
+ async registerTool(tool3) {
17898
17975
  if (!this.options.tools) {
17899
- this.options.tools = {};
17976
+ this.options.tools = [];
17900
17977
  }
17901
- this.options.tools[name2] = tool3;
17978
+ this.options.tools.push(tool3);
17902
17979
  if (this.initialized) {
17903
- this.agentContext.toolRegistry.register({
17904
- id: name2,
17905
- init: async () => ({
17906
- parameters: zod_default.object(tool3.args),
17907
- description: tool3.description,
17908
- execute: async (args2, ctx) => {
17909
- const result = await tool3.execute(args2, ctx);
17910
- return {
17911
- title: "",
17912
- output: typeof result === "string" ? result : JSON.stringify(result),
17913
- metadata: {}
17914
- };
17915
- }
17916
- })
17917
- });
17980
+ this.agentContext.toolRegistry.register(tool3);
17918
17981
  }
17919
17982
  }
17920
17983
  /**
@@ -17923,42 +17986,49 @@ var CodeAgent = class extends EventEmitter {
17923
17986
  get config() {
17924
17987
  return this.options;
17925
17988
  }
17926
- // ── In-memory Stats ────────────────────────────────────────────
17927
- _stats = {
17928
- startedAt: Date.now(),
17929
- totalMessages: 0,
17930
- totalTokens: { input: 0, output: 0, reasoning: 0 },
17931
- totalCost: 0,
17932
- errors: []
17933
- };
17934
- /** Record stats from a chat event (called internally) */
17935
- recordEvent(event) {
17936
- if (event.type === "message.done" && event.usage) {
17937
- this._stats.totalMessages++;
17938
- this._stats.totalTokens.input += event.usage.inputTokens;
17939
- this._stats.totalTokens.output += event.usage.outputTokens;
17940
- this._stats.totalTokens.reasoning += event.usage.reasoningTokens;
17941
- this._stats.totalCost += event.usage.cost;
17942
- }
17943
- if (event.type === "error" && event.error) {
17944
- this._stats.errors.push({ time: Date.now(), message: event.error });
17945
- if (this._stats.errors.length > 20) this._stats.errors.shift();
17946
- }
17947
- }
17948
- // ── Debug APIs ─────────────────────────────────────────────────
17989
+ // ── Stats ──────────────────────────────────────────────────────
17949
17990
  /**
17950
- * Get runtime stats (uptime, tokens, cost, errors).
17991
+ * Get usage stats aggregated from step-finish parts in DB.
17951
17992
  */
17952
- getStats() {
17953
- const uptimeMs = Date.now() - this._stats.startedAt;
17993
+ async getUsage() {
17994
+ const totals = { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } };
17995
+ let totalCost = 0;
17996
+ let totalSteps = 0;
17997
+ if (this._currentSessionId) {
17998
+ const parts = this._dbClient.findMany("part", {
17999
+ op: "eq",
18000
+ field: "session_id",
18001
+ value: this._currentSessionId
18002
+ });
18003
+ for (const part of parts) {
18004
+ if (part.data?.type !== "step-finish") continue;
18005
+ totalSteps++;
18006
+ totalCost += part.data.cost ?? 0;
18007
+ const t = part.data.tokens;
18008
+ if (t) {
18009
+ totals.input += t.input ?? 0;
18010
+ totals.output += t.output ?? 0;
18011
+ totals.reasoning += t.reasoning ?? 0;
18012
+ totals.cache.read += t.cache?.read ?? 0;
18013
+ totals.cache.write += t.cache?.write ?? 0;
18014
+ }
18015
+ }
18016
+ }
17954
18017
  return {
17955
- uptimeMs,
17956
- totalMessages: this._stats.totalMessages,
17957
- totalTokens: { ...this._stats.totalTokens },
17958
- totalCost: this._stats.totalCost,
17959
- errors: [...this._stats.errors]
18018
+ totalSteps,
18019
+ totalTokens: totals,
18020
+ totalCost
17960
18021
  };
17961
18022
  }
18023
+ /**
18024
+ * Get current context window status.
18025
+ */
18026
+ async getContext() {
18027
+ if (!this._currentSessionId) {
18028
+ return { contextUsed: 0, contextLimit: 0, compactionThreshold: 0, compactions: 0 };
18029
+ }
18030
+ return ContextCompaction.getStatus(this.agentContext, this._currentSessionId);
18031
+ }
17962
18032
  /**
17963
18033
  * Get messages for the current session (for history restoration and admin display).
17964
18034
  */
@@ -17992,6 +18062,29 @@ var CodeAgent = class extends EventEmitter {
17992
18062
  }
17993
18063
  return messages;
17994
18064
  }
18065
+ /**
18066
+ * Clear session messages.
18067
+ * - No args: clear ALL messages for this session
18068
+ * - With chatId: clear only messages created during that specific chat() call
18069
+ */
18070
+ async clearMessages(chatId) {
18071
+ this.assertInitialized();
18072
+ if (chatId) {
18073
+ await this._context.memory.clearMessagesByChatId(chatId);
18074
+ } else {
18075
+ const sessionId = this._currentSessionId;
18076
+ const rows = this._context.db.findMany("message", { op: "eq", field: "session_id", value: sessionId });
18077
+ for (const row of rows) {
18078
+ this._context.db.remove("message", {
18079
+ op: "and",
18080
+ conditions: [
18081
+ { op: "eq", field: "id", value: row.id },
18082
+ { op: "eq", field: "session_id", value: sessionId }
18083
+ ]
18084
+ });
18085
+ }
18086
+ }
18087
+ }
17995
18088
  /**
17996
18089
  * Get current session status (busy/idle/retry).
17997
18090
  */
@@ -18054,7 +18147,7 @@ var CodeAgent = class extends EventEmitter {
18054
18147
  if (recentUser && recentAssistant && !recentAssistant.summary) {
18055
18148
  const userInfo = recentUser.info;
18056
18149
  const model2 = await context.provider.getModel(userInfo.model.providerID, userInfo.model.modelID).catch(() => null);
18057
- const tokenOverflow = model2 && recentAssistant.tokens && await ContextCompaction.isOverflow({ tokens: recentAssistant.tokens, model: model2, context });
18150
+ const tokenOverflow = model2 && await ContextCompaction.isOverflowForSession(context, sessionID, model2);
18058
18151
  if (tokenOverflow || msgs.length > 200) {
18059
18152
  const compactResult = await ContextCompaction.process(context, {
18060
18153
  messages: msgs,
@@ -18114,7 +18207,6 @@ var CodeAgent = class extends EventEmitter {
18114
18207
  if (structuredOutput !== void 0) break;
18115
18208
  if (result === "stop") break;
18116
18209
  }
18117
- ContextCompaction.prune(context, { sessionID });
18118
18210
  for await (const item of MessageV2.stream(context, sessionID)) {
18119
18211
  if (item.info.role === "user") continue;
18120
18212
  const queued = context.sessionPrompt.callbacks ?? [];
@@ -18143,12 +18235,11 @@ var CodeAgent = class extends EventEmitter {
18143
18235
  agent: "build",
18144
18236
  variant: lastUser.variant,
18145
18237
  path: { cwd: context.directory, root: context.worktree },
18146
- cost: 0,
18147
- tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
18148
18238
  modelID: model.id,
18149
18239
  providerID: model.providerID,
18150
18240
  time: { created: Date.now() },
18151
- sessionID
18241
+ sessionID,
18242
+ ...lastUser.chatId ? { chatId: lastUser.chatId } : {}
18152
18243
  }),
18153
18244
  sessionID,
18154
18245
  model,
@@ -18267,7 +18358,7 @@ var CodeAgent = class extends EventEmitter {
18267
18358
  }
18268
18359
  };
18269
18360
 
18270
- // ../server/dist/chunk-XOJJG3D2.js
18361
+ // ../server/dist/chunk-GNHGIOCL.js
18271
18362
  import { WebSocketServer, WebSocket as WS } from "ws";
18272
18363
  import * as pty from "@lydell/node-pty";
18273
18364
 
@@ -19961,7 +20052,7 @@ function watch(paths, options = {}) {
19961
20052
  return watcher;
19962
20053
  }
19963
20054
 
19964
- // ../server/dist/chunk-XOJJG3D2.js
20055
+ // ../server/dist/chunk-GNHGIOCL.js
19965
20056
  var __require2 = /* @__PURE__ */ ((x) => typeof __require !== "undefined" ? __require : typeof Proxy !== "undefined" ? new Proxy(x, {
19966
20057
  get: (a3, b) => (typeof __require !== "undefined" ? __require : a3)[b]
19967
20058
  }) : x)(function(x) {
@@ -20164,28 +20255,29 @@ var SetPreviewUrlTool = Tool.define("set_preview_url", async () => {
20164
20255
  };
20165
20256
  });
20166
20257
  var AnyCodeAgent = class {
20167
- name = "AnyCode Agent";
20258
+ name;
20168
20259
  config;
20169
20260
  _codeAgent;
20170
20261
  _initialized = false;
20171
20262
  constructor(config) {
20172
20263
  this.config = config;
20264
+ this.name = config.name || "AnyCode Agent";
20173
20265
  if (!config.codeAgentOptions) {
20174
20266
  throw new Error("AnyCodeAgent requires codeAgentOptions in ChatAgentConfig");
20175
20267
  }
20176
20268
  this._codeAgent = new CodeAgent(config.codeAgentOptions);
20177
20269
  }
20178
- async ensureInit() {
20270
+ async init() {
20179
20271
  if (!this._initialized) {
20180
- await this._codeAgent.init();
20181
20272
  this._initialized = true;
20273
+ await this._codeAgent.init();
20182
20274
  }
20183
20275
  }
20184
20276
  get sessionId() {
20185
20277
  return this._codeAgent.sessionId;
20186
20278
  }
20187
20279
  async *chat(input) {
20188
- await this.ensureInit();
20280
+ await this.init();
20189
20281
  yield* this._codeAgent.chat(input);
20190
20282
  }
20191
20283
  abort() {
@@ -20197,8 +20289,11 @@ var AnyCodeAgent = class {
20197
20289
  setWorkingDirectory(dir) {
20198
20290
  this._codeAgent.setWorkingDirectory(dir);
20199
20291
  }
20200
- getStats() {
20201
- return this._codeAgent.getStats();
20292
+ async getUsage() {
20293
+ return this._codeAgent.getUsage();
20294
+ }
20295
+ async getContext() {
20296
+ return this._codeAgent.getContext();
20202
20297
  }
20203
20298
  getSessionMessages(opts) {
20204
20299
  return this._codeAgent.getSessionMessages(opts);
@@ -20325,7 +20420,7 @@ function createAgentConfig(cfg, directory, sessionId, terminal, preview) {
20325
20420
  ...sessionId ? { sessionId } : {},
20326
20421
  ...terminal ? { terminal } : {},
20327
20422
  ...preview ? { preview } : {},
20328
- extraTools: [
20423
+ tools: [
20329
20424
  SetWorkingDirectoryTool,
20330
20425
  TerminalWriteTool,
20331
20426
  TerminalReadTool,
@@ -20432,7 +20527,7 @@ async function createNewWindow(cfg, isDefault = false) {
20432
20527
  const tp = getOrCreateTerminalProvider(tempId);
20433
20528
  const pp = getOrCreatePreviewProvider(cfg, tempId);
20434
20529
  const chatAgent = createChatAgent(cfg.agent, createChatAgentConfig(cfg, "", void 0, tp, pp));
20435
- await chatAgent.ensureInit();
20530
+ await chatAgent.init();
20436
20531
  const sessionId = chatAgent.sessionId;
20437
20532
  const now = Date.now();
20438
20533
  terminalProviders.delete(tempId);
@@ -21423,12 +21518,12 @@ function createMainServer(cfg) {
21423
21518
  return;
21424
21519
  }
21425
21520
  if (req.method === "GET" && req.url === "/api/status") {
21426
- const list = Array.from(sessions.values()).map((s4) => ({
21521
+ const list = await Promise.all(Array.from(sessions.values()).map(async (s4) => ({
21427
21522
  id: s4.id,
21428
21523
  directory: s4.directory,
21429
- stats: s4.chatAgent.getStats(),
21524
+ stats: await s4.chatAgent.getUsage(),
21430
21525
  sessionId: s4.chatAgent.sessionId
21431
- }));
21526
+ })));
21432
21527
  res.writeHead(200, { "Content-Type": "application/json" });
21433
21528
  res.end(JSON.stringify({ sessions: list }));
21434
21529
  return;
@@ -5,7 +5,7 @@ import {
5
5
  ProviderID,
6
6
  Todo,
7
7
  iife
8
- } from "./chunk-TYWHGJLT.js";
8
+ } from "./chunk-4SPBQLA5.js";
9
9
  import {
10
10
  Identifier,
11
11
  MessageID,
@@ -17826,7 +17826,7 @@ function canConvert(input) {
17826
17826
  }
17827
17827
  var turndown_es_default = TurndownService;
17828
17828
 
17829
- // ../agent/dist/chunk-V3IOOGKZ.js
17829
+ // ../agent/dist/chunk-MD6BEIK2.js
17830
17830
  import { pathToFileURL as pathToFileURL2 } from "url";
17831
17831
  import { pathToFileURL } from "url";
17832
17832
  var SchedulerService = class {
@@ -19199,11 +19199,11 @@ Expected payload format:
19199
19199
  [{"tool": "tool_name", "parameters": {...}}, {...}]`;
19200
19200
  },
19201
19201
  async execute(params, ctx) {
19202
- const { Session } = await import("./session-CD67J7DC-TOJQJOSR.js");
19202
+ const { Session } = await import("./session-3H7MDN6G-ILPE3VAH.js");
19203
19203
  const { PartID: PartID2 } = await import("./schema-2CACIKZR-3CAWV3IP.js");
19204
19204
  const toolCalls = params.tool_calls.slice(0, 25);
19205
19205
  const discardedCalls = params.tool_calls.slice(25);
19206
- const { ToolRegistry: ToolRegistry2 } = await import("./registry-4Z4O3ZD2-QFDRMPNT.js");
19206
+ const { ToolRegistry: ToolRegistry2 } = await import("./registry-N6XVTLPC-H2PNFK4G.js");
19207
19207
  const availableTools = await ctx.toolRegistry.tools({ modelID: ModelID.make(""), providerID: ProviderID.make("") });
19208
19208
  const toolMap = new Map(availableTools.map((t) => [t.id, t]));
19209
19209
  const executeCall = async (call) => {
@@ -21315,7 +21315,7 @@ var ToolRegistry;
21315
21315
  CodeSearchTool,
21316
21316
  SkillTool,
21317
21317
  ApplyPatchTool,
21318
- ...context.extraTools ?? [],
21318
+ ...context.tools ?? [],
21319
21319
  ...config.experimental?.batch_tool === true ? [BatchTool] : [],
21320
21320
  ...Flag.OPENCODE_EXPERIMENTAL_PLAN_MODE && Flag.OPENCODE_CLIENT === "cli" ? [PlanExitTool] : [],
21321
21321
  ...custom
@@ -165,7 +165,7 @@ var require_dist = __commonJS({
165
165
  }
166
166
  });
167
167
 
168
- // ../agent/dist/chunk-CTKFONUT.js
168
+ // ../agent/dist/chunk-QSYBKVFM.js
169
169
  import { EventEmitter as EventEmitter2 } from "events";
170
170
 
171
171
  // ../../node_modules/.pnpm/decimal.js@10.5.0/node_modules/decimal.js/decimal.mjs
@@ -2344,7 +2344,7 @@ var Decimal = P.constructor = clone(DEFAULTS);
2344
2344
  LN10 = new Decimal(LN10);
2345
2345
  PI = new Decimal(PI);
2346
2346
 
2347
- // ../agent/dist/chunk-CTKFONUT.js
2347
+ // ../agent/dist/chunk-QSYBKVFM.js
2348
2348
  import { EventEmitter } from "events";
2349
2349
 
2350
2350
  // ../../node_modules/.pnpm/@ai-sdk+provider@2.0.1/node_modules/@ai-sdk/provider/dist/index.mjs
@@ -15661,7 +15661,7 @@ var uiMessagesSchema = lazyValidator(
15661
15661
  )
15662
15662
  );
15663
15663
 
15664
- // ../agent/dist/chunk-CTKFONUT.js
15664
+ // ../agent/dist/chunk-QSYBKVFM.js
15665
15665
  import { STATUS_CODES } from "http";
15666
15666
  var Slug;
15667
15667
  ((Slug2) => {
@@ -16277,7 +16277,7 @@ var MessageV2;
16277
16277
  root: zod_default.string()
16278
16278
  }),
16279
16279
  summary: zod_default.boolean().optional(),
16280
- cost: zod_default.number(),
16280
+ cost: zod_default.number().optional(),
16281
16281
  tokens: zod_default.object({
16282
16282
  total: zod_default.number().optional(),
16283
16283
  input: zod_default.number(),
@@ -16287,7 +16287,7 @@ var MessageV2;
16287
16287
  read: zod_default.number(),
16288
16288
  write: zod_default.number()
16289
16289
  })
16290
- }),
16290
+ }).optional(),
16291
16291
  structured: zod_default.any().optional(),
16292
16292
  variant: zod_default.string().optional(),
16293
16293
  finish: zod_default.string().optional()
@@ -16774,6 +16774,24 @@ var MemoryService = class extends EventEmitter {
16774
16774
  result.reverse();
16775
16775
  return result;
16776
16776
  }
16777
+ /**
16778
+ * Remove all messages tagged with a specific chatId.
16779
+ * Queries from DB so this works even after process restart.
16780
+ */
16781
+ async clearMessagesByChatId(chatId) {
16782
+ const rows = this.context.db.findMany("message", {});
16783
+ for (const row of rows) {
16784
+ if (row.data?.chatId === chatId) {
16785
+ this.context.db.remove("message", {
16786
+ op: "and",
16787
+ conditions: [
16788
+ { op: "eq", field: "id", value: row.id },
16789
+ { op: "eq", field: "session_id", value: row.session_id }
16790
+ ]
16791
+ });
16792
+ }
16793
+ }
16794
+ }
16777
16795
  };
16778
16796
  var Memory;
16779
16797
  ((Memory2) => {
@@ -17209,7 +17227,6 @@ export {
17209
17227
  Installation,
17210
17228
  iife,
17211
17229
  defer,
17212
- Token,
17213
17230
  ProviderID,
17214
17231
  ModelID,
17215
17232
  MessageV2,
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ToolRegistry
4
- } from "./chunk-ILSZBQFJ.js";
5
- import "./chunk-TYWHGJLT.js";
4
+ } from "./chunk-2X6YJUFL.js";
5
+ import "./chunk-4SPBQLA5.js";
6
6
  import "./chunk-DU4BGORD.js";
7
7
  import "./chunk-6Q6QFZOB.js";
8
8
  import "./chunk-NRFXEZ7N.js";
@@ -4,7 +4,7 @@ import {
4
4
  SessionService,
5
5
  SessionStatus,
6
6
  Todo
7
- } from "./chunk-TYWHGJLT.js";
7
+ } from "./chunk-4SPBQLA5.js";
8
8
  import "./chunk-DU4BGORD.js";
9
9
  import "./chunk-6Q6QFZOB.js";
10
10
  import "./chunk-NRFXEZ7N.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anycodex",
3
- "version": "0.0.24",
3
+ "version": "0.0.25",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -18,8 +18,8 @@
18
18
  "@types/node": "^25.5.0",
19
19
  "tsup": "^8.4.0",
20
20
  "typescript": "^5.7.0",
21
- "@any-code/server": "0.0.4",
22
- "@any-code/app": "0.0.1"
21
+ "@any-code/app": "0.0.2",
22
+ "@any-code/server": "0.0.6"
23
23
  },
24
24
  "scripts": {
25
25
  "build": "tsup"