poe-code 3.0.178 → 3.0.179
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +6 -2
- package/dist/index.js.map +2 -2
- package/package.json +6 -2
- package/packages/cmdkit/dist/cli.compile-check.d.ts +1 -0
- package/packages/cmdkit/dist/cli.compile-check.js +26 -0
- package/packages/cmdkit/dist/cli.d.ts +12 -0
- package/packages/cmdkit/dist/cli.js +2306 -0
- package/packages/cmdkit/dist/cli.js.map +7 -0
- package/packages/cmdkit/dist/index.compile-check.d.ts +1 -0
- package/packages/cmdkit/dist/index.compile-check.js +50 -0
- package/packages/cmdkit/dist/index.d.ts +164 -0
- package/packages/cmdkit/dist/index.js +518 -0
- package/packages/cmdkit/dist/index.js.map +7 -0
- package/packages/cmdkit/dist/mcp.compile-check.d.ts +1 -0
- package/packages/cmdkit/dist/mcp.compile-check.js +26 -0
- package/packages/cmdkit/dist/mcp.d.ts +16 -0
- package/packages/cmdkit/dist/mcp.js +1153 -0
- package/packages/cmdkit/dist/mcp.js.map +7 -0
- package/packages/cmdkit/dist/renderer.d.ts +5 -0
- package/packages/cmdkit/dist/renderer.js +164 -0
- package/packages/cmdkit/dist/renderer.js.map +7 -0
- package/packages/cmdkit/dist/sdk.compile-check.d.ts +1 -0
- package/packages/cmdkit/dist/sdk.compile-check.js +79 -0
- package/packages/cmdkit/dist/sdk.d.ts +63 -0
- package/packages/cmdkit/dist/sdk.js +314 -0
- package/packages/cmdkit/dist/sdk.js.map +7 -0
- package/packages/cmdkit-schema/dist/index.compile-check.d.ts +1 -0
- package/packages/cmdkit-schema/dist/index.compile-check.js +11 -0
- package/packages/cmdkit-schema/dist/index.d.ts +81 -0
- package/packages/cmdkit-schema/dist/index.js +130 -0
- package/packages/design-system/dist/acp/components.d.ts +11 -0
- package/packages/design-system/dist/acp/components.js +121 -0
- package/packages/design-system/dist/acp/index.d.ts +3 -0
- package/packages/design-system/dist/acp/index.js +2 -0
- package/packages/design-system/dist/acp/writer.d.ts +13 -0
- package/packages/design-system/dist/acp/writer.js +21 -0
- package/packages/design-system/dist/components/command-errors.d.ts +16 -0
- package/packages/design-system/dist/components/command-errors.js +22 -0
- package/packages/design-system/dist/components/help-formatter.d.ts +20 -0
- package/packages/design-system/dist/components/help-formatter.js +27 -0
- package/packages/design-system/dist/components/index.d.ts +10 -0
- package/packages/design-system/dist/components/index.js +7 -0
- package/packages/design-system/dist/components/logger.d.ts +11 -0
- package/packages/design-system/dist/components/logger.js +60 -0
- package/packages/design-system/dist/components/symbols.d.ts +12 -0
- package/packages/design-system/dist/components/symbols.js +71 -0
- package/packages/design-system/dist/components/table.d.ts +13 -0
- package/packages/design-system/dist/components/table.js +74 -0
- package/packages/design-system/dist/components/text.d.ts +14 -0
- package/packages/design-system/dist/components/text.js +104 -0
- package/packages/design-system/dist/dashboard/ansi.d.ts +18 -0
- package/packages/design-system/dist/dashboard/ansi.js +298 -0
- package/packages/design-system/dist/dashboard/buffer.d.ts +25 -0
- package/packages/design-system/dist/dashboard/buffer.js +189 -0
- package/packages/design-system/dist/dashboard/components/border.d.ts +9 -0
- package/packages/design-system/dist/dashboard/components/border.js +123 -0
- package/packages/design-system/dist/dashboard/components/footer.d.ts +8 -0
- package/packages/design-system/dist/dashboard/components/footer.js +58 -0
- package/packages/design-system/dist/dashboard/components/output-pane.d.ts +21 -0
- package/packages/design-system/dist/dashboard/components/output-pane.js +323 -0
- package/packages/design-system/dist/dashboard/components/stats-pane.d.ts +7 -0
- package/packages/design-system/dist/dashboard/components/stats-pane.js +120 -0
- package/packages/design-system/dist/dashboard/dashboard.d.ts +20 -0
- package/packages/design-system/dist/dashboard/dashboard.js +187 -0
- package/packages/design-system/dist/dashboard/demo.d.ts +13 -0
- package/packages/design-system/dist/dashboard/demo.js +145 -0
- package/packages/design-system/dist/dashboard/index.d.ts +7 -0
- package/packages/design-system/dist/dashboard/index.js +3 -0
- package/packages/design-system/dist/dashboard/keymap.d.ts +3 -0
- package/packages/design-system/dist/dashboard/keymap.js +114 -0
- package/packages/design-system/dist/dashboard/layout.d.ts +25 -0
- package/packages/design-system/dist/dashboard/layout.js +79 -0
- package/packages/design-system/dist/dashboard/snapshot.d.ts +10 -0
- package/packages/design-system/dist/dashboard/snapshot.js +72 -0
- package/packages/design-system/dist/dashboard/store.d.ts +9 -0
- package/packages/design-system/dist/dashboard/store.js +107 -0
- package/packages/design-system/dist/dashboard/terminal.d.ts +35 -0
- package/packages/design-system/dist/dashboard/terminal.js +215 -0
- package/packages/design-system/dist/dashboard/types.d.ts +45 -0
- package/packages/design-system/dist/dashboard/types.js +1 -0
- package/packages/design-system/dist/index.d.ts +33 -0
- package/packages/design-system/dist/index.js +31 -0
- package/packages/design-system/dist/internal/output-format.d.ts +6 -0
- package/packages/design-system/dist/internal/output-format.js +22 -0
- package/packages/design-system/dist/internal/strip-ansi.d.ts +1 -0
- package/packages/design-system/dist/internal/strip-ansi.js +3 -0
- package/packages/design-system/dist/internal/theme-detect.d.ts +11 -0
- package/packages/design-system/dist/internal/theme-detect.js +49 -0
- package/packages/design-system/dist/prompts/index.d.ts +66 -0
- package/packages/design-system/dist/prompts/index.js +132 -0
- package/packages/design-system/dist/prompts/primitives/cancel.d.ts +2 -0
- package/packages/design-system/dist/prompts/primitives/cancel.js +9 -0
- package/packages/design-system/dist/prompts/primitives/intro.d.ts +1 -0
- package/packages/design-system/dist/prompts/primitives/intro.js +15 -0
- package/packages/design-system/dist/prompts/primitives/log.d.ts +18 -0
- package/packages/design-system/dist/prompts/primitives/log.js +101 -0
- package/packages/design-system/dist/prompts/primitives/note.d.ts +1 -0
- package/packages/design-system/dist/prompts/primitives/note.js +39 -0
- package/packages/design-system/dist/prompts/primitives/outro.d.ts +1 -0
- package/packages/design-system/dist/prompts/primitives/outro.js +16 -0
- package/packages/design-system/dist/prompts/primitives/spinner.d.ts +6 -0
- package/packages/design-system/dist/prompts/primitives/spinner.js +74 -0
- package/packages/design-system/dist/prompts/theme.d.ts +11 -0
- package/packages/design-system/dist/prompts/theme.js +12 -0
- package/packages/design-system/dist/static/index.d.ts +4 -0
- package/packages/design-system/dist/static/index.js +2 -0
- package/packages/design-system/dist/static/menu.d.ts +11 -0
- package/packages/design-system/dist/static/menu.js +36 -0
- package/packages/design-system/dist/static/spinner.d.ts +14 -0
- package/packages/design-system/dist/static/spinner.js +46 -0
- package/packages/design-system/dist/terminal-markdown/ast.d.ts +84 -0
- package/packages/design-system/dist/terminal-markdown/ast.js +1 -0
- package/packages/design-system/dist/terminal-markdown/demo-content.d.ts +2 -0
- package/packages/design-system/dist/terminal-markdown/demo-content.js +139 -0
- package/packages/design-system/dist/terminal-markdown/index.d.ts +6 -0
- package/packages/design-system/dist/terminal-markdown/index.js +8 -0
- package/packages/design-system/dist/terminal-markdown/parser/block.d.ts +6 -0
- package/packages/design-system/dist/terminal-markdown/parser/block.js +1205 -0
- package/packages/design-system/dist/terminal-markdown/parser/frontmatter.d.ts +6 -0
- package/packages/design-system/dist/terminal-markdown/parser/frontmatter.js +395 -0
- package/packages/design-system/dist/terminal-markdown/parser/inline.d.ts +6 -0
- package/packages/design-system/dist/terminal-markdown/parser/inline.js +1087 -0
- package/packages/design-system/dist/terminal-markdown/parser.d.ts +5 -0
- package/packages/design-system/dist/terminal-markdown/parser.js +13 -0
- package/packages/design-system/dist/terminal-markdown/renderer.d.ts +6 -0
- package/packages/design-system/dist/terminal-markdown/renderer.js +572 -0
- package/packages/design-system/dist/terminal-markdown/testing/theme-render-fixture.d.ts +1 -0
- package/packages/design-system/dist/terminal-markdown/testing/theme-render-fixture.js +27 -0
- package/packages/design-system/dist/tokens/colors.d.ts +35 -0
- package/packages/design-system/dist/tokens/colors.js +34 -0
- package/packages/design-system/dist/tokens/index.d.ts +4 -0
- package/packages/design-system/dist/tokens/index.js +4 -0
- package/packages/design-system/dist/tokens/spacing.d.ts +6 -0
- package/packages/design-system/dist/tokens/spacing.js +6 -0
- package/packages/design-system/dist/tokens/typography.d.ts +7 -0
- package/packages/design-system/dist/tokens/typography.js +8 -0
- package/packages/design-system/dist/tokens/widths.d.ts +5 -0
- package/packages/design-system/dist/tokens/widths.js +5 -0
- package/packages/tiny-stdio-mcp-server/dist/content/audio.d.ts +14 -0
- package/packages/tiny-stdio-mcp-server/dist/content/audio.js +76 -0
- package/packages/tiny-stdio-mcp-server/dist/content/convert.d.ts +16 -0
- package/packages/tiny-stdio-mcp-server/dist/content/convert.js +42 -0
- package/packages/tiny-stdio-mcp-server/dist/content/file-type.d.ts +11 -0
- package/packages/tiny-stdio-mcp-server/dist/content/file-type.js +93 -0
- package/packages/tiny-stdio-mcp-server/dist/content/file.d.ts +26 -0
- package/packages/tiny-stdio-mcp-server/dist/content/file.js +94 -0
- package/packages/tiny-stdio-mcp-server/dist/content/image.d.ts +14 -0
- package/packages/tiny-stdio-mcp-server/dist/content/image.js +64 -0
- package/packages/tiny-stdio-mcp-server/dist/content/index.d.ts +5 -0
- package/packages/tiny-stdio-mcp-server/dist/content/index.js +8 -0
- package/packages/tiny-stdio-mcp-server/dist/content/mime.d.ts +1 -0
- package/packages/tiny-stdio-mcp-server/dist/content/mime.js +1 -0
- package/packages/tiny-stdio-mcp-server/dist/index.d.ts +9 -0
- package/packages/tiny-stdio-mcp-server/dist/index.js +7 -0
- package/packages/tiny-stdio-mcp-server/dist/jsonrpc.d.ts +14 -0
- package/packages/tiny-stdio-mcp-server/dist/jsonrpc.js +99 -0
- package/packages/tiny-stdio-mcp-server/dist/schema.d.ts +19 -0
- package/packages/tiny-stdio-mcp-server/dist/schema.js +18 -0
- package/packages/tiny-stdio-mcp-server/dist/server.d.ts +13 -0
- package/packages/tiny-stdio-mcp-server/dist/server.js +226 -0
- package/packages/tiny-stdio-mcp-server/dist/testing.d.ts +7 -0
- package/packages/tiny-stdio-mcp-server/dist/testing.js +20 -0
- package/packages/tiny-stdio-mcp-server/dist/types.d.ts +119 -0
- package/packages/tiny-stdio-mcp-server/dist/types.js +16 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
// packages/cmdkit/src/sdk.ts
|
|
2
|
+
import { access, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
|
|
4
|
+
// packages/cmdkit/src/index.ts
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
var UserError = class extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "UserError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
function parseSimpleSemver(value) {
|
|
13
|
+
const parts = value.split(".");
|
|
14
|
+
if (parts.length !== 3) {
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
const parsed = parts.map((part) => {
|
|
18
|
+
if (part.length === 0) {
|
|
19
|
+
return Number.NaN;
|
|
20
|
+
}
|
|
21
|
+
for (const char of part) {
|
|
22
|
+
if (char < "0" || char > "9") {
|
|
23
|
+
return Number.NaN;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return Number(part);
|
|
27
|
+
});
|
|
28
|
+
if (parsed.some((part) => !Number.isInteger(part) || part < 0)) {
|
|
29
|
+
return void 0;
|
|
30
|
+
}
|
|
31
|
+
return parsed;
|
|
32
|
+
}
|
|
33
|
+
function parseMinimumApiVersion(requirement) {
|
|
34
|
+
if (!requirement.startsWith(">=")) {
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
return parseSimpleSemver(requirement.slice(2).trim());
|
|
38
|
+
}
|
|
39
|
+
function compareSemver(left, right) {
|
|
40
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
41
|
+
if (left[index] === right[index]) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
return left[index] > right[index] ? 1 : -1;
|
|
45
|
+
}
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
function resolveCommandSecrets(command, env = process.env) {
|
|
49
|
+
const secrets = {};
|
|
50
|
+
for (const [name, secret] of Object.entries(command.secrets)) {
|
|
51
|
+
const value = env[secret.env];
|
|
52
|
+
if (value === void 0 && secret.optional !== true) {
|
|
53
|
+
const details = secret.description ? `
|
|
54
|
+
${secret.description}` : "";
|
|
55
|
+
throw new UserError(`Error: Missing required secret ${secret.env}${details}`);
|
|
56
|
+
}
|
|
57
|
+
secrets[name] = value;
|
|
58
|
+
}
|
|
59
|
+
return secrets;
|
|
60
|
+
}
|
|
61
|
+
async function assertCommandRequirements(command, context, options = {}) {
|
|
62
|
+
const requires = command.requires;
|
|
63
|
+
if (requires === void 0) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const env = options.env ?? process.env;
|
|
67
|
+
const authEnvVar = options.authEnvVar ?? "POE_API_KEY";
|
|
68
|
+
if (requires.auth === true && env[authEnvVar] === void 0) {
|
|
69
|
+
throw new UserError(
|
|
70
|
+
`Error: Command "${command.name}" requires authentication.
|
|
71
|
+
Run 'poe-code login' first.`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (requires.apiVersion !== void 0) {
|
|
75
|
+
const minimumVersion = parseMinimumApiVersion(requires.apiVersion);
|
|
76
|
+
if (minimumVersion === void 0) {
|
|
77
|
+
throw new UserError(
|
|
78
|
+
`Error: Command "${command.name}" has invalid apiVersion requirement "${requires.apiVersion}". Expected format ">=X.Y.Z".`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
if (options.apiVersion === void 0) {
|
|
82
|
+
throw new UserError(
|
|
83
|
+
`Error: Command "${command.name}" requires API version ${requires.apiVersion}, but no runner API version was provided.`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
const runnerVersion = parseSimpleSemver(options.apiVersion);
|
|
87
|
+
if (runnerVersion === void 0) {
|
|
88
|
+
throw new UserError(
|
|
89
|
+
`Error: Command "${command.name}" requires API version ${requires.apiVersion}, but runner API version "${options.apiVersion}" is not valid semver.`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
if (compareSemver(runnerVersion, minimumVersion) < 0) {
|
|
93
|
+
throw new UserError(
|
|
94
|
+
`Error: Command "${command.name}" requires API version ${requires.apiVersion}, but runner API version is ${options.apiVersion}.`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const checkResult = await requires.check?.(context);
|
|
99
|
+
if (checkResult && !checkResult.ok) {
|
|
100
|
+
throw new UserError(checkResult.message ?? "Command precondition failed.");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// packages/cmdkit/src/sdk.ts
|
|
105
|
+
var RESERVED_SERVICE_NAMES = /* @__PURE__ */ new Set(["params", "secrets", "fetch", "fs", "env", "progress"]);
|
|
106
|
+
function splitWords(value) {
|
|
107
|
+
const words = [];
|
|
108
|
+
let current = "";
|
|
109
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
110
|
+
const char = value[index] ?? "";
|
|
111
|
+
const lower = char.toLowerCase();
|
|
112
|
+
const upper = char.toUpperCase();
|
|
113
|
+
const isSeparator = char === "-" || char === "_" || char === " " || char === ".";
|
|
114
|
+
if (isSeparator) {
|
|
115
|
+
if (current.length > 0) {
|
|
116
|
+
words.push(current.toLowerCase());
|
|
117
|
+
current = "";
|
|
118
|
+
}
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const isUppercase = char !== lower && char === upper;
|
|
122
|
+
const previous = value[index - 1];
|
|
123
|
+
const next = value[index + 1];
|
|
124
|
+
const previousIsLowercase = previous !== void 0 && previous === previous.toLowerCase() && previous !== previous.toUpperCase();
|
|
125
|
+
const nextIsLowercase = next !== void 0 && next === next.toLowerCase() && next !== next.toUpperCase();
|
|
126
|
+
if (isUppercase && current.length > 0 && (previousIsLowercase || nextIsLowercase)) {
|
|
127
|
+
words.push(current.toLowerCase());
|
|
128
|
+
current = char;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
current += char;
|
|
132
|
+
}
|
|
133
|
+
if (current.length > 0) {
|
|
134
|
+
words.push(current.toLowerCase());
|
|
135
|
+
}
|
|
136
|
+
return words;
|
|
137
|
+
}
|
|
138
|
+
function formatSegment(segment) {
|
|
139
|
+
return splitWords(segment).map((word, index) => index === 0 ? word : `${word[0]?.toUpperCase() ?? ""}${word.slice(1)}`).join("");
|
|
140
|
+
}
|
|
141
|
+
function unwrapOptional(schema) {
|
|
142
|
+
if (schema.kind === "optional") {
|
|
143
|
+
return unwrapOptional(schema.inner);
|
|
144
|
+
}
|
|
145
|
+
return schema;
|
|
146
|
+
}
|
|
147
|
+
function isOptional(schema) {
|
|
148
|
+
return schema.kind === "optional";
|
|
149
|
+
}
|
|
150
|
+
function isPlainObject(value) {
|
|
151
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
152
|
+
}
|
|
153
|
+
function createFs() {
|
|
154
|
+
return {
|
|
155
|
+
readFile: async (path, encoding = "utf8") => readFile(path, { encoding }),
|
|
156
|
+
writeFile: async (path, contents) => {
|
|
157
|
+
await writeFile(path, contents);
|
|
158
|
+
},
|
|
159
|
+
exists: async (path) => {
|
|
160
|
+
try {
|
|
161
|
+
await access(path);
|
|
162
|
+
return true;
|
|
163
|
+
} catch {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function createEnv(values = process.env) {
|
|
170
|
+
return {
|
|
171
|
+
get(key) {
|
|
172
|
+
return values[key];
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function validateServices(services) {
|
|
177
|
+
for (const name of Object.keys(services)) {
|
|
178
|
+
if (RESERVED_SERVICE_NAMES.has(name)) {
|
|
179
|
+
throw new Error(`Service name "${name}" is reserved. Choose a different name.`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function validateEnum(value, schema, label) {
|
|
184
|
+
if (!schema.values.includes(value)) {
|
|
185
|
+
throw new UserError(
|
|
186
|
+
`Invalid value for "${label}". Expected one of: ${schema.values.map((candidate) => String(candidate)).join(", ")}.`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
return value;
|
|
190
|
+
}
|
|
191
|
+
function validateSchemaValue(schema, value, label) {
|
|
192
|
+
const unwrappedSchema = unwrapOptional(schema);
|
|
193
|
+
switch (unwrappedSchema.kind) {
|
|
194
|
+
case "string":
|
|
195
|
+
if (typeof value !== "string") {
|
|
196
|
+
throw new UserError(`Invalid value for "${label}". Expected a string.`);
|
|
197
|
+
}
|
|
198
|
+
return value;
|
|
199
|
+
case "number":
|
|
200
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
201
|
+
throw new UserError(`Invalid value for "${label}". Expected a number.`);
|
|
202
|
+
}
|
|
203
|
+
return value;
|
|
204
|
+
case "boolean":
|
|
205
|
+
if (typeof value !== "boolean") {
|
|
206
|
+
throw new UserError(`Invalid value for "${label}". Expected a boolean.`);
|
|
207
|
+
}
|
|
208
|
+
return value;
|
|
209
|
+
case "enum":
|
|
210
|
+
return validateEnum(value, unwrappedSchema, label);
|
|
211
|
+
case "array":
|
|
212
|
+
if (!Array.isArray(value)) {
|
|
213
|
+
throw new UserError(`Invalid value for "${label}". Expected an array.`);
|
|
214
|
+
}
|
|
215
|
+
return value.map((item, index) => validateSchemaValue(unwrappedSchema.item, item, `${label}[${index}]`));
|
|
216
|
+
case "object":
|
|
217
|
+
return validateObjectSchema(unwrappedSchema, value, label);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function validateObjectSchema(schema, value, label) {
|
|
221
|
+
if (!isPlainObject(value)) {
|
|
222
|
+
throw new UserError(`Invalid value for "${label}". Expected an object.`);
|
|
223
|
+
}
|
|
224
|
+
const result = {};
|
|
225
|
+
const expectedKeys = /* @__PURE__ */ new Map();
|
|
226
|
+
for (const [key, childSchema] of Object.entries(schema.shape)) {
|
|
227
|
+
expectedKeys.set(formatSegment(key), [key, childSchema]);
|
|
228
|
+
}
|
|
229
|
+
for (const key of Object.keys(value)) {
|
|
230
|
+
if (!expectedKeys.has(key)) {
|
|
231
|
+
const fieldLabel = label.length === 0 ? key : `${label}.${key}`;
|
|
232
|
+
throw new UserError(`Unexpected parameter "${fieldLabel}".`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
for (const [inputKey, [outputKey, rawChildSchema]] of expectedKeys.entries()) {
|
|
236
|
+
const childSchema = unwrapOptional(rawChildSchema);
|
|
237
|
+
const hasValue = Object.prototype.hasOwnProperty.call(value, inputKey);
|
|
238
|
+
const fieldLabel = label.length === 0 ? inputKey : `${label}.${inputKey}`;
|
|
239
|
+
if (!hasValue) {
|
|
240
|
+
if (childSchema.default !== void 0) {
|
|
241
|
+
result[outputKey] = childSchema.default;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (isOptional(rawChildSchema)) {
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
throw new UserError(`Missing required parameter "${fieldLabel}".`);
|
|
248
|
+
}
|
|
249
|
+
result[outputKey] = validateSchemaValue(rawChildSchema, value[inputKey], fieldLabel);
|
|
250
|
+
}
|
|
251
|
+
return result;
|
|
252
|
+
}
|
|
253
|
+
function validateSDKArguments(schema, argumentsValue) {
|
|
254
|
+
return validateObjectSchema(schema, argumentsValue ?? {}, "");
|
|
255
|
+
}
|
|
256
|
+
function defineMember(target, key, value) {
|
|
257
|
+
if (Object.prototype.hasOwnProperty.call(target, key)) {
|
|
258
|
+
throw new Error(`Duplicate SDK member "${key}".`);
|
|
259
|
+
}
|
|
260
|
+
Object.defineProperty(target, key, {
|
|
261
|
+
value,
|
|
262
|
+
enumerable: true,
|
|
263
|
+
configurable: false,
|
|
264
|
+
writable: false
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
function createSDK(root, options = {}) {
|
|
268
|
+
const services = options.services ?? {};
|
|
269
|
+
void options.casing;
|
|
270
|
+
validateServices(services);
|
|
271
|
+
function build(node) {
|
|
272
|
+
if (node.kind === "command") {
|
|
273
|
+
return async (params) => {
|
|
274
|
+
const secrets = resolveCommandSecrets(node);
|
|
275
|
+
const baseContext = {
|
|
276
|
+
...services,
|
|
277
|
+
secrets,
|
|
278
|
+
fetch: globalThis.fetch,
|
|
279
|
+
fs: createFs(),
|
|
280
|
+
env: createEnv(),
|
|
281
|
+
progress() {
|
|
282
|
+
return void 0;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
await assertCommandRequirements(node, { ...baseContext, params: void 0 });
|
|
286
|
+
const validatedParams = validateSDKArguments(node.params, params);
|
|
287
|
+
return node.handler({
|
|
288
|
+
...baseContext,
|
|
289
|
+
params: validatedParams
|
|
290
|
+
});
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
const output = {};
|
|
294
|
+
for (const child of node.children) {
|
|
295
|
+
if (child.kind === "command") {
|
|
296
|
+
if (!child.scope.includes("sdk")) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
defineMember(output, formatSegment(child.name), build(child));
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
const childValue = build(child);
|
|
303
|
+
if (isPlainObject(childValue) && Object.keys(childValue).length > 0) {
|
|
304
|
+
defineMember(output, formatSegment(child.name), childValue);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return output;
|
|
308
|
+
}
|
|
309
|
+
return build(root);
|
|
310
|
+
}
|
|
311
|
+
export {
|
|
312
|
+
createSDK
|
|
313
|
+
};
|
|
314
|
+
//# sourceMappingURL=sdk.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/sdk.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["import { access, readFile, writeFile } from \"node:fs/promises\";\nimport type { AnySchema, ObjectSchema, Static } from \"@poe-code/cmdkit-schema\";\nimport type { Command, Group, HandlerEnv, HandlerFs, Scope } from \"./index.js\";\nimport { UserError, assertCommandRequirements, resolveCommandSecrets } from \"./index.js\";\n\nconst RESERVED_SERVICE_NAMES = new Set([\"params\", \"secrets\", \"fetch\", \"fs\", \"env\", \"progress\"]);\n\ntype ScopeInput = readonly Scope[] | undefined;\ntype Primitive = string | number | boolean | bigint | symbol | null | undefined;\ntype EmptyRecord = Record<never, never>;\n\ntype EffectiveCommandScope<\n TOwnScope extends ScopeInput,\n TInheritedScope extends ScopeInput,\n> = TOwnScope extends readonly Scope[]\n ? TOwnScope\n : TInheritedScope extends readonly Scope[]\n ? TInheritedScope\n : readonly [\"cli\", \"sdk\"];\n\ntype EffectiveGroupScope<\n TOwnScope extends ScopeInput,\n TInheritedScope extends ScopeInput,\n> = TOwnScope extends readonly Scope[]\n ? TOwnScope\n : TInheritedScope extends readonly Scope[]\n ? TInheritedScope\n : undefined;\n\ntype IncludesSDK<TScope> = TScope extends readonly Scope[]\n ? \"sdk\" extends TScope[number]\n ? true\n : false\n : false;\n\ntype Separator = \"-\" | \"_\" | \" \" | \".\";\n\ntype IsUppercase<TValue extends string> = TValue extends Uppercase<TValue>\n ? TValue extends Lowercase<TValue>\n ? false\n : true\n : false;\n\ntype IsLowercase<TValue extends string> = TValue extends Lowercase<TValue>\n ? TValue extends Uppercase<TValue>\n ? false\n : true\n : false;\n\ntype LastCharacter<TValue extends string> = TValue extends `${infer THead}${infer TTail}`\n ? TTail extends \"\"\n ? THead\n : LastCharacter<TTail>\n : never;\n\ntype PushCurrentWord<\n TCurrent extends string,\n TWords extends readonly string[],\n> = TCurrent extends \"\" ? TWords : [...TWords, Lowercase<TCurrent>];\n\ntype SplitCamelWords<\n TValue extends string,\n TCurrent extends string = \"\",\n TWords extends readonly string[] = [],\n> = TValue extends `${infer TChar}${infer TRest}`\n ? TChar extends Separator\n ? SplitCamelWords<TRest, \"\", PushCurrentWord<TCurrent, TWords>>\n : IsUppercase<TChar> extends true\n ? TCurrent extends \"\"\n ? SplitCamelWords<TRest, TChar, TWords>\n : TRest extends `${infer TNext}${string}`\n ? IsLowercase<LastCharacter<TCurrent>> extends true\n ? SplitCamelWords<TRest, TChar, PushCurrentWord<TCurrent, TWords>>\n : IsLowercase<TNext> extends true\n ? SplitCamelWords<TRest, TChar, PushCurrentWord<TCurrent, TWords>>\n : SplitCamelWords<TRest, `${TCurrent}${TChar}`, TWords>\n : SplitCamelWords<TRest, `${TCurrent}${TChar}`, TWords>\n : SplitCamelWords<TRest, `${TCurrent}${TChar}`, TWords>\n : PushCurrentWord<TCurrent, TWords>;\n\ntype JoinCamelWords<TWords extends readonly string[]> = TWords extends readonly [\n infer THead extends string,\n ...infer TTail extends readonly string[],\n]\n ? `${THead}${CapitalizeJoinCamelWords<TTail>}`\n : \"\";\n\ntype CapitalizeJoinCamelWords<TWords extends readonly string[]> = TWords extends readonly [\n infer THead extends string,\n ...infer TTail extends readonly string[],\n]\n ? `${Capitalize<THead>}${CapitalizeJoinCamelWords<TTail>}`\n : \"\";\n\ntype CamelCase<TValue extends string> = JoinCamelWords<SplitCamelWords<TValue>>;\n\ntype Camelize<TValue> = TValue extends Primitive\n ? TValue\n : TValue extends readonly (infer TItem)[]\n ? Array<Camelize<TItem>>\n : TValue extends object\n ? {\n [TKey in keyof TValue as TKey extends string ? CamelCase<TKey> : TKey]: Camelize<TValue[TKey]>;\n }\n : TValue;\n\ntype SDKMethod<TParamsSchema extends ObjectSchema<any>, TResult> = (\n params: Camelize<Static<TParamsSchema>>\n) => Promise<TResult>;\n\ntype UnionToIntersection<TValue> = (\n TValue extends unknown ? (value: TValue) => void : never\n) extends (value: infer TResult) => void\n ? TResult\n : never;\n\ntype Simplify<TValue> = { [TKey in keyof TValue]: TValue[TKey] };\n\ntype RawChildrenValue<TChildren> = TChildren extends readonly unknown[] ? TChildren[number] : never;\n\ntype SDKNodeShape<TNode, TInheritedScope extends ScopeInput> =\n TNode extends {\n kind: \"command\";\n readonly __cmdkitCommandTypeInfo: {\n name: infer TName extends string;\n params: infer TParamsSchema extends ObjectSchema<any>;\n result: infer TResult;\n ownScope: infer TOwnScope extends ScopeInput;\n };\n }\n ? IncludesSDK<EffectiveCommandScope<TOwnScope, TInheritedScope>> extends true\n ? { [TKey in CamelCase<TName>]: SDKMethod<TParamsSchema, TResult> }\n : EmptyRecord\n : TNode extends {\n kind: \"group\";\n readonly __cmdkitGroupTypeInfo: {\n name: infer TName extends string;\n children: infer TChildren extends readonly unknown[];\n ownScope: infer TOwnScope extends ScopeInput;\n };\n }\n ? SDKChildrenShape<TChildren, EffectiveGroupScope<TOwnScope, TInheritedScope>> extends infer TChildShape extends object\n ? keyof TChildShape extends never\n ? EmptyRecord\n : { [TKey in CamelCase<TName>]: TChildShape }\n : never\n : EmptyRecord;\n\ntype SDKChildrenShape<TChildren, TInheritedScope extends ScopeInput> = Simplify<\n UnionToIntersection<SDKNodeShape<RawChildrenValue<TChildren>, TInheritedScope>>\n>;\n\nexport interface CreateSDKOptions<TServices extends object = Record<string, unknown>> {\n services?: TServices;\n casing?: \"camel\";\n}\n\nfunction splitWords(value: string): string[] {\n const words: string[] = [];\n let current = \"\";\n\n for (let index = 0; index < value.length; index += 1) {\n const char = value[index] ?? \"\";\n const lower = char.toLowerCase();\n const upper = char.toUpperCase();\n const isSeparator = char === \"-\" || char === \"_\" || char === \" \" || char === \".\";\n\n if (isSeparator) {\n if (current.length > 0) {\n words.push(current.toLowerCase());\n current = \"\";\n }\n continue;\n }\n\n const isUppercase = char !== lower && char === upper;\n const previous = value[index - 1];\n const next = value[index + 1];\n const previousIsLowercase =\n previous !== undefined && previous === previous.toLowerCase() && previous !== previous.toUpperCase();\n const nextIsLowercase =\n next !== undefined && next === next.toLowerCase() && next !== next.toUpperCase();\n\n if (isUppercase && current.length > 0 && (previousIsLowercase || nextIsLowercase)) {\n words.push(current.toLowerCase());\n current = char;\n continue;\n }\n\n current += char;\n }\n\n if (current.length > 0) {\n words.push(current.toLowerCase());\n }\n\n return words;\n}\n\nfunction formatSegment(segment: string): string {\n return splitWords(segment)\n .map((word, index) => (index === 0 ? word : `${word[0]?.toUpperCase() ?? \"\"}${word.slice(1)}`))\n .join(\"\");\n}\n\nfunction unwrapOptional(schema: AnySchema): AnySchema {\n if (schema.kind === \"optional\") {\n return unwrapOptional(schema.inner);\n }\n\n return schema;\n}\n\nfunction isOptional(schema: AnySchema): boolean {\n return schema.kind === \"optional\";\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction createFs(): HandlerFs {\n return {\n readFile: async (path: string, encoding = \"utf8\") => readFile(path, { encoding }),\n writeFile: async (path: string, contents: string) => {\n await writeFile(path, contents);\n },\n exists: async (path: string) => {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n },\n };\n}\n\nfunction createEnv(values: Record<string, string | undefined> = process.env): HandlerEnv {\n return {\n get(key: string): string | undefined {\n return values[key];\n },\n };\n}\n\nfunction validateServices(services: Record<string, unknown>): void {\n for (const name of Object.keys(services)) {\n if (RESERVED_SERVICE_NAMES.has(name)) {\n throw new Error(`Service name \"${name}\" is reserved. Choose a different name.`);\n }\n }\n}\n\nfunction validateEnum(value: unknown, schema: Extract<AnySchema, { kind: \"enum\" }>, label: string): string | number | boolean {\n if (!schema.values.includes(value as never)) {\n throw new UserError(\n `Invalid value for \"${label}\". Expected one of: ${schema.values.map((candidate) => String(candidate)).join(\", \")}.`\n );\n }\n\n return value as string | number | boolean;\n}\n\nfunction validateSchemaValue(schema: AnySchema, value: unknown, label: string): unknown {\n const unwrappedSchema = unwrapOptional(schema);\n\n switch (unwrappedSchema.kind) {\n case \"string\":\n if (typeof value !== \"string\") {\n throw new UserError(`Invalid value for \"${label}\". Expected a string.`);\n }\n return value;\n\n case \"number\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new UserError(`Invalid value for \"${label}\". Expected a number.`);\n }\n return value;\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n throw new UserError(`Invalid value for \"${label}\". Expected a boolean.`);\n }\n return value;\n\n case \"enum\":\n return validateEnum(value, unwrappedSchema, label);\n\n case \"array\":\n if (!Array.isArray(value)) {\n throw new UserError(`Invalid value for \"${label}\". Expected an array.`);\n }\n return value.map((item, index) => validateSchemaValue(unwrappedSchema.item, item, `${label}[${index}]`));\n\n case \"object\":\n return validateObjectSchema(unwrappedSchema, value, label);\n }\n}\n\nfunction validateObjectSchema(\n schema: ObjectSchema<any>,\n value: unknown,\n label: string\n): Record<string, unknown> {\n if (!isPlainObject(value)) {\n throw new UserError(`Invalid value for \"${label}\". Expected an object.`);\n }\n\n const result: Record<string, unknown> = {};\n const expectedKeys = new Map<string, [string, AnySchema]>();\n\n for (const [key, childSchema] of Object.entries(schema.shape) as Array<[string, AnySchema]>) {\n expectedKeys.set(formatSegment(key), [key, childSchema]);\n }\n\n for (const key of Object.keys(value)) {\n if (!expectedKeys.has(key)) {\n const fieldLabel = label.length === 0 ? key : `${label}.${key}`;\n throw new UserError(`Unexpected parameter \"${fieldLabel}\".`);\n }\n }\n\n for (const [inputKey, [outputKey, rawChildSchema]] of expectedKeys.entries()) {\n const childSchema = unwrapOptional(rawChildSchema);\n const hasValue = Object.prototype.hasOwnProperty.call(value, inputKey);\n const fieldLabel = label.length === 0 ? inputKey : `${label}.${inputKey}`;\n\n if (!hasValue) {\n if (childSchema.default !== undefined) {\n result[outputKey] = childSchema.default;\n continue;\n }\n\n if (isOptional(rawChildSchema)) {\n continue;\n }\n\n throw new UserError(`Missing required parameter \"${fieldLabel}\".`);\n }\n\n result[outputKey] = validateSchemaValue(rawChildSchema, value[inputKey], fieldLabel);\n }\n\n return result;\n}\n\nfunction validateSDKArguments(\n schema: ObjectSchema<any>,\n argumentsValue: Record<string, unknown> | undefined\n): Record<string, unknown> {\n return validateObjectSchema(schema, argumentsValue ?? {}, \"\");\n}\n\nfunction defineMember(target: Record<string, unknown>, key: string, value: unknown): void {\n if (Object.prototype.hasOwnProperty.call(target, key)) {\n throw new Error(`Duplicate SDK member \"${key}\".`);\n }\n\n Object.defineProperty(target, key, {\n value,\n enumerable: true,\n configurable: false,\n writable: false,\n });\n}\n\nexport function createSDK<\n TRootInfo,\n TServices extends object = Record<string, unknown>,\n>(\n root: Group<any> & {\n readonly __cmdkitGroupTypeInfo: TRootInfo;\n },\n options?: CreateSDKOptions<TServices>\n): TRootInfo extends { children: infer TChildren extends readonly unknown[] }\n ? SDKChildrenShape<TChildren, undefined>\n : EmptyRecord;\nexport function createSDK(\n root: Group<any>,\n options: CreateSDKOptions<any> = {}\n): Record<string, unknown> {\n const services = options.services ?? {};\n void options.casing;\n validateServices(services as Record<string, unknown>);\n\n function build(node: Group<any> | Command<any, any, any, any>): unknown {\n if (node.kind === \"command\") {\n return async (params: Record<string, unknown> | undefined) => {\n const secrets = resolveCommandSecrets(node);\n const baseContext = {\n ...services,\n secrets,\n fetch: globalThis.fetch,\n fs: createFs(),\n env: createEnv(),\n progress(): void {\n return undefined;\n },\n };\n\n await assertCommandRequirements(node, { ...baseContext, params: undefined });\n\n const validatedParams = validateSDKArguments(node.params, params);\n return node.handler({\n ...baseContext,\n params: validatedParams,\n } as Parameters<typeof node.handler>[0]);\n };\n }\n\n const output: Record<string, unknown> = {};\n\n for (const child of node.children) {\n if (child.kind === \"command\") {\n if (!child.scope.includes(\"sdk\")) {\n continue;\n }\n\n defineMember(output, formatSegment(child.name), build(child));\n continue;\n }\n\n const childValue = build(child);\n if (isPlainObject(childValue) && Object.keys(childValue).length > 0) {\n defineMember(output, formatSegment(child.name), childValue);\n }\n }\n\n return output;\n }\n\n return build(root) as Record<string, unknown>;\n}\n", "import { fileURLToPath } from \"node:url\";\nimport type { ObjectSchema, Static } from \"@poe-code/cmdkit-schema\";\nimport type { LoggerOutput, RenderTableOptions, ThemePalette } from \"@poe-code/design-system\";\n\nconst commandConfigSymbol = Symbol(\"cmdkit.command.config\");\nconst groupConfigSymbol = Symbol(\"cmdkit.group.config\");\nconst commandSourcePathSymbol = Symbol(\"cmdkit.command.sourcePath\");\n\ntype ScopeValue = \"cli\" | \"mcp\" | \"sdk\";\ntype AnyObjectSchema = ObjectSchema<Record<string, never>>;\ntype EmptyServices = Record<string, never>;\ntype ScopeInput = readonly Scope[] | undefined;\n\nexport type Scope = ScopeValue;\n\nexport interface SecretDefinition {\n env: string;\n description?: string;\n optional?: boolean;\n}\n\nexport type SecretDeclarations = Record<string, SecretDefinition>;\n\ntype OptionalSecretKeys<TSecrets extends SecretDeclarations> = {\n [TKey in keyof TSecrets]: TSecrets[TKey] extends { optional: true } ? TKey : never;\n}[keyof TSecrets];\n\ntype RequiredSecretKeys<TSecrets extends SecretDeclarations> = Exclude<\n keyof TSecrets,\n OptionalSecretKeys<TSecrets>\n>;\n\nexport type InferSecrets<TSecrets extends SecretDeclarations | undefined> =\n TSecrets extends SecretDeclarations\n ? { [TKey in RequiredSecretKeys<TSecrets>]: string } & {\n [TKey in OptionalSecretKeys<TSecrets>]?: string;\n }\n : Record<string, never>;\n\nexport interface HandlerFs {\n readFile(path: string, encoding?: BufferEncoding): Promise<string>;\n writeFile(path: string, contents: string): Promise<void>;\n exists(path: string): Promise<boolean>;\n}\n\nexport interface HandlerEnv {\n get(key: string): string | undefined;\n}\n\nexport interface RenderPrimitives {\n logger: LoggerOutput;\n renderTable(options: RenderTableOptions): string;\n getTheme(): ThemePalette;\n note(message: string, title?: string): void;\n}\n\nexport interface CheckResult {\n ok: boolean;\n message?: string;\n}\n\nexport type GroupCheckContext<TServices extends object = EmptyServices> = TServices & {\n params?: unknown;\n secrets?: Record<string, string | undefined>;\n fetch: typeof globalThis.fetch;\n fs: HandlerFs;\n env: HandlerEnv;\n progress(message: string): void;\n};\n\nexport type CommandCheckContext<\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TServices extends object = EmptyServices,\n> = TServices & {\n params?: Static<TParamsSchema>;\n secrets?: InferSecrets<TSecrets>;\n fetch: typeof globalThis.fetch;\n fs: HandlerFs;\n env: HandlerEnv;\n progress(message: string): void;\n};\n\nexport interface Requires<TContext = unknown> {\n auth?: boolean;\n apiVersion?: string;\n check?: (ctx: TContext) => Promise<CheckResult>;\n}\n\nexport interface Renderers<TResult> {\n rich?: (result: TResult, primitives: RenderPrimitives) => void;\n markdown?: (result: TResult, primitives: RenderPrimitives) => string;\n json?: (result: TResult, primitives: RenderPrimitives) => unknown;\n}\n\nexport type HandlerContext<\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TServices extends object = EmptyServices,\n> = TServices & {\n params: Static<TParamsSchema>;\n secrets: InferSecrets<TSecrets>;\n fetch: typeof globalThis.fetch;\n fs: HandlerFs;\n env: HandlerEnv;\n progress(message: string): void;\n};\n\nexport interface CommandConfig<\n TServices extends object,\n TParamsSchema extends ObjectSchema<any>,\n TSecrets extends SecretDeclarations | undefined,\n TResult,\n> {\n name: string;\n description?: string;\n aliases?: string[];\n positional?: string[];\n params: TParamsSchema;\n secrets?: TSecrets;\n scope?: Scope[];\n confirm?: boolean;\n requires?: Requires<CommandCheckContext<TParamsSchema, TSecrets, TServices>>;\n handler: (ctx: HandlerContext<TParamsSchema, TSecrets, TServices>) => Promise<TResult>;\n render?: Renderers<TResult>;\n}\n\nexport interface Command<\n TServices extends object = EmptyServices,\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TResult = unknown,\n> {\n kind: \"command\";\n name: string;\n description?: string;\n aliases: string[];\n positional: string[];\n params: TParamsSchema;\n secrets: SecretDeclarations;\n scope: Scope[];\n confirm: boolean;\n requires?: Requires<any>;\n handler: (ctx: HandlerContext<TParamsSchema, TSecrets, TServices>) => Promise<TResult>;\n render?: Renderers<TResult>;\n}\n\nexport interface GroupConfig<TServices extends object> {\n name: string;\n description?: string;\n aliases?: string[];\n scope?: Scope[];\n secrets?: SecretDeclarations;\n requires?: Requires<GroupCheckContext<TServices>>;\n children: Array<CommandNode<TServices>>;\n default?: Command<TServices, any, any, any>;\n}\n\nexport interface Group<TServices extends object = EmptyServices> {\n kind: \"group\";\n name: string;\n description?: string;\n aliases: string[];\n scope?: Scope[];\n secrets: SecretDeclarations;\n requires?: Requires<any>;\n children: Array<CommandNode<TServices>>;\n default?: Command<TServices, any, any, any>;\n}\n\nexport type CommandNode<TServices extends object = EmptyServices> =\n | Command<TServices, any, any, any>\n | Group<TServices>;\n\nexport interface CommandTypeInfo<\n TName extends string = string,\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TResult = unknown,\n TOwnScope extends ScopeInput = ScopeInput,\n> {\n name: TName;\n params: TParamsSchema;\n result: TResult;\n ownScope: TOwnScope;\n}\n\nexport interface GroupTypeInfo<\n TServices extends object = EmptyServices,\n TName extends string = string,\n TChildren extends readonly unknown[] = readonly CommandNode<TServices>[],\n TOwnScope extends ScopeInput = ScopeInput,\n> {\n name: TName;\n children: TChildren;\n ownScope: TOwnScope;\n}\n\ntype TypedCommandMetadata<\n TName extends string,\n TParamsSchema extends ObjectSchema<any>,\n TResult,\n TOwnScope extends ScopeInput,\n> = {\n readonly __cmdkitCommandTypeInfo: CommandTypeInfo<TName, TParamsSchema, TResult, TOwnScope>;\n};\n\ntype TypedGroupMetadata<\n TServices extends object,\n TName extends string,\n TChildren extends readonly unknown[],\n TOwnScope extends ScopeInput,\n> = {\n readonly __cmdkitGroupTypeInfo: GroupTypeInfo<TServices, TName, TChildren, TOwnScope>;\n};\n\ninterface InternalCommandConfig {\n scope?: Scope[];\n secrets: SecretDeclarations;\n requires?: Requires<any>;\n sourcePath?: string;\n}\n\ninterface InternalGroupConfig<TServices extends object> {\n scope?: Scope[];\n secrets: SecretDeclarations;\n requires?: Requires<any>;\n children: Array<CommandNode<TServices>>;\n default?: Command<TServices, any, any, any>;\n}\n\ninterface InheritedMetadata {\n scope?: Scope[];\n secrets: SecretDeclarations;\n requires?: Requires<any>;\n}\n\nexport class UserError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UserError\";\n }\n}\n\nexport interface CommandRequirementOptions {\n apiVersion?: string;\n authEnvVar?: string;\n env?: Record<string, string | undefined>;\n}\n\nfunction cloneScope(scope: Scope[] | undefined): Scope[] | undefined {\n return scope === undefined ? undefined : [...scope];\n}\n\nfunction cloneSecretDefinition(secret: SecretDefinition): SecretDefinition {\n return {\n env: secret.env,\n description: secret.description,\n optional: secret.optional,\n };\n}\n\nfunction cloneSecrets(secrets: SecretDeclarations | undefined): SecretDeclarations {\n if (secrets === undefined) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(secrets).map(([key, secret]) => [key, cloneSecretDefinition(secret)])\n );\n}\n\nfunction cloneRequires<TContext>(requires: Requires<TContext> | undefined): Requires<TContext> | undefined {\n if (requires === undefined) {\n return undefined;\n }\n\n return {\n auth: requires.auth,\n apiVersion: requires.apiVersion,\n check: requires.check,\n };\n}\n\nfunction parseStackPath(candidate: string): string | undefined {\n if (candidate.startsWith(\"file://\")) {\n try {\n return fileURLToPath(candidate);\n } catch {\n return undefined;\n }\n }\n\n if (candidate.startsWith(\"/\")) {\n return candidate;\n }\n\n return undefined;\n}\n\nfunction extractStackPath(line: string): string | undefined {\n const trimmed = line.trim();\n const fileIndex = trimmed.indexOf(\"file://\");\n\n if (fileIndex >= 0) {\n const location = trimmed.slice(fileIndex);\n const separatorIndex = location.lastIndexOf(\":\");\n const previousSeparatorIndex = separatorIndex >= 0 ? location.lastIndexOf(\":\", separatorIndex - 1) : -1;\n const candidate =\n separatorIndex >= 0 && previousSeparatorIndex >= 0\n ? location.slice(0, previousSeparatorIndex)\n : location;\n\n return parseStackPath(candidate);\n }\n\n const slashIndex = trimmed.indexOf(\"/\");\n if (slashIndex < 0) {\n return undefined;\n }\n\n const location = trimmed.slice(slashIndex);\n const separatorIndex = location.lastIndexOf(\":\");\n const previousSeparatorIndex = separatorIndex >= 0 ? location.lastIndexOf(\":\", separatorIndex - 1) : -1;\n const candidate =\n separatorIndex >= 0 && previousSeparatorIndex >= 0\n ? location.slice(0, previousSeparatorIndex)\n : location;\n\n return parseStackPath(candidate);\n}\n\nfunction inferCommandSourcePath(): string | undefined {\n const stack = new Error().stack;\n\n if (typeof stack !== \"string\") {\n return undefined;\n }\n\n for (const line of stack.split(\"\\n\").slice(1)) {\n const candidate = extractStackPath(line);\n\n if (candidate === undefined) {\n continue;\n }\n\n if (\n candidate.includes(\"/packages/cmdkit/src/index.ts\") ||\n candidate.includes(\"/packages/cmdkit/dist/index.js\")\n ) {\n continue;\n }\n\n return candidate;\n }\n\n return undefined;\n}\n\nfunction composeChecks(\n parentCheck: Requires<any>[\"check\"] | undefined,\n childCheck: Requires<any>[\"check\"] | undefined\n): Requires<any>[\"check\"] | undefined {\n if (parentCheck === undefined) {\n return childCheck;\n }\n\n if (childCheck === undefined) {\n return parentCheck;\n }\n\n return async (ctx) => {\n const parentResult = await parentCheck(ctx);\n if (!parentResult.ok) {\n return parentResult;\n }\n\n return childCheck(ctx);\n };\n}\n\nfunction mergeRequires(parent: Requires<any> | undefined, child: Requires<any> | undefined): Requires<any> | undefined {\n if (parent === undefined && child === undefined) {\n return undefined;\n }\n\n const merged: Requires<any> = {\n auth: child?.auth ?? parent?.auth,\n apiVersion: child?.apiVersion ?? parent?.apiVersion,\n check: composeChecks(parent?.check, child?.check),\n };\n\n if (\n merged.auth === undefined &&\n merged.apiVersion === undefined &&\n merged.check === undefined\n ) {\n return undefined;\n }\n\n return merged;\n}\n\nfunction parseSimpleSemver(value: string): [number, number, number] | undefined {\n const parts = value.split(\".\");\n if (parts.length !== 3) {\n return undefined;\n }\n\n const parsed = parts.map((part) => {\n if (part.length === 0) {\n return Number.NaN;\n }\n\n for (const char of part) {\n if (char < \"0\" || char > \"9\") {\n return Number.NaN;\n }\n }\n\n return Number(part);\n });\n\n if (parsed.some((part) => !Number.isInteger(part) || part < 0)) {\n return undefined;\n }\n\n return parsed as [number, number, number];\n}\n\nfunction parseMinimumApiVersion(requirement: string): [number, number, number] | undefined {\n if (!requirement.startsWith(\">=\")) {\n return undefined;\n }\n\n return parseSimpleSemver(requirement.slice(2).trim());\n}\n\nfunction compareSemver(left: [number, number, number], right: [number, number, number]): number {\n for (let index = 0; index < left.length; index += 1) {\n if (left[index] === right[index]) {\n continue;\n }\n\n return left[index]! > right[index]! ? 1 : -1;\n }\n\n return 0;\n}\n\nexport function resolveCommandSecrets(\n command: Command<any, any, any, any>,\n env: Record<string, string | undefined> = process.env\n): Record<string, string | undefined> {\n const secrets: Record<string, string | undefined> = {};\n\n for (const [name, secret] of Object.entries(command.secrets)) {\n const value = env[secret.env];\n\n if (value === undefined && secret.optional !== true) {\n const details = secret.description ? `\\n ${secret.description}` : \"\";\n throw new UserError(`Error: Missing required secret ${secret.env}${details}`);\n }\n\n secrets[name] = value;\n }\n\n return secrets;\n}\n\nexport async function assertCommandRequirements(\n command: Command<any, any, any, any>,\n context: GroupCheckContext<any>,\n options: CommandRequirementOptions = {}\n): Promise<void> {\n const requires = command.requires;\n if (requires === undefined) {\n return;\n }\n\n const env = options.env ?? process.env;\n const authEnvVar = options.authEnvVar ?? \"POE_API_KEY\";\n\n if (requires.auth === true && env[authEnvVar] === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires authentication.\\n Run 'poe-code login' first.`\n );\n }\n\n if (requires.apiVersion !== undefined) {\n const minimumVersion = parseMinimumApiVersion(requires.apiVersion);\n if (minimumVersion === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" has invalid apiVersion requirement \"${requires.apiVersion}\". Expected format \">=X.Y.Z\".`\n );\n }\n\n if (options.apiVersion === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires API version ${requires.apiVersion}, but no runner API version was provided.`\n );\n }\n\n const runnerVersion = parseSimpleSemver(options.apiVersion);\n if (runnerVersion === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires API version ${requires.apiVersion}, but runner API version \"${options.apiVersion}\" is not valid semver.`\n );\n }\n\n if (compareSemver(runnerVersion, minimumVersion) < 0) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires API version ${requires.apiVersion}, but runner API version is ${options.apiVersion}.`\n );\n }\n }\n\n const checkResult = await requires.check?.(context);\n if (checkResult && !checkResult.ok) {\n throw new UserError(checkResult.message ?? \"Command precondition failed.\");\n }\n}\n\nfunction mergeSecrets(parent: SecretDeclarations, child: SecretDeclarations): SecretDeclarations {\n return cloneSecrets({\n ...parent,\n ...child,\n });\n}\n\nfunction resolveCommandScope(ownScope: Scope[] | undefined, inheritedScope: Scope[] | undefined): Scope[] {\n return cloneScope(ownScope ?? inheritedScope) ?? [\"cli\", \"sdk\"];\n}\n\nfunction resolveGroupScope(ownScope: Scope[] | undefined, inheritedScope: Scope[] | undefined): Scope[] | undefined {\n return cloneScope(ownScope ?? inheritedScope);\n}\n\nfunction createBaseCommand<\n TServices extends object,\n TParamsSchema extends ObjectSchema<any>,\n TSecrets extends SecretDeclarations | undefined,\n TResult,\n>(\n config: CommandConfig<TServices, TParamsSchema, TSecrets, TResult>\n): Command<TServices, TParamsSchema, TSecrets, TResult> {\n const command: Command<TServices, TParamsSchema, TSecrets, TResult> = {\n kind: \"command\",\n name: config.name,\n description: config.description,\n aliases: [...(config.aliases ?? [])],\n positional: [...(config.positional ?? [])],\n params: config.params,\n secrets: cloneSecrets(config.secrets),\n scope: resolveCommandScope(config.scope, undefined),\n confirm: config.confirm ?? false,\n requires: cloneRequires(config.requires),\n handler: config.handler,\n render: config.render,\n };\n\n Object.defineProperty(command, commandConfigSymbol, {\n value: {\n scope: cloneScope(config.scope),\n secrets: cloneSecrets(config.secrets),\n requires: cloneRequires(config.requires),\n sourcePath: inferCommandSourcePath(),\n } satisfies InternalCommandConfig,\n });\n\n return command;\n}\n\nfunction createBaseGroup<TServices extends object>(config: GroupConfig<TServices>): Group<TServices> {\n const group: Group<TServices> = {\n kind: \"group\",\n name: config.name,\n description: config.description,\n aliases: [...(config.aliases ?? [])],\n scope: resolveGroupScope(config.scope, undefined),\n secrets: cloneSecrets(config.secrets),\n requires: cloneRequires(config.requires),\n children: [],\n default: undefined,\n };\n\n Object.defineProperty(group, groupConfigSymbol, {\n value: {\n scope: cloneScope(config.scope),\n secrets: cloneSecrets(config.secrets),\n requires: cloneRequires(config.requires),\n children: [...config.children],\n default: config.default,\n } satisfies InternalGroupConfig<TServices>,\n });\n\n return group;\n}\n\nfunction getInternalCommandConfig(command: Command<any, any, any, any>): InternalCommandConfig {\n return (command as Command<any, any, any, any> & { [commandConfigSymbol]: InternalCommandConfig })[\n commandConfigSymbol\n ];\n}\n\nfunction getInternalGroupConfig<TServices extends object>(group: Group<TServices>): InternalGroupConfig<TServices> {\n return (group as Group<TServices> & { [groupConfigSymbol]: InternalGroupConfig<TServices> })[\n groupConfigSymbol\n ];\n}\n\nfunction materializeCommand<\n TServices extends object,\n TParamsSchema extends ObjectSchema<any>,\n TSecrets extends SecretDeclarations | undefined,\n TResult,\n>(\n command: Command<TServices, TParamsSchema, TSecrets, TResult>,\n inherited: InheritedMetadata\n): Command<TServices, TParamsSchema, TSecrets, TResult> {\n const internal = getInternalCommandConfig(command);\n\n const materialized: Command<TServices, TParamsSchema, TSecrets, TResult> = {\n kind: \"command\",\n name: command.name,\n description: command.description,\n aliases: [...command.aliases],\n positional: [...command.positional],\n params: command.params,\n secrets: mergeSecrets(inherited.secrets, internal.secrets),\n scope: resolveCommandScope(internal.scope, inherited.scope),\n confirm: command.confirm,\n requires: mergeRequires(inherited.requires, internal.requires),\n handler: command.handler,\n render: command.render,\n };\n\n Object.defineProperty(materialized, commandConfigSymbol, {\n value: {\n scope: cloneScope(internal.scope),\n secrets: cloneSecrets(internal.secrets),\n requires: cloneRequires(internal.requires),\n sourcePath: internal.sourcePath,\n } satisfies InternalCommandConfig,\n });\n\n Object.defineProperty(materialized, commandSourcePathSymbol, {\n value: internal.sourcePath,\n });\n\n return materialized;\n}\n\nfunction materializeGroup<TServices extends object>(\n group: Group<TServices>,\n inherited: InheritedMetadata\n): Group<TServices> {\n const internal = getInternalGroupConfig(group);\n const scope = resolveGroupScope(internal.scope, inherited.scope);\n const secrets = mergeSecrets(inherited.secrets, internal.secrets);\n const requires = mergeRequires(inherited.requires, internal.requires);\n const materializedChildren = internal.children.map((child) =>\n materializeNode(child, {\n scope,\n secrets,\n requires,\n })\n );\n\n let defaultChild: Command<TServices, any, any, any> | undefined;\n\n if (internal.default !== undefined) {\n const defaultIndex = internal.children.indexOf(internal.default);\n\n if (defaultIndex === -1) {\n throw new UserError(`Default command \"${internal.default.name}\" must be listed in children.`);\n }\n\n const resolvedDefault = materializedChildren[defaultIndex];\n if (resolvedDefault?.kind !== \"command\") {\n throw new UserError(`Default child \"${internal.default.name}\" must be a command.`);\n }\n\n defaultChild = resolvedDefault;\n }\n\n const materialized: Group<TServices> = {\n kind: \"group\",\n name: group.name,\n description: group.description,\n aliases: [...group.aliases],\n scope,\n secrets,\n requires,\n children: materializedChildren,\n default: defaultChild,\n };\n\n Object.defineProperty(materialized, groupConfigSymbol, {\n value: {\n scope: cloneScope(internal.scope),\n secrets: cloneSecrets(internal.secrets),\n requires: cloneRequires(internal.requires),\n children: [...internal.children],\n default: internal.default,\n } satisfies InternalGroupConfig<TServices>,\n });\n\n return materialized;\n}\n\nfunction materializeNode<TServices extends object>(\n node: CommandNode<TServices>,\n inherited: InheritedMetadata\n): CommandNode<TServices> {\n if (node.kind === \"command\") {\n return materializeCommand(node, inherited);\n }\n\n return materializeGroup(node, inherited);\n}\n\nexport function defineCommand<\n TServices extends object = EmptyServices,\n TName extends string = string,\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TResult = unknown,\n TOwnScope extends ScopeInput = undefined,\n>(\n config: Omit<CommandConfig<TServices, TParamsSchema, TSecrets, TResult>, \"name\" | \"scope\"> & {\n name: TName;\n scope?: TOwnScope;\n }\n): Command<TServices, TParamsSchema, TSecrets, TResult> &\n TypedCommandMetadata<TName, TParamsSchema, TResult, TOwnScope> {\n return materializeCommand(createBaseCommand(config as CommandConfig<TServices, TParamsSchema, TSecrets, TResult>), {\n scope: undefined,\n secrets: {},\n requires: undefined,\n }) as Command<TServices, TParamsSchema, TSecrets, TResult> &\n TypedCommandMetadata<TName, TParamsSchema, TResult, TOwnScope>;\n}\n\nexport function defineGroup<\n TServices extends object = EmptyServices,\n TName extends string = string,\n TChildren extends readonly unknown[] = readonly CommandNode<TServices>[],\n TOwnScope extends ScopeInput = undefined,\n>(\n config: Omit<GroupConfig<TServices>, \"name\" | \"children\" | \"scope\"> & {\n name: TName;\n children: TChildren & readonly CommandNode<TServices>[];\n scope?: TOwnScope;\n }\n): Group<TServices> & TypedGroupMetadata<TServices, TName, TChildren, TOwnScope> {\n return materializeGroup(createBaseGroup(config as unknown as GroupConfig<TServices>), {\n scope: undefined,\n secrets: {},\n requires: undefined,\n }) as Group<TServices> & TypedGroupMetadata<TServices, TName, TChildren, TOwnScope>;\n}\n\nexport function getCommandSourcePath(command: Command<any, any, any, any>): string | undefined {\n return (command as Command<any, any, any, any> & { [commandSourcePathSymbol]?: string })[\n commandSourcePathSymbol\n ];\n}\n\nexport { S, toJsonSchema } from \"@poe-code/cmdkit-schema\";\nexport type { AnySchema, ArraySchema, BooleanSchema, EnumSchema, JsonSchema, NumberSchema, ObjectSchema, OptionalSchema, Static, StringSchema } from \"@poe-code/cmdkit-schema\";\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { S } from "./index.js";
|
|
2
|
+
const ignoredStringSchema = S.String({ description: "Name", default: "guest" });
|
|
3
|
+
const ignoredNumberSchema = S.Number({ description: "Count", default: 1 });
|
|
4
|
+
const ignoredBooleanSchema = S.Boolean({ description: "Enabled", default: false });
|
|
5
|
+
const ignoredEnumSchema = S.Enum(["admin", "user"], { default: "admin" });
|
|
6
|
+
const ignoredArraySchema = S.Array(S.String(), { default: ["a"] });
|
|
7
|
+
const ignoredObjectSchema = S.Object({
|
|
8
|
+
name: S.String(),
|
|
9
|
+
retries: S.Optional(S.Number()),
|
|
10
|
+
});
|
|
11
|
+
const ignoredOptionalSchema = S.Optional(S.Boolean());
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
type JsonSchemaType = "string" | "number" | "boolean" | "array" | "object";
|
|
2
|
+
type SchemaKind = "string" | "number" | "boolean" | "enum" | "array" | "object" | "optional";
|
|
3
|
+
type EnumValue = string | number | boolean;
|
|
4
|
+
type NonEmptyReadonlyArray<T> = readonly [T, ...T[]];
|
|
5
|
+
type ObjectShape = Record<string, AnySchema>;
|
|
6
|
+
type OptionalKeys<TShape extends ObjectShape> = {
|
|
7
|
+
[TKey in keyof TShape]: TShape[TKey] extends OptionalSchema<any> ? TKey : never;
|
|
8
|
+
}[keyof TShape];
|
|
9
|
+
type RequiredKeys<TShape extends ObjectShape> = Exclude<keyof TShape, OptionalKeys<TShape>>;
|
|
10
|
+
type PropertyStatic<TSchema extends AnySchema> = TSchema extends OptionalSchema<infer TInner> ? Static<TInner> : Static<TSchema>;
|
|
11
|
+
type InferObject<TShape extends ObjectShape> = {
|
|
12
|
+
[TKey in RequiredKeys<TShape>]: PropertyStatic<TShape[TKey]>;
|
|
13
|
+
} & {
|
|
14
|
+
[TKey in OptionalKeys<TShape>]?: PropertyStatic<TShape[TKey]>;
|
|
15
|
+
};
|
|
16
|
+
type SchemaOptions<TDefault> = {
|
|
17
|
+
description?: string;
|
|
18
|
+
default?: TDefault;
|
|
19
|
+
short?: string;
|
|
20
|
+
};
|
|
21
|
+
interface SchemaBase<TKind extends SchemaKind, TStatic> {
|
|
22
|
+
readonly kind: TKind;
|
|
23
|
+
readonly description?: string;
|
|
24
|
+
readonly default?: TStatic;
|
|
25
|
+
readonly short?: string;
|
|
26
|
+
readonly __static?: TStatic;
|
|
27
|
+
}
|
|
28
|
+
export interface JsonSchema {
|
|
29
|
+
type?: JsonSchemaType;
|
|
30
|
+
description?: string;
|
|
31
|
+
default?: unknown;
|
|
32
|
+
enum?: ReadonlyArray<EnumValue>;
|
|
33
|
+
items?: JsonSchema;
|
|
34
|
+
properties?: Record<string, JsonSchema>;
|
|
35
|
+
required?: string[];
|
|
36
|
+
}
|
|
37
|
+
export type StringSchema = SchemaBase<"string", string>;
|
|
38
|
+
export type NumberSchema = SchemaBase<"number", number>;
|
|
39
|
+
export type BooleanSchema = SchemaBase<"boolean", boolean>;
|
|
40
|
+
export interface EnumSchema<TValues extends NonEmptyReadonlyArray<EnumValue>> extends SchemaBase<"enum", TValues[number]> {
|
|
41
|
+
readonly values: TValues;
|
|
42
|
+
readonly labels?: Partial<Record<string, string>>;
|
|
43
|
+
readonly loadOptions?: () => Array<{
|
|
44
|
+
label: string;
|
|
45
|
+
value: string;
|
|
46
|
+
}> | Promise<Array<{
|
|
47
|
+
label: string;
|
|
48
|
+
value: string;
|
|
49
|
+
}>>;
|
|
50
|
+
}
|
|
51
|
+
export interface ArraySchema<TItem extends AnySchema> extends SchemaBase<"array", Array<Static<TItem>>> {
|
|
52
|
+
readonly item: TItem;
|
|
53
|
+
}
|
|
54
|
+
export interface ObjectSchema<TShape extends ObjectShape> extends SchemaBase<"object", InferObject<TShape>> {
|
|
55
|
+
readonly shape: TShape;
|
|
56
|
+
}
|
|
57
|
+
export interface OptionalSchema<TInner extends AnySchema> extends SchemaBase<"optional", Static<TInner> | undefined> {
|
|
58
|
+
readonly inner: TInner;
|
|
59
|
+
}
|
|
60
|
+
export type AnySchema = StringSchema | NumberSchema | BooleanSchema | EnumSchema<NonEmptyReadonlyArray<EnumValue>> | ArraySchema<AnySchema> | ObjectSchema<ObjectShape> | OptionalSchema<AnySchema>;
|
|
61
|
+
export type Static<TSchema extends AnySchema> = TSchema extends SchemaBase<any, infer TStatic> ? TStatic : never;
|
|
62
|
+
export declare const S: {
|
|
63
|
+
readonly String: (options?: SchemaOptions<string>) => StringSchema;
|
|
64
|
+
readonly Number: (options?: SchemaOptions<number>) => NumberSchema;
|
|
65
|
+
readonly Boolean: (options?: SchemaOptions<boolean>) => BooleanSchema;
|
|
66
|
+
readonly Enum: <const TValues extends NonEmptyReadonlyArray<EnumValue>>(values: TValues, options?: SchemaOptions<TValues[number]> & {
|
|
67
|
+
labels?: Partial<Record<string, string>>;
|
|
68
|
+
loadOptions?: () => Array<{
|
|
69
|
+
label: string;
|
|
70
|
+
value: string;
|
|
71
|
+
}> | Promise<Array<{
|
|
72
|
+
label: string;
|
|
73
|
+
value: string;
|
|
74
|
+
}>>;
|
|
75
|
+
}) => EnumSchema<TValues>;
|
|
76
|
+
readonly Array: <TItem extends AnySchema>(item: TItem, options?: SchemaOptions<Array<Static<TItem>>>) => ArraySchema<TItem>;
|
|
77
|
+
readonly Object: <const TShape extends ObjectShape>(shape: TShape) => ObjectSchema<TShape>;
|
|
78
|
+
readonly Optional: <TInner extends AnySchema>(inner: TInner) => OptionalSchema<TInner>;
|
|
79
|
+
};
|
|
80
|
+
export declare function toJsonSchema(schema: AnySchema): JsonSchema;
|
|
81
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
function withMetadata(schema, jsonSchema) {
|
|
2
|
+
if (schema.description !== undefined) {
|
|
3
|
+
jsonSchema.description = schema.description;
|
|
4
|
+
}
|
|
5
|
+
if (schema.default !== undefined) {
|
|
6
|
+
jsonSchema.default = schema.default;
|
|
7
|
+
}
|
|
8
|
+
return jsonSchema;
|
|
9
|
+
}
|
|
10
|
+
function getEnumJsonType(values) {
|
|
11
|
+
const [firstValue] = values;
|
|
12
|
+
if (firstValue === undefined) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const firstType = typeof firstValue;
|
|
16
|
+
const isSinglePrimitiveType = values.every((value) => typeof value === firstType);
|
|
17
|
+
if (!isSinglePrimitiveType) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
if (firstType === "string" || firstType === "number" || firstType === "boolean") {
|
|
21
|
+
return firstType;
|
|
22
|
+
}
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
function isOptionalSchema(schema) {
|
|
26
|
+
return schema.kind === "optional";
|
|
27
|
+
}
|
|
28
|
+
function assertValidEnumValues(values) {
|
|
29
|
+
if (values.length === 0) {
|
|
30
|
+
throw new Error("Enum schema requires at least one value");
|
|
31
|
+
}
|
|
32
|
+
const uniqueValues = new Set(values);
|
|
33
|
+
if (uniqueValues.size !== values.length) {
|
|
34
|
+
throw new Error("Enum schema values must be unique");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function unwrapOptional(schema) {
|
|
38
|
+
if (isOptionalSchema(schema)) {
|
|
39
|
+
return unwrapOptional(schema.inner);
|
|
40
|
+
}
|
|
41
|
+
return schema;
|
|
42
|
+
}
|
|
43
|
+
export const S = {
|
|
44
|
+
String(options = {}) {
|
|
45
|
+
return {
|
|
46
|
+
kind: "string",
|
|
47
|
+
...options,
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
Number(options = {}) {
|
|
51
|
+
return {
|
|
52
|
+
kind: "number",
|
|
53
|
+
...options,
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
Boolean(options = {}) {
|
|
57
|
+
return {
|
|
58
|
+
kind: "boolean",
|
|
59
|
+
...options,
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
Enum(values, options = {}) {
|
|
63
|
+
assertValidEnumValues(values);
|
|
64
|
+
return {
|
|
65
|
+
kind: "enum",
|
|
66
|
+
values,
|
|
67
|
+
...options,
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
Array(item, options = {}) {
|
|
71
|
+
return {
|
|
72
|
+
kind: "array",
|
|
73
|
+
item,
|
|
74
|
+
...options,
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
Object(shape) {
|
|
78
|
+
return {
|
|
79
|
+
kind: "object",
|
|
80
|
+
shape,
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
Optional(inner) {
|
|
84
|
+
return {
|
|
85
|
+
kind: "optional",
|
|
86
|
+
inner,
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
export function toJsonSchema(schema) {
|
|
91
|
+
const unwrappedSchema = unwrapOptional(schema);
|
|
92
|
+
switch (unwrappedSchema.kind) {
|
|
93
|
+
case "string":
|
|
94
|
+
return withMetadata(unwrappedSchema, { type: "string" });
|
|
95
|
+
case "number":
|
|
96
|
+
return withMetadata(unwrappedSchema, { type: "number" });
|
|
97
|
+
case "boolean":
|
|
98
|
+
return withMetadata(unwrappedSchema, { type: "boolean" });
|
|
99
|
+
case "enum": {
|
|
100
|
+
const jsonSchema = {
|
|
101
|
+
enum: [...unwrappedSchema.values],
|
|
102
|
+
};
|
|
103
|
+
const enumType = getEnumJsonType(unwrappedSchema.values);
|
|
104
|
+
if (enumType !== undefined) {
|
|
105
|
+
jsonSchema.type = enumType;
|
|
106
|
+
}
|
|
107
|
+
return withMetadata(unwrappedSchema, jsonSchema);
|
|
108
|
+
}
|
|
109
|
+
case "array":
|
|
110
|
+
return withMetadata(unwrappedSchema, {
|
|
111
|
+
type: "array",
|
|
112
|
+
items: toJsonSchema(unwrappedSchema.item),
|
|
113
|
+
});
|
|
114
|
+
case "object": {
|
|
115
|
+
const properties = {};
|
|
116
|
+
const required = [];
|
|
117
|
+
for (const [key, propertySchema] of Object.entries(unwrappedSchema.shape)) {
|
|
118
|
+
properties[key] = toJsonSchema(propertySchema);
|
|
119
|
+
if (!isOptionalSchema(propertySchema)) {
|
|
120
|
+
required.push(key);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
type: "object",
|
|
125
|
+
properties,
|
|
126
|
+
required,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function renderAgentMessage(text: string): void;
|
|
2
|
+
export declare function renderToolStart(kind: string, title: string): void;
|
|
3
|
+
export declare function renderToolComplete(kind: string): void;
|
|
4
|
+
export declare function renderReasoning(text: string): void;
|
|
5
|
+
export declare function renderUsage(tokens: {
|
|
6
|
+
input: number;
|
|
7
|
+
output: number;
|
|
8
|
+
cached?: number;
|
|
9
|
+
costUsd?: number;
|
|
10
|
+
}): void;
|
|
11
|
+
export declare function renderError(message: string): void;
|