theokit 0.20.0 → 0.22.0
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/{agent-76WK2CZJ.js → agent-GXPTQTCU.js} +2 -2
- package/dist/{build-6UDZJIHD.js → build-2JDQBBWN.js} +3 -3
- package/dist/{chunk-DXF64KS5.js → chunk-4QXVTX3X.js} +30 -12
- package/dist/chunk-4QXVTX3X.js.map +1 -0
- package/dist/{chunk-WLKFWVOM.js → chunk-5PY3QPVM.js} +32 -47
- package/dist/chunk-5PY3QPVM.js.map +1 -0
- package/dist/{chunk-3WOODHXK.js → chunk-D7D6V6FN.js} +12 -6
- package/dist/chunk-D7D6V6FN.js.map +1 -0
- package/dist/{chunk-W4YO6S4I.js → chunk-FO2KMFAE.js} +101 -67
- package/dist/chunk-FO2KMFAE.js.map +1 -0
- package/dist/{chunk-23T4CO4M.js → chunk-JRYP7KNS.js} +2 -2
- package/dist/{chunk-7PFHQ56Q.js → chunk-RQCZTDCX.js} +39 -15
- package/dist/chunk-RQCZTDCX.js.map +1 -0
- package/dist/{chunk-DMC6HYUR.js → chunk-VS6LJM2V.js} +69 -47
- package/dist/chunk-VS6LJM2V.js.map +1 -0
- package/dist/cli/index.js +6 -6
- package/dist/{define-websocket-CdK94O-D.d.ts → define-websocket-CPQcQK9h.d.ts} +1 -19
- package/dist/{dev-NHHTXOA4.js → dev-7AW7FBNH.js} +4 -4
- package/dist/{generate-OMKHQ7OM.js → generate-373DALPY.js} +62 -70
- package/dist/generate-373DALPY.js.map +1 -0
- package/dist/{index-B40qUSrQ.d.ts → index-C3ged4mn.d.ts} +2 -2
- package/dist/index.d.ts +1 -8
- package/dist/index.js +2 -3
- package/dist/{mcp-HP5RVOOZ.js → mcp-MOKIIMJ6.js} +4 -4
- package/dist/{mcp-HP5RVOOZ.js.map → mcp-MOKIIMJ6.js.map} +1 -1
- package/dist/{plugin-runner-BGBkzgi0.d.ts → plugin-runner-CMprWWHZ.d.ts} +1 -1
- package/dist/{plugin-types-DNJGxr4Z.d.ts → plugin-types-L49QYMb5.d.ts} +1 -19
- package/dist/{registry-XSRSTH33.js → registry-3NB7KOUI.js} +2 -2
- package/dist/server/define/index.d.ts +169 -221
- package/dist/server/define/index.js +1 -15
- package/dist/server/http/index.d.ts +3 -3
- package/dist/server/index.d.ts +168 -7
- package/dist/server/index.js +61 -19
- package/dist/server/index.js.map +1 -1
- package/dist/server/plugins/index.d.ts +3 -3
- package/dist/server/realtime/index.d.ts +1 -1
- package/dist/{start-ILT6E25Q.js → start-4VHDT4TN.js} +6 -4
- package/dist/{start-ILT6E25Q.js.map → start-4VHDT4TN.js.map} +1 -1
- package/dist/{static-CYG2WGYP.js → static-MB2CD5Y3.js} +1 -1
- package/dist/static-MB2CD5Y3.js.map +1 -0
- package/dist/vite-plugin/index.js +2 -2
- package/dist/{vite-plugin-3UDOJGO5.js → vite-plugin-5WTU62ZH.js} +4 -4
- package/package.json +2 -2
- package/dist/chunk-3WOODHXK.js.map +0 -1
- package/dist/chunk-7PFHQ56Q.js.map +0 -1
- package/dist/chunk-DMC6HYUR.js.map +0 -1
- package/dist/chunk-DXF64KS5.js.map +0 -1
- package/dist/chunk-W4YO6S4I.js.map +0 -1
- package/dist/chunk-WLKFWVOM.js.map +0 -1
- package/dist/generate-OMKHQ7OM.js.map +0 -1
- package/dist/static-CYG2WGYP.js.map +0 -1
- /package/dist/{agent-76WK2CZJ.js.map → agent-GXPTQTCU.js.map} +0 -0
- /package/dist/{build-6UDZJIHD.js.map → build-2JDQBBWN.js.map} +0 -0
- /package/dist/{chunk-23T4CO4M.js.map → chunk-JRYP7KNS.js.map} +0 -0
- /package/dist/{dev-NHHTXOA4.js.map → dev-7AW7FBNH.js.map} +0 -0
- /package/dist/{registry-XSRSTH33.js.map → registry-3NB7KOUI.js.map} +0 -0
- /package/dist/{vite-plugin-3UDOJGO5.js.map → vite-plugin-5WTU62ZH.js.map} +0 -0
|
@@ -27,12 +27,18 @@ function extractAppResources(mod) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
// src/server/agent/mcp-handler.ts
|
|
30
|
-
import {
|
|
31
|
-
buildMcpToolDescriptors,
|
|
32
|
-
compileAgentModule,
|
|
33
|
-
mcpServerInfo
|
|
34
|
-
} from "@theokit/agents";
|
|
30
|
+
import { compileAgentModule } from "@theokit/agents";
|
|
35
31
|
var MCP_PATH = /^\/api\/agents\/([^/]+)\/mcp$/;
|
|
32
|
+
var MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
33
|
+
function toolDescriptors(tools) {
|
|
34
|
+
return tools.map((t) => ({
|
|
35
|
+
name: t.name,
|
|
36
|
+
description: t.description,
|
|
37
|
+
// The compiled tool already carries a JSON Schema (via `z.toJSONSchema()` in defineAgentTool).
|
|
38
|
+
// Fall back to a permissive object only when a tool genuinely declared no schema.
|
|
39
|
+
inputSchema: t.inputSchema && typeof t.inputSchema === "object" ? t.inputSchema : { type: "object", properties: {} }
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
36
42
|
function isMcpPath(urlPath) {
|
|
37
43
|
const match = MCP_PATH.exec(urlPath);
|
|
38
44
|
return match ? decodeURIComponent(match[1]) : null;
|
|
@@ -46,26 +52,50 @@ function jsonResponse(payload) {
|
|
|
46
52
|
headers: { "content-type": "application/json; charset=utf-8" }
|
|
47
53
|
});
|
|
48
54
|
}
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
async function callTool(tools, toolName, args) {
|
|
56
|
+
if (typeof toolName !== "string") {
|
|
57
|
+
return {
|
|
58
|
+
content: [{ type: "text", text: "tools/call requires a string `name`." }],
|
|
59
|
+
isError: true
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const tool = tools.find((t) => t.name === toolName);
|
|
63
|
+
if (!tool) {
|
|
64
|
+
return { content: [{ type: "text", text: `Unknown tool: ${toolName}` }], isError: true };
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const result = await tool.handler(args);
|
|
68
|
+
const text = typeof result === "string" ? result : JSON.stringify(result);
|
|
69
|
+
return { content: [{ type: "text", text }] };
|
|
70
|
+
} catch (err) {
|
|
71
|
+
return {
|
|
72
|
+
content: [
|
|
73
|
+
{ type: "text", text: err instanceof Error ? err.message : "Tool execution failed" }
|
|
74
|
+
],
|
|
75
|
+
isError: true
|
|
76
|
+
};
|
|
77
|
+
}
|
|
67
78
|
}
|
|
68
|
-
function
|
|
79
|
+
function handleResourcesRead(id, params, appResources) {
|
|
80
|
+
const uri = params?.uri;
|
|
81
|
+
if (typeof uri !== "string") {
|
|
82
|
+
return jsonResponse({
|
|
83
|
+
jsonrpc: "2.0",
|
|
84
|
+
id,
|
|
85
|
+
error: { code: -32602, message: "resources/read requires a string `uri` param." }
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
const contents = readAppResource(appResources, uri);
|
|
89
|
+
if (contents === null) {
|
|
90
|
+
return jsonResponse({
|
|
91
|
+
jsonrpc: "2.0",
|
|
92
|
+
id,
|
|
93
|
+
error: { code: -32602, message: `Resource not found: ${uri}` }
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return jsonResponse({ jsonrpc: "2.0", id, result: contents });
|
|
97
|
+
}
|
|
98
|
+
async function handleMcpJsonRpc(mod, name, body, appResources = []) {
|
|
69
99
|
if (!isJsonRpcRequest(body)) {
|
|
70
100
|
return jsonResponse({
|
|
71
101
|
jsonrpc: "2.0",
|
|
@@ -75,23 +105,31 @@ function handleMcpJsonRpc(mod, name, body, appResources = []) {
|
|
|
75
105
|
}
|
|
76
106
|
const { id, method, params } = body;
|
|
77
107
|
try {
|
|
78
|
-
const
|
|
108
|
+
const compiled = compileAgentModule(mod, `mcp server for "${name}"`);
|
|
79
109
|
if (method === "initialize") {
|
|
80
|
-
const info = mcpServerInfo(entry);
|
|
81
110
|
const capabilities = { tools: {} };
|
|
82
111
|
if (appResources.length > 0) capabilities.resources = {};
|
|
83
112
|
return jsonResponse({
|
|
84
113
|
jsonrpc: "2.0",
|
|
85
114
|
id,
|
|
86
115
|
result: {
|
|
87
|
-
protocolVersion:
|
|
116
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
88
117
|
capabilities,
|
|
89
|
-
serverInfo: { name
|
|
118
|
+
serverInfo: { name, version: "1.0" }
|
|
90
119
|
}
|
|
91
120
|
});
|
|
92
121
|
}
|
|
93
122
|
if (method === "tools/list") {
|
|
94
|
-
return jsonResponse({
|
|
123
|
+
return jsonResponse({
|
|
124
|
+
jsonrpc: "2.0",
|
|
125
|
+
id,
|
|
126
|
+
result: { tools: toolDescriptors(compiled.tools) }
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (method === "tools/call") {
|
|
130
|
+
const p = params;
|
|
131
|
+
const result = await callTool(compiled.tools, p?.name, p?.arguments ?? {});
|
|
132
|
+
return jsonResponse({ jsonrpc: "2.0", id, result });
|
|
95
133
|
}
|
|
96
134
|
if (method === "resources/list") {
|
|
97
135
|
return jsonResponse({
|
|
@@ -101,23 +139,7 @@ function handleMcpJsonRpc(mod, name, body, appResources = []) {
|
|
|
101
139
|
});
|
|
102
140
|
}
|
|
103
141
|
if (method === "resources/read") {
|
|
104
|
-
|
|
105
|
-
if (typeof uri !== "string") {
|
|
106
|
-
return jsonResponse({
|
|
107
|
-
jsonrpc: "2.0",
|
|
108
|
-
id,
|
|
109
|
-
error: { code: -32602, message: "resources/read requires a string `uri` param." }
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
const contents = readAppResource(appResources, uri);
|
|
113
|
-
if (contents === null) {
|
|
114
|
-
return jsonResponse({
|
|
115
|
-
jsonrpc: "2.0",
|
|
116
|
-
id,
|
|
117
|
-
error: { code: -32602, message: `Resource not found: ${uri}` }
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
return jsonResponse({ jsonrpc: "2.0", id, result: contents });
|
|
142
|
+
return handleResourcesRead(id, params, appResources);
|
|
121
143
|
}
|
|
122
144
|
return jsonResponse({
|
|
123
145
|
jsonrpc: "2.0",
|
|
@@ -138,4 +160,4 @@ export {
|
|
|
138
160
|
isMcpPath,
|
|
139
161
|
handleMcpJsonRpc
|
|
140
162
|
};
|
|
141
|
-
//# sourceMappingURL=chunk-
|
|
163
|
+
//# sourceMappingURL=chunk-VS6LJM2V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/agent/mcp-app-resources.ts","../src/server/agent/mcp-handler.ts"],"sourcesContent":["/**\n * M30 (ADR-0041) — MCP Apps: `ui://` HTML resources for the MCP server (M16).\n *\n * A tool can declare a `ui://` HTML resource; the MCP server advertises it via `resources/list` and\n * serves the HTML via `resources/read`. The client renders it in a SANDBOXED iframe (see\n * `mcp-app-host.ts`). Pure data transforms here — no LLM, no runtime (ADR-0040 § D2 home concern).\n *\n * Security: only the `ui://` scheme is accepted (an app UI resource), never `http(s)://` — the HTML\n * is rendered sandboxed on the client, and the scheme gate keeps a tool from smuggling a remote URL\n * into the app surface.\n */\n\n/** A declared `ui://` app resource. */\nexport interface AppResource {\n uri: string\n name: string\n mimeType: 'text/html'\n html: string\n description?: string\n}\n\n/** Input to {@link defineAppResource}. */\nexport interface AppResourceInput {\n /** MUST start with `ui://`. */\n uri: string\n name: string\n html: string\n description?: string\n}\n\n/** An MCP `resources/list` descriptor (no HTML body — that comes from `resources/read`). */\nexport interface McpResourceDescriptor {\n uri: string\n name: string\n mimeType: 'text/html'\n description?: string\n}\n\n/** An MCP `resources/read` result. */\nexport interface McpResourceContents {\n contents: { uri: string; mimeType: 'text/html'; text: string }[]\n}\n\n/**\n * Declare a `ui://` HTML app resource. Fails fast if the uri is not a `ui://` scheme or the HTML is\n * empty (error-handling.md) — a misconfigured resource is caught at definition time.\n */\nexport function defineAppResource(input: AppResourceInput): AppResource {\n if (!input.uri.startsWith('ui://')) {\n throw new Error(\n `defineAppResource: uri must use the ui:// scheme (an app UI resource). Got: ${JSON.stringify(input.uri)}`,\n )\n }\n if (input.html.length === 0) {\n throw new Error(`defineAppResource(${JSON.stringify(input.uri)}): html must be non-empty.`)\n }\n return {\n uri: input.uri,\n name: input.name,\n mimeType: 'text/html',\n html: input.html,\n ...(input.description !== undefined ? { description: input.description } : {}),\n }\n}\n\n/** Map app resources to MCP `resources/list` descriptors (the HTML body is omitted from the list). */\nexport function buildResourceDescriptors(\n resources: readonly AppResource[],\n): McpResourceDescriptor[] {\n return resources.map((r) => ({\n uri: r.uri,\n name: r.name,\n mimeType: r.mimeType,\n ...(r.description !== undefined ? { description: r.description } : {}),\n }))\n}\n\n/** Serve the HTML for `uri` as an MCP `resources/read` result, or `null` when unknown. */\nexport function readAppResource(\n resources: readonly AppResource[],\n uri: string,\n): McpResourceContents | null {\n const found = resources.find((r) => r.uri === uri)\n if (!found) return null\n return { contents: [{ uri: found.uri, mimeType: 'text/html', text: found.html }] }\n}\n\n/** True when `v` is a well-formed {@link AppResource} (from `defineAppResource`). */\nfunction isAppResource(v: unknown): v is AppResource {\n if (typeof v !== 'object' || v === null) return false\n const r = v as Record<string, unknown>\n return (\n typeof r.uri === 'string' &&\n r.uri.startsWith('ui://') &&\n r.mimeType === 'text/html' &&\n typeof r.html === 'string'\n )\n}\n\n/**\n * M30 wiring — extract the App resources an agent module declares via a named `appResources` export\n * (`export const appResources = [defineAppResource(...)]`). Returns only the well-formed entries; a\n * module without the export (or with a malformed one) yields `[]`. This is how per-agent `ui://`\n * resources reach the MCP server's `resources/list` + `resources/read` without a runtime dependency\n * from `@theokit/agents` on this theo-side type (the module exports them; the serving path reads them).\n */\nexport function extractAppResources(mod: unknown): AppResource[] {\n const raw = (mod as { appResources?: unknown } | null | undefined)?.appResources\n if (!Array.isArray(raw)) return []\n return raw.filter(isAppResource)\n}\n","/**\n * M16 (theokit-ai-first) — serve an agent as an MCP server over HTTP at `/api/agents/<name>/mcp`.\n *\n * Answers the two core MCP methods over JSON-RPC 2.0: `initialize` (server info + capabilities) and\n * `tools/list` (the agent's tools as MCP descriptors, via `buildMcpToolDescriptors`). M30 adds\n * `resources/list` + `resources/read` for `ui://` App resources. Unknown methods return `-32601`\n * (method not found). Web Standards Response (G8). The stdio transport + full method set stay\n * SDK-side (sdk-runtime.md); this exposes the agent over the app's own HTTP route.\n */\nimport { type CompiledTool, compileAgentModule } from '@theokit/agents'\n\nimport { type AppResource, buildResourceDescriptors, readAppResource } from './mcp-app-resources.js'\n\nconst MCP_PATH = /^\\/api\\/agents\\/([^/]+)\\/mcp$/\n\n/**\n * The MCP protocol revision THIS server transport implements (M34). The protocol version is a\n * property of the server that speaks it (this handler), not of the manifest data generator — so the\n * handler owns it. Current MCP revision (`2025-06-18`); replaces the stale `2024-11-05` the manifest\n * generator carried.\n */\nconst MCP_PROTOCOL_VERSION = '2025-06-18'\n\n/** An MCP `tools/list` descriptor with the tool's REAL input schema retained (M34 — no longer dropped). */\ninterface McpToolDescriptor {\n name: string\n description: string\n inputSchema: Record<string, unknown>\n}\n\n/** Build tool descriptors from the compiled tools, retaining each tool's real JSON-Schema input (M34). */\nfunction toolDescriptors(tools: readonly CompiledTool[]): McpToolDescriptor[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n // The compiled tool already carries a JSON Schema (via `z.toJSONSchema()` in defineAgentTool).\n // Fall back to a permissive object only when a tool genuinely declared no schema.\n inputSchema:\n t.inputSchema && typeof t.inputSchema === 'object'\n ? (t.inputSchema as Record<string, unknown>)\n : { type: 'object', properties: {} },\n }))\n}\n\n/** An MCP `CallToolResult` — `content[]` + `isError` (the shape MCP clients expect). */\ninterface CallToolResult {\n content: { type: 'text'; text: string }[]\n isError?: boolean\n}\n\n/** Return the agent name when `urlPath` is the MCP endpoint, else `null`. */\nexport function isMcpPath(urlPath: string): string | null {\n const match = MCP_PATH.exec(urlPath)\n return match ? decodeURIComponent(match[1]) : null\n}\n\ninterface JsonRpcRequest {\n jsonrpc: '2.0'\n id: number | string | null\n method: string\n params?: unknown\n}\n\nfunction isJsonRpcRequest(body: unknown): body is JsonRpcRequest {\n return (\n typeof body === 'object' &&\n body !== null &&\n (body as { jsonrpc?: unknown }).jsonrpc === '2.0' &&\n typeof (body as { method?: unknown }).method === 'string'\n )\n}\n\nfunction jsonResponse(payload: unknown): Response {\n return new Response(JSON.stringify(payload), {\n status: 200,\n headers: { 'content-type': 'application/json; charset=utf-8' },\n })\n}\n\n/**\n * Execute an MCP `tools/call` against the compiled tools (M34). Finds the tool by name, runs its\n * handler with the supplied `arguments`, and shapes the result into a `CallToolResult`. An unknown\n * tool or a throwing handler yields `{ isError: true }` (MCP convention — the model sees the failure)\n * rather than a JSON-RPC crash.\n */\nasync function callTool(\n tools: readonly CompiledTool[],\n toolName: unknown,\n args: unknown,\n): Promise<CallToolResult> {\n if (typeof toolName !== 'string') {\n return {\n content: [{ type: 'text', text: 'tools/call requires a string `name`.' }],\n isError: true,\n }\n }\n const tool = tools.find((t) => t.name === toolName)\n if (!tool) {\n return { content: [{ type: 'text', text: `Unknown tool: ${toolName}` }], isError: true }\n }\n try {\n const result = await tool.handler(args)\n const text = typeof result === 'string' ? result : JSON.stringify(result)\n return { content: [{ type: 'text', text }] }\n } catch (err) {\n return {\n content: [\n { type: 'text', text: err instanceof Error ? err.message : 'Tool execution failed' },\n ],\n isError: true,\n }\n }\n}\n\n/** `resources/read` (M30) — extracted to keep `handleMcpJsonRpc` within the complexity budget. */\nfunction handleResourcesRead(\n id: number | string | null,\n params: unknown,\n appResources: readonly AppResource[],\n): Response {\n const uri = (params as { uri?: unknown } | undefined)?.uri\n if (typeof uri !== 'string') {\n return jsonResponse({\n jsonrpc: '2.0',\n id,\n error: { code: -32602, message: 'resources/read requires a string `uri` param.' },\n })\n }\n const contents = readAppResource(appResources, uri)\n if (contents === null) {\n return jsonResponse({\n jsonrpc: '2.0',\n id,\n error: { code: -32602, message: `Resource not found: ${uri}` },\n })\n }\n return jsonResponse({ jsonrpc: '2.0', id, result: contents })\n}\n\n/**\n * Handle one MCP JSON-RPC request for an agent module. Always returns a 200 JSON-RPC envelope.\n *\n * M30 — `appResources` (optional) are the agent's declared `ui://` App resources; when present the\n * server advertises `capabilities.resources` and answers `resources/list` + `resources/read`.\n */\nexport async function handleMcpJsonRpc(\n mod: unknown,\n name: string,\n body: unknown,\n appResources: readonly AppResource[] = [],\n): Promise<Response> {\n if (!isJsonRpcRequest(body)) {\n return jsonResponse({\n jsonrpc: '2.0',\n id: null,\n error: { code: -32600, message: 'Invalid Request' },\n })\n }\n const { id, method, params } = body\n try {\n const compiled = compileAgentModule(mod, `mcp server for \"${name}\"`)\n if (method === 'initialize') {\n const capabilities: Record<string, unknown> = { tools: {} }\n if (appResources.length > 0) capabilities.resources = {}\n return jsonResponse({\n jsonrpc: '2.0',\n id,\n result: {\n protocolVersion: MCP_PROTOCOL_VERSION,\n capabilities,\n serverInfo: { name, version: '1.0' },\n },\n })\n }\n if (method === 'tools/list') {\n return jsonResponse({\n jsonrpc: '2.0',\n id,\n result: { tools: toolDescriptors(compiled.tools) },\n })\n }\n if (method === 'tools/call') {\n const p = params as { name?: unknown; arguments?: unknown } | undefined\n const result = await callTool(compiled.tools, p?.name, p?.arguments ?? {})\n return jsonResponse({ jsonrpc: '2.0', id, result })\n }\n if (method === 'resources/list') {\n return jsonResponse({\n jsonrpc: '2.0',\n id,\n result: { resources: buildResourceDescriptors(appResources) },\n })\n }\n if (method === 'resources/read') {\n return handleResourcesRead(id, params, appResources)\n }\n return jsonResponse({\n jsonrpc: '2.0',\n id,\n error: { code: -32601, message: `Method not found: ${method}` },\n })\n } catch (err) {\n return jsonResponse({\n jsonrpc: '2.0',\n id,\n error: { code: -32603, message: err instanceof Error ? err.message : 'Internal error' },\n })\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli/index.js
CHANGED
|
@@ -5,12 +5,12 @@ import "tsx/esm";
|
|
|
5
5
|
import cac from "cac";
|
|
6
6
|
var cli = cac("theokit");
|
|
7
7
|
cli.command("dev", "Start development server").option("--port <port>", "Port number").action(async (options) => {
|
|
8
|
-
const { devCommand } = await import("../dev-
|
|
8
|
+
const { devCommand } = await import("../dev-7AW7FBNH.js");
|
|
9
9
|
await devCommand({ port: options.port ? Number(options.port) : void 0 });
|
|
10
10
|
});
|
|
11
11
|
cli.command("build", "Build for production").option("--target <target>", "Deploy target (node, vercel, cloudflare)").action(async (options) => {
|
|
12
12
|
try {
|
|
13
|
-
const { buildCommand } = await import("../build-
|
|
13
|
+
const { buildCommand } = await import("../build-2JDQBBWN.js");
|
|
14
14
|
await buildCommand({ target: options.target });
|
|
15
15
|
} catch (err) {
|
|
16
16
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -22,7 +22,7 @@ cli.command("build", "Build for production").option("--target <target>", "Deploy
|
|
|
22
22
|
});
|
|
23
23
|
cli.command("start", "Start production server").option("--port <port>", "Port number").action(async (options) => {
|
|
24
24
|
try {
|
|
25
|
-
const { startCommand } = await import("../start-
|
|
25
|
+
const { startCommand } = await import("../start-4VHDT4TN.js");
|
|
26
26
|
await startCommand({ port: options.port ? Number(options.port) : void 0 });
|
|
27
27
|
} catch (err) {
|
|
28
28
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -37,7 +37,7 @@ cli.command(
|
|
|
37
37
|
"Generate a route, action, page, ws, controller, or resource (resource accepts field:type args)"
|
|
38
38
|
).action(async (type, name, fields) => {
|
|
39
39
|
try {
|
|
40
|
-
const { generateCommand } = await import("../generate-
|
|
40
|
+
const { generateCommand } = await import("../generate-373DALPY.js");
|
|
41
41
|
await generateCommand(type, name, fields.length > 0 ? fields : void 0);
|
|
42
42
|
} catch (err) {
|
|
43
43
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -52,7 +52,7 @@ cli.command(
|
|
|
52
52
|
"Run an agent in the terminal (stream + tool calls + approval)"
|
|
53
53
|
).action(async (name, message) => {
|
|
54
54
|
try {
|
|
55
|
-
const { agentCommand } = await import("../agent-
|
|
55
|
+
const { agentCommand } = await import("../agent-GXPTQTCU.js");
|
|
56
56
|
const { sawError } = await agentCommand(name, message);
|
|
57
57
|
if (sawError) process.exit(1);
|
|
58
58
|
} catch (err) {
|
|
@@ -65,7 +65,7 @@ cli.command(
|
|
|
65
65
|
});
|
|
66
66
|
cli.command("mcp <agent>", "Serve an agent as an MCP server over stdio (for desktop MCP clients)").action(async (agent) => {
|
|
67
67
|
try {
|
|
68
|
-
const { mcpCommand } = await import("../mcp-
|
|
68
|
+
const { mcpCommand } = await import("../mcp-MOKIIMJ6.js");
|
|
69
69
|
await mcpCommand(agent);
|
|
70
70
|
} catch (err) {
|
|
71
71
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -10,11 +10,6 @@ interface WebSocketHandler {
|
|
|
10
10
|
onClose?: (ws: WebSocketLike, code: number, reason: Buffer) => void;
|
|
11
11
|
onError?: (ws: WebSocketLike, error: Error) => void;
|
|
12
12
|
}
|
|
13
|
-
/**
|
|
14
|
-
* Define a WebSocket endpoint handler.
|
|
15
|
-
* Identity function — provides type inference for WebSocket handlers.
|
|
16
|
-
*/
|
|
17
|
-
declare function defineWebSocket(handler: WebSocketHandler): WebSocketHandler;
|
|
18
13
|
/**
|
|
19
14
|
* T5a.2 Phase F slice 3/3 — Web-Standards WebSocket endpoint handler.
|
|
20
15
|
*
|
|
@@ -47,18 +42,5 @@ interface WebSocketHandlerWeb {
|
|
|
47
42
|
onClose?: (ws: WebSocketLike, code: number, reason: string) => void;
|
|
48
43
|
onError?: (ws: WebSocketLike, error: Error) => void;
|
|
49
44
|
}
|
|
50
|
-
/**
|
|
51
|
-
* Web-Standards `defineWebSocket` sibling. Identity function — provides
|
|
52
|
-
* type inference for Web WebSocket handlers.
|
|
53
|
-
*
|
|
54
|
-
* **Type difference note vs Node path:**
|
|
55
|
-
* - `onMessage` data is `string | Uint8Array` instead of `string | Buffer`
|
|
56
|
-
* (Web standards have no `Buffer`; Node's Buffer is a Uint8Array
|
|
57
|
-
* subclass so the Node path's Buffer values flow through unchanged
|
|
58
|
-
* when adapters wrap them).
|
|
59
|
-
* - `onClose` reason is `string` instead of `Buffer` (Web `CloseEvent`
|
|
60
|
-
* exposes the reason as a UTF-8 string natively).
|
|
61
|
-
*/
|
|
62
|
-
declare function defineWebSocketWeb(handler: WebSocketHandlerWeb): WebSocketHandlerWeb;
|
|
63
45
|
|
|
64
|
-
export {
|
|
46
|
+
export type { WebSocketHandler as W, WebSocketHandlerWeb as a, WebSocketLike as b };
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
} from "./chunk-HNBWZKIQ.js";
|
|
9
9
|
import {
|
|
10
10
|
theoPluginAsync
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-D7D6V6FN.js";
|
|
12
|
+
import "./chunk-4QXVTX3X.js";
|
|
13
|
+
import "./chunk-VS6LJM2V.js";
|
|
14
14
|
import "./chunk-M6NMS5LR.js";
|
|
15
15
|
import "./chunk-IEES3CHD.js";
|
|
16
16
|
import {
|
|
@@ -111,4 +111,4 @@ export {
|
|
|
111
111
|
devCommand,
|
|
112
112
|
startDevServer
|
|
113
113
|
};
|
|
114
|
-
//# sourceMappingURL=dev-
|
|
114
|
+
//# sourceMappingURL=dev-7AW7FBNH.js.map
|
|
@@ -80,65 +80,69 @@ function generateSchemaEntry(resourceName, fields) {
|
|
|
80
80
|
function generateRouteIndex(resourceName, fields) {
|
|
81
81
|
const bodyFields = fields.map((f) => ` ${f.name}: ${f.zodType},`).join("\n");
|
|
82
82
|
return [
|
|
83
|
-
`import {
|
|
83
|
+
`import { route } from 'theokit/server/define'`,
|
|
84
84
|
`import { z } from 'zod'`,
|
|
85
85
|
`import { db } from '../../db/index.js'`,
|
|
86
86
|
`import { ${resourceName} } from '../../db/schema.js'`,
|
|
87
87
|
``,
|
|
88
|
-
`export const GET =
|
|
89
|
-
` handler
|
|
90
|
-
`
|
|
88
|
+
`export const GET = route()`,
|
|
89
|
+
` .handler(() => db.select().from(${resourceName}).all())`,
|
|
90
|
+
` .build()`,
|
|
91
91
|
``,
|
|
92
|
-
`export const POST =
|
|
93
|
-
` body
|
|
92
|
+
`export const POST = route()`,
|
|
93
|
+
` .body(`,
|
|
94
|
+
` z.object({`,
|
|
94
95
|
bodyFields,
|
|
95
|
-
`
|
|
96
|
-
`
|
|
97
|
-
`
|
|
96
|
+
` }),`,
|
|
97
|
+
` )`,
|
|
98
|
+
` .status(201)`,
|
|
99
|
+
` .handler(({ body }) => {`,
|
|
98
100
|
` const result = db.insert(${resourceName}).values(body).returning().get()`,
|
|
99
101
|
` return result`,
|
|
100
|
-
` }
|
|
101
|
-
`
|
|
102
|
+
` })`,
|
|
103
|
+
` .build()`,
|
|
102
104
|
``
|
|
103
105
|
].join("\n");
|
|
104
106
|
}
|
|
105
107
|
function generateRouteId(resourceName, fields) {
|
|
106
108
|
const updateFields = fields.map((f) => ` ${f.name}: ${f.zodType}.optional(),`).join("\n");
|
|
107
109
|
return [
|
|
108
|
-
`import {
|
|
110
|
+
`import { route } from 'theokit/server/define'`,
|
|
109
111
|
`import { z } from 'zod'`,
|
|
110
112
|
`import { db } from '../../db/index.js'`,
|
|
111
113
|
`import { ${resourceName} } from '../../db/schema.js'`,
|
|
112
114
|
`import { eq } from 'drizzle-orm'`,
|
|
113
115
|
``,
|
|
114
|
-
`export const GET =
|
|
115
|
-
` params
|
|
116
|
-
` handler
|
|
116
|
+
`export const GET = route()`,
|
|
117
|
+
` .params(z.object({ id: z.coerce.number() }))`,
|
|
118
|
+
` .handler(({ params }) => {`,
|
|
117
119
|
` const item = db.select().from(${resourceName}).where(eq(${resourceName}.id, params.id)).get()`,
|
|
118
120
|
` if (!item) return new Response(JSON.stringify({ error: 'Not found' }), { status: 404 })`,
|
|
119
121
|
` return item`,
|
|
120
|
-
` }
|
|
121
|
-
`
|
|
122
|
+
` })`,
|
|
123
|
+
` .build()`,
|
|
122
124
|
``,
|
|
123
|
-
`export const PUT =
|
|
124
|
-
` params
|
|
125
|
-
` body
|
|
125
|
+
`export const PUT = route()`,
|
|
126
|
+
` .params(z.object({ id: z.coerce.number() }))`,
|
|
127
|
+
` .body(`,
|
|
128
|
+
` z.object({`,
|
|
126
129
|
updateFields,
|
|
127
|
-
`
|
|
128
|
-
`
|
|
130
|
+
` }),`,
|
|
131
|
+
` )`,
|
|
132
|
+
` .handler(({ params, body }) => {`,
|
|
129
133
|
` const result = db.update(${resourceName}).set(body).where(eq(${resourceName}.id, params.id)).returning().get()`,
|
|
130
134
|
` if (!result) return new Response(JSON.stringify({ error: 'Not found' }), { status: 404 })`,
|
|
131
135
|
` return result`,
|
|
132
|
-
` }
|
|
133
|
-
`
|
|
136
|
+
` })`,
|
|
137
|
+
` .build()`,
|
|
134
138
|
``,
|
|
135
|
-
`export const DELETE =
|
|
136
|
-
` params
|
|
137
|
-
` status
|
|
138
|
-
` handler
|
|
139
|
+
`export const DELETE = route()`,
|
|
140
|
+
` .params(z.object({ id: z.coerce.number() }))`,
|
|
141
|
+
` .status(204)`,
|
|
142
|
+
` .handler(({ params }) => {`,
|
|
139
143
|
` db.delete(${resourceName}).where(eq(${resourceName}.id, params.id)).run()`,
|
|
140
|
-
` }
|
|
141
|
-
`
|
|
144
|
+
` })`,
|
|
145
|
+
` .build()`,
|
|
142
146
|
``
|
|
143
147
|
].join("\n");
|
|
144
148
|
}
|
|
@@ -246,14 +250,14 @@ function toCamelCase(name) {
|
|
|
246
250
|
}
|
|
247
251
|
function generateRouteTemplate(name) {
|
|
248
252
|
return [
|
|
249
|
-
`import {
|
|
253
|
+
`import { route } from 'theokit/server'`,
|
|
250
254
|
`import { z } from 'zod'`,
|
|
251
255
|
``,
|
|
252
|
-
`export const GET =
|
|
253
|
-
` handler
|
|
256
|
+
`export const GET = route()`,
|
|
257
|
+
` .handler(({ ctx }) => {`,
|
|
254
258
|
` return { message: 'TODO: implement ${name} GET' }`,
|
|
255
|
-
` }
|
|
256
|
-
`
|
|
259
|
+
` })`,
|
|
260
|
+
` .build()`,
|
|
257
261
|
``
|
|
258
262
|
].join("\n");
|
|
259
263
|
}
|
|
@@ -277,56 +281,44 @@ function generateControllerTemplate(name) {
|
|
|
277
281
|
function generateActionTemplate(name) {
|
|
278
282
|
const camel = toCamelCase(name);
|
|
279
283
|
return [
|
|
280
|
-
`import {
|
|
284
|
+
`import { action } from 'theokit/server'`,
|
|
281
285
|
`import { z } from 'zod'`,
|
|
282
286
|
``,
|
|
283
|
-
`export const ${camel} =
|
|
284
|
-
` input
|
|
285
|
-
` handler
|
|
287
|
+
`export const ${camel} = action()`,
|
|
288
|
+
` .input(z.object({}))`,
|
|
289
|
+
` .handler(({ input, ctx }) => {`,
|
|
286
290
|
` return { message: 'TODO: implement ${name}' }`,
|
|
287
|
-
` }
|
|
288
|
-
`
|
|
291
|
+
` })`,
|
|
292
|
+
` .build()`,
|
|
289
293
|
``
|
|
290
294
|
].join("\n");
|
|
291
295
|
}
|
|
292
296
|
function generateAgentTemplate(name) {
|
|
293
|
-
const pascal = toPascalCase(name);
|
|
294
297
|
return [
|
|
295
|
-
`import '
|
|
296
|
-
`import {
|
|
297
|
-
`import { UseGuards } from '@theokit/http'`,
|
|
298
|
+
`import { agent } from '@theokit/agents'`,
|
|
299
|
+
`import { z } from 'zod'`,
|
|
298
300
|
``,
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
`
|
|
302
|
-
`
|
|
303
|
-
`
|
|
304
|
-
`})`,
|
|
305
|
-
`
|
|
306
|
-
` @MainLoop({ strategy: 'react', maxIterations: 5 })`,
|
|
307
|
-
` async run() {}`,
|
|
308
|
-
`}`,
|
|
301
|
+
`// Zero-config: this file is auto-served at POST /api/agents/${name}.`,
|
|
302
|
+
`// Add tools with tool('name')...build() and chain them via .tool(...).`,
|
|
303
|
+
`export default agent()`,
|
|
304
|
+
` .input(z.object({ message: z.string() }))`,
|
|
305
|
+
` .model('openai/gpt-4o-mini')`,
|
|
306
|
+
` .system('You are a helpful ${name} assistant.')`,
|
|
307
|
+
` .build()`,
|
|
309
308
|
``
|
|
310
309
|
].join("\n");
|
|
311
310
|
}
|
|
312
311
|
function generateToolboxTemplate(name) {
|
|
313
|
-
const
|
|
312
|
+
const camel = toCamelCase(name);
|
|
314
313
|
return [
|
|
315
|
-
`import '
|
|
314
|
+
`import { tool } from 'theokit/server'`,
|
|
316
315
|
`import { z } from 'zod'`,
|
|
317
|
-
`import { Toolbox, Tool } from '@theokit/agents'`,
|
|
318
316
|
``,
|
|
319
|
-
|
|
320
|
-
`
|
|
321
|
-
`
|
|
322
|
-
`
|
|
323
|
-
`
|
|
324
|
-
` input: z.object({ name: z.string() }),`,
|
|
325
|
-
` })`,
|
|
326
|
-
` async hello(input: { name: string }) {`,
|
|
327
|
-
` return \`Hello, \${input.name}!\``,
|
|
328
|
-
` }`,
|
|
329
|
-
`}`,
|
|
317
|
+
`export const ${camel}Hello = tool('${name}_hello')`,
|
|
318
|
+
` .describe('Say hello')`,
|
|
319
|
+
` .input(z.object({ name: z.string() }))`,
|
|
320
|
+
` .execute(({ name }) => \`Hello, \${name}!\`)`,
|
|
321
|
+
` .build()`,
|
|
330
322
|
``
|
|
331
323
|
].join("\n");
|
|
332
324
|
}
|
|
@@ -490,4 +482,4 @@ export {
|
|
|
490
482
|
generate,
|
|
491
483
|
generateCommand
|
|
492
484
|
};
|
|
493
|
-
//# sourceMappingURL=generate-
|
|
485
|
+
//# sourceMappingURL=generate-373DALPY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/generate.ts","../src/cli/commands/generate-resource.ts","../src/cli/commands/generate-types.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { resolve, dirname } from 'node:path'\n\nimport { generateResource } from './generate-resource.js'\nimport {\n VALID_TYPES,\n type GeneratorType,\n type GenerateOptions,\n type GenerateStatus,\n type GenerateResult,\n} from './generate-types.js'\n\nexport {\n VALID_TYPES,\n type GeneratorType,\n type GenerateOptions,\n type GenerateStatus,\n type GenerateResult,\n}\n\nfunction toKebabCase(name: string): boolean {\n return /^[a-z][a-z0-9/-]*$/.test(name)\n}\n\n/**\n * Reserved JS identifier names that conflict with object prototype machinery\n * or would shadow built-in module shapes if used as action/route names.\n * Mirrors action-scan's RESERVED_NAMES (T1.4).\n */\nconst RESERVED_BASENAMES = new Set([\n 'index',\n 'constructor',\n '__proto__',\n 'prototype',\n 'hasOwnProperty',\n])\n\n/**\n * Validate that a name segment doesn't hit the reserved-identifier list.\n * Checks the BASENAME (last `/` segment) — nested `admin/constructor` still\n * rejected because the file `constructor.ts` would be the conflict.\n */\nfunction hasReservedSegment(name: string): boolean {\n const basename = name.includes('/') ? (name.split('/').pop() ?? name) : name\n return RESERVED_BASENAMES.has(basename)\n}\n\n/**\n * EC-4: validate that resolving `targetSubpath` under `cwd` stays inside `cwd`.\n * Returns `true` when path is safe (stays inside), `false` when it escapes via\n * `..`, absolute path, null byte, or similar traversal vector.\n */\nfunction isPathInside(cwd: string, targetSubpath: string): boolean {\n if (targetSubpath.includes('\\x00')) return false\n if (targetSubpath.startsWith('/') || targetSubpath.startsWith('\\\\')) return false\n const resolved = resolve(cwd, targetSubpath)\n const cwdResolved = resolve(cwd)\n const sep = process.platform === 'win32' ? '\\\\' : '/'\n return resolved === cwdResolved || resolved.startsWith(cwdResolved + sep)\n}\n\nfunction toPascalCase(name: string): string {\n return name\n .split(/[-/]/)\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1))\n .join('')\n}\n\nfunction toCamelCase(name: string): string {\n const pascal = toPascalCase(name)\n return pascal.charAt(0).toLowerCase() + pascal.slice(1)\n}\n\nfunction generateRouteTemplate(name: string): string {\n return [\n `import { route } from 'theokit/server'`,\n `import { z } from 'zod'`,\n ``,\n `export const GET = route()`,\n ` .handler(({ ctx }) => {`,\n ` return { message: 'TODO: implement ${name} GET' }`,\n ` })`,\n ` .build()`,\n ``,\n ].join('\\n')\n}\n\nfunction generateControllerTemplate(name: string): string {\n const className = toPascalCase(name) + 'Controller'\n const baseName = name.split('/').pop() ?? name\n return [\n `// AUTO-GENERATED by \\`theokit generate controller ${name}\\``,\n `import { Controller, Get } from '@theokit/http'`,\n ``,\n `@Controller('${baseName}')`,\n `export class ${className} {`,\n ` @Get()`,\n ` findAll(): string {`,\n ` return 'This action returns all ${baseName}'`,\n ` }`,\n `}`,\n ``,\n ].join('\\n')\n}\n\nfunction generateActionTemplate(name: string): string {\n const camel = toCamelCase(name)\n return [\n `import { action } from 'theokit/server'`,\n `import { z } from 'zod'`,\n ``,\n `export const ${camel} = action()`,\n ` .input(z.object({}))`,\n ` .handler(({ input, ctx }) => {`,\n ` return { message: 'TODO: implement ${name}' }`,\n ` })`,\n ` .build()`,\n ``,\n ].join('\\n')\n}\n\n/**\n * Co-located test template for `theokit generate action <name>` (T5.2 +\n * plan Q4 cenário 1: roundtrip serialize). Skeleton uses vitest BDD shape\n * per testing.md.\n */\nfunction generateAgentTemplate(name: string): string {\n return [\n `import { agent } from '@theokit/agents'`,\n `import { z } from 'zod'`,\n ``,\n `// Zero-config: this file is auto-served at POST /api/agents/${name}.`,\n `// Add tools with tool('name')...build() and chain them via .tool(...).`,\n `export default agent()`,\n ` .input(z.object({ message: z.string() }))`,\n ` .model('openai/gpt-4o-mini')`,\n ` .system('You are a helpful ${name} assistant.')`,\n ` .build()`,\n ``,\n ].join('\\n')\n}\n\nfunction generateToolboxTemplate(name: string): string {\n const camel = toCamelCase(name)\n return [\n `import { tool } from 'theokit/server'`,\n `import { z } from 'zod'`,\n ``,\n `export const ${camel}Hello = tool('${name}_hello')`,\n ` .describe('Say hello')`,\n ` .input(z.object({ name: z.string() }))`,\n ` .execute(({ name }) => \\`Hello, \\${name}!\\`)`,\n ` .build()`,\n ``,\n ].join('\\n')\n}\n\nfunction resolveTemplate(\n cwd: string,\n type: GeneratorType,\n name: string,\n): { filePath: string; content: string } | null {\n switch (type) {\n case 'route':\n return {\n filePath: resolve(cwd, 'server/routes', `${name}.ts`),\n content: generateRouteTemplate(name),\n }\n case 'action':\n return {\n filePath: resolve(cwd, 'server/actions', `${name}.ts`),\n content: generateActionTemplate(name),\n }\n case 'page':\n return { filePath: resolve(cwd, `app/${name}/page.tsx`), content: generatePageTemplate(name) }\n case 'ws':\n return {\n filePath: resolve(cwd, 'server/ws', `${name}.ts`),\n content: generateWsTemplate(name),\n }\n case 'controller':\n return {\n filePath: resolve(cwd, 'server/controllers', `${name}.controller.ts`),\n content: generateControllerTemplate(name),\n }\n case 'agent':\n return {\n filePath: resolve(cwd, 'server/agents', `${name}.agent.ts`),\n content: generateAgentTemplate(name),\n }\n case 'toolbox':\n return {\n filePath: resolve(cwd, 'server/toolboxes', `${name}.tools.ts`),\n content: generateToolboxTemplate(name),\n }\n default:\n return null\n }\n}\n\nfunction generateActionTestTemplate(name: string): string {\n const camel = toCamelCase(name)\n return [\n `import { describe, it, expect } from 'vitest'`,\n ``,\n `import { ${camel} } from './${name.split('/').pop()}.js'`,\n ``,\n `describe('${name} action', () => {`,\n ` it('should accept a valid input shape', () => {`,\n ` expect(${camel}.input).toBeDefined()`,\n ` expect(typeof ${camel}.handler).toBe('function')`,\n ` })`,\n ``,\n ` it('should reject invalid input via zod schema', () => {`,\n ` const parsed = ${camel}.input.safeParse({ __invalid: true })`,\n ` // Empty object schema accepts {}; tighten this assertion when adding fields.`,\n ` expect(parsed.success).toBe(true)`,\n ` })`,\n `})`,\n ``,\n ].join('\\n')\n}\n\nfunction generatePageTemplate(name: string): string {\n const pascal = toPascalCase(name)\n return [`export default function ${pascal}Page() {`, ` return <h1>${pascal}</h1>`, `}`, ``].join(\n '\\n',\n )\n}\n\nfunction generateWsTemplate(_name: string): string {\n return [\n `import { defineWebSocket } from 'theokit/server'`,\n ``,\n `export default defineWebSocket({`,\n ` onMessage(ws, data) {`,\n ` ws.send(\\`echo: \\${data}\\`)`,\n ` },`,\n `})`,\n ``,\n ].join('\\n')\n}\n\n/**\n * Programmatic generate. Returns a structured result instead of throwing —\n * Studio (`theokit_generate` tool) consumes this directly. The CLI wrapper\n * below maps the structured result to console output + exit code semantics.\n */\n// eslint-disable-next-line @typescript-eslint/require-await\nexport async function generate(opts: GenerateOptions): Promise<GenerateResult> {\n const { cwd, type, name } = opts\n\n if (!existsSync(resolve(cwd, 'theo.config.ts')) && !existsSync(resolve(cwd, 'theo.config.js'))) {\n return {\n status: 'not_a_project',\n message: 'Not a Theo project. cwd has no theo.config.ts or theo.config.js',\n }\n }\n\n if (!VALID_TYPES.includes(type as GeneratorType)) {\n return {\n status: 'invalid_kind',\n message: `Invalid generator type \"${type}\". Available: ${VALID_TYPES.join(', ')}`,\n }\n }\n\n if (!name || !toKebabCase(name)) {\n return {\n status: 'invalid_name',\n message: `Invalid name \"${name}\". Use kebab-case: lowercase letters, numbers, hyphens.`,\n }\n }\n\n // EC-2-related: reject reserved JS identifier basenames (would shadow\n // built-in prototype machinery in virtual module emit or scan).\n if (hasReservedSegment(name)) {\n return {\n status: 'invalid_name',\n message: `Reserved name \"${name}\" — basename collides with built-in identifier (index/constructor/__proto__/prototype/hasOwnProperty).`,\n }\n }\n\n // Resource generates multiple files — handle separately\n if (type === 'resource') {\n return generateResource(cwd, name, opts.fields ?? [])\n }\n\n const resolved = resolveTemplate(cwd, type as GeneratorType, name)\n if (resolved === null) {\n return { status: 'invalid_kind', message: `Unknown type: ${type}` }\n }\n const { filePath, content } = resolved\n\n // EC-4: confirm the resolved filePath stays inside cwd. `toKebabCase`\n // already rejects most traversal vectors but a defense-in-depth check\n // against `..` slipping in via valid-looking segments is cheap.\n const relativeFromCwd = filePath.startsWith(resolve(cwd))\n ? filePath.slice(resolve(cwd).length + 1)\n : filePath\n if (!isPathInside(cwd, relativeFromCwd)) {\n return {\n status: 'invalid_name',\n message: `Path traversal denied: \"${name}\" would escape project root.`,\n }\n }\n\n if (existsSync(filePath)) {\n return { status: 'already_exists', filePath, kind: type as GeneratorType, name }\n }\n\n mkdirSync(dirname(filePath), { recursive: true })\n writeFileSync(filePath, content)\n\n // T5.2 + plan Q4: emit co-located test file alongside actions (only\n // for action type; routes/pages/ws keep prior single-file behavior).\n // Skip if existing test file present (preserve user-customized tests).\n if (type === 'action') {\n const testPath = filePath.replace(/\\.ts$/, '.test.ts')\n if (!existsSync(testPath)) {\n writeFileSync(testPath, generateActionTestTemplate(name))\n }\n }\n\n return { status: 'created', filePath, kind: type as GeneratorType, name }\n}\n\n/**\n * CLI entry point — preserves the original surface (throws + console.log).\n * Wraps the programmatic `generate` function.\n */\nexport async function generateCommand(\n type: string,\n name: string,\n fields?: string[],\n): Promise<void> {\n const result = await generate({ cwd: process.cwd(), type, name, fields })\n switch (result.status) {\n case 'not_a_project':\n throw new Error('Not a Theo project. Run this from a project root with theo.config.ts')\n case 'invalid_kind':\n throw new Error(result.message ?? 'Invalid kind')\n case 'invalid_name':\n throw new Error(\n `Invalid name \"${name}\". Use kebab-case: lowercase letters, numbers, hyphens. Example: my-route`,\n )\n case 'already_exists':\n console.log(`\\n ⚠ ${result.filePath} already exists. Skipping.\\n`)\n return\n case 'created':\n console.log(`\\n ✓ Created ${type}: ${result.filePath}\\n`)\n return\n }\n}\n","import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { resolve, dirname } from 'node:path'\n\nimport type { GenerateResult } from './generate-types.js'\n\n// --- Field parsing ---\n\nconst ALLOWED_FIELD_TYPES = new Set(['string', 'text', 'number', 'boolean'])\nconst RESERVED_FIELDS = new Set(['id', 'createdAt', 'created_at'])\n\nexport interface ResourceField {\n name: string\n type: 'string' | 'text' | 'number' | 'boolean'\n drizzleColumn: string\n zodType: string\n}\n\nexport function parseResourceFields(args: string[]): ResourceField[] {\n if (args.length === 0) {\n throw new Error(\n 'Resource requires at least one field. Example: theokit generate resource posts title:string',\n )\n }\n return args.map((arg) => {\n const parts = arg.split(':')\n if (parts.length !== 2 || !parts[0] || !parts[1]) {\n throw new Error(`Invalid field \"${arg}\". Use name:type format (e.g. title:string)`)\n }\n const [name, type] = parts\n if (!ALLOWED_FIELD_TYPES.has(type)) {\n throw new Error(\n `Unknown field type \"${type}\" in \"${arg}\". Valid types: ${[...ALLOWED_FIELD_TYPES].join(', ')}`,\n )\n }\n if (RESERVED_FIELDS.has(name)) {\n throw new Error(`Field \"${name}\" is reserved (auto-generated by the framework)`)\n }\n const fieldType = type as ResourceField['type']\n return {\n name,\n type: fieldType,\n drizzleColumn: mapDrizzleColumn(name, fieldType),\n zodType: mapZodType(fieldType),\n }\n })\n}\n\n// --- Column / type mapping ---\n\nfunction mapDrizzleColumn(name: string, type: ResourceField['type']): string {\n switch (type) {\n case 'string':\n case 'text':\n return `text('${name}').notNull()`\n case 'number':\n return `integer('${name}').notNull()`\n case 'boolean':\n return `integer('${name}', { mode: 'boolean' }).notNull().default(false)`\n }\n}\n\nfunction mapZodType(type: ResourceField['type']): string {\n switch (type) {\n case 'string':\n case 'text':\n return 'z.string()'\n case 'number':\n return 'z.number()'\n case 'boolean':\n return 'z.boolean()'\n }\n}\n\n// --- Template generators ---\n\nfunction generateSchemaEntry(resourceName: string, fields: ResourceField[]): string {\n const cols = [\n ` id: integer('id').primaryKey({ autoIncrement: true }),`,\n ...fields.map((f) => ` ${f.name}: ${f.drizzleColumn},`),\n ` createdAt: text('created_at')`,\n ` .notNull()`,\n ` .$defaultFn(() => new Date().toISOString().split('T')[0]),`,\n ]\n return [\n ``,\n `export const ${resourceName} = sqliteTable('${resourceName}', {`,\n ...cols,\n `})`,\n ``,\n ].join('\\n')\n}\n\nfunction generateRouteIndex(resourceName: string, fields: ResourceField[]): string {\n const bodyFields = fields.map((f) => ` ${f.name}: ${f.zodType},`).join('\\n')\n return [\n `import { route } from 'theokit/server/define'`,\n `import { z } from 'zod'`,\n `import { db } from '../../db/index.js'`,\n `import { ${resourceName} } from '../../db/schema.js'`,\n ``,\n `export const GET = route()`,\n ` .handler(() => db.select().from(${resourceName}).all())`,\n ` .build()`,\n ``,\n `export const POST = route()`,\n ` .body(`,\n ` z.object({`,\n bodyFields,\n ` }),`,\n ` )`,\n ` .status(201)`,\n ` .handler(({ body }) => {`,\n ` const result = db.insert(${resourceName}).values(body).returning().get()`,\n ` return result`,\n ` })`,\n ` .build()`,\n ``,\n ].join('\\n')\n}\n\nfunction generateRouteId(resourceName: string, fields: ResourceField[]): string {\n const updateFields = fields.map((f) => ` ${f.name}: ${f.zodType}.optional(),`).join('\\n')\n return [\n `import { route } from 'theokit/server/define'`,\n `import { z } from 'zod'`,\n `import { db } from '../../db/index.js'`,\n `import { ${resourceName} } from '../../db/schema.js'`,\n `import { eq } from 'drizzle-orm'`,\n ``,\n `export const GET = route()`,\n ` .params(z.object({ id: z.coerce.number() }))`,\n ` .handler(({ params }) => {`,\n ` const item = db.select().from(${resourceName}).where(eq(${resourceName}.id, params.id)).get()`,\n ` if (!item) return new Response(JSON.stringify({ error: 'Not found' }), { status: 404 })`,\n ` return item`,\n ` })`,\n ` .build()`,\n ``,\n `export const PUT = route()`,\n ` .params(z.object({ id: z.coerce.number() }))`,\n ` .body(`,\n ` z.object({`,\n updateFields,\n ` }),`,\n ` )`,\n ` .handler(({ params, body }) => {`,\n ` const result = db.update(${resourceName}).set(body).where(eq(${resourceName}.id, params.id)).returning().get()`,\n ` if (!result) return new Response(JSON.stringify({ error: 'Not found' }), { status: 404 })`,\n ` return result`,\n ` })`,\n ` .build()`,\n ``,\n `export const DELETE = route()`,\n ` .params(z.object({ id: z.coerce.number() }))`,\n ` .status(204)`,\n ` .handler(({ params }) => {`,\n ` db.delete(${resourceName}).where(eq(${resourceName}.id, params.id)).run()`,\n ` })`,\n ` .build()`,\n ``,\n ].join('\\n')\n}\n\nfunction generateTestTemplate(resourceName: string): string {\n return [\n `import { describe, it, expect } from 'vitest'`,\n ``,\n `describe('${resourceName} API', () => {`,\n ` it('should have a schema defined', async () => {`,\n ` const schema = await import('../server/db/schema.js')`,\n ` expect(schema.${resourceName}).toBeDefined()`,\n ` })`,\n ``,\n ` it('should have route handlers', async () => {`,\n ` const index = await import('../server/routes/${resourceName}/index.js')`,\n ` expect(index.GET).toBeDefined()`,\n ` expect(index.POST).toBeDefined()`,\n ` })`,\n `})`,\n ``,\n ].join('\\n')\n}\n\n// --- Orchestrator ---\n\nexport function generateResource(cwd: string, name: string, fieldArgs: string[]): GenerateResult {\n let fields: ResourceField[]\n try {\n fields = parseResourceFields(fieldArgs)\n } catch (err) {\n return { status: 'invalid_name', message: err instanceof Error ? err.message : String(err) }\n }\n\n const schemaPath = resolve(cwd, 'server/db/schema.ts')\n const routeIndexPath = resolve(cwd, `server/routes/${name}/index.ts`)\n const routeIdPath = resolve(cwd, `server/routes/${name}/[id].ts`)\n const testPath = resolve(cwd, `tests/${name}.test.ts`)\n\n if (!existsSync(schemaPath)) {\n return {\n status: 'not_a_project',\n message:\n 'server/db/schema.ts not found. Run this from a TheoKit project with database setup.',\n }\n }\n\n if (existsSync(routeIndexPath)) {\n return { status: 'already_exists', filePath: routeIndexPath, kind: 'resource', name }\n }\n\n const existingSchema = readFileSync(schemaPath, 'utf-8')\n if (existingSchema.includes(`export const ${name} =`)) {\n return {\n status: 'already_exists',\n filePath: schemaPath,\n kind: 'resource',\n name,\n message: `Table \"${name}\" already exists in schema.ts`,\n }\n }\n\n // 1. Append schema entry\n appendFileSync(schemaPath, generateSchemaEntry(name, fields))\n\n // 2. Create route files\n mkdirSync(dirname(routeIndexPath), { recursive: true })\n writeFileSync(routeIndexPath, generateRouteIndex(name, fields))\n writeFileSync(routeIdPath, generateRouteId(name, fields))\n\n // 3. Create test file\n mkdirSync(dirname(testPath), { recursive: true })\n if (!existsSync(testPath)) {\n writeFileSync(testPath, generateTestTemplate(name))\n }\n\n return { status: 'created', filePath: routeIndexPath, kind: 'resource', name }\n}\n","/**\n * Shared types for the `theokit generate` CLI command family.\n *\n * Extracted to break the circular dependency between generate.ts ↔ generate-resource.ts\n * (architecture-remediation plan T1.1, 2026-06-12).\n */\n\nexport const VALID_TYPES = [\n 'route',\n 'action',\n 'page',\n 'ws',\n 'controller',\n 'agent',\n 'toolbox',\n 'resource',\n] as const\nexport type GeneratorType = (typeof VALID_TYPES)[number]\n\nexport interface GenerateOptions {\n cwd: string\n type: string\n name: string\n fields?: string[]\n}\n\nexport type GenerateStatus =\n | 'created'\n | 'already_exists'\n | 'invalid_kind'\n | 'invalid_name'\n | 'not_a_project'\n\nexport interface GenerateResult {\n status: GenerateStatus\n filePath?: string\n kind?: GeneratorType\n name?: string\n message?: string\n}\n"],"mappings":"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","names":["existsSync","mkdirSync","writeFileSync","resolve","dirname","resolve","existsSync","mkdirSync","dirname","writeFileSync"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as TheoErrorCode, T as TheoErrorEnvelope } from './error-envelope-BsNzzAV5.js';
|
|
2
2
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
|
-
import { P as PluginContext } from './plugin-types-
|
|
4
|
-
import { P as PluginRunner } from './plugin-runner-
|
|
3
|
+
import { P as PluginContext } from './plugin-types-L49QYMb5.js';
|
|
4
|
+
import { P as PluginRunner } from './plugin-runner-CMprWWHZ.js';
|
|
5
5
|
import { J as JobBackend } from './job-backend-CgC8Xf33.js';
|
|
6
6
|
import { L as LoadModule, S as ServerRouteNode } from './match-CfbEFRG4.js';
|
|
7
7
|
import { c as CsrfMode, D as DisallowedConfig } from './csrf-BBrEZSBW.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -280,13 +280,6 @@ declare const theoConfigSchema: z.ZodObject<{
|
|
|
280
280
|
}, z.core.$strip>;
|
|
281
281
|
type TheoConfig = z.infer<typeof theoConfigSchema>;
|
|
282
282
|
|
|
283
|
-
/**
|
|
284
|
-
* Define Theo framework configuration.
|
|
285
|
-
* Identity function — provides type inference for theo.config.ts.
|
|
286
|
-
* Runtime validation happens in loadConfig(), not here.
|
|
287
|
-
*/
|
|
288
|
-
declare function defineConfig(config: Partial<TheoConfig>): Partial<TheoConfig>;
|
|
289
|
-
|
|
290
283
|
/** The fluent config builder. No field is required; `.set()` merges arbitrary config fields. */
|
|
291
284
|
interface ConfigBuilder {
|
|
292
285
|
/** Project identifier (DNS-1123) — used by `.theokit/services.json`. */
|
|
@@ -387,4 +380,4 @@ interface EntryClientOptions {
|
|
|
387
380
|
}
|
|
388
381
|
declare function generateEntryClient(ssr?: boolean, opts?: EntryClientOptions): string;
|
|
389
382
|
|
|
390
|
-
export { type ConfigBuilder, type ConfigIssue, type RouteNode, type TheoConfig, TheoConfigError, TheoProjectError, config, deepMerge,
|
|
383
|
+
export { type ConfigBuilder, type ConfigIssue, type RouteNode, type TheoConfig, TheoConfigError, TheoProjectError, config, deepMerge, generateEntryClient, generateRouteManifest, isRouteFile, loadConfig, scanRoutes, theoConfigSchema, validateProjectStructure };
|
package/dist/index.js
CHANGED
|
@@ -8,11 +8,11 @@ import {
|
|
|
8
8
|
scanRoutes,
|
|
9
9
|
theoConfigSchema,
|
|
10
10
|
theoPlugin
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-RQCZTDCX.js";
|
|
12
12
|
import "./chunk-D7ZH7DTG.js";
|
|
13
13
|
import "./chunk-RSVN727G.js";
|
|
14
14
|
import "./chunk-7BIM27LV.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-FO2KMFAE.js";
|
|
16
16
|
import "./chunk-5QW7IQQU.js";
|
|
17
17
|
import "./chunk-IAJ2JVEH.js";
|
|
18
18
|
import "./chunk-VMEWD57H.js";
|
|
@@ -122,7 +122,6 @@ export {
|
|
|
122
122
|
TheoProjectError,
|
|
123
123
|
config,
|
|
124
124
|
deepMerge,
|
|
125
|
-
defineConfig,
|
|
126
125
|
generateEntryClient,
|
|
127
126
|
generateRouteManifest,
|
|
128
127
|
isRouteFile,
|