@paytmsupport/paytm-jarvis 1.0.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 (58) hide show
  1. package/.npmrc.example +4 -0
  2. package/ENABLE_2FA_PAYTM.md +59 -0
  3. package/NPM_PRIVATE_PUBLISH.md +149 -0
  4. package/NPM_PRO_REQUIRED.md +51 -0
  5. package/NPM_PUBLISH_GUIDE.md +138 -0
  6. package/PRIVATE_PUBLISH_GUIDE.md +112 -0
  7. package/PUBLISH_NOW.md +53 -0
  8. package/PUBLISH_PAYTM.md +48 -0
  9. package/QUICK_START_NPM_PRIVATE.md +54 -0
  10. package/QUICK_START_PRIVATE.md +72 -0
  11. package/dist/commands/compress.d.ts +3 -0
  12. package/dist/commands/compress.js +97 -0
  13. package/dist/commands/config-cmd.d.ts +1 -0
  14. package/dist/commands/config-cmd.js +84 -0
  15. package/dist/commands/diff.d.ts +1 -0
  16. package/dist/commands/diff.js +97 -0
  17. package/dist/commands/handoff.d.ts +1 -0
  18. package/dist/commands/handoff.js +151 -0
  19. package/dist/commands/hook.d.ts +1 -0
  20. package/dist/commands/hook.js +60 -0
  21. package/dist/commands/init.d.ts +1 -0
  22. package/dist/commands/init.js +49 -0
  23. package/dist/commands/log.d.ts +4 -0
  24. package/dist/commands/log.js +53 -0
  25. package/dist/commands/resume.d.ts +4 -0
  26. package/dist/commands/resume.js +44 -0
  27. package/dist/commands/save.d.ts +13 -0
  28. package/dist/commands/save.js +160 -0
  29. package/dist/commands/share.d.ts +3 -0
  30. package/dist/commands/share.js +58 -0
  31. package/dist/commands/suggest.d.ts +1 -0
  32. package/dist/commands/suggest.js +67 -0
  33. package/dist/commands/summarize.d.ts +1 -0
  34. package/dist/commands/summarize.js +122 -0
  35. package/dist/commands/watch.d.ts +3 -0
  36. package/dist/commands/watch.js +99 -0
  37. package/dist/core/ai.d.ts +17 -0
  38. package/dist/core/ai.js +55 -0
  39. package/dist/core/context.d.ts +16 -0
  40. package/dist/core/context.js +88 -0
  41. package/dist/core/git.d.ts +7 -0
  42. package/dist/core/git.js +73 -0
  43. package/dist/core/parser.d.ts +14 -0
  44. package/dist/core/parser.js +539 -0
  45. package/dist/core/parser.test.d.ts +1 -0
  46. package/dist/core/prompt.d.ts +2 -0
  47. package/dist/core/prompt.js +75 -0
  48. package/dist/core/types.d.ts +24 -0
  49. package/dist/core/types.js +2 -0
  50. package/dist/index.d.ts +2 -0
  51. package/dist/index.js +91 -0
  52. package/dist/mcp-server.d.ts +20 -0
  53. package/dist/mcp-server.js +153 -0
  54. package/dist/utils/clipboard.d.ts +5 -0
  55. package/dist/utils/clipboard.js +23 -0
  56. package/dist/utils/config.d.ts +30 -0
  57. package/dist/utils/config.js +48 -0
  58. package/package.json +54 -0
@@ -0,0 +1,72 @@
1
+ # Quick Start: Publish Jarvis Privately to GitHub Packages
2
+
3
+ ## ✅ Already Done
4
+ - ✅ Package name updated to `@naitiksharma/jarvis`
5
+ - ✅ `publishConfig` added for GitHub Packages
6
+
7
+ ## Next Steps
8
+
9
+ ### 1. Create GitHub Token (One-time setup)
10
+
11
+ 1. Go to: https://github.com/settings/tokens/new
12
+ 2. Name: `npm-publish-jarvis`
13
+ 3. Scopes: ✅ `read:packages`, ✅ `write:packages`
14
+ 4. Generate and **COPY THE TOKEN**
15
+
16
+ ### 2. Configure npm
17
+
18
+ ```bash
19
+ # Add token to ~/.npmrc
20
+ echo "//npm.pkg.github.com/:_authToken=PASTE_YOUR_TOKEN_HERE" >> ~/.npmrc
21
+
22
+ # Verify it was added
23
+ cat ~/.npmrc
24
+ ```
25
+
26
+ ### 3. Build and Publish
27
+
28
+ ```bash
29
+ cd jarvis
30
+ npm run build
31
+ npm publish
32
+ ```
33
+
34
+ ### 4. Verify
35
+
36
+ ```bash
37
+ npm view @naitiksharma/jarvis
38
+ ```
39
+
40
+ ### 5. Install (for testing)
41
+
42
+ ```bash
43
+ npm install -g @naitiksharma/jarvis
44
+ jarvis --version
45
+ ```
46
+
47
+ ## For Your Friend
48
+
49
+ They need to:
50
+
51
+ 1. **Get access** to your GitHub package (you add them as collaborator OR they create token)
52
+ 2. **Configure `.npmrc`**:
53
+ ```bash
54
+ echo "//npm.pkg.github.com/:_authToken=THEIR_TOKEN" >> ~/.npmrc
55
+ ```
56
+ 3. **Install**:
57
+ ```bash
58
+ npm install -g @naitiksharma/jarvis
59
+ ```
60
+
61
+ ## Note
62
+
63
+ Your VS Code extension already bundles jarvis, so it works without npm install! 🎉
64
+
65
+ The private npm package is useful if you want:
66
+ - `npx @naitiksharma/jarvis` to work
67
+ - Global install option
68
+ - Version management via npm
69
+
70
+ ---
71
+
72
+ **Full guide**: See `PRIVATE_PUBLISH_GUIDE.md` for detailed instructions.
@@ -0,0 +1,3 @@
1
+ export declare function compressCommand(options?: {
2
+ force?: boolean;
3
+ }): Promise<void>;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.compressCommand = compressCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const context_1 = require("../core/context");
11
+ const git_1 = require("../core/git");
12
+ const ai_1 = require("../core/ai");
13
+ async function compressCommand(options) {
14
+ if (!(await (0, context_1.isInitialized)())) {
15
+ console.log(chalk_1.default.red("✗ DevContext not initialized. Run `jarvis init` first."));
16
+ return;
17
+ }
18
+ try {
19
+ const branch = await (0, git_1.getCurrentBranch)();
20
+ const entries = await (0, context_1.loadBranchContext)(branch);
21
+ if (entries.length <= 2) {
22
+ console.log(chalk_1.default.yellow("⚠ Not enough context to compress (need at least 3 entries)."));
23
+ return;
24
+ }
25
+ console.log(chalk_1.default.gray(` Compressing ${entries.length} entries for branch: ${branch}...`));
26
+ // Keep the most recent entry intact, compress older ones
27
+ const toCompress = entries.slice(0, -1);
28
+ const latest = entries[entries.length - 1];
29
+ const prompt = `You are a developer assistant. Compress the following ${toCompress.length} coding session entries into a single summary entry. Keep only the most important information: key decisions, approaches that worked or failed, and overall progress.
30
+
31
+ Sessions to compress:
32
+ ${toCompress
33
+ .map((e, i) => `
34
+ Session ${i + 1} (${e.timestamp}):
35
+ - Task: ${e.task}
36
+ - Approaches: ${e.approaches.join(", ") || "none"}
37
+ - Decisions: ${e.decisions.join(", ") || "none"}
38
+ - State: ${e.currentState}
39
+ - Next steps: ${e.nextSteps.join(", ") || "none"}
40
+ `)
41
+ .join("\n")}
42
+
43
+ Generate a JSON response:
44
+ {
45
+ "task": "overall task description covering all sessions",
46
+ "approaches": ["significant approaches tried"],
47
+ "decisions": ["key decisions made across all sessions"],
48
+ "currentState": "where things stood after these sessions",
49
+ "nextSteps": ["remaining next steps"]
50
+ }
51
+
52
+ Be concise but preserve important decisions and learnings.`;
53
+ const result = await (0, ai_1.callAI)([
54
+ {
55
+ role: "system",
56
+ content: "You are a helpful assistant. Always respond with valid JSON.",
57
+ },
58
+ { role: "user", content: prompt },
59
+ ]);
60
+ if (result.error) {
61
+ console.log(chalk_1.default.red(`✗ ${result.error}`));
62
+ return;
63
+ }
64
+ let parsed;
65
+ try {
66
+ const jsonMatch = result.content.match(/```(?:json)?\s*([\s\S]*?)```/) ||
67
+ [null, result.content];
68
+ parsed = JSON.parse(jsonMatch[1].trim());
69
+ }
70
+ catch {
71
+ console.log(chalk_1.default.red("✗ Could not parse AI compression result."));
72
+ return;
73
+ }
74
+ // Create compressed entry from the oldest entry's metadata
75
+ const compressed = {
76
+ ...toCompress[0],
77
+ task: parsed.task || toCompress[0].task,
78
+ approaches: parsed.approaches || [],
79
+ decisions: parsed.decisions || [],
80
+ currentState: parsed.currentState || "",
81
+ nextSteps: parsed.nextSteps || [],
82
+ timestamp: toCompress[0].timestamp, // keep oldest timestamp
83
+ };
84
+ // Replace branch file with compressed + latest
85
+ const dir = await (0, context_1.getDevCtxDir)();
86
+ const branchFile = path_1.default.join(dir, "branches", `${branch.replace(/\//g, "__")}.json`);
87
+ const newEntries = [compressed, latest];
88
+ fs_1.default.writeFileSync(branchFile, JSON.stringify(newEntries, null, 2));
89
+ console.log(chalk_1.default.green(`✓ Compressed ${entries.length} entries → 2 entries for branch: ${chalk_1.default.bold(branch)}`));
90
+ console.log(chalk_1.default.gray(` Kept: 1 compressed summary + latest entry`));
91
+ console.log(chalk_1.default.cyan(` Summary: ${parsed.task}`));
92
+ console.log();
93
+ }
94
+ catch (err) {
95
+ console.log(chalk_1.default.red(`✗ Error: ${err.message}`));
96
+ }
97
+ }
@@ -0,0 +1 @@
1
+ export declare function configCommand(action?: string, key?: string, value?: string): Promise<void>;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.configCommand = configCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const context_1 = require("../core/context");
9
+ const config_1 = require("../utils/config");
10
+ const VALID_KEYS = [
11
+ "defaultOutput",
12
+ "autoGitCapture",
13
+ "recentCommitCount",
14
+ "defaultLogCount",
15
+ "watchInterval",
16
+ "autoHook",
17
+ "aiProvider",
18
+ "aiModel",
19
+ "aiApiKey",
20
+ ];
21
+ async function configCommand(action, key, value) {
22
+ if (!(await (0, context_1.isInitialized)())) {
23
+ console.log(chalk_1.default.red("✗ DevContext not initialized. Run `jarvis init` first."));
24
+ return;
25
+ }
26
+ try {
27
+ const config = await (0, config_1.loadConfig)();
28
+ if (!action || action === "list") {
29
+ console.log(chalk_1.default.bold("\nDevContext Configuration:\n"));
30
+ for (const [k, v] of Object.entries(config)) {
31
+ if (k === "aiApiKey" && v) {
32
+ console.log(` ${chalk_1.default.cyan(k)}: ${chalk_1.default.gray("****" + String(v).slice(-4))}`);
33
+ }
34
+ else {
35
+ console.log(` ${chalk_1.default.cyan(k)}: ${chalk_1.default.white(String(v))}`);
36
+ }
37
+ }
38
+ console.log();
39
+ return;
40
+ }
41
+ if (action === "get") {
42
+ if (!key) {
43
+ console.log(chalk_1.default.red("✗ Usage: jarvis config get <key>"));
44
+ return;
45
+ }
46
+ if (!VALID_KEYS.includes(key)) {
47
+ console.log(chalk_1.default.red(`✗ Unknown config key: ${key}`));
48
+ console.log(chalk_1.default.gray(` Valid keys: ${VALID_KEYS.join(", ")}`));
49
+ return;
50
+ }
51
+ const val = config[key];
52
+ console.log(`${chalk_1.default.cyan(key)}: ${chalk_1.default.white(String(val ?? "(not set)"))}`);
53
+ return;
54
+ }
55
+ if (action === "set") {
56
+ if (!key || value === undefined) {
57
+ console.log(chalk_1.default.red("✗ Usage: jarvis config set <key> <value>"));
58
+ return;
59
+ }
60
+ if (!VALID_KEYS.includes(key)) {
61
+ console.log(chalk_1.default.red(`✗ Unknown config key: ${key}`));
62
+ console.log(chalk_1.default.gray(` Valid keys: ${VALID_KEYS.join(", ")}`));
63
+ return;
64
+ }
65
+ // Type coercion
66
+ let typedValue = value;
67
+ if (value === "true")
68
+ typedValue = true;
69
+ else if (value === "false")
70
+ typedValue = false;
71
+ else if (!isNaN(Number(value)) && key !== "aiApiKey" && key !== "aiProvider" && key !== "aiModel") {
72
+ typedValue = Number(value);
73
+ }
74
+ await (0, config_1.saveConfig)({ [key]: typedValue });
75
+ console.log(chalk_1.default.green(`✓ Set ${chalk_1.default.bold(key)} = ${typedValue}`));
76
+ return;
77
+ }
78
+ console.log(chalk_1.default.red(`✗ Unknown action: ${action}`));
79
+ console.log(chalk_1.default.gray(" Usage: jarvis config [list|get|set] [key] [value]"));
80
+ }
81
+ catch (err) {
82
+ console.log(chalk_1.default.red(`✗ Error: ${err.message}`));
83
+ }
84
+ }
@@ -0,0 +1 @@
1
+ export declare function diffCommand(): Promise<void>;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.diffCommand = diffCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const context_1 = require("../core/context");
9
+ const git_1 = require("../core/git");
10
+ function getTimeAgo(timestamp) {
11
+ const diff = Date.now() - new Date(timestamp).getTime();
12
+ const minutes = Math.floor(diff / 60000);
13
+ if (minutes < 60)
14
+ return `${minutes} minutes ago`;
15
+ const hours = Math.floor(minutes / 60);
16
+ if (hours < 24)
17
+ return `${hours} hours ago`;
18
+ const days = Math.floor(hours / 24);
19
+ return `${days} days ago`;
20
+ }
21
+ async function diffCommand() {
22
+ if (!(await (0, context_1.isInitialized)())) {
23
+ console.log(chalk_1.default.red("✗ DevContext not initialized. Run `jarvis init` first."));
24
+ return;
25
+ }
26
+ try {
27
+ const branch = await (0, git_1.getCurrentBranch)();
28
+ const entries = await (0, context_1.loadBranchContext)(branch);
29
+ if (entries.length === 0) {
30
+ console.log(chalk_1.default.yellow(`⚠ No context found for branch: ${branch}`));
31
+ console.log(chalk_1.default.gray(" Run `jarvis save` to capture context first."));
32
+ return;
33
+ }
34
+ const latest = entries[entries.length - 1];
35
+ const [currentChanged, currentStaged] = await Promise.all([
36
+ (0, git_1.getChangedFiles)(),
37
+ (0, git_1.getStagedFiles)(),
38
+ ]);
39
+ const lastSaveTime = getTimeAgo(latest.timestamp);
40
+ console.log(chalk_1.default.bold(`\nSince last save (${lastSaveTime}):\n`));
41
+ // --- Files ---
42
+ const previousFiles = new Set(latest.filesChanged);
43
+ const currentFiles = new Set([...currentChanged, ...currentStaged]);
44
+ const newFiles = [...currentFiles].filter((f) => !previousFiles.has(f));
45
+ const removedFiles = [...previousFiles].filter((f) => !currentFiles.has(f));
46
+ const stillChanged = [...currentFiles].filter((f) => previousFiles.has(f));
47
+ if (newFiles.length > 0) {
48
+ newFiles.forEach((f) => console.log(` ${chalk_1.default.green("+")} ${f} ${chalk_1.default.green("(new)")}`));
49
+ }
50
+ if (stillChanged.length > 0) {
51
+ stillChanged.forEach((f) => console.log(` ${chalk_1.default.yellow("~")} ${f} ${chalk_1.default.gray("(still modified)")}`));
52
+ }
53
+ if (removedFiles.length > 0) {
54
+ removedFiles.forEach((f) => console.log(` ${chalk_1.default.red("-")} ${f} ${chalk_1.default.gray("(resolved)")}`));
55
+ }
56
+ if (newFiles.length === 0 && removedFiles.length === 0 && stillChanged.length === 0) {
57
+ console.log(chalk_1.default.gray(" No file changes since last save."));
58
+ }
59
+ // --- Decisions ---
60
+ if (entries.length >= 2) {
61
+ const previous = entries[entries.length - 2];
62
+ const prevDecisions = new Set(previous.decisions);
63
+ const newDecisions = latest.decisions.filter((d) => !prevDecisions.has(d));
64
+ if (newDecisions.length > 0) {
65
+ console.log();
66
+ newDecisions.forEach((d) => console.log(` ${chalk_1.default.cyan("Decision added:")} "${d}"`));
67
+ }
68
+ }
69
+ else if (latest.decisions.length > 0) {
70
+ console.log();
71
+ latest.decisions.forEach((d) => console.log(` ${chalk_1.default.cyan("Decision:")} "${d}"`));
72
+ }
73
+ // --- Next Steps Progress ---
74
+ if (entries.length >= 2) {
75
+ const previous = entries[entries.length - 2];
76
+ const completedSteps = previous.nextSteps.filter((step) => !latest.nextSteps.includes(step));
77
+ if (completedSteps.length > 0) {
78
+ console.log();
79
+ completedSteps.forEach((s) => console.log(` ${chalk_1.default.green("✓")} Next step completed: "${s}"`));
80
+ }
81
+ const newSteps = latest.nextSteps.filter((step) => !previous.nextSteps.includes(step));
82
+ if (newSteps.length > 0) {
83
+ newSteps.forEach((s) => console.log(` ${chalk_1.default.blue("→")} New next step: "${s}"`));
84
+ }
85
+ }
86
+ // --- Summary line ---
87
+ const totalNew = newFiles.length;
88
+ const totalModified = stillChanged.length;
89
+ const totalResolved = removedFiles.length;
90
+ console.log();
91
+ console.log(chalk_1.default.gray(` Summary: +${totalNew} new, ~${totalModified} modified, -${totalResolved} resolved`));
92
+ console.log();
93
+ }
94
+ catch (err) {
95
+ console.log(chalk_1.default.red(`✗ Error: ${err.message}`));
96
+ }
97
+ }
@@ -0,0 +1 @@
1
+ export declare function handoffCommand(assignee?: string, message?: string): Promise<void>;
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.handoffCommand = handoffCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const inquirer_1 = __importDefault(require("inquirer"));
9
+ const uuid_1 = require("uuid");
10
+ const context_1 = require("../core/context");
11
+ const git_1 = require("../core/git");
12
+ async function handoffCommand(assignee, message) {
13
+ if (!(await (0, context_1.isInitialized)())) {
14
+ console.log(chalk_1.default.red("✗ DevContext not initialized. Run `jarvis init` first."));
15
+ return;
16
+ }
17
+ try {
18
+ // Clean up @ prefix if present
19
+ let targetAssignee = assignee?.replace(/^@/, "") || "";
20
+ let handoffNote = message || "";
21
+ if (!targetAssignee || !handoffNote) {
22
+ const answers = await inquirer_1.default.prompt([
23
+ ...(!targetAssignee
24
+ ? [
25
+ {
26
+ type: "input",
27
+ name: "assignee",
28
+ message: "Who are you handing off to?",
29
+ validate: (input) => input.length > 0 || "Assignee is required",
30
+ },
31
+ ]
32
+ : []),
33
+ ...(!handoffNote
34
+ ? [
35
+ {
36
+ type: "input",
37
+ name: "handoffNote",
38
+ message: "Handoff note (what they need to know):",
39
+ validate: (input) => input.length > 0 || "Handoff note is required",
40
+ },
41
+ ]
42
+ : []),
43
+ {
44
+ type: "input",
45
+ name: "task",
46
+ message: "What were you working on?",
47
+ validate: (input) => input.length > 0 || "Task description is required",
48
+ },
49
+ {
50
+ type: "input",
51
+ name: "currentState",
52
+ message: "Where did you leave off?",
53
+ validate: (input) => input.length > 0 || "Current state is required",
54
+ },
55
+ {
56
+ type: "input",
57
+ name: "nextSteps",
58
+ message: "What comes next? (comma-separated)",
59
+ default: "",
60
+ },
61
+ {
62
+ type: "input",
63
+ name: "blockers",
64
+ message: "Any blockers? (comma-separated)",
65
+ default: "",
66
+ },
67
+ ]);
68
+ targetAssignee = targetAssignee || answers.assignee;
69
+ handoffNote = handoffNote || answers.handoffNote;
70
+ const [branch, repo, filesChanged, filesStaged, recentCommits, author] = await Promise.all([
71
+ (0, git_1.getCurrentBranch)(),
72
+ (0, git_1.getRepoName)(),
73
+ (0, git_1.getChangedFiles)(),
74
+ (0, git_1.getStagedFiles)(),
75
+ (0, git_1.getRecentCommits)(),
76
+ (0, git_1.getAuthor)(),
77
+ ]);
78
+ const entry = {
79
+ id: (0, uuid_1.v4)(),
80
+ timestamp: new Date().toISOString(),
81
+ branch,
82
+ repo,
83
+ author,
84
+ task: answers.task,
85
+ approaches: [],
86
+ decisions: [],
87
+ currentState: answers.currentState,
88
+ nextSteps: answers.nextSteps
89
+ ? answers.nextSteps
90
+ .split(",")
91
+ .map((s) => s.trim())
92
+ .filter(Boolean)
93
+ : [],
94
+ blockers: answers.blockers
95
+ ? answers.blockers
96
+ .split(",")
97
+ .map((s) => s.trim())
98
+ .filter(Boolean)
99
+ : undefined,
100
+ filesChanged,
101
+ filesStaged,
102
+ recentCommits,
103
+ assignee: targetAssignee,
104
+ handoffNote,
105
+ };
106
+ await (0, context_1.saveContext)(entry);
107
+ console.log(chalk_1.default.green(`\n✓ Handoff created for ${chalk_1.default.bold("@" + targetAssignee)}`));
108
+ console.log(chalk_1.default.gray(` Branch: ${branch}`));
109
+ console.log(chalk_1.default.cyan(`\n 📝 Handoff Note:`));
110
+ console.log(chalk_1.default.white(` ${handoffNote}\n`));
111
+ console.log(chalk_1.default.gray(` They can resume with: ${chalk_1.default.white("jarvis resume --branch " + branch)}`));
112
+ }
113
+ else {
114
+ // Quick mode — minimal context with handoff
115
+ const [branch, repo, filesChanged, filesStaged, recentCommits, author] = await Promise.all([
116
+ (0, git_1.getCurrentBranch)(),
117
+ (0, git_1.getRepoName)(),
118
+ (0, git_1.getChangedFiles)(),
119
+ (0, git_1.getStagedFiles)(),
120
+ (0, git_1.getRecentCommits)(),
121
+ (0, git_1.getAuthor)(),
122
+ ]);
123
+ const entry = {
124
+ id: (0, uuid_1.v4)(),
125
+ timestamp: new Date().toISOString(),
126
+ branch,
127
+ repo,
128
+ author,
129
+ task: `Handoff to @${targetAssignee}`,
130
+ approaches: [],
131
+ decisions: [],
132
+ currentState: handoffNote,
133
+ nextSteps: [],
134
+ filesChanged,
135
+ filesStaged,
136
+ recentCommits,
137
+ assignee: targetAssignee,
138
+ handoffNote,
139
+ };
140
+ await (0, context_1.saveContext)(entry);
141
+ console.log(chalk_1.default.green(`\n✓ Handoff created for ${chalk_1.default.bold("@" + targetAssignee)}`));
142
+ console.log(chalk_1.default.gray(` Branch: ${branch}`));
143
+ console.log(chalk_1.default.cyan(`\n 📝 Handoff Note:`));
144
+ console.log(chalk_1.default.white(` ${handoffNote}\n`));
145
+ console.log(chalk_1.default.gray(` They can resume with: ${chalk_1.default.white("jarvis resume --branch " + branch)}`));
146
+ }
147
+ }
148
+ catch (err) {
149
+ console.log(chalk_1.default.red(`✗ Error: ${err.message}`));
150
+ }
151
+ }
@@ -0,0 +1 @@
1
+ export declare function hookCommand(action?: string): Promise<void>;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.hookCommand = hookCommand;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const git_1 = require("../core/git");
11
+ async function hookCommand(action) {
12
+ try {
13
+ const root = await (0, git_1.getRepoRoot)();
14
+ const hooksDir = path_1.default.join(root, ".git", "hooks");
15
+ const hookPath = path_1.default.join(hooksDir, "post-commit");
16
+ if (action === "remove") {
17
+ if (!fs_1.default.existsSync(hookPath)) {
18
+ console.log(chalk_1.default.yellow("⚠ No DevContext git hook found."));
19
+ return;
20
+ }
21
+ const content = fs_1.default.readFileSync(hookPath, "utf-8");
22
+ if (!content.includes("jarvis")) {
23
+ console.log(chalk_1.default.yellow("⚠ post-commit hook exists but was not created by DevContext."));
24
+ return;
25
+ }
26
+ // Remove only the jarvis line, preserve other hooks
27
+ const lines = content.split("\n").filter((l) => !l.includes("jarvis"));
28
+ if (lines.filter((l) => l.trim() && !l.startsWith("#!")).length === 0) {
29
+ fs_1.default.unlinkSync(hookPath);
30
+ }
31
+ else {
32
+ fs_1.default.writeFileSync(hookPath, lines.join("\n"));
33
+ fs_1.default.chmodSync(hookPath, "755");
34
+ }
35
+ console.log(chalk_1.default.green("✓ Removed DevContext post-commit hook"));
36
+ return;
37
+ }
38
+ // Default: install
39
+ fs_1.default.mkdirSync(hooksDir, { recursive: true });
40
+ let hookContent = "#!/bin/sh\n";
41
+ if (fs_1.default.existsSync(hookPath)) {
42
+ const existing = fs_1.default.readFileSync(hookPath, "utf-8");
43
+ if (existing.includes("jarvis")) {
44
+ console.log(chalk_1.default.yellow("⚠ DevContext post-commit hook already installed."));
45
+ return;
46
+ }
47
+ // Append to existing hook
48
+ hookContent = existing.trimEnd() + "\n";
49
+ }
50
+ hookContent += `\n# DevContext auto-snapshot on commit\njarvis save "Auto-saved on commit: $(git log -1 --pretty=%B | head -1)" 2>/dev/null || true\n`;
51
+ fs_1.default.writeFileSync(hookPath, hookContent);
52
+ fs_1.default.chmodSync(hookPath, "755");
53
+ console.log(chalk_1.default.green("✓ Installed DevContext post-commit hook"));
54
+ console.log(chalk_1.default.gray(" Context will be auto-saved on every commit."));
55
+ console.log(chalk_1.default.gray(" Remove with: jarvis hook remove"));
56
+ }
57
+ catch (err) {
58
+ console.log(chalk_1.default.red(`✗ Error: ${err.message}`));
59
+ }
60
+ }
@@ -0,0 +1 @@
1
+ export declare function initCommand(): Promise<void>;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initCommand = initCommand;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const git_1 = require("../core/git");
11
+ async function initCommand() {
12
+ try {
13
+ const root = await (0, git_1.getRepoRoot)();
14
+ const devctxDir = path_1.default.join(root, ".jarvis");
15
+ if (fs_1.default.existsSync(devctxDir)) {
16
+ console.log(chalk_1.default.yellow("⚠ DevContext already initialized in this repo."));
17
+ return;
18
+ }
19
+ // Create directory structure
20
+ fs_1.default.mkdirSync(path_1.default.join(devctxDir, "sessions"), { recursive: true });
21
+ fs_1.default.mkdirSync(path_1.default.join(devctxDir, "branches"), { recursive: true });
22
+ // Write config
23
+ const config = {
24
+ version: "0.1.0",
25
+ createdAt: new Date().toISOString(),
26
+ repo: await (0, git_1.getRepoName)(),
27
+ };
28
+ fs_1.default.writeFileSync(path_1.default.join(devctxDir, "config.json"), JSON.stringify(config, null, 2));
29
+ // Add to .gitignore
30
+ const gitignorePath = path_1.default.join(root, ".gitignore");
31
+ const gitignoreContent = fs_1.default.existsSync(gitignorePath)
32
+ ? fs_1.default.readFileSync(gitignorePath, "utf-8")
33
+ : "";
34
+ if (!gitignoreContent.includes(".jarvis/")) {
35
+ fs_1.default.appendFileSync(gitignorePath, "\n# DevContext - AI coding context\n.jarvis/\n");
36
+ console.log(chalk_1.default.gray(" Added .jarvis/ to .gitignore"));
37
+ }
38
+ console.log(chalk_1.default.green(`✓ Initialized DevContext in ${root}`));
39
+ console.log(chalk_1.default.gray(" Run `jarvis save` to capture your first context."));
40
+ }
41
+ catch (err) {
42
+ if (err.message?.includes("not a git repository")) {
43
+ console.log(chalk_1.default.red("✗ Not a git repository. Run `git init` first."));
44
+ }
45
+ else {
46
+ console.log(chalk_1.default.red(`✗ Error: ${err.message}`));
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,4 @@
1
+ export declare function logCommand(options?: {
2
+ all?: boolean;
3
+ count?: string;
4
+ }): Promise<void>;