@korajs/cli 1.0.0-beta.1 → 1.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ AGENTS_FRAMEWORKS: () => AGENTS_FRAMEWORKS,
33
34
  ClackPromptClient: () => ClackPromptClient,
34
35
  CliError: () => CliError,
35
36
  DEPLOY_PLATFORMS: () => DEPLOY_PLATFORMS,
@@ -48,13 +49,16 @@ __export(index_exports, {
48
49
  StubDeployAdapter: () => StubDeployAdapter,
49
50
  TEMPLATES: () => TEMPLATES,
50
51
  TEMPLATE_INFO: () => TEMPLATE_INFO,
52
+ agentsCommand: () => agentsCommand,
51
53
  applySyncProviderPreset: () => applySyncProviderPreset,
52
54
  buildClient: () => buildClient,
53
55
  bundleServer: () => bundleServer,
54
56
  createDeployAdapter: () => createDeployAdapter,
55
57
  createPromptClient: () => createPromptClient,
56
58
  deployCommand: () => deployCommand,
59
+ detectFrameworkFromManifest: () => detectFrameworkFromManifest,
57
60
  determineTemplateFromSelections: () => determineTemplateFromSelections,
61
+ generateAgentsMd: () => generateAgentsMd,
58
62
  generateDeployPackageJson: () => generateDeployPackageJson,
59
63
  generateDockerIgnore: () => generateDockerIgnore,
60
64
  generateDockerfile: () => generateDockerfile,
@@ -63,6 +67,7 @@ __export(index_exports, {
63
67
  generateTypes: () => generateTypes,
64
68
  getCreatePreferencesOrDefault: () => getCreatePreferencesOrDefault,
65
69
  getDefaultCreatePreferences: () => getDefaultCreatePreferences,
70
+ isAgentsFramework: () => isAgentsFramework,
66
71
  isAuthValue: () => isAuthValue,
67
72
  isDatabaseProviderValue: () => isDatabaseProviderValue,
68
73
  isDatabaseValue: () => isDatabaseValue,
@@ -229,6 +234,311 @@ var DevServerError = class extends import_core.KoraError {
229
234
  searchPath;
230
235
  };
231
236
 
237
+ // src/commands/agents/agents-command.ts
238
+ var import_promises2 = require("fs/promises");
239
+ var import_node_path2 = require("path");
240
+ var import_citty = require("citty");
241
+
242
+ // src/utils/fs-helpers.ts
243
+ var import_promises = require("fs/promises");
244
+ var import_node_path = require("path");
245
+ async function findProjectRoot(startDir) {
246
+ let current = (0, import_node_path.resolve)(startDir ?? process.cwd());
247
+ for (; ; ) {
248
+ const pkgPath = (0, import_node_path.join)(current, "package.json");
249
+ try {
250
+ const content = await (0, import_promises.readFile)(pkgPath, "utf-8");
251
+ const pkg = JSON.parse(content);
252
+ if (isKoraProject(pkg)) {
253
+ return current;
254
+ }
255
+ } catch {
256
+ }
257
+ const parent = (0, import_node_path.dirname)(current);
258
+ if (parent === current) break;
259
+ current = parent;
260
+ }
261
+ return null;
262
+ }
263
+ async function resolveProjectBinaryEntryPoint(projectRoot, packageName, binaryName) {
264
+ const pkgJsonPath = (0, import_node_path.join)(projectRoot, "node_modules", packageName, "package.json");
265
+ try {
266
+ const content = await (0, import_promises.readFile)(pkgJsonPath, "utf-8");
267
+ const pkg = JSON.parse(content);
268
+ let binPath;
269
+ if (typeof pkg.bin === "string") {
270
+ binPath = pkg.bin;
271
+ } else if (typeof pkg.bin === "object" && pkg.bin !== null) {
272
+ binPath = pkg.bin[binaryName];
273
+ }
274
+ if (!binPath) return null;
275
+ const fullPath = (0, import_node_path.join)(projectRoot, "node_modules", packageName, binPath);
276
+ await (0, import_promises.access)(fullPath);
277
+ return fullPath;
278
+ } catch {
279
+ return null;
280
+ }
281
+ }
282
+ function isKoraProject(pkg) {
283
+ if (typeof pkg !== "object" || pkg === null) return false;
284
+ const record = pkg;
285
+ return hasKoraDep(record.dependencies) || hasKoraDep(record.devDependencies);
286
+ }
287
+ function hasKoraDep(deps) {
288
+ if (typeof deps !== "object" || deps === null) return false;
289
+ return Object.keys(deps).some((key) => key === "kora" || key.startsWith("@korajs/"));
290
+ }
291
+
292
+ // src/utils/logger.ts
293
+ var RESET = "\x1B[0m";
294
+ var BOLD = "\x1B[1m";
295
+ var DIM = "\x1B[2m";
296
+ var GREEN = "\x1B[32m";
297
+ var YELLOW = "\x1B[33m";
298
+ var RED = "\x1B[31m";
299
+ var CYAN = "\x1B[36m";
300
+ function createLogger(options) {
301
+ const colorDisabled = options?.noColor === true || process.env.NO_COLOR !== void 0 || !process.stdout.isTTY;
302
+ function color(code, text) {
303
+ return colorDisabled ? text : `${code}${text}${RESET}`;
304
+ }
305
+ return {
306
+ info(message) {
307
+ console.log(color(CYAN, message));
308
+ },
309
+ success(message) {
310
+ console.log(color(GREEN, ` \u2713 ${message}`));
311
+ },
312
+ warn(message) {
313
+ console.warn(color(YELLOW, ` \u26A0 ${message}`));
314
+ },
315
+ error(message) {
316
+ console.error(color(RED, ` \u2717 ${message}`));
317
+ },
318
+ step(message) {
319
+ console.log(color(DIM, ` ${message}`));
320
+ },
321
+ blank() {
322
+ console.log();
323
+ },
324
+ banner() {
325
+ console.log();
326
+ console.log(
327
+ color(BOLD + CYAN, " Kora.js") + color(DIM, ", the offline-first application framework")
328
+ );
329
+ console.log();
330
+ }
331
+ };
332
+ }
333
+
334
+ // src/commands/agents/agents-md-content.ts
335
+ var AGENTS_FRAMEWORKS = ["react", "vue", "svelte"];
336
+ function isAgentsFramework(value) {
337
+ return AGENTS_FRAMEWORKS.includes(value);
338
+ }
339
+ function detectFrameworkFromManifest(manifest) {
340
+ if (typeof manifest !== "object" || manifest === null) return null;
341
+ const record = manifest;
342
+ const deps = collectDependencyNames(record.dependencies, record.devDependencies);
343
+ if (deps.has("@korajs/react")) return "react";
344
+ if (deps.has("@korajs/vue")) return "vue";
345
+ if (deps.has("@korajs/svelte")) return "svelte";
346
+ return null;
347
+ }
348
+ function collectDependencyNames(...groups) {
349
+ const names = /* @__PURE__ */ new Set();
350
+ for (const group of groups) {
351
+ if (typeof group !== "object" || group === null) continue;
352
+ for (const name of Object.keys(group)) {
353
+ names.add(name);
354
+ }
355
+ }
356
+ return names;
357
+ }
358
+ var FRAMEWORK_BINDINGS = {
359
+ react: `## React bindings
360
+
361
+ \`\`\`tsx
362
+ import { KoraProvider, useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/react'
363
+
364
+ // Wrap the tree once near your app entry: <KoraProvider app={app}><App /></KoraProvider>
365
+
366
+ const todos = useCollection('todos')
367
+ const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt'))
368
+ const addTodo = useMutation((data) => todos.insert(data))
369
+ addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
370
+ await addTodo.mutateAsync({ title: 'x' }) // resolves with the result; throws on failure
371
+ const status = useSyncStatus() // status.status, status.pendingOperations
372
+ \`\`\`
373
+
374
+ Rules: always render \`mutation.error\` somewhere. Keep \`<StrictMode>\` in place; the hooks are StrictMode-safe. \`useQuery\` returns data synchronously from the local store, so do not add loading spinners for local reads.`,
375
+ vue: `## Vue bindings
376
+
377
+ \`\`\`ts
378
+ import { useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/vue'
379
+
380
+ const todos = useCollection('todos')
381
+ const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt')) // readonly reactive ref
382
+ const addTodo = useMutation((data) => todos.insert(data))
383
+ addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
384
+ const status = useSyncStatus() // status.status, status.pendingOperations
385
+ \`\`\`
386
+
387
+ Rules: surface the mutation's error state in the UI. \`useQuery\` reads synchronously from the local store, so avoid loading spinners for local data. The Kora context comes from \`KoraProvider\`, wired in your app entry (for example \`src/main.ts\`).`,
388
+ svelte: `## Svelte bindings
389
+
390
+ Kora's Svelte bindings from \`@korajs/svelte\` expose \`useCollection\`, \`useQuery\`, \`useMutation\`, and \`useSyncStatus\`, wired through the provider set up in your app entry.
391
+
392
+ \`\`\`ts
393
+ import { useCollection, useMutation, useQuery, useSyncStatus } from '@korajs/svelte'
394
+
395
+ const todos = useCollection('todos')
396
+ const rows = useQuery(todos.where({ completed: false }).orderBy('createdAt')) // reactive store
397
+ const addTodo = useMutation((data) => todos.insert(data))
398
+ addTodo.mutate({ title: 'x' }) // fire-and-forget; errors land in addTodo.error
399
+ const status = useSyncStatus() // readable store; read $status.status in markup
400
+ \`\`\`
401
+
402
+ Rules: queries are reactive stores that read synchronously from the local database, so avoid loading spinners for local reads. Mutations expose an \`error\` state that must be surfaced in the UI.`
403
+ };
404
+ function generateAgentsMd(framework) {
405
+ return `# AGENTS.md
406
+
407
+ Guidance for AI coding agents working in this project. Humans: this is useful for you too.
408
+
409
+ ## What this project is
410
+
411
+ This project uses **Kora.js**, an offline-first application framework. All application data lives in a local SQLite database (WASM + OPFS in the browser, native SQLite on desktop and server) and optionally syncs across devices through a Kora sync server. Offline is the normal state, not an error state. Full docs live at https://korajs.dev, with a machine-readable index at https://korajs.dev/llms.txt and the complete docs in one file at https://korajs.dev/llms-full.txt. Any documentation page is available as raw markdown by appending \`.md\` to its URL.
412
+
413
+ ## Golden rules
414
+
415
+ 1. **The schema is the source of truth.** Collections are defined with \`defineSchema\` and the \`t.*\` field builders (by convention in \`src/schema.ts\`). To add or change data shapes, edit the schema first; types flow from it automatically. Never hand-write types for records.
416
+ 2. **Never fetch application data over HTTP.** Do not add REST or GraphQL calls for app data, and do not talk to the sync server directly. Read and write through Kora collections only; sync happens automatically in the background.
417
+ 3. **Await readiness before direct collection access.** Outside the UI bindings, \`await app.ready\` before calling \`app.<collection>\` methods. The framework bindings handle this for you inside components.
418
+ 4. **Offline must keep working.** Any feature you add must function with the network off. Never gate a read or write on connectivity. If you are checking \`navigator.onLine\` before a data operation, you are doing it wrong.
419
+ 5. **Surface mutation errors.** Fire-and-forget \`mutate\` calls fold errors into the mutation state. Always render the mutation's \`error\`, or handle the promise from the \`mutateAsync\` variant. Silent failure is the worst failure.
420
+ 6. **Do not add a state library for server or app data.** Kora's reactive queries are the store. Do not reach for react-query, SWR, Redux, Zustand, or similar for data that lives in a collection. Local UI state (form inputs, toggles) can use your framework's normal state tools.
421
+ 7. **Do not add loading spinners for local reads.** \`useQuery\` returns data synchronously from the local store, so there is no loading state to wait on for local data.
422
+
423
+ ## Data API cheat sheet
424
+
425
+ \`\`\`ts
426
+ await app.ready
427
+ const rec = await app.todos.insert({ title: 'x' }) // defaults and .auto() fields applied
428
+ await app.todos.update(rec.id, { completed: true }) // partial update, changed fields only
429
+ await app.todos.delete(rec.id)
430
+ const one = await app.todos.findById(rec.id)
431
+ const unsubscribe = app.todos
432
+ .where({ completed: false })
433
+ .orderBy('createdAt', 'desc')
434
+ .subscribe((rows) => {/* fires immediately, then on every change */})
435
+ \`\`\`
436
+
437
+ Schema example (\`src/schema.ts\`):
438
+
439
+ \`\`\`ts
440
+ import { defineSchema, t } from 'korajs'
441
+
442
+ export default defineSchema({
443
+ version: 1,
444
+ collections: {
445
+ todos: {
446
+ fields: {
447
+ title: t.string(),
448
+ completed: t.boolean().default(false),
449
+ tags: t.array(t.string()).default([]),
450
+ priority: t.enum(['low', 'medium', 'high']).default('medium'),
451
+ createdAt: t.timestamp().auto(), // set automatically; never pass it on insert
452
+ },
453
+ indexes: ['completed', 'createdAt'],
454
+ },
455
+ },
456
+ })
457
+ \`\`\`
458
+
459
+ If you change collection shapes, increment \`version\` and run \`npx kora migrate\`.
460
+
461
+ ## Conflict handling
462
+
463
+ Concurrent edits merge automatically: last-write-wins per field, add-wins for arrays, and character-level CRDT for \`t.richtext()\` fields. When a field needs domain-specific merging (counters, quantities), add a \`resolve\` function in the schema rather than writing sync logic by hand. Never write your own conflict or merge code.
464
+
465
+ ## Sync and auth
466
+
467
+ Enable sync by adding one line to \`createApp\`: \`createApp({ schema, sync: { url } })\`. When the app is offline, writes queue locally and sync when connectivity returns. If the project uses \`@korajs/auth\`, pass its client as \`createApp({ schema, sync: { url, authClient } })\`. Local writes work without sign-in; sync requires the server to accept the connection.
468
+
469
+ ${FRAMEWORK_BINDINGS[framework]}
470
+
471
+ ## Commands
472
+
473
+ - \`npx kora dev\` runs the dev environment (app server, local sync server when configured, schema watcher).
474
+ - \`npx kora doctor\` diagnoses a broken setup.
475
+ - \`npx kora migrate\` applies a schema change to the local store.
476
+ - In a running app, the DevTools overlay (Ctrl+Shift+K, Cmd+Shift+K on macOS) inspects operations, merges, and sync status.
477
+ `;
478
+ }
479
+
480
+ // src/commands/agents/agents-command.ts
481
+ async function fileExists(path) {
482
+ try {
483
+ await (0, import_promises2.access)(path);
484
+ return true;
485
+ } catch {
486
+ return false;
487
+ }
488
+ }
489
+ async function readManifest(root) {
490
+ try {
491
+ return JSON.parse(await (0, import_promises2.readFile)((0, import_node_path2.join)(root, "package.json"), "utf-8"));
492
+ } catch {
493
+ return null;
494
+ }
495
+ }
496
+ function resolveFramework(override, manifest) {
497
+ if (override !== void 0 && isAgentsFramework(override)) return override;
498
+ return detectFrameworkFromManifest(manifest) ?? "react";
499
+ }
500
+ var agentsCommand = (0, import_citty.defineCommand)({
501
+ meta: {
502
+ name: "agents-md",
503
+ description: "Write an AGENTS.md with Kora rules for AI coding agents into this project"
504
+ },
505
+ args: {
506
+ force: {
507
+ type: "boolean",
508
+ description: "Overwrite an existing AGENTS.md",
509
+ default: false
510
+ },
511
+ framework: {
512
+ type: "string",
513
+ description: "Override framework detection (react, vue, or svelte)"
514
+ }
515
+ },
516
+ async run({ args }) {
517
+ const logger = createLogger();
518
+ const projectRoot = await findProjectRoot() ?? process.cwd();
519
+ const manifest = await readManifest(projectRoot);
520
+ const override = typeof args.framework === "string" ? args.framework : void 0;
521
+ if (override !== void 0 && !isAgentsFramework(override)) {
522
+ logger.error(`Unknown framework "${override}". Use one of: react, vue, svelte.`);
523
+ process.exitCode = 1;
524
+ return;
525
+ }
526
+ const framework = resolveFramework(override, manifest);
527
+ const target = (0, import_node_path2.join)(projectRoot, "AGENTS.md");
528
+ const force = args.force === true;
529
+ if (await fileExists(target) && !force) {
530
+ logger.warn("AGENTS.md already exists. Re-run with --force to overwrite it.");
531
+ process.exitCode = 1;
532
+ return;
533
+ }
534
+ await (0, import_promises2.writeFile)(target, generateAgentsMd(framework), "utf-8");
535
+ logger.banner();
536
+ logger.success(`Wrote AGENTS.md (${framework} bindings) to ${target}`);
537
+ logger.step("Commit it so coding agents pick up Kora conventions automatically.");
538
+ logger.blank();
539
+ }
540
+ });
541
+
232
542
  // src/commands/generate/type-generator.ts
233
543
  function generateTypes(schema) {
234
544
  const lines = [
@@ -328,8 +638,8 @@ function toPascalCase(name) {
328
638
 
329
639
  // src/commands/deploy/deploy-command.ts
330
640
  var import_node_fs2 = require("fs");
331
- var import_node_path12 = require("path");
332
- var import_citty = require("citty");
641
+ var import_node_path13 = require("path");
642
+ var import_citty2 = require("citty");
333
643
 
334
644
  // src/prompts/prompt-client.ts
335
645
  var import_prompts = require("@clack/prompts");
@@ -499,98 +809,6 @@ var ClackPromptClient = class {
499
809
  }
500
810
  };
501
811
 
502
- // src/utils/fs-helpers.ts
503
- var import_promises = require("fs/promises");
504
- var import_node_path = require("path");
505
- async function findProjectRoot(startDir) {
506
- let current = (0, import_node_path.resolve)(startDir ?? process.cwd());
507
- for (; ; ) {
508
- const pkgPath = (0, import_node_path.join)(current, "package.json");
509
- try {
510
- const content = await (0, import_promises.readFile)(pkgPath, "utf-8");
511
- const pkg = JSON.parse(content);
512
- if (isKoraProject(pkg)) {
513
- return current;
514
- }
515
- } catch {
516
- }
517
- const parent = (0, import_node_path.dirname)(current);
518
- if (parent === current) break;
519
- current = parent;
520
- }
521
- return null;
522
- }
523
- async function resolveProjectBinaryEntryPoint(projectRoot, packageName, binaryName) {
524
- const pkgJsonPath = (0, import_node_path.join)(projectRoot, "node_modules", packageName, "package.json");
525
- try {
526
- const content = await (0, import_promises.readFile)(pkgJsonPath, "utf-8");
527
- const pkg = JSON.parse(content);
528
- let binPath;
529
- if (typeof pkg.bin === "string") {
530
- binPath = pkg.bin;
531
- } else if (typeof pkg.bin === "object" && pkg.bin !== null) {
532
- binPath = pkg.bin[binaryName];
533
- }
534
- if (!binPath) return null;
535
- const fullPath = (0, import_node_path.join)(projectRoot, "node_modules", packageName, binPath);
536
- await (0, import_promises.access)(fullPath);
537
- return fullPath;
538
- } catch {
539
- return null;
540
- }
541
- }
542
- function isKoraProject(pkg) {
543
- if (typeof pkg !== "object" || pkg === null) return false;
544
- const record = pkg;
545
- return hasKoraDep(record.dependencies) || hasKoraDep(record.devDependencies);
546
- }
547
- function hasKoraDep(deps) {
548
- if (typeof deps !== "object" || deps === null) return false;
549
- return Object.keys(deps).some((key) => key === "kora" || key.startsWith("@korajs/"));
550
- }
551
-
552
- // src/utils/logger.ts
553
- var RESET = "\x1B[0m";
554
- var BOLD = "\x1B[1m";
555
- var DIM = "\x1B[2m";
556
- var GREEN = "\x1B[32m";
557
- var YELLOW = "\x1B[33m";
558
- var RED = "\x1B[31m";
559
- var CYAN = "\x1B[36m";
560
- function createLogger(options) {
561
- const colorDisabled = options?.noColor === true || process.env.NO_COLOR !== void 0 || !process.stdout.isTTY;
562
- function color(code, text) {
563
- return colorDisabled ? text : `${code}${text}${RESET}`;
564
- }
565
- return {
566
- info(message) {
567
- console.log(color(CYAN, message));
568
- },
569
- success(message) {
570
- console.log(color(GREEN, ` \u2713 ${message}`));
571
- },
572
- warn(message) {
573
- console.warn(color(YELLOW, ` \u26A0 ${message}`));
574
- },
575
- error(message) {
576
- console.error(color(RED, ` \u2717 ${message}`));
577
- },
578
- step(message) {
579
- console.log(color(DIM, ` ${message}`));
580
- },
581
- blank() {
582
- console.log();
583
- },
584
- banner() {
585
- console.log();
586
- console.log(
587
- color(BOLD + CYAN, " Kora.js") + color(DIM, " \u2014 Offline-first application framework")
588
- );
589
- console.log();
590
- }
591
- };
592
- }
593
-
594
812
  // src/commands/deploy/adapters/adapter.ts
595
813
  var DEPLOY_PLATFORMS = [
596
814
  "fly",
@@ -607,13 +825,13 @@ function isDeployPlatform(value) {
607
825
 
608
826
  // src/commands/deploy/adapters/aws-ecs-adapter.ts
609
827
  var import_node_child_process2 = require("child_process");
610
- var import_node_path4 = require("path");
828
+ var import_node_path5 = require("path");
611
829
 
612
830
  // src/commands/deploy/builder/client-builder.ts
613
831
  var import_node_child_process = require("child_process");
614
832
  var import_node_fs = require("fs");
615
- var import_promises2 = require("fs/promises");
616
- var import_node_path2 = require("path");
833
+ var import_promises3 = require("fs/promises");
834
+ var import_node_path3 = require("path");
617
835
  async function buildClient(options) {
618
836
  const viteEntryPoint = await resolveProjectBinaryEntryPoint(options.projectRoot, "vite", "vite");
619
837
  if (!viteEntryPoint) {
@@ -634,15 +852,15 @@ async function buildClient(options) {
634
852
  return { outDir: options.outDir };
635
853
  }
636
854
  async function patchSqliteWasmAssets(projectRoot, outDir) {
637
- const assetsDir = (0, import_node_path2.join)(outDir, "assets");
855
+ const assetsDir = (0, import_node_path3.join)(outDir, "assets");
638
856
  if (!(0, import_node_fs.existsSync)(assetsDir)) return;
639
- const files = await (0, import_promises2.readdir)(assetsDir);
857
+ const files = await (0, import_promises3.readdir)(assetsDir);
640
858
  const hashedWasm = files.find((f) => /^sqlite3-.+\.wasm$/.test(f));
641
859
  if (hashedWasm && !files.includes("sqlite3.wasm")) {
642
- await (0, import_promises2.copyFile)((0, import_node_path2.join)(assetsDir, hashedWasm), (0, import_node_path2.join)(assetsDir, "sqlite3.wasm"));
860
+ await (0, import_promises3.copyFile)((0, import_node_path3.join)(assetsDir, hashedWasm), (0, import_node_path3.join)(assetsDir, "sqlite3.wasm"));
643
861
  }
644
862
  if (!files.includes("sqlite3-opfs-async-proxy.js")) {
645
- const proxyFile = (0, import_node_path2.resolve)(
863
+ const proxyFile = (0, import_node_path3.resolve)(
646
864
  projectRoot,
647
865
  "node_modules",
648
866
  "@sqlite.org",
@@ -652,7 +870,7 @@ async function patchSqliteWasmAssets(projectRoot, outDir) {
652
870
  "sqlite3-opfs-async-proxy.js"
653
871
  );
654
872
  if ((0, import_node_fs.existsSync)(proxyFile)) {
655
- await (0, import_promises2.copyFile)(proxyFile, (0, import_node_path2.join)(assetsDir, "sqlite3-opfs-async-proxy.js"));
873
+ await (0, import_promises3.copyFile)(proxyFile, (0, import_node_path3.join)(assetsDir, "sqlite3-opfs-async-proxy.js"));
656
874
  }
657
875
  }
658
876
  }
@@ -677,9 +895,9 @@ async function runProcess(command, args, cwd) {
677
895
  }
678
896
 
679
897
  // src/commands/deploy/builder/server-bundler.ts
680
- var import_promises3 = require("fs/promises");
681
898
  var import_promises4 = require("fs/promises");
682
- var import_node_path3 = require("path");
899
+ var import_promises5 = require("fs/promises");
900
+ var import_node_path4 = require("path");
683
901
  var import_esbuild = require("esbuild");
684
902
  var DEFAULT_ENTRY_CANDIDATES = [
685
903
  "server.ts",
@@ -695,8 +913,8 @@ async function bundleServer(options) {
695
913
  `Could not find a server entry file in ${options.projectRoot}. Looked for: ${candidates.join(", ")}`
696
914
  );
697
915
  }
698
- await (0, import_promises3.mkdir)(options.deployDirectory, { recursive: true });
699
- const outputFilePath = (0, import_node_path3.join)(options.deployDirectory, "server-bundled.js");
916
+ await (0, import_promises4.mkdir)(options.deployDirectory, { recursive: true });
917
+ const outputFilePath = (0, import_node_path4.join)(options.deployDirectory, "server-bundled.js");
700
918
  await (0, import_esbuild.build)({
701
919
  entryPoints: [entryFilePath],
702
920
  outfile: outputFilePath,
@@ -718,9 +936,9 @@ async function bundleServer(options) {
718
936
  }
719
937
  async function resolveServerEntry(projectRoot, candidates) {
720
938
  for (const candidate of candidates) {
721
- const fullPath = (0, import_node_path3.join)(projectRoot, candidate);
939
+ const fullPath = (0, import_node_path4.join)(projectRoot, candidate);
722
940
  try {
723
- await (0, import_promises4.access)(fullPath);
941
+ await (0, import_promises5.access)(fullPath);
724
942
  return fullPath;
725
943
  } catch {
726
944
  }
@@ -822,19 +1040,19 @@ var AwsEcsAdapter = class {
822
1040
  appName: config.appName,
823
1041
  region: config.region
824
1042
  };
825
- const deployDirectory = (0, import_node_path4.join)(config.projectRoot, ".kora", "deploy");
1043
+ const deployDirectory = (0, import_node_path5.join)(config.projectRoot, ".kora", "deploy");
826
1044
  await bundleServer({
827
1045
  projectRoot: config.projectRoot,
828
1046
  deployDirectory
829
1047
  });
830
1048
  const client = config.deployTarget === "sync-server" ? null : await buildClient({
831
1049
  projectRoot: config.projectRoot,
832
- outDir: (0, import_node_path4.join)(deployDirectory, "dist"),
1050
+ outDir: (0, import_node_path5.join)(deployDirectory, "dist"),
833
1051
  mode: "production"
834
1052
  });
835
1053
  return {
836
1054
  clientDirectory: client?.outDir ?? null,
837
- serverBundlePath: (0, import_node_path4.join)(deployDirectory, "server-bundled.js"),
1055
+ serverBundlePath: (0, import_node_path5.join)(deployDirectory, "server-bundled.js"),
838
1056
  deployDirectory
839
1057
  };
840
1058
  }
@@ -1100,7 +1318,7 @@ function inferLogLevel(line) {
1100
1318
 
1101
1319
  // src/commands/deploy/adapters/aws-lightsail-adapter.ts
1102
1320
  var import_node_child_process3 = require("child_process");
1103
- var import_node_path5 = require("path");
1321
+ var import_node_path6 = require("path");
1104
1322
  var AwsLightsailAdapter = class {
1105
1323
  name = "aws-lightsail";
1106
1324
  logger = createLogger();
@@ -1173,19 +1391,19 @@ var AwsLightsailAdapter = class {
1173
1391
  appName: config.appName,
1174
1392
  region: config.region
1175
1393
  };
1176
- const deployDirectory = (0, import_node_path5.join)(config.projectRoot, ".kora", "deploy");
1394
+ const deployDirectory = (0, import_node_path6.join)(config.projectRoot, ".kora", "deploy");
1177
1395
  await bundleServer({
1178
1396
  projectRoot: config.projectRoot,
1179
1397
  deployDirectory
1180
1398
  });
1181
1399
  const client = config.deployTarget === "sync-server" ? null : await buildClient({
1182
1400
  projectRoot: config.projectRoot,
1183
- outDir: (0, import_node_path5.join)(deployDirectory, "dist"),
1401
+ outDir: (0, import_node_path6.join)(deployDirectory, "dist"),
1184
1402
  mode: "production"
1185
1403
  });
1186
1404
  return {
1187
1405
  clientDirectory: client?.outDir ?? null,
1188
- serverBundlePath: (0, import_node_path5.join)(deployDirectory, "server-bundled.js"),
1406
+ serverBundlePath: (0, import_node_path6.join)(deployDirectory, "server-bundled.js"),
1189
1407
  deployDirectory
1190
1408
  };
1191
1409
  }
@@ -1485,11 +1703,11 @@ function inferLogLevel2(line) {
1485
1703
 
1486
1704
  // src/commands/deploy/adapters/fly-adapter.ts
1487
1705
  var import_node_child_process4 = require("child_process");
1488
- var import_node_path7 = require("path");
1706
+ var import_node_path8 = require("path");
1489
1707
 
1490
1708
  // src/commands/deploy/artifacts/fly-toml-generator.ts
1491
- var import_promises5 = require("fs/promises");
1492
- var import_node_path6 = require("path");
1709
+ var import_promises6 = require("fs/promises");
1710
+ var import_node_path7 = require("path");
1493
1711
  var GENERATED_HEADER = "# Generated by kora deploy \u2014 do not edit manually";
1494
1712
  function generateFlyToml(options) {
1495
1713
  const internalPort = options.internalPort ?? 3e3;
@@ -1519,9 +1737,9 @@ function generateFlyToml(options) {
1519
1737
  ].join("\n");
1520
1738
  }
1521
1739
  async function writeFlyTomlArtifact(deployDirectory, options) {
1522
- await (0, import_promises5.mkdir)(deployDirectory, { recursive: true });
1523
- const filePath = (0, import_node_path6.join)(deployDirectory, "fly.toml");
1524
- await (0, import_promises5.writeFile)(filePath, generateFlyToml(options), "utf-8");
1740
+ await (0, import_promises6.mkdir)(deployDirectory, { recursive: true });
1741
+ const filePath = (0, import_node_path7.join)(deployDirectory, "fly.toml");
1742
+ await (0, import_promises6.writeFile)(filePath, generateFlyToml(options), "utf-8");
1525
1743
  return filePath;
1526
1744
  }
1527
1745
 
@@ -1615,7 +1833,7 @@ var FlyAdapter = class {
1615
1833
  appName: config.appName,
1616
1834
  region: config.region
1617
1835
  };
1618
- const deployDirectory = (0, import_node_path7.join)(config.projectRoot, ".kora", "deploy");
1836
+ const deployDirectory = (0, import_node_path8.join)(config.projectRoot, ".kora", "deploy");
1619
1837
  await writeFlyTomlArtifact(deployDirectory, {
1620
1838
  appName: config.appName,
1621
1839
  region: config.region ?? "iad"
@@ -1626,12 +1844,12 @@ var FlyAdapter = class {
1626
1844
  });
1627
1845
  const client = config.deployTarget === "sync-server" ? null : await buildClient({
1628
1846
  projectRoot: config.projectRoot,
1629
- outDir: (0, import_node_path7.join)(deployDirectory, "dist"),
1847
+ outDir: (0, import_node_path8.join)(deployDirectory, "dist"),
1630
1848
  mode: "production"
1631
1849
  });
1632
1850
  return {
1633
1851
  clientDirectory: client?.outDir ?? null,
1634
- serverBundlePath: (0, import_node_path7.join)(deployDirectory, "server-bundled.js"),
1852
+ serverBundlePath: (0, import_node_path8.join)(deployDirectory, "server-bundled.js"),
1635
1853
  deployDirectory
1636
1854
  };
1637
1855
  }
@@ -1853,11 +2071,11 @@ ${stdout}`.toLowerCase();
1853
2071
 
1854
2072
  // src/commands/deploy/adapters/railway-adapter.ts
1855
2073
  var import_node_child_process5 = require("child_process");
1856
- var import_node_path9 = require("path");
2074
+ var import_node_path10 = require("path");
1857
2075
 
1858
2076
  // src/commands/deploy/artifacts/railway-json-generator.ts
1859
- var import_promises6 = require("fs/promises");
1860
- var import_node_path8 = require("path");
2077
+ var import_promises7 = require("fs/promises");
2078
+ var import_node_path9 = require("path");
1861
2079
  var GENERATED_HEADER2 = "Generated by kora deploy - do not edit manually.";
1862
2080
  function generateRailwayJson(options) {
1863
2081
  const file = {
@@ -1882,9 +2100,9 @@ function generateRailwayJson(options) {
1882
2100
  `;
1883
2101
  }
1884
2102
  async function writeRailwayJsonArtifact(deployDirectory, options) {
1885
- await (0, import_promises6.mkdir)(deployDirectory, { recursive: true });
1886
- const filePath = (0, import_node_path8.join)(deployDirectory, "railway.json");
1887
- await (0, import_promises6.writeFile)(filePath, generateRailwayJson(options), "utf-8");
2103
+ await (0, import_promises7.mkdir)(deployDirectory, { recursive: true });
2104
+ const filePath = (0, import_node_path9.join)(deployDirectory, "railway.json");
2105
+ await (0, import_promises7.writeFile)(filePath, generateRailwayJson(options), "utf-8");
1888
2106
  return filePath;
1889
2107
  }
1890
2108
 
@@ -1973,7 +2191,7 @@ var RailwayAdapter = class {
1973
2191
  appName: config.appName,
1974
2192
  region: config.region
1975
2193
  };
1976
- const deployDirectory = (0, import_node_path9.join)(config.projectRoot, ".kora", "deploy");
2194
+ const deployDirectory = (0, import_node_path10.join)(config.projectRoot, ".kora", "deploy");
1977
2195
  await writeRailwayJsonArtifact(deployDirectory, {
1978
2196
  appName: config.appName,
1979
2197
  environment: config.environment
@@ -1984,12 +2202,12 @@ var RailwayAdapter = class {
1984
2202
  });
1985
2203
  const client = config.deployTarget === "sync-server" ? null : await buildClient({
1986
2204
  projectRoot: config.projectRoot,
1987
- outDir: (0, import_node_path9.join)(deployDirectory, "dist"),
2205
+ outDir: (0, import_node_path10.join)(deployDirectory, "dist"),
1988
2206
  mode: "production"
1989
2207
  });
1990
2208
  return {
1991
2209
  clientDirectory: client?.outDir ?? null,
1992
- serverBundlePath: (0, import_node_path9.join)(deployDirectory, "server-bundled.js"),
2210
+ serverBundlePath: (0, import_node_path10.join)(deployDirectory, "server-bundled.js"),
1993
2211
  deployDirectory
1994
2212
  };
1995
2213
  }
@@ -2274,8 +2492,8 @@ function createDeployAdapter(platform) {
2274
2492
  }
2275
2493
 
2276
2494
  // src/commands/deploy/artifacts/dockerfile-generator.ts
2277
- var import_promises7 = require("fs/promises");
2278
- var import_node_path10 = require("path");
2495
+ var import_promises8 = require("fs/promises");
2496
+ var import_node_path11 = require("path");
2279
2497
  var GENERATED_HEADER3 = "# Generated by kora deploy \u2014 do not edit manually";
2280
2498
  function generateDockerfile(options = {}) {
2281
2499
  const nodeVersion = options.nodeVersion ?? "20-alpine";
@@ -2341,37 +2559,37 @@ function generateDockerIgnore() {
2341
2559
  ].join("\n");
2342
2560
  }
2343
2561
  async function writeDockerfileArtifact(deployDirectory, options = {}) {
2344
- await (0, import_promises7.mkdir)(deployDirectory, { recursive: true });
2345
- const dockerfilePath = (0, import_node_path10.join)(deployDirectory, "Dockerfile");
2346
- await (0, import_promises7.writeFile)(dockerfilePath, generateDockerfile(options), "utf-8");
2562
+ await (0, import_promises8.mkdir)(deployDirectory, { recursive: true });
2563
+ const dockerfilePath = (0, import_node_path11.join)(deployDirectory, "Dockerfile");
2564
+ await (0, import_promises8.writeFile)(dockerfilePath, generateDockerfile(options), "utf-8");
2347
2565
  if (options.nativeDependencies && Object.keys(options.nativeDependencies).length > 0) {
2348
- const pkgJsonPath = (0, import_node_path10.join)(deployDirectory, "package.json");
2349
- await (0, import_promises7.writeFile)(pkgJsonPath, generateDeployPackageJson(options.nativeDependencies), "utf-8");
2566
+ const pkgJsonPath = (0, import_node_path11.join)(deployDirectory, "package.json");
2567
+ await (0, import_promises8.writeFile)(pkgJsonPath, generateDeployPackageJson(options.nativeDependencies), "utf-8");
2350
2568
  }
2351
2569
  return dockerfilePath;
2352
2570
  }
2353
2571
  async function writeDockerIgnoreArtifact(deployDirectory) {
2354
- await (0, import_promises7.mkdir)(deployDirectory, { recursive: true });
2355
- const dockerIgnorePath = (0, import_node_path10.join)(deployDirectory, ".dockerignore");
2356
- await (0, import_promises7.writeFile)(dockerIgnorePath, generateDockerIgnore(), "utf-8");
2572
+ await (0, import_promises8.mkdir)(deployDirectory, { recursive: true });
2573
+ const dockerIgnorePath = (0, import_node_path11.join)(deployDirectory, ".dockerignore");
2574
+ await (0, import_promises8.writeFile)(dockerIgnorePath, generateDockerIgnore(), "utf-8");
2357
2575
  return dockerIgnorePath;
2358
2576
  }
2359
2577
 
2360
2578
  // src/commands/deploy/state/deploy-state.ts
2361
- var import_promises8 = require("fs/promises");
2362
- var import_node_path11 = require("path");
2363
- var KORA_DEPLOY_DIRECTORY = (0, import_node_path11.join)(".kora", "deploy");
2579
+ var import_promises9 = require("fs/promises");
2580
+ var import_node_path12 = require("path");
2581
+ var KORA_DEPLOY_DIRECTORY = (0, import_node_path12.join)(".kora", "deploy");
2364
2582
  var DEPLOY_STATE_FILENAME = "deploy.json";
2365
2583
  function resolveDeployDirectory(projectRoot) {
2366
- return (0, import_node_path11.join)(projectRoot, KORA_DEPLOY_DIRECTORY);
2584
+ return (0, import_node_path12.join)(projectRoot, KORA_DEPLOY_DIRECTORY);
2367
2585
  }
2368
2586
  function resolveDeployStatePath(projectRoot) {
2369
- return (0, import_node_path11.join)(resolveDeployDirectory(projectRoot), DEPLOY_STATE_FILENAME);
2587
+ return (0, import_node_path12.join)(resolveDeployDirectory(projectRoot), DEPLOY_STATE_FILENAME);
2370
2588
  }
2371
2589
  async function readDeployState(projectRoot) {
2372
2590
  const statePath = resolveDeployStatePath(projectRoot);
2373
2591
  try {
2374
- const source = await (0, import_promises8.readFile)(statePath, "utf-8");
2592
+ const source = await (0, import_promises9.readFile)(statePath, "utf-8");
2375
2593
  const parsed = JSON.parse(source);
2376
2594
  return parseDeployState(parsed);
2377
2595
  } catch (error) {
@@ -2418,13 +2636,13 @@ async function updateDeployState(projectRoot, patch, now = /* @__PURE__ */ new D
2418
2636
  return nextState;
2419
2637
  }
2420
2638
  async function resetDeployState(projectRoot) {
2421
- await (0, import_promises8.rm)(resolveDeployDirectory(projectRoot), { recursive: true, force: true });
2639
+ await (0, import_promises9.rm)(resolveDeployDirectory(projectRoot), { recursive: true, force: true });
2422
2640
  }
2423
2641
  async function persistDeployState(projectRoot, state) {
2424
2642
  const deployDir = resolveDeployDirectory(projectRoot);
2425
2643
  const statePath = resolveDeployStatePath(projectRoot);
2426
- await (0, import_promises8.mkdir)(deployDir, { recursive: true });
2427
- await (0, import_promises8.writeFile)(statePath, `${JSON.stringify(state, null, 2)}
2644
+ await (0, import_promises9.mkdir)(deployDir, { recursive: true });
2645
+ await (0, import_promises9.writeFile)(statePath, `${JSON.stringify(state, null, 2)}
2428
2646
  `, "utf-8");
2429
2647
  }
2430
2648
  function parseDeployState(value) {
@@ -2474,7 +2692,7 @@ function readOptionalString(value, field) {
2474
2692
  }
2475
2693
 
2476
2694
  // src/commands/deploy/deploy-command.ts
2477
- var deployCommand = (0, import_citty.defineCommand)({
2695
+ var deployCommand = (0, import_citty2.defineCommand)({
2478
2696
  meta: {
2479
2697
  name: "deploy",
2480
2698
  description: "Deploy a Kora project to your selected platform"
@@ -2509,7 +2727,7 @@ var deployCommand = (0, import_citty.defineCommand)({
2509
2727
  }
2510
2728
  },
2511
2729
  subCommands: {
2512
- status: (0, import_citty.defineCommand)({
2730
+ status: (0, import_citty2.defineCommand)({
2513
2731
  meta: {
2514
2732
  name: "status",
2515
2733
  description: "Show current deployment status"
@@ -2540,7 +2758,7 @@ var deployCommand = (0, import_citty.defineCommand)({
2540
2758
  logger.step(`Sync URL: ${state.syncUrl ?? "n/a"}`);
2541
2759
  }
2542
2760
  }),
2543
- rollback: (0, import_citty.defineCommand)({
2761
+ rollback: (0, import_citty2.defineCommand)({
2544
2762
  meta: {
2545
2763
  name: "rollback",
2546
2764
  description: "Rollback the current deployment"
@@ -2571,7 +2789,7 @@ var deployCommand = (0, import_citty.defineCommand)({
2571
2789
  logger.success(`Rolled back ${state.platform} deployment to ${deploymentId}.`);
2572
2790
  }
2573
2791
  }),
2574
- logs: (0, import_citty.defineCommand)({
2792
+ logs: (0, import_citty2.defineCommand)({
2575
2793
  meta: {
2576
2794
  name: "logs",
2577
2795
  description: "Read deployment logs"
@@ -2758,7 +2976,7 @@ function resolveAppName(argValue, storedValue, projectRoot, confirm) {
2758
2976
  "Missing app name in --confirm mode. Provide --app or run an interactive deploy first."
2759
2977
  );
2760
2978
  }
2761
- return sanitizeAppName((0, import_node_path12.basename)(projectRoot));
2979
+ return sanitizeAppName((0, import_node_path13.basename)(projectRoot));
2762
2980
  }
2763
2981
  function resolveRegion(argValue, storedValue, confirm) {
2764
2982
  if (typeof argValue === "string" && argValue.length > 0) return argValue;
@@ -2793,7 +3011,7 @@ function configureAdapterContext(adapter, context) {
2793
3011
  }
2794
3012
  }
2795
3013
  function detectDeployTarget(projectRoot) {
2796
- return (0, import_node_fs2.existsSync)((0, import_node_path12.join)(projectRoot, "src-tauri")) ? "sync-server" : "full-stack";
3014
+ return (0, import_node_fs2.existsSync)((0, import_node_path13.join)(projectRoot, "src-tauri")) ? "sync-server" : "full-stack";
2797
3015
  }
2798
3016
  function hasContextSetter(adapter) {
2799
3017
  return typeof adapter.setContext === "function";
@@ -3104,8 +3322,8 @@ function formatStoredPreferenceLabel(preferences) {
3104
3322
  }
3105
3323
 
3106
3324
  // src/commands/create/sync-provider-preset.ts
3107
- var import_promises9 = require("fs/promises");
3108
- var import_node_path13 = require("path");
3325
+ var import_promises10 = require("fs/promises");
3326
+ var import_node_path14 = require("path");
3109
3327
  async function applySyncProviderPreset(options) {
3110
3328
  if (!isSyncTemplate(options.template)) {
3111
3329
  return;
@@ -3115,10 +3333,10 @@ async function applySyncProviderPreset(options) {
3115
3333
  }
3116
3334
  const providerName = getProviderDisplayName(options.dbProvider);
3117
3335
  const providerConnectionString = getProviderConnectionStringExample(options.dbProvider);
3118
- const envPath = (0, import_node_path13.join)(options.targetDir, ".env.example");
3119
- const readmePath = (0, import_node_path13.join)(options.targetDir, "README.md");
3120
- const existingReadme = await (0, import_promises9.readFile)(readmePath, "utf-8");
3121
- const existingEnv = await (0, import_promises9.readFile)(envPath, "utf-8");
3336
+ const envPath = (0, import_node_path14.join)(options.targetDir, ".env.example");
3337
+ const readmePath = (0, import_node_path14.join)(options.targetDir, "README.md");
3338
+ const existingReadme = await (0, import_promises10.readFile)(readmePath, "utf-8");
3339
+ const existingEnv = await (0, import_promises10.readFile)(envPath, "utf-8");
3122
3340
  const trimmedReadme = existingReadme.trimEnd();
3123
3341
  const trimmedEnv = existingEnv.trimEnd();
3124
3342
  const envSuffix = [
@@ -3138,9 +3356,9 @@ async function applySyncProviderPreset(options) {
3138
3356
  ""
3139
3357
  ].join("\n");
3140
3358
  const readmeTemplate = `${trimmedReadme}${readmeSuffix}`;
3141
- await (0, import_promises9.writeFile)(envPath, `${trimmedEnv}${envSuffix}
3359
+ await (0, import_promises10.writeFile)(envPath, `${trimmedEnv}${envSuffix}
3142
3360
  `, "utf-8");
3143
- await (0, import_promises9.writeFile)(readmePath, readmeTemplate, "utf-8");
3361
+ await (0, import_promises10.writeFile)(readmePath, readmeTemplate, "utf-8");
3144
3362
  }
3145
3363
  function isSyncTemplate(template) {
3146
3364
  return template === "react-sync" || template === "react-tailwind-sync" || template === "vue-sync" || template === "vue-tailwind-sync" || template === "svelte-sync" || template === "svelte-tailwind-sync" || template === "tauri-react";
@@ -3183,6 +3401,7 @@ function getProviderConnectionStringExample(provider) {
3183
3401
  }
3184
3402
  // Annotate the CommonJS export names for ESM import in node:
3185
3403
  0 && (module.exports = {
3404
+ AGENTS_FRAMEWORKS,
3186
3405
  ClackPromptClient,
3187
3406
  CliError,
3188
3407
  DEPLOY_PLATFORMS,
@@ -3201,13 +3420,16 @@ function getProviderConnectionStringExample(provider) {
3201
3420
  StubDeployAdapter,
3202
3421
  TEMPLATES,
3203
3422
  TEMPLATE_INFO,
3423
+ agentsCommand,
3204
3424
  applySyncProviderPreset,
3205
3425
  buildClient,
3206
3426
  bundleServer,
3207
3427
  createDeployAdapter,
3208
3428
  createPromptClient,
3209
3429
  deployCommand,
3430
+ detectFrameworkFromManifest,
3210
3431
  determineTemplateFromSelections,
3432
+ generateAgentsMd,
3211
3433
  generateDeployPackageJson,
3212
3434
  generateDockerIgnore,
3213
3435
  generateDockerfile,
@@ -3216,6 +3438,7 @@ function getProviderConnectionStringExample(provider) {
3216
3438
  generateTypes,
3217
3439
  getCreatePreferencesOrDefault,
3218
3440
  getDefaultCreatePreferences,
3441
+ isAgentsFramework,
3219
3442
  isAuthValue,
3220
3443
  isDatabaseProviderValue,
3221
3444
  isDatabaseValue,