@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.
Files changed (88) hide show
  1. package/CLAUDE.md.example +80 -0
  2. package/LICENSE +35 -0
  3. package/README.md +322 -0
  4. package/build/index.d.ts +2 -0
  5. package/build/index.js +231 -0
  6. package/build/index.js.map +1 -0
  7. package/build/prompts/intent-first-workflow.d.ts +24 -0
  8. package/build/prompts/intent-first-workflow.js +204 -0
  9. package/build/prompts/intent-first-workflow.js.map +1 -0
  10. package/build/resources/active-intent.d.ts +9 -0
  11. package/build/resources/active-intent.js +52 -0
  12. package/build/resources/active-intent.js.map +1 -0
  13. package/build/services/active-intent-store.d.ts +36 -0
  14. package/build/services/active-intent-store.js +45 -0
  15. package/build/services/active-intent-store.js.map +1 -0
  16. package/build/services/kawa-api.d.ts +131 -0
  17. package/build/services/kawa-api.js +239 -0
  18. package/build/services/kawa-api.js.map +1 -0
  19. package/build/services/muninn-ipc.d.ts +45 -0
  20. package/build/services/muninn-ipc.js +275 -0
  21. package/build/services/muninn-ipc.js.map +1 -0
  22. package/build/services/repo-encryption.d.ts +46 -0
  23. package/build/services/repo-encryption.js +92 -0
  24. package/build/services/repo-encryption.js.map +1 -0
  25. package/build/services/storage-decryption.d.ts +52 -0
  26. package/build/services/storage-decryption.js +162 -0
  27. package/build/services/storage-decryption.js.map +1 -0
  28. package/build/tools/assign-blocks.d.ts +87 -0
  29. package/build/tools/assign-blocks.js +49 -0
  30. package/build/tools/assign-blocks.js.map +1 -0
  31. package/build/tools/check-active-intent.d.ts +50 -0
  32. package/build/tools/check-active-intent.js +48 -0
  33. package/build/tools/check-active-intent.js.map +1 -0
  34. package/build/tools/complete-intent.d.ts +48 -0
  35. package/build/tools/complete-intent.js +53 -0
  36. package/build/tools/complete-intent.js.map +1 -0
  37. package/build/tools/create-intent.d.ts +58 -0
  38. package/build/tools/create-intent.js +49 -0
  39. package/build/tools/create-intent.js.map +1 -0
  40. package/build/tools/detect-intent-conflicts.d.ts +361 -0
  41. package/build/tools/detect-intent-conflicts.js +91 -0
  42. package/build/tools/detect-intent-conflicts.js.map +1 -0
  43. package/build/tools/edit-session-decision.d.ts +201 -0
  44. package/build/tools/edit-session-decision.js +50 -0
  45. package/build/tools/edit-session-decision.js.map +1 -0
  46. package/build/tools/evolve-decisions.d.ts +50 -0
  47. package/build/tools/evolve-decisions.js +45 -0
  48. package/build/tools/evolve-decisions.js.map +1 -0
  49. package/build/tools/get-intent-changes.d.ts +49 -0
  50. package/build/tools/get-intent-changes.js +58 -0
  51. package/build/tools/get-intent-changes.js.map +1 -0
  52. package/build/tools/get-intents-for-file.d.ts +57 -0
  53. package/build/tools/get-intents-for-file.js +57 -0
  54. package/build/tools/get-intents-for-file.js.map +1 -0
  55. package/build/tools/get-intents-for-lines.d.ts +71 -0
  56. package/build/tools/get-intents-for-lines.js +64 -0
  57. package/build/tools/get-intents-for-lines.js.map +1 -0
  58. package/build/tools/get-project-context.d.ts +82 -0
  59. package/build/tools/get-project-context.js +73 -0
  60. package/build/tools/get-project-context.js.map +1 -0
  61. package/build/tools/get-project-decisions.d.ts +51 -0
  62. package/build/tools/get-project-decisions.js +56 -0
  63. package/build/tools/get-project-decisions.js.map +1 -0
  64. package/build/tools/get-relevant-context.d.ts +89 -0
  65. package/build/tools/get-relevant-context.js +104 -0
  66. package/build/tools/get-relevant-context.js.map +1 -0
  67. package/build/tools/get-session-decisions.d.ts +57 -0
  68. package/build/tools/get-session-decisions.js +48 -0
  69. package/build/tools/get-session-decisions.js.map +1 -0
  70. package/build/tools/index.d.ts +656 -0
  71. package/build/tools/index.js +57 -0
  72. package/build/tools/index.js.map +1 -0
  73. package/build/tools/infer-history.d.ts +85 -0
  74. package/build/tools/infer-history.js +69 -0
  75. package/build/tools/infer-history.js.map +1 -0
  76. package/build/tools/list-team-intents.d.ts +51 -0
  77. package/build/tools/list-team-intents.js +57 -0
  78. package/build/tools/list-team-intents.js.map +1 -0
  79. package/build/tools/log-work.d.ts +45 -0
  80. package/build/tools/log-work.js +30 -0
  81. package/build/tools/log-work.js.map +1 -0
  82. package/build/tools/record-decision.d.ts +132 -0
  83. package/build/tools/record-decision.js +66 -0
  84. package/build/tools/record-decision.js.map +1 -0
  85. package/build/tools/resolve-origin.d.ts +13 -0
  86. package/build/tools/resolve-origin.js +33 -0
  87. package/build/tools/resolve-origin.js.map +1 -0
  88. package/package.json +36 -0
@@ -0,0 +1,239 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kawa-api.js","sourceRoot":"","sources":["../../src/services/kawa-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AA6EjE,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E,MAAM,OAAO,OAAO;IACV,OAAO,CAAQ;IACf,SAAS,CAAQ;IAEzB,YAAY,OAAgB,EAAE,SAAkB;QAC9C,IAAI,CAAC,OAAO,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,+BAA+B,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QAE1G,+BAA+B;QAC/B,wBAAwB;QACxB,0BAA0B;QAC1B,mCAAmC;QACnC,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAA;QAE/D,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,kCAAkC;YAClC,MAAM,gBAAgB,GAAG,uBAAuB,EAAE,CAAA;YAClD,IAAI,gBAAgB,EAAE,CAAC;gBACrB,IAAI,CAAC,SAAS,GAAG,gBAAgB,CAAA;gBACjC,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAA;YACpF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAA;gBACzD,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAA;gBACpE,OAAO,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAA;gBAC9E,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAA;YACrE,CAAC;QACH,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,wBAAwB;IACxB,6EAA6E;IAE7E;;;;;OAKG;IACH,uBAAuB;QACrB,MAAM,gBAAgB,GAAG,uBAAuB,EAAE,CAAA;QAClD,IAAI,gBAAgB,IAAI,gBAAgB,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;YAC5D,IAAI,CAAC,SAAS,GAAG,gBAAgB,CAAA;YACjC,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAA;YACzD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAA;IAClC,CAAC;IAED,6EAA6E;IAC7E,UAAU;IACV,6EAA6E;IAE7E,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,IAAI,GAAG,IAAI,EAAE,KAAc;QAC3D,MAAM,MAAM,GAA2B,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;QACvD,IAAI,KAAK;YAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAA;QAC/B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;QAClD,OAAO,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA;IAC3B,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAA0B;QAC3C,MAAM,IAAI,GAAG;YACX,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI;YACzB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,SAAS;YAC9C,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;YACrC,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;YAClD,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;YAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAA;QACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAA;QACjD,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;YAC3B,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,IAAI,EAAE;SAC5C,CAAA;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,QAAgB,EAAE,MAAc,EAAE,IAAI,GAAG,IAAI;QAC3D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,eAAe,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;QACxE,OAAO,IAAI,CAAC,MAAM,IAAI,IAAI,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,QAAgB,EAAE,MAAc,EAAE,OAAwB;QAC3E,MAAM,IAAI,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAAA;QACnC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,eAAe,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAA;QAC9D,OAAO,IAAI,CAAC,MAAM,IAAI,IAAI,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,QAAgB,EAAE,MAAc;QACjD,MAAM,IAAI,CAAC,GAAG,CAAC,eAAe,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;IACvD,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,MAAc,EAAE,QAAgB;QACrD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC9E,OAAO,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA;IAC3B,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,MAAc,EAAE,QAAgB,EAAE,SAAiB,EAAE,OAAe;QAC1F,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,sBAAsB,EAAE;YAClD,MAAM;YACN,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC;YAC5B,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC;SACzB,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA;IAC3B,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,MAAc,EAAE,IAAY,EAAE,OAA6B;QAChF,OAAO,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;IAClE,CAAC;IAED,eAAe;IACf,KAAK,CAAC,qBAAqB,CAAC,QAAgB,EAAE,MAAc,EAAE,IAAY,EAAE,KAAa,EAAE,WAAmB;QAC5G,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,QAAQ,eAAe,EAAE;YACvD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW;SACjC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,QAAgB,EAAE,MAAc,EAAE,IAAY;QACvE,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,eAAe,QAAQ,iBAAiB,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;QACnF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,YAAY;IACZ,6EAA6E;IAE7E,KAAK,CAAC,gBAAgB,CAAC,MAAc,EAAE,KAAc;QACnD,MAAM,MAAM,GAA2B,EAAE,MAAM,EAAE,CAAA;QACjD,IAAI,KAAK;YAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAA;QAC/B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAA;QACzD,OAAO,IAAI,CAAC,SAAS,IAAI,EAAE,CAAA;IAC7B,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,QAAgB,EAAE,MAAc;QACvD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,wBAAwB,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;QAC3E,OAAO,IAAI,CAAC,SAAS,IAAI,EAAE,CAAA;IAC7B,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,MAAc,EAAE,QAAgB,EAAE,SAAqB;QACzE,OAAO,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAA;IACzE,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,UAAkB,EAAE,MAAc;QACrD,MAAM,IAAI,CAAC,GAAG,CAAC,iBAAiB,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;IAC3D,CAAC;IAED,6EAA6E;IAC7E,SAAS;IACT,6EAA6E;IAE7E,KAAK,CAAC,qBAAqB,CAAC,MAAc,EAAE,KAAa,EAAE,WAAsB,EAAE,OAElF;QACC,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,CAAC,CAAA;IAC5E,CAAC;IAED,6EAA6E;IAC7E,eAAe;IACf,6EAA6E;IAErE,KAAK,CAAC,GAAG,CAAC,IAAY,EAAE,MAA+B;QAC7D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;QACxC,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,KAAK,SAAS;oBAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACjD,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;IACxD,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,IAAS;QACxC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE;YACvC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAA;IACJ,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,IAAY,EAAE,IAAS;QACzC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE;YACvC,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAA;IACJ,CAAC;IAEO,KAAK,CAAC,GAAG,CAAC,IAAY,EAAE,MAA+B;QAC7D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;QACxC,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,KAAK,SAAS;oBAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACjD,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAA;IAC3D,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,IAAiB;QAClD,MAAM,OAAO,GAA2B;YACtC,GAAG,CAAC,IAAI,CAAC,OAAiC,IAAI,EAAE,CAAC;YACjD,eAAe,EAAE,UAAU,IAAI,CAAC,SAAS,EAAE;SAC5C,CAAA;QAED,IAAI,QAAkB,CAAA;QACtB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;QACnD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC9D,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,CAAC,OAAO,MAAM,IAAI,CAAC,MAAM,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC,CAAA;QAC/F,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;YAClD,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,MAAM,IAAI,GAAG,YAAY,QAAQ,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAA;QACnF,CAAC;QAED,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAA;QAC9D,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC7C,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAA;QACxB,CAAC;QACD,OAAO,EAAE,CAAA;IACX,CAAC;CACF;AAED,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,IAAI,QAAQ,GAAmB,IAAI,CAAA;AAEnC,MAAM,UAAU,MAAM;IACpB,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,IAAI,OAAO,EAAE,CAAA;IAC1B,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Muninn IPC Client for MCP Server
3
+ *
4
+ * Connects to Muninn's Huginn IPC socket as an extension client,
5
+ * translating MCP tool calls into domain:action IPC messages.
6
+ *
7
+ * Modeled after kawa.i18n/src/ipc/muninn-socket.ts but simplified:
8
+ * - No UI bundle or manifest (MCP has no UI)
9
+ * - Request/response correlation via _msgId
10
+ * - 30s timeout per request
11
+ */
12
+ /**
13
+ * Connect to Muninn's Huginn IPC socket.
14
+ *
15
+ * Sends extension handshake and waits for acknowledgment.
16
+ * Throws if Muninn is not running or handshake fails.
17
+ */
18
+ export declare function connectToMuninn(socketPath?: string): Promise<void>;
19
+ /**
20
+ * Send an IPC request to Muninn and await the correlated response.
21
+ *
22
+ * @param domain - Handler domain (e.g., 'intent', 'decision')
23
+ * @param action - Handler action (e.g., 'create', 'get-active')
24
+ * @param data - Request payload
25
+ * @returns The response data from Muninn
26
+ */
27
+ export declare function request(domain: string, action: string, data?: any): Promise<any>;
28
+ /**
29
+ * Ensure a repository path is registered with Muninn as a project.
30
+ *
31
+ * Sends `code:add` with the folder path so Muninn activates the project,
32
+ * sets up git state, and pulls intents/decisions/lessons from the API.
33
+ * Always sends the request — Muninn's AddHandler is idempotent and
34
+ * returns the existing project if already added.
35
+ * Errors are logged but not thrown — repo registration is best-effort.
36
+ */
37
+ export declare function ensureRepo(repoPath: string): Promise<void>;
38
+ /**
39
+ * Check if connected to Muninn.
40
+ */
41
+ export declare function isConnected(): boolean;
42
+ /**
43
+ * Disconnect from Muninn.
44
+ */
45
+ export declare function disconnect(): void;
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Muninn IPC Client for MCP Server
3
+ *
4
+ * Connects to Muninn's Huginn IPC socket as an extension client,
5
+ * translating MCP tool calls into domain:action IPC messages.
6
+ *
7
+ * Modeled after kawa.i18n/src/ipc/muninn-socket.ts but simplified:
8
+ * - No UI bundle or manifest (MCP has no UI)
9
+ * - Request/response correlation via _msgId
10
+ * - 30s timeout per request
11
+ */
12
+ import * as net from 'net';
13
+ import * as fs from 'fs';
14
+ import * as path from 'path';
15
+ import * as os from 'os';
16
+ import * as crypto from 'crypto';
17
+ const EXTENSION_ID = 'mcp';
18
+ const EXTENSION_DOMAINS = ['intent', 'intent-block', 'decision', 'claude-code', 'code', 'inference'];
19
+ const REQUEST_TIMEOUT_MS = 30_000;
20
+ const HANDSHAKE_TIMEOUT_MS = 10_000;
21
+ /**
22
+ * Muninn's Tauri bundle identifier.
23
+ * Used on macOS to locate the App Sandbox container.
24
+ */
25
+ const MUNINN_BUNDLE_ID = 'com.codeawareness.muninn';
26
+ let socket = null;
27
+ let connected = false;
28
+ let cawId = '';
29
+ let connectionPromise = null;
30
+ const pendingRequests = new Map();
31
+ /**
32
+ * Get the default Muninn socket path for the current platform.
33
+ */
34
+ function getDefaultMuninnSocketPath() {
35
+ if (process.platform === 'win32') {
36
+ return '\\\\.\\pipe\\muninn';
37
+ }
38
+ if (process.platform === 'darwin') {
39
+ // App Store (sandboxed) Muninn: socket may be inside the sandbox container
40
+ const containerSocketPath = path.join(os.homedir(), 'Library', 'Containers', MUNINN_BUNDLE_ID, 'Data', 'Library', 'Application Support', 'Kawa Code', 'sockets', 'muninn');
41
+ if (fs.existsSync(containerSocketPath)) {
42
+ return containerSocketPath;
43
+ }
44
+ }
45
+ // All platforms (incl. macOS dev/brew): ~/.kawa-code/sockets/muninn
46
+ // Matches Muninn's paths.rs: sockets_dir().join("muninn")
47
+ return path.join(os.homedir(), '.kawa-code', 'sockets', 'muninn');
48
+ }
49
+ /**
50
+ * Connect to Muninn's Huginn IPC socket.
51
+ *
52
+ * Sends extension handshake and waits for acknowledgment.
53
+ * Throws if Muninn is not running or handshake fails.
54
+ */
55
+ export function connectToMuninn(socketPath) {
56
+ if (connectionPromise)
57
+ return connectionPromise;
58
+ connectionPromise = _connectToMuninn(socketPath).finally(() => {
59
+ connectionPromise = null;
60
+ });
61
+ return connectionPromise;
62
+ }
63
+ function _connectToMuninn(socketPath) {
64
+ const targetPath = socketPath || process.env.MUNINN_SOCKET || getDefaultMuninnSocketPath();
65
+ return new Promise((resolve, reject) => {
66
+ console.error(`[MuninnIPC] Connecting to Muninn catalog at ${targetPath}...`);
67
+ const catalogSock = net.createConnection(targetPath, () => {
68
+ // Send extension handshake
69
+ const handshake = JSON.stringify({
70
+ domain: 'system',
71
+ action: 'handshake',
72
+ data: {
73
+ clientType: 'extension',
74
+ extensionId: EXTENSION_ID,
75
+ domains: EXTENSION_DOMAINS,
76
+ },
77
+ });
78
+ catalogSock.write(handshake + '\n');
79
+ });
80
+ let handshakeReceived = false;
81
+ let switchedToClientPipe = false; // Windows: true after catalog→client pipe handoff
82
+ let buffer = '';
83
+ catalogSock.on('data', (data) => {
84
+ buffer += data.toString();
85
+ const lines = buffer.split('\n');
86
+ buffer = lines.pop() || '';
87
+ for (const line of lines) {
88
+ if (!line.trim())
89
+ continue;
90
+ try {
91
+ const msg = JSON.parse(line);
92
+ if (!handshakeReceived && msg.domain === 'system' && msg.action === 'handshake') {
93
+ handshakeReceived = true;
94
+ cawId = msg.data?.caw || '';
95
+ const pipePath = msg.data?.pipePath;
96
+ if (pipePath) {
97
+ // Windows two-pipe protocol: catalog pipe only handles registration.
98
+ // Muninn sends back a dedicated client pipe path; connect to it for I/O.
99
+ switchedToClientPipe = true;
100
+ console.error(`[MuninnIPC] Handshake complete (caw=${cawId}), connecting to ${pipePath}`);
101
+ catalogSock.destroy();
102
+ // Small delay so Muninn's thread has time to start the client pipe server
103
+ setTimeout(() => connectClientPipe(pipePath, resolve, reject), 50);
104
+ }
105
+ else {
106
+ // Unix: single persistent connection, keep using catalogSock
107
+ socket = catalogSock;
108
+ connected = true;
109
+ console.error(`[MuninnIPC] Handshake complete (caw=${cawId})`);
110
+ resolve();
111
+ }
112
+ continue;
113
+ }
114
+ // Unix path: responses arrive on the same socket
115
+ routeResponse(msg);
116
+ }
117
+ catch {
118
+ // Ignore non-JSON lines
119
+ }
120
+ }
121
+ });
122
+ catalogSock.on('error', (err) => {
123
+ console.error(`[MuninnIPC] Catalog socket error: ${err.message}`);
124
+ if (!handshakeReceived) {
125
+ reject(new Error(`Muninn is not running. Please start Muninn first.\n` +
126
+ `(Could not connect to ${targetPath}: ${err.message})`));
127
+ }
128
+ if (!switchedToClientPipe)
129
+ cleanup();
130
+ });
131
+ catalogSock.on('close', () => {
132
+ // On Windows the catalog pipe closes after handshake — expected, skip cleanup.
133
+ // On Unix the catalog socket IS the main socket, so closing means disconnected.
134
+ if (!switchedToClientPipe) {
135
+ console.error('[MuninnIPC] Socket closed');
136
+ cleanup();
137
+ }
138
+ });
139
+ // Handshake timeout
140
+ setTimeout(() => {
141
+ if (!handshakeReceived) {
142
+ catalogSock.destroy();
143
+ reject(new Error('Muninn handshake timeout (10s). Is Muninn running?'));
144
+ }
145
+ }, HANDSHAKE_TIMEOUT_MS);
146
+ });
147
+ }
148
+ /**
149
+ * Connect to the dedicated client pipe returned in the Windows handshake.
150
+ * On Windows, Muninn creates a per-client named pipe (\\.\pipe\caw.<id>)
151
+ * for bidirectional communication after the catalog registration.
152
+ */
153
+ function connectClientPipe(pipePath, resolve, reject) {
154
+ console.error(`[MuninnIPC] Connecting to client pipe: ${pipePath}`);
155
+ const clientSock = net.createConnection(pipePath, () => {
156
+ socket = clientSock;
157
+ connected = true;
158
+ console.error('[MuninnIPC] Client pipe connected');
159
+ resolve();
160
+ });
161
+ let buffer = '';
162
+ clientSock.on('data', (data) => {
163
+ buffer += data.toString();
164
+ const lines = buffer.split('\n');
165
+ buffer = lines.pop() || '';
166
+ for (const line of lines) {
167
+ if (!line.trim())
168
+ continue;
169
+ try {
170
+ routeResponse(JSON.parse(line));
171
+ }
172
+ catch { /* ignore */ }
173
+ }
174
+ });
175
+ clientSock.on('error', (err) => {
176
+ console.error(`[MuninnIPC] Client pipe error: ${err.message}`);
177
+ if (!connected) {
178
+ reject(new Error(`Failed to connect to Muninn client pipe: ${err.message}`));
179
+ }
180
+ cleanup();
181
+ });
182
+ clientSock.on('close', () => {
183
+ console.error('[MuninnIPC] Client pipe closed');
184
+ cleanup();
185
+ });
186
+ }
187
+ /** Route an inbound response message to its waiting pendingRequest entry. */
188
+ function routeResponse(msg) {
189
+ const msgId = msg._msgId;
190
+ if (msgId && pendingRequests.has(msgId)) {
191
+ const pending = pendingRequests.get(msgId);
192
+ pendingRequests.delete(msgId);
193
+ clearTimeout(pending.timer);
194
+ if (msg.err) {
195
+ pending.reject(new Error(msg.err));
196
+ }
197
+ else {
198
+ pending.resolve(msg.data || {});
199
+ }
200
+ }
201
+ }
202
+ /**
203
+ * Send an IPC request to Muninn and await the correlated response.
204
+ *
205
+ * @param domain - Handler domain (e.g., 'intent', 'decision')
206
+ * @param action - Handler action (e.g., 'create', 'get-active')
207
+ * @param data - Request payload
208
+ * @returns The response data from Muninn
209
+ */
210
+ export async function request(domain, action, data = {}) {
211
+ if (!socket || !connected) {
212
+ await connectToMuninn();
213
+ }
214
+ const msgId = `mcp-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
215
+ return new Promise((resolve, reject) => {
216
+ const timer = setTimeout(() => {
217
+ pendingRequests.delete(msgId);
218
+ reject(new Error(`Muninn request timeout (${REQUEST_TIMEOUT_MS / 1000}s): ${domain}:${action}`));
219
+ }, REQUEST_TIMEOUT_MS);
220
+ pendingRequests.set(msgId, { resolve, reject, timer });
221
+ const message = JSON.stringify({
222
+ flow: 'req',
223
+ domain,
224
+ action,
225
+ caw: cawId,
226
+ data,
227
+ _msgId: msgId,
228
+ });
229
+ socket.write(message + '\n');
230
+ });
231
+ }
232
+ /**
233
+ * Ensure a repository path is registered with Muninn as a project.
234
+ *
235
+ * Sends `code:add` with the folder path so Muninn activates the project,
236
+ * sets up git state, and pulls intents/decisions/lessons from the API.
237
+ * Always sends the request — Muninn's AddHandler is idempotent and
238
+ * returns the existing project if already added.
239
+ * Errors are logged but not thrown — repo registration is best-effort.
240
+ */
241
+ export async function ensureRepo(repoPath) {
242
+ try {
243
+ await request('code', 'add', { folder: repoPath });
244
+ }
245
+ catch (err) {
246
+ console.error(`[MuninnIPC] ensureRepo failed for ${repoPath}: ${err.message}`);
247
+ }
248
+ }
249
+ /**
250
+ * Check if connected to Muninn.
251
+ */
252
+ export function isConnected() {
253
+ return connected;
254
+ }
255
+ /**
256
+ * Disconnect from Muninn.
257
+ */
258
+ export function disconnect() {
259
+ if (socket) {
260
+ socket.destroy();
261
+ }
262
+ cleanup();
263
+ }
264
+ function cleanup() {
265
+ connected = false;
266
+ socket = null;
267
+ connectionPromise = null;
268
+ // Reject all pending requests
269
+ for (const [id, pending] of pendingRequests) {
270
+ clearTimeout(pending.timer);
271
+ pending.reject(new Error('Muninn connection closed'));
272
+ }
273
+ pendingRequests.clear();
274
+ }
275
+ //# sourceMappingURL=muninn-ipc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"muninn-ipc.js","sourceRoot":"","sources":["../../src/services/muninn-ipc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
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
+ };