@kawacode/mcp 5.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.
- package/CLAUDE.md.example +80 -0
- package/LICENSE +35 -0
- package/README.md +322 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +231 -0
- package/build/index.js.map +1 -0
- package/build/prompts/intent-first-workflow.d.ts +24 -0
- package/build/prompts/intent-first-workflow.js +204 -0
- package/build/prompts/intent-first-workflow.js.map +1 -0
- package/build/resources/active-intent.d.ts +9 -0
- package/build/resources/active-intent.js +52 -0
- package/build/resources/active-intent.js.map +1 -0
- package/build/services/active-intent-store.d.ts +36 -0
- package/build/services/active-intent-store.js +45 -0
- package/build/services/active-intent-store.js.map +1 -0
- package/build/services/kawa-api.d.ts +131 -0
- package/build/services/kawa-api.js +239 -0
- package/build/services/kawa-api.js.map +1 -0
- package/build/services/muninn-ipc.d.ts +45 -0
- package/build/services/muninn-ipc.js +275 -0
- package/build/services/muninn-ipc.js.map +1 -0
- package/build/services/repo-encryption.d.ts +46 -0
- package/build/services/repo-encryption.js +92 -0
- package/build/services/repo-encryption.js.map +1 -0
- package/build/services/storage-decryption.d.ts +52 -0
- package/build/services/storage-decryption.js +162 -0
- package/build/services/storage-decryption.js.map +1 -0
- package/build/tools/assign-blocks.d.ts +87 -0
- package/build/tools/assign-blocks.js +49 -0
- package/build/tools/assign-blocks.js.map +1 -0
- package/build/tools/check-active-intent.d.ts +50 -0
- package/build/tools/check-active-intent.js +48 -0
- package/build/tools/check-active-intent.js.map +1 -0
- package/build/tools/complete-intent.d.ts +48 -0
- package/build/tools/complete-intent.js +53 -0
- package/build/tools/complete-intent.js.map +1 -0
- package/build/tools/create-intent.d.ts +58 -0
- package/build/tools/create-intent.js +49 -0
- package/build/tools/create-intent.js.map +1 -0
- package/build/tools/detect-intent-conflicts.d.ts +361 -0
- package/build/tools/detect-intent-conflicts.js +91 -0
- package/build/tools/detect-intent-conflicts.js.map +1 -0
- package/build/tools/edit-session-decision.d.ts +201 -0
- package/build/tools/edit-session-decision.js +50 -0
- package/build/tools/edit-session-decision.js.map +1 -0
- package/build/tools/evolve-decisions.d.ts +50 -0
- package/build/tools/evolve-decisions.js +45 -0
- package/build/tools/evolve-decisions.js.map +1 -0
- package/build/tools/get-intent-changes.d.ts +49 -0
- package/build/tools/get-intent-changes.js +58 -0
- package/build/tools/get-intent-changes.js.map +1 -0
- package/build/tools/get-intents-for-file.d.ts +57 -0
- package/build/tools/get-intents-for-file.js +57 -0
- package/build/tools/get-intents-for-file.js.map +1 -0
- package/build/tools/get-intents-for-lines.d.ts +71 -0
- package/build/tools/get-intents-for-lines.js +64 -0
- package/build/tools/get-intents-for-lines.js.map +1 -0
- package/build/tools/get-project-context.d.ts +82 -0
- package/build/tools/get-project-context.js +73 -0
- package/build/tools/get-project-context.js.map +1 -0
- package/build/tools/get-project-decisions.d.ts +51 -0
- package/build/tools/get-project-decisions.js +56 -0
- package/build/tools/get-project-decisions.js.map +1 -0
- package/build/tools/get-relevant-context.d.ts +89 -0
- package/build/tools/get-relevant-context.js +104 -0
- package/build/tools/get-relevant-context.js.map +1 -0
- package/build/tools/get-session-decisions.d.ts +57 -0
- package/build/tools/get-session-decisions.js +48 -0
- package/build/tools/get-session-decisions.js.map +1 -0
- package/build/tools/index.d.ts +656 -0
- package/build/tools/index.js +57 -0
- package/build/tools/index.js.map +1 -0
- package/build/tools/infer-history.d.ts +85 -0
- package/build/tools/infer-history.js +69 -0
- package/build/tools/infer-history.js.map +1 -0
- package/build/tools/list-team-intents.d.ts +51 -0
- package/build/tools/list-team-intents.js +57 -0
- package/build/tools/list-team-intents.js.map +1 -0
- package/build/tools/log-work.d.ts +45 -0
- package/build/tools/log-work.js +30 -0
- package/build/tools/log-work.js.map +1 -0
- package/build/tools/record-decision.d.ts +132 -0
- package/build/tools/record-decision.js +66 -0
- package/build/tools/record-decision.js.map +1 -0
- package/build/tools/resolve-origin.d.ts +13 -0
- package/build/tools/resolve-origin.js +33 -0
- package/build/tools/resolve-origin.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repository content encryption for zero-knowledge block assignment.
|
|
3
|
+
*
|
|
4
|
+
* Replicates Muninn Gardener's encryption.rs for intent block content:
|
|
5
|
+
* - Key derivation: PBKDF2-HMAC-SHA256, 600,000 iterations
|
|
6
|
+
* - Key material: "{initialCommitSHA}-{origin}"
|
|
7
|
+
* - Salt: "kawa-code-zero-knowledge-v1"
|
|
8
|
+
* - Cipher: AES-256-GCM with random 12-byte IV
|
|
9
|
+
* - Output: JSON string {"encryptedContent", "iv", "authTag"}
|
|
10
|
+
*/
|
|
11
|
+
import * as crypto from 'crypto';
|
|
12
|
+
import { execSync } from 'child_process';
|
|
13
|
+
// Cache derived keys by "initialCommit:origin" to avoid repeated 600K-iteration PBKDF2
|
|
14
|
+
const keyCache = new Map();
|
|
15
|
+
/**
|
|
16
|
+
* Derive a 32-byte AES key from the repo's initial commit SHA and origin.
|
|
17
|
+
*
|
|
18
|
+
* Matches Muninn's derive_repository_key():
|
|
19
|
+
* - key material = "{initialCommit}-{origin}"
|
|
20
|
+
* - salt = "kawa-code-zero-knowledge-v1"
|
|
21
|
+
* - 600,000 PBKDF2-HMAC-SHA256 iterations
|
|
22
|
+
*/
|
|
23
|
+
export function deriveRepoKey(initialCommit, origin) {
|
|
24
|
+
const cacheKey = `${initialCommit.trim()}:${origin}`;
|
|
25
|
+
const cached = keyCache.get(cacheKey);
|
|
26
|
+
if (cached)
|
|
27
|
+
return cached;
|
|
28
|
+
const keyMaterial = `${initialCommit.trim()}-${origin}`;
|
|
29
|
+
const salt = 'kawa-code-zero-knowledge-v1';
|
|
30
|
+
const key = crypto.pbkdf2Sync(keyMaterial, salt, 600_000, 32, 'sha256');
|
|
31
|
+
keyCache.set(cacheKey, key);
|
|
32
|
+
return key;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get the initial (root) commit SHA for a repository.
|
|
36
|
+
*/
|
|
37
|
+
export function getInitialCommitSHA(repoPath) {
|
|
38
|
+
return execSync('git rev-list --max-parents=0 HEAD', {
|
|
39
|
+
cwd: repoPath,
|
|
40
|
+
encoding: 'utf-8',
|
|
41
|
+
timeout: 10000,
|
|
42
|
+
}).trim().split('\n')[0]; // Take first if multiple roots
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Encrypt content using AES-256-GCM.
|
|
46
|
+
*
|
|
47
|
+
* Returns a JSON string matching Muninn's EncryptedContent format:
|
|
48
|
+
* { "encryptedContent": hex, "iv": hex, "authTag": hex }
|
|
49
|
+
*
|
|
50
|
+
* The encryptedContent hex includes the 16-byte auth tag appended
|
|
51
|
+
* (AES-GCM ciphertext + tag), matching Gardener's Rust implementation.
|
|
52
|
+
*/
|
|
53
|
+
export function encryptContent(plaintext, key) {
|
|
54
|
+
const iv = crypto.randomBytes(12);
|
|
55
|
+
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
|
|
56
|
+
const encrypted = Buffer.concat([
|
|
57
|
+
cipher.update(plaintext, 'utf8'),
|
|
58
|
+
cipher.final(),
|
|
59
|
+
]);
|
|
60
|
+
const authTag = cipher.getAuthTag(); // 16 bytes
|
|
61
|
+
// Gardener appends authTag to ciphertext in encryptedContent
|
|
62
|
+
const ciphertextWithTag = Buffer.concat([encrypted, authTag]);
|
|
63
|
+
return JSON.stringify({
|
|
64
|
+
encryptedContent: ciphertextWithTag.toString('hex'),
|
|
65
|
+
iv: iv.toString('hex'),
|
|
66
|
+
authTag: authTag.toString('hex'),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Extract content from a file at the given line range and compute hash + snippet.
|
|
71
|
+
*
|
|
72
|
+
* Matches Gardener's IntentBlockService::extract_content_and_hash():
|
|
73
|
+
* - Lines are 1-based
|
|
74
|
+
* - snippet = first 150 characters
|
|
75
|
+
* - contentHash = SHA-256 of the whitespace-normalized plaintext (hex)
|
|
76
|
+
*/
|
|
77
|
+
export function extractContentAndHash(fileContent, startLine, endLine) {
|
|
78
|
+
const lines = fileContent.split('\n');
|
|
79
|
+
const startIdx = startLine - 1;
|
|
80
|
+
const endIdx = Math.min(endLine, lines.length);
|
|
81
|
+
if (startIdx >= lines.length) {
|
|
82
|
+
return { content: '', contentHash: '', contentSnippet: '' };
|
|
83
|
+
}
|
|
84
|
+
const content = lines.slice(startIdx, endIdx).join('\n');
|
|
85
|
+
const contentSnippet = content.slice(0, 150);
|
|
86
|
+
const contentHash = crypto
|
|
87
|
+
.createHash('sha256')
|
|
88
|
+
.update(content.trim())
|
|
89
|
+
.digest('hex');
|
|
90
|
+
return { content, contentHash, contentSnippet };
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=repo-encryption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-encryption.js","sourceRoot":"","sources":["../../src/services/repo-encryption.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage decryption service for reading auth tokens from Muninn's encrypted storage.
|
|
3
|
+
*
|
|
4
|
+
* This module replicates Muninn's storage encryption scheme to read the auth token
|
|
5
|
+
* from ~/.kawa-code/.storage.caw without requiring manual env var configuration.
|
|
6
|
+
*
|
|
7
|
+
* Encryption details (must match Muninn's encryption.rs):
|
|
8
|
+
* - Key derivation: username:hostname with salt "kawa-storage-encryption-v1"
|
|
9
|
+
* - Algorithm: PBKDF2-HMAC-SHA256, 100,000 iterations
|
|
10
|
+
* - Cipher: AES-256-GCM
|
|
11
|
+
* - Format: hex(iv):hex(ciphertext):hex(auth_tag)
|
|
12
|
+
*/
|
|
13
|
+
export interface TokenObject {
|
|
14
|
+
_id: string;
|
|
15
|
+
token: string;
|
|
16
|
+
kind: string;
|
|
17
|
+
expires: string;
|
|
18
|
+
user: string;
|
|
19
|
+
createdAt: string;
|
|
20
|
+
denied: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface AuthTokens {
|
|
23
|
+
access: TokenObject;
|
|
24
|
+
refresh?: TokenObject;
|
|
25
|
+
}
|
|
26
|
+
export interface StorageData {
|
|
27
|
+
auth?: {
|
|
28
|
+
user?: any;
|
|
29
|
+
tokens?: AuthTokens;
|
|
30
|
+
};
|
|
31
|
+
[key: string]: any;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Read and decrypt the storage file
|
|
35
|
+
*
|
|
36
|
+
* Returns the parsed storage data or null if unavailable/corrupted.
|
|
37
|
+
* Handles both encrypted and legacy unencrypted formats.
|
|
38
|
+
*/
|
|
39
|
+
export declare function readStorage(): StorageData | null;
|
|
40
|
+
/**
|
|
41
|
+
* Extract auth token from storage
|
|
42
|
+
*
|
|
43
|
+
* Returns the access token if available, otherwise null.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getAuthTokenFromStorage(): string | null;
|
|
46
|
+
/**
|
|
47
|
+
* Get full auth data from storage (user + tokens)
|
|
48
|
+
*/
|
|
49
|
+
export declare function getAuthFromStorage(): {
|
|
50
|
+
user: any;
|
|
51
|
+
tokens: AuthTokens;
|
|
52
|
+
} | null;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage decryption service for reading auth tokens from Muninn's encrypted storage.
|
|
3
|
+
*
|
|
4
|
+
* This module replicates Muninn's storage encryption scheme to read the auth token
|
|
5
|
+
* from ~/.kawa-code/.storage.caw without requiring manual env var configuration.
|
|
6
|
+
*
|
|
7
|
+
* Encryption details (must match Muninn's encryption.rs):
|
|
8
|
+
* - Key derivation: username:hostname with salt "kawa-storage-encryption-v1"
|
|
9
|
+
* - Algorithm: PBKDF2-HMAC-SHA256, 100,000 iterations
|
|
10
|
+
* - Cipher: AES-256-GCM
|
|
11
|
+
* - Format: hex(iv):hex(ciphertext):hex(auth_tag)
|
|
12
|
+
*/
|
|
13
|
+
import * as crypto from 'crypto';
|
|
14
|
+
import * as fs from 'fs';
|
|
15
|
+
import * as os from 'os';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
/**
|
|
18
|
+
* Derive storage encryption key from username and hostname
|
|
19
|
+
*
|
|
20
|
+
* Matches Muninn's derive_storage_key() implementation:
|
|
21
|
+
* - Key material: "username:hostname"
|
|
22
|
+
* - Salt: "kawa-storage-encryption-v1"
|
|
23
|
+
* - Algorithm: PBKDF2-HMAC-SHA256
|
|
24
|
+
* - Iterations: 100,000
|
|
25
|
+
* - Key length: 32 bytes
|
|
26
|
+
*/
|
|
27
|
+
function deriveStorageKey() {
|
|
28
|
+
const username = process.env.USER || process.env.USERNAME || 'unknown';
|
|
29
|
+
const hostname = os.hostname() || 'unknown';
|
|
30
|
+
const keyMaterial = `${username}:${hostname}`;
|
|
31
|
+
const salt = 'kawa-storage-encryption-v1';
|
|
32
|
+
// PBKDF2-HMAC-SHA256, 100,000 iterations, 32-byte output
|
|
33
|
+
return crypto.pbkdf2Sync(keyMaterial, salt, 100_000, 32, 'sha256');
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Decrypt storage file content
|
|
37
|
+
*
|
|
38
|
+
* Format: hex(iv):hex(ciphertext_with_auth_tag):hex(auth_tag)
|
|
39
|
+
* The ciphertext includes the auth tag at the end (last 16 bytes).
|
|
40
|
+
* AES-GCM verifies the auth tag automatically during decryption.
|
|
41
|
+
*/
|
|
42
|
+
function decryptStorage(encryptedData) {
|
|
43
|
+
const key = deriveStorageKey();
|
|
44
|
+
// Parse format: hex(iv):hex(ciphertext):hex(auth_tag)
|
|
45
|
+
const parts = encryptedData.split(':');
|
|
46
|
+
if (parts.length !== 3) {
|
|
47
|
+
throw new Error('Invalid encrypted storage format (expected 3 parts)');
|
|
48
|
+
}
|
|
49
|
+
const iv = Buffer.from(parts[0], 'hex');
|
|
50
|
+
const ciphertextWithTag = Buffer.from(parts[1], 'hex');
|
|
51
|
+
const authTag = Buffer.from(parts[2], 'hex');
|
|
52
|
+
// Verify IV length
|
|
53
|
+
if (iv.length !== 12) {
|
|
54
|
+
throw new Error(`Invalid IV length (expected 12, got ${iv.length})`);
|
|
55
|
+
}
|
|
56
|
+
// Verify auth tag length
|
|
57
|
+
if (authTag.length !== 16) {
|
|
58
|
+
throw new Error(`Invalid auth tag length (expected 16, got ${authTag.length})`);
|
|
59
|
+
}
|
|
60
|
+
// Create decipher for AES-256-GCM
|
|
61
|
+
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
|
|
62
|
+
decipher.setAuthTag(authTag);
|
|
63
|
+
// Decrypt (note: ciphertextWithTag includes the auth tag at the end, but we
|
|
64
|
+
// extract just the ciphertext portion for decryption since we set the auth tag separately)
|
|
65
|
+
const ciphertext = ciphertextWithTag.subarray(0, ciphertextWithTag.length - 16);
|
|
66
|
+
let plaintext = decipher.update(ciphertext, undefined, 'utf8');
|
|
67
|
+
plaintext += decipher.final('utf8');
|
|
68
|
+
return plaintext;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Check if content is in encrypted storage format
|
|
72
|
+
*
|
|
73
|
+
* Encrypted format: hex(iv):hex(ciphertext):hex(auth_tag)
|
|
74
|
+
* All three parts should be valid hex strings
|
|
75
|
+
*/
|
|
76
|
+
function isEncryptedStorage(content) {
|
|
77
|
+
const parts = content.split(':');
|
|
78
|
+
if (parts.length !== 3) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
// All parts should be valid hex (even length, only hex chars)
|
|
82
|
+
return parts.every(part => {
|
|
83
|
+
return part.length > 0 &&
|
|
84
|
+
part.length % 2 === 0 &&
|
|
85
|
+
/^[0-9a-fA-F]+$/.test(part);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get the storage file path
|
|
90
|
+
*
|
|
91
|
+
* Returns ~/.kawa-code/.storage.caw
|
|
92
|
+
*/
|
|
93
|
+
function getStoragePath() {
|
|
94
|
+
const homeDir = os.homedir();
|
|
95
|
+
return path.join(homeDir, '.kawa-code', '.storage.caw');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Read and decrypt the storage file
|
|
99
|
+
*
|
|
100
|
+
* Returns the parsed storage data or null if unavailable/corrupted.
|
|
101
|
+
* Handles both encrypted and legacy unencrypted formats.
|
|
102
|
+
*/
|
|
103
|
+
export function readStorage() {
|
|
104
|
+
try {
|
|
105
|
+
const storagePath = getStoragePath();
|
|
106
|
+
if (!fs.existsSync(storagePath)) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const content = fs.readFileSync(storagePath, 'utf8').trim();
|
|
110
|
+
if (!content) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
// Decrypt if encrypted, otherwise treat as legacy plaintext JSON
|
|
114
|
+
let plaintext;
|
|
115
|
+
if (isEncryptedStorage(content)) {
|
|
116
|
+
try {
|
|
117
|
+
plaintext = decryptStorage(content);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
console.error('Failed to decrypt storage (hostname/username may have changed):', err);
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// Legacy unencrypted format
|
|
126
|
+
plaintext = content;
|
|
127
|
+
}
|
|
128
|
+
// Parse JSON
|
|
129
|
+
const data = JSON.parse(plaintext);
|
|
130
|
+
return data;
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
console.error('Failed to read storage file:', err);
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Extract auth token from storage
|
|
139
|
+
*
|
|
140
|
+
* Returns the access token if available, otherwise null.
|
|
141
|
+
*/
|
|
142
|
+
export function getAuthTokenFromStorage() {
|
|
143
|
+
const storage = readStorage();
|
|
144
|
+
if (!storage?.auth?.tokens?.access?.token) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
return storage.auth.tokens.access.token;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get full auth data from storage (user + tokens)
|
|
151
|
+
*/
|
|
152
|
+
export function getAuthFromStorage() {
|
|
153
|
+
const storage = readStorage();
|
|
154
|
+
if (!storage?.auth?.user || !storage?.auth?.tokens) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
user: storage.auth.user,
|
|
159
|
+
tokens: storage.auth.tokens
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=storage-decryption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-decryption.js","sourceRoot":"","sources":["../../src/services/storage-decryption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAA;AAChC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAyB5B;;;;;;;;;GASG;AACH,SAAS,gBAAgB;IACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS,CAAA;IACtE,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,SAAS,CAAA;IAC3C,MAAM,WAAW,GAAG,GAAG,QAAQ,IAAI,QAAQ,EAAE,CAAA;IAC7C,MAAM,IAAI,GAAG,4BAA4B,CAAA;IAEzC,yDAAyD;IACzD,OAAO,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAA;AACpE,CAAC;AAED;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,aAAqB;IAC3C,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAA;IAE9B,sDAAsD;IACtD,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAA;IACxE,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACvC,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACtD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IAE5C,mBAAmB;IACnB,IAAI,EAAE,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,uCAAuC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAA;IACtE,CAAC;IAED,yBAAyB;IACzB,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,6CAA6C,OAAO,CAAC,MAAM,GAAG,CAAC,CAAA;IACjF,CAAC;IAED,kCAAkC;IAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAA;IAChE,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;IAE5B,4EAA4E;IAC5E,2FAA2F;IAC3F,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC,EAAE,iBAAiB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;IAE/E,IAAI,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,CAAA;IAC9D,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAEnC,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;GAKG;AACH,SAAS,kBAAkB,CAAC,OAAe;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAChC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,8DAA8D;IAC9D,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;QACxB,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC;YACf,IAAI,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC;YACrB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc;IACrB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAA;IAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,cAAc,CAAC,CAAA;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,cAAc,EAAE,CAAA;QAEpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAA;QACb,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAA;QAE3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,IAAI,CAAA;QACb,CAAC;QAED,iEAAiE;QACjE,IAAI,SAAiB,CAAA;QACrB,IAAI,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC;gBACH,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,CAAA;YACrC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,iEAAiE,EAAE,GAAG,CAAC,CAAA;gBACrF,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;aAAM,CAAC;YACN,4BAA4B;YAC5B,SAAS,GAAG,OAAO,CAAA;QACrB,CAAC;QAED,aAAa;QACb,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAgB,CAAA;QACjD,OAAO,IAAI,CAAA;IAEb,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,GAAG,CAAC,CAAA;QAClD,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB;IACrC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAA;IAE7B,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAA;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAA;IAE7B,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QACnD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI;QACvB,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM;KAC5B,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const assignBlocksSchema: z.ZodObject<{
|
|
3
|
+
repoOrigin: z.ZodOptional<z.ZodString>;
|
|
4
|
+
repoPath: z.ZodString;
|
|
5
|
+
intentId: z.ZodString;
|
|
6
|
+
blocks: z.ZodArray<z.ZodObject<{
|
|
7
|
+
filePath: z.ZodString;
|
|
8
|
+
startLine: z.ZodNumber;
|
|
9
|
+
endLine: z.ZodNumber;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
filePath: string;
|
|
12
|
+
startLine: number;
|
|
13
|
+
endLine: number;
|
|
14
|
+
}, {
|
|
15
|
+
filePath: string;
|
|
16
|
+
startLine: number;
|
|
17
|
+
endLine: number;
|
|
18
|
+
}>, "many">;
|
|
19
|
+
}, "strip", z.ZodTypeAny, {
|
|
20
|
+
repoPath: string;
|
|
21
|
+
intentId: string;
|
|
22
|
+
blocks: {
|
|
23
|
+
filePath: string;
|
|
24
|
+
startLine: number;
|
|
25
|
+
endLine: number;
|
|
26
|
+
}[];
|
|
27
|
+
repoOrigin?: string | undefined;
|
|
28
|
+
}, {
|
|
29
|
+
repoPath: string;
|
|
30
|
+
intentId: string;
|
|
31
|
+
blocks: {
|
|
32
|
+
filePath: string;
|
|
33
|
+
startLine: number;
|
|
34
|
+
endLine: number;
|
|
35
|
+
}[];
|
|
36
|
+
repoOrigin?: string | undefined;
|
|
37
|
+
}>;
|
|
38
|
+
export type AssignBlocksInput = z.infer<typeof assignBlocksSchema>;
|
|
39
|
+
export interface AssignBlocksResponse {
|
|
40
|
+
success: boolean;
|
|
41
|
+
assignedBlocks: number;
|
|
42
|
+
intentId: string;
|
|
43
|
+
intentTitle: string;
|
|
44
|
+
message: string;
|
|
45
|
+
}
|
|
46
|
+
export declare function assignBlocksToIntent(input: AssignBlocksInput): Promise<AssignBlocksResponse>;
|
|
47
|
+
export declare const assignBlocksToIntentTool: {
|
|
48
|
+
name: string;
|
|
49
|
+
description: string;
|
|
50
|
+
inputSchema: z.ZodObject<{
|
|
51
|
+
repoOrigin: z.ZodOptional<z.ZodString>;
|
|
52
|
+
repoPath: z.ZodString;
|
|
53
|
+
intentId: z.ZodString;
|
|
54
|
+
blocks: z.ZodArray<z.ZodObject<{
|
|
55
|
+
filePath: z.ZodString;
|
|
56
|
+
startLine: z.ZodNumber;
|
|
57
|
+
endLine: z.ZodNumber;
|
|
58
|
+
}, "strip", z.ZodTypeAny, {
|
|
59
|
+
filePath: string;
|
|
60
|
+
startLine: number;
|
|
61
|
+
endLine: number;
|
|
62
|
+
}, {
|
|
63
|
+
filePath: string;
|
|
64
|
+
startLine: number;
|
|
65
|
+
endLine: number;
|
|
66
|
+
}>, "many">;
|
|
67
|
+
}, "strip", z.ZodTypeAny, {
|
|
68
|
+
repoPath: string;
|
|
69
|
+
intentId: string;
|
|
70
|
+
blocks: {
|
|
71
|
+
filePath: string;
|
|
72
|
+
startLine: number;
|
|
73
|
+
endLine: number;
|
|
74
|
+
}[];
|
|
75
|
+
repoOrigin?: string | undefined;
|
|
76
|
+
}, {
|
|
77
|
+
repoPath: string;
|
|
78
|
+
intentId: string;
|
|
79
|
+
blocks: {
|
|
80
|
+
filePath: string;
|
|
81
|
+
startLine: number;
|
|
82
|
+
endLine: number;
|
|
83
|
+
}[];
|
|
84
|
+
repoOrigin?: string | undefined;
|
|
85
|
+
}>;
|
|
86
|
+
handler: typeof assignBlocksToIntent;
|
|
87
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { request } from '../services/muninn-ipc.js';
|
|
3
|
+
import { resolveOrigin } from './resolve-origin.js';
|
|
4
|
+
export const assignBlocksSchema = z.object({
|
|
5
|
+
repoOrigin: z.string().optional().describe('Git remote origin URL. Auto-detected from repoPath via git if not provided.'),
|
|
6
|
+
repoPath: z.string().describe('Local path to the repository root'),
|
|
7
|
+
intentId: z.string().describe('The intent ID to assign blocks to'),
|
|
8
|
+
blocks: z.array(z.object({
|
|
9
|
+
filePath: z.string().describe('Path to the file (relative to repo root)'),
|
|
10
|
+
startLine: z.number().min(1).describe('Start line number (1-based)'),
|
|
11
|
+
endLine: z.number().min(1).describe('End line number (1-based, inclusive)')
|
|
12
|
+
})).describe('Code blocks to assign to the active intent')
|
|
13
|
+
});
|
|
14
|
+
export async function assignBlocksToIntent(input) {
|
|
15
|
+
const actualOrigin = resolveOrigin(input.repoOrigin, input.repoPath);
|
|
16
|
+
// Delegate all file I/O, encryption, and API sync to Muninn
|
|
17
|
+
const res = await request('intent-block', 'batch-assign', {
|
|
18
|
+
repoOrigin: actualOrigin,
|
|
19
|
+
repoPath: input.repoPath,
|
|
20
|
+
intentId: input.intentId,
|
|
21
|
+
blocks: input.blocks.map(b => ({
|
|
22
|
+
filePath: b.filePath,
|
|
23
|
+
startLine: b.startLine,
|
|
24
|
+
endLine: b.endLine,
|
|
25
|
+
})),
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
success: res.success !== false,
|
|
29
|
+
assignedBlocks: res.count || res.assignedCount || input.blocks.length,
|
|
30
|
+
intentId: res.intentId || '',
|
|
31
|
+
intentTitle: res.intentTitle || 'Active Intent',
|
|
32
|
+
message: `Assigned ${res.count || input.blocks.length} code block(s) to active intent`
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export const assignBlocksToIntentTool = {
|
|
36
|
+
name: 'assign_blocks_to_intent',
|
|
37
|
+
description: `Assign code blocks to the currently active intent.
|
|
38
|
+
|
|
39
|
+
Call this AFTER writing code to track which lines were modified:
|
|
40
|
+
1. For each file you modified, provide the line range
|
|
41
|
+
2. Blocks get assigned to the active intent
|
|
42
|
+
3. This enables tracking, conflict detection, and team visibility
|
|
43
|
+
|
|
44
|
+
Example: After adding a function at lines 50-75 in auth.ts, call with:
|
|
45
|
+
{ blocks: [{ filePath: "src/auth.ts", startLine: 50, endLine: 75 }] }`,
|
|
46
|
+
inputSchema: assignBlocksSchema,
|
|
47
|
+
handler: assignBlocksToIntent
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=assign-blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assign-blocks.js","sourceRoot":"","sources":["../../src/tools/assign-blocks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAEnD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6EAA6E,CAAC;IACzH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IAClE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IAClE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QACvB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;QACzE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,6BAA6B,CAAC;QACpE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,sCAAsC,CAAC;KAC5E,CAAC,CAAC,CAAC,QAAQ,CAAC,4CAA4C,CAAC;CAC3D,CAAC,CAAA;AAYF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAwB;IACjE,MAAM,YAAY,GAAG,aAAa,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;IAEpE,4DAA4D;IAC5D,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,cAAc,EAAE,cAAc,EAAE;QACxD,UAAU,EAAE,YAAY;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC7B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,OAAO,EAAE,CAAC,CAAC,OAAO;SACnB,CAAC,CAAC;KACJ,CAAC,CAAA;IAEF,OAAO;QACL,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,KAAK;QAC9B,cAAc,EAAE,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,aAAa,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM;QACrE,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE;QAC5B,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,eAAe;QAC/C,OAAO,EAAE,YAAY,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,iCAAiC;KACvF,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EAAE;;;;;;;;sEAQuD;IACpE,WAAW,EAAE,kBAAkB;IAC/B,OAAO,EAAE,oBAAoB;CAC9B,CAAA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const checkActiveIntentSchema: z.ZodObject<{
|
|
3
|
+
repoOrigin: z.ZodOptional<z.ZodString>;
|
|
4
|
+
repoPath: z.ZodString;
|
|
5
|
+
}, "strip", z.ZodTypeAny, {
|
|
6
|
+
repoPath: string;
|
|
7
|
+
repoOrigin?: string | undefined;
|
|
8
|
+
}, {
|
|
9
|
+
repoPath: string;
|
|
10
|
+
repoOrigin?: string | undefined;
|
|
11
|
+
}>;
|
|
12
|
+
export type CheckActiveIntentInput = z.infer<typeof checkActiveIntentSchema>;
|
|
13
|
+
export interface IntentBlock {
|
|
14
|
+
id: string;
|
|
15
|
+
filePath: string;
|
|
16
|
+
startLine: number;
|
|
17
|
+
endLine: number;
|
|
18
|
+
contentSnippet: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ActiveIntentResponse {
|
|
21
|
+
hasActiveIntent: boolean;
|
|
22
|
+
intent?: {
|
|
23
|
+
id: string;
|
|
24
|
+
localId: string;
|
|
25
|
+
title: string;
|
|
26
|
+
description: string;
|
|
27
|
+
templateType: 'feature' | 'refactor' | 'exploration';
|
|
28
|
+
constraints: string[];
|
|
29
|
+
status: string;
|
|
30
|
+
branch: string;
|
|
31
|
+
forkedFrom?: string;
|
|
32
|
+
blocks: IntentBlock[];
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export declare function checkActiveIntent(input: CheckActiveIntentInput): Promise<ActiveIntentResponse>;
|
|
36
|
+
export declare const checkActiveIntentTool: {
|
|
37
|
+
name: string;
|
|
38
|
+
description: string;
|
|
39
|
+
inputSchema: z.ZodObject<{
|
|
40
|
+
repoOrigin: z.ZodOptional<z.ZodString>;
|
|
41
|
+
repoPath: z.ZodString;
|
|
42
|
+
}, "strip", z.ZodTypeAny, {
|
|
43
|
+
repoPath: string;
|
|
44
|
+
repoOrigin?: string | undefined;
|
|
45
|
+
}, {
|
|
46
|
+
repoPath: string;
|
|
47
|
+
repoOrigin?: string | undefined;
|
|
48
|
+
}>;
|
|
49
|
+
handler: typeof checkActiveIntent;
|
|
50
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { request } from '../services/muninn-ipc.js';
|
|
3
|
+
import { resolveOrigin } from './resolve-origin.js';
|
|
4
|
+
export const checkActiveIntentSchema = z.object({
|
|
5
|
+
repoOrigin: z.string().optional().describe('Git remote origin URL. Auto-detected from repoPath via git if not provided.'),
|
|
6
|
+
repoPath: z.string().describe('Local path to the repository root')
|
|
7
|
+
});
|
|
8
|
+
export async function checkActiveIntent(input) {
|
|
9
|
+
const actualOrigin = resolveOrigin(input.repoOrigin, input.repoPath);
|
|
10
|
+
const res = await request('intent', 'get-active', {
|
|
11
|
+
repoOrigin: actualOrigin,
|
|
12
|
+
});
|
|
13
|
+
// Muninn returns { success, activeIntentId, activeIntent }
|
|
14
|
+
const intent = res.activeIntent;
|
|
15
|
+
if (!intent) {
|
|
16
|
+
return { hasActiveIntent: false };
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
hasActiveIntent: true,
|
|
20
|
+
intent: {
|
|
21
|
+
id: intent.id || res.activeIntentId || '',
|
|
22
|
+
localId: intent.id || res.activeIntentId || '',
|
|
23
|
+
title: intent.title || '',
|
|
24
|
+
description: intent.description || '',
|
|
25
|
+
templateType: (intent.templateType || 'feature'),
|
|
26
|
+
constraints: intent.constraints || [],
|
|
27
|
+
status: intent.status || 'active',
|
|
28
|
+
branch: intent.branch || '',
|
|
29
|
+
forkedFrom: intent.forkedFrom,
|
|
30
|
+
blocks: [] // Blocks are tracked separately by intent-block service
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export const checkActiveIntentTool = {
|
|
35
|
+
name: 'check_active_intent',
|
|
36
|
+
description: `REQUIRED: Call this tool BEFORE writing any code.
|
|
37
|
+
|
|
38
|
+
Returns the currently active intent if one exists. If no active intent is set,
|
|
39
|
+
you should ask the user to confirm intent details and then call create_and_activate_intent.
|
|
40
|
+
|
|
41
|
+
An active intent tracks what the user is working on, enabling:
|
|
42
|
+
- Better code context for AI-generated changes
|
|
43
|
+
- Conflict detection with team members
|
|
44
|
+
- Automatic assignment of code blocks to the intent`,
|
|
45
|
+
inputSchema: checkActiveIntentSchema,
|
|
46
|
+
handler: checkActiveIntent
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=check-active-intent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-active-intent.js","sourceRoot":"","sources":["../../src/tools/check-active-intent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAEnD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6EAA6E,CAAC;IACzH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;CACnE,CAAC,CAAA;AA4BF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAA6B;IACnE,MAAM,YAAY,GAAG,aAAa,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;IAEpE,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,YAAY,EAAE;QAChD,UAAU,EAAE,YAAY;KACzB,CAAC,CAAA;IAEF,2DAA2D;IAC3D,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAA;IAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,CAAA;IACnC,CAAC;IAED,OAAO;QACL,eAAe,EAAE,IAAI;QACrB,MAAM,EAAE;YACN,EAAE,EAAE,MAAM,CAAC,EAAE,IAAI,GAAG,CAAC,cAAc,IAAI,EAAE;YACzC,OAAO,EAAE,MAAM,CAAC,EAAE,IAAI,GAAG,CAAC,cAAc,IAAI,EAAE;YAC9C,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE;YACzB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;YACrC,YAAY,EAAE,CAAC,MAAM,CAAC,YAAY,IAAI,SAAS,CAA2C;YAC1F,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;YACrC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,QAAQ;YACjC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;YAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,MAAM,EAAE,EAAE,CAAC,wDAAwD;SACpE;KACF,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EAAE;;;;;;;;oDAQqC;IAClD,WAAW,EAAE,uBAAuB;IACpC,OAAO,EAAE,iBAAiB;CAC3B,CAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const completeIntentSchema: z.ZodObject<{
|
|
3
|
+
repoOrigin: z.ZodOptional<z.ZodString>;
|
|
4
|
+
repoPath: z.ZodString;
|
|
5
|
+
commitSha: z.ZodOptional<z.ZodString>;
|
|
6
|
+
status: z.ZodDefault<z.ZodEnum<["committed", "pushed", "done", "abandoned"]>>;
|
|
7
|
+
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
repoPath: string;
|
|
9
|
+
status: "committed" | "pushed" | "done" | "abandoned";
|
|
10
|
+
repoOrigin?: string | undefined;
|
|
11
|
+
commitSha?: string | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
repoPath: string;
|
|
14
|
+
repoOrigin?: string | undefined;
|
|
15
|
+
status?: "committed" | "pushed" | "done" | "abandoned" | undefined;
|
|
16
|
+
commitSha?: string | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export type CompleteIntentInput = z.infer<typeof completeIntentSchema>;
|
|
19
|
+
export interface CompleteIntentResponse {
|
|
20
|
+
success: boolean;
|
|
21
|
+
intentId: string;
|
|
22
|
+
previousStatus: string;
|
|
23
|
+
newStatus: string;
|
|
24
|
+
commitSha?: string;
|
|
25
|
+
message: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function completeIntent(input: CompleteIntentInput): Promise<CompleteIntentResponse>;
|
|
28
|
+
export declare const completeIntentTool: {
|
|
29
|
+
name: string;
|
|
30
|
+
description: string;
|
|
31
|
+
inputSchema: z.ZodObject<{
|
|
32
|
+
repoOrigin: z.ZodOptional<z.ZodString>;
|
|
33
|
+
repoPath: z.ZodString;
|
|
34
|
+
commitSha: z.ZodOptional<z.ZodString>;
|
|
35
|
+
status: z.ZodDefault<z.ZodEnum<["committed", "pushed", "done", "abandoned"]>>;
|
|
36
|
+
}, "strip", z.ZodTypeAny, {
|
|
37
|
+
repoPath: string;
|
|
38
|
+
status: "committed" | "pushed" | "done" | "abandoned";
|
|
39
|
+
repoOrigin?: string | undefined;
|
|
40
|
+
commitSha?: string | undefined;
|
|
41
|
+
}, {
|
|
42
|
+
repoPath: string;
|
|
43
|
+
repoOrigin?: string | undefined;
|
|
44
|
+
status?: "committed" | "pushed" | "done" | "abandoned" | undefined;
|
|
45
|
+
commitSha?: string | undefined;
|
|
46
|
+
}>;
|
|
47
|
+
handler: typeof completeIntent;
|
|
48
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { request } from '../services/muninn-ipc.js';
|
|
3
|
+
import { resolveOrigin } from './resolve-origin.js';
|
|
4
|
+
export const completeIntentSchema = z.object({
|
|
5
|
+
repoOrigin: z.string().optional().describe('Git remote origin URL. Auto-detected from repoPath via git if not provided.'),
|
|
6
|
+
repoPath: z.string().describe('Local path to the repository root'),
|
|
7
|
+
commitSha: z.string().optional().describe('The git commit SHA to associate with this intent (if already committed)'),
|
|
8
|
+
status: z.enum(['committed', 'pushed', 'done', 'abandoned']).default('committed')
|
|
9
|
+
.describe('The new status for the intent. Use "committed" after git commit, "done" when work is complete, "abandoned" to discard.')
|
|
10
|
+
});
|
|
11
|
+
export async function completeIntent(input) {
|
|
12
|
+
const actualOrigin = resolveOrigin(input.repoOrigin, input.repoPath);
|
|
13
|
+
const res = await request('intent', 'complete', {
|
|
14
|
+
repoOrigin: actualOrigin,
|
|
15
|
+
status: input.status,
|
|
16
|
+
commitSha: input.commitSha,
|
|
17
|
+
});
|
|
18
|
+
const intentId = res.intentId || '';
|
|
19
|
+
const intentTitle = res.intentTitle || 'Intent';
|
|
20
|
+
const previousStatus = res.previousStatus || 'active';
|
|
21
|
+
const statusMessages = {
|
|
22
|
+
committed: `Intent "${intentTitle}" marked as committed`,
|
|
23
|
+
pushed: `Intent "${intentTitle}" marked as pushed`,
|
|
24
|
+
done: `Intent "${intentTitle}" marked as done`,
|
|
25
|
+
abandoned: `Intent "${intentTitle}" abandoned`
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
success: res.success !== false,
|
|
29
|
+
intentId,
|
|
30
|
+
previousStatus,
|
|
31
|
+
newStatus: input.status,
|
|
32
|
+
commitSha: input.commitSha,
|
|
33
|
+
message: statusMessages[input.status] + (input.commitSha ? ` (commit: ${input.commitSha.substring(0, 7)})` : '')
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export const completeIntentTool = {
|
|
37
|
+
name: 'complete_intent',
|
|
38
|
+
description: `Mark the active intent as completed and clear it.
|
|
39
|
+
|
|
40
|
+
Call this after a successful git commit to:
|
|
41
|
+
1. Update the intent status (committed/pushed/done/abandoned)
|
|
42
|
+
2. Store the commit SHA for tracking
|
|
43
|
+
3. Clear the active intent so a new one can be started
|
|
44
|
+
|
|
45
|
+
Status values:
|
|
46
|
+
- "committed": Code is committed locally (default)
|
|
47
|
+
- "pushed": Code has been pushed to remote
|
|
48
|
+
- "done": Work is fully complete
|
|
49
|
+
- "abandoned": Work was discarded without committing`,
|
|
50
|
+
inputSchema: completeIntentSchema,
|
|
51
|
+
handler: completeIntent
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=complete-intent.js.map
|