This commit is contained in:
NathanFlurry 2026-02-11 14:47:41 +00:00
parent 70287ec471
commit e72eb9f611
No known key found for this signature in database
GPG key ID: 6A5F43A4F3241BCA
264 changed files with 18559 additions and 51021 deletions

View file

@ -1,3 +0,0 @@
node_modules/
.cache/
pnpm-lock.yaml

View file

@ -1,196 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://sandbox-agent/schemas/amp.json",
"title": "AMP Code SDK Schema",
"definitions": {
"StreamJSONMessage": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"system",
"user",
"assistant",
"result",
"message",
"tool_call",
"tool_result",
"error",
"done"
]
},
"id": {
"type": "string"
},
"content": {
"type": "string"
},
"tool_call": {
"$ref": "#/definitions/ToolCall"
},
"error": {
"type": "string"
},
"subtype": {
"type": "string"
},
"cwd": {
"type": "string"
},
"session_id": {
"type": "string"
},
"tools": {
"type": "array",
"items": {
"type": "string"
}
},
"mcp_servers": {
"type": "array",
"items": {
"type": "object"
}
},
"message": {
"type": "object"
},
"parent_tool_use_id": {
"type": "string"
},
"duration_ms": {
"type": "number"
},
"is_error": {
"type": "boolean"
},
"num_turns": {
"type": "number"
},
"result": {
"type": "string"
}
},
"required": [
"type"
]
},
"AmpOptions": {
"type": "object",
"properties": {
"model": {
"type": "string"
},
"apiKey": {
"type": "string"
},
"baseURL": {
"type": "string"
},
"maxTokens": {
"type": "number"
},
"temperature": {
"type": "number"
},
"systemPrompt": {
"type": "string"
},
"tools": {
"type": "array",
"items": {
"type": "object"
}
},
"workingDirectory": {
"type": "string"
},
"permissionRules": {
"type": "array",
"items": {
"$ref": "#/definitions/PermissionRule"
}
}
}
},
"PermissionRule": {
"type": "object",
"properties": {
"tool": {
"type": "string"
},
"action": {
"type": "string",
"enum": [
"allow",
"deny",
"ask"
]
},
"pattern": {
"type": "string"
},
"description": {
"type": "string"
}
},
"required": [
"tool",
"action"
]
},
"Message": {
"type": "object",
"properties": {
"role": {
"type": "string",
"enum": [
"user",
"assistant",
"system"
]
},
"content": {
"type": "string"
},
"tool_calls": {
"type": "array",
"items": {
"$ref": "#/definitions/ToolCall"
}
}
},
"required": [
"role",
"content"
]
},
"ToolCall": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"arguments": {
"oneOf": [
{
"type": "string"
},
{
"type": "object"
}
]
}
},
"required": [
"id",
"name",
"arguments"
]
}
}
}

View file

@ -1,182 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://sandbox-agent/schemas/claude.json",
"title": "Claude Code SDK Schema",
"definitions": {
"SDKMessage": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"user",
"assistant",
"result"
]
},
"content": {
"type": "string"
},
"timestamp": {
"type": "string",
"format": "date-time"
}
},
"required": [
"type"
]
},
"SDKResultMessage": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "result"
},
"result": {
"type": "object"
},
"error": {
"type": "string"
},
"duration_ms": {
"type": "number"
}
},
"required": [
"type"
]
},
"Options": {
"type": "object",
"properties": {
"model": {
"type": "string"
},
"maxTokens": {
"type": "number"
},
"temperature": {
"type": "number"
},
"systemPrompt": {
"type": "string"
},
"tools": {
"type": "array",
"items": {
"type": "string"
}
},
"allowedTools": {
"type": "array",
"items": {
"type": "string"
}
},
"workingDirectory": {
"type": "string"
}
}
},
"BashInput": {
"type": "object",
"properties": {
"command": {
"type": "string"
},
"timeout": {
"type": "number"
},
"workingDirectory": {
"type": "string"
}
},
"required": [
"command"
]
},
"FileEditInput": {
"type": "object",
"properties": {
"path": {
"type": "string"
},
"oldText": {
"type": "string"
},
"newText": {
"type": "string"
}
},
"required": [
"path",
"oldText",
"newText"
]
},
"FileReadInput": {
"type": "object",
"properties": {
"path": {
"type": "string"
},
"startLine": {
"type": "number"
},
"endLine": {
"type": "number"
}
},
"required": [
"path"
]
},
"FileWriteInput": {
"type": "object",
"properties": {
"path": {
"type": "string"
},
"content": {
"type": "string"
}
},
"required": [
"path",
"content"
]
},
"GlobInput": {
"type": "object",
"properties": {
"pattern": {
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"pattern"
]
},
"GrepInput": {
"type": "object",
"properties": {
"pattern": {
"type": "string"
},
"path": {
"type": "string"
},
"include": {
"type": "string"
}
},
"required": [
"pattern"
]
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,695 +0,0 @@
{
"version": "5",
"specifiers": {
"npm:@anthropic-ai/claude-code@latest": "2.1.19",
"npm:@openai/codex@latest": "0.91.0",
"npm:@types/node@22": "22.19.7",
"npm:cheerio@1": "1.2.0",
"npm:ts-json-schema-generator@^2.4.0": "2.4.0",
"npm:tsx@^4.19.0": "4.21.0",
"npm:typescript@^5.7.0": "5.9.3"
},
"npm": {
"@anthropic-ai/claude-code@2.1.19": {
"integrity": "sha512-/bUlQuX/6nKr1Zqfi/9Q6xf7WonUBk72ZfKKENU4WVrIFWqTv/0JJsoW/dHol9QBNHvyfKIeBbYu4avHNRAnuQ==",
"optionalDependencies": [
"@img/sharp-darwin-arm64",
"@img/sharp-darwin-x64",
"@img/sharp-linux-arm",
"@img/sharp-linux-arm64",
"@img/sharp-linux-x64",
"@img/sharp-linuxmusl-arm64",
"@img/sharp-linuxmusl-x64",
"@img/sharp-win32-x64"
],
"bin": true
},
"@esbuild/aix-ppc64@0.27.2": {
"integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==",
"os": ["aix"],
"cpu": ["ppc64"]
},
"@esbuild/android-arm64@0.27.2": {
"integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==",
"os": ["android"],
"cpu": ["arm64"]
},
"@esbuild/android-arm@0.27.2": {
"integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==",
"os": ["android"],
"cpu": ["arm"]
},
"@esbuild/android-x64@0.27.2": {
"integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==",
"os": ["android"],
"cpu": ["x64"]
},
"@esbuild/darwin-arm64@0.27.2": {
"integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==",
"os": ["darwin"],
"cpu": ["arm64"]
},
"@esbuild/darwin-x64@0.27.2": {
"integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==",
"os": ["darwin"],
"cpu": ["x64"]
},
"@esbuild/freebsd-arm64@0.27.2": {
"integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==",
"os": ["freebsd"],
"cpu": ["arm64"]
},
"@esbuild/freebsd-x64@0.27.2": {
"integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==",
"os": ["freebsd"],
"cpu": ["x64"]
},
"@esbuild/linux-arm64@0.27.2": {
"integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==",
"os": ["linux"],
"cpu": ["arm64"]
},
"@esbuild/linux-arm@0.27.2": {
"integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==",
"os": ["linux"],
"cpu": ["arm"]
},
"@esbuild/linux-ia32@0.27.2": {
"integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==",
"os": ["linux"],
"cpu": ["ia32"]
},
"@esbuild/linux-loong64@0.27.2": {
"integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==",
"os": ["linux"],
"cpu": ["loong64"]
},
"@esbuild/linux-mips64el@0.27.2": {
"integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==",
"os": ["linux"],
"cpu": ["mips64el"]
},
"@esbuild/linux-ppc64@0.27.2": {
"integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==",
"os": ["linux"],
"cpu": ["ppc64"]
},
"@esbuild/linux-riscv64@0.27.2": {
"integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==",
"os": ["linux"],
"cpu": ["riscv64"]
},
"@esbuild/linux-s390x@0.27.2": {
"integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==",
"os": ["linux"],
"cpu": ["s390x"]
},
"@esbuild/linux-x64@0.27.2": {
"integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==",
"os": ["linux"],
"cpu": ["x64"]
},
"@esbuild/netbsd-arm64@0.27.2": {
"integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==",
"os": ["netbsd"],
"cpu": ["arm64"]
},
"@esbuild/netbsd-x64@0.27.2": {
"integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==",
"os": ["netbsd"],
"cpu": ["x64"]
},
"@esbuild/openbsd-arm64@0.27.2": {
"integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==",
"os": ["openbsd"],
"cpu": ["arm64"]
},
"@esbuild/openbsd-x64@0.27.2": {
"integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==",
"os": ["openbsd"],
"cpu": ["x64"]
},
"@esbuild/openharmony-arm64@0.27.2": {
"integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==",
"os": ["openharmony"],
"cpu": ["arm64"]
},
"@esbuild/sunos-x64@0.27.2": {
"integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==",
"os": ["sunos"],
"cpu": ["x64"]
},
"@esbuild/win32-arm64@0.27.2": {
"integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==",
"os": ["win32"],
"cpu": ["arm64"]
},
"@esbuild/win32-ia32@0.27.2": {
"integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==",
"os": ["win32"],
"cpu": ["ia32"]
},
"@esbuild/win32-x64@0.27.2": {
"integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==",
"os": ["win32"],
"cpu": ["x64"]
},
"@img/sharp-darwin-arm64@0.33.5": {
"integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
"optionalDependencies": [
"@img/sharp-libvips-darwin-arm64"
],
"os": ["darwin"],
"cpu": ["arm64"]
},
"@img/sharp-darwin-x64@0.33.5": {
"integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
"optionalDependencies": [
"@img/sharp-libvips-darwin-x64"
],
"os": ["darwin"],
"cpu": ["x64"]
},
"@img/sharp-libvips-darwin-arm64@1.0.4": {
"integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
"os": ["darwin"],
"cpu": ["arm64"]
},
"@img/sharp-libvips-darwin-x64@1.0.4": {
"integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
"os": ["darwin"],
"cpu": ["x64"]
},
"@img/sharp-libvips-linux-arm64@1.0.4": {
"integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
"os": ["linux"],
"cpu": ["arm64"]
},
"@img/sharp-libvips-linux-arm@1.0.5": {
"integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
"os": ["linux"],
"cpu": ["arm"]
},
"@img/sharp-libvips-linux-x64@1.0.4": {
"integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
"os": ["linux"],
"cpu": ["x64"]
},
"@img/sharp-libvips-linuxmusl-arm64@1.0.4": {
"integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==",
"os": ["linux"],
"cpu": ["arm64"]
},
"@img/sharp-libvips-linuxmusl-x64@1.0.4": {
"integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==",
"os": ["linux"],
"cpu": ["x64"]
},
"@img/sharp-linux-arm64@0.33.5": {
"integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
"optionalDependencies": [
"@img/sharp-libvips-linux-arm64"
],
"os": ["linux"],
"cpu": ["arm64"]
},
"@img/sharp-linux-arm@0.33.5": {
"integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
"optionalDependencies": [
"@img/sharp-libvips-linux-arm"
],
"os": ["linux"],
"cpu": ["arm"]
},
"@img/sharp-linux-x64@0.33.5": {
"integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
"optionalDependencies": [
"@img/sharp-libvips-linux-x64"
],
"os": ["linux"],
"cpu": ["x64"]
},
"@img/sharp-linuxmusl-arm64@0.33.5": {
"integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==",
"optionalDependencies": [
"@img/sharp-libvips-linuxmusl-arm64"
],
"os": ["linux"],
"cpu": ["arm64"]
},
"@img/sharp-linuxmusl-x64@0.33.5": {
"integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==",
"optionalDependencies": [
"@img/sharp-libvips-linuxmusl-x64"
],
"os": ["linux"],
"cpu": ["x64"]
},
"@img/sharp-win32-x64@0.33.5": {
"integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==",
"os": ["win32"],
"cpu": ["x64"]
},
"@isaacs/balanced-match@4.0.1": {
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="
},
"@isaacs/brace-expansion@5.0.0": {
"integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
"dependencies": [
"@isaacs/balanced-match"
]
},
"@isaacs/cliui@8.0.2": {
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dependencies": [
"string-width@5.1.2",
"string-width-cjs@npm:string-width@4.2.3",
"strip-ansi@7.1.2",
"strip-ansi-cjs@npm:strip-ansi@6.0.1",
"wrap-ansi@8.1.0",
"wrap-ansi-cjs@npm:wrap-ansi@7.0.0"
]
},
"@openai/codex@0.91.0": {
"integrity": "sha512-eRLRg0+uM0g0iW+Ca5VedBk+laslLcq93Hf6rbFtv+gLb4+aMib2UPdvlDlvvCVkBMbvE8ckY/cju+iOOuKCNA==",
"bin": true
},
"@types/json-schema@7.0.15": {
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
},
"@types/node@22.19.7": {
"integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==",
"dependencies": [
"undici-types"
]
},
"ansi-regex@5.0.1": {
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-regex@6.2.2": {
"integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="
},
"ansi-styles@4.3.0": {
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": [
"color-convert"
]
},
"ansi-styles@6.2.3": {
"integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="
},
"boolbase@1.0.0": {
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
},
"cheerio-select@2.1.0": {
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
"dependencies": [
"boolbase",
"css-select",
"css-what",
"domelementtype",
"domhandler",
"domutils"
]
},
"cheerio@1.2.0": {
"integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==",
"dependencies": [
"cheerio-select",
"dom-serializer",
"domhandler",
"domutils",
"encoding-sniffer",
"htmlparser2",
"parse5",
"parse5-htmlparser2-tree-adapter",
"parse5-parser-stream",
"undici",
"whatwg-mimetype"
]
},
"color-convert@2.0.1": {
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": [
"color-name"
]
},
"color-name@1.1.4": {
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"commander@13.1.0": {
"integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="
},
"cross-spawn@7.0.6": {
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dependencies": [
"path-key",
"shebang-command",
"which"
]
},
"css-select@5.2.2": {
"integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
"dependencies": [
"boolbase",
"css-what",
"domhandler",
"domutils",
"nth-check"
]
},
"css-what@6.2.2": {
"integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="
},
"dom-serializer@2.0.0": {
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"dependencies": [
"domelementtype",
"domhandler",
"entities@4.5.0"
]
},
"domelementtype@2.3.0": {
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
},
"domhandler@5.0.3": {
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"dependencies": [
"domelementtype"
]
},
"domutils@3.2.2": {
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
"dependencies": [
"dom-serializer",
"domelementtype",
"domhandler"
]
},
"eastasianwidth@0.2.0": {
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"emoji-regex@8.0.0": {
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"emoji-regex@9.2.2": {
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
"encoding-sniffer@0.2.1": {
"integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==",
"dependencies": [
"iconv-lite",
"whatwg-encoding"
]
},
"entities@4.5.0": {
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
},
"entities@6.0.1": {
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="
},
"entities@7.0.1": {
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="
},
"esbuild@0.27.2": {
"integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
"optionalDependencies": [
"@esbuild/aix-ppc64",
"@esbuild/android-arm",
"@esbuild/android-arm64",
"@esbuild/android-x64",
"@esbuild/darwin-arm64",
"@esbuild/darwin-x64",
"@esbuild/freebsd-arm64",
"@esbuild/freebsd-x64",
"@esbuild/linux-arm",
"@esbuild/linux-arm64",
"@esbuild/linux-ia32",
"@esbuild/linux-loong64",
"@esbuild/linux-mips64el",
"@esbuild/linux-ppc64",
"@esbuild/linux-riscv64",
"@esbuild/linux-s390x",
"@esbuild/linux-x64",
"@esbuild/netbsd-arm64",
"@esbuild/netbsd-x64",
"@esbuild/openbsd-arm64",
"@esbuild/openbsd-x64",
"@esbuild/openharmony-arm64",
"@esbuild/sunos-x64",
"@esbuild/win32-arm64",
"@esbuild/win32-ia32",
"@esbuild/win32-x64"
],
"scripts": true,
"bin": true
},
"foreground-child@3.3.1": {
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
"dependencies": [
"cross-spawn",
"signal-exit"
]
},
"fsevents@2.3.3": {
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"os": ["darwin"],
"scripts": true
},
"get-tsconfig@4.13.0": {
"integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
"dependencies": [
"resolve-pkg-maps"
]
},
"glob@11.1.0": {
"integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
"dependencies": [
"foreground-child",
"jackspeak",
"minimatch",
"minipass",
"package-json-from-dist",
"path-scurry"
],
"bin": true
},
"htmlparser2@10.1.0": {
"integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==",
"dependencies": [
"domelementtype",
"domhandler",
"domutils",
"entities@7.0.1"
]
},
"iconv-lite@0.6.3": {
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dependencies": [
"safer-buffer"
]
},
"is-fullwidth-code-point@3.0.0": {
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"isexe@2.0.0": {
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"jackspeak@4.1.1": {
"integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
"dependencies": [
"@isaacs/cliui"
]
},
"json5@2.2.3": {
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"bin": true
},
"lru-cache@11.2.5": {
"integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw=="
},
"minimatch@10.1.1": {
"integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
"dependencies": [
"@isaacs/brace-expansion"
]
},
"minipass@7.1.2": {
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="
},
"normalize-path@3.0.0": {
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
},
"nth-check@2.1.1": {
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"dependencies": [
"boolbase"
]
},
"package-json-from-dist@1.0.1": {
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
},
"parse5-htmlparser2-tree-adapter@7.1.0": {
"integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
"dependencies": [
"domhandler",
"parse5"
]
},
"parse5-parser-stream@7.1.2": {
"integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
"dependencies": [
"parse5"
]
},
"parse5@7.3.0": {
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
"dependencies": [
"entities@6.0.1"
]
},
"path-key@3.1.1": {
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
},
"path-scurry@2.0.1": {
"integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==",
"dependencies": [
"lru-cache",
"minipass"
]
},
"resolve-pkg-maps@1.0.0": {
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="
},
"safe-stable-stringify@2.5.0": {
"integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="
},
"safer-buffer@2.1.2": {
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"shebang-command@2.0.0": {
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dependencies": [
"shebang-regex"
]
},
"shebang-regex@3.0.0": {
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
},
"signal-exit@4.1.0": {
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="
},
"string-width@4.2.3": {
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dependencies": [
"emoji-regex@8.0.0",
"is-fullwidth-code-point",
"strip-ansi@6.0.1"
]
},
"string-width@5.1.2": {
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dependencies": [
"eastasianwidth",
"emoji-regex@9.2.2",
"strip-ansi@7.1.2"
]
},
"strip-ansi@6.0.1": {
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dependencies": [
"ansi-regex@5.0.1"
]
},
"strip-ansi@7.1.2": {
"integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
"dependencies": [
"ansi-regex@6.2.2"
]
},
"ts-json-schema-generator@2.4.0": {
"integrity": "sha512-HbmNsgs58CfdJq0gpteRTxPXG26zumezOs+SB9tgky6MpqiFgQwieCn2MW70+sxpHouZ/w9LW0V6L4ZQO4y1Ug==",
"dependencies": [
"@types/json-schema",
"commander",
"glob",
"json5",
"normalize-path",
"safe-stable-stringify",
"tslib",
"typescript"
],
"bin": true
},
"tslib@2.8.1": {
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"tsx@4.21.0": {
"integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
"dependencies": [
"esbuild",
"get-tsconfig"
],
"optionalDependencies": [
"fsevents"
],
"bin": true
},
"typescript@5.9.3": {
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"bin": true
},
"undici-types@6.21.0": {
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="
},
"undici@7.19.1": {
"integrity": "sha512-Gpq0iNm5M6cQWlyHQv9MV+uOj1jWk7LpkoE5vSp/7zjb4zMdAcUD+VL5y0nH4p9EbUklq00eVIIX/XcDHzu5xg=="
},
"whatwg-encoding@3.1.1": {
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
"dependencies": [
"iconv-lite"
],
"deprecated": true
},
"whatwg-mimetype@4.0.0": {
"integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="
},
"which@2.0.2": {
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dependencies": [
"isexe"
],
"bin": true
},
"wrap-ansi@7.0.0": {
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dependencies": [
"ansi-styles@4.3.0",
"string-width@4.2.3",
"strip-ansi@6.0.1"
]
},
"wrap-ansi@8.1.0": {
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dependencies": [
"ansi-styles@6.2.3",
"string-width@5.1.2",
"strip-ansi@7.1.2"
]
}
},
"workspace": {
"packageJson": {
"dependencies": [
"npm:@anthropic-ai/claude-code@latest",
"npm:@openai/codex@latest",
"npm:@types/node@22",
"npm:cheerio@1",
"npm:ts-json-schema-generator@^2.4.0",
"npm:tsx@^4.19.0",
"npm:typescript@^5.7.0"
]
}
}
}

View file

@ -1,31 +0,0 @@
{
"name": "agent-schemas",
"version": "1.0.0",
"type": "module",
"license": "Apache-2.0",
"scripts": {
"extract": "tsx src/index.ts",
"extract:opencode": "tsx src/index.ts --agent=opencode",
"extract:claude": "tsx src/index.ts --agent=claude",
"extract:codex": "tsx src/index.ts --agent=codex",
"extract:amp": "tsx src/index.ts --agent=amp",
"extract:pi": "tsx src/index.ts --agent=pi",
"extract:claude-events": "tsx src/claude-event-types.ts",
"extract:claude-events:sdk": "tsx src/claude-event-types-sdk.ts",
"extract:claude-events:cli": "tsx src/claude-event-types-cli.ts",
"extract:claude-events:docs": "tsx src/claude-event-types-docs.ts",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"ts-json-schema-generator": "^2.4.0",
"cheerio": "^1.0.0",
"typescript": "^5.7.0",
"@anthropic-ai/claude-code": "latest",
"@openai/codex": "latest"
},
"devDependencies": {
"tsx": "^4.19.0",
"@types/node": "^22.0.0",
"@types/json-schema": "^7.0.15"
}
}

View file

@ -1,286 +0,0 @@
import * as cheerio from "cheerio";
import { fetchWithCache } from "./cache.js";
import { createNormalizedSchema, type NormalizedSchema } from "./normalize.js";
import type { JSONSchema7 } from "json-schema";
const AMP_DOCS_URL = "https://ampcode.com/manual/appendix?preview#message-schema";
// Key types we want to extract
const TARGET_TYPES = ["StreamJSONMessage", "AmpOptions", "PermissionRule", "Message", "ToolCall"];
export async function extractAmpSchema(): Promise<NormalizedSchema> {
console.log("Extracting AMP schema from documentation...");
try {
const html = await fetchWithCache(AMP_DOCS_URL);
const $ = cheerio.load(html);
// Find TypeScript code blocks
const codeBlocks: string[] = [];
$("pre code").each((_, el) => {
const code = $(el).text();
// Look for TypeScript interface/type definitions
if (
code.includes("interface ") ||
code.includes("type ") ||
code.includes(": {") ||
code.includes("export ")
) {
codeBlocks.push(code);
}
});
if (codeBlocks.length === 0) {
console.log(" [warn] No TypeScript code blocks found, using fallback schema");
return createFallbackSchema();
}
console.log(` [found] ${codeBlocks.length} code blocks`);
// Parse TypeScript definitions into schemas
const definitions = parseTypeScriptToSchema(codeBlocks.join("\n"));
// Verify target types exist
const found = TARGET_TYPES.filter((name) => definitions[name]);
const missing = TARGET_TYPES.filter((name) => !definitions[name]);
if (missing.length > 0) {
console.log(` [warn] Missing expected types: ${missing.join(", ")}`);
}
if (Object.keys(definitions).length === 0) {
console.log(" [warn] No types extracted, using fallback schema");
return createFallbackSchema();
}
console.log(` [ok] Extracted ${Object.keys(definitions).length} types (${found.length} target types)`);
return createNormalizedSchema("amp", "AMP Code SDK Schema", definitions);
} catch (error) {
console.log(` [error] Failed to fetch docs: ${error}`);
console.log(" [fallback] Using embedded schema definitions");
return createFallbackSchema();
}
}
function parseTypeScriptToSchema(code: string): Record<string, JSONSchema7> {
const definitions: Record<string, JSONSchema7> = {};
// Match interface definitions
const interfaceRegex = /(?:export\s+)?interface\s+(\w+)\s*(?:extends\s+[\w,\s]+)?\s*\{([^}]+)\}/g;
let match;
while ((match = interfaceRegex.exec(code)) !== null) {
const [, name, body] = match;
definitions[name] = parseInterfaceBody(body);
}
// Match type definitions (simple object types)
const typeRegex = /(?:export\s+)?type\s+(\w+)\s*=\s*\{([^}]+)\}/g;
while ((match = typeRegex.exec(code)) !== null) {
const [, name, body] = match;
definitions[name] = parseInterfaceBody(body);
}
// Match union type definitions
const unionRegex = /(?:export\s+)?type\s+(\w+)\s*=\s*([^;{]+);/g;
while ((match = unionRegex.exec(code)) !== null) {
const [, name, body] = match;
if (body.includes("|")) {
definitions[name] = parseUnionType(body);
}
}
return definitions;
}
function parseInterfaceBody(body: string): JSONSchema7 {
const properties: Record<string, JSONSchema7> = {};
const required: string[] = [];
// Match property definitions
const propRegex = /(\w+)(\?)?:\s*([^;]+);/g;
let match;
while ((match = propRegex.exec(body)) !== null) {
const [, propName, optional, propType] = match;
properties[propName] = typeToSchema(propType.trim());
if (!optional) {
required.push(propName);
}
}
const schema: JSONSchema7 = {
type: "object",
properties,
};
if (required.length > 0) {
schema.required = required;
}
return schema;
}
function typeToSchema(tsType: string): JSONSchema7 {
// Handle union types
if (tsType.includes("|")) {
return parseUnionType(tsType);
}
// Handle array types
if (tsType.endsWith("[]")) {
const itemType = tsType.slice(0, -2);
return {
type: "array",
items: typeToSchema(itemType),
};
}
// Handle Array<T>
const arrayMatch = tsType.match(/^Array<(.+)>$/);
if (arrayMatch) {
return {
type: "array",
items: typeToSchema(arrayMatch[1]),
};
}
// Handle basic types
switch (tsType) {
case "string":
return { type: "string" };
case "number":
return { type: "number" };
case "boolean":
return { type: "boolean" };
case "null":
return { type: "null" };
case "any":
case "unknown":
return {};
case "object":
return { type: "object" };
default:
// Could be a reference to another type
if (/^[A-Z]/.test(tsType)) {
return { $ref: `#/definitions/${tsType}` };
}
// String literal
if (tsType.startsWith('"') || tsType.startsWith("'")) {
return { type: "string", const: tsType.slice(1, -1) };
}
return { type: "string" };
}
}
function parseUnionType(unionStr: string): JSONSchema7 {
const parts = unionStr.split("|").map((p) => p.trim());
// Check if it's a string literal union
const allStringLiterals = parts.every((p) => p.startsWith('"') || p.startsWith("'"));
if (allStringLiterals) {
return {
type: "string",
enum: parts.map((p) => p.slice(1, -1)),
};
}
// General union
return {
oneOf: parts.map((p) => typeToSchema(p)),
};
}
function createFallbackSchema(): NormalizedSchema {
// Fallback schema based on AMP documentation structure
const definitions: Record<string, JSONSchema7> = {
StreamJSONMessage: {
type: "object",
properties: {
type: {
type: "string",
enum: ["system", "user", "assistant", "result", "message", "tool_call", "tool_result", "error", "done"],
},
// Common fields
id: { type: "string" },
content: { type: "string" },
tool_call: { $ref: "#/definitions/ToolCall" },
error: { type: "string" },
// System message fields
subtype: { type: "string" },
cwd: { type: "string" },
session_id: { type: "string" },
tools: { type: "array", items: { type: "string" } },
mcp_servers: { type: "array", items: { type: "object" } },
// User/Assistant message fields
message: { type: "object" },
parent_tool_use_id: { type: "string" },
// Result fields
duration_ms: { type: "number" },
is_error: { type: "boolean" },
num_turns: { type: "number" },
result: { type: "string" },
},
required: ["type"],
},
AmpOptions: {
type: "object",
properties: {
model: { type: "string" },
apiKey: { type: "string" },
baseURL: { type: "string" },
maxTokens: { type: "number" },
temperature: { type: "number" },
systemPrompt: { type: "string" },
tools: { type: "array", items: { type: "object" } },
workingDirectory: { type: "string" },
permissionRules: {
type: "array",
items: { $ref: "#/definitions/PermissionRule" },
},
},
},
PermissionRule: {
type: "object",
properties: {
tool: { type: "string" },
action: { type: "string", enum: ["allow", "deny", "ask"] },
pattern: { type: "string" },
description: { type: "string" },
},
required: ["tool", "action"],
},
Message: {
type: "object",
properties: {
role: { type: "string", enum: ["user", "assistant", "system"] },
content: { type: "string" },
tool_calls: {
type: "array",
items: { $ref: "#/definitions/ToolCall" },
},
},
required: ["role", "content"],
},
ToolCall: {
type: "object",
properties: {
id: { type: "string" },
name: { type: "string" },
arguments: {
oneOf: [{ type: "string" }, { type: "object" }],
},
},
required: ["id", "name", "arguments"],
},
};
console.log(` [ok] Using fallback schema with ${Object.keys(definitions).length} definitions`);
return createNormalizedSchema("amp", "AMP Code SDK Schema", definitions);
}

View file

@ -1,101 +0,0 @@
import { createHash } from "crypto";
import { existsSync, mkdirSync, readFileSync, writeFileSync, statSync } from "fs";
import { join } from "path";
const CACHE_DIR = join(
import.meta.dirname,
"..",
"..",
"resources",
"agent-schemas",
".cache"
);
const DEFAULT_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
interface CacheEntry<T> {
data: T;
timestamp: number;
ttl: number;
}
function ensureCacheDir(): void {
if (!existsSync(CACHE_DIR)) {
mkdirSync(CACHE_DIR, { recursive: true });
}
}
function hashKey(key: string): string {
return createHash("sha256").update(key).digest("hex");
}
function getCachePath(key: string): string {
return join(CACHE_DIR, `${hashKey(key)}.json`);
}
export function getCached<T>(key: string): T | null {
const path = getCachePath(key);
if (!existsSync(path)) {
return null;
}
try {
const content = readFileSync(path, "utf-8");
const entry: CacheEntry<T> = JSON.parse(content);
const now = Date.now();
if (now - entry.timestamp > entry.ttl) {
// Cache expired
return null;
}
return entry.data;
} catch {
return null;
}
}
export function setCache<T>(key: string, data: T, ttl: number = DEFAULT_TTL_MS): void {
ensureCacheDir();
const entry: CacheEntry<T> = {
data,
timestamp: Date.now(),
ttl,
};
const path = getCachePath(key);
writeFileSync(path, JSON.stringify(entry, null, 2));
}
export async function fetchWithCache(url: string, ttl?: number): Promise<string> {
const cached = getCached<string>(url);
if (cached !== null) {
console.log(` [cache hit] ${url}`);
return cached;
}
console.log(` [fetching] ${url}`);
let lastError: Error | null = null;
for (let attempt = 0; attempt < 3; attempt++) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const text = await response.text();
setCache(url, text, ttl);
return text;
} catch (error) {
lastError = error as Error;
if (attempt < 2) {
const delay = Math.pow(2, attempt) * 1000;
console.log(` [retry ${attempt + 1}] waiting ${delay}ms...`);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}
throw lastError;
}

View file

@ -1,11 +0,0 @@
import { collectFromCli } from "./claude-event-types.js";
const promptArg = process.argv.slice(2).find((arg) => arg.startsWith("--prompt="));
const timeoutArg = process.argv.slice(2).find((arg) => arg.startsWith("--timeoutMs="));
const prompt = promptArg?.split("=")[1] ?? "Reply with exactly OK.";
const timeoutMs = timeoutArg ? Number(timeoutArg.split("=")[1]) : 20000;
collectFromCli(prompt, timeoutMs).then((result) => {
console.log(JSON.stringify(result, null, 2));
});

View file

@ -1,8 +0,0 @@
import { collectFromDocs } from "./claude-event-types.js";
const urlsArg = process.argv.slice(2).find((arg) => arg.startsWith("--urls="));
const urls = urlsArg ? urlsArg.split("=")[1]!.split(",") : undefined;
collectFromDocs(urls ?? []).then((result) => {
console.log(JSON.stringify(result, null, 2));
});

View file

@ -1,4 +0,0 @@
import { collectFromSdkTypes } from "./claude-event-types.js";
const result = collectFromSdkTypes();
console.log(JSON.stringify(result, null, 2));

View file

@ -1,338 +0,0 @@
import { readFileSync, existsSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { spawn } from "node:child_process";
import ts from "typescript";
import { load } from "cheerio";
type SourceResult = {
source: string;
types: string[];
details?: Record<string, string[]>;
error?: string;
};
const SDK_POSSIBLE_PATHS = [
"node_modules/@anthropic-ai/claude-code/sdk-tools.d.ts",
"node_modules/@anthropic-ai/claude-code/dist/index.d.ts",
"node_modules/@anthropic-ai/claude-code/dist/types.d.ts",
"node_modules/@anthropic-ai/claude-code/index.d.ts",
];
const DEFAULT_DOC_URLS = [
"https://platform.claude.com/docs/en/messages-streaming",
"https://platform.claude.com/docs/en/api/messages-streaming",
"https://docs.anthropic.com/claude/reference/messages-streaming",
"https://docs.anthropic.com/claude/reference/messages-streaming#events",
"https://docs.anthropic.com/claude/docs/messages-streaming",
];
function moduleDir(): string {
const metaDir = (import.meta as { dirname?: string }).dirname;
if (typeof metaDir === "string") {
return metaDir;
}
return dirname(fileURLToPath(import.meta.url));
}
function findSdkTypesPath(): string | null {
const resourceDir = join(moduleDir(), "..");
const repoRoot = join(moduleDir(), "..", "..", "..");
const searchRoots = [resourceDir, repoRoot];
for (const root of searchRoots) {
for (const relativePath of SDK_POSSIBLE_PATHS) {
const fullPath = join(root, relativePath);
if (existsSync(fullPath)) {
return fullPath;
}
}
}
return null;
}
function extractStringLiterals(node: ts.TypeNode): string[] {
if (ts.isLiteralTypeNode(node) && ts.isStringLiteral(node.literal)) {
return [node.literal.text];
}
if (ts.isUnionTypeNode(node)) {
return node.types.flatMap((typeNode) => extractStringLiterals(typeNode));
}
return [];
}
function containerName(node: ts.Node): string | null {
let current: ts.Node | undefined = node;
while (current) {
if (ts.isInterfaceDeclaration(current) && current.name) {
return current.name.text;
}
if (ts.isTypeAliasDeclaration(current) && current.name) {
return current.name.text;
}
current = current.parent;
}
return null;
}
function collectFromSdkTypes(): SourceResult {
const path = findSdkTypesPath();
if (!path) {
return { source: "sdk", types: [], error: "Claude SDK types not found" };
}
const content = readFileSync(path, "utf8");
const sourceFile = ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true);
const types = new Set<string>();
const details: Record<string, string[]> = {};
function visit(node: ts.Node): void {
if (ts.isPropertySignature(node)) {
const name = node.name && ts.isIdentifier(node.name) ? node.name.text : null;
if (name === "type" && node.type) {
const literals = extractStringLiterals(node.type);
if (literals.length > 0) {
const parentName = containerName(node) ?? "anonymous";
if (/Event|Stream|Message/i.test(parentName)) {
literals.forEach((value) => types.add(value));
details[parentName] = (details[parentName] ?? []).concat(literals);
}
}
}
}
ts.forEachChild(node, visit);
}
visit(sourceFile);
return { source: "sdk", types: Array.from(types).sort(), details };
}
function collectFromCli(prompt: string, timeoutMs: number): Promise<SourceResult> {
return new Promise((resolve) => {
const result: SourceResult = { source: "cli", types: [] };
const types = new Set<string>();
const denoGlobal = (globalThis as {
Deno?: {
which?: (cmd: string) => string | null;
Command?: new (
cmd: string,
options: { args: string[]; stdout: "piped"; stderr: "piped" },
) => { output: () => Promise<{ stdout: Uint8Array; stderr: Uint8Array; code: number }> };
};
}).Deno;
if (denoGlobal?.which && !denoGlobal.which("claude")) {
result.error = "claude binary not found in PATH";
resolve(result);
return;
}
if (denoGlobal?.Command) {
const command = new denoGlobal.Command("claude", {
args: ["--print", "--output-format", "stream-json", "--verbose", prompt],
stdout: "piped",
stderr: "piped",
});
try {
command
.output()
.then(({ stdout, stderr, code }) => {
const text = new TextDecoder().decode(stdout);
for (const line of text.split("\n")) {
const trimmed = line.trim();
if (!trimmed) continue;
try {
const value = JSON.parse(trimmed);
if (value && typeof value.type === "string") {
types.add(value.type);
}
} catch {
// ignore non-json
}
}
result.types = Array.from(types).sort();
if (code !== 0) {
result.error =
new TextDecoder().decode(stderr).trim() ||
`claude exited with code ${code}`;
}
resolve(result);
})
.catch((error) => {
result.error = error instanceof Error ? error.message : String(error);
resolve(result);
});
} catch (error) {
result.error = error instanceof Error ? error.message : String(error);
resolve(result);
}
return;
}
let child;
try {
child = spawn(
"claude",
["--print", "--output-format", "stream-json", "--verbose", prompt],
{ stdio: ["ignore", "pipe", "pipe"] },
);
} catch (error) {
result.error = error instanceof Error ? error.message : String(error);
resolve(result);
return;
}
if (!child.stdout || !child.stderr) {
result.error = "claude stdout/stderr not available";
resolve(result);
return;
}
let stderr = "";
const timer = setTimeout(() => {
child.kill("SIGKILL");
}, timeoutMs);
child.stdout.on("data", (chunk) => {
const text = chunk.toString("utf8");
for (const line of text.split("\n")) {
const trimmed = line.trim();
if (!trimmed) continue;
try {
const value = JSON.parse(trimmed);
if (value && typeof value.type === "string") {
types.add(value.type);
}
} catch {
// ignore non-json
}
}
});
child.stderr.on("data", (chunk) => {
stderr += chunk.toString("utf8");
});
child.on("close", (code) => {
clearTimeout(timer);
result.types = Array.from(types).sort();
if (code !== 0) {
result.error = stderr.trim() || `claude exited with code ${code}`;
}
resolve(result);
});
});
}
async function collectFromDocs(urls: string[]): Promise<SourceResult> {
if (typeof fetch !== "function") {
return { source: "docs", types: [], error: "fetch is not available in this runtime" };
}
const effectiveUrls = urls.length > 0 ? urls : DEFAULT_DOC_URLS;
const types = new Set<string>();
const extractFromText = (text: string) => {
const typeMatches = text.match(/\"type\"\\s*:\\s*\"([^\"]+)\"/g) ?? [];
for (const match of typeMatches) {
const value = match.split(":")[1]?.trim().replace(/^\"|\"$/g, "");
if (value) types.add(value);
}
const eventMatches = text.match(/event\\s*:\\s*([a-z_]+)/gi) ?? [];
for (const match of eventMatches) {
const value = match.split(":")[1]?.trim();
if (value) types.add(value);
}
};
for (const url of effectiveUrls) {
try {
const res = await fetch(url);
if (!res.ok) {
continue;
}
const html = await res.text();
const $ = load(html);
const blocks = $("pre, code")
.map((_, el) => $(el).text())
.get();
for (const block of blocks) {
extractFromText(block);
}
const nextData = $("#__NEXT_DATA__").text();
if (nextData) {
extractFromText(nextData);
}
extractFromText(html);
} catch {
// ignore per-url errors
}
}
return { source: "docs", types: Array.from(types).sort() };
}
type Args = {
source: "all" | "sdk" | "cli" | "docs";
prompt: string;
timeoutMs: number;
urls: string[];
json: boolean;
};
function parseArgs(): Args {
const args = process.argv.slice(2);
const sourceArg = args.find((arg) => arg.startsWith("--source="));
const promptArg = args.find((arg) => arg.startsWith("--prompt="));
const timeoutArg = args.find((arg) => arg.startsWith("--timeoutMs="));
const urlsArg = args.find((arg) => arg.startsWith("--urls="));
const json = args.includes("--json");
return {
source: (sourceArg?.split("=")[1] as Args["source"]) ?? "all",
prompt: promptArg?.split("=")[1] ?? "Reply with exactly OK.",
timeoutMs: timeoutArg ? Number(timeoutArg.split("=")[1]) : 20000,
urls: urlsArg ? urlsArg.split("=")[1]!.split(",") : DEFAULT_DOC_URLS,
json,
};
}
function summarize(results: SourceResult[]): void {
const counts = results.map((r) => ({ source: r.source, count: r.types.length }));
const max = Math.max(...counts.map((c) => c.count), 0);
const best = counts.filter((c) => c.count === max).map((c) => c.source);
const union = Array.from(
new Set(results.flatMap((r) => r.types))
).sort();
console.log("Claude event type extraction");
console.log("============================");
for (const result of results) {
console.log(`- ${result.source}: ${result.types.length} types${result.error ? " (error)" : ""}`);
}
console.log(`\nMost comprehensive: ${best.join(", ") || "none"}`);
console.log(`Union (${union.length}): ${union.join(", ")}`);
}
async function main(): Promise<void> {
const args = parseArgs();
const results: SourceResult[] = [];
if (args.source === "all" || args.source === "sdk") {
results.push(collectFromSdkTypes());
}
if (args.source === "all" || args.source === "cli") {
results.push(await collectFromCli(args.prompt, args.timeoutMs));
}
if (args.source === "all" || args.source === "docs") {
results.push(await collectFromDocs(args.urls));
}
if (args.json) {
console.log(JSON.stringify({ results }, null, 2));
return;
}
summarize(results);
}
main().catch((error) => {
console.error("Fatal error:", error);
process.exit(1);
});
export { collectFromCli, collectFromDocs, collectFromSdkTypes };

View file

@ -1,137 +0,0 @@
import { execSync } from "child_process";
import { createNormalizedSchema, type NormalizedSchema } from "./normalize.js";
import type { JSONSchema7 } from "json-schema";
export async function extractClaudeSchema(): Promise<NormalizedSchema> {
console.log("Extracting Claude Code schema via CLI...");
try {
// Run claude CLI with --json-schema flag to get the schema
const output = execSync("claude --output-format json --json-schema", {
encoding: "utf-8",
timeout: 30000,
stdio: ["pipe", "pipe", "pipe"],
});
// Parse the JSON output
const parsed = JSON.parse(output);
// Extract definitions from the schema
const definitions: Record<string, JSONSchema7> = {};
if (parsed.definitions) {
for (const [name, def] of Object.entries(parsed.definitions)) {
definitions[name] = def as JSONSchema7;
}
} else if (parsed.$defs) {
for (const [name, def] of Object.entries(parsed.$defs)) {
definitions[name] = def as JSONSchema7;
}
} else {
// The output might be a single schema, use it as the root
definitions["Schema"] = parsed as JSONSchema7;
}
console.log(` [ok] Extracted ${Object.keys(definitions).length} types from CLI`);
return createNormalizedSchema("claude", "Claude Code SDK Schema", definitions);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.log(` [warn] CLI extraction failed: ${errorMessage}`);
console.log(" [fallback] Using embedded schema definitions");
return createFallbackSchema();
}
}
function createFallbackSchema(): NormalizedSchema {
// Fallback schema based on known SDK structure
const definitions: Record<string, JSONSchema7> = {
SDKMessage: {
type: "object",
properties: {
type: { type: "string", enum: ["user", "assistant", "result"] },
content: { type: "string" },
timestamp: { type: "string", format: "date-time" },
},
required: ["type"],
},
SDKResultMessage: {
type: "object",
properties: {
type: { type: "string", const: "result" },
result: { type: "object" },
error: { type: "string" },
duration_ms: { type: "number" },
},
required: ["type"],
},
Options: {
type: "object",
properties: {
model: { type: "string" },
maxTokens: { type: "number" },
temperature: { type: "number" },
systemPrompt: { type: "string" },
tools: { type: "array", items: { type: "string" } },
allowedTools: { type: "array", items: { type: "string" } },
workingDirectory: { type: "string" },
},
},
BashInput: {
type: "object",
properties: {
command: { type: "string" },
timeout: { type: "number" },
workingDirectory: { type: "string" },
},
required: ["command"],
},
FileEditInput: {
type: "object",
properties: {
path: { type: "string" },
oldText: { type: "string" },
newText: { type: "string" },
},
required: ["path", "oldText", "newText"],
},
FileReadInput: {
type: "object",
properties: {
path: { type: "string" },
startLine: { type: "number" },
endLine: { type: "number" },
},
required: ["path"],
},
FileWriteInput: {
type: "object",
properties: {
path: { type: "string" },
content: { type: "string" },
},
required: ["path", "content"],
},
GlobInput: {
type: "object",
properties: {
pattern: { type: "string" },
path: { type: "string" },
},
required: ["pattern"],
},
GrepInput: {
type: "object",
properties: {
pattern: { type: "string" },
path: { type: "string" },
include: { type: "string" },
},
required: ["pattern"],
},
};
console.log(` [ok] Using fallback schema with ${Object.keys(definitions).length} definitions`);
return createNormalizedSchema("claude", "Claude Code SDK Schema", definitions);
}

View file

@ -1,181 +0,0 @@
import { execSync } from "child_process";
import { existsSync, readFileSync, rmSync, readdirSync } from "fs";
import { join } from "path";
import { createNormalizedSchema, type NormalizedSchema } from "./normalize.js";
import type { JSONSchema7 } from "json-schema";
function normalizeCodexRefs(value: JSONSchema7): JSONSchema7 {
if (Array.isArray(value)) {
return value.map((item) => normalizeCodexRefs(item as JSONSchema7)) as JSONSchema7;
}
if (value && typeof value === "object") {
const next: Record<string, JSONSchema7> = {};
for (const [key, child] of Object.entries(value)) {
if (key === "$ref" && typeof child === "string") {
next[key] = child.replace("#/definitions/v2/", "#/definitions/") as JSONSchema7;
continue;
}
next[key] = normalizeCodexRefs(child as JSONSchema7);
}
return next as JSONSchema7;
}
return value;
}
export async function extractCodexSchema(): Promise<NormalizedSchema> {
console.log("Extracting Codex schema via CLI...");
const tempDir = join(import.meta.dirname, "..", ".temp-codex-schemas");
try {
// Run codex CLI to generate JSON schema
execSync(`codex app-server generate-json-schema --out "${tempDir}"`, {
encoding: "utf-8",
timeout: 30000,
stdio: ["pipe", "pipe", "pipe"],
});
// Read generated schema files from temp directory
const definitions: Record<string, JSONSchema7> = {};
if (existsSync(tempDir)) {
const files = readdirSync(tempDir).filter((f) => f.endsWith(".json"));
for (const file of files) {
const filePath = join(tempDir, file);
const content = readFileSync(filePath, "utf-8");
const schema = JSON.parse(content);
// Extract the name from the file (e.g., "ThreadEvent.json" -> "ThreadEvent")
const name = file.replace(".json", "");
if (schema.definitions) {
for (const [defName, def] of Object.entries(schema.definitions)) {
definitions[defName] = normalizeCodexRefs(def as JSONSchema7);
}
} else if (schema.$defs) {
for (const [defName, def] of Object.entries(schema.$defs)) {
definitions[defName] = normalizeCodexRefs(def as JSONSchema7);
}
} else {
definitions[name] = normalizeCodexRefs(schema as JSONSchema7);
}
}
// Clean up temp directory
rmSync(tempDir, { recursive: true, force: true });
}
if (Object.keys(definitions).length === 0) {
console.log(" [warn] No schemas extracted from CLI, using fallback");
return createFallbackSchema();
}
console.log(` [ok] Extracted ${Object.keys(definitions).length} types from CLI`);
return createNormalizedSchema("codex", "Codex SDK Schema", definitions);
} catch (error) {
// Clean up temp directory on error
if (existsSync(tempDir)) {
rmSync(tempDir, { recursive: true, force: true });
}
const errorMessage = error instanceof Error ? error.message : String(error);
console.log(` [warn] CLI extraction failed: ${errorMessage}`);
console.log(" [fallback] Using embedded schema definitions");
return createFallbackSchema();
}
}
function createFallbackSchema(): NormalizedSchema {
// Fallback schema based on known SDK structure
const definitions: Record<string, JSONSchema7> = {
ThreadEvent: {
type: "object",
properties: {
type: {
type: "string",
enum: ["thread.created", "thread.updated", "item.created", "item.updated", "error"],
},
thread_id: { type: "string" },
item: { $ref: "#/definitions/ThreadItem" },
error: { type: "object" },
},
required: ["type"],
},
ThreadItem: {
type: "object",
properties: {
id: { type: "string" },
type: { type: "string", enum: ["message", "function_call", "function_result"] },
role: { type: "string", enum: ["user", "assistant", "system"] },
content: {
oneOf: [{ type: "string" }, { type: "array", items: { type: "object" } }],
},
status: { type: "string", enum: ["pending", "in_progress", "completed", "failed"] },
},
required: ["id", "type"],
},
CodexOptions: {
type: "object",
properties: {
apiKey: { type: "string" },
model: { type: "string" },
baseURL: { type: "string" },
maxTokens: { type: "number" },
temperature: { type: "number" },
},
},
ThreadOptions: {
type: "object",
properties: {
instructions: { type: "string" },
tools: { type: "array", items: { type: "object" } },
model: { type: "string" },
workingDirectory: { type: "string" },
},
},
Input: {
type: "object",
properties: {
type: { type: "string", enum: ["text", "file", "image"] },
content: { type: "string" },
path: { type: "string" },
mimeType: { type: "string" },
},
required: ["type"],
},
ResponseItem: {
type: "object",
properties: {
type: { type: "string" },
id: { type: "string" },
content: { type: "string" },
function_call: { $ref: "#/definitions/FunctionCall" },
},
},
FunctionCall: {
type: "object",
properties: {
name: { type: "string" },
arguments: { type: "string" },
call_id: { type: "string" },
},
required: ["name", "arguments"],
},
Message: {
type: "object",
properties: {
role: { type: "string", enum: ["user", "assistant", "system"] },
content: { type: "string" },
},
required: ["role", "content"],
},
};
console.log(` [ok] Using fallback schema with ${Object.keys(definitions).length} definitions`);
return createNormalizedSchema("codex", "Codex SDK Schema", definitions);
}

View file

@ -1,112 +0,0 @@
import { writeFileSync, existsSync, mkdirSync } from "fs";
import { join } from "path";
import { extractOpenCodeSchema } from "./opencode.js";
import { extractClaudeSchema } from "./claude.js";
import { extractCodexSchema } from "./codex.js";
import { extractAmpSchema } from "./amp.js";
import { extractPiSchema } from "./pi.js";
import { validateSchema, type NormalizedSchema } from "./normalize.js";
const RESOURCE_DIR = join(import.meta.dirname, "..");
const DIST_DIR = join(RESOURCE_DIR, "artifacts", "json-schema");
type AgentName = "opencode" | "claude" | "codex" | "amp" | "pi";
const EXTRACTORS: Record<AgentName, () => Promise<NormalizedSchema>> = {
opencode: extractOpenCodeSchema,
claude: extractClaudeSchema,
codex: extractCodexSchema,
amp: extractAmpSchema,
pi: extractPiSchema,
};
function parseArgs(): { agents: AgentName[] } {
const args = process.argv.slice(2);
const agentArg = args.find((arg) => arg.startsWith("--agent="));
if (agentArg) {
const agent = agentArg.split("=")[1] as AgentName;
if (!EXTRACTORS[agent]) {
console.error(`Unknown agent: ${agent}`);
console.error(`Valid agents: ${Object.keys(EXTRACTORS).join(", ")}`);
process.exit(1);
}
return { agents: [agent] };
}
return { agents: Object.keys(EXTRACTORS) as AgentName[] };
}
function ensureDistDir(): void {
if (!existsSync(DIST_DIR)) {
mkdirSync(DIST_DIR, { recursive: true });
}
}
async function extractAndWrite(agent: AgentName): Promise<boolean> {
try {
const extractor = EXTRACTORS[agent];
const schema = await extractor();
// Validate schema
const validation = validateSchema(schema);
if (!validation.valid) {
console.error(` [error] Schema validation failed for ${agent}:`);
validation.errors.forEach((err) => console.error(` - ${err}`));
return false;
}
// Write to file
const outputPath = join(DIST_DIR, `${agent}.json`);
writeFileSync(outputPath, JSON.stringify(schema, null, 2));
console.log(` [wrote] ${outputPath}`);
return true;
} catch (error) {
console.error(` [error] Failed to extract ${agent}: ${error}`);
return false;
}
}
async function main(): Promise<void> {
console.log("Agent Schema Extractor");
console.log("======================\n");
const { agents } = parseArgs();
ensureDistDir();
console.log(`Extracting schemas for: ${agents.join(", ")}\n`);
const results: Record<string, boolean> = {};
for (const agent of agents) {
results[agent] = await extractAndWrite(agent);
console.log();
}
// Summary
console.log("Summary");
console.log("-------");
const successful = Object.entries(results)
.filter(([, success]) => success)
.map(([name]) => name);
const failed = Object.entries(results)
.filter(([, success]) => !success)
.map(([name]) => name);
if (successful.length > 0) {
console.log(`Successful: ${successful.join(", ")}`);
}
if (failed.length > 0) {
console.log(`Failed: ${failed.join(", ")}`);
process.exit(1);
}
console.log("\nDone!");
}
main().catch((error) => {
console.error("Fatal error:", error);
process.exit(1);
});

View file

@ -1,129 +0,0 @@
import type { JSONSchema7 } from "json-schema";
export interface NormalizedSchema {
$schema: string;
$id: string;
title: string;
definitions: Record<string, JSONSchema7>;
}
/**
* Converts OpenAPI 3.1 schema to JSON Schema draft-07.
* OpenAPI 3.1 is largely compatible with JSON Schema draft 2020-12,
* but we want draft-07 for broader tool compatibility.
*/
export function openApiToJsonSchema(schema: Record<string, unknown>): JSONSchema7 {
const result: Record<string, unknown> = {};
for (const [key, value] of Object.entries(schema)) {
// Skip OpenAPI-specific fields
if (key === "discriminator" || key === "xml" || key === "externalDocs") {
continue;
}
// Handle nullable (OpenAPI 3.0 style)
if (key === "nullable" && value === true) {
continue; // Will be handled by type conversion
}
// Recursively convert nested schemas
if (key === "properties" && typeof value === "object" && value !== null) {
result[key] = {};
for (const [propName, propSchema] of Object.entries(value as Record<string, unknown>)) {
(result[key] as Record<string, unknown>)[propName] = openApiToJsonSchema(
propSchema as Record<string, unknown>
);
}
continue;
}
if (key === "items" && typeof value === "object" && value !== null) {
result[key] = openApiToJsonSchema(value as Record<string, unknown>);
continue;
}
if (key === "additionalProperties" && typeof value === "object" && value !== null) {
result[key] = openApiToJsonSchema(value as Record<string, unknown>);
continue;
}
if ((key === "oneOf" || key === "anyOf" || key === "allOf") && Array.isArray(value)) {
result[key] = value.map((item) =>
typeof item === "object" && item !== null
? openApiToJsonSchema(item as Record<string, unknown>)
: item
);
continue;
}
// Convert $ref paths from OpenAPI to local definitions
if (key === "$ref" && typeof value === "string") {
result[key] = value.replace("#/components/schemas/", "#/definitions/");
continue;
}
result[key] = value;
}
// Handle nullable by adding null to type array
if (schema["nullable"] === true && result["type"]) {
const currentType = result["type"];
if (Array.isArray(currentType)) {
if (!currentType.includes("null")) {
result["type"] = [...currentType, "null"];
}
} else {
result["type"] = [currentType as string, "null"];
}
}
return result as JSONSchema7;
}
/**
* Creates a normalized schema with consistent metadata.
*/
export function createNormalizedSchema(
id: string,
title: string,
definitions: Record<string, JSONSchema7>
): NormalizedSchema {
return {
$schema: "http://json-schema.org/draft-07/schema#",
$id: `https://sandbox-agent/schemas/${id}.json`,
title,
definitions,
};
}
/**
* Validates a schema against JSON Schema draft-07 meta-schema.
* Basic validation - checks required fields and structure.
*/
export function validateSchema(schema: unknown): { valid: boolean; errors: string[] } {
const errors: string[] = [];
if (typeof schema !== "object" || schema === null) {
return { valid: false, errors: ["Schema must be an object"] };
}
const s = schema as Record<string, unknown>;
if (s.$schema && typeof s.$schema !== "string") {
errors.push("$schema must be a string");
}
if (s.definitions && typeof s.definitions !== "object") {
errors.push("definitions must be an object");
}
if (s.definitions && typeof s.definitions === "object") {
for (const [name, def] of Object.entries(s.definitions as Record<string, unknown>)) {
if (typeof def !== "object" || def === null) {
errors.push(`Definition "${name}" must be an object`);
}
}
}
return { valid: errors.length === 0, errors };
}

View file

@ -1,83 +0,0 @@
import { existsSync, mkdirSync, writeFileSync } from "fs";
import { join } from "path";
import { fetchWithCache } from "./cache.js";
import { createNormalizedSchema, openApiToJsonSchema, type NormalizedSchema } from "./normalize.js";
import type { JSONSchema7 } from "json-schema";
const OPENAPI_URLS = [
"https://raw.githubusercontent.com/anomalyco/opencode/dev/packages/sdk/openapi.json",
"https://raw.githubusercontent.com/sst/opencode/dev/packages/sdk/openapi.json",
];
// Key schemas we want to extract
const TARGET_SCHEMAS = [
"Session",
"Message",
"Part",
"Event",
"PermissionRequest",
"QuestionRequest",
"TextPart",
"ToolCallPart",
"ToolResultPart",
"ErrorPart",
];
const OPENAPI_ARTIFACT_DIR = join(import.meta.dirname, "..", "artifacts", "openapi");
const OPENAPI_ARTIFACT_PATH = join(OPENAPI_ARTIFACT_DIR, "opencode.json");
interface OpenAPISpec {
components?: {
schemas?: Record<string, unknown>;
};
}
function writeOpenApiArtifact(specText: string): void {
if (!existsSync(OPENAPI_ARTIFACT_DIR)) {
mkdirSync(OPENAPI_ARTIFACT_DIR, { recursive: true });
}
writeFileSync(OPENAPI_ARTIFACT_PATH, specText);
console.log(` [wrote] ${OPENAPI_ARTIFACT_PATH}`);
}
export async function extractOpenCodeSchema(): Promise<NormalizedSchema> {
console.log("Extracting OpenCode schema from OpenAPI spec...");
let specText: string | null = null;
let lastError: Error | null = null;
for (const url of OPENAPI_URLS) {
try {
specText = await fetchWithCache(url);
break;
} catch (error) {
lastError = error as Error;
}
}
if (!specText) {
throw lastError ?? new Error("Failed to fetch OpenCode OpenAPI spec");
}
writeOpenApiArtifact(specText);
const spec: OpenAPISpec = JSON.parse(specText);
if (!spec.components?.schemas) {
throw new Error("OpenAPI spec missing components.schemas");
}
const definitions: Record<string, JSONSchema7> = {};
// Extract all schemas, not just target ones, to preserve references
for (const [name, schema] of Object.entries(spec.components.schemas)) {
definitions[name] = openApiToJsonSchema(schema as Record<string, unknown>);
}
// Verify target schemas exist
const missing = TARGET_SCHEMAS.filter((name) => !definitions[name]);
if (missing.length > 0) {
console.warn(` [warn] Missing expected schemas: ${missing.join(", ")}`);
}
const found = TARGET_SCHEMAS.filter((name) => definitions[name]);
console.log(` [ok] Extracted ${Object.keys(definitions).length} schemas (${found.length} target schemas)`);
return createNormalizedSchema("opencode", "OpenCode SDK Schema", definitions);
}

View file

@ -1,16 +0,0 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"outDir": "dist",
"rootDir": "src",
"resolveJsonModule": true,
"declaration": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}