ineedcodes 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +161 -0
- package/docs/assets/ineed-logo.svg +161 -0
- package/docs/configuration.md +71 -0
- package/docs/skills.md +58 -0
- package/package.json +41 -0
- package/packages/agent/dist/boost.d.ts +34 -0
- package/packages/agent/dist/boost.js +138 -0
- package/packages/agent/dist/boost.js.map +1 -0
- package/packages/agent/dist/events.d.ts +67 -0
- package/packages/agent/dist/events.js +16 -0
- package/packages/agent/dist/events.js.map +1 -0
- package/packages/agent/dist/index.d.ts +6 -0
- package/packages/agent/dist/index.js +7 -0
- package/packages/agent/dist/index.js.map +1 -0
- package/packages/agent/dist/lead-agent.d.ts +85 -0
- package/packages/agent/dist/lead-agent.js +235 -0
- package/packages/agent/dist/lead-agent.js.map +1 -0
- package/packages/agent/dist/orchestrator.d.ts +43 -0
- package/packages/agent/dist/orchestrator.js +135 -0
- package/packages/agent/dist/orchestrator.js.map +1 -0
- package/packages/agent/dist/runtime.d.ts +44 -0
- package/packages/agent/dist/runtime.js +265 -0
- package/packages/agent/dist/runtime.js.map +1 -0
- package/packages/agent/dist/system-prompts.d.ts +24 -0
- package/packages/agent/dist/system-prompts.js +91 -0
- package/packages/agent/dist/system-prompts.js.map +1 -0
- package/packages/agent/package.json +21 -0
- package/packages/cli/dist/index.d.ts +3 -0
- package/packages/cli/dist/index.js +567 -0
- package/packages/cli/dist/index.js.map +1 -0
- package/packages/cli/dist/setup.d.ts +37 -0
- package/packages/cli/dist/setup.js +240 -0
- package/packages/cli/dist/setup.js.map +1 -0
- package/packages/cli/dist/tools-setup.d.ts +12 -0
- package/packages/cli/dist/tools-setup.js +28 -0
- package/packages/cli/dist/tools-setup.js.map +1 -0
- package/packages/cli/dist/ui/approval.d.ts +12 -0
- package/packages/cli/dist/ui/approval.js +52 -0
- package/packages/cli/dist/ui/approval.js.map +1 -0
- package/packages/cli/dist/ui/colors.d.ts +14 -0
- package/packages/cli/dist/ui/colors.js +21 -0
- package/packages/cli/dist/ui/colors.js.map +1 -0
- package/packages/cli/dist/ui/prompts.d.ts +46 -0
- package/packages/cli/dist/ui/prompts.js +135 -0
- package/packages/cli/dist/ui/prompts.js.map +1 -0
- package/packages/cli/dist/ui/renderer.d.ts +13 -0
- package/packages/cli/dist/ui/renderer.js +95 -0
- package/packages/cli/dist/ui/renderer.js.map +1 -0
- package/packages/cli/package.json +23 -0
- package/packages/core/dist/config/config.d.ts +32 -0
- package/packages/core/dist/config/config.js +43 -0
- package/packages/core/dist/config/config.js.map +1 -0
- package/packages/core/dist/context/engine.d.ts +25 -0
- package/packages/core/dist/context/engine.js +98 -0
- package/packages/core/dist/context/engine.js.map +1 -0
- package/packages/core/dist/index.d.ts +20 -0
- package/packages/core/dist/index.js +21 -0
- package/packages/core/dist/index.js.map +1 -0
- package/packages/core/dist/llm/openai-compatible.d.ts +23 -0
- package/packages/core/dist/llm/openai-compatible.js +177 -0
- package/packages/core/dist/llm/openai-compatible.js.map +1 -0
- package/packages/core/dist/memory/icm-adapter.d.ts +31 -0
- package/packages/core/dist/memory/icm-adapter.js +98 -0
- package/packages/core/dist/memory/icm-adapter.js.map +1 -0
- package/packages/core/dist/permissions/permissions.d.ts +28 -0
- package/packages/core/dist/permissions/permissions.js +89 -0
- package/packages/core/dist/permissions/permissions.js.map +1 -0
- package/packages/core/dist/security/secrets.d.ts +4 -0
- package/packages/core/dist/security/secrets.js +43 -0
- package/packages/core/dist/security/secrets.js.map +1 -0
- package/packages/core/dist/session/store.d.ts +16 -0
- package/packages/core/dist/session/store.js +54 -0
- package/packages/core/dist/session/store.js.map +1 -0
- package/packages/core/dist/shell/process.d.ts +26 -0
- package/packages/core/dist/shell/process.js +128 -0
- package/packages/core/dist/shell/process.js.map +1 -0
- package/packages/core/dist/skills/loader.d.ts +9 -0
- package/packages/core/dist/skills/loader.js +163 -0
- package/packages/core/dist/skills/loader.js.map +1 -0
- package/packages/core/dist/tools/fs.d.ts +10 -0
- package/packages/core/dist/tools/fs.js +409 -0
- package/packages/core/dist/tools/fs.js.map +1 -0
- package/packages/core/dist/tools/git.d.ts +7 -0
- package/packages/core/dist/tools/git.js +251 -0
- package/packages/core/dist/tools/git.js.map +1 -0
- package/packages/core/dist/tools/mcp.d.ts +42 -0
- package/packages/core/dist/tools/mcp.js +158 -0
- package/packages/core/dist/tools/mcp.js.map +1 -0
- package/packages/core/dist/tools/registry.d.ts +21 -0
- package/packages/core/dist/tools/registry.js +50 -0
- package/packages/core/dist/tools/registry.js.map +1 -0
- package/packages/core/dist/tools/search.d.ts +2 -0
- package/packages/core/dist/tools/search.js +243 -0
- package/packages/core/dist/tools/search.js.map +1 -0
- package/packages/core/dist/tools/shell.d.ts +8 -0
- package/packages/core/dist/tools/shell.js +164 -0
- package/packages/core/dist/tools/shell.js.map +1 -0
- package/packages/core/dist/tools/web.d.ts +14 -0
- package/packages/core/dist/tools/web.js +125 -0
- package/packages/core/dist/tools/web.js.map +1 -0
- package/packages/core/dist/types.d.ts +202 -0
- package/packages/core/dist/types.js +7 -0
- package/packages/core/dist/types.js.map +1 -0
- package/packages/core/dist/util/fs.d.ts +5 -0
- package/packages/core/dist/util/fs.js +33 -0
- package/packages/core/dist/util/fs.js.map +1 -0
- package/packages/core/dist/util/shell-quote.d.ts +7 -0
- package/packages/core/dist/util/shell-quote.js +20 -0
- package/packages/core/dist/util/shell-quote.js.map +1 -0
- package/packages/core/dist/workspace/workspace.d.ts +15 -0
- package/packages/core/dist/workspace/workspace.js +84 -0
- package/packages/core/dist/workspace/workspace.js.map +1 -0
- package/packages/core/package.json +21 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { bold, dim, gray, green, red, yellow, cyan, magenta, truncate } from './colors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Renders agent runtime events into a readable terminal stream.
|
|
4
|
+
* Beginners get plain-English narration; the raw data is there for
|
|
5
|
+
* advanced users in the tool output blocks.
|
|
6
|
+
*/
|
|
7
|
+
export class Renderer {
|
|
8
|
+
currentTurn = 0;
|
|
9
|
+
async handle(event) {
|
|
10
|
+
switch (event.type) {
|
|
11
|
+
case 'session-start':
|
|
12
|
+
this.line(dim(`─ session started · model ${event.model} · project ${event.projectRoot}`));
|
|
13
|
+
break;
|
|
14
|
+
case 'turn-start':
|
|
15
|
+
this.currentTurn = event.turn;
|
|
16
|
+
break;
|
|
17
|
+
case 'thinking':
|
|
18
|
+
this.line(gray(`· ${truncate(event.text, 200)}`));
|
|
19
|
+
break;
|
|
20
|
+
case 'assistant-message':
|
|
21
|
+
process.stdout.write('\n');
|
|
22
|
+
for (const para of event.text.split('\n')) {
|
|
23
|
+
this.line(para ? ` ${para}` : '');
|
|
24
|
+
}
|
|
25
|
+
process.stdout.write('\n');
|
|
26
|
+
break;
|
|
27
|
+
case 'tool-start':
|
|
28
|
+
this.line(cyan(`▸ ${event.tool}`) + gray(` ${this.describeInput(event.input)}`));
|
|
29
|
+
break;
|
|
30
|
+
case 'tool-result':
|
|
31
|
+
this.renderToolResult(event.tool, event.result);
|
|
32
|
+
break;
|
|
33
|
+
case 'agent-spawned':
|
|
34
|
+
this.line(magenta(`◆ sub-agent ${event.capability}`) + gray(` · ${truncate(event.objective, 100)}`));
|
|
35
|
+
break;
|
|
36
|
+
case 'agent-status':
|
|
37
|
+
this.line(magenta(` ↳ status: ${event.status}`));
|
|
38
|
+
break;
|
|
39
|
+
case 'agent-result':
|
|
40
|
+
this.line(magenta(` ✓ result: `) + truncate(event.summary, 160));
|
|
41
|
+
break;
|
|
42
|
+
case 'boost-phase':
|
|
43
|
+
this.line(bold(yellow(`⏻ boost · ${event.phase}`)) + (event.detail ? gray(`: ${truncate(event.detail, 120)}`) : ''));
|
|
44
|
+
break;
|
|
45
|
+
case 'compaction':
|
|
46
|
+
this.line(dim(`⟲ context compacted (turn ${this.currentTurn}); checkpoint preserved.`));
|
|
47
|
+
break;
|
|
48
|
+
case 'permission-denied':
|
|
49
|
+
this.line(yellow(`⚠ permission needed for ${event.tool}: ${truncate(event.reason, 160)}`));
|
|
50
|
+
break;
|
|
51
|
+
case 'memory-write':
|
|
52
|
+
this.line(gray(`✦ remembered: ${truncate(event.content, 140)}`));
|
|
53
|
+
break;
|
|
54
|
+
case 'skill-invoked':
|
|
55
|
+
this.line(magenta(`§ skill: ${event.name}`));
|
|
56
|
+
break;
|
|
57
|
+
case 'turn-end':
|
|
58
|
+
if (event.stopReason !== 'continue') {
|
|
59
|
+
this.line(dim(`─ stopped (${event.stopReason}) after turn ${event.turn}`));
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
case 'session-end':
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
renderToolResult(tool, result) {
|
|
67
|
+
if (result.ok) {
|
|
68
|
+
this.line(green(`◂ ${tool}: `) + truncate(result.summary, 150));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.line(red(`◂ ${tool} failed: `) + truncate(result.summary, 200));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
describeInput(input) {
|
|
75
|
+
if (input === null || input === undefined)
|
|
76
|
+
return '';
|
|
77
|
+
if (typeof input !== 'object')
|
|
78
|
+
return truncate(String(input), 100);
|
|
79
|
+
const record = input;
|
|
80
|
+
const parts = [];
|
|
81
|
+
for (const key of ['path', 'command', 'query', 'url', 'from', 'to', 'pattern', 'name', 'message', 'content']) {
|
|
82
|
+
const v = record[key];
|
|
83
|
+
if (typeof v === 'string' && v) {
|
|
84
|
+
parts.push(`${key}=${truncate(v, 80)}`);
|
|
85
|
+
}
|
|
86
|
+
if (parts.length >= 2)
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
return parts.join(' ');
|
|
90
|
+
}
|
|
91
|
+
line(text) {
|
|
92
|
+
process.stdout.write(text + '\n');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/ui/renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ineedcodes/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "iNeedCodes — CLI-first general-purpose autonomous AI agent",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ineed": "dist/index.js",
|
|
9
|
+
"ineedcodes": "dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc -b"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@ineedcodes/agent": "0.1.0",
|
|
18
|
+
"@ineedcodes/core": "0.1.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/node": "^22.0.0"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { LLMProviderConfig } from '../types.js';
|
|
2
|
+
export interface IneedcodesConfig {
|
|
3
|
+
providers: Record<string, LLMProviderConfig>;
|
|
4
|
+
/** Which provider id to use as the default / Lead model. */
|
|
5
|
+
defaultProvider: string;
|
|
6
|
+
/** Per-role model selection. Falls back to defaultProvider. */
|
|
7
|
+
roleProviders?: Partial<Record<'lead' | 'research' | 'coder' | 'reviewer', string>>;
|
|
8
|
+
permissions: {
|
|
9
|
+
mode: 'ask' | 'workspace' | 'autonomous';
|
|
10
|
+
allow?: string[];
|
|
11
|
+
deny?: string[];
|
|
12
|
+
maxParallelAgents: number;
|
|
13
|
+
};
|
|
14
|
+
memory: {
|
|
15
|
+
backend: 'icm' | 'off';
|
|
16
|
+
database?: string;
|
|
17
|
+
};
|
|
18
|
+
webSearch?: {
|
|
19
|
+
provider: string;
|
|
20
|
+
apiKey?: string;
|
|
21
|
+
baseUrl?: string;
|
|
22
|
+
};
|
|
23
|
+
mcpServers?: Record<string, {
|
|
24
|
+
command: string;
|
|
25
|
+
args?: string[];
|
|
26
|
+
env?: Record<string, string>;
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
export declare function defaultConfig(): IneedcodesConfig;
|
|
30
|
+
export declare function configDir(): string;
|
|
31
|
+
export declare function loadConfig(): Promise<IneedcodesConfig>;
|
|
32
|
+
export declare function saveConfig(config: IneedcodesConfig): Promise<void>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import { readJson } from '../util/fs.js';
|
|
4
|
+
export function defaultConfig() {
|
|
5
|
+
return {
|
|
6
|
+
providers: {
|
|
7
|
+
default: {
|
|
8
|
+
baseUrl: process.env['INEEDCODES_BASE_URL'] ?? 'https://api.openai.com/v1',
|
|
9
|
+
apiKey: process.env['INEEDCODES_API_KEY'] ?? process.env['OPENAI_API_KEY'],
|
|
10
|
+
model: process.env['INEEDCODES_MODEL'] ?? 'gpt-4.1-mini',
|
|
11
|
+
maxRetries: 2
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
defaultProvider: 'default',
|
|
15
|
+
permissions: {
|
|
16
|
+
mode: 'workspace',
|
|
17
|
+
maxParallelAgents: 4
|
|
18
|
+
},
|
|
19
|
+
memory: { backend: 'icm' }
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function configDir() {
|
|
23
|
+
return path.join(os.homedir(), '.ineedcodes');
|
|
24
|
+
}
|
|
25
|
+
export async function loadConfig() {
|
|
26
|
+
const file = path.join(configDir(), 'config.json');
|
|
27
|
+
const loaded = await readJson(file);
|
|
28
|
+
const base = defaultConfig();
|
|
29
|
+
if (!loaded)
|
|
30
|
+
return base;
|
|
31
|
+
return {
|
|
32
|
+
...base,
|
|
33
|
+
...loaded,
|
|
34
|
+
permissions: { ...base.permissions, ...(loaded.permissions ?? {}) },
|
|
35
|
+
memory: { ...base.memory, ...(loaded.memory ?? {}) },
|
|
36
|
+
providers: { ...base.providers, ...(loaded.providers ?? {}) }
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export async function saveConfig(config) {
|
|
40
|
+
const { writeJson } = await import('../util/fs.js');
|
|
41
|
+
await writeJson(path.join(configDir(), 'config.json'), config);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AA0BzC,MAAM,UAAU,aAAa;IAC3B,OAAO;QACL,SAAS,EAAE;YACT,OAAO,EAAE;gBACP,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,2BAA2B;gBAC1E,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;gBAC1E,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,cAAc;gBACxD,UAAU,EAAE,CAAC;aACd;SACF;QACD,eAAe,EAAE,SAAS;QAC1B,WAAW,EAAE;YACX,IAAI,EAAE,WAAW;YACjB,iBAAiB,EAAE,CAAC;SACrB;QACD,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;KAC3B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,aAAa,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAA4B,IAAI,CAAC,CAAC;IAC/D,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,OAAO;QACL,GAAG,IAAI;QACP,GAAG,MAAM;QACT,WAAW,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE;QACnE,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE;QACpD,SAAS,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE;KAC9D,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAwB;IACvD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;IACpD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ChatMessage, ContextCheckpoint } from '../types.js';
|
|
2
|
+
export declare function estimateTokens(text: string): number;
|
|
3
|
+
export declare class ContextEngine {
|
|
4
|
+
private contextLimit;
|
|
5
|
+
/** Fraction of the limit at which compaction triggers. */
|
|
6
|
+
private readonly compactAt;
|
|
7
|
+
private history;
|
|
8
|
+
constructor(contextLimit: number,
|
|
9
|
+
/** Fraction of the limit at which compaction triggers. */
|
|
10
|
+
compactAt?: number);
|
|
11
|
+
get messages(): readonly ChatMessage[];
|
|
12
|
+
setMessages(messages: ChatMessage[]): void;
|
|
13
|
+
append(message: ChatMessage): void;
|
|
14
|
+
replaceLastAssistant(content: string): void;
|
|
15
|
+
estimatedTokens(): number;
|
|
16
|
+
needsCompaction(): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Create a factual checkpoint of the current session, drop redundant raw
|
|
19
|
+
* history, and continue. Does NOT touch ICM long-term memory.
|
|
20
|
+
*/
|
|
21
|
+
compact(summarize: (messages: readonly ChatMessage[]) => Promise<ContextCheckpoint>): Promise<ContextCheckpoint>;
|
|
22
|
+
private compactAsync;
|
|
23
|
+
}
|
|
24
|
+
/** Deterministic fallback summarizer when the model call is not desired. */
|
|
25
|
+
export declare function heuristicCheckpoint(messages: readonly ChatMessage[]): ContextCheckpoint;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Context Engine manages the *current* model context.
|
|
3
|
+
* ICM is long-term memory; this is working memory. They stay separate.
|
|
4
|
+
*
|
|
5
|
+
* It tracks conversation, project instructions, relevant memory, tool
|
|
6
|
+
* results, and sub-agent results: and compacts when approaching the
|
|
7
|
+
* model's context limit (plan §31–32).
|
|
8
|
+
*/
|
|
9
|
+
const ROUGH_CHARS_PER_TOKEN = 4;
|
|
10
|
+
export function estimateTokens(text) {
|
|
11
|
+
return Math.ceil(text.length / ROUGH_CHARS_PER_TOKEN);
|
|
12
|
+
}
|
|
13
|
+
export class ContextEngine {
|
|
14
|
+
contextLimit;
|
|
15
|
+
compactAt;
|
|
16
|
+
history = [];
|
|
17
|
+
constructor(contextLimit,
|
|
18
|
+
/** Fraction of the limit at which compaction triggers. */
|
|
19
|
+
compactAt = 0.75) {
|
|
20
|
+
this.contextLimit = contextLimit;
|
|
21
|
+
this.compactAt = compactAt;
|
|
22
|
+
}
|
|
23
|
+
get messages() {
|
|
24
|
+
return this.history;
|
|
25
|
+
}
|
|
26
|
+
setMessages(messages) {
|
|
27
|
+
this.history = [...messages];
|
|
28
|
+
}
|
|
29
|
+
append(message) {
|
|
30
|
+
this.history.push(message);
|
|
31
|
+
}
|
|
32
|
+
replaceLastAssistant(content) {
|
|
33
|
+
for (let i = this.history.length - 1; i >= 0; i--) {
|
|
34
|
+
const m = this.history[i];
|
|
35
|
+
if (m && m.role === 'assistant') {
|
|
36
|
+
this.history[i] = { ...m, content };
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
estimatedTokens() {
|
|
42
|
+
let total = 0;
|
|
43
|
+
for (const m of this.history) {
|
|
44
|
+
total += estimateTokens(m.content ?? '');
|
|
45
|
+
for (const tc of m.toolCalls ?? []) {
|
|
46
|
+
total += estimateTokens(tc.arguments) + estimateTokens(tc.name);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return total;
|
|
50
|
+
}
|
|
51
|
+
needsCompaction() {
|
|
52
|
+
return this.estimatedTokens() > this.contextLimit * this.compactAt;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create a factual checkpoint of the current session, drop redundant raw
|
|
56
|
+
* history, and continue. Does NOT touch ICM long-term memory.
|
|
57
|
+
*/
|
|
58
|
+
compact(summarize) {
|
|
59
|
+
return this.compactAsync(summarize);
|
|
60
|
+
}
|
|
61
|
+
async compactAsync(summarize) {
|
|
62
|
+
const keepRecent = 6;
|
|
63
|
+
const head = this.history.slice(0, Math.max(0, this.history.length - keepRecent));
|
|
64
|
+
const recent = this.history.slice(-keepRecent);
|
|
65
|
+
const checkpoint = await summarize(head);
|
|
66
|
+
const checkpointText = [
|
|
67
|
+
`[Session checkpoint: earlier conversation compacted]`,
|
|
68
|
+
`Objective: ${checkpoint.objective}`,
|
|
69
|
+
checkpoint.decisions.length ? `Decisions so far:\n- ${checkpoint.decisions.join('\n- ')}` : '',
|
|
70
|
+
checkpoint.unresolved.length ? `Unresolved:\n- ${checkpoint.unresolved.join('\n- ')}` : '',
|
|
71
|
+
checkpoint.recentSummary ? `Recent work: ${checkpoint.recentSummary}` : ''
|
|
72
|
+
].filter(Boolean).join('\n');
|
|
73
|
+
this.history = [
|
|
74
|
+
...this.history.slice(0, 1), // keep the original system message
|
|
75
|
+
{ role: 'user', content: checkpointText },
|
|
76
|
+
...recent
|
|
77
|
+
];
|
|
78
|
+
return checkpoint;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Deterministic fallback summarizer when the model call is not desired. */
|
|
82
|
+
export function heuristicCheckpoint(messages) {
|
|
83
|
+
const userMessages = messages.filter((m) => m.role === 'user' && m.content).map((m) => m.content);
|
|
84
|
+
const toolResults = messages.filter((m) => m.role === 'tool' && m.content).map((m) => m.content);
|
|
85
|
+
const decisions = [];
|
|
86
|
+
for (const t of toolResults.slice(-20)) {
|
|
87
|
+
if (t.includes('exitCode": 0') || t.includes('Patched') || t.includes('Wrote')) {
|
|
88
|
+
decisions.push(t.split('\n')[0]?.slice(0, 200) ?? '');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
objective: userMessages[0]?.slice(0, 500) ?? '(unknown objective)',
|
|
93
|
+
decisions: decisions.filter(Boolean).slice(0, 10),
|
|
94
|
+
unresolved: [],
|
|
95
|
+
recentSummary: `Compacted ${messages.length} earlier messages.`
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/context/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './config/config.js';
|
|
3
|
+
export * from './workspace/workspace.js';
|
|
4
|
+
export * from './permissions/permissions.js';
|
|
5
|
+
export * from './security/secrets.js';
|
|
6
|
+
export * from './shell/process.js';
|
|
7
|
+
export * from './tools/registry.js';
|
|
8
|
+
export * from './tools/fs.js';
|
|
9
|
+
export * from './tools/search.js';
|
|
10
|
+
export * from './tools/shell.js';
|
|
11
|
+
export * from './tools/git.js';
|
|
12
|
+
export * from './tools/web.js';
|
|
13
|
+
export * from './tools/mcp.js';
|
|
14
|
+
export * from './llm/openai-compatible.js';
|
|
15
|
+
export * from './memory/icm-adapter.js';
|
|
16
|
+
export * from './context/engine.js';
|
|
17
|
+
export * from './session/store.js';
|
|
18
|
+
export * from './skills/loader.js';
|
|
19
|
+
export * from './util/fs.js';
|
|
20
|
+
export * from './util/shell-quote.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './config/config.js';
|
|
3
|
+
export * from './workspace/workspace.js';
|
|
4
|
+
export * from './permissions/permissions.js';
|
|
5
|
+
export * from './security/secrets.js';
|
|
6
|
+
export * from './shell/process.js';
|
|
7
|
+
export * from './tools/registry.js';
|
|
8
|
+
export * from './tools/fs.js';
|
|
9
|
+
export * from './tools/search.js';
|
|
10
|
+
export * from './tools/shell.js';
|
|
11
|
+
export * from './tools/git.js';
|
|
12
|
+
export * from './tools/web.js';
|
|
13
|
+
export * from './tools/mcp.js';
|
|
14
|
+
export * from './llm/openai-compatible.js';
|
|
15
|
+
export * from './memory/icm-adapter.js';
|
|
16
|
+
export * from './context/engine.js';
|
|
17
|
+
export * from './session/store.js';
|
|
18
|
+
export * from './skills/loader.js';
|
|
19
|
+
export * from './util/fs.js';
|
|
20
|
+
export * from './util/shell-quote.js';
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ChatRequest, ChatResponse, LLMProvider, LLMProviderConfig } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* OpenAI-compatible chat-completions provider. Works with any endpoint that
|
|
4
|
+
* implements POST /chat/completions with streaming SSE and tool calling.
|
|
5
|
+
* Supports the iNeed API through the same interface without hardcoding it.
|
|
6
|
+
*/
|
|
7
|
+
export interface LLMProviderWithConfig extends LLMProvider {
|
|
8
|
+
config: LLMProviderConfig;
|
|
9
|
+
}
|
|
10
|
+
export declare class OpenAICompatibleProvider implements LLMProviderWithConfig {
|
|
11
|
+
readonly config: LLMProviderConfig;
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly model: string;
|
|
14
|
+
readonly contextLimit: number;
|
|
15
|
+
private readonly temperature;
|
|
16
|
+
private readonly maxRetries;
|
|
17
|
+
constructor(config: LLMProviderConfig, providerId?: string);
|
|
18
|
+
complete(request: ChatRequest): Promise<ChatResponse>;
|
|
19
|
+
private attempt;
|
|
20
|
+
private consumeStream;
|
|
21
|
+
private endpointUrl;
|
|
22
|
+
}
|
|
23
|
+
export declare function createProvider(config: LLMProviderConfig, id: string): LLMProviderWithConfig;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
export class OpenAICompatibleProvider {
|
|
2
|
+
config;
|
|
3
|
+
id;
|
|
4
|
+
model;
|
|
5
|
+
contextLimit;
|
|
6
|
+
temperature;
|
|
7
|
+
maxRetries;
|
|
8
|
+
constructor(config, providerId = 'openai-compatible') {
|
|
9
|
+
this.config = config;
|
|
10
|
+
this.id = providerId;
|
|
11
|
+
this.model = config.model;
|
|
12
|
+
this.contextLimit = config.contextLimit ?? 128_000;
|
|
13
|
+
this.temperature = config.temperature ?? 0.2;
|
|
14
|
+
this.maxRetries = config.maxRetries ?? 2;
|
|
15
|
+
}
|
|
16
|
+
async complete(request) {
|
|
17
|
+
let lastError;
|
|
18
|
+
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
19
|
+
try {
|
|
20
|
+
return await this.attempt(request);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
24
|
+
if (request.signal?.aborted)
|
|
25
|
+
throw lastError;
|
|
26
|
+
const retriable = /timeout|econn|fetch failed|5\d\d|rate limit|overloaded/i.test(lastError.message);
|
|
27
|
+
if (!retriable || attempt === this.maxRetries)
|
|
28
|
+
break;
|
|
29
|
+
await sleep(500 * Math.pow(2, attempt));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
throw lastError ?? new Error('LLM request failed');
|
|
33
|
+
}
|
|
34
|
+
async attempt(request) {
|
|
35
|
+
const apiKey = this.config.apiKey;
|
|
36
|
+
if (!apiKey) {
|
|
37
|
+
throw new Error('No API key configured. Set INEEDCODES_API_KEY (or add a provider in ~/.ineedcodes/config.json).');
|
|
38
|
+
}
|
|
39
|
+
const body = {
|
|
40
|
+
model: this.model,
|
|
41
|
+
messages: request.messages.map(toWire),
|
|
42
|
+
temperature: request.temperature ?? this.temperature,
|
|
43
|
+
max_tokens: request.maxTokens,
|
|
44
|
+
stream: true,
|
|
45
|
+
stream_options: { include_usage: true }
|
|
46
|
+
};
|
|
47
|
+
if (request.tools?.length) {
|
|
48
|
+
body.tools = request.tools.map((t) => ({
|
|
49
|
+
type: 'function',
|
|
50
|
+
function: { name: t.name, description: t.description, parameters: t.inputSchema }
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
// Reasoning effort must actually change provider behavior.
|
|
54
|
+
// GLM 5.3-style models ALWAYS think and reject thinking:disabled: they accept
|
|
55
|
+
// effort levels (low/high/max) instead. So:
|
|
56
|
+
// - reasoning_effort: always sent when the user picked a level (OpenAI o-series reads this)
|
|
57
|
+
// - thinking.enabled: only for medium/high; LOW omits the switch entirely
|
|
58
|
+
// (sending disabled makes always-thinking models return HTTP 400)
|
|
59
|
+
if (request.reasoningEffort) {
|
|
60
|
+
body.reasoning_effort = request.reasoningEffort;
|
|
61
|
+
if (request.reasoningEffort !== 'low') {
|
|
62
|
+
body['thinking'] = { type: 'enabled' };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const controller = new AbortController();
|
|
66
|
+
const onAbort = () => controller.abort();
|
|
67
|
+
request.signal?.addEventListener('abort', onAbort, { once: true });
|
|
68
|
+
const timeout = setTimeout(() => controller.abort(), 180_000);
|
|
69
|
+
try {
|
|
70
|
+
const res = await fetch(this.endpointUrl('/chat/completions'), {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
signal: controller.signal,
|
|
73
|
+
headers: {
|
|
74
|
+
'content-type': 'application/json',
|
|
75
|
+
'authorization': `Bearer ${apiKey}`
|
|
76
|
+
},
|
|
77
|
+
body: JSON.stringify(body)
|
|
78
|
+
});
|
|
79
|
+
if (!res.ok || !res.body) {
|
|
80
|
+
const text = await res.text().catch(() => '');
|
|
81
|
+
throw new Error(`Provider HTTP ${res.status}: ${text.slice(0, 500) || res.statusText}`);
|
|
82
|
+
}
|
|
83
|
+
return await this.consumeStream(res.body);
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
clearTimeout(timeout);
|
|
87
|
+
request.signal?.removeEventListener('abort', onAbort);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async consumeStream(body) {
|
|
91
|
+
const reader = body.getReader();
|
|
92
|
+
const decoder = new TextDecoder();
|
|
93
|
+
let buffer = '';
|
|
94
|
+
let content = '';
|
|
95
|
+
let finishReason = null;
|
|
96
|
+
let usage;
|
|
97
|
+
const toolCalls = new Map();
|
|
98
|
+
while (true) {
|
|
99
|
+
const { done, value } = await reader.read();
|
|
100
|
+
if (done)
|
|
101
|
+
break;
|
|
102
|
+
buffer += decoder.decode(value, { stream: true });
|
|
103
|
+
let newlineIndex;
|
|
104
|
+
while ((newlineIndex = buffer.indexOf('\n')) >= 0) {
|
|
105
|
+
const line = buffer.slice(0, newlineIndex).trim();
|
|
106
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
107
|
+
if (!line.startsWith('data:'))
|
|
108
|
+
continue;
|
|
109
|
+
const payload = line.slice(5).trim();
|
|
110
|
+
if (payload === '[DONE]')
|
|
111
|
+
continue;
|
|
112
|
+
let chunk;
|
|
113
|
+
try {
|
|
114
|
+
chunk = JSON.parse(payload);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
continue; // ignore malformed SSE fragments
|
|
118
|
+
}
|
|
119
|
+
if (chunk.usage)
|
|
120
|
+
usage = chunk.usage;
|
|
121
|
+
const choice = chunk.choices?.[0];
|
|
122
|
+
const delta = choice?.delta;
|
|
123
|
+
const reason = choice?.finish_reason ?? delta?.finish_reason;
|
|
124
|
+
if (reason)
|
|
125
|
+
finishReason = reason;
|
|
126
|
+
if (delta?.content)
|
|
127
|
+
content += delta.content;
|
|
128
|
+
for (const tc of delta?.tool_calls ?? []) {
|
|
129
|
+
const existing = toolCalls.get(tc.index) ?? { id: tc.id ?? `call_${tc.index}`, name: '', args: '' };
|
|
130
|
+
if (tc.id)
|
|
131
|
+
existing.id = tc.id;
|
|
132
|
+
if (tc.function?.name)
|
|
133
|
+
existing.name += tc.function.name;
|
|
134
|
+
if (tc.function?.arguments)
|
|
135
|
+
existing.args += tc.function.arguments;
|
|
136
|
+
toolCalls.set(tc.index, existing);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const calls = [...toolCalls.values()]
|
|
141
|
+
.sort((a, b) => a.id.localeCompare(b.id))
|
|
142
|
+
.map((tc) => ({ id: tc.id, name: tc.name, arguments: tc.args || '{}' }));
|
|
143
|
+
return {
|
|
144
|
+
content: content || null,
|
|
145
|
+
toolCalls: calls,
|
|
146
|
+
usage
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
endpointUrl(path) {
|
|
150
|
+
const base = this.config.baseUrl.replace(/\/+$/, '');
|
|
151
|
+
return `${base}${path}`;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function toWire(message) {
|
|
155
|
+
if (message.role === 'tool') {
|
|
156
|
+
return { role: 'tool', content: message.content ?? '', tool_call_id: message.toolCallId };
|
|
157
|
+
}
|
|
158
|
+
if (message.role === 'assistant' && message.toolCalls?.length) {
|
|
159
|
+
return {
|
|
160
|
+
role: 'assistant',
|
|
161
|
+
content: message.content,
|
|
162
|
+
tool_calls: message.toolCalls.map((tc) => ({
|
|
163
|
+
id: tc.id,
|
|
164
|
+
type: 'function',
|
|
165
|
+
function: { name: tc.name, arguments: tc.arguments }
|
|
166
|
+
}))
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
return { role: message.role, content: message.content };
|
|
170
|
+
}
|
|
171
|
+
function sleep(ms) {
|
|
172
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
173
|
+
}
|
|
174
|
+
export function createProvider(config, id) {
|
|
175
|
+
return new OpenAICompatibleProvider(config, id);
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=openai-compatible.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-compatible.js","sourceRoot":"","sources":["../../src/llm/openai-compatible.ts"],"names":[],"mappings":"AAcA,MAAM,OAAO,wBAAwB;IAOd;IANZ,EAAE,CAAS;IACX,KAAK,CAAS;IACd,YAAY,CAAS;IACb,WAAW,CAAS;IACpB,UAAU,CAAS;IAEpC,YAAqB,MAAyB,EAAE,UAAU,GAAG,mBAAmB;QAA3D,WAAM,GAAN,MAAM,CAAmB;QAC5C,IAAI,CAAC,EAAE,GAAG,UAAU,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,OAAO,CAAC;QACnD,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,GAAG,CAAC;QAC7C,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAoB;QACjC,IAAI,SAA4B,CAAC;QACjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;YAC5D,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACrC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,SAAS,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAChE,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;oBAAE,MAAM,SAAS,CAAC;gBAC7C,MAAM,SAAS,GAAG,yDAAyD,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;gBACpG,IAAI,CAAC,SAAS,IAAI,OAAO,KAAK,IAAI,CAAC,UAAU;oBAAE,MAAM;gBACrD,MAAM,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QACD,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACrD,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,OAAoB;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,iGAAiG,CAAC,CAAC;QACrH,CAAC;QAED,MAAM,IAAI,GAA4B;YACpC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;YACtC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW;YACpD,UAAU,EAAE,OAAO,CAAC,SAAS;YAC7B,MAAM,EAAE,IAAI;YACZ,cAAc,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE;SACxC,CAAC;QACF,IAAI,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACrC,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,WAAW,EAAE;aAClF,CAAC,CAAC,CAAC;QACN,CAAC;QACD,2DAA2D;QAC3D,8EAA8E;QAC9E,4CAA4C;QAC5C,4FAA4F;QAC5F,0EAA0E;QAC1E,oEAAoE;QACpE,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;YAChD,IAAI,OAAO,CAAC,eAAe,KAAK,KAAK,EAAE,CAAC;gBACtC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;YACzC,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACzC,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAE9D,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,EAAE;gBAC7D,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,UAAU,CAAC,MAAM;gBACzB,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,eAAe,EAAE,UAAU,MAAM,EAAE;iBACpC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YAEH,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;gBACzB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBAC9C,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YAC1F,CAAC;YAED,OAAO,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,IAAgC;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI,YAAY,GAAkB,IAAI,CAAC;QACvC,IAAI,KAA4B,CAAC;QACjC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAsD,CAAC;QAEhF,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAChB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,IAAI,YAAoB,CAAC;YACzB,OAAO,CAAC,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC;gBAClD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;gBACxC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;oBAAE,SAAS;gBACxC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBACrC,IAAI,OAAO,KAAK,QAAQ;oBAAE,SAAS;gBACnC,IAAI,KAcH,CAAC;gBACF,IAAI,CAAC;oBACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAC9B,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS,CAAC,iCAAiC;gBAC7C,CAAC;gBACD,IAAI,KAAK,CAAC,KAAK;oBAAE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;gBACrC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;gBAClC,MAAM,KAAK,GAAG,MAAM,EAAE,KAAK,CAAC;gBAC5B,MAAM,MAAM,GAAG,MAAM,EAAE,aAAa,IAAI,KAAK,EAAE,aAAa,CAAC;gBAC7D,IAAI,MAAM;oBAAE,YAAY,GAAG,MAAM,CAAC;gBAClC,IAAI,KAAK,EAAE,OAAO;oBAAE,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC;gBAC7C,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,UAAU,IAAI,EAAE,EAAE,CAAC;oBACzC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;oBACpG,IAAI,EAAE,CAAC,EAAE;wBAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;oBAC/B,IAAI,EAAE,CAAC,QAAQ,EAAE,IAAI;wBAAE,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;oBACzD,IAAI,EAAE,CAAC,QAAQ,EAAE,SAAS;wBAAE,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;oBACnE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBACpC,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAmB,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC;aAClD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;aACxC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;QAE3E,OAAO;YACL,OAAO,EAAE,OAAO,IAAI,IAAI;YACxB,SAAS,EAAE,KAAK;YAChB,KAAK;SACN,CAAC;IACJ,CAAC;IAEO,WAAW,CAAC,IAAY;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACrD,OAAO,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;IAC1B,CAAC;CACF;AAED,SAAS,MAAM,CAAC,OAAoB;IAClC,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,YAAY,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;IAC5F,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;QAC9D,OAAO;YACL,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBACzC,EAAE,EAAE,EAAE,CAAC,EAAE;gBACT,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE;aACrD,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;AAC1D,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAyB,EAAE,EAAU;IAClE,OAAO,IAAI,wBAAwB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { MemoryProvider, MemoryRecord } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Memory abstraction. The rest of iNeedCodes depends on this interface,
|
|
4
|
+
* never on ICM internals.
|
|
5
|
+
*/
|
|
6
|
+
export type { MemoryProvider, MemoryRecord };
|
|
7
|
+
/** Disabled memory backend: no-ops, never fails. */
|
|
8
|
+
export declare class OffMemoryProvider implements MemoryProvider {
|
|
9
|
+
readonly id = "off";
|
|
10
|
+
recall(): Promise<MemoryRecord[]>;
|
|
11
|
+
remember(content: string): Promise<MemoryRecord>;
|
|
12
|
+
forget(): Promise<boolean>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* ICM adapter (rtk-ai/icm). Uses the `icm` CLI as the memory engine.
|
|
16
|
+
* Per-project isolation: every project gets its own ICM database under
|
|
17
|
+
* ~/.ineedcodes/projects/<project-id>/memory/ (plan §13).
|
|
18
|
+
*/
|
|
19
|
+
export declare class ICMAdapter implements MemoryProvider {
|
|
20
|
+
private readonly databasePath;
|
|
21
|
+
private readonly topic?;
|
|
22
|
+
readonly id = "icm";
|
|
23
|
+
constructor(databasePath: string, topic?: string | undefined);
|
|
24
|
+
static forProject(projectId: string, projectRoot: string): ICMAdapter;
|
|
25
|
+
private icm;
|
|
26
|
+
recall(query: string, limit?: number): Promise<MemoryRecord[]>;
|
|
27
|
+
remember(content: string, tags?: string[]): Promise<MemoryRecord>;
|
|
28
|
+
forget(id: string): Promise<boolean>;
|
|
29
|
+
}
|
|
30
|
+
export declare function parseRecallOutput(stdout: string): MemoryRecord[];
|
|
31
|
+
export declare function createMemoryProvider(backend: 'icm' | 'off', projectId: string, projectRoot: string): MemoryProvider;
|