open-multi-agent-kit 0.90.4 → 0.90.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.
Files changed (161) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +9 -9
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +1 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/codexbar-cli.d.ts +39 -0
  7. package/dist/codexbar-cli.d.ts.map +1 -0
  8. package/dist/codexbar-cli.js +230 -0
  9. package/dist/codexbar-cli.js.map +1 -0
  10. package/dist/commands/doctor-provider.d.ts.map +1 -1
  11. package/dist/commands/doctor-provider.js +16 -3
  12. package/dist/commands/doctor-provider.js.map +1 -1
  13. package/dist/core/adaptorch-bridge.d.ts +14 -21
  14. package/dist/core/adaptorch-bridge.d.ts.map +1 -1
  15. package/dist/core/adaptorch-bridge.js +11 -18
  16. package/dist/core/adaptorch-bridge.js.map +1 -1
  17. package/dist/core/agent-session.d.ts +6 -39
  18. package/dist/core/agent-session.d.ts.map +1 -1
  19. package/dist/core/agent-session.js +37 -107
  20. package/dist/core/agent-session.js.map +1 -1
  21. package/dist/core/codexbar-adapter.d.ts +44 -0
  22. package/dist/core/codexbar-adapter.d.ts.map +1 -0
  23. package/dist/core/codexbar-adapter.js +211 -0
  24. package/dist/core/codexbar-adapter.js.map +1 -0
  25. package/dist/core/compaction/index.d.ts +2 -0
  26. package/dist/core/compaction/index.d.ts.map +1 -1
  27. package/dist/core/compaction/index.js +2 -0
  28. package/dist/core/compaction/index.js.map +1 -1
  29. package/dist/core/compaction/model-policy.d.ts +9 -0
  30. package/dist/core/compaction/model-policy.d.ts.map +1 -0
  31. package/dist/core/compaction/model-policy.js +37 -0
  32. package/dist/core/compaction/model-policy.js.map +1 -0
  33. package/dist/core/compaction/resume-policy.d.ts +6 -0
  34. package/dist/core/compaction/resume-policy.d.ts.map +1 -0
  35. package/dist/core/compaction/resume-policy.js +8 -0
  36. package/dist/core/compaction/resume-policy.js.map +1 -0
  37. package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
  38. package/dist/core/context-budget-v2-planner.js +10 -2
  39. package/dist/core/context-budget-v2-planner.js.map +1 -1
  40. package/dist/core/context-budget-v2-types.d.ts +7 -1
  41. package/dist/core/context-budget-v2-types.d.ts.map +1 -1
  42. package/dist/core/context-budget-v2-types.js.map +1 -1
  43. package/dist/core/domain-loadouts.d.ts.map +1 -1
  44. package/dist/core/domain-loadouts.js +68 -1
  45. package/dist/core/domain-loadouts.js.map +1 -1
  46. package/dist/core/extensions/loader.d.ts.map +1 -1
  47. package/dist/core/extensions/loader.js +12 -0
  48. package/dist/core/extensions/loader.js.map +1 -1
  49. package/dist/core/extensions/runner.d.ts.map +1 -1
  50. package/dist/core/extensions/runner.js +3 -0
  51. package/dist/core/extensions/runner.js.map +1 -1
  52. package/dist/core/extensions/types.d.ts +15 -0
  53. package/dist/core/extensions/types.d.ts.map +1 -1
  54. package/dist/core/extensions/types.js.map +1 -1
  55. package/dist/core/grok-harness-dispatch.d.ts +22 -0
  56. package/dist/core/grok-harness-dispatch.d.ts.map +1 -0
  57. package/dist/core/grok-harness-dispatch.js +44 -0
  58. package/dist/core/grok-harness-dispatch.js.map +1 -0
  59. package/dist/core/grok-harness.d.ts +25 -0
  60. package/dist/core/grok-harness.d.ts.map +1 -0
  61. package/dist/core/grok-harness.js +61 -0
  62. package/dist/core/grok-harness.js.map +1 -0
  63. package/dist/core/grok-playbook.d.ts +7 -0
  64. package/dist/core/grok-playbook.d.ts.map +1 -0
  65. package/dist/core/grok-playbook.js +34 -0
  66. package/dist/core/grok-playbook.js.map +1 -0
  67. package/dist/core/reasoning-router-bias.d.ts +11 -23
  68. package/dist/core/reasoning-router-bias.d.ts.map +1 -1
  69. package/dist/core/reasoning-router-bias.js +9 -18
  70. package/dist/core/reasoning-router-bias.js.map +1 -1
  71. package/dist/core/reasoning-router-resolver.d.ts +44 -0
  72. package/dist/core/reasoning-router-resolver.d.ts.map +1 -0
  73. package/dist/core/reasoning-router-resolver.js +79 -0
  74. package/dist/core/reasoning-router-resolver.js.map +1 -0
  75. package/dist/core/reasoning-router-v4-weights.d.ts +28 -72
  76. package/dist/core/reasoning-router-v4-weights.d.ts.map +1 -1
  77. package/dist/core/reasoning-router-v4-weights.js +16 -60
  78. package/dist/core/reasoning-router-v4-weights.js.map +1 -1
  79. package/dist/core/reasoning-router-v4.d.ts +25 -70
  80. package/dist/core/reasoning-router-v4.d.ts.map +1 -1
  81. package/dist/core/reasoning-router-v4.js +46 -144
  82. package/dist/core/reasoning-router-v4.js.map +1 -1
  83. package/dist/core/router-feedback-collector.d.ts +13 -16
  84. package/dist/core/router-feedback-collector.d.ts.map +1 -1
  85. package/dist/core/router-feedback-collector.js +5 -8
  86. package/dist/core/router-feedback-collector.js.map +1 -1
  87. package/dist/core/sdk.d.ts.map +1 -1
  88. package/dist/core/sdk.js +31 -12
  89. package/dist/core/sdk.js.map +1 -1
  90. package/dist/core/slash-commands.d.ts.map +1 -1
  91. package/dist/core/slash-commands.js +1 -1
  92. package/dist/core/slash-commands.js.map +1 -1
  93. package/dist/main.d.ts.map +1 -1
  94. package/dist/main.js +4 -0
  95. package/dist/main.js.map +1 -1
  96. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  97. package/dist/modes/interactive/interactive-mode.js +16 -98
  98. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  99. package/dist/utils/tools-manager.d.ts +3 -2
  100. package/dist/utils/tools-manager.d.ts.map +1 -1
  101. package/dist/utils/tools-manager.js +42 -17
  102. package/dist/utils/tools-manager.js.map +1 -1
  103. package/docs/correctness-wall.md +117 -0
  104. package/docs/grok-harness.md +63 -0
  105. package/docs/loadout-domains/README.md +2 -1
  106. package/docs/loadout-domains/ai-agent-ops.md +8 -1
  107. package/docs/loadout-domains/grok-harness.md +74 -0
  108. package/docs/providers.md +4 -0
  109. package/docs/usage.md +11 -12
  110. package/examples/extensions/correctness-wall/LOADOUT.md +87 -0
  111. package/examples/extensions/correctness-wall/README.md +111 -0
  112. package/examples/extensions/correctness-wall/adjudication-fixture.ts +151 -0
  113. package/examples/extensions/correctness-wall/index.ts +470 -0
  114. package/examples/extensions/correctness-wall/repair-state.ts +77 -0
  115. package/examples/extensions/correctness-wall/wall-cache.ts +81 -0
  116. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  117. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  118. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  119. package/examples/extensions/gondolin/package-lock.json +2 -2
  120. package/examples/extensions/gondolin/package.json +1 -1
  121. package/examples/extensions/sandbox/package-lock.json +2 -2
  122. package/examples/extensions/sandbox/package.json +1 -1
  123. package/examples/extensions/subagent/agent-capability-router.test.ts +123 -0
  124. package/examples/extensions/subagent/agent-capability-router.ts +274 -0
  125. package/examples/extensions/subagent/agents/planner.md +3 -0
  126. package/examples/extensions/subagent/agents/reviewer.md +3 -0
  127. package/examples/extensions/subagent/agents/scout.md +3 -0
  128. package/examples/extensions/subagent/agents/worker.md +2 -0
  129. package/examples/extensions/subagent/agents.ts +14 -0
  130. package/examples/extensions/subagent/capabilities.ts +368 -0
  131. package/examples/extensions/subagent/domain-profiles.ts +1089 -0
  132. package/examples/extensions/subagent/index.ts +71 -3
  133. package/examples/extensions/with-deps/package-lock.json +2 -2
  134. package/examples/extensions/with-deps/package.json +1 -1
  135. package/examples/sdk/12-full-control.ts +1 -1
  136. package/npm-shrinkwrap.json +12 -12
  137. package/package.json +5 -5
  138. package/dist/core/compactor.d.ts +0 -42
  139. package/dist/core/compactor.d.ts.map +0 -1
  140. package/dist/core/compactor.js +0 -128
  141. package/dist/core/compactor.js.map +0 -1
  142. package/dist/core/reasoning-router-v2.d.ts +0 -94
  143. package/dist/core/reasoning-router-v2.d.ts.map +0 -1
  144. package/dist/core/reasoning-router-v2.js +0 -288
  145. package/dist/core/reasoning-router-v2.js.map +0 -1
  146. package/dist/core/reasoning-router-v3.d.ts +0 -15
  147. package/dist/core/reasoning-router-v3.d.ts.map +0 -1
  148. package/dist/core/reasoning-router-v3.js +0 -193
  149. package/dist/core/reasoning-router-v3.js.map +0 -1
  150. package/dist/core/reasoning-router-weights.d.ts +0 -155
  151. package/dist/core/reasoning-router-weights.d.ts.map +0 -1
  152. package/dist/core/reasoning-router-weights.js +0 -204
  153. package/dist/core/reasoning-router-weights.js.map +0 -1
  154. package/dist/core/reasoning-router.d.ts +0 -44
  155. package/dist/core/reasoning-router.d.ts.map +0 -1
  156. package/dist/core/reasoning-router.js +0 -138
  157. package/dist/core/reasoning-router.js.map +0 -1
  158. package/dist/core/token-optimizer.d.ts +0 -58
  159. package/dist/core/token-optimizer.d.ts.map +0 -1
  160. package/dist/core/token-optimizer.js +0 -179
  161. package/dist/core/token-optimizer.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"reasoning-router.js","sourceRoot":"","sources":["../../src/core/reasoning-router.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAeH,+FAA+F;AAC/F,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAC7B,6GAA6G;AAC7G,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAErC;;;;;GAKG;AACH,MAAM,gBAAgB,GAA6D;IAClF;QACC,SAAS,EAAE,OAAO;QAClB,OAAO,EACN,sKAAsK;KACvK;IACD;QACC,SAAS,EAAE,UAAU;QACrB,OAAO,EACN,gLAAgL;KACjL;IACD;QACC,SAAS,EAAE,QAAQ;QACnB,OAAO,EAAE,iGAAiG;KAC1G;IACD;QACC,SAAS,EAAE,MAAM;QACjB,OAAO,EACN,mLAAmL;KACpL;IACD;QACC,SAAS,EAAE,aAAa;QACxB,OAAO,EACN,+HAA+H;KAChI;IACD;QACC,SAAS,EAAE,UAAU;QACrB,OAAO,EACN,oIAAoI;KACrI;CACD,CAAC;AAEF,oFAAoF;AACpF,MAAM,mBAAmB,GAAyC;IACjE,OAAO,EAAE,MAAM;IACf,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE,UAAU;IACjB,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,UAAU;CAClB,CAAC;AAEF,SAAS,YAAY,CAAC,IAAY,EAAW;IAC5C,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAAA,CAC5B;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,IAAY,EAAW;IAC9C,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACzE,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CACxD;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,KAA0B,EAAa;IACnE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAEnC,KAAK,MAAM,MAAM,IAAI,gBAAgB,EAAE,CAAC;QACvC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC,SAAS,CAAC;IAC1D,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,MAAM,CAAC;QAAE,OAAO,UAAU,CAAC;IACtE,IAAI,MAAM,CAAC,MAAM,GAAG,iBAAiB;QAAE,OAAO,SAAS,CAAC;IACxD,IAAI,MAAM,CAAC,MAAM,IAAI,uBAAuB;QAAE,OAAO,MAAM,CAAC;IAC5D,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO,mBAAmB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/D,OAAO,UAAU,CAAC;AAAA,CAClB;AAED,oFAAoF;AACpF,MAAM,gBAAgB,GAA6B,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAExG,wGAAwG;AACxG,MAAM,CAAC,MAAM,0BAA0B,GAA+C;IACrF,OAAO,EAAE,SAAS;IAClB,aAAa,EAAE,KAAK;IACpB,UAAU,EAAE,QAAQ;IACpB,KAAK,EAAE,MAAM;IACb,QAAQ,EAAE,MAAM;IAChB,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,OAAO;CACb,CAAC;AAEF,yFAAyF;AACzF,MAAM,SAAS,GAAyD;IACvE,OAAO,EAAE,CAAC;IACV,QAAQ,EAAE,CAAC;IACX,QAAQ,EAAE,CAAC,CAAC;CACZ,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CACnC,SAAoB,EACpB,eAAyC,EACzC,QAA4B,EACZ;IAChB,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,0BAA0B,CAAC,SAAS,CAAC,CAAC,CAAC;IAClF,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,EAAE,CAAC,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEzF,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9F,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,eAAe,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;IACpC,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAC7D,CAAC;IACD,OAAO,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAAA,CAC5B","sourcesContent":["/**\n * Reasoning-effort router: pure, side-effect-free task classification and\n * ThinkingLevel resolution for the `auto` thinking mode.\n *\n * Deterministic by construction: consumes only the prompt text and an optional\n * subagent lane type. No clock, randomness, I/O, or imports from session, TUI,\n * or provider code (the ThinkingLevel import below is type-only and erased).\n */\n\nimport type { ThinkingLevel } from \"omk-agent-core\";\n\n/** Closed set of task classes the router can assign to a turn. */\nexport type TaskClass = \"trivial\" | \"simple-edit\" | \"code-gen\" | \"debug\" | \"refactor\" | \"review\" | \"plan\";\n\n/** Subagent lane types recognized by the classifier and resolver. */\nexport type ReasoningLaneType = \"planner\" | \"security\" | \"explorer\" | \"coder\" | \"reviewer\" | \"tester\";\n\nexport interface TaskClassifierInput {\n\tprompt: string;\n\tlaneType?: ReasoningLaneType;\n}\n\n/** Prompts shorter than this (trimmed) classify as trivial when no stronger signal matches. */\nconst TRIVIAL_MAX_CHARS = 40;\n/** Prompts at/above this length with no keyword/code/diff signal are treated as long prose briefs (plan). */\nconst COMPLEX_PROSE_MIN_CHARS = 2400;\n\n/**\n * Keyword families in FIXED precedence order:\n * debug > refactor > review > plan > simple-edit > code-gen.\n * The first matching family wins; ties are impossible by construction.\n * Patterns are case-insensitive and stateless (no `g` flag, so no lastIndex carry-over).\n */\nconst KEYWORD_FAMILIES: ReadonlyArray<{ taskClass: TaskClass; pattern: RegExp }> = [\n\t{\n\t\ttaskClass: \"debug\",\n\t\tpattern:\n\t\t\t/\\b(debug(ging)?|bugs?|fix(es|ing|ed)?|errors?|exceptions?|crash(es|ing|ed)?|stack\\s*trace|traceback|regressions?|broken|fail(s|ing|ed|ure|ures)?|flaky|reproduce)\\b/i,\n\t},\n\t{\n\t\ttaskClass: \"refactor\",\n\t\tpattern:\n\t\t\t/\\b(refactor(ing|ed)?|restructur(e|ing)|renam(e|ing)|extract(ing)?|clean\\s*up|cleanup|simplif(y|ying|ied)|deduplicat(e|ing)|reorganiz(e|ing)|rewrit(e|ing)|modulariz(e|ing))\\b/i,\n\t},\n\t{\n\t\ttaskClass: \"review\",\n\t\tpattern: /\\b(review(s|ing|ed)?|audit(s|ing|ed)?|critique|assess(ing|ment)?|inspect(ing)?|lgtm|approve)\\b/i,\n\t},\n\t{\n\t\ttaskClass: \"plan\",\n\t\tpattern:\n\t\t\t/\\b(plan(s|ning)?|design(s|ing)?|architect(s|ure|ing)?|roadmap|spec(s|ification|ifications)?|strateg(y|ies|ize)|decompos(e|ing|ition)|break\\s+(this\\s+|it\\s+)?down|milestones?)\\b/i,\n\t},\n\t{\n\t\ttaskClass: \"simple-edit\",\n\t\tpattern:\n\t\t\t/\\b(typos?|tweak(s|ing|ed)?|one-?liner?|single\\s+line|bump(s|ing|ed)?|whitespace|reword(s|ing|ed)?|indentation|punctuation)\\b/i,\n\t},\n\t{\n\t\ttaskClass: \"code-gen\",\n\t\tpattern:\n\t\t\t/\\b(implement(s|ing|ation)?|writ(e|ing)|creat(e|es|ing)|add(s|ing|ed)?|build(s|ing)?|generat(e|es|ing)|scaffold(ing)?|prototype)\\b/i,\n\t},\n];\n\n/** Fallback class per lane when no keyword, code/diff, or length signal decides. */\nconst LANE_FALLBACK_CLASS: Record<ReasoningLaneType, TaskClass> = {\n\tplanner: \"plan\",\n\tsecurity: \"review\",\n\texplorer: \"review\",\n\tcoder: \"code-gen\",\n\treviewer: \"review\",\n\ttester: \"code-gen\",\n};\n\nfunction hasCodeFence(text: string): boolean {\n\treturn text.includes(\"```\");\n}\n\n/**\n * Diff detection: explicit hunk (`@@ ... @@`) or `diff --git` headers count alone;\n * bare `+`/`-` line starts only count when both added AND removed lines are present\n * (avoids false positives on markdown bullet lists).\n */\nfunction hasDiffMarkers(text: string): boolean {\n\tif (/^@@[^\\n]*@@/m.test(text) || /^diff --git /m.test(text)) return true;\n\treturn /^\\+(?!\\+)/m.test(text) && /^-(?!-)/m.test(text);\n}\n\n/**\n * Classify a turn deterministically. Signal precedence (first match wins):\n * 1. Keyword families (debug > refactor > review > plan > simple-edit > code-gen)\n * 2. Code fence or diff markers -> code-gen\n * 3. Trimmed length < TRIVIAL_MAX_CHARS -> trivial\n * 4. Trimmed length >= COMPLEX_PROSE_MIN_CHARS -> plan (long prose brief)\n * 5. Lane fallback (see LANE_FALLBACK_CLASS)\n * 6. Default -> code-gen\n */\nexport function classifyTask(input: TaskClassifierInput): TaskClass {\n\tconst prompt = input.prompt.trim();\n\n\tfor (const family of KEYWORD_FAMILIES) {\n\t\tif (family.pattern.test(prompt)) return family.taskClass;\n\t}\n\n\tif (hasCodeFence(prompt) || hasDiffMarkers(prompt)) return \"code-gen\";\n\tif (prompt.length < TRIVIAL_MAX_CHARS) return \"trivial\";\n\tif (prompt.length >= COMPLEX_PROSE_MIN_CHARS) return \"plan\";\n\tif (input.laneType) return LANE_FALLBACK_CLASS[input.laneType];\n\treturn \"code-gen\";\n}\n\n/** Reasoning ladder used for targets and clamping. Intentionally excludes \"off\". */\nconst REASONING_LADDER: readonly ThinkingLevel[] = [\"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n\n/** Static rule table: task class -> recommended ThinkingLevel (before lane adjustment and clamping). */\nexport const TASK_CLASS_THINKING_LEVELS: Readonly<Record<TaskClass, ThinkingLevel>> = {\n\ttrivial: \"minimal\",\n\t\"simple-edit\": \"low\",\n\t\"code-gen\": \"medium\",\n\tdebug: \"high\",\n\trefactor: \"high\",\n\treview: \"high\",\n\tplan: \"xhigh\",\n};\n\n/** Lane adjustment in ladder steps: planner/security escalate, explorer de-escalates. */\nconst LANE_STEP: Readonly<Partial<Record<ReasoningLaneType, 1 | -1>>> = {\n\tplanner: 1,\n\tsecurity: 1,\n\texplorer: -1,\n};\n\n/**\n * Resolve the recommended ThinkingLevel for a task class:\n * 1. Look up the static rule table.\n * 2. Apply the lane adjustment (one ladder step, saturating at ladder ends).\n * 3. Clamp to the highest level in `availableLevels` that is <= the target;\n * if no available level is at/below the target, return the lowest available\n * reasoning level. Never invents a level outside `availableLevels`.\n *\n * `\"off\"` is never a router output for reasoning models. If `availableLevels`\n * contains no ladder level at all (e.g. a non-reasoning model exposing only\n * \"off\"), the first available level is returned; callers are expected to\n * bypass the router entirely for models with `reasoning: false`.\n */\nexport function resolveThinkingLevel(\n\ttaskClass: TaskClass,\n\tavailableLevels: readonly ThinkingLevel[],\n\tlaneType?: ReasoningLaneType,\n): ThinkingLevel {\n\tconst baseIndex = REASONING_LADDER.indexOf(TASK_CLASS_THINKING_LEVELS[taskClass]);\n\tconst step = laneType ? (LANE_STEP[laneType] ?? 0) : 0;\n\tconst targetIndex = Math.min(Math.max(baseIndex + step, 0), REASONING_LADDER.length - 1);\n\n\tconst availableOnLadder = REASONING_LADDER.filter((level) => availableLevels.includes(level));\n\tif (availableOnLadder.length === 0) {\n\t\treturn availableLevels[0] ?? \"off\";\n\t}\n\n\tfor (let i = targetIndex; i >= 0; i--) {\n\t\tconst candidate = REASONING_LADDER[i];\n\t\tif (availableOnLadder.includes(candidate)) return candidate;\n\t}\n\treturn availableOnLadder[0];\n}\n"]}
@@ -1,58 +0,0 @@
1
- import { EventEmitter } from "events";
2
- export interface TokenOptimizationResult {
3
- originalQuery: string;
4
- optimizedQuery: string;
5
- tokensSaved: number;
6
- technique: string;
7
- cacheHit: boolean;
8
- budgetExceeded: boolean;
9
- }
10
- export interface TokenOptimizerRuntimeStatus {
11
- readonly optimizerId: "legacy-token-optimizer";
12
- readonly status: "quarantined_compatibility";
13
- readonly active: false;
14
- readonly activeContextBudgetOptimizer: "context-budget-v2";
15
- readonly compatibilityOnly: true;
16
- }
17
- export declare function getTokenOptimizerRuntimeStatus(): TokenOptimizerRuntimeStatus;
18
- export declare class LosslessCompressor extends EventEmitter {
19
- compress(query: string): {
20
- compressed: string;
21
- tokensSaved: number;
22
- };
23
- }
24
- export declare class LazyExecutor extends EventEmitter {
25
- private memoCache;
26
- execute<T>(taskId: string, fn: () => T, force?: boolean): T;
27
- clear(): void;
28
- }
29
- export declare class AdaptiveBudget extends EventEmitter {
30
- private budget;
31
- private used;
32
- private history;
33
- constructor(initialBudget?: number);
34
- allocate(tokens: number): boolean;
35
- getStats(): {
36
- budget: number;
37
- used: number;
38
- remaining: number;
39
- utilization: number;
40
- };
41
- adjustBudget(newBudget: number): void;
42
- }
43
- export declare class TokenOptimizer extends EventEmitter {
44
- private compressor;
45
- private executor;
46
- private budget;
47
- constructor(budget?: number);
48
- optimize(query: string): TokenOptimizationResult;
49
- lazyExecute<T>(taskId: string, fn: () => T): T;
50
- getBudgetStats(): {
51
- budget: number;
52
- used: number;
53
- remaining: number;
54
- utilization: number;
55
- };
56
- }
57
- export default TokenOptimizer;
58
- //# sourceMappingURL=token-optimizer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"token-optimizer.d.ts","sourceRoot":"","sources":["../../src/core/token-optimizer.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAmDtC,MAAM,WAAW,uBAAuB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,WAAW,EAAE,wBAAwB,CAAC;IAC/C,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,4BAA4B,EAAE,mBAAmB,CAAC;IAC3D,QAAQ,CAAC,iBAAiB,EAAE,IAAI,CAAC;CACjC;AAED,wBAAgB,8BAA8B,IAAI,2BAA2B,CAQ5E;AAYD,qBAAa,kBAAmB,SAAQ,YAAY;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAYnE;CACD;AAMD,qBAAa,YAAa,SAAQ,YAAY;IAC7C,OAAO,CAAC,SAAS,CAAmC;IAEpD,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,KAAK,UAAQ,GAAG,CAAC,CAOxD;IAED,KAAK,IAAI,IAAI,CAEZ;CACD;AAMD,qBAAa,cAAe,SAAQ,YAAY;IAC/C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,OAAO,CAA6C;IAE5D,YAAY,aAAa,SAAQ,EAGhC;IAED,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQhC;IAED,QAAQ,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAOnF;IAED,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAGpC;CACD;AAMD,qBAAa,cAAe,SAAQ,YAAY;IAC/C,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,MAAM,CAAiB;IAE/B,YAAY,MAAM,SAAQ,EAKzB;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB,CAkB/C;IAED,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE7C;IAED,cAAc,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAEzF;CACD;AAED,eAAe,cAAc,CAAC","sourcesContent":["// packages/coding-agent/src/core/token-optimizer.ts\n// ===========================================\n//\n// @deprecated 이 모듈은 현재 코드베이스 어디에서도 import되지 않는 dead code입니다.\n// 어떤 파일도 이 모듈의 클래스를 직접 사용하지 않습니다.\n// 향후 토큰 최적화가 필요하면 headroom/global-context-compressor를 사용하세요.\n//\n// LosslessCompressor 계약:\n// compress() 출력은 의미적으로 원본과 동일해야 합니다.\n// - 문장 내 단어를 제거/대체/재배치하지 않습니다 (중복 단어 포함).\n// - 연속 공백/탭/줄바꿈 정규화만 수행합니다 (의미 불변).\n// - tokensSaved는 실제 토큰 수 차이를 보고합니다 (과대 계산 금지).\n//\n// v2.0 변경사항:\n// - [fix] Result deduplication 로직 제거 (중복 단어 제거 → 의미 파괴 버그)\n// - [fix] abbreviationMap 제거 (문맥 의존적 축약은 손실/lossy)\n// - [fix] templateCache 제거 (32비트 해시 충돌 시 잘못된 압축 반환)\n// - [fix] tokensSaved를 estimateTokens() 기반으로 정확화\n// - [fix] tokensSaved가 음수가 될 수 없음 보장\n// - compress()는 whitespace 정규화만 수행 (진정한 lossless)\n\nimport { EventEmitter } from \"events\";\n\n// ---------------------------------------------------------------------------\n// 토큰 추정 — BPE 토크나이저 근사\n// ---------------------------------------------------------------------------\n// OpenAI BPE 토크나이저의 동작을 근사:\n// - 일반 영어 단어(빈도 높음)는 대개 1 토큰\n// - 긴/드문 단어는 1 + ceil((len - 1) / 4) 토큰으로 분할\n// - 구두점/특수문자는 보통 각각 1 토큰\n// - 공백 문자는 단어 접두사로 병합되므로 별도 토큰이 아님\n// - CJK 문자는 보통 1자 = 1~2 토큰\n\nfunction estimateTokens(text: string): number {\n\tif (text.length === 0) return 0;\n\n\tlet tokens = 0;\n\t// 공백으로 분할 — 각 청크를 개별적으로 추정\n\tconst chunks = text.split(/(\\s+)/);\n\n\tfor (const chunk of chunks) {\n\t\tif (chunk.length === 0) continue;\n\t\tif (/^\\s+$/.test(chunk)) {\n\t\t\t// 공백 문자열 — BPE에서 단어 접두사로 병합됨, 토큰 0\n\t\t\tcontinue;\n\t\t}\n\n\t\t// CJK 문자 분리 (유니코드 범위: 한글, 한자, 가타나)\n\t\tconst cjkChars = chunk.match(/[\\u3000-\\u9fff\\uf900-\\ufaff]/g);\n\t\tif (cjkChars) {\n\t\t\t// CJK: 1자 ≈ 1.5 토큰 (평균)\n\t\t\ttokens += Math.ceil(cjkChars.length * 1.5);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// 영어 단어/숫자/구두점 청크\n\t\tif (chunk.length <= 6) {\n\t\t\t// 짧은 단어(빈도 높음): 대개 단일 토큰\n\t\t\ttokens += 1;\n\t\t} else {\n\t\t\t// 긴 단어: BPE가 subword로 분할 → 1 + 분할 조각 수\n\t\t\ttokens += 1 + Math.ceil((chunk.length - 1) / 4);\n\t\t}\n\t}\n\n\treturn tokens;\n}\n\n// ---------------------------------------------------------------------------\n// 인터페이스 (역호환)\n// ---------------------------------------------------------------------------\n\nexport interface TokenOptimizationResult {\n\toriginalQuery: string;\n\toptimizedQuery: string;\n\ttokensSaved: number;\n\ttechnique: string;\n\tcacheHit: boolean;\n\tbudgetExceeded: boolean;\n}\n\nexport interface TokenOptimizerRuntimeStatus {\n\treadonly optimizerId: \"legacy-token-optimizer\";\n\treadonly status: \"quarantined_compatibility\";\n\treadonly active: false;\n\treadonly activeContextBudgetOptimizer: \"context-budget-v2\";\n\treadonly compatibilityOnly: true;\n}\n\nexport function getTokenOptimizerRuntimeStatus(): TokenOptimizerRuntimeStatus {\n\treturn {\n\t\toptimizerId: \"legacy-token-optimizer\",\n\t\tstatus: \"quarantined_compatibility\",\n\t\tactive: false,\n\t\tactiveContextBudgetOptimizer: \"context-budget-v2\",\n\t\tcompatibilityOnly: true,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// LosslessCompressor — 진정한 무손실 압축\n// ---------------------------------------------------------------------------\n// 압축 후 역압축 시 원본 복원 가능(의미 100% 보존).\n// 수행하는 변환:\n// 1. 연속 공백/탭 → 단일 공백\n// 2. 앞뒤 공백 제거(trim)\n//\n// 이 두 변환만 수행합니다. 어떤 단어도 제거/대체하지 않습니다.\n\nexport class LosslessCompressor extends EventEmitter {\n\tcompress(query: string): { compressed: string; tokensSaved: number } {\n\t\tconst originalTokens = estimateTokens(query);\n\n\t\t// 1. 연속 공백/탭 → 단일 공백\n\t\t// 2. trim\n\t\tconst compressed = query.replace(/[ \\t]+/g, \" \").trim();\n\n\t\tconst compressedTokens = estimateTokens(compressed);\n\t\t// tokensSaved는 0 이상 — 정규화가 토큰을 줄이지 않으면 0\n\t\tconst tokensSaved = Math.max(0, originalTokens - compressedTokens);\n\n\t\treturn { compressed, tokensSaved };\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// LazyExecutor — 메모이제이션 실행기 (역호환)\n// ---------------------------------------------------------------------------\n\nexport class LazyExecutor extends EventEmitter {\n\tprivate memoCache: Map<string, unknown> = new Map();\n\n\texecute<T>(taskId: string, fn: () => T, force = false): T {\n\t\tif (!force && this.memoCache.has(taskId)) {\n\t\t\treturn this.memoCache.get(taskId) as T;\n\t\t}\n\t\tconst result = fn();\n\t\tthis.memoCache.set(taskId, result);\n\t\treturn result;\n\t}\n\n\tclear(): void {\n\t\tthis.memoCache.clear();\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// AdaptiveBudget — 토큰 예산 관리 (역호환)\n// ---------------------------------------------------------------------------\n\nexport class AdaptiveBudget extends EventEmitter {\n\tprivate budget: number;\n\tprivate used: number = 0;\n\tprivate history: { used: number; timestamp: number }[] = [];\n\n\tconstructor(initialBudget = 10000) {\n\t\tsuper();\n\t\tthis.budget = initialBudget;\n\t}\n\n\tallocate(tokens: number): boolean {\n\t\tif (this.used + tokens > this.budget) {\n\t\t\tthis.emit(\"budgetExceeded\", { used: this.used, requested: tokens, budget: this.budget });\n\t\t\treturn false;\n\t\t}\n\t\tthis.used += tokens;\n\t\tthis.history.push({ used: this.used, timestamp: Date.now() });\n\t\treturn true;\n\t}\n\n\tgetStats(): { budget: number; used: number; remaining: number; utilization: number } {\n\t\treturn {\n\t\t\tbudget: this.budget,\n\t\t\tused: this.used,\n\t\t\tremaining: this.budget - this.used,\n\t\t\tutilization: this.used / this.budget,\n\t\t};\n\t}\n\n\tadjustBudget(newBudget: number): void {\n\t\tthis.budget = newBudget;\n\t\tthis.emit(\"budgetAdjusted\", { newBudget });\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// TokenOptimizer — 통합 인터페이스 (역호환)\n// ---------------------------------------------------------------------------\n\nexport class TokenOptimizer extends EventEmitter {\n\tprivate compressor: LosslessCompressor;\n\tprivate executor: LazyExecutor;\n\tprivate budget: AdaptiveBudget;\n\n\tconstructor(budget = 10000) {\n\t\tsuper();\n\t\tthis.compressor = new LosslessCompressor();\n\t\tthis.executor = new LazyExecutor();\n\t\tthis.budget = new AdaptiveBudget(budget);\n\t}\n\n\toptimize(query: string): TokenOptimizationResult {\n\t\tconst originalTokens = estimateTokens(query);\n\n\t\tconst { compressed } = this.compressor.compress(query);\n\t\tconst optimizedTokens = estimateTokens(compressed);\n\n\t\tconst cacheHit = false; // templateCache 제거됨 — 항상 false\n\n\t\tconst budgetAllocated = this.budget.allocate(optimizedTokens);\n\n\t\treturn {\n\t\t\toriginalQuery: query,\n\t\t\toptimizedQuery: compressed,\n\t\t\ttokensSaved: Math.max(0, originalTokens - optimizedTokens),\n\t\t\ttechnique: \"whitespace_normalization\",\n\t\t\tcacheHit,\n\t\t\tbudgetExceeded: !budgetAllocated,\n\t\t};\n\t}\n\n\tlazyExecute<T>(taskId: string, fn: () => T): T {\n\t\treturn this.executor.execute(taskId, fn);\n\t}\n\n\tgetBudgetStats(): { budget: number; used: number; remaining: number; utilization: number } {\n\t\treturn this.budget.getStats();\n\t}\n}\n\nexport default TokenOptimizer;\n"]}
@@ -1,179 +0,0 @@
1
- // packages/coding-agent/src/core/token-optimizer.ts
2
- // ===========================================
3
- //
4
- // @deprecated 이 모듈은 현재 코드베이스 어디에서도 import되지 않는 dead code입니다.
5
- // 어떤 파일도 이 모듈의 클래스를 직접 사용하지 않습니다.
6
- // 향후 토큰 최적화가 필요하면 headroom/global-context-compressor를 사용하세요.
7
- //
8
- // LosslessCompressor 계약:
9
- // compress() 출력은 의미적으로 원본과 동일해야 합니다.
10
- // - 문장 내 단어를 제거/대체/재배치하지 않습니다 (중복 단어 포함).
11
- // - 연속 공백/탭/줄바꿈 정규화만 수행합니다 (의미 불변).
12
- // - tokensSaved는 실제 토큰 수 차이를 보고합니다 (과대 계산 금지).
13
- //
14
- // v2.0 변경사항:
15
- // - [fix] Result deduplication 로직 제거 (중복 단어 제거 → 의미 파괴 버그)
16
- // - [fix] abbreviationMap 제거 (문맥 의존적 축약은 손실/lossy)
17
- // - [fix] templateCache 제거 (32비트 해시 충돌 시 잘못된 압축 반환)
18
- // - [fix] tokensSaved를 estimateTokens() 기반으로 정확화
19
- // - [fix] tokensSaved가 음수가 될 수 없음 보장
20
- // - compress()는 whitespace 정규화만 수행 (진정한 lossless)
21
- import { EventEmitter } from "events";
22
- // ---------------------------------------------------------------------------
23
- // 토큰 추정 — BPE 토크나이저 근사
24
- // ---------------------------------------------------------------------------
25
- // OpenAI BPE 토크나이저의 동작을 근사:
26
- // - 일반 영어 단어(빈도 높음)는 대개 1 토큰
27
- // - 긴/드문 단어는 1 + ceil((len - 1) / 4) 토큰으로 분할
28
- // - 구두점/특수문자는 보통 각각 1 토큰
29
- // - 공백 문자는 단어 접두사로 병합되므로 별도 토큰이 아님
30
- // - CJK 문자는 보통 1자 = 1~2 토큰
31
- function estimateTokens(text) {
32
- if (text.length === 0)
33
- return 0;
34
- let tokens = 0;
35
- // 공백으로 분할 — 각 청크를 개별적으로 추정
36
- const chunks = text.split(/(\s+)/);
37
- for (const chunk of chunks) {
38
- if (chunk.length === 0)
39
- continue;
40
- if (/^\s+$/.test(chunk)) {
41
- // 공백 문자열 — BPE에서 단어 접두사로 병합됨, 토큰 0
42
- continue;
43
- }
44
- // CJK 문자 분리 (유니코드 범위: 한글, 한자, 가타나)
45
- const cjkChars = chunk.match(/[\u3000-\u9fff\uf900-\ufaff]/g);
46
- if (cjkChars) {
47
- // CJK: 1자 ≈ 1.5 토큰 (평균)
48
- tokens += Math.ceil(cjkChars.length * 1.5);
49
- continue;
50
- }
51
- // 영어 단어/숫자/구두점 청크
52
- if (chunk.length <= 6) {
53
- // 짧은 단어(빈도 높음): 대개 단일 토큰
54
- tokens += 1;
55
- }
56
- else {
57
- // 긴 단어: BPE가 subword로 분할 → 1 + 분할 조각 수
58
- tokens += 1 + Math.ceil((chunk.length - 1) / 4);
59
- }
60
- }
61
- return tokens;
62
- }
63
- export function getTokenOptimizerRuntimeStatus() {
64
- return {
65
- optimizerId: "legacy-token-optimizer",
66
- status: "quarantined_compatibility",
67
- active: false,
68
- activeContextBudgetOptimizer: "context-budget-v2",
69
- compatibilityOnly: true,
70
- };
71
- }
72
- // ---------------------------------------------------------------------------
73
- // LosslessCompressor — 진정한 무손실 압축
74
- // ---------------------------------------------------------------------------
75
- // 압축 후 역압축 시 원본 복원 가능(의미 100% 보존).
76
- // 수행하는 변환:
77
- // 1. 연속 공백/탭 → 단일 공백
78
- // 2. 앞뒤 공백 제거(trim)
79
- //
80
- // 이 두 변환만 수행합니다. 어떤 단어도 제거/대체하지 않습니다.
81
- export class LosslessCompressor extends EventEmitter {
82
- compress(query) {
83
- const originalTokens = estimateTokens(query);
84
- // 1. 연속 공백/탭 → 단일 공백
85
- // 2. trim
86
- const compressed = query.replace(/[ \t]+/g, " ").trim();
87
- const compressedTokens = estimateTokens(compressed);
88
- // tokensSaved는 0 이상 — 정규화가 토큰을 줄이지 않으면 0
89
- const tokensSaved = Math.max(0, originalTokens - compressedTokens);
90
- return { compressed, tokensSaved };
91
- }
92
- }
93
- // ---------------------------------------------------------------------------
94
- // LazyExecutor — 메모이제이션 실행기 (역호환)
95
- // ---------------------------------------------------------------------------
96
- export class LazyExecutor extends EventEmitter {
97
- memoCache = new Map();
98
- execute(taskId, fn, force = false) {
99
- if (!force && this.memoCache.has(taskId)) {
100
- return this.memoCache.get(taskId);
101
- }
102
- const result = fn();
103
- this.memoCache.set(taskId, result);
104
- return result;
105
- }
106
- clear() {
107
- this.memoCache.clear();
108
- }
109
- }
110
- // ---------------------------------------------------------------------------
111
- // AdaptiveBudget — 토큰 예산 관리 (역호환)
112
- // ---------------------------------------------------------------------------
113
- export class AdaptiveBudget extends EventEmitter {
114
- budget;
115
- used = 0;
116
- history = [];
117
- constructor(initialBudget = 10000) {
118
- super();
119
- this.budget = initialBudget;
120
- }
121
- allocate(tokens) {
122
- if (this.used + tokens > this.budget) {
123
- this.emit("budgetExceeded", { used: this.used, requested: tokens, budget: this.budget });
124
- return false;
125
- }
126
- this.used += tokens;
127
- this.history.push({ used: this.used, timestamp: Date.now() });
128
- return true;
129
- }
130
- getStats() {
131
- return {
132
- budget: this.budget,
133
- used: this.used,
134
- remaining: this.budget - this.used,
135
- utilization: this.used / this.budget,
136
- };
137
- }
138
- adjustBudget(newBudget) {
139
- this.budget = newBudget;
140
- this.emit("budgetAdjusted", { newBudget });
141
- }
142
- }
143
- // ---------------------------------------------------------------------------
144
- // TokenOptimizer — 통합 인터페이스 (역호환)
145
- // ---------------------------------------------------------------------------
146
- export class TokenOptimizer extends EventEmitter {
147
- compressor;
148
- executor;
149
- budget;
150
- constructor(budget = 10000) {
151
- super();
152
- this.compressor = new LosslessCompressor();
153
- this.executor = new LazyExecutor();
154
- this.budget = new AdaptiveBudget(budget);
155
- }
156
- optimize(query) {
157
- const originalTokens = estimateTokens(query);
158
- const { compressed } = this.compressor.compress(query);
159
- const optimizedTokens = estimateTokens(compressed);
160
- const cacheHit = false; // templateCache 제거됨 — 항상 false
161
- const budgetAllocated = this.budget.allocate(optimizedTokens);
162
- return {
163
- originalQuery: query,
164
- optimizedQuery: compressed,
165
- tokensSaved: Math.max(0, originalTokens - optimizedTokens),
166
- technique: "whitespace_normalization",
167
- cacheHit,
168
- budgetExceeded: !budgetAllocated,
169
- };
170
- }
171
- lazyExecute(taskId, fn) {
172
- return this.executor.execute(taskId, fn);
173
- }
174
- getBudgetStats() {
175
- return this.budget.getStats();
176
- }
177
- }
178
- export default TokenOptimizer;
179
- //# sourceMappingURL=token-optimizer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"token-optimizer.js","sourceRoot":"","sources":["../../src/core/token-optimizer.ts"],"names":[],"mappings":"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","sourcesContent":["// packages/coding-agent/src/core/token-optimizer.ts\n// ===========================================\n//\n// @deprecated 이 모듈은 현재 코드베이스 어디에서도 import되지 않는 dead code입니다.\n// 어떤 파일도 이 모듈의 클래스를 직접 사용하지 않습니다.\n// 향후 토큰 최적화가 필요하면 headroom/global-context-compressor를 사용하세요.\n//\n// LosslessCompressor 계약:\n// compress() 출력은 의미적으로 원본과 동일해야 합니다.\n// - 문장 내 단어를 제거/대체/재배치하지 않습니다 (중복 단어 포함).\n// - 연속 공백/탭/줄바꿈 정규화만 수행합니다 (의미 불변).\n// - tokensSaved는 실제 토큰 수 차이를 보고합니다 (과대 계산 금지).\n//\n// v2.0 변경사항:\n// - [fix] Result deduplication 로직 제거 (중복 단어 제거 → 의미 파괴 버그)\n// - [fix] abbreviationMap 제거 (문맥 의존적 축약은 손실/lossy)\n// - [fix] templateCache 제거 (32비트 해시 충돌 시 잘못된 압축 반환)\n// - [fix] tokensSaved를 estimateTokens() 기반으로 정확화\n// - [fix] tokensSaved가 음수가 될 수 없음 보장\n// - compress()는 whitespace 정규화만 수행 (진정한 lossless)\n\nimport { EventEmitter } from \"events\";\n\n// ---------------------------------------------------------------------------\n// 토큰 추정 — BPE 토크나이저 근사\n// ---------------------------------------------------------------------------\n// OpenAI BPE 토크나이저의 동작을 근사:\n// - 일반 영어 단어(빈도 높음)는 대개 1 토큰\n// - 긴/드문 단어는 1 + ceil((len - 1) / 4) 토큰으로 분할\n// - 구두점/특수문자는 보통 각각 1 토큰\n// - 공백 문자는 단어 접두사로 병합되므로 별도 토큰이 아님\n// - CJK 문자는 보통 1자 = 1~2 토큰\n\nfunction estimateTokens(text: string): number {\n\tif (text.length === 0) return 0;\n\n\tlet tokens = 0;\n\t// 공백으로 분할 — 각 청크를 개별적으로 추정\n\tconst chunks = text.split(/(\\s+)/);\n\n\tfor (const chunk of chunks) {\n\t\tif (chunk.length === 0) continue;\n\t\tif (/^\\s+$/.test(chunk)) {\n\t\t\t// 공백 문자열 — BPE에서 단어 접두사로 병합됨, 토큰 0\n\t\t\tcontinue;\n\t\t}\n\n\t\t// CJK 문자 분리 (유니코드 범위: 한글, 한자, 가타나)\n\t\tconst cjkChars = chunk.match(/[\\u3000-\\u9fff\\uf900-\\ufaff]/g);\n\t\tif (cjkChars) {\n\t\t\t// CJK: 1자 ≈ 1.5 토큰 (평균)\n\t\t\ttokens += Math.ceil(cjkChars.length * 1.5);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// 영어 단어/숫자/구두점 청크\n\t\tif (chunk.length <= 6) {\n\t\t\t// 짧은 단어(빈도 높음): 대개 단일 토큰\n\t\t\ttokens += 1;\n\t\t} else {\n\t\t\t// 긴 단어: BPE가 subword로 분할 → 1 + 분할 조각 수\n\t\t\ttokens += 1 + Math.ceil((chunk.length - 1) / 4);\n\t\t}\n\t}\n\n\treturn tokens;\n}\n\n// ---------------------------------------------------------------------------\n// 인터페이스 (역호환)\n// ---------------------------------------------------------------------------\n\nexport interface TokenOptimizationResult {\n\toriginalQuery: string;\n\toptimizedQuery: string;\n\ttokensSaved: number;\n\ttechnique: string;\n\tcacheHit: boolean;\n\tbudgetExceeded: boolean;\n}\n\nexport interface TokenOptimizerRuntimeStatus {\n\treadonly optimizerId: \"legacy-token-optimizer\";\n\treadonly status: \"quarantined_compatibility\";\n\treadonly active: false;\n\treadonly activeContextBudgetOptimizer: \"context-budget-v2\";\n\treadonly compatibilityOnly: true;\n}\n\nexport function getTokenOptimizerRuntimeStatus(): TokenOptimizerRuntimeStatus {\n\treturn {\n\t\toptimizerId: \"legacy-token-optimizer\",\n\t\tstatus: \"quarantined_compatibility\",\n\t\tactive: false,\n\t\tactiveContextBudgetOptimizer: \"context-budget-v2\",\n\t\tcompatibilityOnly: true,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// LosslessCompressor — 진정한 무손실 압축\n// ---------------------------------------------------------------------------\n// 압축 후 역압축 시 원본 복원 가능(의미 100% 보존).\n// 수행하는 변환:\n// 1. 연속 공백/탭 → 단일 공백\n// 2. 앞뒤 공백 제거(trim)\n//\n// 이 두 변환만 수행합니다. 어떤 단어도 제거/대체하지 않습니다.\n\nexport class LosslessCompressor extends EventEmitter {\n\tcompress(query: string): { compressed: string; tokensSaved: number } {\n\t\tconst originalTokens = estimateTokens(query);\n\n\t\t// 1. 연속 공백/탭 → 단일 공백\n\t\t// 2. trim\n\t\tconst compressed = query.replace(/[ \\t]+/g, \" \").trim();\n\n\t\tconst compressedTokens = estimateTokens(compressed);\n\t\t// tokensSaved는 0 이상 — 정규화가 토큰을 줄이지 않으면 0\n\t\tconst tokensSaved = Math.max(0, originalTokens - compressedTokens);\n\n\t\treturn { compressed, tokensSaved };\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// LazyExecutor — 메모이제이션 실행기 (역호환)\n// ---------------------------------------------------------------------------\n\nexport class LazyExecutor extends EventEmitter {\n\tprivate memoCache: Map<string, unknown> = new Map();\n\n\texecute<T>(taskId: string, fn: () => T, force = false): T {\n\t\tif (!force && this.memoCache.has(taskId)) {\n\t\t\treturn this.memoCache.get(taskId) as T;\n\t\t}\n\t\tconst result = fn();\n\t\tthis.memoCache.set(taskId, result);\n\t\treturn result;\n\t}\n\n\tclear(): void {\n\t\tthis.memoCache.clear();\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// AdaptiveBudget — 토큰 예산 관리 (역호환)\n// ---------------------------------------------------------------------------\n\nexport class AdaptiveBudget extends EventEmitter {\n\tprivate budget: number;\n\tprivate used: number = 0;\n\tprivate history: { used: number; timestamp: number }[] = [];\n\n\tconstructor(initialBudget = 10000) {\n\t\tsuper();\n\t\tthis.budget = initialBudget;\n\t}\n\n\tallocate(tokens: number): boolean {\n\t\tif (this.used + tokens > this.budget) {\n\t\t\tthis.emit(\"budgetExceeded\", { used: this.used, requested: tokens, budget: this.budget });\n\t\t\treturn false;\n\t\t}\n\t\tthis.used += tokens;\n\t\tthis.history.push({ used: this.used, timestamp: Date.now() });\n\t\treturn true;\n\t}\n\n\tgetStats(): { budget: number; used: number; remaining: number; utilization: number } {\n\t\treturn {\n\t\t\tbudget: this.budget,\n\t\t\tused: this.used,\n\t\t\tremaining: this.budget - this.used,\n\t\t\tutilization: this.used / this.budget,\n\t\t};\n\t}\n\n\tadjustBudget(newBudget: number): void {\n\t\tthis.budget = newBudget;\n\t\tthis.emit(\"budgetAdjusted\", { newBudget });\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// TokenOptimizer — 통합 인터페이스 (역호환)\n// ---------------------------------------------------------------------------\n\nexport class TokenOptimizer extends EventEmitter {\n\tprivate compressor: LosslessCompressor;\n\tprivate executor: LazyExecutor;\n\tprivate budget: AdaptiveBudget;\n\n\tconstructor(budget = 10000) {\n\t\tsuper();\n\t\tthis.compressor = new LosslessCompressor();\n\t\tthis.executor = new LazyExecutor();\n\t\tthis.budget = new AdaptiveBudget(budget);\n\t}\n\n\toptimize(query: string): TokenOptimizationResult {\n\t\tconst originalTokens = estimateTokens(query);\n\n\t\tconst { compressed } = this.compressor.compress(query);\n\t\tconst optimizedTokens = estimateTokens(compressed);\n\n\t\tconst cacheHit = false; // templateCache 제거됨 — 항상 false\n\n\t\tconst budgetAllocated = this.budget.allocate(optimizedTokens);\n\n\t\treturn {\n\t\t\toriginalQuery: query,\n\t\t\toptimizedQuery: compressed,\n\t\t\ttokensSaved: Math.max(0, originalTokens - optimizedTokens),\n\t\t\ttechnique: \"whitespace_normalization\",\n\t\t\tcacheHit,\n\t\t\tbudgetExceeded: !budgetAllocated,\n\t\t};\n\t}\n\n\tlazyExecute<T>(taskId: string, fn: () => T): T {\n\t\treturn this.executor.execute(taskId, fn);\n\t}\n\n\tgetBudgetStats(): { budget: number; used: number; remaining: number; utilization: number } {\n\t\treturn this.budget.getStats();\n\t}\n}\n\nexport default TokenOptimizer;\n"]}