compact-agent 1.30.0 → 1.30.2

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.d.ts CHANGED
@@ -11,10 +11,9 @@ export declare const LEGACY_CONFIG_DIR_NAME = ".crowcoder";
11
11
  export declare function getProjectStateDir(cwd: string): string;
12
12
  export declare function getConfigDir(): string;
13
13
  /**
14
- * Same as CONFIG_DIR but exported as a function so callers in other
15
- * modules don't have to import the private const + re-derive the env
16
- * fallback chain. Use this anywhere you previously wrote
17
- * `join(homedir(), '.crowcoder')`.
14
+ * Same as getConfigDir() but exported under a clearer name for
15
+ * other modules that want the home-dir state root. Used by
16
+ * sessions, debug log, gateguard state, etc.
18
17
  */
19
18
  export declare function getHomeStateDir(): string;
20
19
  export declare function loadConfig(): CrowcoderConfig;
package/dist/config.js CHANGED
@@ -14,10 +14,21 @@ import { homedir } from 'node:os';
14
14
  // skills, memory etc. without any manual step.
15
15
  export const CONFIG_DIR_NAME = '.compact-agent';
16
16
  export const LEGACY_CONFIG_DIR_NAME = '.crowcoder';
17
- const CONFIG_DIR = process.env.COMPACT_AGENT_HOME ||
18
- process.env.CROWCODER_HOME ||
19
- join(homedir(), CONFIG_DIR_NAME);
20
- const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
17
+ // Resolve the config dir LAZILY (every call) instead of caching at
18
+ // module-load time. The cached form prevented tests + sandboxed runs
19
+ // from overriding via COMPACT_AGENT_HOME after the first import: the
20
+ // first module to load would freeze the path at the user's real
21
+ // home, and all subsequent overrides were ignored. The resolution
22
+ // is cheap (env lookup + one join) so calling per access has no
23
+ // observable cost on the hot path.
24
+ function resolveConfigDir() {
25
+ return (process.env.COMPACT_AGENT_HOME ||
26
+ process.env.CROWCODER_HOME ||
27
+ join(homedir(), CONFIG_DIR_NAME));
28
+ }
29
+ function resolveConfigFile() {
30
+ return join(resolveConfigDir(), 'config.json');
31
+ }
21
32
  // Tracks whether we've already attempted the legacy-dir migration this
22
33
  // process. Migration is idempotent (existsSync guard) but we still cache
23
34
  // the decision so loadConfig() can be called repeatedly without re-stat'ing.
@@ -161,25 +172,25 @@ const DEFAULT_CONFIG = {
161
172
  },
162
173
  };
163
174
  export function getConfigDir() {
164
- return CONFIG_DIR;
175
+ return resolveConfigDir();
165
176
  }
166
177
  /**
167
- * Same as CONFIG_DIR but exported as a function so callers in other
168
- * modules don't have to import the private const + re-derive the env
169
- * fallback chain. Use this anywhere you previously wrote
170
- * `join(homedir(), '.crowcoder')`.
178
+ * Same as getConfigDir() but exported under a clearer name for
179
+ * other modules that want the home-dir state root. Used by
180
+ * sessions, debug log, gateguard state, etc.
171
181
  */
172
182
  export function getHomeStateDir() {
173
- return CONFIG_DIR;
183
+ return resolveConfigDir();
174
184
  }
175
185
  export function loadConfig() {
176
186
  // Try to migrate legacy ~/.crowcoder → ~/.compact-agent before reading.
177
187
  migrateLegacyHomeDir();
178
- if (!existsSync(CONFIG_FILE)) {
188
+ const configFile = resolveConfigFile();
189
+ if (!existsSync(configFile)) {
179
190
  return { ...DEFAULT_CONFIG };
180
191
  }
181
192
  try {
182
- const raw = readFileSync(CONFIG_FILE, 'utf-8');
193
+ const raw = readFileSync(configFile, 'utf-8');
183
194
  const loaded = JSON.parse(raw);
184
195
  const config = { ...DEFAULT_CONFIG, ...loaded };
185
196
  validateConfig(config);
@@ -229,8 +240,8 @@ function validateConfig(config) {
229
240
  }
230
241
  }
231
242
  export function saveConfig(config) {
232
- mkdirSync(CONFIG_DIR, { recursive: true });
233
- writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
243
+ mkdirSync(resolveConfigDir(), { recursive: true });
244
+ writeFileSync(resolveConfigFile(), JSON.stringify(config, null, 2), 'utf-8');
234
245
  }
235
246
  export function configExists() {
236
247
  const cfg = loadConfig();
@@ -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
@@ -13,7 +13,7 @@ import { runQuery } from './query.js';
13
13
  import { ALL_TOOLS } from './tools/index.js';
14
14
  import { PROVIDERS } from './types.js';
15
15
  // New systems
16
- import { createSession, autoSave, listSessions, loadSession, deleteSession, saveSession, generateSessionId } from './sessions.js';
16
+ import { createSession, autoSave, listSessions, loadSession, deleteSession, saveSession, generateSessionId, resolveSessionRef } from './sessions.js';
17
17
  import { initHooksDir, runHooks, listHooks, saveHooksConfig, clearQuarantinedHooks } from './hooks.js';
18
18
  import { printUsageSummary, setBudget } from './cost-tracker.js';
19
19
  import { getCompactionStats } from './compaction.js';
@@ -777,40 +777,139 @@ export function handleSlashCommand(input, config, messages, session, mode) {
777
777
  }
778
778
  else {
779
779
  console.log(chalk.cyan(`\n Saved Sessions (${sessions.length}):`));
780
+ // Show the FULL ID. Previously we truncated to 12 chars for
781
+ // visual density, but users copy-paste the displayed string
782
+ // into /resume and the truncated form doesn't match the
783
+ // actual filename — every paste failed. Width-aware padding
784
+ // keeps the table aligned across rows of differing ID
785
+ // lengths.
786
+ const maxIdLen = Math.max(...sessions.map((s) => s.id.length));
780
787
  for (const s of sessions.slice(0, 20)) {
781
- console.log(chalk.white(` ${s.id.slice(0, 12).padEnd(14)}`) +
788
+ console.log(chalk.white(` ${s.id.padEnd(maxIdLen + 2)}`) +
782
789
  chalk.dim(`${s.name.padEnd(30)} ${s.turnCount} turns ${s.model} ${s.updatedAt.slice(0, 10)}`));
783
790
  }
784
- console.log();
791
+ console.log(chalk.dim(`\n Use /resume <id>, /resume <prefix>, or /resume last to restore one.`));
785
792
  }
786
793
  return { handled: true };
787
794
  }
788
795
  case '/save':
789
796
  session.name = args || session.name;
790
- autoSave(session, messages);
797
+ // Snapshot live state so the saved session captures the
798
+ // user's current mode + perm choices, not the values that
799
+ // were on the Session object at create time. Otherwise
800
+ // /resume restores stale config and the model behaves
801
+ // unexpectedly (e.g. a yolo session resumed in ask mode).
802
+ autoSave(session, messages, {
803
+ model: config.model,
804
+ provider: config.provider,
805
+ mode: mode.current,
806
+ permissionMode: config.permissionMode,
807
+ cwd: process.cwd(),
808
+ });
791
809
  console.log(chalk.green(` Session saved: ${session.id} "${session.name}"`));
792
810
  return { handled: true };
793
811
  case '/resume': {
794
- if (!args) {
795
- console.log(chalk.yellow(' Usage: /resume <session-id>'));
812
+ if (!args.trim()) {
813
+ console.log(chalk.yellow(' Usage: /resume <session-id> | <prefix> | last'));
814
+ console.log(chalk.dim(' /sessions lists what\'s saved.'));
796
815
  return { handled: true };
797
816
  }
798
- const loaded = loadSession(args);
799
- if (!loaded) {
800
- console.log(chalk.red(` Session not found: ${args}`));
817
+ // resolveSessionRef accepts exact ID, prefix match (like git),
818
+ // "last"/"latest" shortcut, and strips angle/quote wrappers
819
+ // (users pasting /resume <id> from the help text). This
820
+ // replaces the exact-only lookup that broke for everyone
821
+ // who copy-pasted from /sessions's previously-truncated
822
+ // display.
823
+ const ref = resolveSessionRef(args);
824
+ if ('error' in ref) {
825
+ console.log(chalk.red(` ${ref.error}`));
826
+ if (ref.candidates && ref.candidates.length > 0) {
827
+ console.log(chalk.dim(' Matching candidates:'));
828
+ for (const c of ref.candidates.slice(0, 8))
829
+ console.log(chalk.dim(` ${c}`));
830
+ }
801
831
  return { handled: true };
802
832
  }
833
+ const loaded = loadSession(ref.id);
834
+ if (!loaded) {
835
+ // Resolver said the file exists but loadSession returned
836
+ // null — corrupt JSON. Surface clearly rather than silently
837
+ // looking like a not-found.
838
+ console.log(chalk.red(` Session ${ref.id} resolved but its JSON is corrupt.`));
839
+ return { handled: true };
840
+ }
841
+ // ── Restore live state ─────────────────────────────────
842
+ // Previously /resume only returned newMessages and left the
843
+ // live config / mode / perm at whatever the current REPL
844
+ // happened to be in. That breaks the contract: a yolo
845
+ // session resumed in ask mode means the model needs
846
+ // permission for every tool call the original session ran
847
+ // freely. Now we mutate the live config + session + mode
848
+ // objects in place so the resumed state takes effect
849
+ // immediately. Fields absent from old (pre-v1.30.2) session
850
+ // files leave the current value untouched.
851
+ const changes = [];
852
+ if (loaded.model && loaded.model !== config.model) {
853
+ changes.push(`model ${config.model} → ${loaded.model}`);
854
+ config.model = loaded.model;
855
+ }
856
+ if (loaded.provider && loaded.provider !== config.provider) {
857
+ changes.push(`provider ${config.provider} → ${loaded.provider}`);
858
+ config.provider = loaded.provider;
859
+ }
860
+ if (loaded.permissionMode && loaded.permissionMode !== config.permissionMode) {
861
+ changes.push(`perms ${config.permissionMode} → ${loaded.permissionMode}`);
862
+ config.permissionMode = loaded.permissionMode;
863
+ }
864
+ // mode.current is a { current: Mode } box (shared closure
865
+ // ref) so mutation propagates to the hotkey listener +
866
+ // prompt rendering automatically.
867
+ if (loaded.mode && loaded.mode !== mode.current) {
868
+ changes.push(`mode ${mode.current} → ${loaded.mode}`);
869
+ mode.current = loaded.mode;
870
+ }
871
+ // Adopt the resumed session's identity so subsequent
872
+ // autosaves write to its file, not the current session's.
873
+ session.id = loaded.id;
874
+ session.name = loaded.name;
875
+ session.createdAt = loaded.createdAt;
876
+ session.updatedAt = loaded.updatedAt;
877
+ session.tokenCount = loaded.tokenCount;
878
+ session.turnCount = loaded.turnCount;
879
+ // Persist the config update so the change survives restart.
880
+ saveConfig(config);
803
881
  console.log(chalk.green(` Resumed: ${loaded.name} (${loaded.messages.length} messages)`));
882
+ if (changes.length > 0) {
883
+ console.log(chalk.yellow(` Restored config: ${changes.join(', ')}`));
884
+ }
885
+ else {
886
+ console.log(chalk.dim(' Config unchanged (already matches the saved session).'));
887
+ }
804
888
  return { handled: true, newMessages: loaded.messages };
805
889
  }
806
- case '/delete':
807
- if (args && deleteSession(args)) {
808
- console.log(chalk.green(` Deleted session: ${args}`));
890
+ case '/delete': {
891
+ if (!args.trim()) {
892
+ console.log(chalk.yellow(' Usage: /delete <session-id> | <prefix> | last'));
893
+ return { handled: true };
894
+ }
895
+ const ref = resolveSessionRef(args);
896
+ if ('error' in ref) {
897
+ console.log(chalk.yellow(` ${ref.error}`));
898
+ if (ref.candidates && ref.candidates.length > 0) {
899
+ console.log(chalk.dim(' Matching candidates:'));
900
+ for (const c of ref.candidates.slice(0, 8))
901
+ console.log(chalk.dim(` ${c}`));
902
+ }
903
+ return { handled: true };
904
+ }
905
+ if (deleteSession(ref.id)) {
906
+ console.log(chalk.green(` Deleted session: ${ref.id}`));
809
907
  }
810
908
  else {
811
- console.log(chalk.yellow(` Session not found: ${args}`));
909
+ console.log(chalk.yellow(` Could not delete session: ${ref.id}`));
812
910
  }
813
911
  return { handled: true };
912
+ }
814
913
  // ── Git ───────────────────────────────────────────
815
914
  case '/commit': {
816
915
  const prompt = buildCommitPrompt(process.cwd());
@@ -2955,6 +3054,20 @@ async function main() {
2955
3054
  // with the per-chain timer printed after each model response (see runQuery),
2956
3055
  // gives both "how long am I here" and "how long was that last response."
2957
3056
  const sessionStartMs = new Date(session.createdAt).getTime();
3057
+ // autoSave wrapper that snapshots the live config + mode + perm
3058
+ // into the session before writing. Without this, the saved
3059
+ // session captures only the values the Session object was created
3060
+ // with — every /perm, /model, /mode change made during the
3061
+ // session is lost on /resume. Used by all in-process autosave
3062
+ // callsites; /save in the slash-command handler passes the same
3063
+ // snapshot inline (it doesn't have access to this closure).
3064
+ const saveWithSnapshot = () => autoSave(session, messages, {
3065
+ model: config.model,
3066
+ provider: config.provider,
3067
+ mode: mode.current,
3068
+ permissionMode: config.permissionMode,
3069
+ cwd: process.cwd(),
3070
+ });
2958
3071
  // Main REPL loop
2959
3072
  while (true) {
2960
3073
  let input;
@@ -3101,14 +3214,14 @@ async function main() {
3101
3214
  catch (e) {
3102
3215
  console.log(chalk.red(` Swarm failed: ${e instanceof Error ? e.message : e}`));
3103
3216
  }
3104
- await autoSave(session, messages);
3217
+ await saveWithSnapshot();
3105
3218
  continue;
3106
3219
  }
3107
3220
  else {
3108
3221
  messages.push({ role: 'user', content: result.injectPrompt });
3109
3222
  }
3110
3223
  await runQuery({ config, messages, cwd: process.cwd(), rl, sessionId: session.id, mode: mode.current });
3111
- await autoSave(session, messages);
3224
+ await saveWithSnapshot();
3112
3225
  continue;
3113
3226
  }
3114
3227
  if (result.handled)
@@ -3136,7 +3249,7 @@ async function main() {
3136
3249
  mode: mode.current,
3137
3250
  });
3138
3251
  // Auto-save session
3139
- await autoSave(session, messages);
3252
+ await saveWithSnapshot();
3140
3253
  // Strategic compaction check
3141
3254
  const compactionHint = shouldSuggestCompaction(messages, 0);
3142
3255
  if (compactionHint) {
@@ -3147,7 +3260,7 @@ async function main() {
3147
3260
  onSessionEnd(session.id, messages, process.cwd());
3148
3261
  await runHooks({ event: 'SessionStop', sessionId: session.id, cwd: process.cwd(), permissionMode: config.permissionMode });
3149
3262
  // Final save
3150
- await autoSave(session, messages);
3263
+ await saveWithSnapshot();
3151
3264
  console.log(chalk.dim(`\nSession saved: ${session.id}`));
3152
3265
  console.log(chalk.dim('Goodbye!\n'));
3153
3266
  rl.close();