total-recall-brain 3.40.1 → 3.40.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/README.md +152 -41
- package/bin/total-recall.mjs +16 -76
- package/docs/reference/cli-reference.md +10 -10
- package/extension/background.js +6 -2
- package/extension/config.js +8 -0
- package/extension/lib/brain-client.js +29 -4
- package/extension/options/options.html +1 -0
- package/extension/sidepanel/sidepanel.html +1 -0
- package/frontend/dist/assets/{index-CvQRdT2j.css → index-AGUes-VG.css} +1 -1
- package/frontend/dist/assets/index-Bt5iVPZj.js +5618 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/src/api/keys.ts +9 -2
- package/frontend/src/api/plugins.ts +4 -0
- package/frontend/src/components/plugins/card/CardEngine.tsx +2 -1
- package/frontend/src/components/plugins/card/card.css +1 -1
- package/frontend/src/pages/IntegrationsPage.tsx +315 -8
- package/frontend/src/pages/PluginsPage.tsx +532 -87
- package/package.json +6 -5
- package/scaffold/.agent/skills/meta-harness/references/optimized/original.md +1 -1
- package/scaffold/.agent/skills/meta-harness/references/optimized/section-09.md +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +10 -10
- package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +1 -6
- package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +0 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/browser-session.mjs +309 -4
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/cli-secret.mjs +44 -34
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/google-oauth.mjs +6 -4
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/provider-catalog.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/provider-rotation-recipes.mjs +118 -4
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/routes/auth.mjs +2 -2
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-env-export.mjs +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-remote-deploy.mjs +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/src/secrets-rotate.mjs +24 -6
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/card.js +164 -123
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/README.md +65 -0
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/cli.mjs +76 -0
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/package.json +19 -0
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/plugin.json +290 -0
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/adapters/dsh.mjs +446 -0
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/documentation.mjs +152 -0
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/executor.mjs +71 -0
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/runtime.mjs +36 -0
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/setup.mjs +35 -0
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/src/worker.mjs +175 -0
- package/scaffold/.agent/skills/total-recall/plugins/cli-agents/ui/card.js +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/LICENSE +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/README.md +84 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/cli.mjs +79 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/check.mjs +6 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/report.mjs +6 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/run-core.mjs +27 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/commands/snapshot.mjs +163 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/check.mjs +757 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/config.schema.json +86 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/detect.mjs +89 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report-data.mjs +145 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/report.mjs +210 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/core/state.mjs +20 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +2869 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +28 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +186 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/DESIGN.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/card.js +272 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/ui/code-quality-report.mjs +129 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/LICENSE +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/README.md +73 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/cli.mjs +375 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/examples/commands/echo-tool.mjs +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/examples/commands/group.mjs +262 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/examples/commands/project-id.mjs +74 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +2869 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +31 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +221 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/schemas/cli_command.schema.json +107 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/skills/composable-cli/SKILL.md +63 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/command.mjs +313 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/compile.mjs +19 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/compose.mjs +144 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/contract.mjs +110 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/library.mjs +23 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/registry.mjs +192 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/resolve.mjs +221 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/risk.mjs +126 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/src/ssss-documents.mjs +29 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/DESIGN.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/ui/card.js +273 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/LICENSE +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/README.md +20 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/cli.mjs +310 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +2826 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +11 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +62 -0
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/ui/card.js +297 -0
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/LICENSE +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/README.md +43 -0
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/cli.mjs +258 -0
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package-lock.json +4005 -0
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/package.json +20 -0
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/plugin.json +125 -0
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/DESIGN.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/git-sentinel/ui/card.js +278 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/README.md +9 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/cli.mjs +6 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +4721 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +3 -21
- package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +14 -1
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/cli/mesh.mjs +10 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/headscale-client.mjs +5 -1
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/leader-election.mjs +4 -13
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh-access-verify.mjs +22 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh-files.mjs +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/src/core/mesh.mjs +2 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/test-support/memory-root.mjs +14 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/LICENSE +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/README.md +35 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +124 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +4097 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +12 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +165 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/ingest.mjs +127 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/DESIGN.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/card.js +279 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/panel.js +539 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/LICENSE +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/README.md +67 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/cli.mjs +932 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +3256 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/package.json +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +297 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/scripts/build-ui.mjs +4 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/skills/security/SKILL.md +37 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/src/android.mjs +21 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/src/devices.mjs +94 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/src/machines.mjs +164 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/src/scanner.mjs +41 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/src/windows.mjs +42 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/DESIGN.md +18 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/card.js +95 -0
- package/scaffold/.agent/skills/total-recall/plugins/security/ui/panel.js +98 -0
- package/scaffold/.agent/skills/total-recall/references/auth.md +1 -1
- package/src/cli/brief.mjs +33 -9
- package/src/cli/command.mjs +2 -7
- package/src/cli/config.mjs +1 -0
- package/src/cli/connect.mjs +5 -0
- package/src/cli/context.mjs +2 -1
- package/src/cli/daemon.mjs +36 -1
- package/src/cli/doctor.mjs +6 -0
- package/src/cli/harness.mjs +3 -0
- package/src/cli/help.mjs +26 -0
- package/src/cli/init.mjs +4 -4
- package/src/cli/memory-entry.mjs +1 -0
- package/src/cli/memory-init.mjs +2 -0
- package/src/cli/plugin/index.mjs +11 -0
- package/src/cli/plugin/install.mjs +2 -1
- package/src/cli/rebuild.mjs +3 -1
- package/src/cli/startup.mjs +2 -1
- package/src/cli/update.mjs +19 -0
- package/src/core/automatic-brain-updates.mjs +67 -0
- package/src/core/brain-updates.mjs +21 -2
- package/src/core/cli-commands.mjs +71 -0
- package/src/core/cli-maintenance.mjs +45 -0
- package/src/core/cli-quick-reference.mjs +20 -0
- package/src/core/cli-semantic-index.mjs +722 -0
- package/src/core/context-compiler.mjs +27 -1
- package/src/core/crons.mjs +2 -13
- package/src/core/daemon-control.mjs +6 -4
- package/src/core/daemon-loop.mjs +12 -8
- package/src/core/default-plugins.mjs +5 -0
- package/src/core/global-brain-updates.mjs +39 -0
- package/src/core/mesh-brain-updates.mjs +30 -0
- package/src/core/meta-harness.mjs +108 -0
- package/src/core/plugin-dependencies.mjs +2 -1
- package/src/core/plugin-loader.mjs +2 -1
- package/src/core/plugin-runner.mjs +12 -4
- package/src/core/plugin-setup.mjs +20 -0
- package/src/core/plugin-store.mjs +22 -4
- package/src/core/plugin-tasks.mjs +1 -1
- package/src/core/project-brain.mjs +2 -0
- package/src/core/project-status.mjs +64 -0
- package/src/core/required-plugins.mjs +46 -0
- package/src/core/scaffold-plugins.mjs +17 -3
- package/src/core/source-brain-updates.mjs +47 -0
- package/src/core/startup-health.mjs +5 -3
- package/src/core/surface.mjs +44 -10
- package/src/server/routes/extension.mjs +53 -8
- package/templates/onboarding-interview.md +1 -1
- package/frontend/dist/assets/index-SOVUlZqm.js +0 -5596
package/scaffold/.agent/skills/total-recall/plugins/composable-cli/examples/commands/group.mjs
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* total-recall group <create|add|remove|list|tree|members|delete|show> …
|
|
3
|
+
*
|
|
4
|
+
* Manage groups of projects and groups of groups.
|
|
5
|
+
* Groups are SSSS project_group documents in the global brain.
|
|
6
|
+
*
|
|
7
|
+
* v2 example demonstrating the composable CLI contract with meta export
|
|
8
|
+
* and process.exitCode usage instead of process.exit().
|
|
9
|
+
*
|
|
10
|
+
* Run: total-recall group [--json] <subcommand> ...
|
|
11
|
+
*/
|
|
12
|
+
import fs from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import os from 'node:os';
|
|
15
|
+
import { randomUUID } from 'node:crypto';
|
|
16
|
+
|
|
17
|
+
export const meta = {
|
|
18
|
+
name: 'group',
|
|
19
|
+
description: 'Manage groups of projects and groups of groups (create, add, remove, list, show, tree, members, delete)',
|
|
20
|
+
risk: 'write',
|
|
21
|
+
version: 2,
|
|
22
|
+
background: false,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const DIR = path.join(os.homedir(), '.agent', 'skills', 'total-recall', 'groups');
|
|
26
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
27
|
+
|
|
28
|
+
function die(m, exitCode = 1) {
|
|
29
|
+
process.exitCode = exitCode;
|
|
30
|
+
return { ok: false, error: m, exitCode };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const load = () => {
|
|
34
|
+
if (!fs.existsSync(DIR)) return [];
|
|
35
|
+
return fs.readdirSync(DIR).filter((f) => f.endsWith('.md')).map((f) => {
|
|
36
|
+
const raw = fs.readFileSync(path.join(DIR, f), 'utf8');
|
|
37
|
+
const m = raw.match(/^---\n([\s\S]*?)\n---/);
|
|
38
|
+
if (!m) return null;
|
|
39
|
+
const doc = {};
|
|
40
|
+
for (const line of m[1].split('\n')) {
|
|
41
|
+
const ci = line.indexOf(':');
|
|
42
|
+
if (ci < 0) continue;
|
|
43
|
+
const key = line.slice(0, ci).trim();
|
|
44
|
+
let val = line.slice(ci + 1).trim();
|
|
45
|
+
if (val.startsWith('"') && val.endsWith('"')) val = val.slice(1, -1);
|
|
46
|
+
if (val === 'true') val = true;
|
|
47
|
+
else if (val === 'false') val = false;
|
|
48
|
+
else if (/^\d+$/.test(val)) val = parseInt(val, 10);
|
|
49
|
+
doc[key] = val;
|
|
50
|
+
}
|
|
51
|
+
if (doc.type !== 'project_group') return null;
|
|
52
|
+
// Restore members array from YAML-like list
|
|
53
|
+
const membersMatch = m[1].match(/members:\s*(\[[\s\S]*?\])\s*\n/);
|
|
54
|
+
if (membersMatch) {
|
|
55
|
+
try {
|
|
56
|
+
doc.members = JSON.parse(membersMatch[1].replace(/'/g, '"'));
|
|
57
|
+
} catch {
|
|
58
|
+
doc.members = [];
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
doc.members = [];
|
|
62
|
+
}
|
|
63
|
+
return doc;
|
|
64
|
+
}).filter(Boolean);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function save(g, groups) {
|
|
68
|
+
g.timestamp = new Date().toISOString();
|
|
69
|
+
const body = `---\ntype: project_group\nid: ${g.id}\ntitle: ${g.title}\ndescription: "${(g.description || '').replace(/"/g, '\\"')}"\nmembers: ${JSON.stringify(g.members || [])}\ntimestamp: ${g.timestamp}\n---\n\n# ${g.title}\n\n${g.description || 'Project group.'}\n`;
|
|
70
|
+
fs.mkdirSync(DIR, { recursive: true });
|
|
71
|
+
const file = path.join(DIR, `${g.id}.md`);
|
|
72
|
+
const tmp = `${file}.tmp-${process.pid}`;
|
|
73
|
+
fs.writeFileSync(tmp, body, { mode: 0o644 });
|
|
74
|
+
fs.renameSync(tmp, file);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function flattenMembers(g, byId, seen = new Set()) {
|
|
78
|
+
const out = new Map();
|
|
79
|
+
if (seen.has(g.id)) return out;
|
|
80
|
+
seen.add(g.id);
|
|
81
|
+
for (const m of g.members || []) {
|
|
82
|
+
if (m.type === 'project') out.set(m.id, m);
|
|
83
|
+
else if (byId.has(m.id)) {
|
|
84
|
+
for (const [k, v] of flattenMembers(byId.get(m.id), byId, seen)) out.set(k, v);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function reaches(from, target, byId, seen = new Set()) {
|
|
91
|
+
if (from === target) return true;
|
|
92
|
+
if (seen.has(from)) return false;
|
|
93
|
+
seen.add(from);
|
|
94
|
+
return (byId.get(from)?.members || []).some((m) => m.type === 'group' && reaches(m.id, target, byId, seen));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function findGroup(ref, groups) {
|
|
98
|
+
return groups.find((g) => g.id === ref) || groups.filter((g) => g.title === ref).at(0) || null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function findAll(ref, groups) {
|
|
102
|
+
return groups.filter((g) => g.id === ref || g.title === ref);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function one(ref, groups) {
|
|
106
|
+
const hits = findAll(ref, groups);
|
|
107
|
+
if (hits.length > 1) return { error: `"${ref}" matches ${hits.length} groups — use the id`, group: null };
|
|
108
|
+
if (!hits.length) return { error: `no group "${ref}"`, group: null };
|
|
109
|
+
return { error: null, group: hits[0] };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function printHelp(name) {
|
|
113
|
+
console.log(`Usage: total-recall group <command> [--json]
|
|
114
|
+
|
|
115
|
+
create <name> [--description "<text>"] New group (random UUID id)
|
|
116
|
+
add <group> <member…> Member = project UUID, or group name/UUID
|
|
117
|
+
remove <group> <member…> Remove members
|
|
118
|
+
list All groups
|
|
119
|
+
show <group> One group with direct members
|
|
120
|
+
tree [<group>] Nested view (all roots if omitted)
|
|
121
|
+
members <group> [--recursive] Direct members, or every project reached through nested groups
|
|
122
|
+
delete <group> Delete a group (refused while other groups contain it)
|
|
123
|
+
|
|
124
|
+
Groups are SSSS project_group documents in ${DIR}. Nesting is cycle-checked.`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* v2 entry point — receives (args, context)
|
|
129
|
+
*/
|
|
130
|
+
export default async function main(args = [], context = {}) {
|
|
131
|
+
const { json = false, tr, log } = context;
|
|
132
|
+
|
|
133
|
+
const argl = Array.isArray(args) ? args : [];
|
|
134
|
+
const asJson = json || argl.includes('--json');
|
|
135
|
+
const recursive = argl.includes('--recursive') || argl.includes('-r');
|
|
136
|
+
|
|
137
|
+
// Strip the verb itself from forwarded args
|
|
138
|
+
const cleanArgs = argl.filter((a) => !['group', 'groups'].includes(a) && a !== '--json');
|
|
139
|
+
const pos = cleanArgs.filter((a) => !a.startsWith('-'));
|
|
140
|
+
const [sub, ...rest] = pos;
|
|
141
|
+
|
|
142
|
+
if (!sub || sub === 'help' || cleanArgs.includes('--help') || cleanArgs.includes('-h')) {
|
|
143
|
+
await printHelp(sub);
|
|
144
|
+
return { ok: true, data: null };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
fs.mkdirSync(DIR, { recursive: true });
|
|
148
|
+
const groups = load();
|
|
149
|
+
const byId = new Map(groups.map((g) => [g.id, g]));
|
|
150
|
+
|
|
151
|
+
if (sub === 'create') {
|
|
152
|
+
const name = rest.join(' ').trim();
|
|
153
|
+
if (!name) return die('group create <name>');
|
|
154
|
+
const di = cleanArgs.indexOf('--description');
|
|
155
|
+
const g = { type: 'project_group', id: randomUUID(), title: name, description: di >= 0 ? cleanArgs[di + 1] : '', members: [] };
|
|
156
|
+
save(g, groups);
|
|
157
|
+
const result = { ok: true, group: g };
|
|
158
|
+
if (asJson) return result;
|
|
159
|
+
console.log(` group "${name}" ${g.id}`);
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (sub === 'add' || sub === 'remove') {
|
|
164
|
+
const { group: g, error: err } = one(rest[0], groups);
|
|
165
|
+
if (err) return die(err);
|
|
166
|
+
const refs = rest.slice(1);
|
|
167
|
+
if (!refs.length) return die(`group ${sub} <group> <member…>`);
|
|
168
|
+
const results = [];
|
|
169
|
+
for (const ref of refs) {
|
|
170
|
+
let member = null;
|
|
171
|
+
if (UUID_RE.test(ref)) {
|
|
172
|
+
member = { type: 'project', id: ref };
|
|
173
|
+
} else {
|
|
174
|
+
const g2 = findGroup(ref, groups);
|
|
175
|
+
if (g2) member = { type: 'group', id: g2.id, name: g2.title };
|
|
176
|
+
}
|
|
177
|
+
if (!member) {
|
|
178
|
+
results.push({ ref, ok: false, error: 'not a group or project UUID' });
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (sub === 'add') {
|
|
182
|
+
if (member.type === 'group' && reaches(member.id, g.id, byId)) {
|
|
183
|
+
results.push({ ref, ok: false, error: 'cycle detected' });
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if ((g.members || []).some((x) => x.id === member.id)) {
|
|
187
|
+
results.push({ ref, ok: true, note: 'already a member' });
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
g.members = [...(g.members || []), member];
|
|
191
|
+
results.push({ ref, ok: true, added: member });
|
|
192
|
+
} else {
|
|
193
|
+
const before = (g.members || []).length;
|
|
194
|
+
g.members = (g.members || []).filter((x) => x.id !== member.id);
|
|
195
|
+
results.push({ ref, ok: before !== g.members.length, removed: before !== g.members.length });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
save(g, groups);
|
|
199
|
+
if (results.some((r) => !r.ok)) process.exitCode = 1;
|
|
200
|
+
if (asJson) return { ok: !process.exitCode, group: g.id, results };
|
|
201
|
+
results.forEach((r) => console.log(`${r.ok ? '' : ''} ${r.ref}${r.error ? ' — ' + r.error : r.note ? ' — ' + r.note : ''}`));
|
|
202
|
+
return { ok: !process.exitCode, results };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (sub === 'list') {
|
|
206
|
+
const rows = groups.map((g) => ({ id: g.id, name: g.title, members: (g.members || []).length, projects: flattenMembers(g, byId).size }));
|
|
207
|
+
if (asJson) return { ok: true, data: rows };
|
|
208
|
+
if (rows.length) rows.forEach((r) => console.log(`▸ ${r.name} ${r.id} (${r.members} direct, ${r.projects} projects)`));
|
|
209
|
+
else console.log('No groups yet — total-recall group create <name>');
|
|
210
|
+
return { ok: true, data: rows };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (sub === 'show') {
|
|
214
|
+
const { group: g, error: err } = one(rest[0], groups);
|
|
215
|
+
if (err) return die(err);
|
|
216
|
+
if (asJson) return { ok: true, data: g };
|
|
217
|
+
console.log(`▸ ${g.title} ${g.id}`);
|
|
218
|
+
(g.members || []).forEach((m) => console.log(` ${m.type === 'group' ? '▸' : '•'} ${m.name || m.id}`));
|
|
219
|
+
return { ok: true, data: g };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (sub === 'tree') {
|
|
223
|
+
if (rest[0]) {
|
|
224
|
+
const { group: g, error: err } = one(rest[0], groups);
|
|
225
|
+
if (err) return die(err);
|
|
226
|
+
if (asJson) return { ok: true, data: g };
|
|
227
|
+
console.log(`▸ ${g.title} (${g.id})`);
|
|
228
|
+
(g.members || []).forEach((m) => console.log(` ${m.type === 'group' ? '▸' : '•'} ${m.name || m.id}`));
|
|
229
|
+
return { ok: true, data: g };
|
|
230
|
+
}
|
|
231
|
+
const nested = new Set(groups.flatMap((g) => (g.members || []).filter((m) => m.type === 'group').map((m) => m.id)));
|
|
232
|
+
const roots = groups.filter((g) => !nested.has(g.id));
|
|
233
|
+
if (asJson) return { ok: true, data: roots.map((g) => g.id) };
|
|
234
|
+
roots.forEach((g) => {
|
|
235
|
+
console.log(`▸ ${g.title} (${g.id})`);
|
|
236
|
+
(g.members || []).forEach((m) => console.log(` ${m.type === 'group' ? '▸' : '•'} ${m.name || m.id}`));
|
|
237
|
+
});
|
|
238
|
+
return { ok: true, data: roots.map((g) => g.id) };
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (sub === 'members') {
|
|
242
|
+
const { group: g, error: err } = one(rest[0], groups);
|
|
243
|
+
if (err) return die(err);
|
|
244
|
+
const list = recursive ? [...flattenMembers(g, byId).values()] : (g.members || []);
|
|
245
|
+
if (asJson) return { ok: true, data: list };
|
|
246
|
+
list.forEach((m) => console.log(`${m.type === 'group' ? '▸' : '•'} ${m.name || m.id}`));
|
|
247
|
+
return { ok: true, data: list };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (sub === 'delete') {
|
|
251
|
+
const { group: g, error: err } = one(rest[0], groups);
|
|
252
|
+
if (err) return die(err);
|
|
253
|
+
const parents = groups.filter((x) => (x.members || []).some((m) => m.type === 'group' && m.id === g.id));
|
|
254
|
+
if (parents.length) return die(`"${g.title}" is inside ${parents.map((p) => p.title).join(', ')} — remove it there first`);
|
|
255
|
+
fs.unlinkSync(path.join(DIR, `${g.id}.md`));
|
|
256
|
+
if (asJson) return { ok: true, data: { deleted: g.id } };
|
|
257
|
+
console.log(` deleted "${g.title}"`);
|
|
258
|
+
return { ok: true, data: { deleted: g.id } };
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return die(`unknown subcommand "${sub}" — total-recall group --help`);
|
|
262
|
+
}
|
package/scaffold/.agent/skills/total-recall/plugins/composable-cli/examples/commands/project-id.mjs
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* total-recall project-id [--json] | --all
|
|
3
|
+
*
|
|
4
|
+
* Prints this project's stable random-UUID id, creating it on first use.
|
|
5
|
+
*
|
|
6
|
+
* v2 example demonstrating the composable CLI contract with meta export,
|
|
7
|
+
* tr() composition, and risk declaration.
|
|
8
|
+
*
|
|
9
|
+
* Run: total-recall project-id [--json]
|
|
10
|
+
*/
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import fs from 'node:fs';
|
|
13
|
+
import crypto from 'node:crypto';
|
|
14
|
+
|
|
15
|
+
export const meta = {
|
|
16
|
+
name: 'project-id',
|
|
17
|
+
description: 'Print this project\'s random-UUID project id (created on first use, stored in config/brain.json)',
|
|
18
|
+
risk: 'read',
|
|
19
|
+
version: 2,
|
|
20
|
+
background: false,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const BRAIN_FILE = path.join(process.cwd(), '.agent', 'skills', 'total-recall', 'config', 'brain.json');
|
|
24
|
+
|
|
25
|
+
function readProjectBrain() {
|
|
26
|
+
try {
|
|
27
|
+
if (fs.existsSync(BRAIN_FILE)) {
|
|
28
|
+
return JSON.parse(fs.readFileSync(BRAIN_FILE, 'utf8'));
|
|
29
|
+
}
|
|
30
|
+
} catch { /* not found or invalid */ }
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function ensureProjectId() {
|
|
35
|
+
const brain = readProjectBrain() || {};
|
|
36
|
+
let created = false;
|
|
37
|
+
if (!brain.project_id) {
|
|
38
|
+
brain.project_id = crypto.randomUUID();
|
|
39
|
+
created = true;
|
|
40
|
+
fs.mkdirSync(path.dirname(BRAIN_FILE), { recursive: true });
|
|
41
|
+
fs.writeFileSync(BRAIN_FILE, JSON.stringify(brain, null, 2) + '\n');
|
|
42
|
+
}
|
|
43
|
+
return { project_id: brain.project_id, created };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* v2 entry point — receives (args, context)
|
|
48
|
+
*/
|
|
49
|
+
export default async function main(args = [], context = {}) {
|
|
50
|
+
const { json = false, tr, log } = context;
|
|
51
|
+
|
|
52
|
+
const safeArgs = args.filter((a) => a !== 'project-id');
|
|
53
|
+
|
|
54
|
+
if (safeArgs.includes('--help') || safeArgs.includes('-h')) {
|
|
55
|
+
const usage = 'Usage: total-recall project-id [--json]\n\nPrints this project\'s random-UUID project id.';
|
|
56
|
+
if (json) return { ok: true, data: { usage } };
|
|
57
|
+
console.log(usage);
|
|
58
|
+
return { ok: true, data: null };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const { project_id, created } = ensureProjectId();
|
|
62
|
+
const result = {
|
|
63
|
+
project_id,
|
|
64
|
+
name: path.basename(process.cwd()),
|
|
65
|
+
created,
|
|
66
|
+
path: process.cwd(),
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
if (json) {
|
|
70
|
+
return { ok: true, data: result };
|
|
71
|
+
}
|
|
72
|
+
console.log(project_id);
|
|
73
|
+
return { ok: true, data: result };
|
|
74
|
+
}
|