@gajae-code/agent-core 0.5.1 → 0.5.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.5.2] - 2026-06-15
6
+
7
+ ### Fixed
8
+
9
+ - Fixed compaction token estimation in Bun standalone binaries by loading the native tokenizer through the sibling native entrypoint instead of package-name dynamic resolution.
10
+
5
11
  ## [0.5.1] - 2026-06-14
6
12
 
7
13
  - Version aligned with the 0.5.1 monorepo release; no functional changes in this package.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/agent-core",
4
- "version": "0.5.1",
4
+ "version": "0.5.2",
5
5
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
6
6
  "homepage": "https://gaebal-gajae.dev",
7
7
  "author": "Yeachan-Heo",
@@ -35,9 +35,9 @@
35
35
  "fmt": "biome format --write ."
36
36
  },
37
37
  "dependencies": {
38
- "@gajae-code/ai": "0.5.1",
39
- "@gajae-code/natives": "0.5.1",
40
- "@gajae-code/utils": "0.5.1",
38
+ "@gajae-code/ai": "0.5.2",
39
+ "@gajae-code/natives": "0.5.2",
40
+ "@gajae-code/utils": "0.5.2",
41
41
  "@opentelemetry/api": "^1.9.0"
42
42
  },
43
43
  "devDependencies": {
@@ -5,6 +5,7 @@
5
5
  * and after compaction the session is reloaded.
6
6
  */
7
7
 
8
+ import { createRequire } from "node:module";
8
9
  import {
9
10
  type AssistantMessage,
10
11
  Effort,
@@ -13,7 +14,7 @@ import {
13
14
  type Model,
14
15
  type Usage,
15
16
  } from "@gajae-code/ai";
16
- import { logger, prompt } from "@gajae-code/utils";
17
+ import { isCompiledBinary, logger, prompt } from "@gajae-code/utils";
17
18
  import { type AgentTelemetry, instrumentedCompleteSimple } from "../telemetry";
18
19
  import type { AgentMessage, AgentTool } from "../types";
19
20
  import type { CompactionEntry, SessionEntry } from "./entries";
@@ -265,23 +266,44 @@ export function resolveThresholdTokens(
265
266
  * matching what providers typically bill for inline images.
266
267
  */
267
268
  const IMAGE_TOKEN_ESTIMATE = 1200;
269
+ const SOURCE_NATIVE_TOKENIZER_ENTRYPOINT = "../../../natives/native/index.js";
270
+ const COMPILED_NATIVE_TOKENIZER_ENTRYPOINT = "/$bunfs/root/packages/natives/native/index.js";
271
+
272
+ const requireFromCompaction = createRequire(import.meta.url);
273
+
274
+ interface NativeTokenizerModule {
275
+ countTokens(input: string | string[], encoding?: unknown): number;
276
+ }
268
277
 
269
278
  /**
270
279
  * Lazily-required native `countTokens`. `@gajae-code/natives` dlopens a ~39MB
271
280
  * addon; importing it at module scope would put that cost on every cold path
272
281
  * that touches compaction exports (status line, print mode, context report).
273
- * Deferring the require to the first context-changing call keeps the trivial
274
- * `-p` / display paths native-free.
282
+ * Deferring the require to the first context-changing call keeps display paths
283
+ * native-free.
284
+ *
285
+ * Do not resolve this via a package-name dynamic require of
286
+ * `@gajae-code/natives`: Bun standalone binaries cannot satisfy those from
287
+ * `$bunfs`. The sibling-package source path is stable for workspace and
288
+ * package-install layouts:
289
+ *
290
+ * - workspace: `packages/agent` -> `packages/natives`
291
+ * - npm/bun install: `node_modules/@gajae-code/agent-core` ->
292
+ * `node_modules/@gajae-code/natives`
293
+ *
294
+ * Bun rewrites `createRequire(import.meta.url)` to the compiled executable
295
+ * root (`/$bunfs/root/gjc-*`) in standalone binaries, so compiled mode uses the
296
+ * absolute bunfs module path emitted by the binary build scripts.
275
297
  */
276
298
  let cachedNativeCountTokens: ((input: string | string[], encoding?: unknown) => number) | null = null;
277
299
 
300
+ function nativeTokenizerEntrypoint(): string {
301
+ return isCompiledBinary() ? COMPILED_NATIVE_TOKENIZER_ENTRYPOINT : SOURCE_NATIVE_TOKENIZER_ENTRYPOINT;
302
+ }
303
+
278
304
  function nativeCountTokens(fragments: string[]): number {
279
305
  if (!cachedNativeCountTokens) {
280
- const { createRequire } = require("node:module") as typeof import("node:module");
281
- const requireFromHere = createRequire(import.meta.url);
282
- const natives = requireFromHere("@gajae-code/natives") as {
283
- countTokens: (input: string | string[], encoding?: unknown) => number;
284
- };
306
+ const natives = requireFromCompaction(nativeTokenizerEntrypoint()) as NativeTokenizerModule;
285
307
  cachedNativeCountTokens = natives.countTokens;
286
308
  }
287
309
  return cachedNativeCountTokens(fragments);