idea-manager 2.2.0 → 2.3.1

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 (68) hide show
  1. package/.next/build-manifest.json +2 -2
  2. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  3. package/.next/server/app/_global-error.html +2 -2
  4. package/.next/server/app/_global-error.rsc +1 -1
  5. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  6. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  7. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  12. package/.next/server/app/_not-found.html +2 -2
  13. package/.next/server/app/_not-found.rsc +1 -1
  14. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  15. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  16. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  20. package/.next/server/app/api/advisor-actions/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/archive/route_client-reference-manifest.js +1 -1
  22. package/.next/server/app/api/filesystem/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/filesystem/tree/route_client-reference-manifest.js +1 -1
  24. package/.next/server/app/api/global-advisor/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/global-memo/route_client-reference-manifest.js +1 -1
  26. package/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
  27. package/.next/server/app/api/maintenance/route_client-reference-manifest.js +1 -1
  28. package/.next/server/app/api/projects/[id]/advisor/route_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/projects/[id]/apply-distribute/route_client-reference-manifest.js +1 -1
  30. package/.next/server/app/api/projects/[id]/auto-distribute/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/projects/[id]/brainstorm/route_client-reference-manifest.js +1 -1
  32. package/.next/server/app/api/projects/[id]/git-sync/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/projects/[id]/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/projects/[id]/sub-projects/[subId]/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/projects/[id]/sub-projects/[subId]/tasks/[taskId]/chat/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/projects/[id]/sub-projects/[subId]/tasks/[taskId]/prompt/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/projects/[id]/sub-projects/[subId]/tasks/[taskId]/refine/route_client-reference-manifest.js +1 -1
  38. package/.next/server/app/api/projects/[id]/sub-projects/[subId]/tasks/[taskId]/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/api/projects/[id]/sub-projects/[subId]/tasks/reorder/route_client-reference-manifest.js +1 -1
  40. package/.next/server/app/api/projects/[id]/sub-projects/[subId]/tasks/route_client-reference-manifest.js +1 -1
  41. package/.next/server/app/api/projects/[id]/sub-projects/route_client-reference-manifest.js +1 -1
  42. package/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  43. package/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
  44. package/.next/server/app/api/sync/route_client-reference-manifest.js +1 -1
  45. package/.next/server/app/api/tasks/[taskId]/move/route_client-reference-manifest.js +1 -1
  46. package/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  47. package/.next/server/app/api/version/route_client-reference-manifest.js +1 -1
  48. package/.next/server/app/index.html +2 -2
  49. package/.next/server/app/index.rsc +2 -2
  50. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  51. package/.next/server/app/index.segments/_full.segment.rsc +2 -2
  52. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  53. package/.next/server/app/index.segments/_index.segment.rsc +1 -1
  54. package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  55. package/.next/server/app/page.js +7 -7
  56. package/.next/server/app/page_client-reference-manifest.js +1 -1
  57. package/.next/server/app/projects/[id]/page_client-reference-manifest.js +1 -1
  58. package/.next/server/app-paths-manifest.json +10 -10
  59. package/.next/server/pages/404.html +2 -2
  60. package/.next/server/pages/500.html +2 -2
  61. package/.next/static/chunks/app/{page-92e516361aff0ece.js → page-a0491c7ecdd773ca.js} +9 -9
  62. package/package.json +1 -1
  63. package/src/cli.ts +3 -3
  64. package/src/components/dashboard/DashboardPanel.tsx +13 -0
  65. package/src/components/memo/GlobalMemoLayer.tsx +15 -0
  66. package/src/components/task/NoteEditor.tsx +63 -2
  67. /package/.next/static/{hhAzw58XbAFfL_Ly5sk13 → cNwwQZS0Jhwz2yyh3ks6E}/_buildManifest.js +0 -0
  68. /package/.next/static/{hhAzw58XbAFfL_Ly5sk13 → cNwwQZS0Jhwz2yyh3ks6E}/_ssgManifest.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "idea-manager",
3
- "version": "2.2.0",
3
+ "version": "2.3.1",
4
4
  "description": "AI-powered idea & task manager for developers. Brainstorm → structured tasks → AI agent execution. CodeMirror editor with slash commands, MCP Server, Claude/Gemini/Codex support. Local-first SQLite, cross-PC Git sync.",
5
5
  "keywords": [
6
6
  "idea-manager",
package/src/cli.ts CHANGED
@@ -136,9 +136,9 @@ program
136
136
  nextCli = path.join(PKG_ROOT, 'node_modules', 'next', 'dist', 'bin', 'next');
137
137
  }
138
138
 
139
- // Build if not already built
140
- const buildDir = path.join(PKG_ROOT, '.next');
141
- if (!fs.existsSync(buildDir)) {
139
+ // Build if not already built (check BUILD_ID, not just .next dir existence)
140
+ const buildMarker = path.join(PKG_ROOT, '.next', 'BUILD_ID');
141
+ if (!fs.existsSync(buildMarker)) {
142
142
  console.log('\n IM - First run: building... (this may take a minute)\n');
143
143
  const buildResult = spawn(process.execPath, [nextCli, 'build'], {
144
144
  cwd: PKG_ROOT,
@@ -96,6 +96,17 @@ export default function DashboardPanel() {
96
96
  if (savedTab) setTab(savedTab);
97
97
  }, [fetchData]);
98
98
 
99
+ // Sync memo when another instance (⌘M layer) saves
100
+ useEffect(() => {
101
+ const onSync = () => {
102
+ fetch('/api/global-memo').then(r => r.ok ? r.json() : null)
103
+ .then(d => { if (d?.content !== undefined) setMemoContent(d.content); })
104
+ .catch(() => {});
105
+ };
106
+ window.addEventListener('global-memo-updated', onSync);
107
+ return () => window.removeEventListener('global-memo-updated', onSync);
108
+ }, []);
109
+
99
110
  const handleMemoChange = (value: string) => {
100
111
  setMemoContent(value);
101
112
  if (memoSaveTimer.current) clearTimeout(memoSaveTimer.current);
@@ -104,6 +115,8 @@ export default function DashboardPanel() {
104
115
  method: 'PUT',
105
116
  headers: { 'Content-Type': 'application/json' },
106
117
  body: JSON.stringify({ content: value }),
118
+ }).then(() => {
119
+ window.dispatchEvent(new Event('global-memo-updated'));
107
120
  });
108
121
  }, 500);
109
122
  };
@@ -34,10 +34,25 @@ export default function GlobalMemoLayer() {
34
34
  method: 'PUT',
35
35
  headers: { 'Content-Type': 'application/json' },
36
36
  body: JSON.stringify({ content: value }),
37
+ }).then(() => {
38
+ window.dispatchEvent(new Event('global-memo-updated'));
37
39
  }).catch(() => {});
38
40
  }, 600);
39
41
  }, []);
40
42
 
43
+ // Sync when other memo instance saves
44
+ useEffect(() => {
45
+ const onSync = () => {
46
+ if (!open) return;
47
+ fetch('/api/global-memo')
48
+ .then(r => r.ok ? r.json() : null)
49
+ .then(d => { if (d?.content !== undefined) setContent(d.content); })
50
+ .catch(() => {});
51
+ };
52
+ window.addEventListener('global-memo-updated', onSync);
53
+ return () => window.removeEventListener('global-memo-updated', onSync);
54
+ }, [open]);
55
+
41
56
  const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
42
57
  const v = e.target.value;
43
58
  setContent(v);
@@ -3,12 +3,72 @@
3
3
  import { forwardRef, useMemo, useRef } from 'react';
4
4
  import CodeMirror, { type ReactCodeMirrorRef } from '@uiw/react-codemirror';
5
5
  import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
6
- import { EditorView, Decoration, keymap, ViewPlugin, WidgetType } from '@codemirror/view';
7
- import { EditorState, StateEffect, StateField, Prec } from '@codemirror/state';
6
+ import { EditorView, Decoration, keymap, ViewPlugin, WidgetType, type DecorationSet } from '@codemirror/view';
7
+ import { EditorState, StateEffect, StateField, Prec, RangeSetBuilder } from '@codemirror/state';
8
8
  import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
9
9
  import { autocompletion, type CompletionContext, type CompletionResult } from '@codemirror/autocomplete';
10
10
  import { tags as t } from '@lezer/highlight';
11
11
 
12
+ // ─────────────────────────────────────────────────────────────
13
+ // Arrow ligatures: visually replace -> => <- etc. with unicode
14
+ // arrows. The actual document text is unchanged.
15
+ // ─────────────────────────────────────────────────────────────
16
+ // Map of arrow text → unicode, longest patterns first to prevent partial matches.
17
+ const LIGATURE_MAP: Record<string, string> = {
18
+ '<-->': '⟷', '<=>': '⇔',
19
+ '-->': '⟶', '<--': '⟵', '==>': '⟹', '<==': '⟸', '<->': '↔',
20
+ '=>': '⇒', '->': '→', '<-': '←',
21
+ };
22
+ const LIGATURE_RE = new RegExp(
23
+ Object.keys(LIGATURE_MAP)
24
+ .sort((a, b) => b.length - a.length)
25
+ .map(k => k.replace(/[-<>=]/g, '\\$&'))
26
+ .join('|'),
27
+ 'g',
28
+ );
29
+
30
+ class LigatureWidget extends WidgetType {
31
+ constructor(public readonly ch: string) { super(); }
32
+ eq(other: LigatureWidget) { return other.ch === this.ch; }
33
+ toDOM() {
34
+ const span = document.createElement('span');
35
+ span.textContent = this.ch;
36
+ span.className = 'cm-ligature';
37
+ span.style.color = 'hsl(var(--primary))';
38
+ return span;
39
+ }
40
+ ignoreEvent() { return true; }
41
+ }
42
+
43
+ function buildLigatureDecorations(view: EditorView): DecorationSet {
44
+ const builder = new RangeSetBuilder<Decoration>();
45
+ const doc = view.state.doc;
46
+ for (let i = 1; i <= doc.lines; i++) {
47
+ const line = doc.line(i);
48
+ LIGATURE_RE.lastIndex = 0;
49
+ let m: RegExpExecArray | null;
50
+ while ((m = LIGATURE_RE.exec(line.text)) !== null) {
51
+ const ch = LIGATURE_MAP[m[0]];
52
+ if (!ch) continue;
53
+ const from = line.from + m.index;
54
+ const to = from + m[0].length;
55
+ builder.add(from, to, Decoration.replace({ widget: new LigatureWidget(ch) }));
56
+ }
57
+ }
58
+ return builder.finish();
59
+ }
60
+
61
+ const ligaturePlugin = ViewPlugin.fromClass(
62
+ class {
63
+ decorations: DecorationSet;
64
+ constructor(view: EditorView) { this.decorations = buildLigatureDecorations(view); }
65
+ update(u: { docChanged: boolean; view: EditorView }) {
66
+ if (u.docChanged) this.decorations = buildLigatureDecorations(u.view);
67
+ }
68
+ },
69
+ { decorations: (v) => v.decorations },
70
+ );
71
+
12
72
  // ─────────────────────────────────────────────────────────────
13
73
  // Ghost-text state: a decoration widget after the cursor.
14
74
  // ─────────────────────────────────────────────────────────────
@@ -451,6 +511,7 @@ const NoteEditor = forwardRef<ReactCodeMirrorRef, NoteEditorProps>(function Note
451
511
  const extensions = useMemo(() => [
452
512
  markdown({ base: markdownLanguage }),
453
513
  syntaxHighlighting(mdHighlight),
514
+ ligaturePlugin,
454
515
  autocompletion({
455
516
  override: [slashCompletion],
456
517
  defaultKeymap: true,