overmind-mcp 2.8.12 → 2.8.14

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 (71) hide show
  1. package/dist/bin/launch.js +78 -0
  2. package/dist/bin/overmind-bridge.d.ts +42 -0
  3. package/dist/bin/overmind-bridge.d.ts.map +1 -0
  4. package/dist/bin/overmind-bridge.js +503 -0
  5. package/dist/bin/overmind-bridge.js.map +1 -0
  6. package/dist/bridge/AgentRegistry.d.ts +123 -0
  7. package/dist/bridge/AgentRegistry.d.ts.map +1 -0
  8. package/dist/bridge/AgentRegistry.js +207 -0
  9. package/dist/bridge/AgentRegistry.js.map +1 -0
  10. package/dist/bridge/ArgParser.d.ts +45 -0
  11. package/dist/bridge/ArgParser.d.ts.map +1 -0
  12. package/dist/bridge/ArgParser.js +134 -0
  13. package/dist/bridge/ArgParser.js.map +1 -0
  14. package/dist/bridge/BridgeHttpClient.d.ts +61 -0
  15. package/dist/bridge/BridgeHttpClient.d.ts.map +1 -0
  16. package/dist/bridge/BridgeHttpClient.js +164 -0
  17. package/dist/bridge/BridgeHttpClient.js.map +1 -0
  18. package/dist/bridge/DirectiveParser.d.ts +82 -0
  19. package/dist/bridge/DirectiveParser.d.ts.map +1 -0
  20. package/dist/bridge/DirectiveParser.js +154 -0
  21. package/dist/bridge/DirectiveParser.js.map +1 -0
  22. package/dist/bridge/JsonSanitizer.d.ts +34 -0
  23. package/dist/bridge/JsonSanitizer.d.ts.map +1 -0
  24. package/dist/bridge/JsonSanitizer.js +90 -0
  25. package/dist/bridge/JsonSanitizer.js.map +1 -0
  26. package/dist/bridge/MessageLog.d.ts +142 -0
  27. package/dist/bridge/MessageLog.d.ts.map +1 -0
  28. package/dist/bridge/MessageLog.js +311 -0
  29. package/dist/bridge/MessageLog.js.map +1 -0
  30. package/dist/bridge/OverBridgeServer.d.ts +179 -0
  31. package/dist/bridge/OverBridgeServer.d.ts.map +1 -0
  32. package/dist/bridge/OverBridgeServer.js +982 -0
  33. package/dist/bridge/OverBridgeServer.js.map +1 -0
  34. package/dist/bridge/PromptSource.d.ts +66 -0
  35. package/dist/bridge/PromptSource.d.ts.map +1 -0
  36. package/dist/bridge/PromptSource.js +152 -0
  37. package/dist/bridge/PromptSource.js.map +1 -0
  38. package/dist/bridge/RequestContext.d.ts +19 -0
  39. package/dist/bridge/RequestContext.d.ts.map +1 -0
  40. package/dist/bridge/RequestContext.js +34 -0
  41. package/dist/bridge/RequestContext.js.map +1 -0
  42. package/dist/bridge/ScenarioLoader.d.ts +124 -0
  43. package/dist/bridge/ScenarioLoader.d.ts.map +1 -0
  44. package/dist/bridge/ScenarioLoader.js +333 -0
  45. package/dist/bridge/ScenarioLoader.js.map +1 -0
  46. package/dist/bridge/SessionStore.d.ts +109 -0
  47. package/dist/bridge/SessionStore.d.ts.map +1 -0
  48. package/dist/bridge/SessionStore.js +220 -0
  49. package/dist/bridge/SessionStore.js.map +1 -0
  50. package/dist/bridge/WebhookAdapter.d.ts +76 -0
  51. package/dist/bridge/WebhookAdapter.d.ts.map +1 -0
  52. package/dist/bridge/WebhookAdapter.js +186 -0
  53. package/dist/bridge/WebhookAdapter.js.map +1 -0
  54. package/dist/bridge/index.d.ts +23 -1
  55. package/dist/bridge/index.d.ts.map +1 -1
  56. package/dist/bridge/index.js +19 -1
  57. package/dist/bridge/index.js.map +1 -1
  58. package/dist/bridge/utils.d.ts +9 -0
  59. package/dist/bridge/utils.d.ts.map +1 -1
  60. package/dist/bridge/utils.js +17 -0
  61. package/dist/bridge/utils.js.map +1 -1
  62. package/dist/services/AgentManager.d.ts.map +1 -1
  63. package/dist/services/AgentManager.js +16 -3
  64. package/dist/services/AgentManager.js.map +1 -1
  65. package/dist/services/NousHermesRunner.d.ts.map +1 -1
  66. package/dist/services/NousHermesRunner.js +47 -8
  67. package/dist/services/NousHermesRunner.js.map +1 -1
  68. package/dist/tools/create_agent.d.ts.map +1 -1
  69. package/dist/tools/create_agent.js +11 -0
  70. package/dist/tools/create_agent.js.map +1 -1
  71. package/package.json +2 -1
@@ -0,0 +1,164 @@
1
+ /**
2
+ * ╔══════════════════════════════════════════════════════════════════════╗
3
+ * ║ OVERMIND BRIDGE — BridgeHttpClient (JSON-RPC 2.0 HTTP Caller) ║
4
+ * ║ ║
5
+ * ║ Client HTTP minimaliste pour parler à un OverBridgeServer. ║
6
+ * ║ Utilisé par le CLI pour les commandes 'call', 'scenario', etc. ║
7
+ * ║ Supporte : ║
8
+ * ║ - Single + batch JSON-RPC 2.0 ║
9
+ * ║ - Auth Bearer token ║
10
+ * ║ - Timeout configurable ║
11
+ * ║ - Mode "auto" : démarre un bridge local si pas de serveur ║
12
+ * ╚══════════════════════════════════════════════════════════════════════╝
13
+ */
14
+ import http from 'node:http';
15
+ import { URL } from 'node:url';
16
+ // ─── BridgeHttpClient ──────────────────────────────────────────────────────
17
+ export class BridgeHttpClient {
18
+ config;
19
+ rpcId = 1;
20
+ constructor(config) {
21
+ this.config = {
22
+ baseUrl: config.baseUrl.replace(/\/+$/, ''), // strip trailing slashes
23
+ authToken: config.authToken,
24
+ timeoutMs: config.timeoutMs ?? 60_000,
25
+ };
26
+ }
27
+ get baseUrl() {
28
+ return this.config.baseUrl;
29
+ }
30
+ // ─── JSON-RPC Calls ──────────────────────────────────────────────────────
31
+ /**
32
+ * Appelle une méthode JSON-RPC et retourne le résultat (ou throw).
33
+ */
34
+ async call(method, params, timeoutMs) {
35
+ const req = {
36
+ jsonrpc: '2.0',
37
+ id: this.rpcId++,
38
+ method,
39
+ params,
40
+ };
41
+ const res = await this._post('/rpc', req, timeoutMs ?? this.config.timeoutMs);
42
+ if (Array.isArray(res)) {
43
+ throw new Error('Unexpected batch response to single call');
44
+ }
45
+ if (res.error) {
46
+ const err = new Error(`JSON-RPC error ${res.error.code}: ${res.error.message}`);
47
+ Object.assign(err, { code: res.error.code, data: res.error.data });
48
+ throw err;
49
+ }
50
+ return res.result;
51
+ }
52
+ /**
53
+ * Batch JSON-RPC (plusieurs calls en un round-trip).
54
+ */
55
+ async callBatch(calls) {
56
+ const reqs = calls.map((c) => ({
57
+ jsonrpc: '2.0',
58
+ id: this.rpcId++,
59
+ method: c.method,
60
+ params: c.params,
61
+ }));
62
+ const responses = await this._post('/rpc', reqs, this.config.timeoutMs);
63
+ if (!Array.isArray(responses)) {
64
+ throw new Error('Batch call did not return an array');
65
+ }
66
+ return responses.map((r) => {
67
+ if (r.error) {
68
+ const err = new Error(`JSON-RPC error ${r.error.code}: ${r.error.message}`);
69
+ Object.assign(err, { code: r.error.code, data: r.error.data });
70
+ throw err;
71
+ }
72
+ return r.result;
73
+ });
74
+ }
75
+ /**
76
+ * GET /health (pas JSON-RPC, endpoint séparé).
77
+ */
78
+ async health() {
79
+ const res = await this._get('/health', 5_000);
80
+ return JSON.parse(res);
81
+ }
82
+ // ─── HTTP Helpers ────────────────────────────────────────────────────────
83
+ async _post(path, body, timeoutMs) {
84
+ const url = new URL(this.config.baseUrl + path);
85
+ const data = JSON.stringify(body);
86
+ return new Promise((resolve, reject) => {
87
+ const controller = new AbortController();
88
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
89
+ const req = http.request({
90
+ hostname: url.hostname,
91
+ port: url.port || (url.protocol === 'https:' ? 443 : 80),
92
+ path: url.pathname + url.search,
93
+ method: 'POST',
94
+ headers: {
95
+ 'Content-Type': 'application/json',
96
+ 'Accept': 'application/json',
97
+ 'Content-Length': Buffer.byteLength(data),
98
+ ...(this.config.authToken ? { Authorization: `Bearer ${this.config.authToken}` } : {}),
99
+ },
100
+ signal: controller.signal,
101
+ }, (res) => {
102
+ clearTimeout(timer);
103
+ const chunks = [];
104
+ res.on('data', (chunk) => chunks.push(chunk));
105
+ res.on('end', () => {
106
+ const text = Buffer.concat(chunks).toString('utf-8');
107
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
108
+ try {
109
+ resolve(JSON.parse(text));
110
+ }
111
+ catch (err) {
112
+ reject(new Error(`Invalid JSON response: ${text.slice(0, 200)}`));
113
+ }
114
+ }
115
+ else {
116
+ reject(new Error(`HTTP ${res.statusCode}: ${text.slice(0, 200)}`));
117
+ }
118
+ });
119
+ res.on('error', reject);
120
+ });
121
+ req.on('error', (err) => {
122
+ clearTimeout(timer);
123
+ reject(err);
124
+ });
125
+ req.write(data);
126
+ req.end();
127
+ });
128
+ }
129
+ async _get(path, timeoutMs) {
130
+ const url = new URL(this.config.baseUrl + path);
131
+ return new Promise((resolve, reject) => {
132
+ const controller = new AbortController();
133
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
134
+ const req = http.request({
135
+ hostname: url.hostname,
136
+ port: url.port || 80,
137
+ path: url.pathname + url.search,
138
+ method: 'GET',
139
+ headers: { Accept: 'application/json' },
140
+ signal: controller.signal,
141
+ }, (res) => {
142
+ clearTimeout(timer);
143
+ const chunks = [];
144
+ res.on('data', (chunk) => chunks.push(chunk));
145
+ res.on('end', () => {
146
+ const text = Buffer.concat(chunks).toString('utf-8');
147
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
148
+ resolve(text);
149
+ }
150
+ else {
151
+ reject(new Error(`HTTP ${res.statusCode}: ${text.slice(0, 200)}`));
152
+ }
153
+ });
154
+ res.on('error', reject);
155
+ });
156
+ req.on('error', (err) => {
157
+ clearTimeout(timer);
158
+ reject(err);
159
+ });
160
+ req.end();
161
+ });
162
+ }
163
+ }
164
+ //# sourceMappingURL=BridgeHttpClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BridgeHttpClient.js","sourceRoot":"","sources":["../../src/bridge/BridgeHttpClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * ╔══════════════════════════════════════════════════════════════════════╗
3
+ * ║ OVERMIND BRIDGE — DirectiveParser (Agent-Side Protocol) ║
4
+ * ║ ║
5
+ * ║ Permet aux agents d'injecter des directives structurées dans ║
6
+ * ║ leurs réponses textuelles. Le bridge les extrait et les exécute. ║
7
+ * ║ ║
8
+ * ║ PATTERN ║
9
+ * ║ ─────── ║
10
+ * ║ Inspiré du `CONTEXT_UPDATE: step=X employe_id=Y` de bt-sms. ║
11
+ * ║ ║
12
+ * ║ L'agent écrit dans sa réponse : ║
13
+ * ║ ║
14
+ * ║ "Voici mon analyse. ║
15
+ * ║ SESSION_ID: hermes-sess-abc123 ║
16
+ * ║ CONTEXT_UPDATE: step=awaiting_description employe_id=42 ║
17
+ * ║ BRIDGE_NEXT: agent=scout prompt=\"Analyse BTC\" ║
18
+ * ║ BRIDGE_END" ║
19
+ * ║ ║
20
+ * ║ Le bridge : ║
21
+ * ║ 1. Extrait SESSION_ID, l'assigne au store ║
22
+ * ║ 2. Patche le context (state machine) ║
23
+ * ║ 3. Lance automatiquement un nouveau call vers scout ║
24
+ * ║ 4. Supprime les directives du texte retourné au client ║
25
+ * ║ ║
26
+ * ║ DIRECTIVES SUPPORTÉES ║
27
+ * ║ ────────────────────── ║
28
+ * ║ - SESSION_ID: <id> → assigne le sessionId ║
29
+ * ║ - CONTEXT_UPDATE: k=v k=v → patche le context ║
30
+ * ║ - BRIDGE_NEXT: method=X ... → déclenche un appel suivant ║
31
+ * ║ - BRIDGE_END → arrête la chaîne de next calls ║
32
+ * ║ - BRIDGE_HINT: <text> → tag/metadata (no action) ║
33
+ * ╚══════════════════════════════════════════════════════════════════════╝
34
+ */
35
+ import { type BridgeLogger } from './utils.js';
36
+ import type { JsonRpcRequest } from './OverBridgeServer.js';
37
+ export type DirectiveAction = {
38
+ kind: 'session';
39
+ sessionId: string;
40
+ } | {
41
+ kind: 'context';
42
+ patch: Record<string, string>;
43
+ } | {
44
+ kind: 'next';
45
+ call: JsonRpcRequest;
46
+ } | {
47
+ kind: 'end';
48
+ } | {
49
+ kind: 'hint';
50
+ text: string;
51
+ };
52
+ export interface ParsedDirectives {
53
+ /** Texte original sans les directives (propre, pour le client) */
54
+ cleanText: string;
55
+ /** Directives extraites, dans l'ordre */
56
+ actions: DirectiveAction[];
57
+ /** Erreurs de parsing (lignes mal formées, ignorées mais loguées) */
58
+ errors: string[];
59
+ }
60
+ export interface DirectiveParserOptions {
61
+ /** Logger */
62
+ logger?: BridgeLogger;
63
+ }
64
+ export declare class DirectiveParser {
65
+ private readonly log;
66
+ constructor(opts?: DirectiveParserOptions);
67
+ /**
68
+ * Parse un texte de réponse d'agent et extrait les directives.
69
+ * Lignes de directive : `DIRECTIVE_NAME: value`.
70
+ */
71
+ parse(responseText: string): ParsedDirectives;
72
+ /**
73
+ * Parse une directive individuelle. Retourne null si nom inconnu.
74
+ */
75
+ private parseDirective;
76
+ }
77
+ /**
78
+ * Parse un format "key=value key2='value with spaces' key3="value with quotes"".
79
+ * Supporte quotes simples, doubles, et backslash escape.
80
+ */
81
+ export declare function parseKeyValueArgs(input: string): Record<string, string>;
82
+ //# sourceMappingURL=DirectiveParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DirectiveParser.d.ts","sourceRoot":"","sources":["../../src/bridge/DirectiveParser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,qEAAqE;IACrE,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,aAAa;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAID,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEvB,IAAI,GAAE,sBAA2B;IAI7C;;;OAGG;IACH,KAAK,CAAC,YAAY,EAAE,MAAM,GAAG,gBAAgB;IAkC7C;;OAEG;IACH,OAAO,CAAC,cAAc;CAwCvB;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYvE"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * ╔══════════════════════════════════════════════════════════════════════╗
3
+ * ║ OVERMIND BRIDGE — DirectiveParser (Agent-Side Protocol) ║
4
+ * ║ ║
5
+ * ║ Permet aux agents d'injecter des directives structurées dans ║
6
+ * ║ leurs réponses textuelles. Le bridge les extrait et les exécute. ║
7
+ * ║ ║
8
+ * ║ PATTERN ║
9
+ * ║ ─────── ║
10
+ * ║ Inspiré du `CONTEXT_UPDATE: step=X employe_id=Y` de bt-sms. ║
11
+ * ║ ║
12
+ * ║ L'agent écrit dans sa réponse : ║
13
+ * ║ ║
14
+ * ║ "Voici mon analyse. ║
15
+ * ║ SESSION_ID: hermes-sess-abc123 ║
16
+ * ║ CONTEXT_UPDATE: step=awaiting_description employe_id=42 ║
17
+ * ║ BRIDGE_NEXT: agent=scout prompt=\"Analyse BTC\" ║
18
+ * ║ BRIDGE_END" ║
19
+ * ║ ║
20
+ * ║ Le bridge : ║
21
+ * ║ 1. Extrait SESSION_ID, l'assigne au store ║
22
+ * ║ 2. Patche le context (state machine) ║
23
+ * ║ 3. Lance automatiquement un nouveau call vers scout ║
24
+ * ║ 4. Supprime les directives du texte retourné au client ║
25
+ * ║ ║
26
+ * ║ DIRECTIVES SUPPORTÉES ║
27
+ * ║ ────────────────────── ║
28
+ * ║ - SESSION_ID: <id> → assigne le sessionId ║
29
+ * ║ - CONTEXT_UPDATE: k=v k=v → patche le context ║
30
+ * ║ - BRIDGE_NEXT: method=X ... → déclenche un appel suivant ║
31
+ * ║ - BRIDGE_END → arrête la chaîne de next calls ║
32
+ * ║ - BRIDGE_HINT: <text> → tag/metadata (no action) ║
33
+ * ╚══════════════════════════════════════════════════════════════════════╝
34
+ */
35
+ import { createBridgeLogger } from './utils.js';
36
+ // ─── DirectiveParser ───────────────────────────────────────────────────────
37
+ export class DirectiveParser {
38
+ log;
39
+ constructor(opts = {}) {
40
+ this.log = opts.logger ?? createBridgeLogger('directive-parser');
41
+ }
42
+ /**
43
+ * Parse un texte de réponse d'agent et extrait les directives.
44
+ * Lignes de directive : `DIRECTIVE_NAME: value`.
45
+ */
46
+ parse(responseText) {
47
+ const actions = [];
48
+ const errors = [];
49
+ const cleanedLines = [];
50
+ for (const rawLine of responseText.split('\n')) {
51
+ const line = rawLine.trim();
52
+ // Détecte ligne "DIRECTIVE:" (case-insensitive)
53
+ const m = line.match(/^([A-Z_]+):\s*(.*)$/);
54
+ if (!m) {
55
+ cleanedLines.push(rawLine);
56
+ continue;
57
+ }
58
+ const [, name, rawValue] = m;
59
+ try {
60
+ const action = this.parseDirective(name, rawValue);
61
+ if (action) {
62
+ actions.push(action);
63
+ continue; // directive consommée
64
+ }
65
+ cleanedLines.push(rawLine); // nom inconnu, on garde
66
+ }
67
+ catch (err) {
68
+ errors.push(`Failed to parse ${name}: ${err.message}`);
69
+ cleanedLines.push(rawLine); // on garde la ligne en cas d'erreur
70
+ }
71
+ }
72
+ return {
73
+ cleanText: cleanedLines.join('\n').replace(/\n{3,}/g, '\n\n').trim(),
74
+ actions,
75
+ errors,
76
+ };
77
+ }
78
+ /**
79
+ * Parse une directive individuelle. Retourne null si nom inconnu.
80
+ */
81
+ parseDirective(name, value) {
82
+ switch (name) {
83
+ case 'SESSION_ID':
84
+ if (!value.trim())
85
+ throw new Error('Empty session id');
86
+ return { kind: 'session', sessionId: value.trim() };
87
+ case 'CONTEXT_UPDATE': {
88
+ const patch = {};
89
+ for (const token of value.split(/\s+/)) {
90
+ const eqIdx = token.indexOf('=');
91
+ if (eqIdx === -1)
92
+ continue;
93
+ const k = token.slice(0, eqIdx).trim();
94
+ const v = token.slice(eqIdx + 1).trim();
95
+ if (k)
96
+ patch[k] = decodeURIComponentSafe(v);
97
+ }
98
+ if (Object.keys(patch).length === 0)
99
+ throw new Error('Empty CONTEXT_UPDATE');
100
+ return { kind: 'context', patch };
101
+ }
102
+ case 'BRIDGE_NEXT': {
103
+ // Format: method=agent.run agent=scout prompt="..."
104
+ // method=agent.a2a from=scout to=analyst prompt="..."
105
+ const params = parseKeyValueArgs(value);
106
+ if (!params.method)
107
+ throw new Error('BRIDGE_NEXT requires method=...');
108
+ return {
109
+ kind: 'next',
110
+ call: { jsonrpc: '2.0', id: 0, method: params.method, params },
111
+ };
112
+ }
113
+ case 'BRIDGE_END':
114
+ return { kind: 'end' };
115
+ case 'BRIDGE_HINT':
116
+ return { kind: 'hint', text: value.trim() };
117
+ default:
118
+ return null; // nom inconnu, le caller garde la ligne
119
+ }
120
+ }
121
+ }
122
+ // ─── Helpers ───────────────────────────────────────────────────────────────
123
+ /**
124
+ * Parse un format "key=value key2='value with spaces' key3="value with quotes"".
125
+ * Supporte quotes simples, doubles, et backslash escape.
126
+ */
127
+ export function parseKeyValueArgs(input) {
128
+ const result = {};
129
+ const re = /(\w+)=(?:"((?:\\.|[^"\\])*)"|'((?:\\.|[^'\\])*)'|(\S+))/g;
130
+ let m;
131
+ while ((m = re.exec(input)) !== null) {
132
+ const key = m[1];
133
+ const value = m[2] ?? m[3] ?? m[4] ?? '';
134
+ // Déchapper les séquences \\ \"
135
+ const decoded = value.replace(/\\(.)/g, '$1');
136
+ result[key] = decoded;
137
+ }
138
+ return result;
139
+ }
140
+ /**
141
+ * Décode une valeur URI-component si elle ressemble à du %XX, sinon la retourne brute.
142
+ */
143
+ function decodeURIComponentSafe(value) {
144
+ if (value.includes('%') && /%[0-9A-Fa-f]{2}/.test(value)) {
145
+ try {
146
+ return decodeURIComponent(value);
147
+ }
148
+ catch {
149
+ return value;
150
+ }
151
+ }
152
+ return value;
153
+ }
154
+ //# sourceMappingURL=DirectiveParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DirectiveParser.js","sourceRoot":"","sources":["../../src/bridge/DirectiveParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * ╔══════════════════════════════════════════════════════════════════════╗
3
+ * ║ OVERMIND BRIDGE — JSON Sanitizer (Windows Path Rescue) ║
4
+ * ║ ║
5
+ * ║ Répare les payloads JSON mal échappés contenant des chemins ║
6
+ * ║ Windows (ex: `C:\Users\Deamon\file.txt` qui casse le JSON si ║
7
+ * ║ pas double-échappé). Pattern inspiré de bt-sms. ║
8
+ * ║ ║
9
+ * ║ Le problème : un client envoie un body qui contient ║
10
+ * ║ `"path": "C:\Users\Deamon\file.txt"` — l'antislash devant `U` ║
11
+ * ║ est interprété comme un caractère d'échappement JSON invalide. ║
12
+ * ║ ║
13
+ * ║ La solution : un sanitizer state-machine qui : ║
14
+ * ║ - Détecte si on est dans une string ║
15
+ * ║ - Double les `\` qui ne sont pas suivis d'un char d'échappement ║
16
+ * ║ - Préserve le contenu légitime ║
17
+ * ╚══════════════════════════════════════════════════════════════════════╝
18
+ */
19
+ /**
20
+ * Tente de réparer un JSON malformé contenant des chemins Windows non échappés.
21
+ * Retourne le JSON parsé, ou throw si irrécupérable.
22
+ */
23
+ export declare function sanitizeAndParse(rawBody: string): unknown;
24
+ /**
25
+ * State-machine qui double les `\` non-échappés dans les strings JSON.
26
+ * Préserve les séquences d'échappement valides (\n, \t, \\, \", etc.)
27
+ */
28
+ export declare function sanitizeJsonRaw(rawBody: string): string;
29
+ /**
30
+ * Détecte si un body est probablement cassé par des Windows paths non échappés.
31
+ * Heuristique simple : présence de `:\` dans le body.
32
+ */
33
+ export declare function looksLikeWindowsPathIssue(rawBody: string): boolean;
34
+ //# sourceMappingURL=JsonSanitizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonSanitizer.d.ts","sourceRoot":"","sources":["../../src/bridge/JsonSanitizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAkBzD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAuCvD;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAElE"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * ╔══════════════════════════════════════════════════════════════════════╗
3
+ * ║ OVERMIND BRIDGE — JSON Sanitizer (Windows Path Rescue) ║
4
+ * ║ ║
5
+ * ║ Répare les payloads JSON mal échappés contenant des chemins ║
6
+ * ║ Windows (ex: `C:\Users\Deamon\file.txt` qui casse le JSON si ║
7
+ * ║ pas double-échappé). Pattern inspiré de bt-sms. ║
8
+ * ║ ║
9
+ * ║ Le problème : un client envoie un body qui contient ║
10
+ * ║ `"path": "C:\Users\Deamon\file.txt"` — l'antislash devant `U` ║
11
+ * ║ est interprété comme un caractère d'échappement JSON invalide. ║
12
+ * ║ ║
13
+ * ║ La solution : un sanitizer state-machine qui : ║
14
+ * ║ - Détecte si on est dans une string ║
15
+ * ║ - Double les `\` qui ne sont pas suivis d'un char d'échappement ║
16
+ * ║ - Préserve le contenu légitime ║
17
+ * ╚══════════════════════════════════════════════════════════════════════╝
18
+ */
19
+ /**
20
+ * Tente de réparer un JSON malformé contenant des chemins Windows non échappés.
21
+ * Retourne le JSON parsé, ou throw si irrécupérable.
22
+ */
23
+ export function sanitizeAndParse(rawBody) {
24
+ // Essai 1 : parse direct
25
+ try {
26
+ return JSON.parse(rawBody);
27
+ }
28
+ catch {
29
+ // Fall through
30
+ }
31
+ // Essai 2 : sanitizer state-machine
32
+ const sanitized = sanitizeJsonRaw(rawBody);
33
+ try {
34
+ return JSON.parse(sanitized);
35
+ }
36
+ catch {
37
+ // Fall through
38
+ }
39
+ // Donné, on throw
40
+ throw new Error('JSON body is malformed and could not be sanitized');
41
+ }
42
+ /**
43
+ * State-machine qui double les `\` non-échappés dans les strings JSON.
44
+ * Préserve les séquences d'échappement valides (\n, \t, \\, \", etc.)
45
+ */
46
+ export function sanitizeJsonRaw(rawBody) {
47
+ let insideString = false;
48
+ let result = '';
49
+ for (let i = 0; i < rawBody.length; i++) {
50
+ const char = rawBody[i];
51
+ if (char === '"' && (i === 0 || rawBody[i - 1] !== '\\')) {
52
+ insideString = !insideString;
53
+ result += char;
54
+ continue;
55
+ }
56
+ if (char === '\\' && insideString) {
57
+ const nextChar = rawBody[i + 1];
58
+ if (nextChar === '\\') {
59
+ // \\ : on garde, on saute le 2e
60
+ result += '\\\\';
61
+ i++;
62
+ continue;
63
+ }
64
+ if (nextChar === '"') {
65
+ // \" : on garde
66
+ result += '\\"';
67
+ i++;
68
+ continue;
69
+ }
70
+ // Autres : \n, \t, \u, etc. — légitime, on garde tel quel
71
+ if (nextChar && /[nrtbf/\\"u]/.test(nextChar)) {
72
+ result += char;
73
+ continue;
74
+ }
75
+ // \X non standard (typiquement \U de C:\Users) — on double
76
+ result += '\\\\';
77
+ continue;
78
+ }
79
+ result += char;
80
+ }
81
+ return result;
82
+ }
83
+ /**
84
+ * Détecte si un body est probablement cassé par des Windows paths non échappés.
85
+ * Heuristique simple : présence de `:\` dans le body.
86
+ */
87
+ export function looksLikeWindowsPathIssue(rawBody) {
88
+ return /:\\/.test(rawBody);
89
+ }
90
+ //# sourceMappingURL=JsonSanitizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsonSanitizer.js","sourceRoot":"","sources":["../../src/bridge/JsonSanitizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,yBAAyB;IACzB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IAED,oCAAoC;IACpC,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC3C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IAED,kBAAkB;IAClB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAExB,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;YACzD,YAAY,GAAG,CAAC,YAAY,CAAC;YAC7B,MAAM,IAAI,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,IAAI,IAAI,YAAY,EAAE,CAAC;YAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAChC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;gBACtB,gCAAgC;gBAChC,MAAM,IAAI,MAAM,CAAC;gBACjB,CAAC,EAAE,CAAC;gBACJ,SAAS;YACX,CAAC;YACD,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;gBACrB,gBAAgB;gBAChB,MAAM,IAAI,KAAK,CAAC;gBAChB,CAAC,EAAE,CAAC;gBACJ,SAAS;YACX,CAAC;YACD,0DAA0D;YAC1D,IAAI,QAAQ,IAAI,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9C,MAAM,IAAI,IAAI,CAAC;gBACf,SAAS;YACX,CAAC;YACD,2DAA2D;YAC3D,MAAM,IAAI,MAAM,CAAC;YACjB,SAAS;QACX,CAAC;QAED,MAAM,IAAI,IAAI,CAAC;IACjB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAe;IACvD,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC"}