decisionnode 0.2.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/LICENSE +21 -0
- package/README.md +80 -0
- package/dist/ai/gemini.d.ts +15 -0
- package/dist/ai/gemini.js +56 -0
- package/dist/ai/rag.d.ts +79 -0
- package/dist/ai/rag.js +268 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1724 -0
- package/dist/cloud.d.ts +177 -0
- package/dist/cloud.js +631 -0
- package/dist/env.d.ts +47 -0
- package/dist/env.js +139 -0
- package/dist/history.d.ts +34 -0
- package/dist/history.js +159 -0
- package/dist/maintenance.d.ts +7 -0
- package/dist/maintenance.js +49 -0
- package/dist/marketplace.d.ts +46 -0
- package/dist/marketplace.js +300 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +621 -0
- package/dist/setup.d.ts +6 -0
- package/dist/setup.js +132 -0
- package/dist/store.d.ts +126 -0
- package/dist/store.js +555 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.js +9 -0
- package/package.json +57 -0
package/dist/setup.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Load environment variables first
|
|
3
|
+
import './env.js';
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import readline from 'readline';
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
/**
|
|
11
|
+
* Prompt user for input
|
|
12
|
+
*/
|
|
13
|
+
function prompt(question) {
|
|
14
|
+
const rl = readline.createInterface({
|
|
15
|
+
input: process.stdin,
|
|
16
|
+
output: process.stdout
|
|
17
|
+
});
|
|
18
|
+
return new Promise((resolve) => {
|
|
19
|
+
rl.question(question, (answer) => {
|
|
20
|
+
rl.close();
|
|
21
|
+
resolve(answer.trim());
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get the MCP config file path
|
|
27
|
+
*/
|
|
28
|
+
function getMCPConfigPath() {
|
|
29
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
30
|
+
return path.join(homeDir, '.gemini', 'antigravity', 'mcp_config.json');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Read existing MCP config
|
|
34
|
+
*/
|
|
35
|
+
async function readMCPConfig(configPath) {
|
|
36
|
+
try {
|
|
37
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
38
|
+
return JSON.parse(content);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
// File doesn't exist or is invalid, return empty config
|
|
42
|
+
return { mcpServers: {} };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Write MCP config
|
|
47
|
+
*/
|
|
48
|
+
async function writeMCPConfig(configPath, config) {
|
|
49
|
+
// Ensure directory exists
|
|
50
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
51
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Try to read API key from environment (already loaded by env.ts)
|
|
55
|
+
*/
|
|
56
|
+
function getApiKeyFromEnv() {
|
|
57
|
+
return process.env.GEMINI_API_KEY || null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Main setup flow
|
|
61
|
+
*/
|
|
62
|
+
export async function runSetup() {
|
|
63
|
+
console.log('š§ DecisionNode MCP Setup\n');
|
|
64
|
+
// 1. Try to auto-detect API key from .env
|
|
65
|
+
let apiKey = getApiKeyFromEnv();
|
|
66
|
+
if (apiKey) {
|
|
67
|
+
console.log('ā Found GEMINI_API_KEY in .env file\n');
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.log('Step 1: Gemini API Key');
|
|
71
|
+
console.log('Get your free API key from: https://aistudio.google.com/api-keys\n');
|
|
72
|
+
apiKey = await prompt('Enter your GEMINI_API_KEY (or press Enter to skip): ');
|
|
73
|
+
if (!apiKey) {
|
|
74
|
+
console.log('\nā ļø Skipping API key for now. You can add it later in the MCP config file.');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// 2. Get MCP config path
|
|
78
|
+
const configPath = getMCPConfigPath();
|
|
79
|
+
console.log(`\nStep 2: Updating MCP config at:\n${configPath}\n`);
|
|
80
|
+
// 3. Read existing config
|
|
81
|
+
let config;
|
|
82
|
+
try {
|
|
83
|
+
config = await readMCPConfig(configPath);
|
|
84
|
+
console.log('ā Found existing MCP config');
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
config = { mcpServers: {} };
|
|
88
|
+
console.log('ā Creating new MCP config');
|
|
89
|
+
}
|
|
90
|
+
// 4. Add/update DecisionNode entry for THIS project
|
|
91
|
+
if (!config.mcpServers) {
|
|
92
|
+
config.mcpServers = {};
|
|
93
|
+
}
|
|
94
|
+
// Single entry - Antigravity sets cwd based on active workspace
|
|
95
|
+
config.mcpServers.decisionnode = {
|
|
96
|
+
command: 'npx',
|
|
97
|
+
args: ['decide-mcp'],
|
|
98
|
+
...(apiKey ? { env: { GEMINI_API_KEY: apiKey } } : {})
|
|
99
|
+
};
|
|
100
|
+
// 5. Write config
|
|
101
|
+
try {
|
|
102
|
+
await writeMCPConfig(configPath, config);
|
|
103
|
+
console.log('ā Updated MCP config\n');
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
console.error('ā Failed to write MCP config:', error);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
// 6. Success message
|
|
110
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
111
|
+
const globalStore = path.join(homeDir, '.decisionnode');
|
|
112
|
+
console.log('ā
DecisionNode MCP setup complete!\n');
|
|
113
|
+
console.log('š Global store: ' + globalStore);
|
|
114
|
+
console.log(' Each project gets its own isolated folder automatically.\n');
|
|
115
|
+
if (!apiKey) {
|
|
116
|
+
console.log('š To add your API key later, edit:');
|
|
117
|
+
console.log(` ${configPath}\n`);
|
|
118
|
+
console.log(' Add this to the "decisionnode" entry:');
|
|
119
|
+
console.log(' "env": { "GEMINI_API_KEY": "your-key-here" }\n');
|
|
120
|
+
}
|
|
121
|
+
console.log('š Next steps:');
|
|
122
|
+
console.log(' 1. Restart Antigravity (or reload MCP servers)');
|
|
123
|
+
console.log(' 2. Open any project - decisions are automatically isolated!');
|
|
124
|
+
console.log(' 3. Try asking: "Add a decision about our architecture"\n');
|
|
125
|
+
}
|
|
126
|
+
// Run setup if called directly
|
|
127
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
128
|
+
runSetup().catch((error) => {
|
|
129
|
+
console.error('Setup failed:', error);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
});
|
|
132
|
+
}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { DecisionNode, DecisionCollection } from './types.js';
|
|
2
|
+
import { SourceType } from './history.js';
|
|
3
|
+
/**
|
|
4
|
+
* Get all available scopes by scanning the .decisions directory
|
|
5
|
+
*/
|
|
6
|
+
export declare function getAvailableScopes(): Promise<string[]>;
|
|
7
|
+
/**
|
|
8
|
+
* Get all available scopes in the global decisions folder
|
|
9
|
+
*/
|
|
10
|
+
export declare function getGlobalScopes(): Promise<string[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Load all decisions for a given scope from the global folder
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadGlobalDecisions(scope: string): Promise<DecisionCollection>;
|
|
15
|
+
/**
|
|
16
|
+
* Save decisions for a given scope in the global folder
|
|
17
|
+
*/
|
|
18
|
+
export declare function saveGlobalDecisions(collection: DecisionCollection): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* List all global decisions, optionally filtered by scope
|
|
21
|
+
* Returns decisions with "global:" prefix on IDs
|
|
22
|
+
*/
|
|
23
|
+
export declare function listGlobalDecisions(scope?: string): Promise<DecisionNode[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Get a global decision by ID (with or without "global:" prefix)
|
|
26
|
+
*/
|
|
27
|
+
export declare function getGlobalDecisionById(id: string): Promise<DecisionNode | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Generate the next decision ID for a global scope
|
|
30
|
+
* Returns ID without the "global:" prefix (prefix is added on read)
|
|
31
|
+
*/
|
|
32
|
+
export declare function getNextGlobalDecisionId(scope: string): Promise<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Add a new global decision
|
|
35
|
+
*/
|
|
36
|
+
export declare function addGlobalDecision(decision: DecisionNode, source?: SourceType): Promise<{
|
|
37
|
+
embedded: boolean;
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Update an existing global decision
|
|
41
|
+
*/
|
|
42
|
+
export declare function updateGlobalDecision(id: string, updates: Partial<DecisionNode>): Promise<DecisionNode | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Delete a global decision
|
|
45
|
+
*/
|
|
46
|
+
export declare function deleteGlobalDecision(id: string): Promise<boolean>;
|
|
47
|
+
/**
|
|
48
|
+
* Normalize scope to consistent capitalized format
|
|
49
|
+
* e.g., 'ui', 'UI', 'Ui', 'uI' all become 'UI'
|
|
50
|
+
* e.g., 'backend', 'Backend', 'BACKEND' all become 'Backend'
|
|
51
|
+
*/
|
|
52
|
+
export declare function normalizeScope(scope: string): string;
|
|
53
|
+
export interface ProjectInfo {
|
|
54
|
+
name: string;
|
|
55
|
+
decisionCount: number;
|
|
56
|
+
scopes: string[];
|
|
57
|
+
lastModified?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* List all available projects in the global store
|
|
61
|
+
* Returns project name, decision count, and available scopes
|
|
62
|
+
*/
|
|
63
|
+
export declare function listProjects(): Promise<ProjectInfo[]>;
|
|
64
|
+
/**
|
|
65
|
+
* Load all decisions for a given scope
|
|
66
|
+
*/
|
|
67
|
+
export declare function loadDecisions(scope: string): Promise<DecisionCollection>;
|
|
68
|
+
/**
|
|
69
|
+
* Save decisions for a given scope
|
|
70
|
+
*/
|
|
71
|
+
export declare function saveDecisions(collection: DecisionCollection): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Get a single decision by ID across all scopes
|
|
74
|
+
*/
|
|
75
|
+
export declare function getDecisionById(id: string): Promise<DecisionNode | null>;
|
|
76
|
+
/**
|
|
77
|
+
* List all decisions, optionally filtered by scope
|
|
78
|
+
*/
|
|
79
|
+
export declare function listDecisions(scope?: string): Promise<DecisionNode[]>;
|
|
80
|
+
/**
|
|
81
|
+
* Add a new decision
|
|
82
|
+
* Auto-embeds and logs the action
|
|
83
|
+
* @param decision - The decision to add
|
|
84
|
+
* @param source - Where this action originated (default: 'cli')
|
|
85
|
+
*/
|
|
86
|
+
export declare function addDecision(decision: DecisionNode, source?: SourceType): Promise<{
|
|
87
|
+
embedded: boolean;
|
|
88
|
+
}>;
|
|
89
|
+
/**
|
|
90
|
+
* Update an existing decision
|
|
91
|
+
* Auto-embeds and logs the action
|
|
92
|
+
*/
|
|
93
|
+
export declare function updateDecision(id: string, updates: Partial<DecisionNode>): Promise<DecisionNode | null>;
|
|
94
|
+
/**
|
|
95
|
+
* Delete a decision by ID
|
|
96
|
+
* Clears embedding and logs the action
|
|
97
|
+
*/
|
|
98
|
+
export declare function deleteDecision(id: string): Promise<boolean>;
|
|
99
|
+
/**
|
|
100
|
+
* Delete an entire scope (all decisions within it)
|
|
101
|
+
* Deletes the scope file, embeddings, and optionally from cloud
|
|
102
|
+
*/
|
|
103
|
+
export declare function deleteScope(scope: string): Promise<{
|
|
104
|
+
deleted: number;
|
|
105
|
+
decisionIds: string[];
|
|
106
|
+
}>;
|
|
107
|
+
/**
|
|
108
|
+
* Generate the next decision ID for a scope
|
|
109
|
+
*/
|
|
110
|
+
export declare function getNextDecisionId(scope: string): Promise<string>;
|
|
111
|
+
/**
|
|
112
|
+
* Renumber decisions in a scope after deletion
|
|
113
|
+
* Also updates embeddings for renamed IDs
|
|
114
|
+
*/
|
|
115
|
+
export declare function renumberDecisions(scope: string): Promise<string[]>;
|
|
116
|
+
/**
|
|
117
|
+
* Import decisions from a JSON file or object
|
|
118
|
+
* Auto-embeds all imported decisions
|
|
119
|
+
*/
|
|
120
|
+
export declare function importDecisions(decisions: DecisionNode[], options?: {
|
|
121
|
+
overwrite?: boolean;
|
|
122
|
+
}): Promise<{
|
|
123
|
+
added: number;
|
|
124
|
+
skipped: number;
|
|
125
|
+
embedded: number;
|
|
126
|
+
}>;
|