compact-agent 1.9.0 → 1.10.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.
package/dist/config.js CHANGED
@@ -26,6 +26,15 @@ const DEFAULT_CONFIG = {
26
26
  // Thinking / reasoning shown by default — gives users live "the model isn't
27
27
  // dead" feedback during long turns. Toggle off with /thinking.
28
28
  showThinking: true,
29
+ // MemPalace persistent memory. ON by default — it's a featured capability,
30
+ // zero overhead until something is written, and the agent only uses the
31
+ // tools when it sees a durable fact worth keeping. User can opt out during
32
+ // the setup wizard or anytime via /memory disable.
33
+ memory: {
34
+ enabled: true,
35
+ globalScope: true,
36
+ projectScope: true,
37
+ },
29
38
  // Voice / accessibility is OFF by default. ffmpeg is optional. Users opt in
30
39
  // via `/voice on` (and set the two API keys via `/voice config`). The
31
40
  // sub-blocks define what becomes active once enabled; this just primes them
@@ -113,7 +122,7 @@ function validateConfig(config) {
113
122
  config.permissionMode = 'ask';
114
123
  }
115
124
  // Warn on unexpected fields
116
- const expectedFields = new Set(['apiKey', 'baseURL', 'model', 'fallbackModel', 'provider', 'maxTokens', 'temperature', 'permissionMode', 'alwaysAllowedTools', 'dryRun', 'theme', 'palette', 'showThinking', 'voice']);
125
+ const expectedFields = new Set(['apiKey', 'baseURL', 'model', 'fallbackModel', 'provider', 'maxTokens', 'temperature', 'permissionMode', 'alwaysAllowedTools', 'dryRun', 'theme', 'palette', 'showThinking', 'voice', 'memory']);
117
126
  for (const key in config) {
118
127
  if (!expectedFields.has(key)) {
119
128
  console.warn(`Warning: Unexpected config field: ${key}`);
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -55,6 +55,8 @@ import { installEcc, getEccCommandPrompt, loadEccState, eccResourcesAvailable, r
55
55
  import { buildWalkthroughPrompt } from './walkthrough.js';
56
56
  // Stitch (Google's AI UI/UX design tool) — /stitch, /stitch-config, /stitch-tools
57
57
  import { buildStitchPrompt, buildStitchToolsPrompt, saveStitchConfig, printStitchStatus, stitchConfigured } from './stitch.js';
58
+ // MemPalace memory subsystem — wings/rooms/drawers/tunnels/KG, both global + project stores
59
+ import * as mempalace from './mempalace/index.js';
58
60
  // Voice / accessibility — built-in dictation (Whisper) + readout (ElevenLabs)
59
61
  import { printVoiceStatus, isVoiceEnabled, getTtsConfig, getSttConfig, getAccessibilityConfig, speak, dictateOnce, } from './voice.js';
60
62
  import { isFfmpegAvailable, audioCue, startRecording, probeMic, micProbeMessage } from './audio.js';
@@ -103,6 +105,16 @@ async function setupWizard(rl) {
103
105
  console.log(chalk.dim(' 3. yolo — approve everything (fastest)\n'));
104
106
  const permChoice = await rl.question(chalk.yellow(' Permission mode [1]: '));
105
107
  const permMode = ['ask', 'auto', 'yolo'][parseInt(permChoice || '1', 10) - 1] || 'ask';
108
+ // ── MemPalace memory setup ──────────────────────────────
109
+ // Featured capability, opt-out at setup time. Explain briefly so the
110
+ // user can make an informed choice — most users want this on.
111
+ console.log(chalk.white('\n MemPalace persistent memory'));
112
+ console.log(chalk.dim(' Lets the agent remember your preferences, codebase landmarks, and lessons across sessions.'));
113
+ console.log(chalk.dim(' Two stores: global (~/.crowcoder/memory) for cross-project facts, project (.crowcoder/memory'));
114
+ console.log(chalk.dim(' in each repo) for codebase-specific knowledge. Searchable via /memory or by the agent itself.'));
115
+ console.log(chalk.dim(' Zero external dependencies; storage is local JSON files. Can be toggled anytime via /memory disable.'));
116
+ const memoryChoice = await rl.question(chalk.yellow(' Enable MemPalace memory? [Y/n]: '));
117
+ const memoryEnabled = !(memoryChoice.trim().toLowerCase().startsWith('n'));
106
118
  const config = {
107
119
  apiKey,
108
120
  baseURL,
@@ -111,9 +123,21 @@ async function setupWizard(rl) {
111
123
  maxTokens: 8192,
112
124
  temperature: 0.3,
113
125
  permissionMode: permMode,
126
+ memory: {
127
+ enabled: memoryEnabled,
128
+ globalScope: true,
129
+ projectScope: true,
130
+ },
114
131
  };
115
132
  saveConfig(config);
116
- console.log(chalk.green(`\n Config saved to ${getConfigDir()}/config.json\n`));
133
+ console.log(chalk.green(`\n Config saved to ${getConfigDir()}/config.json`));
134
+ if (memoryEnabled) {
135
+ console.log(chalk.dim(` MemPalace: ENABLED — 7 memory_* tools available to the agent. Storage created on first write.`));
136
+ }
137
+ else {
138
+ console.log(chalk.dim(` MemPalace: disabled. Re-enable anytime with /memory enable.`));
139
+ }
140
+ console.log();
117
141
  return config;
118
142
  }
119
143
  /**
@@ -250,7 +274,7 @@ export function handleSlashCommand(input, config, messages, session, mode) {
250
274
  console.log(d(' ') + c('/evolve') + d(' — cluster instincts into reusable skills'));
251
275
  console.log(d(' ') + c('/prune') + d(' — delete expired instincts'));
252
276
  console.log(d(' ') + c('/skills') + d(' — list learned skills'));
253
- console.log(d(' ') + c('/memory') + d(' show memory status'));
277
+ console.log(d(' ') + c('/memory [sub]') + d(' MemPalace: status, enable/disable, wings, rooms, ls, search <q>, get <id>, rm <id>'));
254
278
  console.log(d(' ') + c('/users') + d(' — manage users table'));
255
279
  console.log(d(' ') + c('/count [inc|dec|reset]') + d(' — increment/decrement/reset counter'));
256
280
  console.log(d(' ') + c('/detect') + d(' — detect package manager, test runner, build tool'));
@@ -786,9 +810,151 @@ export function handleSlashCommand(input, config, messages, session, mode) {
786
810
  case '/skills':
787
811
  printSkillList();
788
812
  return { handled: true };
789
- case '/memory':
790
- printMemoryStatus();
791
- return { handled: true };
813
+ // /memory <sub> — MemPalace inventory & inspection.
814
+ // /memory status + counts (legacy + new combined)
815
+ // /memory wings list wings in both stores
816
+ // /memory rooms <wing> rooms within a wing
817
+ // /memory ls <w> <r> drawers in a wing/room
818
+ // /memory search <q> text search (same backend as memory_search tool)
819
+ // /memory get <id> full content of a single drawer
820
+ // /memory rm <id> delete a drawer (cascades tunnels + triples)
821
+ // /memory stats storage + counts per scope
822
+ case '/memory': {
823
+ const parts = args.trim().split(/\s+/).filter(Boolean);
824
+ const sub = (parts[0] || '').toLowerCase();
825
+ try {
826
+ // Enable / disable — affects whether the memory_* tools are
827
+ // registered for the model on next REPL boot. Existing data is
828
+ // preserved either way; toggling never deletes anything.
829
+ if (sub === 'enable' || sub === 'on') {
830
+ config.memory = { ...(config.memory || {}), enabled: true };
831
+ saveConfig(config);
832
+ console.log(chalk.green(' MemPalace: ENABLED.'));
833
+ console.log(chalk.dim(' Restart the REPL for the memory_* tools to appear in the agent\'s registry.'));
834
+ return { handled: true };
835
+ }
836
+ if (sub === 'disable' || sub === 'off') {
837
+ config.memory = { ...(config.memory || {}), enabled: false };
838
+ saveConfig(config);
839
+ console.log(chalk.green(' MemPalace: disabled.'));
840
+ console.log(chalk.dim(' Existing drawers/tunnels/triples preserved. Restart the REPL to remove memory_* tools from the agent.'));
841
+ return { handled: true };
842
+ }
843
+ const enabled = config.memory?.enabled !== false;
844
+ if (!sub || sub === 'status' || sub === 'stats') {
845
+ const s = mempalace.stats(process.cwd());
846
+ console.log(chalk.cyan('\n MemPalace status'));
847
+ console.log(chalk.dim(` enabled: ${enabled ? '✓ yes' : '✗ no (toggle with /memory enable)'}`));
848
+ console.log(chalk.dim(` global ${s.globalPath}`));
849
+ console.log(chalk.dim(` ${s.global.drawers} drawer(s) · ${s.global.wings} wing(s) · ${s.global.rooms} room(s) · ${s.global.tunnels} tunnel(s) · ${s.global.triples} fact(s)`));
850
+ console.log(chalk.dim(` project ${s.projectPath}${s.projectExists ? '' : ' (not yet created)'}`));
851
+ console.log(chalk.dim(` ${s.project.drawers} drawer(s) · ${s.project.wings} wing(s) · ${s.project.rooms} room(s) · ${s.project.tunnels} tunnel(s) · ${s.project.triples} fact(s)`));
852
+ console.log();
853
+ printMemoryStatus();
854
+ return { handled: true };
855
+ }
856
+ if (sub === 'wings') {
857
+ const w = mempalace.listWings(process.cwd());
858
+ console.log(chalk.cyan('\n Wings:'));
859
+ if (w.global.length === 0 && w.project.length === 0) {
860
+ console.log(chalk.dim(' (none yet — agent will create wings as it learns)'));
861
+ }
862
+ for (const wm of w.global)
863
+ console.log(chalk.dim(` global · ${wm.name.padEnd(20)} ${wm.drawerCount} drawer(s)`));
864
+ for (const wm of w.project)
865
+ console.log(chalk.dim(` project · ${wm.name.padEnd(19)} ${wm.drawerCount} drawer(s)`));
866
+ console.log();
867
+ return { handled: true };
868
+ }
869
+ if (sub === 'rooms') {
870
+ const r = mempalace.listRooms(process.cwd(), parts[1]);
871
+ const all = [...r.global.map((m) => ({ ...m, s: 'global' })), ...r.project.map((m) => ({ ...m, s: 'project' }))];
872
+ if (all.length === 0) {
873
+ console.log(chalk.dim(` No rooms${parts[1] ? ' in wing ' + parts[1] : ''}.`));
874
+ return { handled: true };
875
+ }
876
+ console.log(chalk.cyan(`\n Rooms${parts[1] ? ' in ' + parts[1] : ''}:`));
877
+ for (const m of all)
878
+ console.log(chalk.dim(` ${m.s.padEnd(7)} ${m.wing}/${m.name} — ${m.drawerCount} drawer(s), last ${m.lastTouched.slice(0, 10)}`));
879
+ console.log();
880
+ return { handled: true };
881
+ }
882
+ if (sub === 'ls' || sub === 'list') {
883
+ const drawers = mempalace.listDrawers({ wing: parts[1], room: parts[2], cwd: process.cwd() });
884
+ if (drawers.length === 0) {
885
+ console.log(chalk.dim(' No drawers match.'));
886
+ return { handled: true };
887
+ }
888
+ console.log(chalk.cyan(`\n Drawers (${drawers.length}):`));
889
+ for (const d of drawers.slice(0, 50)) {
890
+ const excerpt = d.content.length > 90 ? d.content.slice(0, 90) + '…' : d.content;
891
+ console.log(chalk.dim(` ${d.id} (${d.scope}) ${d.wing}/${d.room}: `) + chalk.white(excerpt));
892
+ }
893
+ if (drawers.length > 50)
894
+ console.log(chalk.dim(` … and ${drawers.length - 50} more`));
895
+ console.log();
896
+ return { handled: true };
897
+ }
898
+ if (sub === 'search') {
899
+ const q = parts.slice(1).join(' ');
900
+ if (!q) {
901
+ console.log(chalk.yellow(' Usage: /memory search <query>'));
902
+ return { handled: true };
903
+ }
904
+ const hits = mempalace.search(q, process.cwd(), { limit: 10 });
905
+ if (hits.length === 0) {
906
+ console.log(chalk.dim(` No matches for "${q}".`));
907
+ return { handled: true };
908
+ }
909
+ console.log(chalk.cyan(`\n ${hits.length} match(es) for "${q}":`));
910
+ for (const h of hits) {
911
+ const excerpt = h.drawer.content.length > 200 ? h.drawer.content.slice(0, 200) + '…' : h.drawer.content;
912
+ const tagStr = h.drawer.tags.length > 0 ? ` [${h.drawer.tags.join(', ')}]` : '';
913
+ console.log(chalk.dim(` ${h.drawer.id} (${h.drawer.scope} · ${h.drawer.wing}/${h.drawer.room}${tagStr}) score ${h.score.toFixed(2)}`));
914
+ console.log(chalk.white(` ${excerpt}`));
915
+ }
916
+ console.log();
917
+ return { handled: true };
918
+ }
919
+ if (sub === 'get' || sub === 'recall') {
920
+ const id = parts[1];
921
+ if (!id) {
922
+ console.log(chalk.yellow(' Usage: /memory get <drawer-id>'));
923
+ return { handled: true };
924
+ }
925
+ const d = mempalace.getDrawer(id, process.cwd());
926
+ if (!d) {
927
+ console.log(chalk.yellow(` No drawer ${id}.`));
928
+ return { handled: true };
929
+ }
930
+ const tagStr = d.tags.length > 0 ? ` [${d.tags.join(', ')}]` : '';
931
+ console.log(chalk.cyan(`\n ${d.id} (${d.scope} · ${d.wing}/${d.room}${tagStr})`));
932
+ console.log(chalk.dim(` importance ${d.importance} · created ${d.createdAt} · updated ${d.updatedAt}\n`));
933
+ console.log(d.content);
934
+ console.log();
935
+ return { handled: true };
936
+ }
937
+ if (sub === 'rm' || sub === 'delete') {
938
+ const id = parts[1];
939
+ if (!id) {
940
+ console.log(chalk.yellow(' Usage: /memory rm <drawer-id>'));
941
+ return { handled: true };
942
+ }
943
+ // Try both stores; whichever owns it returns true
944
+ const removed = mempalace.getGlobalStore().deleteDrawer(id)
945
+ || mempalace.getProjectStore(process.cwd()).deleteDrawer(id);
946
+ console.log(removed ? chalk.green(` Deleted drawer ${id} (cascaded tunnels + triples).`) : chalk.yellow(` No drawer ${id}.`));
947
+ return { handled: true };
948
+ }
949
+ console.log(chalk.yellow(` Unknown /memory subcommand: ${sub}`));
950
+ console.log(chalk.dim(' Try: /memory (status), wings, rooms <wing>, ls <wing> <room>, search <q>, get <id>, rm <id>'));
951
+ return { handled: true };
952
+ }
953
+ catch (e) {
954
+ console.log(chalk.red(` /memory failed: ${e instanceof Error ? e.message : e}`));
955
+ return { handled: true };
956
+ }
957
+ }
792
958
  // ── Users Table ──────────────────────────────────────
793
959
  case '/users': {
794
960
  const sub = args.trim();