@lunora/cli 1.0.0-alpha.42 → 1.0.0-alpha.420

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.
Files changed (138) hide show
  1. package/LICENSE.md +33 -0
  2. package/README.md +3 -1
  3. package/dist/bin.mjs +2 -10
  4. package/dist/index.d.mts +1069 -374
  5. package/dist/index.d.ts +1069 -374
  6. package/dist/index.mjs +1 -19
  7. package/dist/packem_chunks/dispatch.mjs +1 -0
  8. package/dist/packem_chunks/handler.mjs +23 -158
  9. package/dist/packem_chunks/handler10.mjs +1 -16
  10. package/dist/packem_chunks/handler11.mjs +1 -22
  11. package/dist/packem_chunks/handler12.mjs +1 -192
  12. package/dist/packem_chunks/handler13.mjs +1 -131
  13. package/dist/packem_chunks/handler14.mjs +3 -65
  14. package/dist/packem_chunks/handler15.mjs +1 -58
  15. package/dist/packem_chunks/handler16.mjs +1 -80
  16. package/dist/packem_chunks/handler17.mjs +1 -43
  17. package/dist/packem_chunks/handler18.mjs +7 -105
  18. package/dist/packem_chunks/handler19.mjs +2 -170
  19. package/dist/packem_chunks/handler2.mjs +1 -114
  20. package/dist/packem_chunks/handler20.mjs +1 -94
  21. package/dist/packem_chunks/handler21.mjs +3 -94
  22. package/dist/packem_chunks/handler22.mjs +3 -0
  23. package/dist/packem_chunks/handler23.mjs +1 -0
  24. package/dist/packem_chunks/handler24.mjs +2 -0
  25. package/dist/packem_chunks/handler25.mjs +99 -0
  26. package/dist/packem_chunks/handler26.mjs +2 -0
  27. package/dist/packem_chunks/handler27.mjs +9 -0
  28. package/dist/packem_chunks/handler28.mjs +1 -0
  29. package/dist/packem_chunks/handler3.mjs +1 -204
  30. package/dist/packem_chunks/handler4.mjs +1 -33
  31. package/dist/packem_chunks/handler5.mjs +3 -49
  32. package/dist/packem_chunks/handler6.mjs +1 -91
  33. package/dist/packem_chunks/handler7.mjs +1 -42
  34. package/dist/packem_chunks/handler8.mjs +1 -174
  35. package/dist/packem_chunks/handler9.mjs +2 -315
  36. package/dist/packem_chunks/runCodegenCommand.mjs +4 -52
  37. package/dist/packem_chunks/runDevCommand.mjs +2 -0
  38. package/dist/packem_chunks/runInitCommand.mjs +165 -1432
  39. package/dist/packem_chunks/runResetCommand.mjs +1 -41
  40. package/dist/packem_chunks/runRpcCommand.mjs +1 -68
  41. package/dist/packem_shared/COMMANDS-BCSDC-pv.mjs +1 -0
  42. package/dist/packem_shared/DEFAULT_IMPORT_BATCH_SIZE-CyIsI3S1.mjs +1 -0
  43. package/dist/packem_shared/EXIT_CODE-D_XCixv8.mjs +1 -0
  44. package/dist/packem_shared/admin-token-VdUnvnKW.mjs +1 -0
  45. package/dist/packem_shared/admin-url-DJB8P6Jh.mjs +1 -0
  46. package/dist/packem_shared/api-spec-lYyq4vL6.mjs +1 -0
  47. package/dist/packem_shared/binding-manifest-file-CQ1eQYy1.mjs +2 -0
  48. package/dist/packem_shared/buildRegistryIndex-Dc8D8AR6.mjs +1 -0
  49. package/dist/packem_shared/cap-error-body-YBKO32BF.mjs +1 -0
  50. package/dist/packem_shared/catalog-CahzmDLV.mjs +1 -0
  51. package/dist/packem_shared/cli-BbgDNGew.mjs +2 -0
  52. package/dist/packem_shared/cli-manifest-DoQ_3bzs.mjs +1 -0
  53. package/dist/packem_shared/cloudflare-credentials-BVmZnDZk.mjs +1 -0
  54. package/dist/packem_shared/codegen-error-AmH54ofi.mjs +3 -0
  55. package/dist/packem_shared/command-CB4JM-Jl.mjs +1 -0
  56. package/dist/packem_shared/commands-DvSfLvyt.mjs +13 -0
  57. package/dist/packem_shared/createLogger-4TujevyB.mjs +2 -0
  58. package/dist/packem_shared/createRecordingSpawner-Ch7zuQQE.mjs +1 -0
  59. package/dist/packem_shared/deploy-target-resolve-BTCW1Iv4.mjs +1 -0
  60. package/dist/packem_shared/diffSnapshots-htqNZT8Q.mjs +7 -0
  61. package/dist/packem_shared/docker-DpVxvYpL.mjs +1 -0
  62. package/dist/packem_shared/free-port-DjbFhaaT.mjs +1 -0
  63. package/dist/packem_shared/health-probe-Bw9JFfIy.mjs +1 -0
  64. package/dist/packem_shared/import-BRM1hs7j.mjs +12 -0
  65. package/dist/packem_shared/index-oHZBGBwB.mjs +1 -0
  66. package/dist/packem_shared/insertSchemaExtension-DuiV6cba.mjs +8 -0
  67. package/dist/packem_shared/lint-ignore-report-DKZagpqk.mjs +2 -0
  68. package/dist/packem_shared/mcp-config-file-CcDTeXIq.mjs +2 -0
  69. package/dist/packem_shared/open-url-EnKy--w-.mjs +1 -0
  70. package/dist/packem_shared/output-format-DWe_tkTR.mjs +2 -0
  71. package/dist/packem_shared/parseManifest-CwPTKdtS.mjs +1 -0
  72. package/dist/packem_shared/path-containment-CgxYZggb.mjs +1 -0
  73. package/dist/packem_shared/plan-DFY3CqHD.mjs +5 -0
  74. package/dist/packem_shared/planDevCommand-BDoJUgQ4.mjs +1 -0
  75. package/dist/packem_shared/platform-diagnostics-Cn2g6Jh-.mjs +4 -0
  76. package/dist/packem_shared/prompt-cancelled-BvsNxg_Q.mjs +1 -0
  77. package/dist/packem_shared/render-lunora-error-B6893vbU.mjs +2 -0
  78. package/dist/packem_shared/resolve-Bdc9KEUv.mjs +5 -0
  79. package/dist/packem_shared/resolve-target-C_ZloTvd.mjs +1 -0
  80. package/dist/packem_shared/runAddCommand-BChdJQ5L.mjs +1 -0
  81. package/dist/packem_shared/runDeployCommand-D40F3PLQ.mjs +1 -0
  82. package/dist/packem_shared/runExportCommand-slAq5BCF.mjs +5 -0
  83. package/dist/packem_shared/runMigrateGenerateCommand-BwemPIOz.mjs +11 -0
  84. package/dist/packem_shared/schemaIrToSnapshot-BHuNOfgs.mjs +1 -0
  85. package/dist/packem_shared/secret-key-8DPOH98z.mjs +1 -0
  86. package/dist/packem_shared/shared-D-zCOmgY.mjs +1 -0
  87. package/dist/packem_shared/storage-DNzYhXR-.mjs +1 -0
  88. package/dist/packem_shared/tui-prompts-B3YwUhGw.mjs +4 -0
  89. package/dist/packem_shared/variables-CPYyJtsL.mjs +1 -0
  90. package/dist/packem_shared/wrangler-name-Dsk5K1f-.mjs +1 -0
  91. package/dist/packem_shared/wrangler-secrets-CTQPpalP.mjs +1 -0
  92. package/package.json +39 -19
  93. package/skills/README.md +36 -17
  94. package/skills/lunora/SKILL.md +158 -65
  95. package/skills/lunora-cloudflare-audit/SKILL.md +163 -0
  96. package/skills/lunora-create-package/SKILL.md +97 -84
  97. package/skills/lunora-deploy/SKILL.md +175 -105
  98. package/skills/lunora-functions/SKILL.md +363 -56
  99. package/skills/lunora-migration-helper/SKILL.md +162 -137
  100. package/skills/lunora-performance-audit/SKILL.md +137 -95
  101. package/skills/lunora-quickstart/SKILL.md +136 -136
  102. package/skills/lunora-realtime/SKILL.md +217 -97
  103. package/skills/lunora-setup-auth/SKILL.md +162 -102
  104. package/skills/lunora-setup-hyperdrive/SKILL.md +130 -109
  105. package/skills/lunora-setup-hyperdrive-global/SKILL.md +93 -90
  106. package/skills/lunora-setup-mail/SKILL.md +85 -113
  107. package/skills/lunora-setup-scheduler/SKILL.md +132 -96
  108. package/skills/lunora-setup-storage/SKILL.md +189 -95
  109. package/dist/packem_chunks/planDevCommand.mjs +0 -541
  110. package/dist/packem_chunks/runDeployCommand.mjs +0 -594
  111. package/dist/packem_chunks/runMigrateGenerateCommand.mjs +0 -397
  112. package/dist/packem_shared/COMMANDS-B0ftFD_3.mjs +0 -948
  113. package/dist/packem_shared/DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs +0 -244
  114. package/dist/packem_shared/admin-url-4UzT-CI4.mjs +0 -19
  115. package/dist/packem_shared/api-spec-CtA6ilu4.mjs +0 -13
  116. package/dist/packem_shared/buildRegistryIndex-BcYe607_.mjs +0 -38
  117. package/dist/packem_shared/codegen-error-DJG-ghs_.mjs +0 -31
  118. package/dist/packem_shared/command-D3lB_4Az.mjs +0 -19
  119. package/dist/packem_shared/commands-B-gR09Z_.mjs +0 -845
  120. package/dist/packem_shared/createLogger-B40gPzQo.mjs +0 -78
  121. package/dist/packem_shared/createRecordingSpawner-DxI3mebw.mjs +0 -43
  122. package/dist/packem_shared/detect-package-manager-DYp7n3mJ.mjs +0 -61
  123. package/dist/packem_shared/diffSnapshots-BeDvvNiF.mjs +0 -161
  124. package/dist/packem_shared/docker-hMQ97KSQ.mjs +0 -21
  125. package/dist/packem_shared/insertSchemaExtension-DAqbfr9Z.mjs +0 -64
  126. package/dist/packem_shared/open-url-Dfq6fAyT.mjs +0 -41
  127. package/dist/packem_shared/output-format-wUvAN6AL.mjs +0 -17
  128. package/dist/packem_shared/parseArgs-YXFuKdEk.mjs +0 -56
  129. package/dist/packem_shared/parseManifest--vZf2FY1.mjs +0 -94
  130. package/dist/packem_shared/prompt-cancelled-APzX1Im-.mjs +0 -9
  131. package/dist/packem_shared/resolve-target-qbsJ_5sF.mjs +0 -16
  132. package/dist/packem_shared/runAddCommand-bnY6-HKb.mjs +0 -4
  133. package/dist/packem_shared/schema-drift-gate-BtBt0as0.mjs +0 -79
  134. package/dist/packem_shared/schemaIrToSnapshot-DdsljJT-.mjs +0 -43
  135. package/dist/packem_shared/storage-BIsph-Vk.mjs +0 -84
  136. package/dist/packem_shared/tui-prompts-BjEN8XgP.mjs +0 -658
  137. package/dist/packem_shared/wrangler-name-cy4yhm9j.mjs +0 -12
  138. package/dist/packem_shared/wrangler-secrets-P2_ZUR-k.mjs +0 -47
@@ -1,131 +1 @@
1
- import { r as resolveAdminBaseUrl } from '../packem_shared/admin-url-4UzT-CI4.mjs';
2
- import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
3
- import { a as resolveProductionWorkerUrl } from '../packem_shared/resolve-target-qbsJ_5sF.mjs';
4
-
5
- const GET_FUNCTION_STATS_OP = "__lunora_admin__:getFunctionStats";
6
- const DEFAULT_LIMIT = 10;
7
- const TRAILING_SLASH = /\/$/u;
8
- const toInsightRow = (stat, rate) => {
9
- return {
10
- calls: stat.calls,
11
- conflicts: stat.conflicts ?? 0,
12
- errors: stat.errors,
13
- lastErrorMessage: stat.lastErrorMessage,
14
- maxDurationMs: stat.maxDurationMs,
15
- meanDurationMs: stat.calls === 0 ? 0 : stat.totalDurationMs / stat.calls,
16
- path: stat.path,
17
- rate
18
- };
19
- };
20
- const buildInsightsReport = (functions, limit) => {
21
- const writeContention = functions.filter((stat) => (stat.conflicts ?? 0) > 0).map((stat) => toInsightRow(stat, stat.calls === 0 ? 0 : (stat.conflicts ?? 0) / stat.calls)).toSorted((a, b) => b.rate - a.rate || b.conflicts - a.conflicts).slice(0, limit);
22
- const errorHotspots = functions.filter((stat) => stat.errors > 0).map((stat) => toInsightRow(stat, stat.calls === 0 ? 0 : stat.errors / stat.calls)).toSorted((a, b) => b.rate - a.rate || b.errors - a.errors).slice(0, limit);
23
- const latencyOutliers = functions.map((stat) => toInsightRow(stat, 0)).toSorted((a, b) => b.maxDurationMs - a.maxDurationMs).slice(0, limit);
24
- return { errorHotspots, latencyOutliers, totalFunctions: functions.length, writeContention };
25
- };
26
- const percent = (rate) => `${(rate * 100).toFixed(1)}%`;
27
- const formatMs = (ms) => ms < 1e3 ? `${Math.round(ms).toString()}ms` : `${(ms / 1e3).toFixed(2)}s`;
28
- const formatSection = (heading, rows, emptyNote, renderRow) => [
29
- heading,
30
- ...rows.length === 0 ? [` ${emptyNote}`] : rows.map((row) => ` ${renderRow(row)}`)
31
- ];
32
- const formatInsightsReport = (report) => {
33
- const errorTail = (row) => row.lastErrorMessage ? ` — ${row.lastErrorMessage}` : "";
34
- return [
35
- `Insights over ${report.totalFunctions.toString()} function${report.totalFunctions === 1 ? "" : "s"}`,
36
- "",
37
- ...formatSection(
38
- "Write-conflict hot-spots (OCC contention — candidates for sharding):",
39
- report.writeContention,
40
- "none — no write conflicts observed",
41
- (row) => `${row.path} ${row.conflicts.toString()}/${row.calls.toString()} calls (${percent(row.rate)})`
42
- ),
43
- "",
44
- ...formatSection(
45
- "Error hot-spots:",
46
- report.errorHotspots,
47
- "none — no errors observed",
48
- (row) => `${row.path} ${row.errors.toString()}/${row.calls.toString()} calls (${percent(row.rate)})${errorTail(row)}`
49
- ),
50
- "",
51
- ...formatSection(
52
- "Latency outliers (slowest single call):",
53
- report.latencyOutliers,
54
- "none — no functions have run",
55
- (row) => `${row.path} max ${formatMs(row.maxDurationMs)}, mean ${formatMs(row.meanDurationMs)} over ${row.calls.toString()} calls`
56
- )
57
- ].join("\n");
58
- };
59
- const resolveLimit = (raw) => {
60
- if (raw === void 0 || !Number.isFinite(raw) || raw <= 0) {
61
- return DEFAULT_LIMIT;
62
- }
63
- return Math.floor(raw);
64
- };
65
- const runInsightsCommand = async (options) => {
66
- if (options.prod && options.url === void 0) {
67
- options.logger.error("--prod requires an explicit --url (refusing to report from the implicit localhost worker)");
68
- return { code: 1 };
69
- }
70
- const token = options.token ?? process.env.LUNORA_ADMIN_TOKEN;
71
- if (!token) {
72
- options.logger.error("admin token required — pass --token or set LUNORA_ADMIN_TOKEN");
73
- return { code: 1 };
74
- }
75
- const baseUrl = resolveAdminBaseUrl(options.url, options.logger);
76
- if (baseUrl === void 0) {
77
- return { code: 1 };
78
- }
79
- const requestUrl = `${baseUrl.replace(TRAILING_SLASH, "")}/_lunora/rpc`;
80
- const fetchImpl = globalThis.fetch;
81
- if (typeof fetchImpl !== "function") {
82
- throw new TypeError("no fetch implementation available — pass fetchImpl or run on Node >= 18");
83
- }
84
- const payload = { args: {}, functionPath: GET_FUNCTION_STATS_OP };
85
- if (options.shard !== void 0) {
86
- payload.shardKey = options.shard;
87
- }
88
- options.logger.info(`POST ${requestUrl} -> insights`);
89
- const response = await fetchImpl(requestUrl, {
90
- body: JSON.stringify(payload),
91
- headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
92
- method: "POST"
93
- });
94
- const text = await response.text();
95
- if (!response.ok) {
96
- options.logger.error(`insights failed: HTTP ${String(response.status)}: ${text}`);
97
- return { code: 1 };
98
- }
99
- let parsed;
100
- try {
101
- parsed = JSON.parse(text);
102
- } catch {
103
- options.logger.error(`insights failed: worker returned non-JSON: ${text}`);
104
- return { code: 1 };
105
- }
106
- const result = parsed.result ?? parsed;
107
- const { functions } = result;
108
- if (!Array.isArray(functions)) {
109
- options.logger.error("insights failed: response carried no `functions` array");
110
- return { code: 1 };
111
- }
112
- const report = buildInsightsReport(functions, resolveLimit(options.limit));
113
- options.logger.info(options.json ? JSON.stringify(report, void 0, 2) : formatInsightsReport(report));
114
- return { code: 0, report };
115
- };
116
- const execute = defineHandler(({ cwd, logger, options }) => {
117
- const limit = options.limit === void 0 ? void 0 : Number.parseInt(options.limit, 10);
118
- return runInsightsCommand({
119
- json: options.json,
120
- limit,
121
- logger,
122
- prod: options.prod,
123
- shard: options.shard,
124
- token: options.token,
125
- // Fall back to the `.lunora/project.json` link when `--prod` is set, so a
126
- // linked checkout doesn't need --url repeated for prod insights.
127
- url: resolveProductionWorkerUrl({ cwd, prod: options.prod === true, url: options.url })
128
- });
129
- });
130
-
131
- export { buildInsightsReport, execute, formatInsightsReport, runInsightsCommand };
1
+ import{existsSync as u,readdirSync as d,statSync as g,mkdirSync as h,writeFileSync as w,readFileSync as y}from"node:fs";import{fileURLToPath as v}from"node:url";import{AGENT_RULES_DIR as a,detectAgentRules as R,LUNORA_SKILL_NAMES as L}from"@lunora/config";import{join as i,relative as A,resolve as E,dirname as m}from"@visulima/path";import{f as I}from"../packem_shared/cli-manifest-DoQ_3bzs.mjs";import{d as $}from"../packem_shared/command-CB4JM-Jl.mjs";import{EXIT_CODE as _}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";const b=(e=m(v(import.meta.url)))=>{const r=I(e),t=r===void 0?void 0:i(r,"skills");return t!==void 0&&u(t)?t:void 0},j=e=>d(e).filter(r=>{const t=i(e,r);return g(t).isDirectory()&&u(i(t,"SKILL.md"))}),f=(e,r,t)=>{h(r,{recursive:!0});let n=!1;for(const o of d(e)){const l=i(e,o),s=i(r,o);if(g(l).isDirectory()){n=f(l,s,t)||n;continue}u(s)&&!t||(w(s,y(l)),n=!0)}return n},D=["pnpm-workspace.yaml","pnpm-lock.yaml","yarn.lock","package-lock.json","bun.lock","bun.lockb",".git"],O=e=>{let r=e;for(;;){if(D.some(n=>u(i(r,n))))return r;const t=m(r);if(t===r)return e;r=t}},k=(e,r)=>r===void 0?O(e):E(e,r),U=e=>{const r=e.cwd??process.cwd(),t=k(r,e.dir),n=e.overwrite===!0,o=b();if(o===void 0)return e.logger.error("rules: could not locate the bundled skills (is @lunora/cli installed correctly?)."),{code:1,installed:[],skipped:[]};const l=[],s=[];for(const c of j(o)){const S=i(t,a,c);f(i(o,c),S,n)?l.push(c):s.push(c)}const p=A(r,i(t,a))||a;return l.length>0&&e.logger.success(`Installed ${String(l.length)} Lunora skill(s) into ${p}/: ${l.join(", ")}.`),s.length>0&&e.logger.info(`Skipped ${String(s.length)} existing skill(s) (re-run with --overwrite to replace): ${s.join(", ")}.`),e.logger.info("Your AI coding agent will pick these up automatically. Start with the `lunora` skill."),{code:0,installed:l,skipped:s}},x=e=>{const r=e.cwd??process.cwd(),t=k(r,e.dir),n=R(t);return n.installed?(e.logger.success(`Lunora agent rules are installed (${String(n.present.length)}/${String(L.length)} skills).`),n.missing.length>0&&e.logger.info(`Missing: ${n.missing.join(", ")}. Run \`lunora rules install\` to add them.`),{code:0,installed:n.present,skipped:[]}):(e.logger.warn("Lunora agent rules are not installed. Run `lunora rules install` so your AI agent knows how to use Lunora."),{code:e.strict===!0?1:0,installed:n.present,skipped:[]})},G=$(({argument:e,cwd:r,logger:t,options:n})=>{const o=e[0]??"check";return o==="install"?U({cwd:r,dir:n.dir,logger:t,overwrite:n.overwrite===!0}):o==="check"?x({cwd:r,dir:n.dir,logger:t,strict:n.strict===!0}):(t.error("rules: unknown subcommand. Usage: lunora rules <install|check>"),{code:_.USAGE})});export{G as execute,j as listBundledSkills,b as resolveBundledSkillsDirectory,x as runRulesCheck,U as runRulesInstall};
@@ -1,65 +1,3 @@
1
- import { existsSync, rmSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import { writeLinkedProject, LINKED_PROJECT_FILE } from '@lunora/config';
4
- import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
5
- import { r as readWranglerName } from '../packem_shared/wrangler-name-cy4yhm9j.mjs';
6
-
7
- const isValidWorkerUrl = (value) => {
8
- try {
9
- const { protocol } = new URL(value);
10
- return protocol === "http:" || protocol === "https:";
11
- } catch {
12
- return false;
13
- }
14
- };
15
- const runLinkRemove = (cwd, logger) => {
16
- const path = join(cwd, LINKED_PROJECT_FILE);
17
- if (!existsSync(path)) {
18
- logger.warn(`link: no ${LINKED_PROJECT_FILE} to remove`);
19
- return { code: 0 };
20
- }
21
- rmSync(path);
22
- logger.success(`link: removed ${LINKED_PROJECT_FILE}`);
23
- return { code: 0 };
24
- };
25
- const runLinkCommand = (options) => {
26
- const cwd = options.cwd ?? process.cwd();
27
- const { logger } = options;
28
- if (options.remove) {
29
- return runLinkRemove(cwd, logger);
30
- }
31
- if (options.url === void 0 || options.url === "") {
32
- logger.error("link requires a deployed Worker URL. Usage: lunora link --url <https://your-worker>");
33
- return { code: 1 };
34
- }
35
- if (!isValidWorkerUrl(options.url)) {
36
- logger.error(`link: invalid --url "${options.url}" — expected an http(s) URL`);
37
- return { code: 1 };
38
- }
39
- const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
40
- const link = {
41
- env: options.env,
42
- linkedAt: now(),
43
- workerName: options.name ?? readWranglerName(cwd),
44
- workerUrl: options.url
45
- };
46
- const path = writeLinkedProject(cwd, link);
47
- logger.success(`link: ${link.workerName ?? "(unnamed worker)"} -> ${options.url}`);
48
- logger.info(`link: wrote ${path}`);
49
- if (link.env !== void 0) {
50
- logger.info(`link: environment "${link.env}"`);
51
- }
52
- return { code: 0, link };
53
- };
54
- const execute = defineHandler(
55
- ({ cwd, logger, options }) => runLinkCommand({
56
- cwd,
57
- env: options.env,
58
- logger,
59
- name: options.name,
60
- remove: options.remove === true,
61
- url: options.url
62
- })
63
- );
64
-
65
- export { execute, runLinkCommand };
1
+ import{existsSync as S}from"node:fs";import{mkdtemp as v,writeFile as k,rm as j}from"node:fs/promises";import{tmpdir as R}from"node:os";import{discoverSchema as C,schemaFromIr as T}from"@lunora/codegen";import{seedPlan as $}from"@lunora/seed";import{join as w}from"@visulima/path";import{Project as A}from"ts-morph";import{t as y}from"../packem_shared/admin-token-VdUnvnKW.mjs";import{d as E}from"../packem_shared/command-CB4JM-Jl.mjs";import{EXIT_CODE as u}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{a as F}from"../packem_shared/resolve-target-C_ZloTvd.mjs";import{b as N}from"../packem_shared/tui-prompts-B3YwUhGw.mjs";import{runResetCommand as U}from"./runResetCommand.mjs";import{r as I}from"../packem_shared/import-BRM1hs7j.mjs";const O=(e,r)=>typeof r=="bigint"?Number(r):r instanceof ArrayBuffer?[...new Uint8Array(r)]:r,f=(e,r)=>({code:e,error:r,ndjson:""}),x=(e,r)=>{if(!S(r)){const o=`schema not found: ${r} — run \`vis generate lunora-table --name=<name>\` to create one`;return e.logger.error(o),f(u.NOT_FOUND,o)}if(e.reset===!0&&y({prod:e.prod,url:e.url})){const o="--reset only clears local .wrangler/state and cannot be combined with --prod or a remote --url";return e.logger.error(o),f(u.USAGE,o)}},z=async(e,r,o,t,n)=>{const s=await v(w(R(),"lunora-seed-")),d=w(s,"rows.ndjson");await k(d,e,"utf8");try{const a=await I({batchSize:n.batchSize,cwd:t,fetchImpl:n.fetchImpl,file:d,logger:n.logger,prod:n.prod,token:n.token,url:n.url,yes:!0}),i=a.body?.conflicts??0;return i>0&&n.logger.warn(`${String(i)} row(s) skipped — their _id already exists. Seeding is deterministic; re-run with --reset to wipe local state first, or a different --seed for fresh ids.`),{code:a.code,data:{conflicts:i,generated:r,inserted:a.inserted,tables:o},ndjson:e,...a.error===void 0?{}:{error:a.error}}}finally{await j(s,{force:!0,recursive:!0}).catch(()=>{})}},D=(e,r)=>{if(e.table===void 0||r.tables.some(n=>n.name===e.table))return;const o=r.tables.map(n=>n.name).join(", "),t=`unknown table "${e.table}" — schema defines: ${o||"(no tables)"}`;return e.logger.error(t),f(u.USAGE,t)},_=async(e,r)=>{if(!y({prod:e.prod,url:e.url})||e.yes===!0)return;if(!process.stdin.isTTY&&e.confirm===void 0){const s="seed: refusing to insert into a non-local target without confirmation — re-run with --yes";return e.logger.error(s),f(u.USAGE,s)}if(!await(e.confirm??N)(`This will insert ${String(r)} generated row(s) into ${e.url??"the production worker"}. Continue?`))return e.logger.info("seed: aborted"),f(u.CANCELLED,"seed: aborted at the confirmation prompt")},G=e=>{const r=[];for(const{rows:o,table:t}of e)for(const n of o)r.push(JSON.stringify({doc:n,table:t},O));return{lines:r,ndjson:r.length>0?`${r.join(`
2
+ `)}
3
+ `:""}},P=async e=>{const r=e.cwd??process.cwd(),o=e.format==="json",t=w(r,"lunora","schema.ts"),n=x(e,t);if(n!==void 0)return n;const s=new A({skipAddingFilesFromTsConfig:!0}),d=C(s,t),a=D(e,d);if(a!==void 0)return a;const i=T(d),l=$(i,{defaultCount:e.count??10,now:e.now,only:e.table===void 0?void 0:[e.table],seed:e.seed??0}),{lines:h,ndjson:c}=G(l),m=h.length;if(e.dryRun===!0)return!o&&c.length>0&&process.stdout.write(c),e.logger.info(`generated ${String(m)} row(s) across ${String(l.length)} table(s) — dry run, nothing inserted`),{code:0,data:{conflicts:0,generated:m,inserted:0,rows:o?h.map(g=>JSON.parse(g)):void 0,tables:l.length},ndjson:c};if(m===0)return e.logger.warn("no rows generated — nothing to insert"),{code:0,data:{conflicts:0,generated:0,inserted:0,tables:l.length},ndjson:c};if(e.reset===!0){const g=await U({confirm:e.confirm,cwd:r,logger:e.logger,yes:e.yes});if(g.code!==0)return{code:g.code,error:"seed: --reset could not clear local state",ndjson:c}}const b=await _(e,m);return b!==void 0?b:z(c,m,l.length,r,e)},ee=E(async({cwd:e,format:r,logger:o,options:t})=>{const n=await P({batchSize:t.batchSize,count:t.count,cwd:e,dryRun:t.dryRun===!0,format:r,logger:o,prod:t.prod===!0,reset:t.reset===!0,now:t.now,seed:t.seed,table:t.table,token:t.token,url:F({cwd:e,prod:t.prod===!0,url:t.url}),yes:t.yes===!0});return{code:n.code,data:n.data,error:n.error}});export{ee as execute,P as runSeedCommand};
@@ -1,58 +1 @@
1
- import { readLinkedProject } from '@lunora/config';
2
- import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
3
- import { defaultSpawner } from '../packem_shared/createRecordingSpawner-DxI3mebw.mjs';
4
-
5
- const LOG_FORMATS = /* @__PURE__ */ new Set(["json", "pretty"]);
6
- const runLogsCommand = async (options) => {
7
- const cwd = options.cwd ?? process.cwd();
8
- if (options.format !== void 0 && !LOG_FORMATS.has(options.format)) {
9
- options.logger.error(`logs: unknown --format "${options.format}" — expected pretty | json`);
10
- return { code: 1, descriptor: void 0, error: "invalid format" };
11
- }
12
- const args = ["exec", "wrangler", "tail"];
13
- if (options.worker !== void 0) {
14
- args.push(options.worker);
15
- }
16
- const env = options.env ?? readLinkedProject(cwd)?.env;
17
- if (env !== void 0) {
18
- args.push("--env", env);
19
- }
20
- if (options.format !== void 0) {
21
- args.push("--format", options.format);
22
- }
23
- if (options.status !== void 0) {
24
- args.push("--status", options.status);
25
- }
26
- if (options.search !== void 0) {
27
- args.push("--search", options.search);
28
- }
29
- if (options.temporary) {
30
- args.push("--temporary");
31
- }
32
- const descriptor = {
33
- args,
34
- command: "pnpm",
35
- cwd
36
- };
37
- options.logger.info(`tailing logs via ${descriptor.command} ${descriptor.args.join(" ")}`);
38
- const spawner = options.spawner ?? defaultSpawner;
39
- const result = await spawner(descriptor);
40
- return {
41
- code: result.code,
42
- descriptor
43
- };
44
- };
45
- const execute = defineHandler(
46
- ({ argument, cwd, logger, options }) => runLogsCommand({
47
- cwd,
48
- env: options.env,
49
- format: options.format,
50
- logger,
51
- search: options.search,
52
- status: options.status,
53
- temporary: options.temporary === true,
54
- worker: argument[0]
55
- })
56
- );
57
-
58
- export { execute, runLogsCommand };
1
+ import{r as $}from"../packem_shared/admin-token-VdUnvnKW.mjs";import{r as S,a as p}from"../packem_shared/admin-url-DJB8P6Jh.mjs";import{d as k}from"../packem_shared/command-CB4JM-Jl.mjs";import{EXIT_CODE as u,exitCodeForStatus as b}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{a as y}from"../packem_shared/resolve-target-C_ZloTvd.mjs";const w="/_lunora/admin/shard-registry/prune",f=["prune"],d=(e,r,a)=>(e.error(r),{code:a,error:r}),g=(e,r,a)=>{for(const{shardKey:t,table:n}of r.released)e.info(`${a?"would release":"released"} ${t} (${n})`);for(const{message:t,shardKey:n,tables:l}of r.failed)e.error(`could not check ${n} (${l.join(", ")}) — kept: ${t}`);const s=`${String(r.released.length)} ${a?"would be released":"released"}, ${String(r.kept.length)} kept (still hold rows), ${String(r.failed.length)} unreachable`;r.failed.length>0?e.warn(`${s} — re-run to retry the unreachable shards`):e.success(s)},A=async e=>{const{logger:r}=e;if(!f.includes(e.subcommand))return d(r,`shards: unknown subcommand "${e.subcommand??""}" — expected ${f.join(" | ")}`,u.USAGE);if(e.prod&&e.url===void 0)return d(r,"--prod requires an explicit --url (refusing to prune the implicit localhost worker)",u.USAGE);const a=S(e.url,r,e.cwd);if(a===void 0)return{code:u.USAGE,error:"could not resolve a usable worker URL"};const{token:s}=$({cwd:e.cwd??process.cwd(),token:e.token,url:a});if(!s)return d(r,"admin token required — pass --token, set LUNORA_ADMIN_TOKEN, or add it to .dev.vars (local targets only)",u.AUTH);const t=`${a}${w}`,n=e.fetchImpl??p,l=e.tables?.split(",").map(h=>h.trim()).filter(h=>h!==""),i=e.dryRun===!0;r.info(`POST ${t} -> shards prune${i?" (dry run)":""}`);const c=await n(t,{body:JSON.stringify({dryRun:i,...l===void 0?{}:{tables:l}}),headers:{authorization:`Bearer ${s}`,"content-type":"application/json"},method:"POST"}),m=await c.text();if(!c.ok)return d(r,`shards prune failed: HTTP ${String(c.status)}: ${m}`,b(c.status));let o;try{o=JSON.parse(m)}catch{return d(r,`shards prune failed: worker returned non-JSON: ${m}`,1)}return e.format!=="json"&&g(r,o,i),o.failed.length>0?{code:1,error:`shards prune: ${String(o.failed.length)} shard(s) could not be checked`,result:o}:{code:0,result:o}},E=k(async({argument:e,cwd:r,format:a,logger:s,options:t})=>{const n=await A({cwd:r,dryRun:t.dryRun===!0,format:a,logger:s,prod:t.prod,subcommand:e[0],tables:t.tables,token:t.token,url:y({cwd:r,prod:t.prod===!0,url:t.url})});return{code:n.code,data:n.result,error:n.error}});export{E as execute,A as runShardsCommand};
@@ -1,80 +1 @@
1
- import { runCodegen } from '@lunora/codegen';
2
- import { validateWranglerProject, inferLunoraBindings, reconcileWranglerBindings } from '@lunora/config';
3
- import { p as parseApiSpec } from '../packem_shared/api-spec-CtA6ilu4.mjs';
4
- import { r as renderCodegenFailure } from '../packem_shared/codegen-error-DJG-ghs_.mjs';
5
- import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
6
- import { r as runSchemaDriftGate } from '../packem_shared/schema-drift-gate-BtBt0as0.mjs';
7
-
8
- const provisionBindings = async (cwd, logger) => {
9
- try {
10
- const inferred = await inferLunoraBindings({ projectRoot: cwd });
11
- const reconciled = reconcileWranglerBindings(cwd, inferred);
12
- if (reconciled.changed) {
13
- logger.success(`provisioned bindings: ${reconciled.added.join(", ")} → ${reconciled.wranglerPath ?? "wrangler.jsonc"}`);
14
- }
15
- for (const warning of reconciled.warnings) {
16
- logger.warn(warning);
17
- }
18
- } catch (error) {
19
- const message = error instanceof Error ? error.message : String(error);
20
- logger.warn(`binding inference skipped: ${message}`);
21
- }
22
- };
23
- const runPrepareCommand = async (options) => {
24
- const cwd = options.cwd ?? process.cwd();
25
- options.logger.info("running codegen");
26
- let codegen;
27
- try {
28
- codegen = runCodegen({ apiSpec: options.apiSpec, projectRoot: cwd });
29
- options.logger.success("codegen complete");
30
- } catch (error) {
31
- const message = error instanceof Error ? error.message : String(error);
32
- options.logger.error(renderCodegenFailure(error));
33
- return {
34
- code: 1,
35
- error: `codegen failed: ${message}`,
36
- validation: { problems: [], wranglerPath: void 0 }
37
- };
38
- }
39
- const gate = runSchemaDriftGate({
40
- allowDrift: options.allowSchemaDrift === true,
41
- codegen,
42
- logger: options.logger,
43
- updateBaseline: options.updateSchemaBaseline === true
44
- });
45
- if (gate.blocked) {
46
- return {
47
- code: 1,
48
- error: "schema drift gate blocked prepare",
49
- schemaDrift: { blocked: true, reason: gate.reason },
50
- validation: { problems: [], wranglerPath: void 0 }
51
- };
52
- }
53
- await provisionBindings(cwd, options.logger);
54
- const validation = validateWranglerProject({ projectRoot: cwd });
55
- if (validation.problems.length > 0) {
56
- options.logger.error("wrangler.jsonc validation failed:");
57
- for (const problem of validation.problems) {
58
- options.logger.error(` - ${problem}`);
59
- }
60
- return {
61
- code: 1,
62
- error: "wrangler validation failed",
63
- validation
64
- };
65
- }
66
- gate.rebless?.();
67
- options.logger.success("project is ready to deploy");
68
- return { code: 0, validation };
69
- };
70
- const execute = defineHandler(
71
- ({ cwd, logger, options }) => runPrepareCommand({
72
- allowSchemaDrift: options.allowSchemaDrift === true,
73
- apiSpec: parseApiSpec(options.apiSpec),
74
- cwd,
75
- logger,
76
- updateSchemaBaseline: options.updateSchemaBaseline === true
77
- })
78
- );
79
-
80
- export { execute, runPrepareCommand };
1
+ import{existsSync as h}from"node:fs";import{join as p}from"node:path";import{runCodegen as g}from"@lunora/codegen";import{resolveLazyFunctions as u}from"@lunora/config";import{validateWranglerProject as v,wranglerCodegenInputs as y}from"@lunora/config/cloudflare";import{a as w,e as S,r as k}from"../packem_shared/platform-diagnostics-Cn2g6Jh-.mjs";import{p as j}from"../packem_shared/api-spec-lYyq4vL6.mjs";import{r as E}from"../packem_shared/codegen-error-AmH54ofi.mjs";import{d as A}from"../packem_shared/command-CB4JM-Jl.mjs";import{r as D}from"../packem_shared/deploy-target-resolve-BTCW1Iv4.mjs";import{EXIT_CODE as R}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{r as $,p as b}from"../packem_shared/health-probe-Bw9JFfIy.mjs";import{defaultSpawner as F}from"../packem_shared/createRecordingSpawner-Ch7zuQQE.mjs";import{execArgsFor as U,detectPackageManager as x}from"@lunora/config/cli";const P=async(r,a,t)=>{if(!h(p(r,"tsconfig.json")))return{warning:"no tsconfig.json found — skipping TypeScript type-check"};const o=U(x(r),"tsc",["--noEmit","-p","tsconfig.json"]),e=await a({args:o.args,command:o.command,cwd:r,stdoutToStderr:t==="json"});return e.code===0?{}:{error:`type errors: tsc --noEmit exited ${String(e.code)}`}},T=async(r,a)=>{if(r.healthUrl===void 0||r.healthUrl==="")return;const t=await b({baseUrl:r.healthUrl,fetchImpl:r.healthFetch});if(t.error===void 0){a.success(`verify: health probe ok (${t.url})`);return}return t.error},z=(r,a)=>{const{errorAdvisories:t,names:o,shouldBlock:e}=S(r,k(a));if(e)return`${t.length.toString()} ERROR-level ${t.length===1?"advisory":"advisories"} (${o.join(", ")}). Pass --no-strict-advisories to downgrade this to a warning and continue.`},C=(r,a,t,o)=>{if(a.length===0&&t.length===0)return r.success("verify: project is valid"),{code:0,errors:[],warnings:[],wranglerPath:o};if(t.length>0){r.warn("verify: warnings:");for(const e of t)r.warn(` - ${e}`)}if(a.length>0){r.error("verify: errors:");for(const e of a){r.error(` - ${e}`);const s=E(e);s!==void 0&&r.error(s)}return{code:1,error:a[0],errors:a,warnings:t,wranglerPath:o}}return r.success("verify: project is valid (with warnings)"),{code:0,errors:[],warnings:t,wranglerPath:o}},H=async r=>{const a=r.cwd??process.cwd(),{logger:t}=r,o=v({environment:r.env,projectRoot:a}),e=[...o.report.errors],s=[...o.report.warnings];try{const n=D(a,r.target);if(n.target===void 0){const c=n.error??"unknown deploy target";return t.error(c),{code:R.USAGE,error:c,errors:[c],warnings:[],wranglerPath:void 0}}const i=g({apiSpec:r.apiSpec,lazyFunctions:u(r.lazyFunctions),dryRun:!0,projectRoot:a,target:n.target,...y(a)}),l=w(i.platformDiagnostics,t);e.push(...l.errors),s.push(...l.warnings);const f=z(i.advisories,r);f!==void 0&&e.push(f);const m=$({allowDrift:r.allowSchemaDrift===!0,codegen:i,command:"verify",logger:t,readOnly:!0});m.blocked&&e.push(m.reason)}catch(n){const i=n instanceof Error?n.message:String(n);e.push(`codegen failed: ${i}`)}if(r.typecheck!==!1){const n=await P(a,r.spawner??F,r.format??"pretty");n.error!==void 0&&e.push(n.error),n.warning!==void 0&&s.push(n.warning)}const d=await T(r,t);return d!==void 0&&e.push(d),C(t,e,s,o.wranglerPath)},Q=A(async({cwd:r,format:a,logger:t,options:o})=>{const e=await H({allowSchemaDrift:o.allowSchemaDrift===!0,apiSpec:j(o.apiSpec),lazyFunctions:u(o.lazyFunctions),cwd:r,env:o.env,format:a,healthUrl:o.healthUrl,logger:t,strictAdvisories:o.strictAdvisories,target:o.target,typecheck:o.typecheck===!1?!1:void 0});return{code:e.code,data:{errors:e.errors,warnings:e.warnings,wranglerPath:e.wranglerPath},error:e.error}});export{Q as execute,H as runVerifyCommand};
@@ -1,43 +1 @@
1
- import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
2
- import { r as runAddCommand, b as runRegistryViewCommand, a as runBuildIndexCommand } from '../packem_shared/commands-B-gR09Z_.mjs';
3
-
4
- const execute = defineHandler(({ argument, cwd, logger, options }) => {
5
- const subcommand = argument[0];
6
- const names = argument.slice(1);
7
- if (subcommand === "add") {
8
- return runAddCommand({
9
- allowUnsafeSource: options.allowUnsafeSource === true,
10
- cwd,
11
- diff: options.diff === true,
12
- dryRun: options.dryRun === true,
13
- from: options.from,
14
- json: options.json === true,
15
- logger,
16
- names,
17
- overwrite: options.overwrite === true,
18
- ref: options.ref,
19
- source: options.source,
20
- yes: options.yes === true
21
- });
22
- }
23
- if (subcommand === "list") {
24
- return runAddCommand({ cwd, from: options.from, json: options.json === true, list: true, logger, names: [], ref: options.ref, source: options.source });
25
- }
26
- if (subcommand === "view") {
27
- return runRegistryViewCommand({
28
- allowUnsafeSource: options.allowUnsafeSource === true,
29
- from: options.from,
30
- logger,
31
- names,
32
- ref: options.ref,
33
- source: options.source
34
- });
35
- }
36
- if (subcommand === "build") {
37
- return runBuildIndexCommand({ check: options.check === true, from: options.from, logger, out: options.out });
38
- }
39
- logger.error("registry: unknown subcommand. Usage: lunora registry <add|list|view|build> [names…]");
40
- return { code: 1 };
41
- });
42
-
43
- export { execute };
1
+ import{readLiveDevServerState as c}from"@lunora/config";import{d as i}from"../packem_shared/command-CB4JM-Jl.mjs";import{o as a}from"../packem_shared/open-url-EnKy--w-.mjs";const n="http://127.0.0.1:6173",d="/__lunora",u=/\/$/u,l=r=>{const e=c(r);return e===void 0?n:e.studioUrl!==void 0?e.studioUrl:e.mode==="vite"?`${e.url.replace(u,"")}${d}`:n},m=async r=>{const e=l(r.cwd??process.cwd()),{logger:t}=r;t.info(`opening ${e}`);try{await a(e,{opener:r.opener})}catch(o){const s=o instanceof Error?o.message:String(o);return t.error(`view: failed to open URL: ${s}`),{code:1,url:e}}return{code:0,url:e}},v=i(({cwd:r,logger:e})=>m({cwd:r,logger:e}));export{v as execute,m as runViewCommand};
@@ -1,105 +1,7 @@
1
- import { existsSync, readFileSync, readdirSync, statSync, mkdirSync, writeFileSync } from 'node:fs';
2
- import { fileURLToPath } from 'node:url';
3
- import { AGENT_RULES_DIR, detectAgentRules, LUNORA_SKILL_NAMES } from '@lunora/config';
4
- import { join, relative, dirname } from '@visulima/path';
5
- import { d as defineHandler } from '../packem_shared/command-D3lB_4Az.mjs';
6
-
7
- const resolveBundledSkillsDirectory = (startDirectory = dirname(fileURLToPath(import.meta.url))) => {
8
- let directory = startDirectory;
9
- for (let index = 0; index < 6; index += 1) {
10
- const packageJson = join(directory, "package.json");
11
- if (existsSync(packageJson)) {
12
- try {
13
- const parsed = JSON.parse(readFileSync(packageJson, "utf8"));
14
- if (parsed.name === "@lunora/cli") {
15
- const skills = join(directory, "skills");
16
- return existsSync(skills) ? skills : void 0;
17
- }
18
- } catch {
19
- }
20
- }
21
- const parent = dirname(directory);
22
- if (parent === directory) {
23
- break;
24
- }
25
- directory = parent;
26
- }
27
- return void 0;
28
- };
29
- const listBundledSkills = (skillsDirectory) => readdirSync(skillsDirectory).filter((name) => {
30
- const directory = join(skillsDirectory, name);
31
- return statSync(directory).isDirectory() && existsSync(join(directory, "SKILL.md"));
32
- });
33
- const copySkill = (source, destination, overwrite) => {
34
- mkdirSync(destination, { recursive: true });
35
- let wrote = false;
36
- for (const entry of readdirSync(source)) {
37
- const from = join(source, entry);
38
- const to = join(destination, entry);
39
- if (statSync(from).isDirectory()) {
40
- wrote = copySkill(from, to, overwrite) || wrote;
41
- continue;
42
- }
43
- if (existsSync(to) && !overwrite) {
44
- continue;
45
- }
46
- writeFileSync(to, readFileSync(from));
47
- wrote = true;
48
- }
49
- return wrote;
50
- };
51
- const runRulesInstall = (options) => {
52
- const cwd = options.cwd ?? process.cwd();
53
- const overwrite = options.overwrite === true;
54
- const skillsDirectory = resolveBundledSkillsDirectory();
55
- if (skillsDirectory === void 0) {
56
- options.logger.error("rules: could not locate the bundled skills (is @lunora/cli installed correctly?).");
57
- return { code: 1, installed: [], skipped: [] };
58
- }
59
- const installed = [];
60
- const skipped = [];
61
- for (const name of listBundledSkills(skillsDirectory)) {
62
- const destination = join(cwd, AGENT_RULES_DIR, name);
63
- const wrote = copySkill(join(skillsDirectory, name), destination, overwrite);
64
- if (wrote) {
65
- installed.push(name);
66
- } else {
67
- skipped.push(name);
68
- }
69
- }
70
- const target = relative(cwd, join(cwd, AGENT_RULES_DIR)) || AGENT_RULES_DIR;
71
- if (installed.length > 0) {
72
- options.logger.success(`Installed ${String(installed.length)} Lunora skill(s) into ${target}/: ${installed.join(", ")}.`);
73
- }
74
- if (skipped.length > 0) {
75
- options.logger.info(`Skipped ${String(skipped.length)} existing skill(s) (re-run with --overwrite to replace): ${skipped.join(", ")}.`);
76
- }
77
- options.logger.info("Your AI coding agent will pick these up automatically. Start with the `lunora` skill.");
78
- return { code: 0, installed, skipped };
79
- };
80
- const runRulesCheck = (options) => {
81
- const cwd = options.cwd ?? process.cwd();
82
- const status = detectAgentRules(cwd);
83
- if (status.installed) {
84
- options.logger.success(`Lunora agent rules are installed (${String(status.present.length)}/${String(LUNORA_SKILL_NAMES.length)} skills).`);
85
- if (status.missing.length > 0) {
86
- options.logger.info(`Missing: ${status.missing.join(", ")}. Run \`lunora rules install\` to add them.`);
87
- }
88
- return { code: 0, installed: status.present, skipped: [] };
89
- }
90
- options.logger.warn("Lunora agent rules are not installed. Run `lunora rules install` so your AI agent knows how to use Lunora.");
91
- return { code: options.strict === true ? 1 : 0, installed: status.present, skipped: [] };
92
- };
93
- const execute = defineHandler(({ argument, cwd, logger, options }) => {
94
- const subcommand = argument[0] ?? "check";
95
- if (subcommand === "install") {
96
- return runRulesInstall({ cwd, logger, overwrite: options.overwrite === true });
97
- }
98
- if (subcommand === "check") {
99
- return runRulesCheck({ cwd, logger, strict: options.strict === true });
100
- }
101
- logger.error("rules: unknown subcommand. Usage: lunora rules <install|check>");
102
- return { code: 1 };
103
- });
104
-
105
- export { execute, resolveBundledSkillsDirectory, runRulesCheck, runRulesInstall };
1
+ import{writeFileSync as h,existsSync as S,readFileSync as p}from"node:fs";import{isAbsolute as v,join as w}from"node:path";import{byCodepoint as b,scoreAdvisor as y,parseAdvisorMap as x,compareToBaseline as j}from"@lunora/advisor";import{runCodegen as A}from"@lunora/codegen";import{resolveLazyFunctions as M}from"@lunora/config";import{wranglerCodegenInputs as F}from"@lunora/config/cloudflare";import{d as D}from"../packem_shared/command-CB4JM-Jl.mjs";import{EXIT_CODE as E}from"../packem_shared/EXIT_CODE-D_XCixv8.mjs";import{D as u}from"../packem_shared/cli-BbgDNGew.mjs";const l={clean:"·",exempt:"–",failing:"✗",warned:"!"},d=(e,r)=>e.length>=r?e:e+" ".repeat(r-e.length),R=e=>`${e.id} (${e.visibility} ${e.kind})`,f=e=>{let r=0;for(const n of e)r=Math.max(r,n.id.length);return r},g=(e,r)=>` ${d(String(e.score),3)} ${l[e.coverage]} ${d(e.id,r)} ${e.visibility} ${e.kind}`,k=e=>{if(!e.comparable)return[` baseline not comparable (${e.reason}) — regenerate it; this run cannot verify anything`];if(!e.regressed)return[` no regression against baseline (score ${e.scoreDelta>=0?"+":""}${String(e.scoreDelta)})`];const r=[` REGRESSED against baseline (score ${e.scoreDelta>=0?"+":""}${String(e.scoreDelta)})`];for(const n of e.dropped)r.push(` ${n.id}: ${String(n.before)} → ${String(n.after)}`);for(const n of e.newFailing)r.push(` ${n}: now failing`);for(const n of e.worsened)r.push(` ${n}: more findings than the baseline`);return e.projectRegressed&&r.push(" project: new schema/config rules fired"),r},C=(e,r)=>{const n=e.procedures.filter(i=>i.coverage!=="clean"&&i.coverage!=="exempt"),t=f(n),o=[`advisor health ${String(e.score)}/100 — ${e.grade}`,` ${String(e.summary.clean)} clean · ${String(e.summary.warned)} warned · ${String(e.summary.failing)} failing · ${String(e.summary.exempt)} exempt (${String(e.summary.procedures)} procedures, ${String(e.summary.rulesFired)} rules fired)`];return e.project.checks.length>0&&o.push("",` project ${String(e.project.score)}/100 — ${e.project.checks.map(i=>i.name).join(", ")}`),n.length>0&&o.push("",...n.map(i=>g(i,t)),""," run with --all for every procedure, or --entry <file#export> for one"),r!==void 0&&o.push("",...k(r)),o.join(`
2
+ `)},T=e=>e.coverage==="exempt"?[` exempt: ${e.exemptReason===void 0||e.exemptReason===""?"no reason given":e.exemptReason}`]:e.checks.map(r=>{const n=r.occurrences>1?`, ×${String(r.occurrences)}`:"";return` ${r.name} (−${String(r.weight)}${n})`}),B=e=>{const r=new Map;for(const n of e){const t=r.get(n.file);t===void 0?r.set(n.file,[n]):t.push(n)}return[...r].toSorted(([n],[t])=>b(n,t))},I=e=>{const r=f(e.procedures),n=[`advisor health ${String(e.score)}/100 — ${e.grade}`,"",` legend: ${l.clean} clean ${l.warned} warned ${l.failing} failing ${l.exempt} exempt`];for(const[t,o]of B(e.procedures)){n.push("",` ${t}`);for(const i of o)n.push(g(i,r),...T(i))}return n.join(`
3
+ `)},L=(e,r)=>{const n=e.procedures.find(o=>o.id===r);if(n===void 0){const o=e.procedures.slice(0,10).map(i=>` ${i.id}`);return[`no procedure ${r} in the map. Known ids:`,...o,e.procedures.length>10?" …":""].filter(Boolean).join(`
4
+ `)}const t=[`${R(n)} — ${String(n.score)}/100, ${n.coverage}`,` weight in the global mean: ${String(n.weight)}`];if(n.checks.length===0)return t.push(""," no rule fired"),t.join(`
5
+ `);t.push(""," rules fired:");for(const o of n.checks)t.push(` [${o.level}] ${o.name} −${String(o.weight)}${o.occurrences>1?` (×${String(o.occurrences)})`:""}`);return t.join(`
6
+ `)},N=new Date(0).toISOString(),m=(e,r)=>v(r)?r:w(e,r),P=e=>{if(e===void 0)return{value:void 0};if(e===null||e==="")return{error:"--min-score needs a value between 0 and 100"};const r=Number(e);return Number.isFinite(r)&&r>=0&&r<=100?{value:r}:{error:"--min-score must be a number between 0 and 100"}},_=(e,r,n)=>{const t=m(r,n===null||n===""?u:n);if(!S(t))return{error:`baseline not found at ${t} — generate one with \`lunora advisor\` and commit it`};const o=x(JSON.parse(p(t,"utf8")));return o===void 0?{error:`baseline at ${t} is malformed — regenerate it with \`lunora advisor\``}:{comparison:j(e,o)}},z=e=>`baseline is not comparable (${e}) — regenerate it; this run verified nothing`,G=(e,r,n)=>r.entry!==void 0?L(e,r.entry):r.all===!0?I(e):C(e,n),H=e=>{const r=e.cwd??process.cwd(),n=e.format==="json",{logger:t}=e,o=P(e.minScore);if("error"in o)return e.logger.error(o.error),{code:E.USAGE,error:o.error};const{advisorContext:i,advisories:$}=A({dryRun:!0,lazyFunctions:M(),projectRoot:r,...F(r)}),a=y(i?.procedureProtections??[],$,{generatedAt:e.generatedAt??N}),s={map:a};if(e.baseline!==void 0){const c=_(a,r,e.baseline);if("error"in c)return e.logger.error(c.error),{...s,error:c.error};s.comparison=c.comparison,c.comparison.comparable||e.logger.error(z(c.comparison.reason))}if(e.write!==!1){const c=m(r,e.out??u);h(c,`${JSON.stringify(a,void 0,4)}
7
+ `,"utf8"),s.written=c}return s.belowMinScore=o.value!==void 0&&a.score<o.value,s.belowMinScore&&t.error(`advisor score ${String(a.score)} is below the required ${String(o.value)}`),n||(t.info(G(a,e,s.comparison)),s.written!==void 0&&t.success(`wrote ${s.written}`)),s},J=e=>e.error!==void 0||e.belowMinScore===!0?!0:e.comparison!==void 0&&(!e.comparison.comparable||e.comparison.regressed),Z=D(({cwd:e,format:r,logger:n,options:t})=>{const o=H({all:t.all,baseline:t.baseline,cwd:e,entry:t.entry,format:r,logger:n,minScore:t.minScore,out:t.out,write:t.write});return{code:o.code??(J(o)?1:0),data:{belowMinScore:o.belowMinScore,comparison:o.comparison,map:o.map,written:o.written},error:o.error}});export{Z as execute,H as runAdvisorCommand};