@mmnto/cli 0.1.0
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/commands/briefing.d.ts +7 -0
- package/dist/commands/briefing.d.ts.map +1 -0
- package/dist/commands/briefing.js +134 -0
- package/dist/commands/briefing.js.map +1 -0
- package/dist/commands/handoff.d.ts +7 -0
- package/dist/commands/handoff.d.ts.map +1 -0
- package/dist/commands/handoff.js +119 -0
- package/dist/commands/handoff.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +227 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install-hooks.d.ts +4 -0
- package/dist/commands/install-hooks.d.ts.map +1 -0
- package/dist/commands/install-hooks.js +125 -0
- package/dist/commands/install-hooks.js.map +1 -0
- package/dist/commands/learn.d.ts +14 -0
- package/dist/commands/learn.d.ts.map +1 -0
- package/dist/commands/learn.js +323 -0
- package/dist/commands/learn.js.map +1 -0
- package/dist/commands/search.d.ts +5 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +31 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/shield.d.ts +8 -0
- package/dist/commands/shield.d.ts.map +1 -0
- package/dist/commands/shield.js +130 -0
- package/dist/commands/shield.js.map +1 -0
- package/dist/commands/spec.d.ts +7 -0
- package/dist/commands/spec.d.ts.map +1 -0
- package/dist/commands/spec.js +159 -0
- package/dist/commands/spec.js.map +1 -0
- package/dist/commands/stats.d.ts +2 -0
- package/dist/commands/stats.d.ts.map +1 -0
- package/dist/commands/stats.js +22 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/sync.d.ts +4 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +16 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/triage.d.ts +7 -0
- package/dist/commands/triage.d.ts.map +1 -0
- package/dist/commands/triage.js +149 -0
- package/dist/commands/triage.js.map +1 -0
- package/dist/git.d.ts +12 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +127 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +178 -0
- package/dist/index.js.map +1 -0
- package/dist/utils.d.ts +48 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +224 -0
- package/dist/utils.js.map +1 -0
- package/package.json +51 -0
package/dist/git.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { IS_WIN } from './utils.js';
|
|
3
|
+
// ─── Constants ──────────────────────────────────────────
|
|
4
|
+
const GIT_COMMAND_TIMEOUT_MS = 15_000;
|
|
5
|
+
function throwIfGitMissing(err) {
|
|
6
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7
|
+
if (msg.includes('ENOENT') || msg.includes('not found')) {
|
|
8
|
+
throw new Error(`[Totem Error] 'git' command not found. Ensure Git is installed and in your PATH.`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
// ─── Git helpers ────────────────────────────────────────
|
|
12
|
+
export function getGitBranch(cwd) {
|
|
13
|
+
try {
|
|
14
|
+
return execFileSync('git', ['branch', '--show-current'], {
|
|
15
|
+
cwd,
|
|
16
|
+
encoding: 'utf-8',
|
|
17
|
+
shell: IS_WIN,
|
|
18
|
+
}).trim();
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return '(unknown)';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function getGitStatus(cwd) {
|
|
25
|
+
try {
|
|
26
|
+
return execFileSync('git', ['status', '--porcelain'], {
|
|
27
|
+
cwd,
|
|
28
|
+
encoding: 'utf-8',
|
|
29
|
+
shell: IS_WIN,
|
|
30
|
+
}).trim();
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return '';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function getGitDiff(mode, cwd) {
|
|
37
|
+
const args = mode === 'staged' ? ['diff', '--staged'] : ['diff', 'HEAD'];
|
|
38
|
+
try {
|
|
39
|
+
return execFileSync('git', args, {
|
|
40
|
+
cwd,
|
|
41
|
+
encoding: 'utf-8',
|
|
42
|
+
timeout: GIT_COMMAND_TIMEOUT_MS,
|
|
43
|
+
shell: IS_WIN,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
throwIfGitMissing(err);
|
|
48
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
49
|
+
throw new Error(`[Totem Error] Failed to get git diff: ${msg}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export function getGitDiffStat(cwd) {
|
|
53
|
+
try {
|
|
54
|
+
return execFileSync('git', ['diff', 'HEAD', '--stat'], {
|
|
55
|
+
cwd,
|
|
56
|
+
encoding: 'utf-8',
|
|
57
|
+
timeout: GIT_COMMAND_TIMEOUT_MS,
|
|
58
|
+
shell: IS_WIN,
|
|
59
|
+
}).trim();
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return '';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Detect the default branch of the remote (e.g. main, master).
|
|
67
|
+
* Falls back to 'main' if detection fails.
|
|
68
|
+
*/
|
|
69
|
+
export function getDefaultBranch(cwd) {
|
|
70
|
+
try {
|
|
71
|
+
const ref = execFileSync('git', ['symbolic-ref', 'refs/remotes/origin/HEAD', '--short'], {
|
|
72
|
+
cwd,
|
|
73
|
+
encoding: 'utf-8',
|
|
74
|
+
timeout: GIT_COMMAND_TIMEOUT_MS,
|
|
75
|
+
shell: IS_WIN,
|
|
76
|
+
}).trim();
|
|
77
|
+
// ref is like "origin/main" — strip the remote prefix
|
|
78
|
+
return ref.replace(/^origin\//, '');
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
throwIfGitMissing(err);
|
|
82
|
+
// Fallback: check if 'main' exists, then 'master'
|
|
83
|
+
for (const branch of ['main', 'master']) {
|
|
84
|
+
try {
|
|
85
|
+
execFileSync('git', ['rev-parse', '--verify', branch], {
|
|
86
|
+
cwd,
|
|
87
|
+
encoding: 'utf-8',
|
|
88
|
+
timeout: GIT_COMMAND_TIMEOUT_MS,
|
|
89
|
+
shell: IS_WIN,
|
|
90
|
+
});
|
|
91
|
+
return branch;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Try next candidate
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
throw new Error(`[Totem Error] Could not determine default branch. Neither 'main' nor 'master' found locally, and 'git symbolic-ref' failed.`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export function getGitBranchDiff(cwd, base) {
|
|
101
|
+
const baseBranch = base ?? getDefaultBranch(cwd);
|
|
102
|
+
try {
|
|
103
|
+
return execFileSync('git', ['diff', `${baseBranch}...HEAD`], {
|
|
104
|
+
cwd,
|
|
105
|
+
encoding: 'utf-8',
|
|
106
|
+
timeout: GIT_COMMAND_TIMEOUT_MS,
|
|
107
|
+
shell: IS_WIN,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
throwIfGitMissing(err);
|
|
112
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
113
|
+
throw new Error(`[Totem Error] Failed to get branch diff (${baseBranch}...HEAD): ${msg}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export function extractChangedFiles(diff) {
|
|
117
|
+
const files = [];
|
|
118
|
+
for (const line of diff.split('\n')) {
|
|
119
|
+
if (line.startsWith('diff --git')) {
|
|
120
|
+
const match = line.match(/^diff --git a\/.+ b\/(.+)$/);
|
|
121
|
+
if (match)
|
|
122
|
+
files.push(match[1]);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return files;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { initCommand } from './commands/init.js';
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const { version } = z.object({ version: z.string() }).parse(require('../package.json'));
|
|
8
|
+
function handleError(err) {
|
|
9
|
+
if (err instanceof Error) {
|
|
10
|
+
console.error(err.message);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
console.error('[Totem Error] An unknown error occurred:', err);
|
|
14
|
+
}
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const program = new Command();
|
|
18
|
+
program
|
|
19
|
+
.name('totem')
|
|
20
|
+
.description('Totem — persistent memory and context layer for AI agents')
|
|
21
|
+
.version(version);
|
|
22
|
+
program
|
|
23
|
+
.command('init')
|
|
24
|
+
.description('Initialize Totem in the current project')
|
|
25
|
+
.action(async () => {
|
|
26
|
+
try {
|
|
27
|
+
await initCommand();
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
handleError(err);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
program
|
|
34
|
+
.command('sync')
|
|
35
|
+
.description('Re-index project files into the local vector store')
|
|
36
|
+
.option('--full', 'Force a full re-index (ignores incremental)')
|
|
37
|
+
.option('--incremental', 'Run an incremental sync (default behavior)')
|
|
38
|
+
.action(async (opts) => {
|
|
39
|
+
try {
|
|
40
|
+
const { syncCommand } = await import('./commands/sync.js');
|
|
41
|
+
await syncCommand(opts);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
handleError(err);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
program
|
|
48
|
+
.command('search <query>')
|
|
49
|
+
.description('Search the knowledge index')
|
|
50
|
+
.option('-t, --type <type>', 'Filter by content type (code, session_log, spec)')
|
|
51
|
+
.option('-n, --max-results <n>', 'Maximum results to return', '5')
|
|
52
|
+
.action(async (query, opts) => {
|
|
53
|
+
try {
|
|
54
|
+
const { searchCommand } = await import('./commands/search.js');
|
|
55
|
+
await searchCommand(query, opts);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
handleError(err);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
program
|
|
62
|
+
.command('stats')
|
|
63
|
+
.description('Show index statistics')
|
|
64
|
+
.action(async () => {
|
|
65
|
+
try {
|
|
66
|
+
const { statsCommand } = await import('./commands/stats.js');
|
|
67
|
+
await statsCommand();
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
handleError(err);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
program
|
|
74
|
+
.command('spec <input>')
|
|
75
|
+
.description('Generate a pre-work spec briefing for a GitHub issue or topic')
|
|
76
|
+
.option('--raw', 'Output retrieved context without LLM synthesis')
|
|
77
|
+
.option('--out <path>', 'Write output to a file instead of stdout')
|
|
78
|
+
.option('--model <name>', 'Override the default model for the orchestrator')
|
|
79
|
+
.action(async (input, opts) => {
|
|
80
|
+
try {
|
|
81
|
+
const { specCommand } = await import('./commands/spec.js');
|
|
82
|
+
await specCommand(input, opts);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
handleError(err);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
program
|
|
89
|
+
.command('briefing')
|
|
90
|
+
.description('Generate a session startup briefing with current context')
|
|
91
|
+
.option('--raw', 'Output retrieved context without LLM synthesis')
|
|
92
|
+
.option('--out <path>', 'Write output to a file instead of stdout')
|
|
93
|
+
.option('--model <name>', 'Override the default model for the orchestrator')
|
|
94
|
+
.action(async (opts) => {
|
|
95
|
+
try {
|
|
96
|
+
const { briefingCommand } = await import('./commands/briefing.js');
|
|
97
|
+
await briefingCommand(opts);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
handleError(err);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
program
|
|
104
|
+
.command('shield')
|
|
105
|
+
.description('Pre-flight code review: analyze your diff against Totem knowledge')
|
|
106
|
+
.option('--raw', 'Output retrieved context without LLM synthesis')
|
|
107
|
+
.option('--out <path>', 'Write output to a file instead of stdout')
|
|
108
|
+
.option('--model <name>', 'Override the default model for the orchestrator')
|
|
109
|
+
.option('--staged', 'Review only staged changes (default: all uncommitted)')
|
|
110
|
+
.action(async (opts) => {
|
|
111
|
+
try {
|
|
112
|
+
const { shieldCommand } = await import('./commands/shield.js');
|
|
113
|
+
await shieldCommand(opts);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
handleError(err);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
program
|
|
120
|
+
.command('triage')
|
|
121
|
+
.description('Prioritize open issues into an active work roadmap')
|
|
122
|
+
.option('--raw', 'Output retrieved context without LLM synthesis')
|
|
123
|
+
.option('--out <path>', 'Write output to a file instead of stdout')
|
|
124
|
+
.option('--model <name>', 'Override the default model for the orchestrator')
|
|
125
|
+
.action(async (opts) => {
|
|
126
|
+
try {
|
|
127
|
+
const { triageCommand } = await import('./commands/triage.js');
|
|
128
|
+
await triageCommand(opts);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
handleError(err);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
program
|
|
135
|
+
.command('handoff')
|
|
136
|
+
.description('Generate an end-of-session handoff snapshot for the next session')
|
|
137
|
+
.option('--raw', 'Output retrieved context without LLM synthesis')
|
|
138
|
+
.option('--out <path>', 'Write output to a file instead of stdout')
|
|
139
|
+
.option('--model <name>', 'Override the default model for the orchestrator')
|
|
140
|
+
.action(async (opts) => {
|
|
141
|
+
try {
|
|
142
|
+
const { handoffCommand } = await import('./commands/handoff.js');
|
|
143
|
+
await handoffCommand(opts);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
handleError(err);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
program
|
|
150
|
+
.command('learn <pr-number>')
|
|
151
|
+
.description('Extract lessons from a PR review into .totem/lessons.md')
|
|
152
|
+
.option('--raw', 'Output assembled prompt without LLM synthesis')
|
|
153
|
+
.option('--out <path>', 'Write output to a file instead of stdout')
|
|
154
|
+
.option('--model <name>', 'Override the default model for the orchestrator')
|
|
155
|
+
.option('--dry-run', 'Show extracted lessons without writing to lessons.md')
|
|
156
|
+
.action(async (prNumber, opts) => {
|
|
157
|
+
try {
|
|
158
|
+
const { learnCommand } = await import('./commands/learn.js');
|
|
159
|
+
await learnCommand(prNumber, opts);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
handleError(err);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
program
|
|
166
|
+
.command('install-hooks')
|
|
167
|
+
.description('Install post-merge git hook for automatic Totem sync')
|
|
168
|
+
.action(async () => {
|
|
169
|
+
try {
|
|
170
|
+
const { installHooksCommand } = await import('./commands/install-hooks.js');
|
|
171
|
+
await installHooksCommand();
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
handleError(err);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
program.parse();
|
|
178
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { SearchResult, TotemConfig } from '@mmnto/totem';
|
|
2
|
+
/** execFileSync on Windows can't resolve executables without `shell: true`. */
|
|
3
|
+
export declare const IS_WIN: boolean;
|
|
4
|
+
/** Timeout for GitHub CLI calls (ms). */
|
|
5
|
+
export declare const GH_TIMEOUT_MS = 15000;
|
|
6
|
+
/**
|
|
7
|
+
* Load environment variables from .env file (does not override existing).
|
|
8
|
+
*/
|
|
9
|
+
export declare function loadEnv(cwd: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* Load and parse totem.config.ts via jiti.
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadConfig(configPath: string): Promise<TotemConfig>;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve config path and validate it exists. Exits if missing.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveConfigPath(cwd: string): string;
|
|
18
|
+
export interface OrchestratorResult {
|
|
19
|
+
content: string;
|
|
20
|
+
inputTokens: number | null;
|
|
21
|
+
outputTokens: number | null;
|
|
22
|
+
durationMs: number;
|
|
23
|
+
}
|
|
24
|
+
export declare function invokeShellOrchestrator(prompt: string, command: string, model: string, cwd: string, tag: string, totemDir: string): OrchestratorResult;
|
|
25
|
+
export declare function writeOutput(content: string, outPath?: string): void;
|
|
26
|
+
export declare function formatResults(results: SearchResult[], heading: string): string;
|
|
27
|
+
export interface OrchestratorRunOptions {
|
|
28
|
+
raw?: boolean;
|
|
29
|
+
out?: string;
|
|
30
|
+
model?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Validate orchestrator config, then either output raw context (--raw) or
|
|
34
|
+
* invoke the shell orchestrator and return the LLM content.
|
|
35
|
+
*
|
|
36
|
+
* Returns `undefined` in --raw mode (prompt already written to output).
|
|
37
|
+
* Returns the LLM response content string otherwise.
|
|
38
|
+
* Callers are responsible for writing output via `writeOutput()`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function runOrchestrator(opts: {
|
|
41
|
+
prompt: string;
|
|
42
|
+
tag: string;
|
|
43
|
+
options: OrchestratorRunOptions;
|
|
44
|
+
config: TotemConfig;
|
|
45
|
+
cwd: string;
|
|
46
|
+
totalResults?: number;
|
|
47
|
+
}): string | undefined;
|
|
48
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAU9D,+EAA+E;AAC/E,eAAO,MAAM,MAAM,SAA+B,CAAC;AAEnD,yCAAyC;AACzC,eAAO,MAAM,aAAa,QAAS,CAAC;AAEpC;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAezC;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAMzE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMrD;AAcD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAyDD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GACf,kBAAkB,CA2CpB;AAID,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAUnE;AAMD,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAS9E;AAID,MAAM,WAAW,sBAAsB;IACrC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,sBAAsB,CAAC;IAChC,MAAM,EAAE,WAAW,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,MAAM,GAAG,SAAS,CAyErB"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import * as crypto from 'node:crypto';
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { TotemConfigSchema } from '@mmnto/totem';
|
|
7
|
+
// ─── Shared constants ────────────────────────────────────
|
|
8
|
+
const LLM_TIMEOUT_MS = 180_000;
|
|
9
|
+
const TEMP_ID_BYTES = 4;
|
|
10
|
+
const MODEL_NAME_RE = /^[\w./:_-]+$/;
|
|
11
|
+
const TELEMETRY_FILE = 'telemetry.jsonl';
|
|
12
|
+
/** execFileSync on Windows can't resolve executables without `shell: true`. */
|
|
13
|
+
export const IS_WIN = process.platform === 'win32';
|
|
14
|
+
/** Timeout for GitHub CLI calls (ms). */
|
|
15
|
+
export const GH_TIMEOUT_MS = 15_000;
|
|
16
|
+
/**
|
|
17
|
+
* Load environment variables from .env file (does not override existing).
|
|
18
|
+
*/
|
|
19
|
+
export function loadEnv(cwd) {
|
|
20
|
+
const envPath = path.join(cwd, '.env');
|
|
21
|
+
if (!fs.existsSync(envPath))
|
|
22
|
+
return;
|
|
23
|
+
const content = fs.readFileSync(envPath, 'utf-8');
|
|
24
|
+
for (const line of content.split('\n')) {
|
|
25
|
+
const match = line.match(/^([^#=]+)=(.*)$/);
|
|
26
|
+
if (match) {
|
|
27
|
+
const key = match[1].trim();
|
|
28
|
+
const value = match[2].trim();
|
|
29
|
+
if (!process.env[key]) {
|
|
30
|
+
process.env[key] = value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Load and parse totem.config.ts via jiti.
|
|
37
|
+
*/
|
|
38
|
+
export async function loadConfig(configPath) {
|
|
39
|
+
const { createJiti } = await import('jiti');
|
|
40
|
+
const jiti = createJiti(import.meta.url);
|
|
41
|
+
const mod = (await jiti.import(configPath));
|
|
42
|
+
const raw = mod['default'] ?? mod;
|
|
43
|
+
return TotemConfigSchema.parse(raw);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolve config path and validate it exists. Exits if missing.
|
|
47
|
+
*/
|
|
48
|
+
export function resolveConfigPath(cwd) {
|
|
49
|
+
const configPath = path.join(cwd, 'totem.config.ts');
|
|
50
|
+
if (!fs.existsSync(configPath)) {
|
|
51
|
+
throw new Error('[Totem Error] No totem.config.ts found. Run `totem init` first.');
|
|
52
|
+
}
|
|
53
|
+
return configPath;
|
|
54
|
+
}
|
|
55
|
+
function appendTelemetry(entry, cwd, totemDir) {
|
|
56
|
+
try {
|
|
57
|
+
const tempDir = path.join(cwd, totemDir, 'temp');
|
|
58
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
59
|
+
fs.appendFileSync(path.join(tempDir, TELEMETRY_FILE), JSON.stringify(entry) + '\n', 'utf-8');
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
// Telemetry is best-effort — never block the command, but warn on failure
|
|
63
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
64
|
+
console.error(`[Totem Warning] Failed to write telemetry: ${msg}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const GeminiModelStatsSchema = z.object({
|
|
68
|
+
tokens: z.object({ input: z.number(), candidates: z.number() }).optional(),
|
|
69
|
+
api: z.object({ totalLatencyMs: z.number() }).optional(),
|
|
70
|
+
});
|
|
71
|
+
const GeminiOutputSchema = z.object({
|
|
72
|
+
response: z.string(),
|
|
73
|
+
stats: z.object({ models: z.record(GeminiModelStatsSchema) }),
|
|
74
|
+
});
|
|
75
|
+
/**
|
|
76
|
+
* Try to parse Gemini CLI JSON output. Returns extracted data or null if
|
|
77
|
+
* the output is not valid Gemini JSON (e.g. raw text from a non-Gemini orchestrator).
|
|
78
|
+
*/
|
|
79
|
+
function tryParseGeminiJson(raw) {
|
|
80
|
+
let data;
|
|
81
|
+
try {
|
|
82
|
+
data = JSON.parse(raw);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const result = GeminiOutputSchema.safeParse(data);
|
|
88
|
+
if (!result.success)
|
|
89
|
+
return null;
|
|
90
|
+
const modelKey = Object.keys(result.data.stats.models)[0];
|
|
91
|
+
if (!modelKey)
|
|
92
|
+
return null;
|
|
93
|
+
const modelStats = result.data.stats.models[modelKey];
|
|
94
|
+
if (!modelStats)
|
|
95
|
+
return null;
|
|
96
|
+
return {
|
|
97
|
+
content: result.data.response,
|
|
98
|
+
inputTokens: modelStats.tokens?.input ?? 0,
|
|
99
|
+
outputTokens: modelStats.tokens?.candidates ?? 0,
|
|
100
|
+
latencyMs: modelStats.api?.totalLatencyMs ?? null,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// ─── Shell orchestrator ─────────────────────────────────
|
|
104
|
+
export function invokeShellOrchestrator(prompt, command, model, cwd, tag, totemDir) {
|
|
105
|
+
const tmpName = `totem-${tag.toLowerCase()}-${crypto.randomBytes(TEMP_ID_BYTES).toString('hex')}.md`;
|
|
106
|
+
const tempDir = path.join(cwd, totemDir, 'temp');
|
|
107
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
108
|
+
const tempPath = path.join(tempDir, tmpName);
|
|
109
|
+
try {
|
|
110
|
+
fs.writeFileSync(tempPath, prompt, { encoding: 'utf-8', mode: 0o600 });
|
|
111
|
+
const resolvedCmd = command.replace(/\{file\}/g, `"${tempPath}"`).replace(/\{model\}/g, model);
|
|
112
|
+
console.error(`[${tag}] Invoking orchestrator (this may take 15-60 seconds)...`);
|
|
113
|
+
const startMs = Date.now();
|
|
114
|
+
const raw = execSync(resolvedCmd, {
|
|
115
|
+
cwd,
|
|
116
|
+
encoding: 'utf-8',
|
|
117
|
+
timeout: LLM_TIMEOUT_MS,
|
|
118
|
+
stdio: ['pipe', 'pipe', 'inherit'],
|
|
119
|
+
});
|
|
120
|
+
const wallMs = Date.now() - startMs;
|
|
121
|
+
const gemini = tryParseGeminiJson(raw);
|
|
122
|
+
if (gemini) {
|
|
123
|
+
return {
|
|
124
|
+
content: gemini.content,
|
|
125
|
+
inputTokens: gemini.inputTokens,
|
|
126
|
+
outputTokens: gemini.outputTokens,
|
|
127
|
+
durationMs: gemini.latencyMs ?? wallMs,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return { content: raw.trim(), inputTokens: null, outputTokens: null, durationMs: wallMs };
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
134
|
+
throw new Error(`[Totem Error] Shell orchestrator command failed: ${msg}`);
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
try {
|
|
138
|
+
fs.unlinkSync(tempPath);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Temp cleanup is best-effort
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// ─── Output helpers ─────────────────────────────────────
|
|
146
|
+
export function writeOutput(content, outPath) {
|
|
147
|
+
if (outPath) {
|
|
148
|
+
const dir = path.dirname(outPath);
|
|
149
|
+
if (!fs.existsSync(dir)) {
|
|
150
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
151
|
+
}
|
|
152
|
+
fs.writeFileSync(outPath, content, 'utf-8');
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
console.log(content);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// ─── Context formatting ─────────────────────────────────
|
|
159
|
+
const MAX_RESULT_CONTENT_LENGTH = 300;
|
|
160
|
+
export function formatResults(results, heading) {
|
|
161
|
+
if (results.length === 0)
|
|
162
|
+
return '';
|
|
163
|
+
const items = results
|
|
164
|
+
.map((r) => `- **${r.label}** (${r.filePath}, score: ${r.score.toFixed(3)})\n ${r.content.slice(0, MAX_RESULT_CONTENT_LENGTH).replace(/\n/g, '\n ')}`)
|
|
165
|
+
.join('\n\n');
|
|
166
|
+
return `\n=== ${heading} ===\n${items}\n`;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Validate orchestrator config, then either output raw context (--raw) or
|
|
170
|
+
* invoke the shell orchestrator and return the LLM content.
|
|
171
|
+
*
|
|
172
|
+
* Returns `undefined` in --raw mode (prompt already written to output).
|
|
173
|
+
* Returns the LLM response content string otherwise.
|
|
174
|
+
* Callers are responsible for writing output via `writeOutput()`.
|
|
175
|
+
*/
|
|
176
|
+
export function runOrchestrator(opts) {
|
|
177
|
+
const { prompt, tag, options, config, cwd } = opts;
|
|
178
|
+
// --raw mode: output context only
|
|
179
|
+
if (options.raw) {
|
|
180
|
+
writeOutput(prompt, options.out);
|
|
181
|
+
const suffix = opts.totalResults != null ? ` (${opts.totalResults} chunks)` : '';
|
|
182
|
+
console.error(`[${tag}] Raw context output complete${suffix}.`);
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
// Require orchestrator for LLM synthesis
|
|
186
|
+
if (!config.orchestrator) {
|
|
187
|
+
throw new Error(`[Totem Error] No orchestrator configured. Add an 'orchestrator' block to totem.config.ts.\n` +
|
|
188
|
+
`Example:\n orchestrator: {\n provider: 'shell',\n command: 'gemini --model {model} -e none < {file}',\n defaultModel: 'gemini-2.5-pro',\n }`);
|
|
189
|
+
}
|
|
190
|
+
if (config.orchestrator.provider !== 'shell') {
|
|
191
|
+
throw new Error(`[Totem Error] Unsupported orchestrator provider: '${config.orchestrator.provider}'. Only 'shell' is supported.`);
|
|
192
|
+
}
|
|
193
|
+
const model = options.model ?? config.orchestrator.defaultModel;
|
|
194
|
+
if (!model) {
|
|
195
|
+
throw new Error(`[Totem Error] No model specified. Provide one with --model or set 'defaultModel' in your orchestrator config.`);
|
|
196
|
+
}
|
|
197
|
+
if (model.startsWith('-') || !MODEL_NAME_RE.test(model)) {
|
|
198
|
+
throw new Error(`[Totem Error] Invalid model name '${model}'. Model names may not start with a hyphen and may only contain word characters, dots, slashes, colons, underscores, and hyphens.`);
|
|
199
|
+
}
|
|
200
|
+
console.error(`[${tag}] Model: ${model}`);
|
|
201
|
+
const result = invokeShellOrchestrator(prompt, config.orchestrator.command, model, cwd, tag, config.totemDir);
|
|
202
|
+
// Log telemetry
|
|
203
|
+
appendTelemetry({
|
|
204
|
+
timestamp: new Date().toISOString(),
|
|
205
|
+
tag,
|
|
206
|
+
model,
|
|
207
|
+
promptChars: prompt.length,
|
|
208
|
+
inputTokens: result.inputTokens,
|
|
209
|
+
outputTokens: result.outputTokens,
|
|
210
|
+
durationMs: result.durationMs,
|
|
211
|
+
}, cwd, config.totemDir);
|
|
212
|
+
// Console summary
|
|
213
|
+
const secs = (result.durationMs / 1000).toFixed(1);
|
|
214
|
+
if (result.inputTokens != null && result.outputTokens != null) {
|
|
215
|
+
const inTok = result.inputTokens.toLocaleString();
|
|
216
|
+
const outTok = result.outputTokens.toLocaleString();
|
|
217
|
+
console.error(`[${tag}] Done: ${secs}s | ${inTok} in | ${outTok} out`);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
console.error(`[${tag}] Done: ${secs}s | ${(prompt.length / 1024).toFixed(0)}KB prompt`);
|
|
221
|
+
}
|
|
222
|
+
return result.content;
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|