@mmnto/cli 0.6.0 → 0.8.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/adapters/gh-utils.d.ts +12 -0
- package/dist/adapters/gh-utils.d.ts.map +1 -0
- package/dist/adapters/gh-utils.js +53 -0
- package/dist/adapters/gh-utils.js.map +1 -0
- package/dist/adapters/gh-utils.test.d.ts +2 -0
- package/dist/adapters/gh-utils.test.d.ts.map +1 -0
- package/dist/adapters/gh-utils.test.js +81 -0
- package/dist/adapters/gh-utils.test.js.map +1 -0
- package/dist/adapters/github-cli-pr.d.ts +10 -0
- package/dist/adapters/github-cli-pr.d.ts.map +1 -0
- package/dist/adapters/github-cli-pr.js +83 -0
- package/dist/adapters/github-cli-pr.js.map +1 -0
- package/dist/adapters/github-cli-pr.test.d.ts +2 -0
- package/dist/adapters/github-cli-pr.test.d.ts.map +1 -0
- package/dist/adapters/github-cli-pr.test.js +108 -0
- package/dist/adapters/github-cli-pr.test.js.map +1 -0
- package/dist/adapters/github-cli.d.ts +0 -1
- package/dist/adapters/github-cli.d.ts.map +1 -1
- package/dist/adapters/github-cli.js +4 -40
- package/dist/adapters/github-cli.js.map +1 -1
- package/dist/adapters/github-cli.test.d.ts +2 -0
- package/dist/adapters/github-cli.test.d.ts.map +1 -0
- package/dist/adapters/github-cli.test.js +87 -0
- package/dist/adapters/github-cli.test.js.map +1 -0
- package/dist/adapters/pr-adapter.d.ts +41 -0
- package/dist/adapters/pr-adapter.d.ts.map +1 -0
- package/dist/adapters/pr-adapter.js +6 -0
- package/dist/adapters/pr-adapter.js.map +1 -0
- package/dist/commands/anchor.d.ts.map +1 -1
- package/dist/commands/anchor.js +6 -4
- package/dist/commands/anchor.js.map +1 -1
- package/dist/commands/briefing.d.ts +2 -0
- package/dist/commands/briefing.d.ts.map +1 -1
- package/dist/commands/briefing.js +19 -38
- package/dist/commands/briefing.js.map +1 -1
- package/dist/commands/briefing.test.d.ts +2 -0
- package/dist/commands/briefing.test.d.ts.map +1 -0
- package/dist/commands/briefing.test.js +26 -0
- package/dist/commands/briefing.test.js.map +1 -0
- package/dist/commands/handoff.d.ts +1 -0
- package/dist/commands/handoff.d.ts.map +1 -1
- package/dist/commands/handoff.js +17 -14
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/handoff.test.d.ts +2 -0
- package/dist/commands/handoff.test.d.ts.map +1 -0
- package/dist/commands/handoff.test.js +35 -0
- package/dist/commands/handoff.test.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +17 -15
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/learn.d.ts +12 -1
- package/dist/commands/learn.d.ts.map +1 -1
- package/dist/commands/learn.js +145 -141
- package/dist/commands/learn.js.map +1 -1
- package/dist/commands/learn.test.d.ts +2 -0
- package/dist/commands/learn.test.d.ts.map +1 -0
- package/dist/commands/learn.test.js +169 -0
- package/dist/commands/learn.test.js.map +1 -0
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +5 -4
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/shield.d.ts.map +1 -1
- package/dist/commands/shield.js +21 -16
- package/dist/commands/shield.js.map +1 -1
- package/dist/commands/shield.test.js +4 -0
- package/dist/commands/shield.test.js.map +1 -1
- package/dist/commands/spec.d.ts +1 -1
- package/dist/commands/spec.d.ts.map +1 -1
- package/dist/commands/spec.js +56 -43
- package/dist/commands/spec.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +15 -6
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/triage.d.ts +2 -0
- package/dist/commands/triage.d.ts.map +1 -1
- package/dist/commands/triage.js +15 -12
- package/dist/commands/triage.js.map +1 -1
- package/dist/commands/triage.test.d.ts +2 -0
- package/dist/commands/triage.test.d.ts.map +1 -0
- package/dist/commands/triage.test.js +33 -0
- package/dist/commands/triage.test.js.map +1 -0
- package/dist/index.js +9 -8
- package/dist/index.js.map +1 -1
- package/dist/orchestrator.test.d.ts +2 -0
- package/dist/orchestrator.test.d.ts.map +1 -0
- package/dist/orchestrator.test.js +90 -0
- package/dist/orchestrator.test.js.map +1 -0
- package/dist/ui.d.ts +26 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +85 -0
- package/dist/ui.js.map +1 -0
- package/dist/ui.test.d.ts +2 -0
- package/dist/ui.test.d.ts.map +1 -0
- package/dist/ui.test.js +76 -0
- package/dist/ui.test.js.map +1 -0
- package/dist/utils.d.ts +16 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +38 -9
- package/dist/utils.js.map +1 -1
- package/dist/utils.test.js +277 -2
- package/dist/utils.test.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic PR adapter interface — decouples Totem commands from any
|
|
3
|
+
* specific code hosting platform (GitHub, GitLab, etc.).
|
|
4
|
+
*/
|
|
5
|
+
export interface StandardPrListItem {
|
|
6
|
+
number: number;
|
|
7
|
+
title: string;
|
|
8
|
+
headRefName: string;
|
|
9
|
+
}
|
|
10
|
+
export interface StandardPrComment {
|
|
11
|
+
author: string;
|
|
12
|
+
body: string;
|
|
13
|
+
}
|
|
14
|
+
export interface StandardPrReview {
|
|
15
|
+
author: string;
|
|
16
|
+
state: string;
|
|
17
|
+
body: string;
|
|
18
|
+
}
|
|
19
|
+
export interface StandardPr {
|
|
20
|
+
number: number;
|
|
21
|
+
title: string;
|
|
22
|
+
body: string;
|
|
23
|
+
state: string;
|
|
24
|
+
comments: StandardPrComment[];
|
|
25
|
+
reviews: StandardPrReview[];
|
|
26
|
+
}
|
|
27
|
+
export interface StandardReviewComment {
|
|
28
|
+
id: number;
|
|
29
|
+
author: string;
|
|
30
|
+
body: string;
|
|
31
|
+
path: string;
|
|
32
|
+
diffHunk: string;
|
|
33
|
+
inReplyToId?: number;
|
|
34
|
+
createdAt?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface PrAdapter {
|
|
37
|
+
fetchOpenPRs(): StandardPrListItem[];
|
|
38
|
+
fetchPr(prNumber: number): StandardPr;
|
|
39
|
+
fetchReviewComments(prNumber: number): StandardReviewComment[];
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=pr-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/pr-adapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,YAAY,IAAI,kBAAkB,EAAE,CAAC;IACrC,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAAC;IACtC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAAC;CAChE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-adapter.js","sourceRoot":"","sources":["../../src/adapters/pr-adapter.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../src/commands/anchor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../src/commands/anchor.ts"],"names":[],"mappings":"AAmBA,wBAAsB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2ErE"}
|
package/dist/commands/anchor.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as fs from 'node:fs';
|
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { stdin as input, stdout as output } from 'node:process';
|
|
5
5
|
import * as readline from 'node:readline/promises';
|
|
6
|
+
import { log } from '../ui.js';
|
|
6
7
|
import { IS_WIN, loadConfig, loadEnv, resolveConfigPath } from '../utils.js';
|
|
7
8
|
function detectSyncCommand(cwd) {
|
|
8
9
|
if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) {
|
|
@@ -53,16 +54,16 @@ export async function anchorCommand(lessonArg) {
|
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
if (!lessonText || !lessonText.trim()) {
|
|
56
|
-
|
|
57
|
+
log.error('Totem', 'Lesson text cannot be empty.');
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
59
60
|
const timestamp = new Date().toISOString();
|
|
60
61
|
const tagString = tags.length > 0 ? tags.join(', ') : 'manual';
|
|
61
62
|
const entry = `\n## Lesson — ${timestamp}\n\n**Tags:** ${tagString}\n\n${lessonText.trim()}\n`;
|
|
62
63
|
fs.appendFileSync(lessonsPath, entry, 'utf-8');
|
|
63
|
-
|
|
64
|
+
log.success('Totem', `Lesson saved to ${config.totemDir}/lessons.md`);
|
|
64
65
|
const logPath = path.join(totemDir, 'mcp-sync.log');
|
|
65
|
-
|
|
66
|
+
log.dim('Totem', 'Triggering background re-index...');
|
|
66
67
|
try {
|
|
67
68
|
const { cmd, args } = detectSyncCommand(cwd);
|
|
68
69
|
const logFd = fs.openSync(logPath, 'a');
|
|
@@ -76,7 +77,8 @@ export async function anchorCommand(lessonArg) {
|
|
|
76
77
|
child.unref();
|
|
77
78
|
}
|
|
78
79
|
catch (err) {
|
|
79
|
-
|
|
80
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
81
|
+
log.warn('Totem', `Failed to trigger background sync: ${message}`);
|
|
80
82
|
}
|
|
81
83
|
}
|
|
82
84
|
//# sourceMappingURL=anchor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anchor.js","sourceRoot":"","sources":["../../src/commands/anchor.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"anchor.js","sourceRoot":"","sources":["../../src/commands/anchor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"briefing.d.ts","sourceRoot":"","sources":["../../src/commands/briefing.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"briefing.d.ts","sourceRoot":"","sources":["../../src/commands/briefing.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AA2EpE,wBAAgB,YAAY,CAAC,GAAG,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAG9D;AAqCD,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C7E"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { execFileSync } from 'node:child_process';
|
|
2
1
|
import * as path from 'node:path';
|
|
3
|
-
import { z } from 'zod';
|
|
4
2
|
import { createEmbedder, LanceStore } from '@mmnto/totem';
|
|
3
|
+
import { GitHubCliPrAdapter } from '../adapters/github-cli-pr.js';
|
|
5
4
|
import { getGitBranch, getGitStatus } from '../git.js';
|
|
6
|
-
import {
|
|
5
|
+
import { log } from '../ui.js';
|
|
6
|
+
import { formatResults, getSystemPrompt, loadConfig, loadEnv, resolveConfigPath, runOrchestrator, wrapXml, writeOutput, } from '../utils.js';
|
|
7
7
|
// ─── Constants ──────────────────────────────────────────
|
|
8
8
|
const TAG = 'Briefing';
|
|
9
9
|
const MAX_SPEC_RESULTS = 5;
|
|
@@ -40,28 +40,6 @@ Respond with ONLY the sections below. No preamble, no closing remarks.
|
|
|
40
40
|
### Recommended First Action
|
|
41
41
|
[Single clear recommendation for what the developer should do first in this session. Consider: uncommitted work to commit/continue, PRs to review/merge, next issue to pick up.]
|
|
42
42
|
`;
|
|
43
|
-
// ─── GitHub helpers ─────────────────────────────────────
|
|
44
|
-
const GhPrListItemSchema = z.object({
|
|
45
|
-
number: z.number(),
|
|
46
|
-
title: z.string(),
|
|
47
|
-
headRefName: z.string(),
|
|
48
|
-
});
|
|
49
|
-
function fetchOpenPRs(cwd) {
|
|
50
|
-
try {
|
|
51
|
-
const result = execFileSync('gh', ['pr', 'list', '--state', 'open', '--json', 'number,title,headRefName'], { cwd, encoding: 'utf-8', timeout: GH_TIMEOUT_MS, shell: IS_WIN });
|
|
52
|
-
return z.array(GhPrListItemSchema).parse(JSON.parse(result));
|
|
53
|
-
}
|
|
54
|
-
catch (err) {
|
|
55
|
-
if (err instanceof z.ZodError) {
|
|
56
|
-
throw new Error(`[Totem Error] Failed to parse GitHub PR list response: ${err.message}`);
|
|
57
|
-
}
|
|
58
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
59
|
-
if (msg.includes('ENOENT') || msg.includes('not found')) {
|
|
60
|
-
throw new Error(`[Totem Error] GitHub CLI (gh) is required for PR fetching. Install: https://cli.github.com`);
|
|
61
|
-
}
|
|
62
|
-
throw new Error(`[Totem Error] Failed to fetch open PRs: ${msg}`);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
43
|
async function retrieveContext(query, store) {
|
|
66
44
|
const search = (typeFilter, maxResults) => store.search({ query, typeFilter, maxResults });
|
|
67
45
|
const [specs, sessions] = await Promise.all([
|
|
@@ -71,13 +49,13 @@ async function retrieveContext(query, store) {
|
|
|
71
49
|
return { specs, sessions };
|
|
72
50
|
}
|
|
73
51
|
// ─── Prompt assembly ────────────────────────────────────
|
|
74
|
-
function formatPRList(prs) {
|
|
52
|
+
export function formatPRList(prs) {
|
|
75
53
|
if (prs.length === 0)
|
|
76
54
|
return '(none)';
|
|
77
55
|
return prs.map((pr) => `- #${pr.number} — ${pr.title} (branch: ${pr.headRefName})`).join('\n');
|
|
78
56
|
}
|
|
79
|
-
function assemblePrompt(branch, status, prs, context) {
|
|
80
|
-
const sections = [
|
|
57
|
+
function assemblePrompt(branch, status, prs, context, systemPrompt) {
|
|
58
|
+
const sections = [systemPrompt];
|
|
81
59
|
// Git state
|
|
82
60
|
sections.push('=== GIT STATE ===');
|
|
83
61
|
sections.push(`Branch: ${branch}`);
|
|
@@ -103,32 +81,35 @@ export async function briefingCommand(options) {
|
|
|
103
81
|
loadEnv(cwd);
|
|
104
82
|
const config = await loadConfig(configPath);
|
|
105
83
|
// Gather git state
|
|
106
|
-
|
|
84
|
+
log.info(TAG, 'Gathering git state...');
|
|
107
85
|
const branch = getGitBranch(cwd);
|
|
108
86
|
const status = getGitStatus(cwd);
|
|
109
|
-
|
|
87
|
+
log.info(TAG, `Branch: ${branch}`);
|
|
110
88
|
// Fetch open PRs
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
|
|
89
|
+
log.info(TAG, 'Fetching open PRs...');
|
|
90
|
+
const adapter = new GitHubCliPrAdapter(cwd);
|
|
91
|
+
const prs = adapter.fetchOpenPRs();
|
|
92
|
+
log.info(TAG, `Found ${prs.length} open PRs.`);
|
|
114
93
|
// Connect to LanceDB
|
|
115
94
|
const embedder = createEmbedder(config.embedding);
|
|
116
95
|
const store = new LanceStore(path.join(cwd, config.lanceDir), embedder);
|
|
117
96
|
await store.connect();
|
|
118
97
|
// Retrieve context from LanceDB
|
|
119
98
|
const query = `${branch} active work session priorities`;
|
|
120
|
-
|
|
99
|
+
log.info(TAG, 'Querying Totem index...');
|
|
121
100
|
const context = await retrieveContext(query, store);
|
|
122
101
|
const totalResults = context.specs.length + context.sessions.length;
|
|
123
|
-
|
|
102
|
+
log.info(TAG, `Found: ${context.specs.length} specs, ${context.sessions.length} sessions`);
|
|
103
|
+
// Resolve system prompt (allow .totem/prompts/briefing.md override)
|
|
104
|
+
const systemPrompt = getSystemPrompt('briefing', SYSTEM_PROMPT, cwd, config.totemDir);
|
|
124
105
|
// Assemble prompt
|
|
125
|
-
const prompt = assemblePrompt(branch, status, prs, context);
|
|
126
|
-
|
|
106
|
+
const prompt = assemblePrompt(branch, status, prs, context, systemPrompt);
|
|
107
|
+
log.dim(TAG, `Prompt: ${(prompt.length / 1024).toFixed(0)}KB`);
|
|
127
108
|
const content = runOrchestrator({ prompt, tag: TAG, options, config, cwd, totalResults });
|
|
128
109
|
if (content != null) {
|
|
129
110
|
writeOutput(content, options.out);
|
|
130
111
|
if (options.out)
|
|
131
|
-
|
|
112
|
+
log.success(TAG, `Written to ${options.out}`);
|
|
132
113
|
}
|
|
133
114
|
}
|
|
134
115
|
//# sourceMappingURL=briefing.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"briefing.js","sourceRoot":"","sources":["../../src/commands/briefing.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"briefing.js","sourceRoot":"","sources":["../../src/commands/briefing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"briefing.test.d.ts","sourceRoot":"","sources":["../../src/commands/briefing.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { formatPRList } from './briefing.js';
|
|
3
|
+
describe('formatPRList', () => {
|
|
4
|
+
it('returns (none) for empty PR list', () => {
|
|
5
|
+
expect(formatPRList([])).toBe('(none)');
|
|
6
|
+
});
|
|
7
|
+
it('formats a single PR with number, title, and branch', () => {
|
|
8
|
+
const prs = [
|
|
9
|
+
{ number: 42, title: 'Add widget', headRefName: 'feat/widget' },
|
|
10
|
+
];
|
|
11
|
+
const output = formatPRList(prs);
|
|
12
|
+
expect(output).toBe('- #42 — Add widget (branch: feat/widget)');
|
|
13
|
+
});
|
|
14
|
+
it('formats multiple PRs as a bulleted list', () => {
|
|
15
|
+
const prs = [
|
|
16
|
+
{ number: 1, title: 'First', headRefName: 'feat/first' },
|
|
17
|
+
{ number: 2, title: 'Second', headRefName: 'feat/second' },
|
|
18
|
+
];
|
|
19
|
+
const output = formatPRList(prs);
|
|
20
|
+
const lines = output.split('\n');
|
|
21
|
+
expect(lines).toHaveLength(2);
|
|
22
|
+
expect(lines[0]).toContain('#1');
|
|
23
|
+
expect(lines[1]).toContain('#2');
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=briefing.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"briefing.test.js","sourceRoot":"","sources":["../../src/commands/briefing.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAG9C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,GAAG,GAAyB;YAChC,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE;SAChE,CAAC;QACF,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,GAAG,GAAyB;YAChC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE;YACxD,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;SAC3D,CAAC;QACF,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handoff.d.ts","sourceRoot":"","sources":["../../src/commands/handoff.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"handoff.d.ts","sourceRoot":"","sources":["../../src/commands/handoff.ts"],"names":[],"mappings":"AA4DA,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUvE;AAiDD,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAwC3E"}
|
package/dist/commands/handoff.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import { getGitBranch, getGitDiff, getGitDiffStat, getGitStatus } from '../git.js';
|
|
4
|
-
import {
|
|
4
|
+
import { log } from '../ui.js';
|
|
5
|
+
import { getSystemPrompt, loadConfig, loadEnv, resolveConfigPath, runOrchestrator, wrapXml, writeOutput, } from '../utils.js';
|
|
5
6
|
// ─── Constants ──────────────────────────────────────────
|
|
6
7
|
const TAG = 'Handoff';
|
|
7
8
|
const MAX_DIFF_CHARS = 50_000;
|
|
@@ -42,7 +43,7 @@ Respond with ONLY the sections below. No preamble, no closing remarks.
|
|
|
42
43
|
[Clear, ordered list of what the next session should do first. Be specific — not "continue working" but "finish implementing X in file Y, then run tests."]
|
|
43
44
|
`;
|
|
44
45
|
// ─── Lessons file reader ────────────────────────────────
|
|
45
|
-
function readRecentLessons(cwd, totemDir) {
|
|
46
|
+
export function readRecentLessons(cwd, totemDir) {
|
|
46
47
|
const lessonsPath = path.join(cwd, totemDir, 'lessons.md');
|
|
47
48
|
if (!fs.existsSync(lessonsPath))
|
|
48
49
|
return '';
|
|
@@ -53,8 +54,8 @@ function readRecentLessons(cwd, totemDir) {
|
|
|
53
54
|
return lines.slice(-LESSONS_TAIL_LINES).join('\n').trim();
|
|
54
55
|
}
|
|
55
56
|
// ─── Prompt assembly ────────────────────────────────────
|
|
56
|
-
function assemblePrompt(branch, status, diff, diffStat, lessons) {
|
|
57
|
-
const sections = [
|
|
57
|
+
function assemblePrompt(branch, status, diff, diffStat, lessons, systemPrompt) {
|
|
58
|
+
const sections = [systemPrompt];
|
|
58
59
|
// Git state
|
|
59
60
|
sections.push('=== GIT STATE ===');
|
|
60
61
|
sections.push(`Branch: ${branch}`);
|
|
@@ -87,32 +88,34 @@ export async function handoffCommand(options) {
|
|
|
87
88
|
loadEnv(cwd);
|
|
88
89
|
const config = await loadConfig(configPath);
|
|
89
90
|
// Gather git state
|
|
90
|
-
|
|
91
|
+
log.info(TAG, 'Gathering git state...');
|
|
91
92
|
const branch = getGitBranch(cwd);
|
|
92
93
|
const status = getGitStatus(cwd);
|
|
93
|
-
|
|
94
|
+
log.info(TAG, `Branch: ${branch}`);
|
|
94
95
|
// Get diff
|
|
95
|
-
|
|
96
|
+
log.info(TAG, 'Getting uncommitted diff...');
|
|
96
97
|
const diff = getGitDiff('all', cwd);
|
|
97
98
|
const diffStat = diff.trim() ? getGitDiffStat(cwd) : '';
|
|
98
99
|
if (diff.trim()) {
|
|
99
|
-
|
|
100
|
+
log.info(TAG, `Diff: ${(diff.length / 1024).toFixed(0)}KB`);
|
|
100
101
|
}
|
|
101
102
|
else {
|
|
102
|
-
|
|
103
|
+
log.dim(TAG, 'Working tree is clean.');
|
|
103
104
|
}
|
|
104
105
|
// Read recent lessons
|
|
105
|
-
|
|
106
|
+
log.info(TAG, 'Reading recent lessons...');
|
|
106
107
|
const lessons = readRecentLessons(cwd, config.totemDir);
|
|
107
|
-
|
|
108
|
+
log.info(TAG, `Lessons: ${lessons ? `${lessons.split('\n').length} lines` : 'none found'}`);
|
|
109
|
+
// Resolve system prompt (allow .totem/prompts/handoff.md override)
|
|
110
|
+
const systemPrompt = getSystemPrompt('handoff', SYSTEM_PROMPT, cwd, config.totemDir);
|
|
108
111
|
// Assemble prompt
|
|
109
|
-
const prompt = assemblePrompt(branch, status, diff, diffStat, lessons);
|
|
110
|
-
|
|
112
|
+
const prompt = assemblePrompt(branch, status, diff, diffStat, lessons, systemPrompt);
|
|
113
|
+
log.dim(TAG, `Prompt: ${(prompt.length / 1024).toFixed(0)}KB`);
|
|
111
114
|
const content = runOrchestrator({ prompt, tag: TAG, options, config, cwd });
|
|
112
115
|
if (content != null) {
|
|
113
116
|
writeOutput(content, options.out);
|
|
114
117
|
if (options.out)
|
|
115
|
-
|
|
118
|
+
log.success(TAG, `Written to ${options.out}`);
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
//# sourceMappingURL=handoff.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handoff.js","sourceRoot":"","sources":["../../src/commands/handoff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACnF,OAAO,EACL,UAAU,EACV,OAAO,EACP,iBAAiB,EACjB,eAAe,EACf,OAAO,EACP,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,2DAA2D;AAE3D,MAAM,GAAG,GAAG,SAAS,CAAC;AACtB,MAAM,cAAc,GAAG,MAAM,CAAC;AAC9B,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B,2DAA2D;AAE3D,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCrB,CAAC;AAEF,2DAA2D;AAE3D,
|
|
1
|
+
{"version":3,"file":"handoff.js","sourceRoot":"","sources":["../../src/commands/handoff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handoff.test.d.ts","sourceRoot":"","sources":["../../src/commands/handoff.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
5
|
+
import { readRecentLessons } from './handoff.js';
|
|
6
|
+
describe('readRecentLessons', () => {
|
|
7
|
+
let tmpDir;
|
|
8
|
+
const totemDir = '.totem';
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-handoff-'));
|
|
11
|
+
});
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
14
|
+
});
|
|
15
|
+
it('returns empty string when lessons.md does not exist', () => {
|
|
16
|
+
expect(readRecentLessons(tmpDir, totemDir)).toBe('');
|
|
17
|
+
});
|
|
18
|
+
it('returns full content when file is short', () => {
|
|
19
|
+
const lessonsDir = path.join(tmpDir, totemDir);
|
|
20
|
+
fs.mkdirSync(lessonsDir, { recursive: true });
|
|
21
|
+
fs.writeFileSync(path.join(lessonsDir, 'lessons.md'), '## Lesson\nSome content', 'utf-8');
|
|
22
|
+
expect(readRecentLessons(tmpDir, totemDir)).toBe('## Lesson\nSome content');
|
|
23
|
+
});
|
|
24
|
+
it('returns only the last 100 lines for long files', () => {
|
|
25
|
+
const lessonsDir = path.join(tmpDir, totemDir);
|
|
26
|
+
fs.mkdirSync(lessonsDir, { recursive: true });
|
|
27
|
+
const lines = Array.from({ length: 200 }, (_, i) => `Line ${i + 1}`);
|
|
28
|
+
fs.writeFileSync(path.join(lessonsDir, 'lessons.md'), lines.join('\n'), 'utf-8');
|
|
29
|
+
const result = readRecentLessons(tmpDir, totemDir);
|
|
30
|
+
expect(result).toContain('Line 200');
|
|
31
|
+
expect(result).toContain('Line 101');
|
|
32
|
+
expect(result).not.toContain('Line 100\n');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=handoff.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handoff.test.js","sourceRoot":"","sources":["../../src/commands/handoff.test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAErE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAI,MAAc,CAAC;IACnB,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAE1B,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC/C,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,yBAAyB,EAAE,OAAO,CAAC,CAAC;QAC1F,MAAM,CAAC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC/C,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QAEjF,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAqDA,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAInF;AA0CD,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC;IAAE,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAoD5D;AAmID,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAiLjD"}
|
package/dist/commands/init.js
CHANGED
|
@@ -2,6 +2,7 @@ import * as fs from 'node:fs';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import { stdin as input, stdout as output } from 'node:process';
|
|
4
4
|
import * as readline from 'node:readline/promises';
|
|
5
|
+
import { bold, brand, dim, log, printBanner, success } from '../ui.js';
|
|
5
6
|
import { IS_WIN } from '../utils.js';
|
|
6
7
|
import { installPostMergeHook } from './install-hooks.js';
|
|
7
8
|
const AI_PROMPT_BLOCK = `
|
|
@@ -223,9 +224,10 @@ export async function initCommand() {
|
|
|
223
224
|
const rl = readline.createInterface({ input, output });
|
|
224
225
|
const summary = [];
|
|
225
226
|
try {
|
|
227
|
+
printBanner();
|
|
226
228
|
if (!configExists) {
|
|
227
229
|
// --- Fresh install: generate config ---
|
|
228
|
-
|
|
230
|
+
log.info('Totem', 'Scanning project...');
|
|
229
231
|
const detected = detectProject(cwd);
|
|
230
232
|
const detections = [];
|
|
231
233
|
if (detected.hasTypeScript)
|
|
@@ -241,10 +243,10 @@ export async function initCommand() {
|
|
|
241
243
|
if (detected.hasSessions)
|
|
242
244
|
detections.push('session logs');
|
|
243
245
|
if (detections.length > 0) {
|
|
244
|
-
|
|
246
|
+
log.info('Totem', `Detected: ${bold(detections.join(', '))}`);
|
|
245
247
|
}
|
|
246
248
|
else {
|
|
247
|
-
|
|
249
|
+
log.dim('Totem', 'No specific project structure detected. Using markdown defaults.');
|
|
248
250
|
}
|
|
249
251
|
const targets = buildTargets(detected);
|
|
250
252
|
let provider = 'openai';
|
|
@@ -252,7 +254,7 @@ export async function initCommand() {
|
|
|
252
254
|
const apiKey = answer.trim().replace(/[\r\n]/g, '');
|
|
253
255
|
if (apiKey) {
|
|
254
256
|
if (!/^sk-[a-zA-Z0-9_-]+$/.test(apiKey)) {
|
|
255
|
-
|
|
257
|
+
log.warn('Totem', 'API key does not look like a valid OpenAI key (expected sk-...). Skipping.');
|
|
256
258
|
provider = 'ollama';
|
|
257
259
|
}
|
|
258
260
|
else {
|
|
@@ -273,14 +275,14 @@ export async function initCommand() {
|
|
|
273
275
|
}
|
|
274
276
|
else {
|
|
275
277
|
provider = 'ollama';
|
|
276
|
-
|
|
278
|
+
log.info('Totem', 'Configured for Ollama. Make sure it is running locally.');
|
|
277
279
|
}
|
|
278
280
|
const configContent = generateConfig(targets, provider);
|
|
279
281
|
fs.writeFileSync(configPath, configContent, 'utf-8');
|
|
280
282
|
summary.push({ file: 'totem.config.ts', action: 'Created with auto-detected targets' });
|
|
281
283
|
}
|
|
282
284
|
else {
|
|
283
|
-
|
|
285
|
+
log.dim('Totem', 'totem.config.ts already exists. Checking reflexes and hooks...');
|
|
284
286
|
}
|
|
285
287
|
// --- Always run: .totem/ directory ---
|
|
286
288
|
if (!fs.existsSync(totemDir)) {
|
|
@@ -295,7 +297,7 @@ export async function initCommand() {
|
|
|
295
297
|
const detectedTools = detectAiTools(cwd);
|
|
296
298
|
if (detectedTools.length > 0) {
|
|
297
299
|
const toolNames = detectedTools.map((t) => t.name).join(', ');
|
|
298
|
-
|
|
300
|
+
log.info('Totem', `Detected AI tools: ${bold(toolNames)}`);
|
|
299
301
|
const toolAnswer = await rl.question('Which tools should Totem configure? [all/none/select] (default: all): ');
|
|
300
302
|
let selectedTools;
|
|
301
303
|
const trimmed = toolAnswer.trim().toLowerCase();
|
|
@@ -320,9 +322,9 @@ export async function initCommand() {
|
|
|
320
322
|
const filePath = path.join(cwd, tool.mcpPath);
|
|
321
323
|
const result = scaffoldMcpConfig(filePath, tool.serverEntry);
|
|
322
324
|
if (result.err) {
|
|
323
|
-
|
|
324
|
-
console.
|
|
325
|
-
console.
|
|
325
|
+
log.error('Totem', result.err);
|
|
326
|
+
console.error(`To fix this, add the following manually to your ${tool.mcpPath} under "mcpServers":\n`);
|
|
327
|
+
console.error(` "totem": ${JSON.stringify(tool.serverEntry, null, 2)}\n`);
|
|
326
328
|
}
|
|
327
329
|
else if (result.action === 'created') {
|
|
328
330
|
summary.push({ file: tool.mcpPath, action: `Created with Totem MCP server` });
|
|
@@ -344,7 +346,7 @@ export async function initCommand() {
|
|
|
344
346
|
}
|
|
345
347
|
catch (err) {
|
|
346
348
|
const message = err instanceof Error ? err.message : String(err);
|
|
347
|
-
|
|
349
|
+
log.error('Totem', `Failed to inject reflexes into ${tool.reflexFile}: ${message}`);
|
|
348
350
|
}
|
|
349
351
|
}
|
|
350
352
|
}
|
|
@@ -361,13 +363,13 @@ export async function initCommand() {
|
|
|
361
363
|
}
|
|
362
364
|
// --- Print summary ---
|
|
363
365
|
if (summary.length > 0) {
|
|
364
|
-
console.
|
|
366
|
+
console.error(`\n${brand('--- Totem Init Summary ---')}`);
|
|
365
367
|
for (const entry of summary) {
|
|
366
|
-
console.
|
|
368
|
+
console.error(` ${success('OK')} ${dim(entry.file)} — ${entry.action}`);
|
|
367
369
|
}
|
|
368
|
-
console.
|
|
370
|
+
console.error(brand('--------------------------'));
|
|
369
371
|
}
|
|
370
|
-
|
|
372
|
+
log.success('Totem', 'Init complete. Run `totem sync` to index your project.');
|
|
371
373
|
}
|
|
372
374
|
finally {
|
|
373
375
|
rl.close();
|