@halfagiraf/clawx 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/.env.example +44 -0
- package/LICENSE +21 -0
- package/README.md +489 -0
- package/clawx.json.example +23 -0
- package/dist/cli/main.d.ts +21 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +176 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/repl.d.ts +11 -0
- package/dist/cli/repl.d.ts.map +1 -0
- package/dist/cli/repl.js +119 -0
- package/dist/cli/repl.js.map +1 -0
- package/dist/cli/tui.d.ts +35 -0
- package/dist/cli/tui.d.ts.map +1 -0
- package/dist/cli/tui.js +92 -0
- package/dist/cli/tui.js.map +1 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +106 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/agent.d.ts +53 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +152 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/provider.d.ts +30 -0
- package/dist/core/provider.d.ts.map +1 -0
- package/dist/core/provider.js +76 -0
- package/dist/core/provider.js.map +1 -0
- package/dist/core/session.d.ts +37 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +87 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/streaming.d.ts +27 -0
- package/dist/core/streaming.d.ts.map +1 -0
- package/dist/core/streaming.js +137 -0
- package/dist/core/streaming.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/gitDiff.d.ts +13 -0
- package/dist/tools/gitDiff.d.ts.map +1 -0
- package/dist/tools/gitDiff.js +50 -0
- package/dist/tools/gitDiff.js.map +1 -0
- package/dist/tools/gitStatus.d.ts +13 -0
- package/dist/tools/gitStatus.d.ts.map +1 -0
- package/dist/tools/gitStatus.js +43 -0
- package/dist/tools/gitStatus.js.map +1 -0
- package/dist/tools/searchFiles.d.ts +19 -0
- package/dist/tools/searchFiles.d.ts.map +1 -0
- package/dist/tools/searchFiles.js +101 -0
- package/dist/tools/searchFiles.js.map +1 -0
- package/dist/tools/sshRun.d.ts +26 -0
- package/dist/tools/sshRun.d.ts.map +1 -0
- package/dist/tools/sshRun.js +170 -0
- package/dist/tools/sshRun.js.map +1 -0
- package/dist/types/index.d.ts +35 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +43 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/system-prompt.d.ts +9 -0
- package/dist/utils/system-prompt.d.ts.map +1 -0
- package/dist/utils/system-prompt.js +49 -0
- package/dist/utils/system-prompt.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clawx Agent — the core orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* EXTRACTION NOTE:
|
|
5
|
+
* OpenClaw's agent orchestration lives in pi-embedded-runner/run.ts (3000+ lines)
|
|
6
|
+
* which handles auth rotation, sandbox environments, context engines, plugin hooks,
|
|
7
|
+
* provider-specific quirks, compaction, failover, and channel integration.
|
|
8
|
+
*
|
|
9
|
+
* We DISCARD all of that and use the clean pi-agent-core agentLoop() directly.
|
|
10
|
+
* The agentLoop (agent-loop.js, 308 lines) handles:
|
|
11
|
+
* user message → model call → tool calls → tool execution → next model call → end
|
|
12
|
+
*
|
|
13
|
+
* Our orchestrator is a thin wrapper that:
|
|
14
|
+
* 1. Resolves the model from config
|
|
15
|
+
* 2. Assembles tools (pi-coding-agent builtins + our custom tools)
|
|
16
|
+
* 3. Builds the agent context (system prompt, messages, tools)
|
|
17
|
+
* 4. Calls agentLoop() and streams events to the terminal
|
|
18
|
+
* 5. Persists session state
|
|
19
|
+
*
|
|
20
|
+
* This replaces ~4000 lines of OpenClaw platform code with ~200 lines.
|
|
21
|
+
*/
|
|
22
|
+
import { agentLoop, } from "@mariozechner/pi-agent-core";
|
|
23
|
+
import { createCodingTools, createGrepTool, createFindTool, createLsTool, convertToLlm, } from "@mariozechner/pi-coding-agent";
|
|
24
|
+
import { resolveModel } from "./provider.js";
|
|
25
|
+
import { buildSystemPrompt } from "../utils/system-prompt.js";
|
|
26
|
+
import { createSshRunTool } from "../tools/sshRun.js";
|
|
27
|
+
import { createGitStatusTool } from "../tools/gitStatus.js";
|
|
28
|
+
import { createGitDiffTool } from "../tools/gitDiff.js";
|
|
29
|
+
import { createSearchFilesTool } from "../tools/searchFiles.js";
|
|
30
|
+
import { log } from "../utils/logger.js";
|
|
31
|
+
/**
|
|
32
|
+
* Create the full tool set for Clawx.
|
|
33
|
+
*
|
|
34
|
+
* EXTRACTION NOTE:
|
|
35
|
+
* OpenClaw's createOpenClawCodingTools() (pi-tools.ts, 619 lines) handles:
|
|
36
|
+
* - 6 layers of tool policies (global, agent, group, profile, provider, subagent)
|
|
37
|
+
* - Sandbox vs gateway vs node execution routing
|
|
38
|
+
* - Memory flush restrictions
|
|
39
|
+
* - Channel capabilities filtering
|
|
40
|
+
* - Tool schema sanitization per provider
|
|
41
|
+
* - Image sanitization limits
|
|
42
|
+
* - Abort signal wrapping
|
|
43
|
+
* - Loop detection wrapping
|
|
44
|
+
*
|
|
45
|
+
* We discard ALL of that. Our tools are the pi-coding-agent defaults plus
|
|
46
|
+
* our custom SSH/git/search tools. No policies, no sandboxing, no restrictions.
|
|
47
|
+
*/
|
|
48
|
+
function createTools(config) {
|
|
49
|
+
const cwd = config.workDir;
|
|
50
|
+
// pi-coding-agent's built-in coding tools: read, write, edit, bash (exec)
|
|
51
|
+
// These are KEPT AS-IS from the OpenClaw dependency chain.
|
|
52
|
+
const builtinTools = createCodingTools(cwd);
|
|
53
|
+
// Add grep, find, ls from pi-coding-agent
|
|
54
|
+
builtinTools.push(createGrepTool(cwd));
|
|
55
|
+
builtinTools.push(createFindTool(cwd));
|
|
56
|
+
builtinTools.push(createLsTool(cwd));
|
|
57
|
+
// Our custom tools (WRITTEN FRESH — not in OpenClaw)
|
|
58
|
+
const customTools = [
|
|
59
|
+
createSearchFilesTool(cwd),
|
|
60
|
+
createGitStatusTool(cwd),
|
|
61
|
+
createGitDiffTool(cwd),
|
|
62
|
+
];
|
|
63
|
+
// SSH tool — only if targets are configured
|
|
64
|
+
if (Object.keys(config.sshTargets).length > 0) {
|
|
65
|
+
customTools.push(createSshRunTool(config.sshTargets));
|
|
66
|
+
}
|
|
67
|
+
return [...builtinTools, ...customTools];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Run the Clawx agent loop.
|
|
71
|
+
*
|
|
72
|
+
* This is the main entry point. It:
|
|
73
|
+
* 1. Resolves the model
|
|
74
|
+
* 2. Builds tools
|
|
75
|
+
* 3. Creates the agent context
|
|
76
|
+
* 4. Runs agentLoop() from pi-agent-core
|
|
77
|
+
* 5. Streams events via callback
|
|
78
|
+
* 6. Returns the full message history
|
|
79
|
+
*/
|
|
80
|
+
export async function runAgent(config, options) {
|
|
81
|
+
const model = resolveModel(config);
|
|
82
|
+
const tools = createTools(config);
|
|
83
|
+
const systemPrompt = buildSystemPrompt(config);
|
|
84
|
+
log.info(`Tools: ${tools.map((t) => t.name).join(", ")}`);
|
|
85
|
+
// Build context with existing messages or empty
|
|
86
|
+
const existingMessages = options.messages || [];
|
|
87
|
+
const context = {
|
|
88
|
+
systemPrompt,
|
|
89
|
+
messages: existingMessages,
|
|
90
|
+
tools,
|
|
91
|
+
};
|
|
92
|
+
// Build the user message
|
|
93
|
+
const userMessage = {
|
|
94
|
+
role: "user",
|
|
95
|
+
content: options.prompt,
|
|
96
|
+
timestamp: Date.now(),
|
|
97
|
+
};
|
|
98
|
+
// Agent loop config
|
|
99
|
+
const loopConfig = {
|
|
100
|
+
model: model,
|
|
101
|
+
apiKey: config.apiKey,
|
|
102
|
+
maxTokens: config.maxTokens,
|
|
103
|
+
reasoning: config.thinkingLevel === "off" ? undefined : config.thinkingLevel,
|
|
104
|
+
convertToLlm: async (messages) => {
|
|
105
|
+
// Use pi-coding-agent's convertToLlm which handles the standard message types
|
|
106
|
+
try {
|
|
107
|
+
return convertToLlm(messages);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Fallback: filter to standard LLM messages
|
|
111
|
+
return messages.filter((m) => m.role === "user" || m.role === "assistant" || m.role === "toolResult");
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
getSteeringMessages: async () => {
|
|
115
|
+
// Support mid-run message injection (e.g., user typing while agent works)
|
|
116
|
+
if (options.steeringQueue && options.steeringQueue.length > 0) {
|
|
117
|
+
const queued = [...options.steeringQueue];
|
|
118
|
+
options.steeringQueue.length = 0;
|
|
119
|
+
return queued;
|
|
120
|
+
}
|
|
121
|
+
return [];
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
// Run the loop
|
|
125
|
+
const eventStream = agentLoop([userMessage], context, loopConfig, options.signal);
|
|
126
|
+
let aborted = false;
|
|
127
|
+
// Process events
|
|
128
|
+
for await (const event of eventStream) {
|
|
129
|
+
if (options.onEvent) {
|
|
130
|
+
options.onEvent(event);
|
|
131
|
+
}
|
|
132
|
+
if (event.type === "agent_end" ||
|
|
133
|
+
(event.type === "turn_end" &&
|
|
134
|
+
event.message.role === "assistant" &&
|
|
135
|
+
"stopReason" in event.message &&
|
|
136
|
+
(event.message.stopReason === "error" || event.message.stopReason === "aborted"))) {
|
|
137
|
+
if ("message" in event &&
|
|
138
|
+
event.message.role === "assistant" &&
|
|
139
|
+
"stopReason" in event.message &&
|
|
140
|
+
event.message.stopReason === "aborted") {
|
|
141
|
+
aborted = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Get the final messages from the event stream result
|
|
146
|
+
const result = await eventStream.result();
|
|
147
|
+
return {
|
|
148
|
+
messages: [...existingMessages, ...result],
|
|
149
|
+
aborted,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model/provider resolution for Clawx.
|
|
3
|
+
*
|
|
4
|
+
* EXTRACTION NOTE:
|
|
5
|
+
* OpenClaw's model resolution (pi-embedded-runner/model.ts, 398 lines) handles
|
|
6
|
+
* 15+ providers with config overrides, forward-compat fallbacks, OpenRouter pre-fetch,
|
|
7
|
+
* and auth profile rotation. We discard all of that.
|
|
8
|
+
*
|
|
9
|
+
* Instead we use pi-ai's model system directly:
|
|
10
|
+
* - For known providers (openai, anthropic, google): use getModel()
|
|
11
|
+
* - For local/custom endpoints (llama.cpp, ollama, vllm): construct Model manually
|
|
12
|
+
* with api:"openai-completions" and a custom baseUrl
|
|
13
|
+
*
|
|
14
|
+
* This covers all target models:
|
|
15
|
+
* - Qwen2.5-Coder-14B-Instruct-abliterated (local llama.cpp)
|
|
16
|
+
* - Qwen3.5-35B-A3B (local)
|
|
17
|
+
* - GLM-4.7-Flash-Uncensored (local)
|
|
18
|
+
* - Any OpenAI-compatible endpoint
|
|
19
|
+
*/
|
|
20
|
+
import type { Api, Model } from "@mariozechner/pi-ai";
|
|
21
|
+
import type { ClawxConfig } from "../types/index.js";
|
|
22
|
+
/**
|
|
23
|
+
* Resolve a Model object from Clawx configuration.
|
|
24
|
+
*
|
|
25
|
+
* For local endpoints, we construct a Model with api:"openai-completions"
|
|
26
|
+
* pointed at the custom baseUrl. This is exactly how OpenClaw handles
|
|
27
|
+
* Ollama and local models — via the OpenAI-compatible completions API.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveModel(config: ClawxConfig): Model<Api>;
|
|
30
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/core/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAuBrD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC,CAgC5D"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model/provider resolution for Clawx.
|
|
3
|
+
*
|
|
4
|
+
* EXTRACTION NOTE:
|
|
5
|
+
* OpenClaw's model resolution (pi-embedded-runner/model.ts, 398 lines) handles
|
|
6
|
+
* 15+ providers with config overrides, forward-compat fallbacks, OpenRouter pre-fetch,
|
|
7
|
+
* and auth profile rotation. We discard all of that.
|
|
8
|
+
*
|
|
9
|
+
* Instead we use pi-ai's model system directly:
|
|
10
|
+
* - For known providers (openai, anthropic, google): use getModel()
|
|
11
|
+
* - For local/custom endpoints (llama.cpp, ollama, vllm): construct Model manually
|
|
12
|
+
* with api:"openai-completions" and a custom baseUrl
|
|
13
|
+
*
|
|
14
|
+
* This covers all target models:
|
|
15
|
+
* - Qwen2.5-Coder-14B-Instruct-abliterated (local llama.cpp)
|
|
16
|
+
* - Qwen3.5-35B-A3B (local)
|
|
17
|
+
* - GLM-4.7-Flash-Uncensored (local)
|
|
18
|
+
* - Any OpenAI-compatible endpoint
|
|
19
|
+
*/
|
|
20
|
+
import { log } from "../utils/logger.js";
|
|
21
|
+
/**
|
|
22
|
+
* Known provider mappings to pi-ai API types.
|
|
23
|
+
*/
|
|
24
|
+
const PROVIDER_API_MAP = {
|
|
25
|
+
openai: "openai-completions",
|
|
26
|
+
"openai-completions": "openai-completions",
|
|
27
|
+
"openai-responses": "openai-responses",
|
|
28
|
+
anthropic: "anthropic-messages",
|
|
29
|
+
"anthropic-messages": "anthropic-messages",
|
|
30
|
+
google: "google-generative-ai",
|
|
31
|
+
"google-generative-ai": "google-generative-ai",
|
|
32
|
+
mistral: "mistral-conversations",
|
|
33
|
+
deepseek: "openai-completions",
|
|
34
|
+
local: "openai-completions",
|
|
35
|
+
"llama.cpp": "openai-completions",
|
|
36
|
+
ollama: "openai-completions",
|
|
37
|
+
vllm: "openai-completions",
|
|
38
|
+
lmstudio: "openai-completions",
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Resolve a Model object from Clawx configuration.
|
|
42
|
+
*
|
|
43
|
+
* For local endpoints, we construct a Model with api:"openai-completions"
|
|
44
|
+
* pointed at the custom baseUrl. This is exactly how OpenClaw handles
|
|
45
|
+
* Ollama and local models — via the OpenAI-compatible completions API.
|
|
46
|
+
*/
|
|
47
|
+
export function resolveModel(config) {
|
|
48
|
+
const api = PROVIDER_API_MAP[config.provider] || "openai-completions";
|
|
49
|
+
log.info(`Provider: ${config.provider} (api: ${api})`);
|
|
50
|
+
log.info(`Model: ${config.model}`);
|
|
51
|
+
log.info(`Base URL: ${config.baseUrl}`);
|
|
52
|
+
// Context window defaults per provider
|
|
53
|
+
const contextWindows = {
|
|
54
|
+
deepseek: 65536,
|
|
55
|
+
anthropic: 200000,
|
|
56
|
+
"anthropic-messages": 200000,
|
|
57
|
+
google: 1048576,
|
|
58
|
+
openai: 128000,
|
|
59
|
+
};
|
|
60
|
+
const contextWindow = contextWindows[config.provider] || 32768;
|
|
61
|
+
// Construct model descriptor
|
|
62
|
+
const model = {
|
|
63
|
+
id: config.model,
|
|
64
|
+
name: config.model,
|
|
65
|
+
api,
|
|
66
|
+
provider: config.provider,
|
|
67
|
+
baseUrl: config.baseUrl,
|
|
68
|
+
reasoning: config.thinkingLevel !== "off",
|
|
69
|
+
input: ["text"],
|
|
70
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
71
|
+
contextWindow,
|
|
72
|
+
maxTokens: config.maxTokens,
|
|
73
|
+
};
|
|
74
|
+
return model;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/core/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAEzC;;GAEG;AACH,MAAM,gBAAgB,GAAwB;IAC5C,MAAM,EAAE,oBAAoB;IAC5B,oBAAoB,EAAE,oBAAoB;IAC1C,kBAAkB,EAAE,kBAAkB;IACtC,SAAS,EAAE,oBAAoB;IAC/B,oBAAoB,EAAE,oBAAoB;IAC1C,MAAM,EAAE,sBAAsB;IAC9B,sBAAsB,EAAE,sBAAsB;IAC9C,OAAO,EAAE,uBAAuB;IAChC,QAAQ,EAAE,oBAAoB;IAC9B,KAAK,EAAE,oBAAoB;IAC3B,WAAW,EAAE,oBAAoB;IACjC,MAAM,EAAE,oBAAoB;IAC5B,IAAI,EAAE,oBAAoB;IAC1B,QAAQ,EAAE,oBAAoB;CAC/B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC9C,MAAM,GAAG,GAAG,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,oBAAoB,CAAC;IAEtE,GAAG,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,QAAQ,UAAU,GAAG,GAAG,CAAC,CAAC;IACvD,GAAG,CAAC,IAAI,CAAC,UAAU,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACnC,GAAG,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAExC,uCAAuC;IACvC,MAAM,cAAc,GAA2B;QAC7C,QAAQ,EAAE,KAAK;QACf,SAAS,EAAE,MAAM;QACjB,oBAAoB,EAAE,MAAM;QAC5B,MAAM,EAAE,OAAO;QACf,MAAM,EAAE,MAAM;KACf,CAAC;IACF,MAAM,aAAa,GAAG,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC;IAE/D,6BAA6B;IAC7B,MAAM,KAAK,GAAe;QACxB,EAAE,EAAE,MAAM,CAAC,KAAK;QAChB,IAAI,EAAE,MAAM,CAAC,KAAK;QAClB,GAAG;QACH,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,SAAS,EAAE,MAAM,CAAC,aAAa,KAAK,KAAK;QACzC,KAAK,EAAE,CAAC,MAAM,CAAC;QACf,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE;QAC1D,aAAa;QACb,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC;IAEF,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session persistence for Clawx.
|
|
3
|
+
*
|
|
4
|
+
* EXTRACTION NOTE:
|
|
5
|
+
* OpenClaw's session store (config/sessions/store.ts, 400+ lines) handles:
|
|
6
|
+
* - TTL-based in-memory caching (45s)
|
|
7
|
+
* - Atomic disk writes with lock acquisition
|
|
8
|
+
* - Legacy session key migration
|
|
9
|
+
* - Delivery context normalization
|
|
10
|
+
* - Entry count capping, stale pruning, disk budget enforcement
|
|
11
|
+
* - File rotation on size limits
|
|
12
|
+
*
|
|
13
|
+
* pi-coding-agent provides a SessionManager that handles session persistence
|
|
14
|
+
* with file-based storage, entries, compaction, and branching.
|
|
15
|
+
*
|
|
16
|
+
* For Clawx, we use a SIMPLER approach:
|
|
17
|
+
* - JSON file per session in ~/.clawx/sessions/
|
|
18
|
+
* - Session = id + messages + metadata
|
|
19
|
+
* - Load/save by session ID
|
|
20
|
+
* - List recent sessions
|
|
21
|
+
* - No caching, no TTL, no locking, no rotation
|
|
22
|
+
*
|
|
23
|
+
* This replaces the OpenClaw session store with ~100 lines.
|
|
24
|
+
*/
|
|
25
|
+
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
|
26
|
+
import type { ClawxSession } from "../types/index.js";
|
|
27
|
+
interface SessionData {
|
|
28
|
+
session: ClawxSession;
|
|
29
|
+
messages: AgentMessage[];
|
|
30
|
+
}
|
|
31
|
+
export declare function createSessionId(): string;
|
|
32
|
+
export declare function saveSession(sessionDir: string, session: ClawxSession, messages: AgentMessage[]): void;
|
|
33
|
+
export declare function loadSession(sessionDir: string, id: string): SessionData | null;
|
|
34
|
+
export declare function listSessions(sessionDir: string): ClawxSession[];
|
|
35
|
+
export declare function getLatestSession(sessionDir: string): SessionData | null;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,UAAU,WAAW;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAYD,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,YAAY,EAAE,GACvB,IAAI,CAMN;AAED,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,GACT,WAAW,GAAG,IAAI,CAUpB;AAED,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,GACjB,YAAY,EAAE,CAkBhB;AAED,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,GACjB,WAAW,GAAG,IAAI,CAIpB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session persistence for Clawx.
|
|
3
|
+
*
|
|
4
|
+
* EXTRACTION NOTE:
|
|
5
|
+
* OpenClaw's session store (config/sessions/store.ts, 400+ lines) handles:
|
|
6
|
+
* - TTL-based in-memory caching (45s)
|
|
7
|
+
* - Atomic disk writes with lock acquisition
|
|
8
|
+
* - Legacy session key migration
|
|
9
|
+
* - Delivery context normalization
|
|
10
|
+
* - Entry count capping, stale pruning, disk budget enforcement
|
|
11
|
+
* - File rotation on size limits
|
|
12
|
+
*
|
|
13
|
+
* pi-coding-agent provides a SessionManager that handles session persistence
|
|
14
|
+
* with file-based storage, entries, compaction, and branching.
|
|
15
|
+
*
|
|
16
|
+
* For Clawx, we use a SIMPLER approach:
|
|
17
|
+
* - JSON file per session in ~/.clawx/sessions/
|
|
18
|
+
* - Session = id + messages + metadata
|
|
19
|
+
* - Load/save by session ID
|
|
20
|
+
* - List recent sessions
|
|
21
|
+
* - No caching, no TTL, no locking, no rotation
|
|
22
|
+
*
|
|
23
|
+
* This replaces the OpenClaw session store with ~100 lines.
|
|
24
|
+
*/
|
|
25
|
+
import fs from "node:fs";
|
|
26
|
+
import path from "node:path";
|
|
27
|
+
import crypto from "node:crypto";
|
|
28
|
+
import { log } from "../utils/logger.js";
|
|
29
|
+
function ensureDir(dir) {
|
|
30
|
+
if (!fs.existsSync(dir)) {
|
|
31
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function sessionPath(dir, id) {
|
|
35
|
+
return path.join(dir, `${id}.json`);
|
|
36
|
+
}
|
|
37
|
+
export function createSessionId() {
|
|
38
|
+
return crypto.randomBytes(8).toString("hex");
|
|
39
|
+
}
|
|
40
|
+
export function saveSession(sessionDir, session, messages) {
|
|
41
|
+
ensureDir(sessionDir);
|
|
42
|
+
const data = { session, messages };
|
|
43
|
+
const filePath = sessionPath(sessionDir, session.id);
|
|
44
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
45
|
+
log.debug(`Session saved: ${session.id}`);
|
|
46
|
+
}
|
|
47
|
+
export function loadSession(sessionDir, id) {
|
|
48
|
+
const filePath = sessionPath(sessionDir, id);
|
|
49
|
+
if (!fs.existsSync(filePath))
|
|
50
|
+
return null;
|
|
51
|
+
try {
|
|
52
|
+
const raw = fs.readFileSync(filePath, "utf-8");
|
|
53
|
+
return JSON.parse(raw);
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
log.warn(`Failed to load session ${id}: ${e}`);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function listSessions(sessionDir) {
|
|
61
|
+
ensureDir(sessionDir);
|
|
62
|
+
try {
|
|
63
|
+
const files = fs.readdirSync(sessionDir).filter((f) => f.endsWith(".json"));
|
|
64
|
+
const sessions = [];
|
|
65
|
+
for (const file of files) {
|
|
66
|
+
try {
|
|
67
|
+
const raw = fs.readFileSync(path.join(sessionDir, file), "utf-8");
|
|
68
|
+
const data = JSON.parse(raw);
|
|
69
|
+
sessions.push(data.session);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Skip corrupt sessions
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return sessions.sort((a, b) => b.startedAt - a.startedAt);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export function getLatestSession(sessionDir) {
|
|
82
|
+
const sessions = listSessions(sessionDir);
|
|
83
|
+
if (sessions.length === 0)
|
|
84
|
+
return null;
|
|
85
|
+
return loadSession(sessionDir, sessions[0].id);
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal streaming renderer for Clawx.
|
|
3
|
+
*
|
|
4
|
+
* EXTRACTION NOTE:
|
|
5
|
+
* OpenClaw's streaming (pi-embedded-subscribe.ts, 726 lines) handles:
|
|
6
|
+
* - Thinking/reasoning tag stripping with code-span awareness
|
|
7
|
+
* - Block chunking for channel message size limits
|
|
8
|
+
* - Messaging tool duplicate detection
|
|
9
|
+
* - Compaction retry coordination
|
|
10
|
+
* - Multi-level buffering with partial block state
|
|
11
|
+
* - Channel-aware formatting (markdown vs plain)
|
|
12
|
+
*
|
|
13
|
+
* We DISCARD all of that. For terminal output, we render agent events directly:
|
|
14
|
+
* - Stream text deltas as they arrive
|
|
15
|
+
* - Show tool calls with their names and a spinner
|
|
16
|
+
* - Show tool results
|
|
17
|
+
* - Show errors
|
|
18
|
+
*
|
|
19
|
+
* Clean, simple, terminal-native.
|
|
20
|
+
*/
|
|
21
|
+
import type { AgentEvent } from "@mariozechner/pi-agent-core";
|
|
22
|
+
export interface StreamRenderer {
|
|
23
|
+
onEvent(event: AgentEvent): void;
|
|
24
|
+
finish(): void;
|
|
25
|
+
}
|
|
26
|
+
export declare function createStreamRenderer(): StreamRenderer;
|
|
27
|
+
//# sourceMappingURL=streaming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../../src/core/streaming.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACjC,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,wBAAgB,oBAAoB,IAAI,cAAc,CAwGrD"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal streaming renderer for Clawx.
|
|
3
|
+
*
|
|
4
|
+
* EXTRACTION NOTE:
|
|
5
|
+
* OpenClaw's streaming (pi-embedded-subscribe.ts, 726 lines) handles:
|
|
6
|
+
* - Thinking/reasoning tag stripping with code-span awareness
|
|
7
|
+
* - Block chunking for channel message size limits
|
|
8
|
+
* - Messaging tool duplicate detection
|
|
9
|
+
* - Compaction retry coordination
|
|
10
|
+
* - Multi-level buffering with partial block state
|
|
11
|
+
* - Channel-aware formatting (markdown vs plain)
|
|
12
|
+
*
|
|
13
|
+
* We DISCARD all of that. For terminal output, we render agent events directly:
|
|
14
|
+
* - Stream text deltas as they arrive
|
|
15
|
+
* - Show tool calls with their names and a spinner
|
|
16
|
+
* - Show tool results
|
|
17
|
+
* - Show errors
|
|
18
|
+
*
|
|
19
|
+
* Clean, simple, terminal-native.
|
|
20
|
+
*/
|
|
21
|
+
import chalk from "chalk";
|
|
22
|
+
export function createStreamRenderer() {
|
|
23
|
+
let currentToolName = null;
|
|
24
|
+
let toolCallCount = 0;
|
|
25
|
+
let turnCount = 0;
|
|
26
|
+
return {
|
|
27
|
+
onEvent(event) {
|
|
28
|
+
switch (event.type) {
|
|
29
|
+
case "agent_start":
|
|
30
|
+
break;
|
|
31
|
+
case "turn_start":
|
|
32
|
+
turnCount++;
|
|
33
|
+
break;
|
|
34
|
+
case "message_start":
|
|
35
|
+
if (event.message.role === "assistant") {
|
|
36
|
+
// New assistant response starting
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
case "message_update": {
|
|
40
|
+
const evt = event.assistantMessageEvent;
|
|
41
|
+
if (evt.type === "text_delta") {
|
|
42
|
+
process.stdout.write(evt.delta);
|
|
43
|
+
}
|
|
44
|
+
else if (evt.type === "thinking_delta") {
|
|
45
|
+
// Show thinking in dim if present
|
|
46
|
+
process.stderr.write(chalk.dim(evt.delta));
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case "message_end": {
|
|
51
|
+
const msg = event.message;
|
|
52
|
+
if (msg.role === "assistant") {
|
|
53
|
+
const assistant = msg;
|
|
54
|
+
// Ensure newline after streamed text
|
|
55
|
+
const hasText = assistant.content.some((c) => c.type === "text" && c.text.trim().length > 0);
|
|
56
|
+
if (hasText) {
|
|
57
|
+
process.stdout.write("\n");
|
|
58
|
+
}
|
|
59
|
+
// Show stop reason if not normal
|
|
60
|
+
if (assistant.stopReason === "error") {
|
|
61
|
+
console.error(chalk.red(`\n[error] ${assistant.errorMessage || "Unknown error"}`));
|
|
62
|
+
}
|
|
63
|
+
else if (assistant.stopReason === "length") {
|
|
64
|
+
console.error(chalk.yellow("\n[truncated — max tokens reached]"));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case "tool_execution_start": {
|
|
70
|
+
currentToolName = event.toolName;
|
|
71
|
+
toolCallCount++;
|
|
72
|
+
const argsPreview = formatToolArgs(event.args);
|
|
73
|
+
process.stderr.write(chalk.cyan(`\n[tool] ${event.toolName}`) +
|
|
74
|
+
chalk.gray(` ${argsPreview}\n`));
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case "tool_execution_update":
|
|
78
|
+
// Could show progress, but most tools are fast
|
|
79
|
+
break;
|
|
80
|
+
case "tool_execution_end": {
|
|
81
|
+
currentToolName = null;
|
|
82
|
+
const isErr = event.isError;
|
|
83
|
+
const resultText = extractResultText(event.result);
|
|
84
|
+
const truncated = resultText.length > 500
|
|
85
|
+
? resultText.slice(0, 500) + "... (truncated)"
|
|
86
|
+
: resultText;
|
|
87
|
+
if (isErr) {
|
|
88
|
+
process.stderr.write(chalk.red(` [error] ${truncated}\n`));
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
process.stderr.write(chalk.gray(` ${truncated}\n`));
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case "turn_end":
|
|
96
|
+
break;
|
|
97
|
+
case "agent_end":
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
finish() {
|
|
102
|
+
if (toolCallCount > 0) {
|
|
103
|
+
process.stderr.write(chalk.gray(`\n[done] ${turnCount} turns, ${toolCallCount} tool calls\n`));
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function formatToolArgs(args) {
|
|
109
|
+
if (!args || Object.keys(args).length === 0)
|
|
110
|
+
return "";
|
|
111
|
+
const parts = [];
|
|
112
|
+
for (const [key, value] of Object.entries(args)) {
|
|
113
|
+
if (typeof value === "string" && value.length > 80) {
|
|
114
|
+
parts.push(`${key}="${value.slice(0, 80)}..."`);
|
|
115
|
+
}
|
|
116
|
+
else if (typeof value === "string") {
|
|
117
|
+
parts.push(`${key}="${value}"`);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
parts.push(`${key}=${JSON.stringify(value)}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return parts.join(" ");
|
|
124
|
+
}
|
|
125
|
+
function extractResultText(result) {
|
|
126
|
+
if (!result || typeof result !== "object")
|
|
127
|
+
return String(result);
|
|
128
|
+
const r = result;
|
|
129
|
+
if (Array.isArray(r.content)) {
|
|
130
|
+
return r.content
|
|
131
|
+
.filter((c) => c.type === "text" && c.text)
|
|
132
|
+
.map((c) => c.text)
|
|
133
|
+
.join("\n");
|
|
134
|
+
}
|
|
135
|
+
return JSON.stringify(result).slice(0, 200);
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=streaming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming.js","sourceRoot":"","sources":["../../src/core/streaming.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,MAAM,UAAU,oBAAoB;IAClC,IAAI,eAAe,GAAkB,IAAI,CAAC;IAC1C,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,OAAO;QACL,OAAO,CAAC,KAAiB;YACvB,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;gBACnB,KAAK,aAAa;oBAChB,MAAM;gBAER,KAAK,YAAY;oBACf,SAAS,EAAE,CAAC;oBACZ,MAAM;gBAER,KAAK,eAAe;oBAClB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;wBACvC,kCAAkC;oBACpC,CAAC;oBACD,MAAM;gBAER,KAAK,gBAAgB,CAAC,CAAC,CAAC;oBACtB,MAAM,GAAG,GAAG,KAAK,CAAC,qBAAqB,CAAC;oBACxC,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;wBAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;oBAClC,CAAC;yBAAM,IAAI,GAAG,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;wBACzC,kCAAkC;wBAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;oBAC7C,CAAC;oBACD,MAAM;gBACR,CAAC;gBAED,KAAK,aAAa,CAAC,CAAC,CAAC;oBACnB,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC;oBAC1B,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;wBAC7B,MAAM,SAAS,GAAG,GAAuB,CAAC;wBAC1C,qCAAqC;wBACrC,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CACpC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CACvE,CAAC;wBACF,IAAI,OAAO,EAAE,CAAC;4BACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;wBAC7B,CAAC;wBAED,iCAAiC;wBACjC,IAAI,SAAS,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;4BACrC,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAAC,aAAa,SAAS,CAAC,YAAY,IAAI,eAAe,EAAE,CAAC,CACpE,CAAC;wBACJ,CAAC;6BAAM,IAAI,SAAS,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;4BAC7C,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,oCAAoC,CAAC,CAAC,CAAC;wBACpE,CAAC;oBACH,CAAC;oBACD,MAAM;gBACR,CAAC;gBAED,KAAK,sBAAsB,CAAC,CAAC,CAAC;oBAC5B,eAAe,GAAG,KAAK,CAAC,QAAQ,CAAC;oBACjC,aAAa,EAAE,CAAC;oBAChB,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,CAAC,IAAI,CAAC,YAAY,KAAK,CAAC,QAAQ,EAAE,CAAC;wBACtC,KAAK,CAAC,IAAI,CAAC,IAAI,WAAW,IAAI,CAAC,CAClC,CAAC;oBACF,MAAM;gBACR,CAAC;gBAED,KAAK,uBAAuB;oBAC1B,+CAA+C;oBAC/C,MAAM;gBAER,KAAK,oBAAoB,CAAC,CAAC,CAAC;oBAC1B,eAAe,GAAG,IAAI,CAAC;oBACvB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC;oBAC5B,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;oBACnD,MAAM,SAAS,GACb,UAAU,CAAC,MAAM,GAAG,GAAG;wBACrB,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,iBAAiB;wBAC9C,CAAC,CAAC,UAAU,CAAC;oBAEjB,IAAI,KAAK,EAAE,CAAC;wBACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,SAAS,IAAI,CAAC,CAAC,CAAC;oBAC9D,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC;oBACvD,CAAC;oBACD,MAAM;gBACR,CAAC;gBAED,KAAK,UAAU;oBACb,MAAM;gBAER,KAAK,WAAW;oBACd,MAAM;YACV,CAAC;QACH,CAAC;QAED,MAAM;YACJ,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,CAAC,IAAI,CAAC,YAAY,SAAS,WAAW,aAAa,eAAe,CAAC,CACzE,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,IAA6B;IACnD,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACvD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACnD,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;QAClD,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,KAAK,GAAG,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAe;IACxC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;IACjE,MAAM,CAAC,GAAG,MAA8D,CAAC;IACzE,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,CAAC,OAAO;aACb,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC;aAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAK,CAAC;aACnB,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC9C,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clawx — lean coding/execution agent.
|
|
3
|
+
*
|
|
4
|
+
* Public API for programmatic usage.
|
|
5
|
+
*/
|
|
6
|
+
export { loadConfig } from "./config/index.js";
|
|
7
|
+
export { runAgent, type AgentRunOptions, type AgentRunResult } from "./core/agent.js";
|
|
8
|
+
export { resolveModel } from "./core/provider.js";
|
|
9
|
+
export { createSessionId, saveSession, loadSession, listSessions, getLatestSession, } from "./core/session.js";
|
|
10
|
+
export { createStreamRenderer } from "./core/streaming.js";
|
|
11
|
+
export { buildSystemPrompt } from "./utils/system-prompt.js";
|
|
12
|
+
export { log } from "./utils/logger.js";
|
|
13
|
+
export { createSshRunTool } from "./tools/sshRun.js";
|
|
14
|
+
export { createGitStatusTool } from "./tools/gitStatus.js";
|
|
15
|
+
export { createGitDiffTool } from "./tools/gitDiff.js";
|
|
16
|
+
export { createSearchFilesTool } from "./tools/searchFiles.js";
|
|
17
|
+
export type { ClawxConfig, SshTarget, ClawxSession } from "./types/index.js";
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EACL,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAGxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clawx — lean coding/execution agent.
|
|
3
|
+
*
|
|
4
|
+
* Public API for programmatic usage.
|
|
5
|
+
*/
|
|
6
|
+
export { loadConfig } from "./config/index.js";
|
|
7
|
+
export { runAgent } from "./core/agent.js";
|
|
8
|
+
export { resolveModel } from "./core/provider.js";
|
|
9
|
+
export { createSessionId, saveSession, loadSession, listSessions, getLatestSession, } from "./core/session.js";
|
|
10
|
+
export { createStreamRenderer } from "./core/streaming.js";
|
|
11
|
+
export { buildSystemPrompt } from "./utils/system-prompt.js";
|
|
12
|
+
export { log } from "./utils/logger.js";
|
|
13
|
+
// Tool factories for custom compositions
|
|
14
|
+
export { createSshRunTool } from "./tools/sshRun.js";
|
|
15
|
+
export { createGitStatusTool } from "./tools/gitStatus.js";
|
|
16
|
+
export { createGitDiffTool } from "./tools/gitDiff.js";
|
|
17
|
+
export { createSearchFilesTool } from "./tools/searchFiles.js";
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAA6C,MAAM,iBAAiB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EACL,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAExC,yCAAyC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git diff tool for Clawx.
|
|
3
|
+
* Written fresh — not present in OpenClaw as a model tool.
|
|
4
|
+
*/
|
|
5
|
+
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
|
6
|
+
declare const GitDiffSchema: import("@sinclair/typebox").TObject<{
|
|
7
|
+
path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
8
|
+
staged: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
9
|
+
file: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function createGitDiffTool(defaultCwd: string): AgentTool<typeof GitDiffSchema>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=gitDiff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitDiff.d.ts","sourceRoot":"","sources":["../../src/tools/gitDiff.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAmB,MAAM,6BAA6B,CAAC;AAM9E,QAAA,MAAM,aAAa;;;;EAUjB,CAAC;AAIH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GACjB,SAAS,CAAC,OAAO,aAAa,CAAC,CAoCjC"}
|