@theokit/sdk-tools 0.9.1 → 0.11.0

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
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - SE38 (#119) — `createTodolistTool()` is now session-aware: it scopes its items by the
8
+ run's `ctx.threadId`, so one tool object served to many sessions from a single process
9
+ (the multi-tenant server shape) no longer leaks one session's list into another. When no
10
+ `threadId` is present (single-session CLI usage) every call shares one default session, so
11
+ existing behavior is unchanged. `handler` accepts an optional 2nd `ctx` argument and
12
+ `getItems(threadId?)` is session-scoped — both additive/back-compatible.
13
+
14
+ ## 0.10.0
15
+
16
+ ### Minor Changes
17
+
18
+ - 2606c98: SE37 — Reasoning ergonomics. Ships `ReasoningTools.create()` (`think`/`analyze` scratchpad tools, from `@theokit/sdk` core, re-exported by `@theokit/sdk-tools`) and a lightweight `AgentOptions.reasoning?: boolean` flag. When `reasoning: true`, the agent gets a chain-of-thought preamble prepended to its system prompt AND the reasoning tools auto-attached, turning a non-reasoning model into a reason→act→observe loop using the SAME model (reuses the existing tool loop; no new runtime). Inert (with a one-time warn) when a native reasoning model is configured (`model.params: [{ id: "thinking" }]`) — native reasoning wins, no double-reasoning. Default off; byte-identical behaviour when unset. Validated REAL on OpenRouter: `reasoning: true` drove the `think` tool and answered the "9.11 vs 9.9" trap correctly (9.9).
19
+
3
20
  ## 0.9.1
4
21
 
5
22
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -1435,6 +1435,37 @@ function evaluateReadBeforeWrite(tracker, path, currentMtimeMs) {
1435
1435
  if (recorded !== currentMtimeMs) return "stale";
1436
1436
  return "ok";
1437
1437
  }
1438
+ var ReasoningTools = class {
1439
+ constructor() {
1440
+ }
1441
+ /** Build the tools. Pass `{ analyze: false }` for `think` only. */
1442
+ static create(opts) {
1443
+ const think = sdk.Tool.create({
1444
+ name: "think",
1445
+ description: "Use this as a scratchpad to think step by step BEFORE answering or acting. Write out your reasoning for one step. Nothing else happens \u2014 it is only your private reasoning space. Call it as many times as you need before the final answer.",
1446
+ inputSchema: zod.z.object({
1447
+ thought: zod.z.string().min(1, "think: `thought` must be a non-empty string.")
1448
+ }),
1449
+ handler: ({ thought }) => thought
1450
+ });
1451
+ if (opts?.analyze === false) return [think];
1452
+ const analyze = sdk.Tool.create({
1453
+ name: "analyze",
1454
+ description: "Analyze the result of a previous step or tool call. State what you looked at, your analysis, and whether to `continue` reasoning, `validate` (double-check) your work, or give the `final_answer`. Use this to catch your own mistakes before answering.",
1455
+ inputSchema: zod.z.object({
1456
+ title: zod.z.string().optional(),
1457
+ result: zod.z.string().min(1, "analyze: `result` must describe what you are analyzing."),
1458
+ analysis: zod.z.string().min(1, "analyze: `analysis` must contain your reasoning."),
1459
+ next_action: zod.z.enum(["continue", "validate", "final_answer"])
1460
+ }),
1461
+ handler: ({ title, result, analysis, next_action }) => `${title ? `# ${title}
1462
+ ` : ""}Result: ${result}
1463
+ Analysis: ${analysis}
1464
+ Next: ${next_action}`
1465
+ });
1466
+ return [think, analyze];
1467
+ }
1468
+ };
1438
1469
  var DEFAULT_TIMEOUT_MS2 = 12e4;
1439
1470
  var DEFAULT_MAX_STDOUT_BYTES2 = 10 * 1024 * 1024;
1440
1471
  function createRunVitestTool(opts) {
@@ -1772,7 +1803,7 @@ function requireId(input) {
1772
1803
  if (!("id" in input) || !input.id) return null;
1773
1804
  return input.id;
1774
1805
  }
1775
- function createTodolistTool() {
1806
+ function makeSessionOps() {
1776
1807
  const items = [];
1777
1808
  let nextId = 1;
1778
1809
  function genId() {
@@ -1841,6 +1872,26 @@ ${done}/${items.length} done | ${inProg} in progress | ${pending} pending`);
1841
1872
  list: () => listResult({}),
1842
1873
  clear_completed: handleClearCompleted
1843
1874
  };
1875
+ return {
1876
+ handle: (input) => {
1877
+ const action = actions[input.action];
1878
+ if (!action) return fail({ error: "invalid_action" });
1879
+ return action(input);
1880
+ },
1881
+ getItems: () => [...items]
1882
+ };
1883
+ }
1884
+ function createTodolistTool() {
1885
+ const sessions = /* @__PURE__ */ new Map();
1886
+ function ops(threadId) {
1887
+ const key = threadId ?? "__default__";
1888
+ let session = sessions.get(key);
1889
+ if (session === void 0) {
1890
+ session = makeSessionOps();
1891
+ sessions.set(key, session);
1892
+ }
1893
+ return session;
1894
+ }
1844
1895
  return {
1845
1896
  name: "todolist",
1846
1897
  description: "Create and maintain a structured task list for the current session \u2014 tracks progress and keeps a multi-step plan visible across turns. Use it proactively when the work has 3+ steps or the user gave multiple tasks; skip it for a single trivial step. Keep exactly ONE item 'in_progress' at a time, and mark 'complete' only after the work is actually done. Actions: 'add' (create with title), 'in_progress' (mark started by id), 'complete' (mark done by id), 'remove' (delete by id), 'list' (show all), 'clear_completed' (remove done items). Returns { ok, items, items_summary } (items = structured array; items_summary = formatted text).",
@@ -1863,12 +1914,8 @@ ${done}/${items.length} done | ${inProg} in progress | ${pending} pending`);
1863
1914
  },
1864
1915
  required: ["action"]
1865
1916
  },
1866
- handler: (input) => {
1867
- const action = actions[input.action];
1868
- if (!action) return fail({ error: "invalid_action" });
1869
- return action(input);
1870
- },
1871
- getItems: () => [...items]
1917
+ handler: (input, ctx) => ops(ctx?.threadId).handle(input),
1918
+ getItems: (threadId) => ops(threadId).getItems()
1872
1919
  };
1873
1920
  }
1874
1921
  function truncateOutput(output, opts) {
@@ -2197,6 +2244,7 @@ async function isBinaryFile(absolutePath) {
2197
2244
  exports.CatastrophicCommandError = CatastrophicCommandError;
2198
2245
  exports.DEFAULT_TOOL_GUIDANCE = DEFAULT_TOOL_GUIDANCE;
2199
2246
  exports.ReadTracker = ReadTracker;
2247
+ exports.ReasoningTools = ReasoningTools;
2200
2248
  exports.RedirectBlockedError = RedirectBlockedError;
2201
2249
  exports.SsrfBlockedError = SsrfBlockedError;
2202
2250
  exports.buildEnvContext = buildEnvContext;