reasonix 0.12.8 → 0.12.13

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/index.d.ts CHANGED
@@ -491,11 +491,28 @@ interface ImmutablePrefixOptions {
491
491
  }
492
492
  declare class ImmutablePrefix {
493
493
  readonly system: string;
494
- readonly toolSpecs: readonly ToolSpec[];
494
+ /**
495
+ * Backing array for `toolSpecs`. Originally `Object.freeze`d at
496
+ * construction (hence the class name) — but `addTool` now lets the
497
+ * dashboard register `semantic_search` after a mid-session
498
+ * `reasonix index` build without forcing the user to restart. Each
499
+ * add is documented to cost one cache-miss turn (the cached prefix
500
+ * on DeepSeek's side is keyed by the full tool list); subsequent
501
+ * turns re-cache against the new shape.
502
+ */
503
+ private _toolSpecs;
495
504
  readonly fewShots: readonly ChatMessage[];
496
505
  constructor(opts: ImmutablePrefixOptions);
506
+ get toolSpecs(): readonly ToolSpec[];
497
507
  toMessages(): ChatMessage[];
498
508
  tools(): ToolSpec[];
509
+ /**
510
+ * Add a tool spec to the prefix. Returns `true` if added, `false`
511
+ * if a tool with the same name was already present (callers can
512
+ * decide whether to ignore or surface the no-op). The model picks
513
+ * up the new tool on the next turn after the cache busts once.
514
+ */
515
+ addTool(spec: ToolSpec): boolean;
499
516
  get fingerprint(): string;
500
517
  }
501
518
  declare class AppendOnlyLog {
package/dist/index.js CHANGED
@@ -1157,23 +1157,48 @@ function blockToString(block) {
1157
1157
  import { createHash } from "crypto";
1158
1158
  var ImmutablePrefix = class {
1159
1159
  system;
1160
- toolSpecs;
1160
+ /**
1161
+ * Backing array for `toolSpecs`. Originally `Object.freeze`d at
1162
+ * construction (hence the class name) — but `addTool` now lets the
1163
+ * dashboard register `semantic_search` after a mid-session
1164
+ * `reasonix index` build without forcing the user to restart. Each
1165
+ * add is documented to cost one cache-miss turn (the cached prefix
1166
+ * on DeepSeek's side is keyed by the full tool list); subsequent
1167
+ * turns re-cache against the new shape.
1168
+ */
1169
+ _toolSpecs;
1161
1170
  fewShots;
1162
1171
  constructor(opts) {
1163
1172
  this.system = opts.system;
1164
- this.toolSpecs = Object.freeze([...opts.toolSpecs ?? []]);
1173
+ this._toolSpecs = [...opts.toolSpecs ?? []];
1165
1174
  this.fewShots = Object.freeze([...opts.fewShots ?? []]);
1166
1175
  }
1176
+ get toolSpecs() {
1177
+ return this._toolSpecs;
1178
+ }
1167
1179
  toMessages() {
1168
1180
  return [{ role: "system", content: this.system }, ...this.fewShots.map((m) => ({ ...m }))];
1169
1181
  }
1170
1182
  tools() {
1171
- return this.toolSpecs.map((t) => structuredClone(t));
1183
+ return this._toolSpecs.map((t) => structuredClone(t));
1184
+ }
1185
+ /**
1186
+ * Add a tool spec to the prefix. Returns `true` if added, `false`
1187
+ * if a tool with the same name was already present (callers can
1188
+ * decide whether to ignore or surface the no-op). The model picks
1189
+ * up the new tool on the next turn after the cache busts once.
1190
+ */
1191
+ addTool(spec) {
1192
+ const name = spec.function?.name;
1193
+ if (!name) return false;
1194
+ if (this._toolSpecs.some((t) => t.function?.name === name)) return false;
1195
+ this._toolSpecs.push(spec);
1196
+ return true;
1172
1197
  }
1173
1198
  get fingerprint() {
1174
1199
  const blob = JSON.stringify({
1175
1200
  system: this.system,
1176
- tools: this.toolSpecs,
1201
+ tools: this._toolSpecs,
1177
1202
  shots: this.fewShots
1178
1203
  });
1179
1204
  return createHash("sha256").update(blob).digest("hex").slice(0, 16);