@zhushanwen/pi-structured-output 5.1.0 → 5.1.2
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/package.json +3 -3
- package/src/execute.ts +2 -2
- package/src/schema-guards.ts +6 -2
- package/src/tool-definition.ts +9 -7
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-structured-output",
|
|
3
|
-
"version": "5.1.
|
|
4
|
-
"description": "Structured output tool for Pi —
|
|
3
|
+
"version": "5.1.2",
|
|
4
|
+
"description": "Structured output tool for Pi — workflow schema enforcement via pi's parameter layer; interactive mode validates self-reported schemas with Ajv",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
7
7
|
"xyz-agent": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"ajv": "^8.17.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@earendil-works/pi-coding-agent": "^0.84.
|
|
30
|
+
"@earendil-works/pi-coding-agent": "^0.84.4",
|
|
31
31
|
"typebox": "*"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
package/src/execute.ts
CHANGED
|
@@ -42,8 +42,8 @@ import {
|
|
|
42
42
|
* 直接被这些约束校验,故算 object 根。组合根(anyOf/oneOf/allOf/$ref/enum)
|
|
43
43
|
* 可能接受非 object 值,保真起见一律包装({value} 内可容纳任意成员类型)。
|
|
44
44
|
*
|
|
45
|
-
* [同源锚定]
|
|
46
|
-
*
|
|
45
|
+
* [同源锚定] packages/subagent-core 的 agent-opts-resolver.ts(src/orchestration/)
|
|
46
|
+
* 持有本函数的本地副本(两包独立 npm 不能直接 import,optional peer 不保证存在),
|
|
47
47
|
* 其 ASP 文案按本判定同源条件化——改动本函数判定逻辑必须同步该副本。
|
|
48
48
|
*/
|
|
49
49
|
export function isObjectRootSchema(schema: unknown): schema is Record<string, unknown> {
|
package/src/schema-guards.ts
CHANGED
|
@@ -96,6 +96,10 @@ export function isToolExecutionEndEvent(
|
|
|
96
96
|
return typeof e === "object" && e !== null && "toolName" in e && "isError" in e;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
/**
|
|
99
|
+
/**
|
|
100
|
+
* swap 检测 + keyword-less schema 拒绝的纠错文案前缀,所有相关错误共用。
|
|
101
|
+
* 工具名逐字拼写(非 ${TOOL_NAME} 引用):本模块是纯逻辑叶节点(零业务依赖),
|
|
102
|
+
* 反向 import tool-definition 会成环。
|
|
103
|
+
*/
|
|
100
104
|
export const CORRECT_USAGE_HINT =
|
|
101
|
-
"Correct:
|
|
105
|
+
"Correct: structured-output({schema:{type:'object',properties:{...}}, data:{...actual values}}). ";
|
package/src/tool-definition.ts
CHANGED
|
@@ -37,9 +37,9 @@ export const ENV_SCHEMA = "PI_WORKFLOW_SCHEMA";
|
|
|
37
37
|
*
|
|
38
38
|
* 背景:PI_WORKFLOW_SCHEMA 经 spawn childEnv 注入子进程,env 块受 ARG_MAX 约束
|
|
39
39
|
*(Linux E2BIG)——超大 schema 会在 spawn 调用点报难归因的失败。硬拒绝在
|
|
40
|
-
* subagent-
|
|
41
|
-
* SCHEMA_ENV_MAX_BYTES = 256 * 1024,见其 src/shared/schema-env.ts
|
|
42
|
-
* 注释);本包独立 npm 不能直接 import(isObjectRootSchema 本地副本同例),常量
|
|
40
|
+
* subagent-core 侧(packages/subagent-core 的 session-runner applySchemaEnvToChildEnv,
|
|
41
|
+
* 同值上限 SCHEMA_ENV_MAX_BYTES = 256 * 1024,见其 src/shared/schema-env.ts
|
|
42
|
+
* [跨包契约 SSOT] 注释);本包独立 npm 不能直接 import(isObjectRootSchema 本地副本同例),常量
|
|
43
43
|
* 各自保留、跨包契约测试锁字节相等(tests/cross-package-contract.test.ts)。
|
|
44
44
|
* 本侧职责仅可见性:注册时超限 logger.warn(无 logger API,stderr 直出惯例)提示
|
|
45
45
|
* env 通道有上限,建议拆分 schema 或精简——不拒绝注册(子进程能收到 env 说明 SW
|
|
@@ -47,7 +47,9 @@ export const ENV_SCHEMA = "PI_WORKFLOW_SCHEMA";
|
|
|
47
47
|
*
|
|
48
48
|
* [跨包契约] 任一端改值必须同步另一端,否则 SW 侧硬拒绝线与 SO 侧提示线漂移。
|
|
49
49
|
*/
|
|
50
|
-
|
|
50
|
+
const SCHEMA_SIZE_WARN_KIB = 256;
|
|
51
|
+
const BYTES_PER_KIB = 1024;
|
|
52
|
+
export const SO_SCHEMA_SIZE_WARN_BYTES = SCHEMA_SIZE_WARN_KIB * BYTES_PER_KIB;
|
|
51
53
|
|
|
52
54
|
/**
|
|
53
55
|
* 注册期 schema 体积可见性提示(SO-DATA-4 的 SO 侧职责:提示,不拒绝)。
|
|
@@ -59,7 +61,7 @@ function warnIfSchemaOversized(envSchema: string): void {
|
|
|
59
61
|
if (bytes <= SO_SCHEMA_SIZE_WARN_BYTES) return;
|
|
60
62
|
process.stderr.write(
|
|
61
63
|
`[structured-output] PI_WORKFLOW_SCHEMA is ${bytes} bytes (> ${SO_SCHEMA_SIZE_WARN_BYTES} bytes / `
|
|
62
|
-
+ `${SO_SCHEMA_SIZE_WARN_BYTES /
|
|
64
|
+
+ `${SO_SCHEMA_SIZE_WARN_BYTES / BYTES_PER_KIB} KiB). The env channel has a size ceiling: the workflow runner `
|
|
63
65
|
+ "rejects injection above its own limit (spawn fails, hard to attribute), and oversized values can "
|
|
64
66
|
+ "hit E2BIG (ARG_MAX) at spawn. "
|
|
65
67
|
+ "👉 精简 outputSchema(删冗余 description / 收敛深嵌套)或拆分为多个小 schema 步骤。\n",
|
|
@@ -192,7 +194,7 @@ export function createDailyToolDefinition() {
|
|
|
192
194
|
+ "Call this tool to produce validated JSON data. "
|
|
193
195
|
+ "Pass `schema` (a JSON Schema draft-07 object) and `data` (the value to validate). "
|
|
194
196
|
+ "schema describes the shape; data fills the values; they must match.\n\n"
|
|
195
|
-
+
|
|
197
|
+
+ `✅ Correct (full call): ${TOOL_NAME}({schema:{type:'object',properties:{name:{type:'string'},age:{type:'number'}},required:['name']}, data:{name:'Alice',age:30}})\n`
|
|
196
198
|
+ "✅ Correct: schema={type:'array',items:{type:'string'}}, data=['a','b','c']\n"
|
|
197
199
|
+ "✅ Correct: schema={type:'string',enum:['low','medium','high']}, data='medium'\n"
|
|
198
200
|
+ "✅ Correct: schema={type:'number',minimum:0,maximum:100}, data=42\n"
|
|
@@ -200,7 +202,7 @@ export function createDailyToolDefinition() {
|
|
|
200
202
|
+ "❌ Wrong: putting the answer in text instead of calling this tool\n"
|
|
201
203
|
+ "❌ Wrong: data not matching schema (e.g. schema requires number but data is string)\n"
|
|
202
204
|
+ "❌ Wrong: schema={type:'object'} with data='hello' (string ≠ object)\n"
|
|
203
|
-
+
|
|
205
|
+
+ `❌ Wrong: ${TOOL_NAME}({name:'Alice'}) — missing the schema/data envelope. Wrap as {schema:{...}, data:{name:'Alice'}}.\n`
|
|
204
206
|
+ "❌ Wrong: swapping schema and data (passing the answer as schema). The tool detects this as 'likely swapped' and rejects it.\n"
|
|
205
207
|
+ "❌ Wrong: merging schema and data into one object.\n"
|
|
206
208
|
+ "❌ Wrong: schema with no recognized JSON Schema keyword (e.g. {} or {answer:42}). The schema must describe shape via draft-07 keywords (type/properties/items/if-then-else/enum/...); a keyword-less object is rejected to prevent silent accept-all compilation.",
|