@limno/core 0.1.10 → 0.1.12

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
@@ -297,6 +297,11 @@ async function uncommitted(root, files) {
297
297
  const top = (await git(root, ["rev-parse", "--show-toplevel"])).out.trim();
298
298
  return files.filter((f) => dirty.has(top ? import_node_path2.default.relative(top, import_node_path2.default.join(root, f)) : f) || dirty.has(f));
299
299
  }
300
+ async function committedSince(root, files, since) {
301
+ if (!files.length) return false;
302
+ const r = await git(root, ["log", `--since=${Math.floor(since / 1e3)}`, "--format=%h", "--", ...files]);
303
+ return r.code === 0 && r.out.trim().length > 0;
304
+ }
300
305
  async function commitFiles(root, files, message) {
301
306
  if (!await isGitRepo(root)) return { ok: false, error: "This project isn\u2019t a git repository." };
302
307
  for (const marker of ["MERGE_HEAD", "rebase-merge", "rebase-apply", "CHERRY_PICK_HEAD"]) {
@@ -314,6 +319,10 @@ async function commitFiles(root, files, message) {
314
319
  }
315
320
 
316
321
  // src/runner.ts
322
+ var fullMessage = (text) => {
323
+ const t = String(text).trim().replace(/\n{3,}/g, "\n\n");
324
+ return t.length > 4e3 ? `${t.slice(0, 3999).trimEnd()}\u2026` : t;
325
+ };
317
326
  var NAMES = { claude: "Claude Code", codex: "Codex" };
318
327
  var SIGN_IN = { claude: "claude auth login", codex: "codex login" };
319
328
  var PROMPT = [
@@ -321,7 +330,9 @@ var PROMPT = [
321
330
  "Call limno_get_changes to read the visual changes and comments waiting for you, then implement them in this project's source by following the rules it gives you.",
322
331
  "Report progress with limno_update_status, and answer comments with limno_reply.",
323
332
  "Only read and edit files inside this project. Don't run shell commands; Limno checks the result on the page itself.",
324
- "Finish with one short sentence summarising what you changed."
333
+ "Finish with a summary the designer reads in Limno, at most two short sentences and 45 words in total:",
334
+ "first what you changed (or why you changed nothing); then, only if needed, what they must know or decide, as a direct question when it is one.",
335
+ "No file paths, no lists, nothing they already know from the change itself."
325
336
  ].join(" ");
326
337
  var trustFile = () => import_node_path3.default.join(import_node_os.default.homedir(), ".limno", "trust.json");
327
338
  function projectKey(root) {
@@ -557,7 +568,7 @@ function createRunner(root, folder, onState) {
557
568
  else if (name === "Edit" || name === "MultiEdit" || name === "Write") log({ kind: "edit", text: `Editing ${rel(input.file_path)}`, file: rel(input.file_path) });
558
569
  else if (name === "Glob" || name === "Grep") log({ kind: "search", text: "Searching the project" });
559
570
  } else if (block.type === "text" && String(block.text).trim()) {
560
- log({ kind: "message", text: String(block.text).trim().split("\n")[0].slice(0, 220) });
571
+ log({ kind: "message", text: fullMessage(block.text) });
561
572
  }
562
573
  }
563
574
  return;
@@ -578,7 +589,7 @@ function createRunner(root, folder, onState) {
578
589
  else if (item.type === "file_change" && e.type === "item.completed") {
579
590
  for (const c of item.changes ?? []) log({ kind: "edit", text: `Editing ${rel(c.path)}`, file: rel(c.path) });
580
591
  } else if (item.type === "agent_message" && e.type === "item.completed" && item.text) {
581
- log({ kind: "message", text: String(item.text).trim().split("\n")[0].slice(0, 220) });
592
+ log({ kind: "message", text: fullMessage(item.text) });
582
593
  } else if (item.type === "command_execution" && e.type === "item.started") {
583
594
  log({ kind: "search", text: "Looking through the project" });
584
595
  }
@@ -702,7 +713,9 @@ function createRunner(root, folder, onState) {
702
713
  return {
703
714
  async info(force) {
704
715
  if (state.commit && !state.commit.committed && state.commit.uncommitted.length && !child) {
705
- state.commit = { ...state.commit, uncommitted: await uncommitted(root, state.files) };
716
+ const left = await uncommitted(root, state.files);
717
+ const undone = !left.length && !await committedSince(root, state.files, state.startedAt ?? 0);
718
+ state.commit = { ...state.commit, uncommitted: left, undone };
706
719
  }
707
720
  return { agents: await detectAgents(force), allowed: allowed(), autoCommit: autoCommitOn(), state };
708
721
  },
package/dist/index.d.cts CHANGED
@@ -117,6 +117,8 @@ interface RunCommit {
117
117
  };
118
118
  /** Why an auto-commit didn't happen. */
119
119
  note?: string;
120
+ /** No longer changed and never committed: the edits were undone (reverted or discarded). */
121
+ undone?: boolean;
120
122
  }
121
123
  interface RunnerInfo {
122
124
  agents: RunnerAgent[];
package/dist/index.d.ts CHANGED
@@ -117,6 +117,8 @@ interface RunCommit {
117
117
  };
118
118
  /** Why an auto-commit didn't happen. */
119
119
  note?: string;
120
+ /** No longer changed and never committed: the edits were undone (reverted or discarded). */
121
+ undone?: boolean;
120
122
  }
121
123
  interface RunnerInfo {
122
124
  agents: RunnerAgent[];
package/dist/index.js CHANGED
@@ -248,6 +248,11 @@ async function uncommitted(root, files) {
248
248
  const top = (await git(root, ["rev-parse", "--show-toplevel"])).out.trim();
249
249
  return files.filter((f) => dirty.has(top ? path2.relative(top, path2.join(root, f)) : f) || dirty.has(f));
250
250
  }
251
+ async function committedSince(root, files, since) {
252
+ if (!files.length) return false;
253
+ const r = await git(root, ["log", `--since=${Math.floor(since / 1e3)}`, "--format=%h", "--", ...files]);
254
+ return r.code === 0 && r.out.trim().length > 0;
255
+ }
251
256
  async function commitFiles(root, files, message) {
252
257
  if (!await isGitRepo(root)) return { ok: false, error: "This project isn\u2019t a git repository." };
253
258
  for (const marker of ["MERGE_HEAD", "rebase-merge", "rebase-apply", "CHERRY_PICK_HEAD"]) {
@@ -265,6 +270,10 @@ async function commitFiles(root, files, message) {
265
270
  }
266
271
 
267
272
  // src/runner.ts
273
+ var fullMessage = (text) => {
274
+ const t = String(text).trim().replace(/\n{3,}/g, "\n\n");
275
+ return t.length > 4e3 ? `${t.slice(0, 3999).trimEnd()}\u2026` : t;
276
+ };
268
277
  var NAMES = { claude: "Claude Code", codex: "Codex" };
269
278
  var SIGN_IN = { claude: "claude auth login", codex: "codex login" };
270
279
  var PROMPT = [
@@ -272,7 +281,9 @@ var PROMPT = [
272
281
  "Call limno_get_changes to read the visual changes and comments waiting for you, then implement them in this project's source by following the rules it gives you.",
273
282
  "Report progress with limno_update_status, and answer comments with limno_reply.",
274
283
  "Only read and edit files inside this project. Don't run shell commands; Limno checks the result on the page itself.",
275
- "Finish with one short sentence summarising what you changed."
284
+ "Finish with a summary the designer reads in Limno, at most two short sentences and 45 words in total:",
285
+ "first what you changed (or why you changed nothing); then, only if needed, what they must know or decide, as a direct question when it is one.",
286
+ "No file paths, no lists, nothing they already know from the change itself."
276
287
  ].join(" ");
277
288
  var trustFile = () => path3.join(os.homedir(), ".limno", "trust.json");
278
289
  function projectKey(root) {
@@ -508,7 +519,7 @@ function createRunner(root, folder, onState) {
508
519
  else if (name === "Edit" || name === "MultiEdit" || name === "Write") log({ kind: "edit", text: `Editing ${rel(input.file_path)}`, file: rel(input.file_path) });
509
520
  else if (name === "Glob" || name === "Grep") log({ kind: "search", text: "Searching the project" });
510
521
  } else if (block.type === "text" && String(block.text).trim()) {
511
- log({ kind: "message", text: String(block.text).trim().split("\n")[0].slice(0, 220) });
522
+ log({ kind: "message", text: fullMessage(block.text) });
512
523
  }
513
524
  }
514
525
  return;
@@ -529,7 +540,7 @@ function createRunner(root, folder, onState) {
529
540
  else if (item.type === "file_change" && e.type === "item.completed") {
530
541
  for (const c of item.changes ?? []) log({ kind: "edit", text: `Editing ${rel(c.path)}`, file: rel(c.path) });
531
542
  } else if (item.type === "agent_message" && e.type === "item.completed" && item.text) {
532
- log({ kind: "message", text: String(item.text).trim().split("\n")[0].slice(0, 220) });
543
+ log({ kind: "message", text: fullMessage(item.text) });
533
544
  } else if (item.type === "command_execution" && e.type === "item.started") {
534
545
  log({ kind: "search", text: "Looking through the project" });
535
546
  }
@@ -653,7 +664,9 @@ function createRunner(root, folder, onState) {
653
664
  return {
654
665
  async info(force) {
655
666
  if (state.commit && !state.commit.committed && state.commit.uncommitted.length && !child) {
656
- state.commit = { ...state.commit, uncommitted: await uncommitted(root, state.files) };
667
+ const left = await uncommitted(root, state.files);
668
+ const undone = !left.length && !await committedSince(root, state.files, state.startedAt ?? 0);
669
+ state.commit = { ...state.commit, uncommitted: left, undone };
657
670
  }
658
671
  return { agents: await detectAgents(force), allowed: allowed(), autoCommit: autoCommitOn(), state };
659
672
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@limno/core",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Limno's framework-neutral dev tooling: JSX source stamping, the change-set store and the endpoints the editor talks to.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "type": "module",
@@ -17,12 +17,7 @@
17
17
  "files": [
18
18
  "dist"
19
19
  ],
20
- "repository": {
21
- "type": "git",
22
- "url": "git+https://github.com/armie3/limno.git",
23
- "directory": "packages/core"
24
- },
25
- "homepage": "https://github.com/armie3/limno#readme",
20
+ "homepage": "https://limno.dev",
26
21
  "keywords": [
27
22
  "limno",
28
23
  "design",
@@ -42,9 +37,9 @@
42
37
  "dependencies": {
43
38
  "@babel/parser": "^7.29.0",
44
39
  "@babel/traverse": "^7.29.0",
45
- "@limno/mcp": "0.1.4",
46
- "@limno/overlay": "0.1.10",
47
- "@limno/spec": "0.1.4",
40
+ "@limno/mcp": "0.1.6",
41
+ "@limno/overlay": "0.1.12",
42
+ "@limno/spec": "0.1.6",
48
43
  "launch-editor": "^2.14.1",
49
44
  "magic-string": "^0.30.17"
50
45
  },