@zauso-ai/capstan-dev 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ export { createDevServer } from "./server.js";
2
+ export { watchRoutes } from "./watcher.js";
3
+ export { loadRouteModule, loadApiHandlers, loadPageModule } from "./loader.js";
4
+ export { printStartupBanner } from "./printer.js";
5
+ export type { DevServerConfig, DevServerInstance } from "./types.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { createDevServer } from "./server.js";
2
+ export { watchRoutes } from "./watcher.js";
3
+ export { loadRouteModule, loadApiHandlers, loadPageModule } from "./loader.js";
4
+ export { printStartupBanner } from "./printer.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Dynamically import a module from disk, bypassing Node's module cache
3
+ * by appending a unique query parameter to the file URL.
4
+ *
5
+ * Returns the full module namespace object.
6
+ */
7
+ export declare function loadRouteModule(filePath: string): Promise<Record<string, unknown>>;
8
+ /**
9
+ * Import an API route file and extract the exported HTTP method handlers
10
+ * and optional `meta` export.
11
+ *
12
+ * API route files are expected to export one or more of:
13
+ * GET, POST, PUT, DELETE, PATCH
14
+ *
15
+ * Each export should be the result of `defineAPI()` from @zauso-ai/capstan-core,
16
+ * which produces an `APIDefinition` object with a `.handler` method.
17
+ *
18
+ * An optional `meta` export provides additional route metadata (e.g.
19
+ * description, tags) that is merged into the agent manifest.
20
+ */
21
+ export declare function loadApiHandlers(filePath: string): Promise<{
22
+ GET?: unknown;
23
+ POST?: unknown;
24
+ PUT?: unknown;
25
+ DELETE?: unknown;
26
+ PATCH?: unknown;
27
+ meta?: Record<string, unknown>;
28
+ }>;
29
+ /**
30
+ * Import a page route file and extract the default component and
31
+ * optional loader function.
32
+ *
33
+ * Page files are expected to export:
34
+ * - `default` -- a React component (the page itself)
35
+ * - `loader` -- (optional) a server-side data-loading function
36
+ */
37
+ export declare function loadPageModule(filePath: string): Promise<{
38
+ default?: unknown;
39
+ loader?: unknown;
40
+ }>;
41
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAMlC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/D,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC,CAuBD;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC,CAYD"}
package/dist/loader.js ADDED
@@ -0,0 +1,69 @@
1
+ import { pathToFileURL } from "node:url";
2
+ /**
3
+ * Monotonically increasing counter used to bust Node's ESM module cache.
4
+ * Each call to `loadRouteModule` gets a unique query string so that the
5
+ * runtime always re-evaluates the file -- critical for HMR-like behavior
6
+ * during development.
7
+ */
8
+ let cacheBustCounter = 0;
9
+ /**
10
+ * Dynamically import a module from disk, bypassing Node's module cache
11
+ * by appending a unique query parameter to the file URL.
12
+ *
13
+ * Returns the full module namespace object.
14
+ */
15
+ export async function loadRouteModule(filePath) {
16
+ const fileUrl = pathToFileURL(filePath).href;
17
+ const bustUrl = `${fileUrl}?t=${Date.now()}_${cacheBustCounter++}`;
18
+ const mod = (await import(bustUrl));
19
+ return mod;
20
+ }
21
+ /**
22
+ * Import an API route file and extract the exported HTTP method handlers
23
+ * and optional `meta` export.
24
+ *
25
+ * API route files are expected to export one or more of:
26
+ * GET, POST, PUT, DELETE, PATCH
27
+ *
28
+ * Each export should be the result of `defineAPI()` from @zauso-ai/capstan-core,
29
+ * which produces an `APIDefinition` object with a `.handler` method.
30
+ *
31
+ * An optional `meta` export provides additional route metadata (e.g.
32
+ * description, tags) that is merged into the agent manifest.
33
+ */
34
+ export async function loadApiHandlers(filePath) {
35
+ const mod = await loadRouteModule(filePath);
36
+ const result = {};
37
+ if (mod["GET"] !== undefined)
38
+ result.GET = mod["GET"];
39
+ if (mod["POST"] !== undefined)
40
+ result.POST = mod["POST"];
41
+ if (mod["PUT"] !== undefined)
42
+ result.PUT = mod["PUT"];
43
+ if (mod["DELETE"] !== undefined)
44
+ result.DELETE = mod["DELETE"];
45
+ if (mod["PATCH"] !== undefined)
46
+ result.PATCH = mod["PATCH"];
47
+ if (mod["meta"] !== undefined && typeof mod["meta"] === "object") {
48
+ result.meta = mod["meta"];
49
+ }
50
+ return result;
51
+ }
52
+ /**
53
+ * Import a page route file and extract the default component and
54
+ * optional loader function.
55
+ *
56
+ * Page files are expected to export:
57
+ * - `default` -- a React component (the page itself)
58
+ * - `loader` -- (optional) a server-side data-loading function
59
+ */
60
+ export async function loadPageModule(filePath) {
61
+ const mod = await loadRouteModule(filePath);
62
+ const result = {};
63
+ if (mod["default"] !== undefined)
64
+ result.default = mod["default"];
65
+ if (mod["loader"] !== undefined)
66
+ result.loader = mod["loader"];
67
+ return result;
68
+ }
69
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;;;GAKG;AACH,IAAI,gBAAgB,GAAG,CAAC,CAAC;AAEzB;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAgB;IAEhB,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;IAC7C,MAAM,OAAO,GAAG,GAAG,OAAO,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,gBAAgB,EAAE,EAAE,CAAC;IAEnE,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAA4B,CAAC;IAC/D,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB;IAQpD,MAAM,GAAG,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;IAE5C,MAAM,MAAM,GAOR,EAAE,CAAC;IAEP,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,SAAS;QAAE,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IACtD,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACzD,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,SAAS;QAAE,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IACtD,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,SAAS;QAAE,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/D,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,SAAS;QAAE,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;IAE5D,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,QAAQ,EAAE,CAAC;QACjE,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAA4B,CAAC;IACvD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB;IAInD,MAAM,GAAG,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;IAE5C,MAAM,MAAM,GAGR,EAAE,CAAC;IAEP,IAAI,GAAG,CAAC,SAAS,CAAC,KAAK,SAAS;QAAE,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;IAClE,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,SAAS;QAAE,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;IAE/D,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Print a nicely formatted startup banner to stdout showing key server
3
+ * information: URLs, route counts, and the application name.
4
+ */
5
+ export declare function printStartupBanner(config: {
6
+ appName: string;
7
+ port: number;
8
+ host: string;
9
+ routeCount: number;
10
+ apiRouteCount: number;
11
+ pageRouteCount: number;
12
+ }): void;
13
+ //# sourceMappingURL=printer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"printer.d.ts","sourceRoot":"","sources":["../src/printer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB,GAAG,IAAI,CAyCP"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Print a nicely formatted startup banner to stdout showing key server
3
+ * information: URLs, route counts, and the application name.
4
+ */
5
+ export function printStartupBanner(config) {
6
+ const { appName, port, host, routeCount, apiRouteCount, pageRouteCount } = config;
7
+ const displayHost = host === "0.0.0.0" ? "localhost" : host;
8
+ const base = `http://${displayHost}:${port}`;
9
+ const webUrl = base;
10
+ const agentUrl = `${base}/api`;
11
+ const manifestUrl = `${base}/.well-known/capstan.json`;
12
+ const openApiUrl = `${base}/openapi.json`;
13
+ // Build content lines, then measure the longest to size the box.
14
+ const lines = [
15
+ "Capstan Dev Server",
16
+ "",
17
+ `App: ${appName}`,
18
+ `Web UI: ${webUrl}`,
19
+ `Agent API: ${agentUrl}`,
20
+ `Manifest: ${manifestUrl}`,
21
+ `OpenAPI: ${openApiUrl}`,
22
+ "",
23
+ `Routes: ${routeCount} (${apiRouteCount} API, ${pageRouteCount} pages)`,
24
+ ];
25
+ const maxLen = Math.max(...lines.map((l) => l.length));
26
+ // Pad each line to the maximum width so the right border aligns.
27
+ const padded = lines.map((l) => l.padEnd(maxLen));
28
+ const horizontal = "\u2500".repeat(maxLen + 2); // ─
29
+ const top = ` \u250C${horizontal}\u2510`; // ┌─...─┐
30
+ const bottom = ` \u2514${horizontal}\u2518`; // └─...─┘
31
+ const body = padded
32
+ .map((l) => ` \u2502 ${l} \u2502`) // │ content │
33
+ .join("\n");
34
+ const banner = `\n${top}\n${body}\n${bottom}\n`;
35
+ // eslint-disable-next-line no-console
36
+ console.log(banner);
37
+ }
38
+ //# sourceMappingURL=printer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"printer.js","sourceRoot":"","sources":["../src/printer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAOlC;IACC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,GACtE,MAAM,CAAC;IAET,MAAM,WAAW,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5D,MAAM,IAAI,GAAG,UAAU,WAAW,IAAI,IAAI,EAAE,CAAC;IAE7C,MAAM,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,QAAQ,GAAG,GAAG,IAAI,MAAM,CAAC;IAC/B,MAAM,WAAW,GAAG,GAAG,IAAI,2BAA2B,CAAC;IACvD,MAAM,UAAU,GAAG,GAAG,IAAI,eAAe,CAAC;IAE1C,iEAAiE;IACjE,MAAM,KAAK,GAAG;QACZ,oBAAoB;QACpB,EAAE;QACF,cAAc,OAAO,EAAE;QACvB,cAAc,MAAM,EAAE;QACtB,cAAc,QAAQ,EAAE;QACxB,cAAc,WAAW,EAAE;QAC3B,cAAc,UAAU,EAAE;QAC1B,EAAE;QACF,cAAc,UAAU,KAAK,aAAa,SAAS,cAAc,SAAS;KAC3E,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,iEAAiE;IACjE,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAElD,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;IACpD,MAAM,GAAG,GAAG,WAAW,UAAU,QAAQ,CAAC,CAAC,UAAU;IACrD,MAAM,MAAM,GAAG,WAAW,UAAU,QAAQ,CAAC,CAAC,UAAU;IAExD,MAAM,IAAI,GAAG,MAAM;SAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,cAAc;SACjD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,MAAM,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IAEhD,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { DevServerConfig, DevServerInstance } from "./types.js";
2
+ /**
3
+ * Create and return a dev server instance that:
4
+ *
5
+ * 1. Scans `app/routes/` for route files
6
+ * 2. Creates a Hono server with all routes registered
7
+ * 3. Starts an HTTP server on the configured port
8
+ * 4. Watches for file changes and re-builds routes
9
+ * 5. Serves the agent manifest, OpenAPI spec, and health endpoint
10
+ * 6. Prints a startup banner with URLs and route counts
11
+ */
12
+ export declare function createDevServer(config: DevServerConfig): Promise<DevServerInstance>;
13
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA+yBrE;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,iBAAiB,CAAC,CA6M5B"}
package/dist/server.js ADDED
@@ -0,0 +1,788 @@
1
+ import { createServer } from "node:http";
2
+ import path from "node:path";
3
+ import { Hono } from "hono";
4
+ import { cors } from "hono/cors";
5
+ import { scanRoutes } from "@zauso-ai/capstan-router";
6
+ import { createContext, createApproval, getApproval, listApprovals, resolveApproval, } from "@zauso-ai/capstan-core";
7
+ import { loadApiHandlers, loadPageModule } from "./loader.js";
8
+ import { watchRoutes } from "./watcher.js";
9
+ import { printStartupBanner } from "./printer.js";
10
+ // ---------------------------------------------------------------------------
11
+ // Helpers
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Read the full request body from an IncomingMessage and return it
15
+ * as a parsed JSON value (or raw string if JSON parsing fails).
16
+ */
17
+ function readBody(req) {
18
+ return new Promise((resolve, reject) => {
19
+ const chunks = [];
20
+ req.on("data", (chunk) => chunks.push(chunk));
21
+ req.on("error", reject);
22
+ req.on("end", () => {
23
+ const raw = Buffer.concat(chunks).toString("utf-8");
24
+ if (raw.length === 0) {
25
+ resolve(undefined);
26
+ return;
27
+ }
28
+ try {
29
+ resolve(JSON.parse(raw));
30
+ }
31
+ catch {
32
+ resolve(raw);
33
+ }
34
+ });
35
+ });
36
+ }
37
+ /**
38
+ * Determine if an exported handler value looks like an APIDefinition
39
+ * produced by `defineAPI()` from @zauso-ai/capstan-core.
40
+ */
41
+ function isAPIDefinition(value) {
42
+ return (value !== null &&
43
+ typeof value === "object" &&
44
+ "handler" in value &&
45
+ typeof value.handler === "function");
46
+ }
47
+ /**
48
+ * Build a minimal `CapstanContext` from a raw `Request` for use outside
49
+ * of the Hono middleware pipeline (e.g. for page loaders).
50
+ */
51
+ function buildStandaloneContext(request, auth) {
52
+ return {
53
+ auth: auth ?? {
54
+ isAuthenticated: false,
55
+ type: "anonymous",
56
+ permissions: [],
57
+ },
58
+ request,
59
+ env: process.env,
60
+ // In dev mode we don't have a real Hono context for standalone calls.
61
+ // The context is cast to satisfy the type; page loaders should not
62
+ // depend on `honoCtx` directly.
63
+ honoCtx: {},
64
+ };
65
+ }
66
+ /**
67
+ * Given a scanned route manifest, build a fresh Hono application with all
68
+ * routes registered. Returns the Hono app plus metadata used by the
69
+ * framework endpoints (manifest, openapi, health).
70
+ */
71
+ async function buildApp(manifest, config) {
72
+ const app = new Hono();
73
+ // Global middleware ---------------------------------------------------------
74
+ app.use("*", cors());
75
+ // --- Auth middleware -------------------------------------------------------
76
+ // If the config includes auth settings, create the auth resolver from
77
+ // @zauso-ai/capstan-auth. Otherwise, fall back to anonymous and warn once.
78
+ let resolveAuth = null;
79
+ if (config.auth) {
80
+ try {
81
+ const authModuleName = "@zauso-ai/capstan-auth";
82
+ const authPkg = (await import(authModuleName));
83
+ resolveAuth = authPkg.createAuthMiddleware(config.auth, {});
84
+ }
85
+ catch {
86
+ // @zauso-ai/capstan-auth is not installed or failed to load — continue without it.
87
+ // eslint-disable-next-line no-console
88
+ console.warn("[capstan] @zauso-ai/capstan-auth not available. Auth middleware disabled.");
89
+ }
90
+ }
91
+ else {
92
+ // eslint-disable-next-line no-console
93
+ console.warn("[capstan] No auth config provided. All requests treated as anonymous.");
94
+ }
95
+ // Hono middleware that resolves auth and attaches it to the context so that
96
+ // `createContext(c)` picks it up via `c.get("capstanAuth")`.
97
+ app.use("*", async (c, next) => {
98
+ if (resolveAuth) {
99
+ const authCtx = await resolveAuth(c.req.raw);
100
+ c.set("capstanAuth", authCtx);
101
+ }
102
+ await next();
103
+ });
104
+ // Route metadata accumulated for the agent manifest / OpenAPI spec.
105
+ const routeRegistry = [];
106
+ /**
107
+ * Handler registry keyed by "METHOD /path" so approved requests can
108
+ * re-execute the original handler without going through the HTTP stack.
109
+ */
110
+ const handlerRegistry = new Map();
111
+ let apiRouteCount = 0;
112
+ let pageRouteCount = 0;
113
+ // Separate API and page routes from the manifest.
114
+ const apiRoutes = [];
115
+ const pageRoutes = [];
116
+ for (const route of manifest.routes) {
117
+ if (route.type === "api")
118
+ apiRoutes.push(route);
119
+ if (route.type === "page")
120
+ pageRoutes.push(route);
121
+ }
122
+ // --- Register API routes --------------------------------------------------
123
+ for (const route of apiRoutes) {
124
+ let handlers;
125
+ try {
126
+ handlers = await loadApiHandlers(route.filePath);
127
+ }
128
+ catch (err) {
129
+ // eslint-disable-next-line no-console
130
+ console.error(`[capstan] Failed to load API route ${route.filePath}:`, err instanceof Error ? err.message : err);
131
+ continue;
132
+ }
133
+ const methodEntries = [
134
+ ["GET", handlers.GET],
135
+ ["POST", handlers.POST],
136
+ ["PUT", handlers.PUT],
137
+ ["DELETE", handlers.DELETE],
138
+ ["PATCH", handlers.PATCH],
139
+ ];
140
+ for (const [method, handler] of methodEntries) {
141
+ if (handler === undefined)
142
+ continue;
143
+ apiRouteCount++;
144
+ // Record metadata for agent manifest / OpenAPI.
145
+ const meta = {
146
+ method,
147
+ path: route.urlPattern,
148
+ };
149
+ if (isAPIDefinition(handler)) {
150
+ if (handler.description !== undefined) {
151
+ meta.description = handler.description;
152
+ }
153
+ if (handler.capability !== undefined) {
154
+ meta.capability = handler.capability;
155
+ }
156
+ }
157
+ routeRegistry.push(meta);
158
+ // Store the handler for approval re-execution.
159
+ if (isAPIDefinition(handler)) {
160
+ const routeKey = `${method} ${route.urlPattern}`;
161
+ const apiHandler = handler;
162
+ handlerRegistry.set(routeKey, async (input, ctx) => {
163
+ return apiHandler.handler({ input, ctx });
164
+ });
165
+ }
166
+ // Mount the handler on the Hono app.
167
+ const honoMethod = method.toLowerCase();
168
+ app[honoMethod](route.urlPattern, async (c) => {
169
+ const ctx = createContext(c);
170
+ // Parse input from query string (GET) or request body (others).
171
+ let input;
172
+ try {
173
+ if (method === "GET") {
174
+ input = Object.fromEntries(new URL(c.req.url).searchParams);
175
+ }
176
+ else {
177
+ const contentType = c.req.header("content-type") ?? "";
178
+ if (contentType.includes("application/json")) {
179
+ input = await c.req.json();
180
+ }
181
+ else {
182
+ input = {};
183
+ }
184
+ }
185
+ }
186
+ catch {
187
+ input = {};
188
+ }
189
+ try {
190
+ // --- Policy enforcement -------------------------------------------
191
+ // If the handler declares a policy, enforce it before executing.
192
+ if (isAPIDefinition(handler) && handler.policy) {
193
+ const policyName = handler.policy;
194
+ // requireAuth is a built-in policy: deny anonymous requests.
195
+ if (policyName === "requireAuth") {
196
+ if (!ctx.auth.isAuthenticated) {
197
+ return c.json({ error: "Unauthorized", policy: policyName }, 401);
198
+ }
199
+ }
200
+ // For custom policies that are not "requireAuth", create a
201
+ // pending approval so a human/supervisor can review the action.
202
+ // The dev server does not maintain a full policy registry, so
203
+ // custom policies are treated as requiring approval in dev mode.
204
+ if (policyName !== "requireAuth") {
205
+ const reason = `Policy "${policyName}" requires approval`;
206
+ const approval = createApproval({
207
+ method,
208
+ path: route.urlPattern,
209
+ input,
210
+ policy: policyName,
211
+ reason,
212
+ });
213
+ return c.json({
214
+ status: "approval_required",
215
+ approvalId: approval.id,
216
+ reason,
217
+ pollUrl: `/capstan/approvals/${approval.id}`,
218
+ }, 202);
219
+ }
220
+ }
221
+ if (isAPIDefinition(handler)) {
222
+ const result = await handler.handler({ input, ctx });
223
+ return c.json(result);
224
+ }
225
+ // If the export is a plain function rather than an APIDefinition,
226
+ // invoke it directly with a similar signature.
227
+ if (typeof handler === "function") {
228
+ const result = await handler({ input, ctx });
229
+ return c.json(result);
230
+ }
231
+ return c.json({ error: "Invalid handler export" }, 500);
232
+ }
233
+ catch (err) {
234
+ // Zod validation errors
235
+ if (err !== null &&
236
+ typeof err === "object" &&
237
+ "issues" in err &&
238
+ Array.isArray(err.issues)) {
239
+ return c.json({
240
+ error: "Validation Error",
241
+ issues: err.issues,
242
+ }, 400);
243
+ }
244
+ const message = err instanceof Error ? err.message : "Internal Server Error";
245
+ // eslint-disable-next-line no-console
246
+ console.error(`[capstan] Error in ${method} ${route.urlPattern}:`, message);
247
+ return c.json({ error: message }, 500);
248
+ }
249
+ });
250
+ }
251
+ }
252
+ // --- Register page routes -------------------------------------------------
253
+ for (const route of pageRoutes) {
254
+ let pageModule;
255
+ try {
256
+ pageModule = await loadPageModule(route.filePath);
257
+ }
258
+ catch (err) {
259
+ // eslint-disable-next-line no-console
260
+ console.error(`[capstan] Failed to load page ${route.filePath}:`, err instanceof Error ? err.message : err);
261
+ continue;
262
+ }
263
+ if (!pageModule.default) {
264
+ // eslint-disable-next-line no-console
265
+ console.warn(`[capstan] Page ${route.filePath} has no default export, skipping.`);
266
+ continue;
267
+ }
268
+ pageRouteCount++;
269
+ app.get(route.urlPattern, async (c) => {
270
+ // In dev mode we do a simplified server render:
271
+ // - Run the loader (if any) to get data
272
+ // - Attempt to render using @zauso-ai/capstan-react's renderPage
273
+ // - Fall back to a minimal HTML shell with loader data if React
274
+ // rendering is unavailable or fails.
275
+ const request = c.req.raw;
276
+ const params = {};
277
+ for (const name of route.params) {
278
+ const value = c.req.param(name);
279
+ if (value !== undefined) {
280
+ params[name] = value;
281
+ }
282
+ }
283
+ // Resolve auth for page loaders when auth middleware is configured.
284
+ let pageAuth;
285
+ if (resolveAuth) {
286
+ try {
287
+ pageAuth = await resolveAuth(request);
288
+ }
289
+ catch {
290
+ // Auth resolution failed — fall through to anonymous.
291
+ }
292
+ }
293
+ const ctx = buildStandaloneContext(request, pageAuth);
294
+ // Run loader if present
295
+ let loaderData = null;
296
+ if (typeof pageModule.loader === "function") {
297
+ try {
298
+ loaderData = await pageModule.loader({
299
+ params,
300
+ request,
301
+ ctx: { auth: ctx.auth },
302
+ fetch: {
303
+ get: async () => null,
304
+ post: async () => null,
305
+ put: async () => null,
306
+ delete: async () => null,
307
+ },
308
+ });
309
+ }
310
+ catch (err) {
311
+ // eslint-disable-next-line no-console
312
+ console.error(`[capstan] Loader error in ${route.filePath}:`, err instanceof Error ? err.message : err);
313
+ }
314
+ }
315
+ // Attempt full SSR via @zauso-ai/capstan-react. If the package is available
316
+ // and the page module has a valid React component, render it.
317
+ // We use a dynamic import so the dev server works even when
318
+ // @zauso-ai/capstan-react is not installed.
319
+ try {
320
+ const reactModuleName = "@zauso-ai/capstan-react";
321
+ const reactPkg = (await import(reactModuleName));
322
+ const result = await reactPkg.renderPage({
323
+ pageModule: {
324
+ default: pageModule.default,
325
+ loader: pageModule.loader,
326
+ },
327
+ layouts: [],
328
+ params,
329
+ request,
330
+ loaderArgs: {
331
+ params,
332
+ request,
333
+ ctx: { auth: ctx.auth },
334
+ fetch: {
335
+ get: async () => null,
336
+ post: async () => null,
337
+ put: async () => null,
338
+ delete: async () => null,
339
+ },
340
+ },
341
+ });
342
+ return c.html(result.html, result.statusCode);
343
+ }
344
+ catch {
345
+ // @zauso-ai/capstan-react not available or render failed -- serve a
346
+ // minimal HTML shell that exposes loader data.
347
+ const html = `<!DOCTYPE html>
348
+ <html lang="en">
349
+ <head>
350
+ <meta charset="utf-8" />
351
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
352
+ <title>${config.appName ?? "Capstan App"}</title>
353
+ </head>
354
+ <body>
355
+ <div id="capstan-root">
356
+ <p>Page: ${route.urlPattern}</p>
357
+ </div>
358
+ <script>window.__CAPSTAN_DATA__ = ${JSON.stringify({ loaderData, params })}</script>
359
+ </body>
360
+ </html>`;
361
+ return c.html(html);
362
+ }
363
+ });
364
+ }
365
+ // --- Approval management endpoints ----------------------------------------
366
+ /** List all approvals, optionally filtered by ?status=pending|approved|denied */
367
+ app.get("/capstan/approvals", (c) => {
368
+ const statusParam = new URL(c.req.url).searchParams.get("status");
369
+ const items = listApprovals(statusParam ?? undefined);
370
+ return c.json({ approvals: items });
371
+ });
372
+ /** Get a single approval by ID */
373
+ app.get("/capstan/approvals/:id", (c) => {
374
+ const id = c.req.param("id");
375
+ const approval = getApproval(id);
376
+ if (!approval) {
377
+ return c.json({ error: "Approval not found" }, 404);
378
+ }
379
+ return c.json(approval);
380
+ });
381
+ /** Approve a pending approval — re-executes the original handler */
382
+ app.post("/capstan/approvals/:id/approve", async (c) => {
383
+ const id = c.req.param("id");
384
+ const existing = getApproval(id);
385
+ if (!existing) {
386
+ return c.json({ error: "Approval not found" }, 404);
387
+ }
388
+ if (existing.status !== "pending") {
389
+ return c.json({ error: "Approval already resolved", status: existing.status }, 409);
390
+ }
391
+ let resolvedBy;
392
+ try {
393
+ const body = await c.req.json();
394
+ if (typeof body.resolvedBy === "string") {
395
+ resolvedBy = body.resolvedBy;
396
+ }
397
+ }
398
+ catch {
399
+ // No body or invalid JSON — that's fine.
400
+ }
401
+ const approval = resolveApproval(id, "approved", resolvedBy);
402
+ if (!approval) {
403
+ return c.json({ error: "Approval not found" }, 404);
404
+ }
405
+ // Re-execute the original handler with the stored input.
406
+ const routeKey = `${approval.method} ${approval.path}`;
407
+ const handler = handlerRegistry.get(routeKey);
408
+ if (!handler) {
409
+ return c.json({ error: "Handler not found for route", route: routeKey }, 500);
410
+ }
411
+ try {
412
+ const ctx = createContext(c);
413
+ const result = await handler(approval.input, ctx);
414
+ approval.result = result;
415
+ return c.json({
416
+ status: "approved",
417
+ approvalId: approval.id,
418
+ result,
419
+ });
420
+ }
421
+ catch (err) {
422
+ const message = err instanceof Error ? err.message : "Handler execution failed";
423
+ return c.json({ error: message, approvalId: approval.id }, 500);
424
+ }
425
+ });
426
+ /** Deny a pending approval */
427
+ app.post("/capstan/approvals/:id/deny", async (c) => {
428
+ const id = c.req.param("id");
429
+ const existing = getApproval(id);
430
+ if (!existing) {
431
+ return c.json({ error: "Approval not found" }, 404);
432
+ }
433
+ if (existing.status !== "pending") {
434
+ return c.json({ error: "Approval already resolved", status: existing.status }, 409);
435
+ }
436
+ let resolvedBy;
437
+ let reason;
438
+ try {
439
+ const body = await c.req.json();
440
+ if (typeof body.resolvedBy === "string") {
441
+ resolvedBy = body.resolvedBy;
442
+ }
443
+ if (typeof body.reason === "string") {
444
+ reason = body.reason;
445
+ }
446
+ }
447
+ catch {
448
+ // No body or invalid JSON — that's fine.
449
+ }
450
+ const approval = resolveApproval(id, "denied", resolvedBy);
451
+ if (!approval) {
452
+ return c.json({ error: "Approval not found" }, 404);
453
+ }
454
+ return c.json({
455
+ status: "denied",
456
+ approvalId: approval.id,
457
+ ...(reason !== undefined ? { reason } : {}),
458
+ });
459
+ });
460
+ // --- Framework endpoints --------------------------------------------------
461
+ // Agent manifest
462
+ app.get("/.well-known/capstan.json", (c) => {
463
+ const manifest = {
464
+ capstan: "1.0",
465
+ name: config.appName ?? "capstan-app",
466
+ description: config.appDescription ?? "",
467
+ authentication: {
468
+ schemes: [
469
+ {
470
+ type: "bearer",
471
+ name: "API Key",
472
+ header: "Authorization",
473
+ description: "Bearer token for agent authentication",
474
+ },
475
+ ],
476
+ },
477
+ capabilities: routeRegistry.map((r) => ({
478
+ key: `${r.method} ${r.path}`,
479
+ title: r.description ?? `${r.method} ${r.path}`,
480
+ mode: (r.capability ?? "read"),
481
+ endpoint: {
482
+ method: r.method,
483
+ path: r.path,
484
+ },
485
+ })),
486
+ };
487
+ return c.json(manifest);
488
+ });
489
+ // OpenAPI spec
490
+ app.get("/openapi.json", (c) => {
491
+ const paths = {};
492
+ for (const r of routeRegistry) {
493
+ const pathKey = r.path.replace(/:(\w+)/g, "{$1}").replace(/\*/g, "{path}");
494
+ if (!paths[pathKey]) {
495
+ paths[pathKey] = {};
496
+ }
497
+ paths[pathKey][r.method.toLowerCase()] = {
498
+ summary: r.description ?? `${r.method} ${r.path}`,
499
+ operationId: `${r.method.toLowerCase()}_${r.path.replace(/[/:*]/g, "_").replace(/^_/, "")}`,
500
+ responses: {
501
+ "200": { description: "Successful response" },
502
+ },
503
+ ...(r.inputSchema ? { requestBody: { content: { "application/json": { schema: r.inputSchema } } } } : {}),
504
+ };
505
+ }
506
+ const spec = {
507
+ openapi: "3.1.0",
508
+ info: {
509
+ title: config.appName ?? "capstan-app",
510
+ description: config.appDescription ?? "",
511
+ version: "0.1.0",
512
+ },
513
+ paths,
514
+ };
515
+ return c.json(spec);
516
+ });
517
+ // Health check
518
+ app.get("/health", (c) => {
519
+ return c.json({
520
+ status: "ok",
521
+ uptime: process.uptime(),
522
+ timestamp: new Date().toISOString(),
523
+ });
524
+ });
525
+ // --- A2A endpoints ---------------------------------------------------------
526
+ // GET /.well-known/agent.json — A2A Agent Card discovery
527
+ // POST /.well-known/a2a — A2A JSON-RPC task handler
528
+ app.get("/.well-known/agent.json", async (c) => {
529
+ try {
530
+ const agentModuleName = "@zauso-ai/capstan-agent";
531
+ const agentPkg = (await import(agentModuleName));
532
+ const card = agentPkg.generateA2AAgentCard({
533
+ name: config.appName ?? "capstan-app",
534
+ ...(config.appDescription ? { description: config.appDescription } : {}),
535
+ baseUrl: `http://${config.host ?? "localhost"}:${config.port ?? 3000}`,
536
+ }, routeRegistry);
537
+ return c.json(card);
538
+ }
539
+ catch {
540
+ return c.json({ error: "@zauso-ai/capstan-agent not available — A2A disabled" }, 501);
541
+ }
542
+ });
543
+ app.post("/.well-known/a2a", async (c) => {
544
+ try {
545
+ const agentModuleName = "@zauso-ai/capstan-agent";
546
+ const agentPkg = (await import(agentModuleName));
547
+ const executeRoute = async (method, urlPath, input) => {
548
+ const url = `http://localhost:${config.port ?? 3000}${urlPath}`;
549
+ const init = {
550
+ method,
551
+ headers: { "Content-Type": "application/json" },
552
+ };
553
+ if (method !== "GET" && method !== "HEAD" && input !== undefined) {
554
+ init.body = JSON.stringify(input);
555
+ }
556
+ const request = new Request(url, init);
557
+ // Use the outer Hono app reference for internal dispatch.
558
+ const response = await app.fetch(request);
559
+ try {
560
+ return await response.json();
561
+ }
562
+ catch {
563
+ return { status: response.status, body: await response.text() };
564
+ }
565
+ };
566
+ const handler = agentPkg.createA2AHandler({
567
+ name: config.appName ?? "capstan-app",
568
+ ...(config.appDescription ? { description: config.appDescription } : {}),
569
+ baseUrl: `http://${config.host ?? "localhost"}:${config.port ?? 3000}`,
570
+ }, routeRegistry, executeRoute);
571
+ const body = await c.req.json();
572
+ const result = await handler.handleRequest(body);
573
+ return c.json(result);
574
+ }
575
+ catch {
576
+ return c.json({
577
+ jsonrpc: "2.0",
578
+ id: null,
579
+ error: {
580
+ code: -32603,
581
+ message: "@zauso-ai/capstan-agent not available — A2A disabled",
582
+ },
583
+ }, 501);
584
+ }
585
+ });
586
+ // --- MCP discovery endpoint -----------------------------------------------
587
+ // POST /.well-known/mcp returns a JSON description of available MCP tools
588
+ // so that agents can discover capabilities without connecting via stdio.
589
+ app.post("/.well-known/mcp", async (c) => {
590
+ try {
591
+ const agentModuleName = "@zauso-ai/capstan-agent";
592
+ const agentPkg = (await import(agentModuleName));
593
+ const tools = routeRegistry.map((r) => ({
594
+ name: agentPkg.routeToToolName(r.method, r.path),
595
+ description: r.description ?? `${r.method} ${r.path}`,
596
+ method: r.method,
597
+ path: r.path,
598
+ inputSchema: r.inputSchema ?? { type: "object", properties: {} },
599
+ }));
600
+ return c.json({
601
+ protocol: "mcp",
602
+ version: "1.0",
603
+ name: config.appName ?? "capstan-app",
604
+ tools,
605
+ });
606
+ }
607
+ catch {
608
+ // @zauso-ai/capstan-agent not available
609
+ return c.json({
610
+ protocol: "mcp",
611
+ version: "1.0",
612
+ name: config.appName ?? "capstan-app",
613
+ tools: [],
614
+ error: "@zauso-ai/capstan-agent not available",
615
+ });
616
+ }
617
+ });
618
+ return { app, apiRouteCount, pageRouteCount, routeRegistry };
619
+ }
620
+ // ---------------------------------------------------------------------------
621
+ // Public API
622
+ // ---------------------------------------------------------------------------
623
+ /**
624
+ * Create and return a dev server instance that:
625
+ *
626
+ * 1. Scans `app/routes/` for route files
627
+ * 2. Creates a Hono server with all routes registered
628
+ * 3. Starts an HTTP server on the configured port
629
+ * 4. Watches for file changes and re-builds routes
630
+ * 5. Serves the agent manifest, OpenAPI spec, and health endpoint
631
+ * 6. Prints a startup banner with URLs and route counts
632
+ */
633
+ export async function createDevServer(config) {
634
+ const port = config.port ?? 3000;
635
+ const host = config.host ?? "0.0.0.0";
636
+ const routesDir = path.join(config.rootDir, "app", "routes");
637
+ // --- Initial route scan ---------------------------------------------------
638
+ let manifest = await scanRoutes(routesDir);
639
+ let { app, apiRouteCount, pageRouteCount, routeRegistry } = await buildApp(manifest, config);
640
+ // The Node.js HTTP server holds a reference to the current Hono app.
641
+ // When routes change we rebuild the app and swap the reference -- in-flight
642
+ // requests finish against the old app while new requests hit the new one.
643
+ let currentApp = app;
644
+ let mcpInstance = null;
645
+ async function buildMcpServer() {
646
+ try {
647
+ const agentModuleName = "@zauso-ai/capstan-agent";
648
+ const agentPkg = (await import(agentModuleName));
649
+ const executeRoute = async (method, urlPath, input) => {
650
+ const url = `http://localhost:${port}${urlPath}`;
651
+ const init = {
652
+ method,
653
+ headers: { "Content-Type": "application/json" },
654
+ };
655
+ if (method !== "GET" && method !== "HEAD" && input !== undefined) {
656
+ init.body = JSON.stringify(input);
657
+ }
658
+ const request = new Request(url, init);
659
+ const response = await currentApp.fetch(request);
660
+ try {
661
+ return await response.json();
662
+ }
663
+ catch {
664
+ return { status: response.status, body: await response.text() };
665
+ }
666
+ };
667
+ mcpInstance = agentPkg.createMcpServer({
668
+ name: config.appName ?? "capstan-app",
669
+ ...(config.appDescription ? { description: config.appDescription } : {}),
670
+ }, routeRegistry, executeRoute);
671
+ }
672
+ catch {
673
+ // @zauso-ai/capstan-agent not available — MCP disabled.
674
+ mcpInstance = null;
675
+ }
676
+ }
677
+ await buildMcpServer();
678
+ // --- HTTP server ----------------------------------------------------------
679
+ const server = createServer(async (req, res) => {
680
+ try {
681
+ const url = new URL(req.url ?? "/", `http://${req.headers.host ?? `${host}:${port}`}`);
682
+ // Build a Web API Request from the Node.js IncomingMessage.
683
+ const headers = new Headers();
684
+ for (const [key, value] of Object.entries(req.headers)) {
685
+ if (value === undefined)
686
+ continue;
687
+ if (Array.isArray(value)) {
688
+ for (const v of value) {
689
+ headers.append(key, v);
690
+ }
691
+ }
692
+ else {
693
+ headers.set(key, value);
694
+ }
695
+ }
696
+ const hasBody = req.method !== "GET" && req.method !== "HEAD";
697
+ let body;
698
+ if (hasBody) {
699
+ const raw = await readBody(req);
700
+ body = raw !== undefined ? (typeof raw === "string" ? raw : JSON.stringify(raw)) : undefined;
701
+ }
702
+ const init = {
703
+ method: req.method ?? "GET",
704
+ headers,
705
+ };
706
+ if (body !== undefined) {
707
+ init.body = body;
708
+ }
709
+ const request = new Request(url.toString(), init);
710
+ const response = await currentApp.fetch(request);
711
+ // Write the Hono response back through the Node.js response.
712
+ res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
713
+ const responseBody = await response.text();
714
+ res.end(responseBody);
715
+ }
716
+ catch (err) {
717
+ // eslint-disable-next-line no-console
718
+ console.error("[capstan] Unhandled request error:", err);
719
+ if (!res.headersSent) {
720
+ res.writeHead(500, { "Content-Type": "application/json" });
721
+ }
722
+ res.end(JSON.stringify({ error: "Internal Server Error" }));
723
+ }
724
+ });
725
+ // --- File watcher ---------------------------------------------------------
726
+ async function rebuildRoutes() {
727
+ try {
728
+ // eslint-disable-next-line no-console
729
+ console.log("[capstan] Routes changed, rebuilding...");
730
+ manifest = await scanRoutes(routesDir);
731
+ const rebuilt = await buildApp(manifest, config);
732
+ currentApp = rebuilt.app;
733
+ apiRouteCount = rebuilt.apiRouteCount;
734
+ pageRouteCount = rebuilt.pageRouteCount;
735
+ routeRegistry = rebuilt.routeRegistry;
736
+ // Rebuild MCP server with updated routes.
737
+ await buildMcpServer();
738
+ const totalRoutes = apiRouteCount + pageRouteCount;
739
+ // eslint-disable-next-line no-console
740
+ console.log(`[capstan] Rebuilt: ${totalRoutes} routes (${apiRouteCount} API, ${pageRouteCount} pages)`);
741
+ }
742
+ catch (err) {
743
+ // eslint-disable-next-line no-console
744
+ console.error("[capstan] Failed to rebuild routes:", err instanceof Error ? err.message : err);
745
+ }
746
+ }
747
+ const watcher = watchRoutes(routesDir, () => {
748
+ void rebuildRoutes();
749
+ });
750
+ // --- DevServerInstance ----------------------------------------------------
751
+ const instance = {
752
+ port,
753
+ host,
754
+ start() {
755
+ return new Promise((resolve, reject) => {
756
+ server.on("error", (err) => {
757
+ reject(err);
758
+ });
759
+ server.listen(port, host, () => {
760
+ printStartupBanner({
761
+ appName: config.appName ?? "capstan-app",
762
+ port,
763
+ host,
764
+ routeCount: apiRouteCount + pageRouteCount,
765
+ apiRouteCount,
766
+ pageRouteCount,
767
+ });
768
+ resolve();
769
+ });
770
+ });
771
+ },
772
+ stop() {
773
+ return new Promise((resolve, reject) => {
774
+ watcher.close();
775
+ server.close((err) => {
776
+ if (err) {
777
+ reject(err);
778
+ }
779
+ else {
780
+ resolve();
781
+ }
782
+ });
783
+ });
784
+ },
785
+ };
786
+ return instance;
787
+ }
788
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export interface DevServerConfig {
2
+ /** Root directory of the Capstan app (contains app/ directory) */
3
+ rootDir: string;
4
+ /** Port to listen on */
5
+ port?: number;
6
+ /** Host to bind to */
7
+ host?: string;
8
+ /** App name for manifests */
9
+ appName?: string;
10
+ /** App description */
11
+ appDescription?: string;
12
+ /** Auth configuration — when set, session cookie / API key auth is enabled */
13
+ auth?: {
14
+ session: {
15
+ secret: string;
16
+ maxAge?: string;
17
+ };
18
+ apiKeys?: {
19
+ prefix?: string;
20
+ headerName?: string;
21
+ };
22
+ };
23
+ }
24
+ export interface DevServerInstance {
25
+ /** Start the dev server */
26
+ start(): Promise<void>;
27
+ /** Stop the dev server */
28
+ stop(): Promise<void>;
29
+ /** Current port */
30
+ port: number;
31
+ /** Current host */
32
+ host: string;
33
+ }
34
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sBAAsB;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,IAAI,CAAC,EAAE;QACL,OAAO,EAAE;YACP,MAAM,EAAE,MAAM,CAAC;YACf,MAAM,CAAC,EAAE,MAAM,CAAC;SACjB,CAAC;QACF,OAAO,CAAC,EAAE;YACR,MAAM,CAAC,EAAE,MAAM,CAAC;YAChB,UAAU,CAAC,EAAE,MAAM,CAAC;SACrB,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,2BAA2B;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,0BAA0B;IAC1B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;CACd"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Watch a routes directory for file changes and invoke a callback when
3
+ * route files (.ts, .tsx) are added, modified, or removed.
4
+ *
5
+ * Uses `node:fs.watch` in recursive mode with a 300ms debounce to
6
+ * coalesce rapid filesystem events (e.g. editor save + lint writes).
7
+ *
8
+ * Gracefully handles the case where the routes directory does not yet
9
+ * exist -- the caller should create it and restart the watcher.
10
+ */
11
+ export declare function watchRoutes(routesDir: string, onChange: () => void): {
12
+ close: () => void;
13
+ };
14
+ //# sourceMappingURL=watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,IAAI,GACnB;IAAE,KAAK,EAAE,MAAM,IAAI,CAAA;CAAE,CAiEvB"}
@@ -0,0 +1,70 @@
1
+ import { watch, existsSync } from "node:fs";
2
+ /**
3
+ * Watch a routes directory for file changes and invoke a callback when
4
+ * route files (.ts, .tsx) are added, modified, or removed.
5
+ *
6
+ * Uses `node:fs.watch` in recursive mode with a 300ms debounce to
7
+ * coalesce rapid filesystem events (e.g. editor save + lint writes).
8
+ *
9
+ * Gracefully handles the case where the routes directory does not yet
10
+ * exist -- the caller should create it and restart the watcher.
11
+ */
12
+ export function watchRoutes(routesDir, onChange) {
13
+ // If the directory doesn't exist, return a no-op watcher.
14
+ // The dev server will retry on next explicit scan.
15
+ if (!existsSync(routesDir)) {
16
+ return { close: () => { } };
17
+ }
18
+ let debounceTimer = null;
19
+ let closed = false;
20
+ const DEBOUNCE_MS = 300;
21
+ /** Route-file extensions we care about. */
22
+ const ROUTE_EXTENSIONS = [".ts", ".tsx"];
23
+ function isRouteFile(filename) {
24
+ if (!filename)
25
+ return false;
26
+ return ROUTE_EXTENSIONS.some((ext) => filename.endsWith(ext));
27
+ }
28
+ function scheduleCallback() {
29
+ if (closed)
30
+ return;
31
+ if (debounceTimer !== null) {
32
+ clearTimeout(debounceTimer);
33
+ }
34
+ debounceTimer = setTimeout(() => {
35
+ debounceTimer = null;
36
+ if (!closed) {
37
+ onChange();
38
+ }
39
+ }, DEBOUNCE_MS);
40
+ }
41
+ let watcher;
42
+ try {
43
+ watcher = watch(routesDir, { recursive: true }, (_eventType, filename) => {
44
+ if (isRouteFile(filename ?? null)) {
45
+ scheduleCallback();
46
+ }
47
+ });
48
+ }
49
+ catch {
50
+ // If watching fails (e.g. permission error), return a no-op handle.
51
+ return { close: () => { } };
52
+ }
53
+ // Handle watcher errors silently -- the dev server keeps running
54
+ // and the user can still trigger manual reloads.
55
+ watcher.on("error", () => {
56
+ // Intentionally swallowed. The server remains usable even if the
57
+ // watcher encounters a transient filesystem error.
58
+ });
59
+ return {
60
+ close: () => {
61
+ closed = true;
62
+ if (debounceTimer !== null) {
63
+ clearTimeout(debounceTimer);
64
+ debounceTimer = null;
65
+ }
66
+ watcher.close();
67
+ },
68
+ };
69
+ }
70
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG5C;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CACzB,SAAiB,EACjB,QAAoB;IAEpB,0DAA0D;IAC1D,mDAAmD;IACnD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IAC7B,CAAC;IAED,IAAI,aAAa,GAAyC,IAAI,CAAC;IAC/D,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,MAAM,WAAW,GAAG,GAAG,CAAC;IAExB,2CAA2C;IAC3C,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAEzC,SAAS,WAAW,CAAC,QAAuB;QAC1C,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5B,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,SAAS,gBAAgB;QACvB,IAAI,MAAM;YAAE,OAAO;QAEnB,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC3B,YAAY,CAAC,aAAa,CAAC,CAAC;QAC9B,CAAC;QAED,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,aAAa,GAAG,IAAI,CAAC;YACrB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,QAAQ,EAAE,CAAC;YACb,CAAC;QACH,CAAC,EAAE,WAAW,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,OAAkB,CAAC;IAEvB,IAAI,CAAC;QACH,OAAO,GAAG,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE;YACvE,IAAI,WAAW,CAAC,QAAQ,IAAI,IAAI,CAAC,EAAE,CAAC;gBAClC,gBAAgB,EAAE,CAAC;YACrB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;QACpE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IAC7B,CAAC;IAED,iEAAiE;IACjE,iDAAiD;IACjD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACvB,iEAAiE;QACjE,mDAAmD;IACrD,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,EAAE,GAAG,EAAE;YACV,MAAM,GAAG,IAAI,CAAC;YACd,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,YAAY,CAAC,aAAa,CAAC,CAAC;gBAC5B,aAAa,GAAG,IAAI,CAAC;YACvB,CAAC;YACD,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@zauso-ai/capstan-dev",
3
+ "version": "0.1.2",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc -p tsconfig.json",
18
+ "typecheck": "tsc -p tsconfig.json --noEmit"
19
+ },
20
+ "dependencies": {
21
+ "@zauso-ai/capstan-agent": "*",
22
+ "@zauso-ai/capstan-auth": "*",
23
+ "@zauso-ai/capstan-core": "*",
24
+ "@zauso-ai/capstan-router": "*",
25
+ "hono": "^4.0.0"
26
+ },
27
+ "description": "Dev server for Capstan — file watching, hot route reload, MCP/A2A endpoints",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/barry3406/capstan.git",
31
+ "directory": "packages/dev"
32
+ },
33
+ "license": "MIT",
34
+ "author": "barry3406",
35
+ "homepage": "https://github.com/barry3406/capstan",
36
+ "keywords": [
37
+ "capstan",
38
+ "ai-agent",
39
+ "full-stack",
40
+ "framework",
41
+ "mcp",
42
+ "a2a",
43
+ "typescript"
44
+ ],
45
+ "publishConfig": {
46
+ "access": "public"
47
+ }
48
+ }