@theokit/sdk 2.18.1 → 2.19.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.
@@ -34,6 +34,17 @@ export interface GenerateObjectOptions<T extends ZodType> {
34
34
  * when the right env key is set under a different provider name.
35
35
  */
36
36
  providers?: ProviderRoutingSettings;
37
+ /**
38
+ * What to do when the model's output fails schema validation after all
39
+ * retries are exhausted (M14):
40
+ * - `'throw'` (default) — throw {@link GenerateObjectError} `parse_failed`.
41
+ * - `'return-raw'` — resolve with the raw, UNVALIDATED input the model sent
42
+ * (`object` may not match the schema; inspect `raw` too).
43
+ * - `'return-partial'` — for object schemas, resolve with only the fields that
44
+ * individually validate (best-effort salvage); non-object schemas fall back
45
+ * to raw.
46
+ */
47
+ errorStrategy?: "throw" | "return-partial" | "return-raw";
37
48
  }
38
49
  /**
39
50
  * Successful return from {@link Agent.generateObject}.
package/dist/index.cjs CHANGED
@@ -3800,6 +3800,19 @@ __export(generate_object_exports, {
3800
3800
  GenerateObjectError: () => exports.GenerateObjectError,
3801
3801
  generateObjectImpl: () => generateObjectImpl
3802
3802
  });
3803
+ function salvagePartial(schema, raw) {
3804
+ if (typeof raw !== "object" || raw === null) return raw;
3805
+ const shape = schema.shape;
3806
+ if (shape === void 0 || typeof shape !== "object") return raw;
3807
+ const rawObj = raw;
3808
+ const out = {};
3809
+ for (const [key2, fieldSchema] of Object.entries(shape)) {
3810
+ if (typeof fieldSchema?.safeParse !== "function") continue;
3811
+ const parsed = fieldSchema.safeParse(rawObj[key2]);
3812
+ if (parsed.success) out[key2] = parsed.data;
3813
+ }
3814
+ return out;
3815
+ }
3803
3816
  async function generateObjectImpl(options, deps) {
3804
3817
  const { jsonSchema, maxRetries, initialUsage } = setupStructuredOutput(
3805
3818
  options.schema,
@@ -3866,6 +3879,22 @@ async function generateObjectImpl(options, deps) {
3866
3879
  }
3867
3880
  lastParseError = parsed.error;
3868
3881
  }
3882
+ if (options.errorStrategy === "return-raw") {
3883
+ return {
3884
+ object: capturedRaw,
3885
+ raw: capturedRaw,
3886
+ usage: lastUsage,
3887
+ finishReason: "tool_use"
3888
+ };
3889
+ }
3890
+ if (options.errorStrategy === "return-partial") {
3891
+ return {
3892
+ object: salvagePartial(options.schema, capturedRaw),
3893
+ raw: capturedRaw,
3894
+ usage: lastUsage,
3895
+ finishReason: "tool_use"
3896
+ };
3897
+ }
3869
3898
  throw new exports.GenerateObjectError(
3870
3899
  "parse_failed",
3871
3900
  "Schema parse failed after all retries.",
@@ -11682,22 +11711,23 @@ async function executeTool(inputs, resolved, call) {
11682
11711
  return { stdout: "", stderr: `Unknown tool ${call.name}`, exitCode: 127 };
11683
11712
  }
11684
11713
  if (resolved.origin === "shell") return runShellTool(inputs, call);
11685
- if (resolved.origin === "memory") return runMemoryTool(resolved, call);
11686
- if (resolved.origin === "custom") return runCustomTool(resolved, call, inputs.signal);
11714
+ if (resolved.origin === "memory") return runMemoryTool(resolved, call, inputs.context);
11715
+ if (resolved.origin === "custom")
11716
+ return runCustomTool(resolved, call, inputs.signal, inputs.context);
11687
11717
  return runMcpTool(inputs, resolved, call);
11688
11718
  }
11689
- async function runMemoryTool(resolved, call) {
11690
- return runHandlerTool("memory", resolved.memoryHandler, call);
11719
+ async function runMemoryTool(resolved, call, context) {
11720
+ return runHandlerTool("memory", resolved.memoryHandler, call, void 0, context);
11691
11721
  }
11692
- async function runCustomTool(resolved, call, signal) {
11693
- return runHandlerTool("custom", resolved.customHandler, call, signal);
11722
+ async function runCustomTool(resolved, call, signal, context) {
11723
+ return runHandlerTool("custom", resolved.customHandler, call, signal, context);
11694
11724
  }
11695
- async function runHandlerTool(kind, handler, call, signal) {
11725
+ async function runHandlerTool(kind, handler, call, signal, context) {
11696
11726
  if (handler === void 0) {
11697
11727
  return { stdout: "", stderr: `${kind} tool ${call.name} has no handler`, exitCode: 127 };
11698
11728
  }
11699
11729
  try {
11700
- const stdout = await handler(call.input, { signal });
11730
+ const stdout = await handler(call.input, { signal, context });
11701
11731
  return { stdout, stderr: "", exitCode: 0 };
11702
11732
  } catch (cause) {
11703
11733
  const message = cause instanceof Error ? cause.message : String(cause);
@@ -15596,6 +15626,9 @@ function buildLoopInputs(options, runId, userText) {
15596
15626
  // D318 — forward SendOptions.signal to the agent loop so streamLlmTurn
15597
15627
  // can attach it to the LLM `fetch({ signal })` call.
15598
15628
  ...options.sendOptions.signal !== void 0 ? { signal: options.sendOptions.signal } : {},
15629
+ // M7 — forward SendOptions.context to the loop so every tool handler receives
15630
+ // it on `ctx.context` (shared run config set once, e.g. projectRoot).
15631
+ ...options.sendOptions.context !== void 0 ? { context: options.sendOptions.context } : {},
15599
15632
  // #58 / #57 — forward the per-tool timeout + tool-result guard so a consumer
15600
15633
  // can enable them via SendOptions (not only internal AgentLoopInputs).
15601
15634
  ...options.sendOptions.perToolTimeoutMs !== void 0 ? { perToolTimeoutMs: options.sendOptions.perToolTimeoutMs } : {},