@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.
Files changed (57) hide show
  1. package/dist/commands/briefing.d.ts +7 -0
  2. package/dist/commands/briefing.d.ts.map +1 -0
  3. package/dist/commands/briefing.js +134 -0
  4. package/dist/commands/briefing.js.map +1 -0
  5. package/dist/commands/handoff.d.ts +7 -0
  6. package/dist/commands/handoff.d.ts.map +1 -0
  7. package/dist/commands/handoff.js +119 -0
  8. package/dist/commands/handoff.js.map +1 -0
  9. package/dist/commands/init.d.ts +2 -0
  10. package/dist/commands/init.d.ts.map +1 -0
  11. package/dist/commands/init.js +227 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/commands/install-hooks.d.ts +4 -0
  14. package/dist/commands/install-hooks.d.ts.map +1 -0
  15. package/dist/commands/install-hooks.js +125 -0
  16. package/dist/commands/install-hooks.js.map +1 -0
  17. package/dist/commands/learn.d.ts +14 -0
  18. package/dist/commands/learn.d.ts.map +1 -0
  19. package/dist/commands/learn.js +323 -0
  20. package/dist/commands/learn.js.map +1 -0
  21. package/dist/commands/search.d.ts +5 -0
  22. package/dist/commands/search.d.ts.map +1 -0
  23. package/dist/commands/search.js +31 -0
  24. package/dist/commands/search.js.map +1 -0
  25. package/dist/commands/shield.d.ts +8 -0
  26. package/dist/commands/shield.d.ts.map +1 -0
  27. package/dist/commands/shield.js +130 -0
  28. package/dist/commands/shield.js.map +1 -0
  29. package/dist/commands/spec.d.ts +7 -0
  30. package/dist/commands/spec.d.ts.map +1 -0
  31. package/dist/commands/spec.js +159 -0
  32. package/dist/commands/spec.js.map +1 -0
  33. package/dist/commands/stats.d.ts +2 -0
  34. package/dist/commands/stats.d.ts.map +1 -0
  35. package/dist/commands/stats.js +22 -0
  36. package/dist/commands/stats.js.map +1 -0
  37. package/dist/commands/sync.d.ts +4 -0
  38. package/dist/commands/sync.d.ts.map +1 -0
  39. package/dist/commands/sync.js +16 -0
  40. package/dist/commands/sync.js.map +1 -0
  41. package/dist/commands/triage.d.ts +7 -0
  42. package/dist/commands/triage.d.ts.map +1 -0
  43. package/dist/commands/triage.js +149 -0
  44. package/dist/commands/triage.js.map +1 -0
  45. package/dist/git.d.ts +12 -0
  46. package/dist/git.d.ts.map +1 -0
  47. package/dist/git.js +127 -0
  48. package/dist/git.js.map +1 -0
  49. package/dist/index.d.ts +3 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +178 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/utils.d.ts +48 -0
  54. package/dist/utils.d.ts.map +1 -0
  55. package/dist/utils.js +224 -0
  56. package/dist/utils.js.map +1 -0
  57. 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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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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"}
@@ -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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"}