@cognipeer/agent-sdk 0.10.3 → 0.10.4

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.cjs CHANGED
@@ -513,7 +513,7 @@ function getModelCapabilities(model) {
513
513
  return {
514
514
  provider,
515
515
  structuredOutput: supportsNativeStructuredOutput(provider) ? "native" : "tool_based",
516
- strictToolCalling: requiresStrictToolCalling(provider),
516
+ strictToolCalling: requiresStrictToolCalling(provider) && isOpenAIHostedEndpoint(model._lc),
517
517
  streaming: true
518
518
  };
519
519
  }
@@ -556,6 +556,17 @@ function supportsNativeStructuredOutput(provider) {
556
556
  function requiresStrictToolCalling(provider) {
557
557
  return ["openai"].includes(provider);
558
558
  }
559
+ function isOpenAIHostedEndpoint(lcModel) {
560
+ if (!lcModel) return true;
561
+ const baseURL = lcModel.clientConfig?.baseURL ?? lcModel.configuration?.baseURL ?? lcModel.baseURL;
562
+ if (typeof baseURL !== "string" || baseURL.trim() === "") return true;
563
+ try {
564
+ const host = new URL(baseURL).hostname.toLowerCase();
565
+ return host === "api.openai.com" || host.endsWith(".openai.azure.com") || host.endsWith(".cognitiveservices.azure.com");
566
+ } catch {
567
+ return false;
568
+ }
569
+ }
559
570
 
560
571
  // src/model.ts
561
572
  function isSmartModel(m) {
@@ -2520,13 +2531,19 @@ function resolveCapabilities(provider) {
2520
2531
  switch (provider) {
2521
2532
  case "openai":
2522
2533
  case "azure":
2523
- case "openai-compatible":
2524
2534
  return {
2525
2535
  structuredOutput: "native",
2526
2536
  strictToolCalling: true,
2527
2537
  streaming: true,
2528
2538
  provider
2529
2539
  };
2540
+ case "openai-compatible":
2541
+ return {
2542
+ structuredOutput: "native",
2543
+ strictToolCalling: false,
2544
+ streaming: true,
2545
+ provider
2546
+ };
2530
2547
  case "anthropic":
2531
2548
  return {
2532
2549
  structuredOutput: "tool_based",
@@ -3855,6 +3872,187 @@ Identical to an earlier ${duplicate.toolName} result. Use get_tool_response with
3855
3872
  }
3856
3873
  return notApplied4(output);
3857
3874
  }
3875
+ var identity = (value) => value;
3876
+ function describeLike(schema, source, suffix) {
3877
+ const description = [source.description, suffix].filter(Boolean).join(" ");
3878
+ return description ? schema.describe(description) : schema;
3879
+ }
3880
+ function jsonString(source) {
3881
+ return {
3882
+ schema: describeLike(zod.z.string(), source, "(a JSON value, encoded as a string)"),
3883
+ restore: (value) => {
3884
+ if (typeof value !== "string") return value;
3885
+ try {
3886
+ return JSON.parse(value);
3887
+ } catch {
3888
+ return value;
3889
+ }
3890
+ }
3891
+ };
3892
+ }
3893
+ function unwrapOptional(schema) {
3894
+ const def = schema._def;
3895
+ if (def?.typeName === "ZodOptional") return { inner: def.innerType, optional: true };
3896
+ if (def?.typeName === "ZodDefault") return { inner: def.innerType, optional: true };
3897
+ return { inner: schema, optional: false };
3898
+ }
3899
+ function isZodSchema2(schema) {
3900
+ return Boolean(schema) && typeof schema.safeParse === "function" && Boolean(schema._def);
3901
+ }
3902
+ function toStrictCompatible(schema) {
3903
+ const def = schema?._def;
3904
+ switch (def?.typeName) {
3905
+ case "ZodObject": {
3906
+ const shape = typeof def.shape === "function" ? def.shape() : def.shape;
3907
+ const keys = Object.keys(shape ?? {});
3908
+ const open = def.unknownKeys === "passthrough" || def.catchall && def.catchall._def?.typeName !== "ZodNever";
3909
+ if (keys.length === 0 && open) return jsonString(schema);
3910
+ const nextShape = {};
3911
+ const restores = {};
3912
+ for (const key of keys) {
3913
+ const field = shape[key];
3914
+ const { inner, optional } = unwrapOptional(field);
3915
+ const child = toStrictCompatible(inner);
3916
+ const childSchema = describeLike(child.schema, field.description ? field : inner);
3917
+ nextShape[key] = optional ? childSchema.nullable() : childSchema;
3918
+ restores[key] = { restore: child.restore, optional };
3919
+ }
3920
+ return {
3921
+ schema: describeLike(zod.z.object(nextShape), schema),
3922
+ restore: (value) => {
3923
+ if (!value || typeof value !== "object" || Array.isArray(value)) return value;
3924
+ const out = {};
3925
+ for (const [key, raw] of Object.entries(value)) {
3926
+ const entry = restores[key];
3927
+ if (raw === null && entry?.optional) continue;
3928
+ out[key] = entry ? entry.restore(raw) : raw;
3929
+ }
3930
+ return out;
3931
+ }
3932
+ };
3933
+ }
3934
+ case "ZodOptional":
3935
+ case "ZodDefault": {
3936
+ const child = toStrictCompatible(def.innerType);
3937
+ return {
3938
+ schema: describeLike(child.schema.nullable(), schema),
3939
+ restore: (value) => value === null ? void 0 : child.restore(value)
3940
+ };
3941
+ }
3942
+ case "ZodNullable": {
3943
+ const child = toStrictCompatible(def.innerType);
3944
+ return {
3945
+ schema: describeLike(child.schema.nullable(), schema),
3946
+ restore: (value) => value === null ? null : child.restore(value)
3947
+ };
3948
+ }
3949
+ case "ZodArray": {
3950
+ const child = toStrictCompatible(def.type);
3951
+ return {
3952
+ schema: describeLike(zod.z.array(child.schema), schema),
3953
+ restore: (value) => Array.isArray(value) ? value.map(child.restore) : value
3954
+ };
3955
+ }
3956
+ case "ZodUnion":
3957
+ case "ZodDiscriminatedUnion": {
3958
+ const rawOptions = def.options instanceof Map ? [...def.options.values()] : def.options;
3959
+ const options = rawOptions.map(toStrictCompatible);
3960
+ if (options.length === 1) return options[0];
3961
+ if (options.every((option, index) => option.schema === rawOptions[index])) {
3962
+ return { schema, restore: identity };
3963
+ }
3964
+ return {
3965
+ schema: describeLike(zod.z.union(options.map((option) => option.schema)), schema),
3966
+ restore: (value) => {
3967
+ const candidates = options.map((option) => option.restore(value));
3968
+ const index = candidates.findIndex((candidate, i) => rawOptions[i].safeParse(candidate).success);
3969
+ return candidates[index >= 0 ? index : 0];
3970
+ }
3971
+ };
3972
+ }
3973
+ case "ZodEffects":
3974
+ return toStrictCompatible(def.schema);
3975
+ case "ZodRecord":
3976
+ case "ZodAny":
3977
+ case "ZodUnknown":
3978
+ return jsonString(schema);
3979
+ default:
3980
+ return { schema, restore: identity };
3981
+ }
3982
+ }
3983
+ function topLevelObject(transform) {
3984
+ if (transform.schema._def?.typeName === "ZodObject") return transform;
3985
+ return {
3986
+ schema: zod.z.object({
3987
+ input: transform.schema.describe(
3988
+ transform.schema.description ?? "The tool arguments as a JSON object, encoded as a string"
3989
+ )
3990
+ }),
3991
+ restore: (value) => {
3992
+ const input = value && typeof value === "object" ? value.input : void 0;
3993
+ const restored = transform.restore(input);
3994
+ return restored && typeof restored === "object" ? restored : {};
3995
+ }
3996
+ };
3997
+ }
3998
+ function toStrictToolSchema(schema) {
3999
+ return topLevelObject(toStrictCompatible(schema));
4000
+ }
4001
+ function restoreToolCalls(message, restorers) {
4002
+ if (!message || typeof message !== "object" || restorers.size === 0) return message;
4003
+ const restoreList = (calls) => {
4004
+ if (!Array.isArray(calls) || calls.length === 0) return calls;
4005
+ return calls.map((call) => {
4006
+ const fn = call?.function;
4007
+ const name = call?.name ?? fn?.name;
4008
+ const restore = name ? restorers.get(name) : void 0;
4009
+ if (!restore) return call;
4010
+ let next = call;
4011
+ if (call.args && typeof call.args === "object") next = { ...next, args: restore(call.args) };
4012
+ if (fn && typeof fn.arguments === "string") {
4013
+ try {
4014
+ next = { ...next, function: { ...fn, arguments: JSON.stringify(restore(JSON.parse(fn.arguments))) } };
4015
+ } catch {
4016
+ }
4017
+ }
4018
+ return next;
4019
+ });
4020
+ };
4021
+ const m = message;
4022
+ const hasDirect = Array.isArray(m.tool_calls) && m.tool_calls.length > 0;
4023
+ const hasKwargs = Array.isArray(m.additional_kwargs?.tool_calls) && m.additional_kwargs.tool_calls.length > 0;
4024
+ if (!hasDirect && !hasKwargs) return message;
4025
+ return {
4026
+ ...message,
4027
+ ...hasDirect ? { tool_calls: restoreList(m.tool_calls) } : {},
4028
+ ...hasKwargs ? { additional_kwargs: { ...m.additional_kwargs, tool_calls: restoreList(m.additional_kwargs.tool_calls) } } : {}
4029
+ };
4030
+ }
4031
+ var strictViews = /* @__PURE__ */ new WeakMap();
4032
+ function prepareStrictToolMenu(tools) {
4033
+ const restorers = /* @__PURE__ */ new Map();
4034
+ const menu = tools.map((tool) => {
4035
+ const t = tool;
4036
+ if (!t || typeof t.name !== "string" || !isZodSchema2(t.schema)) return tool;
4037
+ const cached = strictViews.get(tool);
4038
+ if (cached && cached.schema === t.schema) {
4039
+ restorers.set(t.name, cached.restore);
4040
+ return cached.view;
4041
+ }
4042
+ try {
4043
+ const transform = toStrictToolSchema(t.schema);
4044
+ const view = Object.create(tool);
4045
+ view.schema = transform.schema;
4046
+ view.__lcTool = void 0;
4047
+ strictViews.set(tool, { schema: t.schema, view, restore: transform.restore });
4048
+ restorers.set(t.name, transform.restore);
4049
+ return view;
4050
+ } catch {
4051
+ return tool;
4052
+ }
4053
+ });
4054
+ return { menu, restorers };
4055
+ }
3858
4056
 
3859
4057
  // src/nodes/agentCore.ts
3860
4058
  function createAgentCoreNode(opts) {
@@ -3875,10 +4073,17 @@ function createAgentCoreNode(opts) {
3875
4073
  };
3876
4074
  let tools = runtime.tools ?? [];
3877
4075
  const shouldUseStrictToolCalling = Boolean(
3878
- runtime.responseFormat && runtime.model?.capabilities?.strictToolCalling
4076
+ runtime.model?.capabilities?.strictToolCalling
3879
4077
  );
4078
+ let strictRestorers = /* @__PURE__ */ new Map();
4079
+ const wireMenu = (menu) => {
4080
+ if (!shouldUseStrictToolCalling) return menu;
4081
+ const prepared = prepareStrictToolMenu(menu);
4082
+ strictRestorers = prepared.restorers;
4083
+ return prepared.menu;
4084
+ };
3880
4085
  const bindToolMenu = (menu) => runtime.model?.bindTools ? runtime.model.bindTools(
3881
- menu,
4086
+ wireMenu(menu),
3882
4087
  shouldUseStrictToolCalling ? { strict: true } : void 0
3883
4088
  ) : runtime.model;
3884
4089
  const menuMutationReachesProvider = typeof runtime.model?.bindTools === "function";
@@ -3889,7 +4094,8 @@ function createAgentCoreNode(opts) {
3889
4094
  const computeTraceToolDefinitions = (menu) => {
3890
4095
  if (!traceSession || !traceSession.resolvedConfig.logData || menu.length === 0) return void 0;
3891
4096
  try {
3892
- return menu.map((tool) => {
4097
+ const wire = shouldUseStrictToolCalling ? prepareStrictToolMenu(menu).menu : menu;
4098
+ return wire.map((tool) => {
3893
4099
  const def = toToolDefinition(tool, shouldUseStrictToolCalling ? true : void 0);
3894
4100
  return { name: def.name, description: def.description || void 0, parameters: def.parameters };
3895
4101
  });
@@ -4195,6 +4401,9 @@ ${append}`;
4195
4401
  throw err;
4196
4402
  }
4197
4403
  }
4404
+ if (shortCircuited === void 0 && strictRestorers.size > 0) {
4405
+ response = restoreToolCalls(response, strictRestorers);
4406
+ }
4198
4407
  if (!host?.has("postModelCall")) break;
4199
4408
  const postGate = await host.runGate("postModelCall", {
4200
4409
  message: response,
@@ -8793,6 +9002,21 @@ var todoUpdateItemSchema = zod.z.object({
8793
9002
  status: todoStatusSchema.optional(),
8794
9003
  evidence: zod.z.string().max(300).optional()
8795
9004
  });
9005
+ var todoItemWireSchema = zod.z.object({
9006
+ id: zod.z.number().int().min(1).describe("Sequential id starting from 1 (write) or an existing id (update)"),
9007
+ step: zod.z.string().min(1).optional(),
9008
+ title: zod.z.string().min(1).optional(),
9009
+ description: zod.z.string().min(1).optional(),
9010
+ owner: zod.z.string().min(1).optional(),
9011
+ exitCriteria: zod.z.string().min(1).optional(),
9012
+ status: todoStatusSchema.optional().describe("Required for every item on write"),
9013
+ evidence: zod.z.string().max(300).optional()
9014
+ });
9015
+ function describeTodoIssue(issue) {
9016
+ if (!issue) return void 0;
9017
+ const path2 = issue.path.length > 0 ? `todoList[${issue.path[0]}]${issue.path.slice(1).map((p) => `.${String(p)}`).join("")}` : "todoList";
9018
+ return `${path2}: ${issue.message}`;
9019
+ }
8796
9020
  function normalizeTodoItem(item, existing) {
8797
9021
  const id = item.id ?? existing?.id;
8798
9022
  const step = item.step || item.title || item.description || existing?.step || existing?.title || existing?.description || `Step ${id}`;
@@ -8909,7 +9133,7 @@ function createPlanTool(stateRef, toolName, description) {
8909
9133
  schema: zod.z.object({
8910
9134
  operation: zod.z.enum(["write", "read", "update"]),
8911
9135
  expectedVersion: zod.z.number().int().min(0).optional(),
8912
- todoList: zod.z.array(zod.z.union([todoWriteItemSchema, todoUpdateItemSchema])).optional()
9136
+ todoList: zod.z.array(todoItemWireSchema).optional()
8913
9137
  }),
8914
9138
  func: async ({ operation, expectedVersion, todoList }) => {
8915
9139
  const toolStateRef = manageTodo._stateRef;
@@ -8975,7 +9199,10 @@ function createPlanTool(stateRef, toolName, description) {
8975
9199
  return {
8976
9200
  status: "error",
8977
9201
  operation,
8978
- error: parsed.error.issues[0]?.message || "Invalid todoList for write.",
9202
+ // The wire schema has `status` optional (one shape for write and
9203
+ // update), so a missing one is caught here — named, so the model
9204
+ // can fix the call.
9205
+ error: describeTodoIssue(parsed.error.issues[0]) || "Invalid todoList for write.",
8979
9206
  version: currentVersion,
8980
9207
  adherenceScore: stateRef.adherenceScore || 0
8981
9208
  };
@@ -8998,7 +9225,7 @@ function createPlanTool(stateRef, toolName, description) {
8998
9225
  return {
8999
9226
  status: "error",
9000
9227
  operation,
9001
- error: parsed.error.issues[0]?.message || "Invalid todoList for update.",
9228
+ error: describeTodoIssue(parsed.error.issues[0]) || "Invalid todoList for update.",
9002
9229
  version: currentVersion,
9003
9230
  adherenceScore: stateRef.adherenceScore || 0
9004
9231
  };
@@ -16658,6 +16885,7 @@ exports.httpSink = httpSink;
16658
16885
  exports.inMemoryCheckpointStore = inMemoryCheckpointStore;
16659
16886
  exports.inMemoryConversationStore = inMemoryConversationStore;
16660
16887
  exports.isHookImplemented = isHookImplemented;
16888
+ exports.isOpenAIHostedEndpoint = isOpenAIHostedEndpoint;
16661
16889
  exports.isSmartModel = isSmartModel;
16662
16890
  exports.isValidIban = isValidIban;
16663
16891
  exports.isValidLuhn = isValidLuhn;
@@ -16686,6 +16914,7 @@ exports.portkeyGateway = portkeyGateway;
16686
16914
  exports.portkeyGuardrail = portkeyGuardrail;
16687
16915
  exports.preopenSkills = preopenSkills;
16688
16916
  exports.preopenToolCallId = preopenToolCallId;
16917
+ exports.prepareStrictToolMenu = prepareStrictToolMenu;
16689
16918
  exports.promptInjectionGuard = promptInjectionGuard;
16690
16919
  exports.rateLimit = rateLimit;
16691
16920
  exports.readMemoryFacts = readMemoryFacts;
@@ -16705,6 +16934,7 @@ exports.resolveToolApprovalState = resolveToolApprovalState;
16705
16934
  exports.resolveUserQuestionState = resolveUserQuestionState;
16706
16935
  exports.responseCache = responseCache;
16707
16936
  exports.restoreSnapshot = restoreSnapshot;
16937
+ exports.restoreToolCalls = restoreToolCalls;
16708
16938
  exports.runSmartAgentEvalHarness = runSmartAgentEvalHarness;
16709
16939
  exports.scoreItemsByRelevance = scoreItemsByRelevance;
16710
16940
  exports.searchSkills = searchSkills;
@@ -16715,6 +16945,8 @@ exports.setTokenCounter = setTokenCounter;
16715
16945
  exports.startStreamingSession = startStreamingSession;
16716
16946
  exports.summarizeObject = summarizeObject;
16717
16947
  exports.textFromContent = textFromContent;
16948
+ exports.toStrictCompatible = toStrictCompatible;
16949
+ exports.toStrictToolSchema = toStrictToolSchema;
16718
16950
  exports.tokenize = tokenize;
16719
16951
  exports.toolPolicy = toolPolicy;
16720
16952
  exports.traceSessionToOtlp = traceSessionToOtlp;