total-recall-brain 3.32.3 → 3.32.4
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/package.json
CHANGED
package/src/cli/command.mjs
CHANGED
|
@@ -170,7 +170,7 @@ function printHelp() {
|
|
|
170
170
|
`);
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
function resolveTargetDir(isGlobal) {
|
|
173
|
+
export function resolveTargetDir(isGlobal) {
|
|
174
174
|
if (isGlobal) {
|
|
175
175
|
try {
|
|
176
176
|
const gBrain = resolveBrainLayer('global');
|
|
@@ -235,7 +235,7 @@ function existingTag(file, key) {
|
|
|
235
235
|
* Composable instructions: the surfaces list every command, so any change to
|
|
236
236
|
* the command set recompiles them (project layer, or every project for global).
|
|
237
237
|
*/
|
|
238
|
-
function recompileSurfaces(isGlobal) {
|
|
238
|
+
export function recompileSurfaces(isGlobal) {
|
|
239
239
|
if (process.env.TR_COMMAND_NO_COMPILE === '1' || !process.argv[1]) return;
|
|
240
240
|
try {
|
|
241
241
|
const child = spawn(process.execPath, [process.argv[1], 'compile', isGlobal ? '--global' : '--project'], { detached: true, stdio: 'ignore' });
|
|
@@ -246,6 +246,48 @@ function recompileSurfaces(isGlobal) {
|
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Register every `commands` entry of an installed plugin as a composable command.
|
|
251
|
+
* A command that already exists and was generated from this plugin is refreshed;
|
|
252
|
+
* one that exists from anywhere else is left alone and reported.
|
|
253
|
+
*/
|
|
254
|
+
export function syncPluginCommands(pluginDir, { global: isGlobal = false } = {}) {
|
|
255
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(fs.realpathSync(pluginDir), 'plugin.json'), 'utf8'));
|
|
256
|
+
const commandsDir = resolveTargetDir(isGlobal);
|
|
257
|
+
const result = { created: [], skipped: [] };
|
|
258
|
+
for (const entry of manifest.commands || []) {
|
|
259
|
+
const file = path.join(commandsDir, `${entry.name}.mjs`);
|
|
260
|
+
if (fs.existsSync(file)) {
|
|
261
|
+
if (!fs.readFileSync(file, 'utf8').startsWith(`// Generated from plugin ${manifest.id};`)) {
|
|
262
|
+
result.skipped.push({ name: entry.name, reason: 'a different command with this name exists' });
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
fs.rmSync(file);
|
|
266
|
+
}
|
|
267
|
+
generatePluginCommand(pluginDir, entry.name, commandsDir);
|
|
268
|
+
result.created.push(entry.name);
|
|
269
|
+
}
|
|
270
|
+
if (result.created.length) recompileSurfaces(isGlobal);
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Remove the commands a plugin generated (only files carrying its generated header). */
|
|
275
|
+
export function removePluginCommands(pluginId, { global: isGlobal = false } = {}) {
|
|
276
|
+
const commandsDir = resolveTargetDir(isGlobal);
|
|
277
|
+
const removed = [];
|
|
278
|
+
if (!fs.existsSync(commandsDir)) return removed;
|
|
279
|
+
for (const name of fs.readdirSync(commandsDir)) {
|
|
280
|
+
if (!name.endsWith('.mjs')) continue;
|
|
281
|
+
const file = path.join(commandsDir, name);
|
|
282
|
+
if (fs.readFileSync(file, 'utf8').startsWith(`// Generated from plugin ${pluginId};`)) {
|
|
283
|
+
fs.rmSync(file);
|
|
284
|
+
removed.push(name.replace(/\.mjs$/, ''));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (removed.length) recompileSurfaces(isGlobal);
|
|
288
|
+
return removed;
|
|
289
|
+
}
|
|
290
|
+
|
|
249
291
|
export default async function commandCmd(rawArgs = []) {
|
|
250
292
|
const isGlobal = rawArgs.includes('--global') || rawArgs.includes('-g');
|
|
251
293
|
const asJson = rawArgs.includes('--json');
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { installPlugin as install } from '../../core/plugin-store.mjs';
|
|
2
|
+
import { syncPluginCommands } from '../command.mjs';
|
|
2
3
|
|
|
3
4
|
export async function installPlugin(args = []) {
|
|
4
5
|
const isGlobal = args.includes('--global') || args.includes('-g');
|
|
@@ -16,7 +17,11 @@ export async function installPlugin(args = []) {
|
|
|
16
17
|
const from = result.source.kind === 'peer' ? `peer ${result.source.peer_hostname}` : result.source.kind;
|
|
17
18
|
console.log(`\n✅ Installed '${result.plugin.name}' (id: ${result.plugin.id}, v${result.plugin.version}) from ${from}`);
|
|
18
19
|
console.log(` Location: ${result.plugin.dir}`);
|
|
19
|
-
console.log(` sha256: ${result.sha256}
|
|
20
|
+
console.log(` sha256: ${result.sha256}`);
|
|
21
|
+
const cmds = syncPluginCommands(result.plugin.dir, { global: isGlobal });
|
|
22
|
+
if (cmds.created.length) console.log(` Commands: ${cmds.created.map((c) => `total-recall ${c}`).join(', ')}`);
|
|
23
|
+
for (const c of cmds.skipped) console.log(` Skipped command '${c.name}': ${c.reason}`);
|
|
24
|
+
console.log('');
|
|
20
25
|
} catch (err) {
|
|
21
26
|
console.error(`❌ ${err.message}`);
|
|
22
27
|
process.exit(1);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { uninstallPlugin, setPluginShared } from '../../core/plugin-store.mjs';
|
|
2
|
+
import { removePluginCommands } from '../command.mjs';
|
|
2
3
|
import { publicPluginShareUrl } from '../../core/plugin-public.mjs';
|
|
3
4
|
|
|
4
5
|
export async function removePlugin(args = []) {
|
|
@@ -13,7 +14,10 @@ export async function removePlugin(args = []) {
|
|
|
13
14
|
|
|
14
15
|
try {
|
|
15
16
|
const result = await uninstallPlugin(id, { projectRoot: process.cwd(), global: isGlobal ? true : undefined });
|
|
16
|
-
|
|
17
|
+
const removed = removePluginCommands(id, { global: result.scope === 'global' });
|
|
18
|
+
console.log(`\n✅ Removed plugin '${id}' (${result.scope}) from ${result.dir}`);
|
|
19
|
+
if (removed.length) console.log(` Removed commands: ${removed.join(', ')}`);
|
|
20
|
+
console.log('');
|
|
17
21
|
} catch (err) {
|
|
18
22
|
console.error(`❌ ${err.message}`);
|
|
19
23
|
process.exit(1);
|
package/src/core/env-import.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import fs from 'node:fs';
|
|
|
10
10
|
import path from 'node:path';
|
|
11
11
|
import os from 'node:os';
|
|
12
12
|
import { setSecret, listSecretsMeta, updateSecretMeta } from './secrets-store.mjs';
|
|
13
|
+
import { providerForKeyName } from './provider-catalog.mjs';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* @deprecated Kept as empty/export for older callers. Import does NOT use this
|
|
@@ -108,13 +109,9 @@ export function inferProvider(key) {
|
|
|
108
109
|
if (!key) return null;
|
|
109
110
|
const k = String(key);
|
|
110
111
|
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// Use sync require-free approach: duplicate-free segment heuristic only here for speed.
|
|
115
|
-
} catch {
|
|
116
|
-
/* ignore */
|
|
117
|
-
}
|
|
112
|
+
// A known provider anywhere in the key name wins (JSN_SMTP2GO_API_KEY -> smtp2go).
|
|
113
|
+
const known = providerForKeyName(k);
|
|
114
|
+
if (known) return known.id;
|
|
118
115
|
|
|
119
116
|
// Strip common prefixes that are not the vendor
|
|
120
117
|
let base = k
|