@hanzlaa/rcode 4.1.2 → 4.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.
- package/cli/install.js +176 -13
- package/cli/lib/config.cjs +4 -2
- package/cli/lib/fsutil.cjs +13 -2
- package/cli/lib/homedir.cjs +21 -0
- package/cli/lib/schemas.cjs +6 -1
- package/cli/nuke.js +13 -8
- package/cli/postinstall.js +14 -4
- package/cli/rcode-slash-router.cjs +118 -0
- package/cli/uninstall.js +59 -1
- package/cli/update.js +10 -5
- package/dist/rcode.js +234 -230
- package/package.json +1 -1
- package/rcode/references/auto-init-guard.md +2 -2
- package/rcode/references/output-format.md +5 -5
- package/rcode/skills/actions/2-plan/rcode-create-milestone/steps/step-10-complete.md +1 -1
- package/server/dashboard.js +33 -13
- package/server/lib/api.js +62 -4
- package/server/lib/html/client/agents-data.js +22 -18
- package/server/lib/html/client/app.js +3 -0
- package/server/lib/html/client/components/AgentCard.js +127 -0
- package/server/lib/html/client/components/App.js +104 -39
- package/server/lib/html/client/components/CommandPalette.js +133 -0
- package/server/lib/html/client/components/FileReader.js +116 -0
- package/server/lib/html/client/components/FilterChips.js +94 -0
- package/server/lib/html/client/components/NotifyCenter.js +117 -0
- package/server/lib/html/client/components/OrchPanel.js +80 -52
- package/server/lib/html/client/components/PhaseGraph.js +300 -0
- package/server/lib/html/client/components/RejectDialog.js +78 -0
- package/server/lib/html/client/components/RunnerPicker.js +190 -0
- package/server/lib/html/client/components/Sidebar.js +106 -61
- package/server/lib/html/client/components/StatusSummaryBar.js +76 -0
- package/server/lib/html/client/components/TaskPipeline.js +83 -0
- package/server/lib/html/client/components/Topbar.js +86 -39
- package/server/lib/html/client/components/dashboard/Blockers.js +57 -0
- package/server/lib/html/client/components/dashboard/CompletedTasks.js +47 -0
- package/server/lib/html/client/components/dashboard/CurrentPhase.js +107 -0
- package/server/lib/html/client/components/dashboard/InProgress.js +72 -0
- package/server/lib/html/client/components/dashboard/ProgressDonut.js +101 -0
- package/server/lib/html/client/components/dashboard/ProgressTimeline.js +101 -0
- package/server/lib/html/client/components/dashboard/ProjectHealth.js +80 -0
- package/server/lib/html/client/components/dashboard/RecentDecisions.js +57 -0
- package/server/lib/html/client/components/dashboard/Timeline.js +143 -0
- package/server/lib/html/client/components/shared.js +47 -11
- package/server/lib/html/client/filter-state.js +72 -0
- package/server/lib/html/client/icons-client.js +7 -0
- package/server/lib/html/client/notify.js +75 -0
- package/server/lib/html/client/orchestrator.js +168 -41
- package/server/lib/html/client/preact.js +13 -8
- package/server/lib/html/client/store.js +70 -6
- package/server/lib/html/client/util.js +78 -0
- package/server/lib/html/client/vendor/htm.js +1 -0
- package/server/lib/html/client/vendor/preact-hooks.js +2 -0
- package/server/lib/html/client/vendor/preact.js +2 -0
- package/server/lib/html/client/views/AgentsView.js +144 -51
- package/server/lib/html/client/views/FilesView.js +20 -103
- package/server/lib/html/client/views/KanbanView.js +40 -21
- package/server/lib/html/client/views/MemoryView.js +26 -9
- package/server/lib/html/client/views/MilestonesView.js +4 -4
- package/server/lib/html/client/views/OrchestrationView.js +154 -19
- package/server/lib/html/client/views/OverviewView.js +47 -239
- package/server/lib/html/client/views/PhasesView.js +50 -6
- package/server/lib/html/client/views/RoadmapView.js +6 -3
- package/server/lib/html/client/views/SprintsView.js +50 -6
- package/server/lib/html/client/views/TasksView.js +4 -3
- package/server/lib/html/client.js +21 -4
- package/server/lib/html/css.js +2761 -8
- package/server/lib/html/icons.js +7 -0
- package/server/lib/html/shell.js +10 -3
- package/server/lib/scanner.js +376 -39
- package/server/orchestrator.js +346 -7
package/cli/uninstall.js
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
27
|
const fs = require('fs');
|
|
28
|
+
const os = require('os');
|
|
28
29
|
const path = require('path');
|
|
29
30
|
const { spawnSync } = require('child_process');
|
|
30
31
|
const { askConfirm, PromptAbortError } = require('./lib/prompts.cjs');
|
|
@@ -128,6 +129,35 @@ function cleanRcodePreCommitHook(cwd) {
|
|
|
128
129
|
} catch { return 'skipped'; }
|
|
129
130
|
}
|
|
130
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Remove the rcode slash-router hook entry from a CLI hooks JSON file
|
|
134
|
+
* (codex: ~/.codex/hooks.json UserPromptSubmit, antigravity:
|
|
135
|
+
* ~/.gemini/antigravity/settings.json UserPrompt) while preserving every
|
|
136
|
+
* other entry (herdr's, the user's). Matches the router by command substring.
|
|
137
|
+
* Idempotent + guarded: missing/unparseable files are no-ops.
|
|
138
|
+
* Returns 'removed' | 'unchanged' | 'skipped'.
|
|
139
|
+
*/
|
|
140
|
+
function removeSlashRouterHook(jsonPath, eventKey) {
|
|
141
|
+
if (!fs.existsSync(jsonPath)) return 'skipped';
|
|
142
|
+
let root;
|
|
143
|
+
try { root = JSON.parse(fs.readFileSync(jsonPath, 'utf8')); } catch { return 'skipped'; }
|
|
144
|
+
if (!root || typeof root !== 'object' || !root.hooks || !Array.isArray(root.hooks[eventKey])) {
|
|
145
|
+
return 'unchanged';
|
|
146
|
+
}
|
|
147
|
+
const before = root.hooks[eventKey].length;
|
|
148
|
+
root.hooks[eventKey] = root.hooks[eventKey].filter(group =>
|
|
149
|
+
!(Array.isArray(group?.hooks) &&
|
|
150
|
+
group.hooks.some(h => typeof h?.command === 'string' && h.command.includes('rcode-slash-router.cjs'))),
|
|
151
|
+
);
|
|
152
|
+
if (root.hooks[eventKey].length === before) return 'unchanged';
|
|
153
|
+
// Drop the event key entirely if it is now empty, to leave a tidy file.
|
|
154
|
+
if (root.hooks[eventKey].length === 0) delete root.hooks[eventKey];
|
|
155
|
+
try {
|
|
156
|
+
writeFileAtomic(jsonPath, JSON.stringify(root, null, 2) + '\n');
|
|
157
|
+
return 'removed';
|
|
158
|
+
} catch { return 'skipped'; }
|
|
159
|
+
}
|
|
160
|
+
|
|
131
161
|
/**
|
|
132
162
|
* Walk a directory and remove all files/subdirs whose name matches a predicate.
|
|
133
163
|
* Returns the number of entries removed. Always skips local overrides (#382).
|
|
@@ -433,7 +463,11 @@ function planToPathList(plan, cwd, options = {}) {
|
|
|
433
463
|
* still proceed since the user already confirmed the destructive action.
|
|
434
464
|
*/
|
|
435
465
|
function createBackup(cwd, plan, options = {}) {
|
|
436
|
-
|
|
466
|
+
// Tar entry names are always '/'-separated; on Windows planToPathList
|
|
467
|
+
// produces '\'-joined paths that bsdtar may store verbatim. Normalize so
|
|
468
|
+
// the archive (and any `tar -tzf` consumer) sees portable paths.
|
|
469
|
+
const paths = planToPathList(plan, cwd, { purge: options.purge === true })
|
|
470
|
+
.map((p) => p.split(path.sep).join('/'));
|
|
437
471
|
if (paths.length === 0) {
|
|
438
472
|
return { ok: false, warning: 'nothing to back up' };
|
|
439
473
|
}
|
|
@@ -746,6 +780,29 @@ async function runUninstall(args) {
|
|
|
746
780
|
if (n > 0) console.log(` ✓ removed ${n} Antigravity agents`);
|
|
747
781
|
}
|
|
748
782
|
|
|
783
|
+
// Slash-router hooks (home-dir, CLI-native). Installed only via `--global`
|
|
784
|
+
// for codex/antigravity; remove the rcode UserPromptSubmit/UserPrompt entry
|
|
785
|
+
// from each CLI's hooks JSON, leaving herdr + other hooks intact.
|
|
786
|
+
if (editors.includes('codex')) {
|
|
787
|
+
const r = removeSlashRouterHook(path.join(os.homedir(), '.codex', 'hooks.json'), 'UserPromptSubmit');
|
|
788
|
+
if (r === 'removed') console.log(` ✓ removed rcode slash-router hook from ~/.codex/hooks.json`);
|
|
789
|
+
}
|
|
790
|
+
if (editors.includes('antigravity')) {
|
|
791
|
+
const r = removeSlashRouterHook(path.join(os.homedir(), '.gemini', 'antigravity', 'settings.json'), 'UserPrompt');
|
|
792
|
+
if (r === 'removed') console.log(` ✓ removed rcode slash-router hook from ~/.gemini/antigravity/settings.json`);
|
|
793
|
+
}
|
|
794
|
+
// The router script + command-body copies are shared by both CLIs; remove
|
|
795
|
+
// them once if either is in scope.
|
|
796
|
+
if (editors.includes('codex') || editors.includes('antigravity')) {
|
|
797
|
+
const home = os.homedir();
|
|
798
|
+
for (const dir of [path.join(home, '.rcode', 'slash-commands'), path.join(home, '.rcode', 'bin')]) {
|
|
799
|
+
if (fs.existsSync(dir)) {
|
|
800
|
+
const rr = safeRmSync(dir, home);
|
|
801
|
+
if (rr.ok) console.log(` ✓ removed ${dir}`);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
749
806
|
// #706 — gemini removal (.gemini/rcode/{agents,commands})
|
|
750
807
|
if (editors.includes('gemini')) {
|
|
751
808
|
let n = 0;
|
|
@@ -925,6 +982,7 @@ module.exports.isLocalOverride = isLocalOverride;
|
|
|
925
982
|
module.exports.planToPathList = planToPathList;
|
|
926
983
|
module.exports.discoverKnownActionSkills = discoverKnownActionSkills;
|
|
927
984
|
module.exports.stripRcodeGitignoreBlock = stripRcodeGitignoreBlock;
|
|
985
|
+
module.exports.removeSlashRouterHook = removeSlashRouterHook;
|
|
928
986
|
|
|
929
987
|
// Direct invocation — allow `node cli/uninstall.js [flags]` to run end-to-end.
|
|
930
988
|
// When called via cli/index.js, module.exports is invoked directly.
|
package/cli/update.js
CHANGED
|
@@ -34,6 +34,8 @@ const { spawnSync } = require('child_process');
|
|
|
34
34
|
const clack = require('@clack/prompts');
|
|
35
35
|
const { PromptAbortError } = require('./lib/prompts.cjs');
|
|
36
36
|
const { writeFileAtomic } = require('./lib/fsutil.cjs');
|
|
37
|
+
// HOME-aware home resolution (#889): os.homedir() ignores HOME on Windows.
|
|
38
|
+
const { homedir } = require('./lib/homedir.cjs');
|
|
37
39
|
const { verifyInstall, formatReport } = require('./lib/manifest.cjs');
|
|
38
40
|
const install = require('./install');
|
|
39
41
|
|
|
@@ -46,7 +48,9 @@ const install = require('./install');
|
|
|
46
48
|
function readConfigYaml(configPath) {
|
|
47
49
|
const text = fs.readFileSync(configPath, 'utf8');
|
|
48
50
|
const obj = {};
|
|
49
|
-
|
|
51
|
+
// CRLF tolerance (#889): split on \r?\n — a stray \r otherwise defeats the
|
|
52
|
+
// `#.*$` comment strip ($ won't cross the \r) and leaks comments into values.
|
|
53
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
50
54
|
const line = raw.replace(/#.*$/, '').trimEnd();
|
|
51
55
|
if (!line) continue;
|
|
52
56
|
if (line.startsWith(' ')) continue; // ignore nested keys (rare; preserved on disk via raw text path)
|
|
@@ -68,14 +72,16 @@ function readConfigYaml(configPath) {
|
|
|
68
72
|
* If the key doesn't exist, append it.
|
|
69
73
|
*/
|
|
70
74
|
function setYamlKey(rawText, key, value) {
|
|
71
|
-
|
|
75
|
+
// CRLF tolerance (#889): [^\S\n]/[^\r\n] keep the match on one line even
|
|
76
|
+
// when the file uses \r\n (plain \s would walk across the line break).
|
|
77
|
+
const re = new RegExp(`^${key}:[^\\S\\n]*[^\\r\\n]*$`, 'm');
|
|
72
78
|
const replacement = typeof value === 'string'
|
|
73
79
|
? `${key}: "${value.replace(/"/g, '\\"')}"`
|
|
74
80
|
: `${key}: ${value}`;
|
|
75
81
|
if (re.test(rawText)) {
|
|
76
82
|
return rawText.replace(re, replacement);
|
|
77
83
|
}
|
|
78
|
-
return rawText.replace(
|
|
84
|
+
return rawText.replace(/(?:\r?\n)*$/, '') + `\n${replacement}\n`;
|
|
79
85
|
}
|
|
80
86
|
|
|
81
87
|
function parseArgs(args) {
|
|
@@ -98,8 +104,7 @@ function detectInstalledEditors(cwd) {
|
|
|
98
104
|
// .rcode/config.yaml as the canonical signal — if config exists, the
|
|
99
105
|
// project ran rcode install at least once for claude. The presence of
|
|
100
106
|
// any commands/agents/skills then becomes secondary evidence.
|
|
101
|
-
const
|
|
102
|
-
const homeSkills = path.join(os.homedir(), '.claude/skills');
|
|
107
|
+
const homeSkills = path.join(homedir(), '.claude/skills');
|
|
103
108
|
const projectClaude = (
|
|
104
109
|
(fs.existsSync(path.join(cwd, '.claude/skills')) &&
|
|
105
110
|
fs.readdirSync(path.join(cwd, '.claude/skills')).some(n => n.startsWith('rcode-'))) ||
|