@code-yeongyu/senpi 2026.7.17-2 → 2026.7.17-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.
Files changed (50) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts +1 -1
  3. package/dist/core/extensions/builtin/mcp/expose/native-search.d.ts.map +1 -1
  4. package/dist/core/extensions/builtin/mcp/expose/native-search.js +1 -1
  5. package/dist/core/extensions/builtin/mcp/expose/native-search.js.map +1 -1
  6. package/dist/core/extensions/builtin/mcp/expose/policy.js +1 -1
  7. package/dist/core/extensions/builtin/mcp/expose/policy.js.map +1 -1
  8. package/dist/core/extensions/builtin/mcp/expose/status.js +1 -1
  9. package/dist/core/extensions/builtin/mcp/expose/status.js.map +1 -1
  10. package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts +3 -3
  11. package/dist/core/extensions/builtin/mcp/expose/tier-b.d.ts.map +1 -1
  12. package/dist/core/extensions/builtin/mcp/expose/tier-b.js +10 -10
  13. package/dist/core/extensions/builtin/mcp/expose/tier-b.js.map +1 -1
  14. package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts +3 -3
  15. package/dist/core/extensions/builtin/mcp/expose/tool-search.d.ts.map +1 -1
  16. package/dist/core/extensions/builtin/mcp/expose/tool-search.js +14 -14
  17. package/dist/core/extensions/builtin/mcp/expose/tool-search.js.map +1 -1
  18. package/dist/core/extensions/builtin/mcp/index.js +5 -5
  19. package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
  20. package/dist/core/extensions/builtin/mcp/service.d.ts +2 -2
  21. package/dist/core/extensions/builtin/mcp/service.d.ts.map +1 -1
  22. package/dist/core/extensions/builtin/mcp/service.js +2 -2
  23. package/dist/core/extensions/builtin/mcp/service.js.map +1 -1
  24. package/dist/core/extensions/builtin/websearch/index.d.ts.map +1 -1
  25. package/dist/core/extensions/builtin/websearch/index.js +20 -3
  26. package/dist/core/extensions/builtin/websearch/index.js.map +1 -1
  27. package/docs/AGENTS.md +70 -0
  28. package/docs/mcp.md +5 -5
  29. package/examples/AGENTS.md +3 -0
  30. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
  31. package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
  32. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  33. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
  34. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +19 -0
  35. package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
  36. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +0 -21
  37. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  38. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js +6 -6
  39. package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js.map +1 -1
  40. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts +0 -21
  41. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts.map +1 -1
  42. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js +3 -21
  43. package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
  44. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-schema-compat.d.ts.map +1 -1
  45. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-schema-compat.js +45 -1
  46. package/node_modules/@earendil-works/pi-ai/dist/utils/tool-schema-compat.js.map +1 -1
  47. package/node_modules/@earendil-works/pi-ai/package.json +1 -1
  48. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  49. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  50. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"tool-schema-compat.d.ts","sourceRoot":"","sources":["../../src/utils/tool-schema-compat.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,gBAAgB,GAAG,eAAe,CAAC;AA8H/C;;;GAGG;AACH,wBAAgB,sCAAsC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE/G;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG3G"}
1
+ {"version":3,"file":"tool-schema-compat.d.ts","sourceRoot":"","sources":["../../src/utils/tool-schema-compat.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,gBAAgB,GAAG,eAAe,CAAC;AA4K/C;;;GAGG;AACH,wBAAgB,sCAAsC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE/G;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG3G"}
@@ -81,6 +81,50 @@ function collapseConstUnion(node) {
81
81
  node.type = sharedType;
82
82
  node.enum = values;
83
83
  }
84
+ function mergeRootObjectUnion(schema) {
85
+ const branches = Array.isArray(schema.anyOf) ? schema.anyOf : Array.isArray(schema.oneOf) ? schema.oneOf : undefined;
86
+ if (branches === undefined || branches.length === 0)
87
+ return undefined;
88
+ const objectBranches = [];
89
+ for (const branch of branches) {
90
+ if (!isJsonObject(branch) || branch.type !== "object")
91
+ return undefined;
92
+ if (branch.properties !== undefined && !isJsonObject(branch.properties))
93
+ return undefined;
94
+ if (branch.required !== undefined && !Array.isArray(branch.required))
95
+ return undefined;
96
+ objectBranches.push(branch);
97
+ }
98
+ const properties = {};
99
+ for (const branch of objectBranches) {
100
+ if (!isJsonObject(branch.properties))
101
+ continue;
102
+ for (const [name, propertySchema] of Object.entries(branch.properties)) {
103
+ const existing = properties[name];
104
+ properties[name] =
105
+ existing === undefined || JSON.stringify(existing) === JSON.stringify(propertySchema)
106
+ ? propertySchema
107
+ : { anyOf: [existing, propertySchema] };
108
+ }
109
+ }
110
+ const firstRequired = objectBranches[0]?.required;
111
+ let commonRequired = Array.isArray(firstRequired)
112
+ ? firstRequired.filter((name) => typeof name === "string")
113
+ : [];
114
+ for (const branch of objectBranches.slice(1)) {
115
+ const branchRequired = new Set(Array.isArray(branch.required)
116
+ ? branch.required.filter((name) => typeof name === "string")
117
+ : []);
118
+ commonRequired = commonRequired.filter((name) => branchRequired.has(name));
119
+ }
120
+ const { anyOf: _anyOf, oneOf: _oneOf, ...rest } = schema;
121
+ return {
122
+ ...rest,
123
+ type: "object",
124
+ properties,
125
+ ...(commonRequired.length > 0 ? { required: commonRequired } : {}),
126
+ };
127
+ }
84
128
  function normalizeNode(node) {
85
129
  if (Array.isArray(node)) {
86
130
  return node.map((child) => normalizeNode(child));
@@ -129,7 +173,7 @@ export function normalizeToolParametersForOpenAICompat(schema) {
129
173
  */
130
174
  export function normalizeToolParametersForMoonshot(schema) {
131
175
  const normalized = normalizeToolParametersForOpenAICompat(schema);
132
- return stripMoonshotAnnotations(normalized);
176
+ return stripMoonshotAnnotations(mergeRootObjectUnion(normalized) ?? normalized);
133
177
  }
134
178
  function stripMoonshotAnnotations(node) {
135
179
  if (Array.isArray(node)) {
@@ -1 +1 @@
1
- {"version":3,"file":"tool-schema-compat.js","sourceRoot":"","sources":["../../src/utils/tool-schema-compat.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * JSON Schema normalization for tool parameters sent to OpenAI-compatible\n * backends. Some gateways (e.g. Apitopia → Kimi / Moonshot) enforce a stricter\n * subset that rejects a sibling `type` keyword on schemas that also declare\n * `anyOf` / `oneOf` / `allOf`. This helper removes that redundancy while\n * preserving the schema's semantics.\n */\n\nexport type ToolSchemaFlavor = \"moonshot-mfjs\";\n\nconst COMBINER_KEYS = [\"anyOf\", \"oneOf\", \"allOf\"] as const;\nconst SCHEMA_MAP_KEYS = [\"properties\", \"patternProperties\", \"$defs\", \"definitions\"] as const;\nconst SCHEMA_SINGLE_KEYS = [\n\t\"items\",\n\t\"additionalProperties\",\n\t\"contains\",\n\t\"propertyNames\",\n\t\"if\",\n\t\"then\",\n\t\"else\",\n\t\"not\",\n] as const;\n\nfunction isJsonObject(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isScalarType(type: unknown): type is \"string\" | \"number\" | \"integer\" | \"boolean\" {\n\treturn type === \"string\" || type === \"number\" || type === \"integer\" || type === \"boolean\";\n}\n\n/**\n * Move a parent-level `type` keyword into combiner branches that do not already\n * declare one, then drop the parent `type`. This keeps the schema equivalent\n * while satisfying validators that require `type` to live inside each branch.\n */\nfunction moveTypeIntoCombinerBranches(node: Record<string, unknown>): void {\n\tif (!(\"type\" in node)) return;\n\n\tconst parentType = node.type;\n\tfor (const combiner of COMBINER_KEYS) {\n\t\tconst branches = node[combiner];\n\t\tif (!Array.isArray(branches)) continue;\n\n\t\tfor (const branch of branches) {\n\t\t\tif (isJsonObject(branch) && !(\"type\" in branch)) {\n\t\t\t\tbranch.type = parentType;\n\t\t\t}\n\t\t}\n\t}\n\n\tdelete node.type;\n}\n\n/**\n * Collapse a homogeneous all-`const` union into a typed `enum`. This is the\n * wire shape many OpenAI-compatible gateways expect for literal unions.\n */\nfunction collapseConstUnion(node: Record<string, unknown>): void {\n\tconst branches = node.anyOf;\n\tif (!Array.isArray(branches) || branches.length < 2) return;\n\tif (\"type\" in node) return;\n\n\tconst values: unknown[] = [];\n\tlet sharedType: string | undefined;\n\n\tfor (const branch of branches) {\n\t\tif (!isJsonObject(branch)) return;\n\t\tif (!Object.hasOwn(branch, \"const\")) return;\n\n\t\tconst keys = Object.keys(branch);\n\t\tif (keys.length !== 2 || !keys.includes(\"type\")) return;\n\n\t\tconst branchType = branch.type;\n\t\tif (!isScalarType(branchType)) return;\n\n\t\tif (sharedType === undefined) {\n\t\t\tsharedType = branchType;\n\t\t} else if (sharedType !== branchType) {\n\t\t\treturn;\n\t\t}\n\n\t\tvalues.push(branch.const);\n\t}\n\n\tif (sharedType === undefined || values.length === 0) return;\n\n\tdelete node.anyOf;\n\tnode.type = sharedType;\n\tnode.enum = values;\n}\n\nfunction normalizeNode(node: unknown): unknown {\n\tif (Array.isArray(node)) {\n\t\treturn node.map((child) => normalizeNode(child));\n\t}\n\n\tif (!isJsonObject(node)) {\n\t\treturn node;\n\t}\n\n\tconst hasCombiner = COMBINER_KEYS.some((key) => Array.isArray(node[key]));\n\tif (hasCombiner) {\n\t\tmoveTypeIntoCombinerBranches(node);\n\t}\n\n\tfor (const combiner of COMBINER_KEYS) {\n\t\tconst branches = node[combiner];\n\t\tif (Array.isArray(branches)) {\n\t\t\tnode[combiner] = branches.map((branch) => normalizeNode(branch));\n\t\t}\n\t}\n\n\tif (Array.isArray(node.anyOf)) {\n\t\tcollapseConstUnion(node);\n\t}\n\n\tfor (const key of SCHEMA_SINGLE_KEYS) {\n\t\tif (Object.hasOwn(node, key)) {\n\t\t\tnode[key] = normalizeNode(node[key]);\n\t\t}\n\t}\n\n\tfor (const key of SCHEMA_MAP_KEYS) {\n\t\tconst map = node[key];\n\t\tif (!isJsonObject(map)) continue;\n\t\tfor (const name of Object.keys(map)) {\n\t\t\tmap[name] = normalizeNode(map[name]);\n\t\t}\n\t}\n\n\treturn node;\n}\n\n/**\n * Return a deep-normalized copy of a tool's JSON Schema parameters, suitable\n * for OpenAI-compatible Chat Completions backends.\n */\nexport function normalizeToolParametersForOpenAICompat(schema: Record<string, unknown>): Record<string, unknown> {\n\treturn normalizeNode(structuredClone(schema)) as Record<string, unknown>;\n}\n\n/**\n * Moonshot-flavored JSON Schema subset: in addition to the OpenAI-compatible\n * normalization, drop non-structural annotation keywords that Moonshot rejects.\n */\nexport function normalizeToolParametersForMoonshot(schema: Record<string, unknown>): Record<string, unknown> {\n\tconst normalized = normalizeToolParametersForOpenAICompat(schema);\n\treturn stripMoonshotAnnotations(normalized);\n}\n\nfunction stripMoonshotAnnotations(node: unknown): Record<string, unknown> {\n\tif (Array.isArray(node)) {\n\t\treturn node.map((child) => stripMoonshotAnnotations(child)) as unknown as Record<string, unknown>;\n\t}\n\n\tif (!isJsonObject(node)) {\n\t\treturn node as Record<string, unknown>;\n\t}\n\n\t// Moonshot does not support JSON Schema validators like `format` or\n\t// annotation-only keywords like `examples` inside function parameters.\n\tdelete node.format;\n\tdelete node.examples;\n\tdelete node.readOnly;\n\tdelete node.writeOnly;\n\tdelete node.deprecated;\n\tdelete node.$schema;\n\tdelete node.$id;\n\n\tfor (const combiner of COMBINER_KEYS) {\n\t\tconst branches = node[combiner];\n\t\tif (Array.isArray(branches)) {\n\t\t\tnode[combiner] = branches.map((branch) => stripMoonshotAnnotations(branch));\n\t\t}\n\t}\n\n\tfor (const key of SCHEMA_SINGLE_KEYS) {\n\t\tif (Object.hasOwn(node, key)) {\n\t\t\tnode[key] = stripMoonshotAnnotations(node[key]);\n\t\t}\n\t}\n\n\tfor (const key of SCHEMA_MAP_KEYS) {\n\t\tconst map = node[key];\n\t\tif (!isJsonObject(map)) continue;\n\t\tfor (const name of Object.keys(map)) {\n\t\t\tmap[name] = stripMoonshotAnnotations(map[name]);\n\t\t}\n\t}\n\n\treturn node;\n}\n"]}
1
+ {"version":3,"file":"tool-schema-compat.js","sourceRoot":"","sources":["../../src/utils/tool-schema-compat.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * JSON Schema normalization for tool parameters sent to OpenAI-compatible\n * backends. Some gateways (e.g. Apitopia → Kimi / Moonshot) enforce a stricter\n * subset that rejects a sibling `type` keyword on schemas that also declare\n * `anyOf` / `oneOf` / `allOf`. This helper removes that redundancy while\n * preserving the schema's semantics.\n */\n\nexport type ToolSchemaFlavor = \"moonshot-mfjs\";\n\nconst COMBINER_KEYS = [\"anyOf\", \"oneOf\", \"allOf\"] as const;\nconst SCHEMA_MAP_KEYS = [\"properties\", \"patternProperties\", \"$defs\", \"definitions\"] as const;\nconst SCHEMA_SINGLE_KEYS = [\n\t\"items\",\n\t\"additionalProperties\",\n\t\"contains\",\n\t\"propertyNames\",\n\t\"if\",\n\t\"then\",\n\t\"else\",\n\t\"not\",\n] as const;\n\nfunction isJsonObject(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isScalarType(type: unknown): type is \"string\" | \"number\" | \"integer\" | \"boolean\" {\n\treturn type === \"string\" || type === \"number\" || type === \"integer\" || type === \"boolean\";\n}\n\n/**\n * Move a parent-level `type` keyword into combiner branches that do not already\n * declare one, then drop the parent `type`. This keeps the schema equivalent\n * while satisfying validators that require `type` to live inside each branch.\n */\nfunction moveTypeIntoCombinerBranches(node: Record<string, unknown>): void {\n\tif (!(\"type\" in node)) return;\n\n\tconst parentType = node.type;\n\tfor (const combiner of COMBINER_KEYS) {\n\t\tconst branches = node[combiner];\n\t\tif (!Array.isArray(branches)) continue;\n\n\t\tfor (const branch of branches) {\n\t\t\tif (isJsonObject(branch) && !(\"type\" in branch)) {\n\t\t\t\tbranch.type = parentType;\n\t\t\t}\n\t\t}\n\t}\n\n\tdelete node.type;\n}\n\n/**\n * Collapse a homogeneous all-`const` union into a typed `enum`. This is the\n * wire shape many OpenAI-compatible gateways expect for literal unions.\n */\nfunction collapseConstUnion(node: Record<string, unknown>): void {\n\tconst branches = node.anyOf;\n\tif (!Array.isArray(branches) || branches.length < 2) return;\n\tif (\"type\" in node) return;\n\n\tconst values: unknown[] = [];\n\tlet sharedType: string | undefined;\n\n\tfor (const branch of branches) {\n\t\tif (!isJsonObject(branch)) return;\n\t\tif (!Object.hasOwn(branch, \"const\")) return;\n\n\t\tconst keys = Object.keys(branch);\n\t\tif (keys.length !== 2 || !keys.includes(\"type\")) return;\n\n\t\tconst branchType = branch.type;\n\t\tif (!isScalarType(branchType)) return;\n\n\t\tif (sharedType === undefined) {\n\t\t\tsharedType = branchType;\n\t\t} else if (sharedType !== branchType) {\n\t\t\treturn;\n\t\t}\n\n\t\tvalues.push(branch.const);\n\t}\n\n\tif (sharedType === undefined || values.length === 0) return;\n\n\tdelete node.anyOf;\n\tnode.type = sharedType;\n\tnode.enum = values;\n}\n\nfunction mergeRootObjectUnion(schema: Record<string, unknown>): Record<string, unknown> | undefined {\n\tconst branches = Array.isArray(schema.anyOf) ? schema.anyOf : Array.isArray(schema.oneOf) ? schema.oneOf : undefined;\n\tif (branches === undefined || branches.length === 0) return undefined;\n\n\tconst objectBranches: Record<string, unknown>[] = [];\n\tfor (const branch of branches) {\n\t\tif (!isJsonObject(branch) || branch.type !== \"object\") return undefined;\n\t\tif (branch.properties !== undefined && !isJsonObject(branch.properties)) return undefined;\n\t\tif (branch.required !== undefined && !Array.isArray(branch.required)) return undefined;\n\t\tobjectBranches.push(branch);\n\t}\n\n\tconst properties: Record<string, unknown> = {};\n\tfor (const branch of objectBranches) {\n\t\tif (!isJsonObject(branch.properties)) continue;\n\t\tfor (const [name, propertySchema] of Object.entries(branch.properties)) {\n\t\t\tconst existing = properties[name];\n\t\t\tproperties[name] =\n\t\t\t\texisting === undefined || JSON.stringify(existing) === JSON.stringify(propertySchema)\n\t\t\t\t\t? propertySchema\n\t\t\t\t\t: { anyOf: [existing, propertySchema] };\n\t\t}\n\t}\n\n\tconst firstRequired = objectBranches[0]?.required;\n\tlet commonRequired = Array.isArray(firstRequired)\n\t\t? firstRequired.filter((name): name is string => typeof name === \"string\")\n\t\t: [];\n\tfor (const branch of objectBranches.slice(1)) {\n\t\tconst branchRequired = new Set(\n\t\t\tArray.isArray(branch.required)\n\t\t\t\t? branch.required.filter((name): name is string => typeof name === \"string\")\n\t\t\t\t: [],\n\t\t);\n\t\tcommonRequired = commonRequired.filter((name) => branchRequired.has(name));\n\t}\n\n\tconst { anyOf: _anyOf, oneOf: _oneOf, ...rest } = schema;\n\treturn {\n\t\t...rest,\n\t\ttype: \"object\",\n\t\tproperties,\n\t\t...(commonRequired.length > 0 ? { required: commonRequired } : {}),\n\t};\n}\n\nfunction normalizeNode(node: unknown): unknown {\n\tif (Array.isArray(node)) {\n\t\treturn node.map((child) => normalizeNode(child));\n\t}\n\n\tif (!isJsonObject(node)) {\n\t\treturn node;\n\t}\n\n\tconst hasCombiner = COMBINER_KEYS.some((key) => Array.isArray(node[key]));\n\tif (hasCombiner) {\n\t\tmoveTypeIntoCombinerBranches(node);\n\t}\n\n\tfor (const combiner of COMBINER_KEYS) {\n\t\tconst branches = node[combiner];\n\t\tif (Array.isArray(branches)) {\n\t\t\tnode[combiner] = branches.map((branch) => normalizeNode(branch));\n\t\t}\n\t}\n\n\tif (Array.isArray(node.anyOf)) {\n\t\tcollapseConstUnion(node);\n\t}\n\n\tfor (const key of SCHEMA_SINGLE_KEYS) {\n\t\tif (Object.hasOwn(node, key)) {\n\t\t\tnode[key] = normalizeNode(node[key]);\n\t\t}\n\t}\n\n\tfor (const key of SCHEMA_MAP_KEYS) {\n\t\tconst map = node[key];\n\t\tif (!isJsonObject(map)) continue;\n\t\tfor (const name of Object.keys(map)) {\n\t\t\tmap[name] = normalizeNode(map[name]);\n\t\t}\n\t}\n\n\treturn node;\n}\n\n/**\n * Return a deep-normalized copy of a tool's JSON Schema parameters, suitable\n * for OpenAI-compatible Chat Completions backends.\n */\nexport function normalizeToolParametersForOpenAICompat(schema: Record<string, unknown>): Record<string, unknown> {\n\treturn normalizeNode(structuredClone(schema)) as Record<string, unknown>;\n}\n\n/**\n * Moonshot-flavored JSON Schema subset: in addition to the OpenAI-compatible\n * normalization, drop non-structural annotation keywords that Moonshot rejects.\n */\nexport function normalizeToolParametersForMoonshot(schema: Record<string, unknown>): Record<string, unknown> {\n\tconst normalized = normalizeToolParametersForOpenAICompat(schema);\n\treturn stripMoonshotAnnotations(mergeRootObjectUnion(normalized) ?? normalized);\n}\n\nfunction stripMoonshotAnnotations(node: unknown): Record<string, unknown> {\n\tif (Array.isArray(node)) {\n\t\treturn node.map((child) => stripMoonshotAnnotations(child)) as unknown as Record<string, unknown>;\n\t}\n\n\tif (!isJsonObject(node)) {\n\t\treturn node as Record<string, unknown>;\n\t}\n\n\t// Moonshot does not support JSON Schema validators like `format` or\n\t// annotation-only keywords like `examples` inside function parameters.\n\tdelete node.format;\n\tdelete node.examples;\n\tdelete node.readOnly;\n\tdelete node.writeOnly;\n\tdelete node.deprecated;\n\tdelete node.$schema;\n\tdelete node.$id;\n\n\tfor (const combiner of COMBINER_KEYS) {\n\t\tconst branches = node[combiner];\n\t\tif (Array.isArray(branches)) {\n\t\t\tnode[combiner] = branches.map((branch) => stripMoonshotAnnotations(branch));\n\t\t}\n\t}\n\n\tfor (const key of SCHEMA_SINGLE_KEYS) {\n\t\tif (Object.hasOwn(node, key)) {\n\t\t\tnode[key] = stripMoonshotAnnotations(node[key]);\n\t\t}\n\t}\n\n\tfor (const key of SCHEMA_MAP_KEYS) {\n\t\tconst map = node[key];\n\t\tif (!isJsonObject(map)) continue;\n\t\tfor (const name of Object.keys(map)) {\n\t\t\tmap[name] = stripMoonshotAnnotations(map[name]);\n\t\t}\n\t}\n\n\treturn node;\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-ai",
3
3
  "private": true,
4
- "version": "2026.7.17-2",
4
+ "version": "2026.7.17-4",
5
5
  "description": "Unified LLM API with automatic model discovery and provider configuration",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-pty",
3
3
  "private": true,
4
- "version": "2026.7.17-2",
4
+ "version": "2026.7.17-4",
5
5
  "description": "Typed PTY session loader for Senpi persistent terminals",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-tui",
3
3
  "private": true,
4
- "version": "2026.7.17-2",
4
+ "version": "2026.7.17-4",
5
5
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/senpi",
3
- "version": "2026.7.17-2",
3
+ "version": "2026.7.17-4",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -43,11 +43,11 @@
43
43
  "dependencies": {
44
44
  "@anthropic-ai/sdk": "0.91.1",
45
45
  "@aws-sdk/client-bedrock-runtime": "3.1048.0",
46
- "@code-yeongyu/senpi-codemode": "^2026.7.17-2",
47
- "@earendil-works/pi-agent-core": "^2026.7.17-2",
48
- "@earendil-works/pi-ai": "^2026.7.17-2",
49
- "@earendil-works/pi-pty": "^2026.7.17-2",
50
- "@earendil-works/pi-tui": "^2026.7.17-2",
46
+ "@code-yeongyu/senpi-codemode": "^2026.7.17-4",
47
+ "@earendil-works/pi-agent-core": "^2026.7.17-4",
48
+ "@earendil-works/pi-ai": "^2026.7.17-4",
49
+ "@earendil-works/pi-pty": "^2026.7.17-4",
50
+ "@earendil-works/pi-tui": "^2026.7.17-4",
51
51
  "@mistralai/mistralai": "2.2.6",
52
52
  "@modelcontextprotocol/sdk": "1.29.0",
53
53
  "@mozilla/readability": "0.6.0",