@kawacode/mcp 5.0.4 → 5.1.1
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/README.md +52 -62
- package/build/services/muninn-ipc.d.ts +1 -1
- package/build/services/muninn-ipc.js +1 -1
- package/build/tools/evolve-decisions.d.ts +0 -6
- package/build/tools/evolve-decisions.js +1 -3
- package/build/tools/evolve-decisions.js.map +1 -1
- package/build/tools/get-session-decisions.d.ts +1 -0
- package/build/tools/get-session-decisions.js.map +1 -1
- package/build/tools/index.d.ts +3 -6
- package/build/tools/infer-history.d.ts +2 -6
- package/build/tools/infer-history.js +26 -12
- package/build/tools/infer-history.js.map +1 -1
- package/build/tools/record-decision.d.ts +6 -0
- package/build/tools/record-decision.js +2 -0
- package/build/tools/record-decision.js.map +1 -1
- package/build/tools/resolve-origin.js +1 -0
- package/build/tools/resolve-origin.js.map +1 -1
- package/package.json +1 -1
- package/build/services/active-intent-store.d.ts +0 -36
- package/build/services/active-intent-store.js +0 -45
- package/build/services/active-intent-store.js.map +0 -1
- package/build/services/kawa-api.d.ts +0 -131
- package/build/services/kawa-api.js +0 -239
- package/build/services/kawa-api.js.map +0 -1
- package/build/services/repo-encryption.d.ts +0 -46
- package/build/services/repo-encryption.js +0 -92
- package/build/services/repo-encryption.js.map +0 -1
- package/build/services/storage-decryption.d.ts +0 -52
- package/build/services/storage-decryption.js +0 -162
- package/build/services/storage-decryption.js.map +0 -1
- package/build/tools/get-project-context.d.ts +0 -82
- package/build/tools/get-project-context.js +0 -73
- package/build/tools/get-project-context.js.map +0 -1
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* In-memory active intent tracking.
|
|
3
|
-
*
|
|
4
|
-
* Simple Map keyed by normalized origin. Replaces Muninn's per-repo
|
|
5
|
-
* active intent tracking. State lives only for the MCP server lifetime.
|
|
6
|
-
*/
|
|
7
|
-
class ActiveIntentStore {
|
|
8
|
-
store = new Map();
|
|
9
|
-
get(origin) {
|
|
10
|
-
return this.store.get(origin) || null;
|
|
11
|
-
}
|
|
12
|
-
set(origin, intent) {
|
|
13
|
-
this.store.set(origin, intent);
|
|
14
|
-
}
|
|
15
|
-
clear(origin) {
|
|
16
|
-
this.store.delete(origin);
|
|
17
|
-
}
|
|
18
|
-
/** Return all active intents as [origin, intent] pairs */
|
|
19
|
-
getAll() {
|
|
20
|
-
return [...this.store.entries()];
|
|
21
|
-
}
|
|
22
|
-
/** Convert an API Intent to the ActiveIntent shape and store it */
|
|
23
|
-
setFromApiIntent(origin, apiIntent, cloudId) {
|
|
24
|
-
this.store.set(origin, {
|
|
25
|
-
id: cloudId || apiIntent._id || apiIntent.id || '',
|
|
26
|
-
title: apiIntent.title || '',
|
|
27
|
-
description: apiIntent.description || '',
|
|
28
|
-
templateType: apiIntent.templateType || 'feature',
|
|
29
|
-
status: apiIntent.status || 'active',
|
|
30
|
-
constraints: apiIntent.constraints || [],
|
|
31
|
-
blocks: (apiIntent.blocks || []).map(b => ({
|
|
32
|
-
filePath: b.filePath,
|
|
33
|
-
startLine: b.startLine,
|
|
34
|
-
endLine: b.endLine,
|
|
35
|
-
contentSnippet: b.contentSnippet,
|
|
36
|
-
})),
|
|
37
|
-
branch: apiIntent.branch,
|
|
38
|
-
forkedFrom: apiIntent.forkedFrom,
|
|
39
|
-
createdAt: apiIntent.createdAt,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// Singleton
|
|
44
|
-
export const activeIntentStore = new ActiveIntentStore();
|
|
45
|
-
//# sourceMappingURL=active-intent-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"active-intent-store.js","sourceRoot":"","sources":["../../src/services/active-intent-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsBH,MAAM,iBAAiB;IACb,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAA;IAE/C,GAAG,CAAC,MAAc;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAA;IACvC,CAAC;IAED,GAAG,CAAC,MAAc,EAAE,MAAoB;QACtC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,CAAC;IAED,KAAK,CAAC,MAAc;QAClB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC3B,CAAC;IAED,0DAA0D;IAC1D,MAAM;QACJ,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;IAClC,CAAC;IAED,mEAAmE;IACnE,gBAAgB,CAAC,MAAc,EAAE,SAAiB,EAAE,OAAe;QACjE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE;YACrB,EAAE,EAAE,OAAO,IAAI,SAAS,CAAC,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE;YAClD,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,EAAE;YAC5B,WAAW,EAAE,SAAS,CAAC,WAAW,IAAI,EAAE;YACxC,YAAY,EAAE,SAAS,CAAC,YAAY,IAAI,SAAS;YACjD,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,QAAQ;YACpC,WAAW,EAAE,SAAS,CAAC,WAAW,IAAI,EAAE;YACxC,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACzC,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,cAAc,EAAE,CAAC,CAAC,cAAc;aACjC,CAAC,CAAC;YACH,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,UAAU,EAAE,SAAS,CAAC,UAAU;YAChC,SAAS,EAAE,SAAS,CAAC,SAAS;SAC/B,CAAC,CAAA;IACJ,CAAC;CACF;AAED,YAAY;AACZ,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,EAAE,CAAA"}
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTTP client for the Kawa API.
|
|
3
|
-
*
|
|
4
|
-
* Replaces Muninn IPC — all data operations go directly to the REST API.
|
|
5
|
-
* Uses Node 18+ built-in fetch (no new dependencies).
|
|
6
|
-
*
|
|
7
|
-
* Config:
|
|
8
|
-
* KAWA_API_URL — defaults to https://api.codeawareness.com (set to http://localhost:3008 for local dev)
|
|
9
|
-
* KAWA_AUTH_TOKEN — JWT bearer token (optional - auto-loaded from storage if not set)
|
|
10
|
-
*
|
|
11
|
-
* Auth token resolution order:
|
|
12
|
-
* 1. KAWA_AUTH_TOKEN environment variable
|
|
13
|
-
* 2. ~/.kawa-code/.storage.caw (decrypted using username+hostname)
|
|
14
|
-
*/
|
|
15
|
-
export interface Intent {
|
|
16
|
-
_id?: string;
|
|
17
|
-
id?: string;
|
|
18
|
-
title: string;
|
|
19
|
-
description: string;
|
|
20
|
-
templateType: string;
|
|
21
|
-
status?: string;
|
|
22
|
-
scope?: {
|
|
23
|
-
type: string;
|
|
24
|
-
paths: string[];
|
|
25
|
-
};
|
|
26
|
-
blocks?: IntentBlock[];
|
|
27
|
-
constraints?: string[];
|
|
28
|
-
branch?: string;
|
|
29
|
-
forkedFrom?: string;
|
|
30
|
-
encrypted?: boolean;
|
|
31
|
-
authorId?: string;
|
|
32
|
-
authorName?: string;
|
|
33
|
-
createdAt?: string;
|
|
34
|
-
updatedAt?: string;
|
|
35
|
-
}
|
|
36
|
-
export interface IntentBlock {
|
|
37
|
-
filePath: string;
|
|
38
|
-
startLine: number;
|
|
39
|
-
endLine: number;
|
|
40
|
-
contentHash?: string;
|
|
41
|
-
contentSnippet?: string;
|
|
42
|
-
codeContent?: string;
|
|
43
|
-
}
|
|
44
|
-
export interface IntentTranslation {
|
|
45
|
-
intentId: string;
|
|
46
|
-
lang: string;
|
|
47
|
-
title: string;
|
|
48
|
-
description: string;
|
|
49
|
-
}
|
|
50
|
-
export interface Decision {
|
|
51
|
-
decisionId: string;
|
|
52
|
-
intentId?: string;
|
|
53
|
-
authorId?: string;
|
|
54
|
-
timestamp?: string;
|
|
55
|
-
decisionType: string;
|
|
56
|
-
summary: string;
|
|
57
|
-
context?: string;
|
|
58
|
-
alternatives?: string[];
|
|
59
|
-
rationale: string;
|
|
60
|
-
consequences?: string;
|
|
61
|
-
relatedFiles?: string[];
|
|
62
|
-
supersedes?: string[];
|
|
63
|
-
constraintsChecked?: string[];
|
|
64
|
-
constraintViolations?: Array<{
|
|
65
|
-
alternative: string;
|
|
66
|
-
constraint: string;
|
|
67
|
-
reason: string;
|
|
68
|
-
}>;
|
|
69
|
-
createdAt?: string;
|
|
70
|
-
updatedAt?: string;
|
|
71
|
-
}
|
|
72
|
-
export interface CreateIntentParams {
|
|
73
|
-
origin: string;
|
|
74
|
-
lang?: string;
|
|
75
|
-
title: string;
|
|
76
|
-
description: string;
|
|
77
|
-
templateType?: string;
|
|
78
|
-
constraints?: string[];
|
|
79
|
-
scope?: {
|
|
80
|
-
type: string;
|
|
81
|
-
paths: string[];
|
|
82
|
-
};
|
|
83
|
-
blocks?: IntentBlock[];
|
|
84
|
-
branch?: string;
|
|
85
|
-
forkedFrom?: string;
|
|
86
|
-
}
|
|
87
|
-
export declare class KawaApi {
|
|
88
|
-
private baseUrl;
|
|
89
|
-
private authToken;
|
|
90
|
-
constructor(baseUrl?: string, authToken?: string);
|
|
91
|
-
/**
|
|
92
|
-
* Refresh the auth token from storage
|
|
93
|
-
*
|
|
94
|
-
* Call this periodically to pick up token refreshes from Muninn.
|
|
95
|
-
* Returns true if a new token was loaded.
|
|
96
|
-
*/
|
|
97
|
-
refreshTokenFromStorage(): boolean;
|
|
98
|
-
/**
|
|
99
|
-
* Check if the client has an auth token
|
|
100
|
-
*/
|
|
101
|
-
hasAuthToken(): boolean;
|
|
102
|
-
listIntents(origin: string, lang?: string, since?: string): Promise<Intent[]>;
|
|
103
|
-
createIntent(params: CreateIntentParams): Promise<{
|
|
104
|
-
intent: Intent;
|
|
105
|
-
cloudId: string;
|
|
106
|
-
}>;
|
|
107
|
-
getIntent(intentId: string, origin: string, lang?: string): Promise<Intent>;
|
|
108
|
-
updateIntent(intentId: string, origin: string, updates: Partial<Intent>): Promise<Intent>;
|
|
109
|
-
deleteIntent(intentId: string, origin: string): Promise<void>;
|
|
110
|
-
getIntentsByFile(origin: string, filePath: string): Promise<Intent[]>;
|
|
111
|
-
getIntentsByLines(origin: string, filePath: string, startLine: number, endLine: number): Promise<Intent[]>;
|
|
112
|
-
batchSaveIntents(origin: string, lang: string, intents: CreateIntentParams[]): Promise<any>;
|
|
113
|
-
saveIntentTranslation(intentId: string, origin: string, lang: string, title: string, description: string): Promise<any>;
|
|
114
|
-
getIntentTranslation(intentId: string, origin: string, lang: string): Promise<IntentTranslation | null>;
|
|
115
|
-
getTeamDecisions(origin: string, since?: string): Promise<Decision[]>;
|
|
116
|
-
getIntentDecisions(intentId: string, origin: string): Promise<Decision[]>;
|
|
117
|
-
syncDecisions(origin: string, intentId: string, decisions: Decision[]): Promise<any>;
|
|
118
|
-
deleteDecision(decisionId: string, origin: string): Promise<void>;
|
|
119
|
-
searchRelevantContext(origin: string, query: string, activeFiles?: string[], options?: {
|
|
120
|
-
maxIntents?: number;
|
|
121
|
-
maxDecisions?: number;
|
|
122
|
-
minScore?: number;
|
|
123
|
-
}): Promise<any>;
|
|
124
|
-
private get;
|
|
125
|
-
private post;
|
|
126
|
-
private patch;
|
|
127
|
-
private del;
|
|
128
|
-
getBaseUrl(): string;
|
|
129
|
-
private request;
|
|
130
|
-
}
|
|
131
|
-
export declare function getApi(): KawaApi;
|
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTTP client for the Kawa API.
|
|
3
|
-
*
|
|
4
|
-
* Replaces Muninn IPC — all data operations go directly to the REST API.
|
|
5
|
-
* Uses Node 18+ built-in fetch (no new dependencies).
|
|
6
|
-
*
|
|
7
|
-
* Config:
|
|
8
|
-
* KAWA_API_URL — defaults to https://api.codeawareness.com (set to http://localhost:3008 for local dev)
|
|
9
|
-
* KAWA_AUTH_TOKEN — JWT bearer token (optional - auto-loaded from storage if not set)
|
|
10
|
-
*
|
|
11
|
-
* Auth token resolution order:
|
|
12
|
-
* 1. KAWA_AUTH_TOKEN environment variable
|
|
13
|
-
* 2. ~/.kawa-code/.storage.caw (decrypted using username+hostname)
|
|
14
|
-
*/
|
|
15
|
-
import { getAuthTokenFromStorage } from './storage-decryption.js';
|
|
16
|
-
// ============================================================================
|
|
17
|
-
// API Client
|
|
18
|
-
// ============================================================================
|
|
19
|
-
export class KawaApi {
|
|
20
|
-
baseUrl;
|
|
21
|
-
authToken;
|
|
22
|
-
constructor(baseUrl, authToken) {
|
|
23
|
-
this.baseUrl = (baseUrl || process.env.KAWA_API_URL || 'https://api.codeawareness.com').replace(/\/$/, '');
|
|
24
|
-
// Auth token resolution order:
|
|
25
|
-
// 1. Explicit parameter
|
|
26
|
-
// 2. Environment variable
|
|
27
|
-
// 3. Storage file (auto-decrypted)
|
|
28
|
-
this.authToken = authToken || process.env.KAWA_AUTH_TOKEN || '';
|
|
29
|
-
if (!this.authToken) {
|
|
30
|
-
// Try to load from Muninn storage
|
|
31
|
-
const tokenFromStorage = getAuthTokenFromStorage();
|
|
32
|
-
if (tokenFromStorage) {
|
|
33
|
-
this.authToken = tokenFromStorage;
|
|
34
|
-
console.error('Loaded auth token from Muninn storage (~/.kawa-code/.storage.caw)');
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
console.error('Warning: No auth token available. Tried:');
|
|
38
|
-
console.error(' 1. KAWA_AUTH_TOKEN environment variable (not set)');
|
|
39
|
-
console.error(' 2. ~/.kawa-code/.storage.caw (not found or not decryptable)');
|
|
40
|
-
console.error(' → API calls will fail until you log in to Muninn');
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
// --------------------------------------------------------------------------
|
|
45
|
-
// Auth Token Management
|
|
46
|
-
// --------------------------------------------------------------------------
|
|
47
|
-
/**
|
|
48
|
-
* Refresh the auth token from storage
|
|
49
|
-
*
|
|
50
|
-
* Call this periodically to pick up token refreshes from Muninn.
|
|
51
|
-
* Returns true if a new token was loaded.
|
|
52
|
-
*/
|
|
53
|
-
refreshTokenFromStorage() {
|
|
54
|
-
const tokenFromStorage = getAuthTokenFromStorage();
|
|
55
|
-
if (tokenFromStorage && tokenFromStorage !== this.authToken) {
|
|
56
|
-
this.authToken = tokenFromStorage;
|
|
57
|
-
console.error('Refreshed auth token from Muninn storage');
|
|
58
|
-
return true;
|
|
59
|
-
}
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Check if the client has an auth token
|
|
64
|
-
*/
|
|
65
|
-
hasAuthToken() {
|
|
66
|
-
return this.authToken.length > 0;
|
|
67
|
-
}
|
|
68
|
-
// --------------------------------------------------------------------------
|
|
69
|
-
// Intents
|
|
70
|
-
// --------------------------------------------------------------------------
|
|
71
|
-
async listIntents(origin, lang = 'en', since) {
|
|
72
|
-
const params = { origin, lang };
|
|
73
|
-
if (since)
|
|
74
|
-
params.since = since;
|
|
75
|
-
const data = await this.get('/v1/intents', params);
|
|
76
|
-
return data.intents || [];
|
|
77
|
-
}
|
|
78
|
-
async createIntent(params) {
|
|
79
|
-
const body = {
|
|
80
|
-
origin: params.origin,
|
|
81
|
-
lang: params.lang || 'en',
|
|
82
|
-
title: params.title,
|
|
83
|
-
description: params.description,
|
|
84
|
-
templateType: params.templateType || 'feature',
|
|
85
|
-
constraints: params.constraints || [],
|
|
86
|
-
scope: params.scope || { type: 'repo', paths: [] },
|
|
87
|
-
blocks: params.blocks || [],
|
|
88
|
-
branch: params.branch,
|
|
89
|
-
forkedFrom: params.forkedFrom,
|
|
90
|
-
};
|
|
91
|
-
const data = await this.post('/v1/intents', body);
|
|
92
|
-
return {
|
|
93
|
-
intent: data.intent || data,
|
|
94
|
-
cloudId: data.intent?._id || data._id || ''
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
async getIntent(intentId, origin, lang = 'en') {
|
|
98
|
-
const data = await this.get(`/v1/intents/${intentId}`, { origin, lang });
|
|
99
|
-
return data.intent || data;
|
|
100
|
-
}
|
|
101
|
-
async updateIntent(intentId, origin, updates) {
|
|
102
|
-
const body = { origin, ...updates };
|
|
103
|
-
const data = await this.patch(`/v1/intents/${intentId}`, body);
|
|
104
|
-
return data.intent || data;
|
|
105
|
-
}
|
|
106
|
-
async deleteIntent(intentId, origin) {
|
|
107
|
-
await this.del(`/v1/intents/${intentId}`, { origin });
|
|
108
|
-
}
|
|
109
|
-
async getIntentsByFile(origin, filePath) {
|
|
110
|
-
const data = await this.get('/v1/intents/by-file', { origin, path: filePath });
|
|
111
|
-
return data.intents || [];
|
|
112
|
-
}
|
|
113
|
-
async getIntentsByLines(origin, filePath, startLine, endLine) {
|
|
114
|
-
const data = await this.get('/v1/intents/by-lines', {
|
|
115
|
-
origin,
|
|
116
|
-
path: filePath,
|
|
117
|
-
startLine: String(startLine),
|
|
118
|
-
endLine: String(endLine)
|
|
119
|
-
});
|
|
120
|
-
return data.intents || [];
|
|
121
|
-
}
|
|
122
|
-
async batchSaveIntents(origin, lang, intents) {
|
|
123
|
-
return this.post('/v1/intents/batch', { origin, lang, intents });
|
|
124
|
-
}
|
|
125
|
-
// Translations
|
|
126
|
-
async saveIntentTranslation(intentId, origin, lang, title, description) {
|
|
127
|
-
return this.post(`/v1/intents/${intentId}/translations`, {
|
|
128
|
-
origin, lang, title, description
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
async getIntentTranslation(intentId, origin, lang) {
|
|
132
|
-
try {
|
|
133
|
-
return await this.get(`/v1/intents/${intentId}/translations/${lang}`, { origin });
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
// --------------------------------------------------------------------------
|
|
140
|
-
// Decisions
|
|
141
|
-
// --------------------------------------------------------------------------
|
|
142
|
-
async getTeamDecisions(origin, since) {
|
|
143
|
-
const params = { origin };
|
|
144
|
-
if (since)
|
|
145
|
-
params.since = since;
|
|
146
|
-
const data = await this.get('/v1/decisions/team', params);
|
|
147
|
-
return data.decisions || [];
|
|
148
|
-
}
|
|
149
|
-
async getIntentDecisions(intentId, origin) {
|
|
150
|
-
const data = await this.get(`/v1/decisions/intent/${intentId}`, { origin });
|
|
151
|
-
return data.decisions || [];
|
|
152
|
-
}
|
|
153
|
-
async syncDecisions(origin, intentId, decisions) {
|
|
154
|
-
return this.post('/v1/decisions/sync', { origin, intentId, decisions });
|
|
155
|
-
}
|
|
156
|
-
async deleteDecision(decisionId, origin) {
|
|
157
|
-
await this.del(`/v1/decisions/${decisionId}`, { origin });
|
|
158
|
-
}
|
|
159
|
-
// --------------------------------------------------------------------------
|
|
160
|
-
// Search
|
|
161
|
-
// --------------------------------------------------------------------------
|
|
162
|
-
async searchRelevantContext(origin, query, activeFiles, options) {
|
|
163
|
-
return this.post('/v1/search', { origin, query, activeFiles, ...options });
|
|
164
|
-
}
|
|
165
|
-
// --------------------------------------------------------------------------
|
|
166
|
-
// HTTP helpers
|
|
167
|
-
// --------------------------------------------------------------------------
|
|
168
|
-
async get(path, params) {
|
|
169
|
-
const url = new URL(this.baseUrl + path);
|
|
170
|
-
if (params) {
|
|
171
|
-
for (const [k, v] of Object.entries(params)) {
|
|
172
|
-
if (v !== undefined)
|
|
173
|
-
url.searchParams.set(k, v);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
return this.request(url.toString(), { method: 'GET' });
|
|
177
|
-
}
|
|
178
|
-
async post(path, body) {
|
|
179
|
-
return this.request(this.baseUrl + path, {
|
|
180
|
-
method: 'POST',
|
|
181
|
-
headers: { 'Content-Type': 'application/json' },
|
|
182
|
-
body: JSON.stringify(body)
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
async patch(path, body) {
|
|
186
|
-
return this.request(this.baseUrl + path, {
|
|
187
|
-
method: 'PATCH',
|
|
188
|
-
headers: { 'Content-Type': 'application/json' },
|
|
189
|
-
body: JSON.stringify(body)
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
async del(path, params) {
|
|
193
|
-
const url = new URL(this.baseUrl + path);
|
|
194
|
-
if (params) {
|
|
195
|
-
for (const [k, v] of Object.entries(params)) {
|
|
196
|
-
if (v !== undefined)
|
|
197
|
-
url.searchParams.set(k, v);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
return this.request(url.toString(), { method: 'DELETE' });
|
|
201
|
-
}
|
|
202
|
-
getBaseUrl() {
|
|
203
|
-
return this.baseUrl;
|
|
204
|
-
}
|
|
205
|
-
async request(url, init) {
|
|
206
|
-
const headers = {
|
|
207
|
-
...(init.headers || {}),
|
|
208
|
-
'Authorization': `Bearer ${this.authToken}`
|
|
209
|
-
};
|
|
210
|
-
let response;
|
|
211
|
-
try {
|
|
212
|
-
response = await fetch(url, { ...init, headers });
|
|
213
|
-
}
|
|
214
|
-
catch (err) {
|
|
215
|
-
const cause = err instanceof Error ? err.message : String(err);
|
|
216
|
-
throw new Error(`Cannot reach Kawa API at ${this.baseUrl} — ${init.method} ${url}: ${cause}`);
|
|
217
|
-
}
|
|
218
|
-
if (!response.ok) {
|
|
219
|
-
const text = await response.text().catch(() => '');
|
|
220
|
-
throw new Error(`API ${init.method} ${url} failed (${response.status}): ${text}`);
|
|
221
|
-
}
|
|
222
|
-
const contentType = response.headers.get('content-type') || '';
|
|
223
|
-
if (contentType.includes('application/json')) {
|
|
224
|
-
return response.json();
|
|
225
|
-
}
|
|
226
|
-
return {};
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
// ============================================================================
|
|
230
|
-
// Singleton
|
|
231
|
-
// ============================================================================
|
|
232
|
-
let instance = null;
|
|
233
|
-
export function getApi() {
|
|
234
|
-
if (!instance) {
|
|
235
|
-
instance = new KawaApi();
|
|
236
|
-
}
|
|
237
|
-
return instance;
|
|
238
|
-
}
|
|
239
|
-
//# sourceMappingURL=kawa-api.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"kawa-api.js","sourceRoot":"","sources":["../../src/services/kawa-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,46 +0,0 @@
|
|
|
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
|
-
/**
|
|
12
|
-
* Derive a 32-byte AES key from the repo's initial commit SHA and origin.
|
|
13
|
-
*
|
|
14
|
-
* Matches Muninn's derive_repository_key():
|
|
15
|
-
* - key material = "{initialCommit}-{origin}"
|
|
16
|
-
* - salt = "kawa-code-zero-knowledge-v1"
|
|
17
|
-
* - 600,000 PBKDF2-HMAC-SHA256 iterations
|
|
18
|
-
*/
|
|
19
|
-
export declare function deriveRepoKey(initialCommit: string, origin: string): Buffer;
|
|
20
|
-
/**
|
|
21
|
-
* Get the initial (root) commit SHA for a repository.
|
|
22
|
-
*/
|
|
23
|
-
export declare function getInitialCommitSHA(repoPath: string): string;
|
|
24
|
-
/**
|
|
25
|
-
* Encrypt content using AES-256-GCM.
|
|
26
|
-
*
|
|
27
|
-
* Returns a JSON string matching Muninn's EncryptedContent format:
|
|
28
|
-
* { "encryptedContent": hex, "iv": hex, "authTag": hex }
|
|
29
|
-
*
|
|
30
|
-
* The encryptedContent hex includes the 16-byte auth tag appended
|
|
31
|
-
* (AES-GCM ciphertext + tag), matching Gardener's Rust implementation.
|
|
32
|
-
*/
|
|
33
|
-
export declare function encryptContent(plaintext: string, key: Buffer): string;
|
|
34
|
-
/**
|
|
35
|
-
* Extract content from a file at the given line range and compute hash + snippet.
|
|
36
|
-
*
|
|
37
|
-
* Matches Gardener's IntentBlockService::extract_content_and_hash():
|
|
38
|
-
* - Lines are 1-based
|
|
39
|
-
* - snippet = first 150 characters
|
|
40
|
-
* - contentHash = SHA-256 of the whitespace-normalized plaintext (hex)
|
|
41
|
-
*/
|
|
42
|
-
export declare function extractContentAndHash(fileContent: string, startLine: number, endLine: number): {
|
|
43
|
-
content: string;
|
|
44
|
-
contentHash: string;
|
|
45
|
-
contentSnippet: string;
|
|
46
|
-
};
|
|
@@ -1,92 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"repo-encryption.js","sourceRoot":"","sources":["../../src/services/repo-encryption.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,52 +0,0 @@
|
|
|
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;
|