cawdex 1.35.76 → 1.35.77
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/command-palette.js +1 -0
- package/dist/command-palette.js.map +1 -1
- package/dist/config.js +7 -1
- package/dist/config.js.map +1 -1
- package/dist/fixed-footer.d.ts +4 -1
- package/dist/fixed-footer.js +26 -11
- package/dist/fixed-footer.js.map +1 -1
- package/dist/imports.d.ts +126 -0
- package/dist/imports.js +611 -0
- package/dist/imports.js.map +1 -0
- package/dist/index.js +206 -3
- package/dist/index.js.map +1 -1
- package/dist/inline-suggest.js +136 -12
- package/dist/inline-suggest.js.map +1 -1
- package/dist/query.js +34 -5
- package/dist/query.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -94,7 +94,8 @@ import { normalizeTypeaheadDraftForPrompt } from './prompt-buffer.js';
|
|
|
94
94
|
import { maybeInstantAnswer } from './instant-answer.js';
|
|
95
95
|
import { maybeCreateInstantArtifact } from './instant-artifact.js';
|
|
96
96
|
import { getCurrentVersion, startStartupUpdateCheck } from './updater.js';
|
|
97
|
-
import {
|
|
97
|
+
import { importStatus, previewImport, rollbackImport, runImport, scanImportSources, } from './imports.js';
|
|
98
|
+
import { activateFooter, askWithFooterPrompt, buildFooterSnapshot, deactivateFooter, isFooterActive, setFooterActivity, shouldUseFixedFooter, updateFooter, writeFooterSubmittedLine, writeScrollableLine, } from './fixed-footer.js';
|
|
98
99
|
/**
|
|
99
100
|
* Unified prompt resolver — prefers the bundled ECC prompt for a given
|
|
100
101
|
* intent and falls back to the built-in builder when ECC isn't installed.
|
|
@@ -486,6 +487,56 @@ async function setupWizard(rl, currentConfig) {
|
|
|
486
487
|
const defaultTarget = await askOptionalSwarmDefault('Default target platform/stack', currentConfig?.swarm?.defaultTarget);
|
|
487
488
|
const defaultAssets = await askOptionalSwarmDefault('Default starting assets/resources', currentConfig?.swarm?.defaultAssets);
|
|
488
489
|
const defaultQuality = await askOptionalSwarmDefault('Default quality bar/release target', currentConfig?.swarm?.defaultQuality);
|
|
490
|
+
console.log(chalk.white('\n Import settings'));
|
|
491
|
+
console.log(chalk.dim(' Defaults for /import and optional startup auto-sync.'));
|
|
492
|
+
const importSourceChoices = [
|
|
493
|
+
{ label: 'Auto-detect', detail: 'scan all supported sources and import what is available', value: 'auto' },
|
|
494
|
+
{ label: 'Claude', detail: 'prefer ~/.claude/projects exports', value: 'claude' },
|
|
495
|
+
{ label: 'Codex', detail: 'prefer ~/.codex/sessions exports', value: 'codex' },
|
|
496
|
+
{ label: 'MemPalace', detail: 'prefer ~/.mempalace notes and identity files', value: 'mempalace' },
|
|
497
|
+
];
|
|
498
|
+
const currentImportSource = currentConfig?.import?.defaultSource ?? 'auto';
|
|
499
|
+
const importSourceDefaultIndex = Math.max(0, importSourceChoices.findIndex((c) => c.value === currentImportSource));
|
|
500
|
+
const defaultImportSource = await selectConfigChoice(rl, 'Import default source', importSourceChoices, {
|
|
501
|
+
defaultIndex: importSourceDefaultIndex,
|
|
502
|
+
fallbackPrompt: ` Import default source [${importSourceDefaultIndex + 1}]: `,
|
|
503
|
+
parseFallback: (answer, defaultIndex) => {
|
|
504
|
+
const raw = (answer || String(defaultIndex + 1)).trim().toLowerCase();
|
|
505
|
+
const byName = importSourceChoices.find((choice) => choice.value === raw);
|
|
506
|
+
if (byName)
|
|
507
|
+
return byName.value;
|
|
508
|
+
const byNumber = importSourceChoices[Number.parseInt(raw, 10) - 1];
|
|
509
|
+
return byNumber?.value;
|
|
510
|
+
},
|
|
511
|
+
});
|
|
512
|
+
const autoSyncDefaultIndex = currentConfig?.import?.autoSyncOnStartup ? 0 : 1;
|
|
513
|
+
const autoSyncOnStartup = await selectConfigChoice(rl, 'Import auto-sync on startup', [
|
|
514
|
+
{ label: 'Enable', detail: 'run /import run <source> --limit N once at startup', value: true },
|
|
515
|
+
{ label: 'Disable', detail: 'import only when requested via /import run', value: false },
|
|
516
|
+
], {
|
|
517
|
+
defaultIndex: autoSyncDefaultIndex,
|
|
518
|
+
fallbackPrompt: ` Import auto-sync? [${autoSyncDefaultIndex === 0 ? 'Y/n' : 'y/N'}]: `,
|
|
519
|
+
parseFallback: (answer, defaultIndex) => {
|
|
520
|
+
const raw = answer.trim().toLowerCase();
|
|
521
|
+
if (!raw)
|
|
522
|
+
return defaultIndex === 0;
|
|
523
|
+
if (raw.startsWith('n'))
|
|
524
|
+
return false;
|
|
525
|
+
if (raw.startsWith('y'))
|
|
526
|
+
return true;
|
|
527
|
+
const byNumber = Number.parseInt(raw, 10);
|
|
528
|
+
if (byNumber === 1)
|
|
529
|
+
return true;
|
|
530
|
+
if (byNumber === 2)
|
|
531
|
+
return false;
|
|
532
|
+
return undefined;
|
|
533
|
+
},
|
|
534
|
+
});
|
|
535
|
+
const currentSyncLimit = Math.max(10, Math.min(5000, Number(currentConfig?.import?.syncLimit ?? 200)));
|
|
536
|
+
const syncLimitAnswer = await rl.question(chalk.yellow(` Import sync limit [${currentSyncLimit}]: `));
|
|
537
|
+
const importSyncLimit = syncLimitAnswer.trim()
|
|
538
|
+
? Math.max(10, Math.min(5000, Number.parseInt(syncLimitAnswer.trim(), 10) || currentSyncLimit))
|
|
539
|
+
: currentSyncLimit;
|
|
489
540
|
const config = {
|
|
490
541
|
...(currentConfig ?? {}),
|
|
491
542
|
apiKey,
|
|
@@ -503,6 +554,11 @@ async function setupWizard(rl, currentConfig) {
|
|
|
503
554
|
...(defaultAssets ? { defaultAssets } : {}),
|
|
504
555
|
...(defaultQuality ? { defaultQuality } : {}),
|
|
505
556
|
},
|
|
557
|
+
import: {
|
|
558
|
+
defaultSource: defaultImportSource,
|
|
559
|
+
autoSyncOnStartup,
|
|
560
|
+
syncLimit: importSyncLimit,
|
|
561
|
+
},
|
|
506
562
|
};
|
|
507
563
|
if (fallbackModel)
|
|
508
564
|
config.fallbackModel = fallbackModel;
|
|
@@ -515,7 +571,7 @@ async function setupWizard(rl, currentConfig) {
|
|
|
515
571
|
applyModelSelection(config, model);
|
|
516
572
|
saveConfig(config);
|
|
517
573
|
console.log(chalk.green(`\n Config saved to ${getConfigDir()}/config.json`));
|
|
518
|
-
console.log(chalk.dim(` Configured: /model, /fallback, /perm, and /
|
|
574
|
+
console.log(chalk.dim(` Configured: /model, /fallback, /perm, /swarm, and /import defaults. Memory stays under /memory.`));
|
|
519
575
|
console.log();
|
|
520
576
|
return config;
|
|
521
577
|
}
|
|
@@ -662,7 +718,7 @@ function printResumedHistory(messages, sessionName) {
|
|
|
662
718
|
*/
|
|
663
719
|
async function askWithDecoratedPrompt(rl, sessionTag, modeTag, promptGlyph, prefill = '') {
|
|
664
720
|
if (isFooterActive()) {
|
|
665
|
-
return askWithFooterPrompt(rl, prefill);
|
|
721
|
+
return askWithFooterPrompt(rl, prefill, { echoSubmittedLine: false });
|
|
666
722
|
}
|
|
667
723
|
const decorative = sessionTag + modeTag;
|
|
668
724
|
if (decorative.length > 0) {
|
|
@@ -925,6 +981,7 @@ export function handleSlashCommand(input, config, messages, session, mode) {
|
|
|
925
981
|
console.log(d(' ') + c('/save [name]') + d(' — save current session'));
|
|
926
982
|
console.log(d(' ') + c('/resume <id>') + d(' — resume a saved session'));
|
|
927
983
|
console.log(d(' ') + c('/delete <id>') + d(' — delete a session'));
|
|
984
|
+
console.log(d(' ') + c('/import [sub]') + d(' — import Claude/Codex/MemPalace history and memory'));
|
|
928
985
|
console.log(h('\n ── Git ──'));
|
|
929
986
|
console.log(d(' ') + c('/commit') + d(' — AI-generated commit'));
|
|
930
987
|
console.log(d(' ') + c('/pr') + d(' — AI-generated pull request'));
|
|
@@ -1809,6 +1866,121 @@ export function handleSlashCommand(input, config, messages, session, mode) {
|
|
|
1809
1866
|
return { handled: true };
|
|
1810
1867
|
}
|
|
1811
1868
|
// ── Git ───────────────────────────────────────────
|
|
1869
|
+
case '/import': {
|
|
1870
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
1871
|
+
const sub = (tokens[0] || 'help').toLowerCase();
|
|
1872
|
+
const sourceToken = (tokens[1] || 'auto').toLowerCase();
|
|
1873
|
+
const limitIdx = tokens.findIndex((t) => t === '--limit');
|
|
1874
|
+
const dryRun = tokens.includes('--dry-run');
|
|
1875
|
+
const knownSources = ['claude', 'codex', 'mempalace'];
|
|
1876
|
+
const parsedSource = knownSources.includes(sourceToken)
|
|
1877
|
+
? sourceToken
|
|
1878
|
+
: null;
|
|
1879
|
+
const limit = limitIdx >= 0 && tokens[limitIdx + 1]
|
|
1880
|
+
? Math.max(1, Math.min(10_000, Number(tokens[limitIdx + 1]) || 1000))
|
|
1881
|
+
: 1000;
|
|
1882
|
+
const detected = scanImportSources();
|
|
1883
|
+
const detectedSources = detected.filter((s) => s.detected && s.artifactsFound > 0).map((s) => s.source);
|
|
1884
|
+
const targets = parsedSource
|
|
1885
|
+
? [parsedSource]
|
|
1886
|
+
: (detectedSources.length > 0 ? detectedSources : ['claude', 'codex', 'mempalace']);
|
|
1887
|
+
if (sub === 'help') {
|
|
1888
|
+
console.log(chalk.cyan('\n /import'));
|
|
1889
|
+
console.log(chalk.dim(' Migrate prior agent work into Cawdex without losing conversation history.'));
|
|
1890
|
+
console.log(chalk.dim(' /import scan'));
|
|
1891
|
+
console.log(chalk.dim(' /import preview <claude|codex|mempalace|auto> [--limit N]'));
|
|
1892
|
+
console.log(chalk.dim(' /import run <claude|codex|mempalace|auto> [--limit N] [--dry-run]'));
|
|
1893
|
+
console.log(chalk.dim(' /import status'));
|
|
1894
|
+
console.log(chalk.dim(' /import rollback <run-id>'));
|
|
1895
|
+
console.log(chalk.dim(' Notes:'));
|
|
1896
|
+
console.log(chalk.dim(' - Claude source: ~/.claude/projects/**/*.jsonl'));
|
|
1897
|
+
console.log(chalk.dim(' - Codex source: ~/.codex/sessions/**/*.jsonl'));
|
|
1898
|
+
console.log(chalk.dim(' - MemPalace source: ~/.mempalace/session_notes + identity.txt'));
|
|
1899
|
+
console.log();
|
|
1900
|
+
return { handled: true };
|
|
1901
|
+
}
|
|
1902
|
+
if (sub === 'scan') {
|
|
1903
|
+
console.log(chalk.cyan('\n Import sources:'));
|
|
1904
|
+
for (const item of detected) {
|
|
1905
|
+
const marker = item.detected ? chalk.green('✓') : chalk.yellow('•');
|
|
1906
|
+
const count = chalk.dim(`${item.artifactsFound} artifact(s)`);
|
|
1907
|
+
console.log(` ${marker} ${item.source.padEnd(10)} ${count} ${chalk.dim(item.rootPath)}`);
|
|
1908
|
+
if (item.note)
|
|
1909
|
+
console.log(chalk.dim(` ${item.note}`));
|
|
1910
|
+
}
|
|
1911
|
+
console.log();
|
|
1912
|
+
return { handled: true };
|
|
1913
|
+
}
|
|
1914
|
+
if (sub === 'status') {
|
|
1915
|
+
const status = importStatus();
|
|
1916
|
+
console.log(chalk.cyan('\n Import status:'));
|
|
1917
|
+
console.log(chalk.dim(` ledger entries: ${status.ledgerEntries}`));
|
|
1918
|
+
console.log(chalk.dim(` runs: ${status.runs}`));
|
|
1919
|
+
console.log(chalk.dim(` sessions imported: ${status.sessionsImported}`));
|
|
1920
|
+
console.log(chalk.dim(` memory drawers imported: ${status.drawersImported}`));
|
|
1921
|
+
for (const src of knownSources) {
|
|
1922
|
+
const row = status.bySource[src];
|
|
1923
|
+
console.log(chalk.dim(` ${src.padEnd(10)} sessions ${String(row.sessions).padStart(4)} drawers ${String(row.drawers).padStart(4)}`));
|
|
1924
|
+
}
|
|
1925
|
+
console.log();
|
|
1926
|
+
return { handled: true };
|
|
1927
|
+
}
|
|
1928
|
+
if (sub === 'rollback') {
|
|
1929
|
+
const runId = tokens[1];
|
|
1930
|
+
if (!runId) {
|
|
1931
|
+
console.log(chalk.yellow(' Usage: /import rollback <run-id>'));
|
|
1932
|
+
return { handled: true };
|
|
1933
|
+
}
|
|
1934
|
+
const res = rollbackImport(runId, process.cwd());
|
|
1935
|
+
console.log(chalk.green(` Rolled back ${runId}.`));
|
|
1936
|
+
console.log(chalk.dim(` deleted sessions: ${res.deletedSessions}`));
|
|
1937
|
+
console.log(chalk.dim(` deleted memory drawers: ${res.deletedDrawers}`));
|
|
1938
|
+
for (const warning of res.warnings)
|
|
1939
|
+
console.log(chalk.yellow(` warning: ${warning}`));
|
|
1940
|
+
return { handled: true };
|
|
1941
|
+
}
|
|
1942
|
+
if (sub === 'preview') {
|
|
1943
|
+
for (const src of targets) {
|
|
1944
|
+
const res = previewImport(src, { limit, cwd: process.cwd() });
|
|
1945
|
+
console.log(chalk.cyan(`\n Preview: ${src}`));
|
|
1946
|
+
console.log(chalk.dim(` artifacts found: ${res.artifactsFound}`));
|
|
1947
|
+
console.log(chalk.dim(` importable: ${res.importableArtifacts}`));
|
|
1948
|
+
console.log(chalk.dim(` already imported: ${res.alreadyImportedArtifacts}`));
|
|
1949
|
+
if (res.totalMessages > 0)
|
|
1950
|
+
console.log(chalk.dim(` messages in sample: ${res.totalMessages}`));
|
|
1951
|
+
for (const thread of res.threads.slice(0, 10)) {
|
|
1952
|
+
console.log(chalk.dim(` ${thread.sourceThreadId} ${thread.messageCount} msgs ${thread.updatedAt.slice(0, 10)} ${thread.model}`));
|
|
1953
|
+
}
|
|
1954
|
+
for (const warning of res.warnings.slice(0, 5))
|
|
1955
|
+
console.log(chalk.yellow(` warning: ${warning}`));
|
|
1956
|
+
}
|
|
1957
|
+
console.log();
|
|
1958
|
+
return { handled: true };
|
|
1959
|
+
}
|
|
1960
|
+
if (sub === 'run') {
|
|
1961
|
+
for (const src of targets) {
|
|
1962
|
+
const res = runImport(src, { limit, dryRun, cwd: process.cwd() });
|
|
1963
|
+
const prefix = dryRun ? 'Dry-run' : 'Imported';
|
|
1964
|
+
console.log(chalk.green(`\n ${prefix}: ${src}`));
|
|
1965
|
+
console.log(chalk.dim(` run id: ${res.runId}`));
|
|
1966
|
+
console.log(chalk.dim(` imported artifacts: ${res.importedArtifacts}`));
|
|
1967
|
+
console.log(chalk.dim(` skipped artifacts: ${res.skippedArtifacts}`));
|
|
1968
|
+
if (res.importedSessions > 0)
|
|
1969
|
+
console.log(chalk.dim(` sessions created: ${res.importedSessions}`));
|
|
1970
|
+
if (res.importedMessages > 0)
|
|
1971
|
+
console.log(chalk.dim(` messages imported: ${res.importedMessages}`));
|
|
1972
|
+
if (res.importedDrawers > 0)
|
|
1973
|
+
console.log(chalk.dim(` memory drawers created: ${res.importedDrawers}`));
|
|
1974
|
+
for (const warning of res.warnings.slice(0, 5))
|
|
1975
|
+
console.log(chalk.yellow(` warning: ${warning}`));
|
|
1976
|
+
}
|
|
1977
|
+
console.log();
|
|
1978
|
+
return { handled: true };
|
|
1979
|
+
}
|
|
1980
|
+
console.log(chalk.yellow(` Unknown /import subcommand: ${sub}`));
|
|
1981
|
+
console.log(chalk.dim(' Try: /import help'));
|
|
1982
|
+
return { handled: true };
|
|
1983
|
+
}
|
|
1812
1984
|
case '/commit': {
|
|
1813
1985
|
const prompt = buildCommitPrompt(process.cwd());
|
|
1814
1986
|
if (!prompt) {
|
|
@@ -3663,6 +3835,31 @@ async function main() {
|
|
|
3663
3835
|
if (memoryContext) {
|
|
3664
3836
|
messages.push({ role: 'system', content: memoryContext });
|
|
3665
3837
|
}
|
|
3838
|
+
if (!nonInteractive && config.import?.autoSyncOnStartup) {
|
|
3839
|
+
const wanted = config.import.defaultSource ?? 'auto';
|
|
3840
|
+
const limit = Math.max(10, Math.min(5000, Number(config.import.syncLimit ?? 200)));
|
|
3841
|
+
const scan = scanImportSources();
|
|
3842
|
+
const available = scan.filter((s) => s.detected && s.artifactsFound > 0).map((s) => s.source);
|
|
3843
|
+
const sources = wanted === 'auto'
|
|
3844
|
+
? available
|
|
3845
|
+
: [wanted];
|
|
3846
|
+
if (sources.length > 0) {
|
|
3847
|
+
let totalImported = 0;
|
|
3848
|
+
let totalSkipped = 0;
|
|
3849
|
+
for (const src of sources) {
|
|
3850
|
+
try {
|
|
3851
|
+
const result = runImport(src, { limit, cwd: process.cwd() });
|
|
3852
|
+
totalImported += result.importedArtifacts;
|
|
3853
|
+
totalSkipped += result.skippedArtifacts;
|
|
3854
|
+
}
|
|
3855
|
+
catch (err) {
|
|
3856
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
3857
|
+
console.log(theme.warning(` import auto-sync (${src}) failed: ${msg}`));
|
|
3858
|
+
}
|
|
3859
|
+
}
|
|
3860
|
+
console.log(theme.dim(` import auto-sync: imported ${totalImported}, skipped ${totalSkipped} (limit ${limit})`));
|
|
3861
|
+
}
|
|
3862
|
+
}
|
|
3666
3863
|
// Show startup display based on theme setting. Skipped entirely in
|
|
3667
3864
|
// non-interactive mode — banners are noise when a harness is parsing
|
|
3668
3865
|
// our stdout.
|
|
@@ -4714,6 +4911,9 @@ async function main() {
|
|
|
4714
4911
|
const trimmed = input.trim();
|
|
4715
4912
|
if (!trimmed)
|
|
4716
4913
|
continue;
|
|
4914
|
+
if (isFooterActive()) {
|
|
4915
|
+
writeFooterSubmittedLine(input);
|
|
4916
|
+
}
|
|
4717
4917
|
// Shell escape
|
|
4718
4918
|
if (trimmed.startsWith('!')) {
|
|
4719
4919
|
const { exec } = await import('node:child_process');
|
|
@@ -4745,6 +4945,9 @@ async function main() {
|
|
|
4745
4945
|
nextTurnOverride = result.turnOverride;
|
|
4746
4946
|
}
|
|
4747
4947
|
syncFooter();
|
|
4948
|
+
if (isFooterActive()) {
|
|
4949
|
+
setFooterActivity('Ready', 0, null);
|
|
4950
|
+
}
|
|
4748
4951
|
if (trimmed.startsWith('/config') && !result?.shouldExit) {
|
|
4749
4952
|
deactivateFooter();
|
|
4750
4953
|
config = await setupWizard(rl, config);
|