@intrect/openswarm 0.3.0 → 0.4.3
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 +674 -21
- package/README.md +15 -1
- package/config.example.yaml +6 -1
- package/dist/adapters/agenticLoop.d.ts +90 -0
- package/dist/adapters/agenticLoop.d.ts.map +1 -0
- package/dist/adapters/agenticLoop.js +219 -0
- package/dist/adapters/agenticLoop.js.map +1 -0
- package/dist/adapters/base.d.ts.map +1 -1
- package/dist/adapters/base.js +5 -1
- package/dist/adapters/base.js.map +1 -1
- package/dist/adapters/envPath.d.ts +20 -0
- package/dist/adapters/envPath.d.ts.map +1 -0
- package/dist/adapters/envPath.js +49 -0
- package/dist/adapters/envPath.js.map +1 -0
- package/dist/adapters/gpt.d.ts +5 -1
- package/dist/adapters/gpt.d.ts.map +1 -1
- package/dist/adapters/gpt.js +59 -81
- package/dist/adapters/gpt.js.map +1 -1
- package/dist/adapters/local.d.ts +9 -0
- package/dist/adapters/local.d.ts.map +1 -1
- package/dist/adapters/local.js +91 -47
- package/dist/adapters/local.js.map +1 -1
- package/dist/adapters/tools.d.ts +30 -0
- package/dist/adapters/tools.d.ts.map +1 -0
- package/dist/adapters/tools.js +219 -0
- package/dist/adapters/tools.js.map +1 -0
- package/dist/adapters/types.d.ts +2 -0
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/agents/draftAnalyzer.d.ts +54 -0
- package/dist/agents/draftAnalyzer.d.ts.map +1 -0
- package/dist/agents/draftAnalyzer.js +251 -0
- package/dist/agents/draftAnalyzer.js.map +1 -0
- package/dist/agents/pairPipeline.d.ts +20 -1
- package/dist/agents/pairPipeline.d.ts.map +1 -1
- package/dist/agents/pairPipeline.js +100 -3
- package/dist/agents/pairPipeline.js.map +1 -1
- package/dist/agents/reviewer.d.ts.map +1 -1
- package/dist/agents/reviewer.js +1 -0
- package/dist/agents/reviewer.js.map +1 -1
- package/dist/agents/worker.d.ts +3 -0
- package/dist/agents/worker.d.ts.map +1 -1
- package/dist/agents/worker.js +2 -0
- package/dist/agents/worker.js.map +1 -1
- package/dist/automation/autonomousRunner.d.ts +9 -0
- package/dist/automation/autonomousRunner.d.ts.map +1 -1
- package/dist/automation/autonomousRunner.js +18 -4
- package/dist/automation/autonomousRunner.js.map +1 -1
- package/dist/automation/longRunningMonitor.d.ts.map +1 -1
- package/dist/automation/longRunningMonitor.js +128 -8
- package/dist/automation/longRunningMonitor.js.map +1 -1
- package/dist/automation/runnerExecution.d.ts +6 -1
- package/dist/automation/runnerExecution.d.ts.map +1 -1
- package/dist/automation/runnerExecution.js +46 -5
- package/dist/automation/runnerExecution.js.map +1 -1
- package/dist/automation/runnerState.d.ts.map +1 -1
- package/dist/automation/runnerState.js +1 -2
- package/dist/automation/runnerState.js.map +1 -1
- package/dist/automation/scheduler.d.ts.map +1 -1
- package/dist/automation/scheduler.js +13 -6
- package/dist/automation/scheduler.js.map +1 -1
- package/dist/cli/checkHandler.d.ts +2 -0
- package/dist/cli/checkHandler.d.ts.map +1 -1
- package/dist/cli/checkHandler.js +96 -1
- package/dist/cli/checkHandler.js.map +1 -1
- package/dist/cli/daemon.d.ts +30 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/daemon.js +141 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli.js +100 -6
- package/dist/cli.js.map +1 -1
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +44 -11
- package/dist/core/config.js.map +1 -1
- package/dist/core/envFile.d.ts +11 -0
- package/dist/core/envFile.d.ts.map +1 -0
- package/dist/core/envFile.js +99 -0
- package/dist/core/envFile.js.map +1 -0
- package/dist/core/service.d.ts.map +1 -1
- package/dist/core/service.js +8 -2
- package/dist/core/service.js.map +1 -1
- package/dist/core/types.d.ts +6 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.js +32 -1
- package/dist/index.js.map +1 -1
- package/dist/issues/graphql/resolvers.d.ts +2 -2
- package/dist/issues/schema.d.ts +1 -1
- package/dist/knowledge/index.js +5 -5
- package/dist/knowledge/index.js.map +1 -1
- package/dist/knowledge/store.d.ts.map +1 -1
- package/dist/knowledge/store.js +34 -6
- package/dist/knowledge/store.js.map +1 -1
- package/dist/linear/linear.d.ts.map +1 -1
- package/dist/linear/linear.js +58 -19
- package/dist/linear/linear.js.map +1 -1
- package/dist/locale/prompts/en.d.ts.map +1 -1
- package/dist/locale/prompts/en.js +95 -93
- package/dist/locale/prompts/en.js.map +1 -1
- package/dist/locale/prompts/ko.d.ts.map +1 -1
- package/dist/locale/prompts/ko.js +95 -93
- package/dist/locale/prompts/ko.js.map +1 -1
- package/dist/locale/types.d.ts +40 -0
- package/dist/locale/types.d.ts.map +1 -1
- package/dist/registry/graphql/resolvers.d.ts +15 -15
- package/dist/registry/schema.d.ts +4 -4
- package/dist/support/planner.d.ts +8 -0
- package/dist/support/planner.d.ts.map +1 -1
- package/dist/support/planner.js +3 -1
- package/dist/support/planner.js.map +1 -1
- package/dist/support/web.d.ts.map +1 -1
- package/dist/support/web.js +56 -19
- package/dist/support/web.js.map +1 -1
- package/dist/taskState/store.d.ts.map +1 -1
- package/dist/taskState/store.js +6 -2
- package/dist/taskState/store.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -3,9 +3,23 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@intrect/openswarm)
|
|
4
4
|
[](https://www.npmjs.com/package/@intrect/openswarm)
|
|
5
5
|
[](LICENSE)
|
|
6
|
+
[](https://ko-fi.com/unohee)
|
|
6
7
|
|
|
7
8
|
> Autonomous AI agent orchestrator — Claude, GPT, Codex, and local models (Ollama/LMStudio/llama.cpp)
|
|
8
9
|
|
|
10
|
+
## Sponsor
|
|
11
|
+
|
|
12
|
+
OpenSwarm is developed and maintained in my spare time by a single author.
|
|
13
|
+
If the project saves you time or money, please consider chipping in —
|
|
14
|
+
it directly funds ongoing updates, bug fixes, and new adapters.
|
|
15
|
+
|
|
16
|
+
[](https://ko-fi.com/unohee)
|
|
17
|
+
|
|
18
|
+
One-off contributions are perfectly fine — there is no subscription
|
|
19
|
+
tier and no feature is paywalled. Thank you.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
9
23
|
OpenSwarm orchestrates multiple AI agents as autonomous code workers. It picks up Linear issues, runs Worker/Reviewer pair pipelines, reports to Discord, and retains long-term memory via LanceDB. Supports Claude Code, OpenAI GPT, Codex, and **local open-source models** via Ollama, LMStudio, or llama.cpp.
|
|
10
24
|
|
|
11
25
|
## Quick Start
|
|
@@ -446,4 +460,4 @@ src/
|
|
|
446
460
|
|
|
447
461
|
## License
|
|
448
462
|
|
|
449
|
-
|
|
463
|
+
GPL-3.0
|
package/config.example.yaml
CHANGED
|
@@ -109,11 +109,16 @@ autonomous:
|
|
|
109
109
|
reviewer: claude-sonnet-4-20250514 # Sonnet reviews Sonnet
|
|
110
110
|
|
|
111
111
|
# Long-running task monitoring (RunPod training, batch processing, etc.)
|
|
112
|
+
#
|
|
113
|
+
# checkCommand is a literal argv array — no shell is invoked, so pipes,
|
|
114
|
+
# redirects, and substitutions do not work. Put shell logic in a script
|
|
115
|
+
# you control and call that script instead (e.g. ["/opt/probe.sh", "arg"]).
|
|
116
|
+
#
|
|
112
117
|
# monitors:
|
|
113
118
|
# - id: runpod-training
|
|
114
119
|
# name: "LSTM model training"
|
|
115
120
|
# issueId: INT-456
|
|
116
|
-
# checkCommand:
|
|
121
|
+
# checkCommand: ["ssh", "runpod", "tail -1 /workspace/train.log"]
|
|
117
122
|
# completionCheck:
|
|
118
123
|
# type: output-regex
|
|
119
124
|
# successPattern: "Training finished"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { type ToolDefinition } from './tools.js';
|
|
2
|
+
import type { CliRunResult } from './types.js';
|
|
3
|
+
/** OpenAI Chat Completions API 메시지 포맷 */
|
|
4
|
+
export type ChatMessage = {
|
|
5
|
+
role: 'system';
|
|
6
|
+
content: string;
|
|
7
|
+
} | {
|
|
8
|
+
role: 'user';
|
|
9
|
+
content: string;
|
|
10
|
+
} | {
|
|
11
|
+
role: 'assistant';
|
|
12
|
+
content: string | null;
|
|
13
|
+
tool_calls?: ApiToolCall[];
|
|
14
|
+
} | {
|
|
15
|
+
role: 'tool';
|
|
16
|
+
tool_call_id: string;
|
|
17
|
+
content: string;
|
|
18
|
+
};
|
|
19
|
+
interface ApiToolCall {
|
|
20
|
+
id: string;
|
|
21
|
+
type: 'function';
|
|
22
|
+
function: {
|
|
23
|
+
name: string;
|
|
24
|
+
arguments: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
interface ChatCompletionResponse {
|
|
28
|
+
choices: Array<{
|
|
29
|
+
message: {
|
|
30
|
+
role: string;
|
|
31
|
+
content: string | null;
|
|
32
|
+
tool_calls?: ApiToolCall[];
|
|
33
|
+
};
|
|
34
|
+
finish_reason: string;
|
|
35
|
+
}>;
|
|
36
|
+
usage?: {
|
|
37
|
+
prompt_tokens: number;
|
|
38
|
+
completion_tokens: number;
|
|
39
|
+
total_tokens: number;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** 에이전틱 루프 설정 */
|
|
43
|
+
export interface AgenticLoopOptions {
|
|
44
|
+
/** 시스템 프롬프트 */
|
|
45
|
+
systemPrompt?: string;
|
|
46
|
+
/** 사용자 프롬프트 (작업 지시) */
|
|
47
|
+
prompt: string;
|
|
48
|
+
/** 프로젝트 작업 디렉토리 (도구 실행 cwd) */
|
|
49
|
+
cwd: string;
|
|
50
|
+
/** 모델명 */
|
|
51
|
+
model: string;
|
|
52
|
+
/** API 호출 함수 (어댑터별로 주입) */
|
|
53
|
+
callApi: (messages: ChatMessage[], tools: ToolDefinition[]) => Promise<ChatCompletionResponse>;
|
|
54
|
+
/** 최대 도구 사용 턴 수 (기본: 15) */
|
|
55
|
+
maxTurns?: number;
|
|
56
|
+
/** 전체 타임아웃 (ms, 기본: 300000) */
|
|
57
|
+
timeoutMs?: number;
|
|
58
|
+
/** 실시간 로그 콜백 */
|
|
59
|
+
onLog?: (line: string) => void;
|
|
60
|
+
/** 도구 사용 허용 여부 (기본: true) */
|
|
61
|
+
enableTools?: boolean;
|
|
62
|
+
}
|
|
63
|
+
/** 루프 실행 결과 */
|
|
64
|
+
export interface AgenticLoopResult {
|
|
65
|
+
/** 최종 텍스트 응답 */
|
|
66
|
+
text: string;
|
|
67
|
+
/** 사용한 도구 호출 횟수 */
|
|
68
|
+
toolCallCount: number;
|
|
69
|
+
/** 총 API 호출 횟수 */
|
|
70
|
+
apiCallCount: number;
|
|
71
|
+
/** 총 토큰 사용량 (추적 가능한 경우) */
|
|
72
|
+
totalTokens: number;
|
|
73
|
+
/** 소요 시간 (ms) */
|
|
74
|
+
durationMs: number;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 에이전틱 도구 루프 실행
|
|
78
|
+
*
|
|
79
|
+
* 흐름:
|
|
80
|
+
* 1. 프롬프트로 API 호출 (도구 정의 포함)
|
|
81
|
+
* 2. 응답에 tool_calls가 있으면 → 도구 실행 → 결과를 메시지에 추가 → 2로
|
|
82
|
+
* 3. 응답에 tool_calls가 없으면 (finish_reason = 'stop') → 최종 텍스트 반환
|
|
83
|
+
*/
|
|
84
|
+
export declare function runAgenticLoop(options: AgenticLoopOptions): Promise<AgenticLoopResult>;
|
|
85
|
+
/**
|
|
86
|
+
* AgenticLoopResult → CliRunResult 변환
|
|
87
|
+
*/
|
|
88
|
+
export declare function loopResultToCliResult(result: AgenticLoopResult): CliRunResult;
|
|
89
|
+
export {};
|
|
90
|
+
//# sourceMappingURL=agenticLoop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agenticLoop.d.ts","sourceRoot":"","sources":["../../src/adapters/agenticLoop.ts"],"names":[],"mappings":"AAQA,OAAO,EAAsE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AACrH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI/C,yCAAyC;AACzC,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,UAAU,CAAC,EAAE,WAAW,EAAE,CAAA;CAAE,GACzE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,UAAU,sBAAsB;IAC9B,OAAO,EAAE,KAAK,CAAC;QACb,OAAO,EAAE;YACP,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;YACvB,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC;SAC5B,CAAC;QACF,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;IACH,KAAK,CAAC,EAAE;QACN,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,iBAAiB;AACjB,MAAM,WAAW,kBAAkB;IACjC,eAAe;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU;IACV,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,OAAO,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IAC/F,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,6BAA6B;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,eAAe;AACf,MAAM,WAAW,iBAAiB;IAChC,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAID;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0H5F;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG,YAAY,CAO7E"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// OpenSwarm - Agentic Tool Loop
|
|
3
|
+
// Created: 2026-04-11
|
|
4
|
+
// Purpose: GPT/Local 어댑터에 Claude CLI와 동등한 도구 사용 능력을 부여하는
|
|
5
|
+
// 범용 에이전틱 루프 엔진.
|
|
6
|
+
// OpenAI function calling 포맷 기반.
|
|
7
|
+
// ============================================
|
|
8
|
+
import { TOOL_DEFINITIONS, executeToolCalls } from './tools.js';
|
|
9
|
+
// ============ 에이전틱 루프 ============
|
|
10
|
+
/**
|
|
11
|
+
* 에이전틱 도구 루프 실행
|
|
12
|
+
*
|
|
13
|
+
* 흐름:
|
|
14
|
+
* 1. 프롬프트로 API 호출 (도구 정의 포함)
|
|
15
|
+
* 2. 응답에 tool_calls가 있으면 → 도구 실행 → 결과를 메시지에 추가 → 2로
|
|
16
|
+
* 3. 응답에 tool_calls가 없으면 (finish_reason = 'stop') → 최종 텍스트 반환
|
|
17
|
+
*/
|
|
18
|
+
export async function runAgenticLoop(options) {
|
|
19
|
+
const { systemPrompt, prompt, cwd, callApi, maxTurns = 15, timeoutMs = 300000, onLog, enableTools = true, } = options;
|
|
20
|
+
const startTime = Date.now();
|
|
21
|
+
const deadline = startTime + timeoutMs;
|
|
22
|
+
// 메시지 히스토리 구성
|
|
23
|
+
const messages = [];
|
|
24
|
+
if (systemPrompt) {
|
|
25
|
+
messages.push({ role: 'system', content: systemPrompt });
|
|
26
|
+
}
|
|
27
|
+
messages.push({ role: 'user', content: prompt });
|
|
28
|
+
const tools = enableTools ? TOOL_DEFINITIONS : [];
|
|
29
|
+
let toolCallCount = 0;
|
|
30
|
+
let apiCallCount = 0;
|
|
31
|
+
let totalTokens = 0;
|
|
32
|
+
let finalText = '';
|
|
33
|
+
for (let turn = 0; turn < maxTurns + 1; turn++) {
|
|
34
|
+
// 타임아웃 체크
|
|
35
|
+
if (Date.now() > deadline) {
|
|
36
|
+
onLog?.(`⏰ Agentic loop timeout after ${turn} turns`);
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
// 매 턴 히스토리 압축 — 이전 턴의 tool call/result를 1줄 요약으로 교체
|
|
40
|
+
if (turn >= 2) {
|
|
41
|
+
compactPriorTurns(messages);
|
|
42
|
+
}
|
|
43
|
+
// API 호출
|
|
44
|
+
apiCallCount++;
|
|
45
|
+
onLog?.(`▸ API call #${apiCallCount}${turn > 0 ? ` (tool turn ${turn})` : ''}`);
|
|
46
|
+
let response;
|
|
47
|
+
try {
|
|
48
|
+
response = await callApi(messages, tools);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
52
|
+
onLog?.(`✖ API error: ${msg}`);
|
|
53
|
+
finalText = `API error: ${msg}`;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
if (response.usage) {
|
|
57
|
+
totalTokens += response.usage.prompt_tokens + response.usage.completion_tokens;
|
|
58
|
+
}
|
|
59
|
+
const choice = response.choices?.[0];
|
|
60
|
+
if (!choice) {
|
|
61
|
+
onLog?.('✖ Empty response from API');
|
|
62
|
+
finalText = 'Empty API response';
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
const assistantMsg = choice.message;
|
|
66
|
+
// 도구 호출이 없으면 최종 응답
|
|
67
|
+
if (!assistantMsg.tool_calls || assistantMsg.tool_calls.length === 0) {
|
|
68
|
+
finalText = assistantMsg.content ?? '';
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
// 어시스턴트 메시지를 히스토리에 추가 (tool_calls 포함)
|
|
72
|
+
messages.push({
|
|
73
|
+
role: 'assistant',
|
|
74
|
+
content: assistantMsg.content,
|
|
75
|
+
tool_calls: assistantMsg.tool_calls,
|
|
76
|
+
});
|
|
77
|
+
// 도구 실행
|
|
78
|
+
const toolCalls = assistantMsg.tool_calls.map(tc => ({
|
|
79
|
+
id: tc.id,
|
|
80
|
+
function: {
|
|
81
|
+
name: tc.function.name,
|
|
82
|
+
arguments: tc.function.arguments,
|
|
83
|
+
},
|
|
84
|
+
}));
|
|
85
|
+
for (const tc of toolCalls) {
|
|
86
|
+
try {
|
|
87
|
+
const args = JSON.parse(tc.function.arguments);
|
|
88
|
+
const argSummary = summarizeToolArgs(tc.function.name, args);
|
|
89
|
+
onLog?.(` 🔧 ${tc.function.name}${argSummary ? ': ' + argSummary : ''}`);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
onLog?.(` 🔧 ${tc.function.name}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const results = await executeToolCalls(toolCalls, cwd);
|
|
96
|
+
toolCallCount += toolCalls.length;
|
|
97
|
+
// 도구 결과를 메시지에 추가
|
|
98
|
+
for (const result of results) {
|
|
99
|
+
messages.push({
|
|
100
|
+
role: 'tool',
|
|
101
|
+
tool_call_id: result.tool_call_id,
|
|
102
|
+
content: result.content,
|
|
103
|
+
});
|
|
104
|
+
if (result.is_error) {
|
|
105
|
+
onLog?.(` ✖ ${result.content.slice(0, 100)}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
text: finalText,
|
|
111
|
+
toolCallCount,
|
|
112
|
+
apiCallCount,
|
|
113
|
+
totalTokens,
|
|
114
|
+
durationMs: Date.now() - startTime,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* AgenticLoopResult → CliRunResult 변환
|
|
119
|
+
*/
|
|
120
|
+
export function loopResultToCliResult(result) {
|
|
121
|
+
return {
|
|
122
|
+
exitCode: 0,
|
|
123
|
+
stdout: result.text,
|
|
124
|
+
stderr: '',
|
|
125
|
+
durationMs: result.durationMs,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// ============ 히스토리 압축 ============
|
|
129
|
+
/**
|
|
130
|
+
* 최근 1턴(assistant + tool results)만 원본 유지.
|
|
131
|
+
* 그 이전 턴의 assistant+tool 쌍을 1줄 요약 assistant 메시지로 교체.
|
|
132
|
+
*
|
|
133
|
+
* 구조 변환:
|
|
134
|
+
* [system, user, asst(tool_calls), tool, tool, asst(tool_calls), tool, ...]
|
|
135
|
+
* → [system, user, asst("Prior: read_file→ok, edit→ok"), asst(latest_tool_calls), tool, ...]
|
|
136
|
+
*
|
|
137
|
+
* OpenAI API 제약: tool 메시지는 직전 assistant의 tool_call_id와 대응해야 함.
|
|
138
|
+
* 따라서 오래된 tool 메시지는 삭제하고, 해당 assistant도 일반 텍스트로 교체.
|
|
139
|
+
*/
|
|
140
|
+
function compactPriorTurns(messages) {
|
|
141
|
+
const headerCount = messages[0]?.role === 'system' ? 2 : 1;
|
|
142
|
+
// 마지막 assistant+tool 블록의 시작 인덱스 찾기
|
|
143
|
+
let lastAssistantIdx = -1;
|
|
144
|
+
for (let i = messages.length - 1; i >= headerCount; i--) {
|
|
145
|
+
if (messages[i].role === 'assistant') {
|
|
146
|
+
lastAssistantIdx = i;
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (lastAssistantIdx <= headerCount)
|
|
151
|
+
return; // 압축할 이전 턴이 없음
|
|
152
|
+
// headerCount ~ lastAssistantIdx 사이의 모든 assistant+tool 쌍을 요약
|
|
153
|
+
const summaryParts = [];
|
|
154
|
+
const toRemove = [];
|
|
155
|
+
for (let i = headerCount; i < lastAssistantIdx; i++) {
|
|
156
|
+
const msg = messages[i];
|
|
157
|
+
if (msg.role === 'assistant' && msg.tool_calls && msg.tool_calls.length > 0) {
|
|
158
|
+
// tool call 요약: "read_file(src/foo.ts), edit_file(src/foo.ts)"
|
|
159
|
+
const callSummaries = msg.tool_calls.map(tc => {
|
|
160
|
+
try {
|
|
161
|
+
const args = JSON.parse(tc.function.arguments);
|
|
162
|
+
const key = args.path || args.pattern || args.command;
|
|
163
|
+
const short = typeof key === 'string' ? key.slice(0, 50) : '';
|
|
164
|
+
return `${tc.function.name}(${short})`;
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return tc.function.name;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
summaryParts.push(callSummaries.join(', '));
|
|
171
|
+
toRemove.push(i);
|
|
172
|
+
}
|
|
173
|
+
else if (msg.role === 'tool') {
|
|
174
|
+
// tool result → 성공/실패만 기록
|
|
175
|
+
const ok = !msg.content.startsWith('BLOCKED') && !msg.content.startsWith('Tool error');
|
|
176
|
+
const firstLine = msg.content.split('\n')[0].slice(0, 60);
|
|
177
|
+
summaryParts.push(ok ? `→ok` : `→err: ${firstLine}`);
|
|
178
|
+
toRemove.push(i);
|
|
179
|
+
}
|
|
180
|
+
else if (msg.role === 'assistant' && !msg.tool_calls) {
|
|
181
|
+
// 일반 assistant 메시지 — 첫 줄만 유지
|
|
182
|
+
const short = (msg.content ?? '').split('\n')[0].slice(0, 80);
|
|
183
|
+
if (short)
|
|
184
|
+
summaryParts.push(`note: ${short}`);
|
|
185
|
+
toRemove.push(i);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (toRemove.length === 0)
|
|
189
|
+
return;
|
|
190
|
+
// 요약 메시지 생성
|
|
191
|
+
const summaryText = `[Prior turns compacted] ${summaryParts.join(' | ')}`;
|
|
192
|
+
// 역순으로 제거 (인덱스 안정성)
|
|
193
|
+
for (let i = toRemove.length - 1; i >= 0; i--) {
|
|
194
|
+
messages.splice(toRemove[i], 1);
|
|
195
|
+
}
|
|
196
|
+
// header 직후에 요약 삽입
|
|
197
|
+
messages.splice(headerCount, 0, {
|
|
198
|
+
role: 'assistant',
|
|
199
|
+
content: summaryText,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
// ============ 헬퍼 ============
|
|
203
|
+
function summarizeToolArgs(name, args) {
|
|
204
|
+
switch (name) {
|
|
205
|
+
case 'read_file':
|
|
206
|
+
return String(args.path ?? '');
|
|
207
|
+
case 'write_file':
|
|
208
|
+
return String(args.path ?? '');
|
|
209
|
+
case 'edit_file':
|
|
210
|
+
return String(args.path ?? '');
|
|
211
|
+
case 'search_files':
|
|
212
|
+
return `"${args.pattern}" in ${args.path}`;
|
|
213
|
+
case 'bash':
|
|
214
|
+
return String(args.command ?? '').slice(0, 80);
|
|
215
|
+
default:
|
|
216
|
+
return '';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=agenticLoop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agenticLoop.js","sourceRoot":"","sources":["../../src/adapters/agenticLoop.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK1E;;;;GAIG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CA0GvB"}
|
package/dist/adapters/base.js
CHANGED
|
@@ -6,6 +6,7 @@ import { spawn } from 'node:child_process';
|
|
|
6
6
|
import fs from 'node:fs/promises';
|
|
7
7
|
import { parseCliStreamChunk } from '../agents/cliStreamParser.js';
|
|
8
8
|
import { registerProcess } from './processRegistry.js';
|
|
9
|
+
import { buildWorkerEnv } from './envPath.js';
|
|
9
10
|
/**
|
|
10
11
|
* Spawn a CLI process using the given adapter and options.
|
|
11
12
|
* Handles: temp file write, spawn with shell, timeout/SIGKILL,
|
|
@@ -30,7 +31,10 @@ export async function spawnCli(adapter, options) {
|
|
|
30
31
|
const proc = spawn(cmd, {
|
|
31
32
|
shell: true,
|
|
32
33
|
cwd: options.cwd,
|
|
33
|
-
|
|
34
|
+
// Inject OpenSwarm's bundled node_modules/.bin (gives workers access
|
|
35
|
+
// to `cxt` and other shipped CLIs) without touching the user's shell
|
|
36
|
+
// PATH or ~/.claude/ config.
|
|
37
|
+
env: buildWorkerEnv(process.env),
|
|
34
38
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
35
39
|
});
|
|
36
40
|
// Register process for tracking if context provided
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,+BAA+B;AAC/B,0CAA0C;AAC1C,+CAA+C;AAE/C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve OpenSwarm's bundled `node_modules/.bin` directory.
|
|
3
|
+
*
|
|
4
|
+
* envPath.js lives at `<pkg>/dist/adapters/envPath.js` after build, so the
|
|
5
|
+
* package root is two directories up. During `npm run dev` / `tsx`, the file
|
|
6
|
+
* is at `<pkg>/src/adapters/envPath.ts` — same relative structure.
|
|
7
|
+
*
|
|
8
|
+
* Returns null if the .bin directory does not exist (e.g. dev checkout
|
|
9
|
+
* without `npm install`), so callers can fall back to process.env.PATH as-is.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getBundledBinDir(): string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Build an env object for spawned workers with OpenSwarm's bundled `.bin`
|
|
14
|
+
* directory prepended to PATH. Keeps every other env var untouched.
|
|
15
|
+
*
|
|
16
|
+
* Prepending (not appending) means a locally-bundled `cxt` wins over an
|
|
17
|
+
* older global install, which matters when we start pinning cxt versions.
|
|
18
|
+
*/
|
|
19
|
+
export declare function buildWorkerEnv(base?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
20
|
+
//# sourceMappingURL=envPath.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envPath.d.ts","sourceRoot":"","sources":["../../src/adapters/envPath.ts"],"names":[],"mappings":"AAcA;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAKhD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAAC,UAAU,CAavF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// OpenSwarm - Worker environment PATH helper
|
|
3
|
+
// ============================================
|
|
4
|
+
//
|
|
5
|
+
// Workers spawned by OpenSwarm need access to bundled CLI dependencies
|
|
6
|
+
// (notably `cxt` from @intrect/cxt) without the user having them installed
|
|
7
|
+
// globally. We inject OpenSwarm's own `node_modules/.bin` into PATH for the
|
|
8
|
+
// spawned process only — user's shell PATH and ~/.claude/* are untouched.
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
10
|
+
import { dirname, join, resolve } from 'node:path';
|
|
11
|
+
import { delimiter } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
/**
|
|
14
|
+
* Resolve OpenSwarm's bundled `node_modules/.bin` directory.
|
|
15
|
+
*
|
|
16
|
+
* envPath.js lives at `<pkg>/dist/adapters/envPath.js` after build, so the
|
|
17
|
+
* package root is two directories up. During `npm run dev` / `tsx`, the file
|
|
18
|
+
* is at `<pkg>/src/adapters/envPath.ts` — same relative structure.
|
|
19
|
+
*
|
|
20
|
+
* Returns null if the .bin directory does not exist (e.g. dev checkout
|
|
21
|
+
* without `npm install`), so callers can fall back to process.env.PATH as-is.
|
|
22
|
+
*/
|
|
23
|
+
export function getBundledBinDir() {
|
|
24
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
25
|
+
const pkgRoot = resolve(here, '..', '..');
|
|
26
|
+
const binDir = join(pkgRoot, 'node_modules', '.bin');
|
|
27
|
+
return existsSync(binDir) ? binDir : null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Build an env object for spawned workers with OpenSwarm's bundled `.bin`
|
|
31
|
+
* directory prepended to PATH. Keeps every other env var untouched.
|
|
32
|
+
*
|
|
33
|
+
* Prepending (not appending) means a locally-bundled `cxt` wins over an
|
|
34
|
+
* older global install, which matters when we start pinning cxt versions.
|
|
35
|
+
*/
|
|
36
|
+
export function buildWorkerEnv(base = process.env) {
|
|
37
|
+
const binDir = getBundledBinDir();
|
|
38
|
+
if (binDir === null)
|
|
39
|
+
return { ...base };
|
|
40
|
+
const existingPath = base.PATH ?? base.Path ?? '';
|
|
41
|
+
// Avoid duplicate entries if this env is reused across spawns.
|
|
42
|
+
const parts = existingPath.split(delimiter).filter(Boolean);
|
|
43
|
+
if (parts[0] === binDir) {
|
|
44
|
+
return { ...base };
|
|
45
|
+
}
|
|
46
|
+
const nextPath = [binDir, ...parts.filter((p) => p !== binDir)].join(delimiter);
|
|
47
|
+
return { ...base, PATH: nextPath };
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=envPath.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envPath.js","sourceRoot":"","sources":["../../src/adapters/envPath.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,6CAA6C;AAC7C,+CAA+C;AAC/C,EAAE;AACF,uEAAuE;AACvE,2EAA2E;AAC3E,4EAA4E;AAC5E,0EAA0E;AAE1E,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;IACrD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,OAA0B,OAAO,CAAC,GAAG;IAClE,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;IAExC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IAClD,+DAA+D;IAC/D,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5D,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;IACrB,CAAC;IACD,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEhF,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACrC,CAAC"}
|
package/dist/adapters/gpt.d.ts
CHANGED
|
@@ -8,8 +8,12 @@ export declare class GptCliAdapter implements CliAdapter {
|
|
|
8
8
|
args: string[];
|
|
9
9
|
};
|
|
10
10
|
run(options: CliRunOptions): Promise<CliRunResult>;
|
|
11
|
+
/**
|
|
12
|
+
* OpenAI API 호출 함수 생성 (에이전틱 루프에 주입)
|
|
13
|
+
* 401 시 토큰 갱신 + 1회 재시도 포함
|
|
14
|
+
*/
|
|
15
|
+
private createApiCaller;
|
|
11
16
|
parseWorkerOutput(raw: CliRunResult): WorkerResult;
|
|
12
17
|
parseReviewerOutput(raw: CliRunResult): ReviewResult;
|
|
13
|
-
private callApi;
|
|
14
18
|
}
|
|
15
19
|
//# sourceMappingURL=gpt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gpt.d.ts","sourceRoot":"","sources":["../../src/adapters/gpt.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gpt.d.ts","sourceRoot":"","sources":["../../src/adapters/gpt.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,YAAY,EACb,MAAM,YAAY,CAAC;AAUpB,qBAAa,aAAc,YAAW,UAAU;IAC9C,QAAQ,CAAC,IAAI,SAAS;IAEtB,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAMxC;IAEI,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAUrC,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE;IAKpE,GAAG,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAkDxD;;;OAGG;IACH,OAAO,CAAC,eAAe;IAiDvB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY;IAKlD,mBAAmB,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY;CAKrD"}
|