aisnitch 0.2.22 → 0.2.24
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/README.md +433 -403
- package/dist/cli/index.cjs +352 -8
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +354 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +35 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js +35 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -743,7 +743,7 @@ import { Command, InvalidArgumentError } from "commander";
|
|
|
743
743
|
|
|
744
744
|
// src/package-info.ts
|
|
745
745
|
var AISNITCH_PACKAGE_NAME = "aisnitch";
|
|
746
|
-
var AISNITCH_VERSION = "0.2.
|
|
746
|
+
var AISNITCH_VERSION = "0.2.24";
|
|
747
747
|
var AISNITCH_DESCRIPTION = "Universal bridge for AI coding tool activity \u2014 capture, normalize, stream.";
|
|
748
748
|
|
|
749
749
|
// src/core/events/schema.ts
|
|
@@ -1927,6 +1927,9 @@ var OpenClawSetup = class {
|
|
|
1927
1927
|
hookHandlerPath;
|
|
1928
1928
|
hookUrl;
|
|
1929
1929
|
openclawHomeDirectory;
|
|
1930
|
+
pluginDirectory;
|
|
1931
|
+
pluginFilePath;
|
|
1932
|
+
pluginDocumentPath;
|
|
1930
1933
|
toolName = "openclaw";
|
|
1931
1934
|
constructor(httpPort, dependencies = {}) {
|
|
1932
1935
|
this.binaryExists = dependencies.binaryExists ?? isBinaryAvailable;
|
|
@@ -1940,6 +1943,13 @@ var OpenClawSetup = class {
|
|
|
1940
1943
|
this.hookDocumentPath = join2(this.hookDirectory, "HOOK.md");
|
|
1941
1944
|
this.hookHandlerPath = join2(this.hookDirectory, "handler.ts");
|
|
1942
1945
|
this.hookUrl = `http://localhost:${httpPort}/hooks/openclaw`;
|
|
1946
|
+
this.pluginDirectory = join2(
|
|
1947
|
+
this.openclawHomeDirectory,
|
|
1948
|
+
"plugins",
|
|
1949
|
+
"aisnitch-monitor"
|
|
1950
|
+
);
|
|
1951
|
+
this.pluginFilePath = join2(this.pluginDirectory, "index.ts");
|
|
1952
|
+
this.pluginDocumentPath = join2(this.pluginDirectory, "README.md");
|
|
1943
1953
|
}
|
|
1944
1954
|
async detect() {
|
|
1945
1955
|
return await this.binaryExists("openclaw") || await fileExists(this.openclawHomeDirectory) || await fileExists("/Applications/OpenClaw.app");
|
|
@@ -1951,9 +1961,13 @@ var OpenClawSetup = class {
|
|
|
1951
1961
|
const currentConfigContent = await readOptionalFile(this.configPath);
|
|
1952
1962
|
const currentHookDocument = await readOptionalFile(this.hookDocumentPath);
|
|
1953
1963
|
const currentHookHandler = await readOptionalFile(this.hookHandlerPath);
|
|
1964
|
+
const currentPluginDocument = await readOptionalFile(this.pluginDocumentPath);
|
|
1965
|
+
const currentPluginFile = await readOptionalFile(this.pluginFilePath);
|
|
1954
1966
|
const nextConfigContent = this.buildNextConfigContent(currentConfigContent);
|
|
1955
1967
|
const nextHookDocument = buildOpenClawHookDocumentSource();
|
|
1956
1968
|
const nextHookHandler = buildOpenClawHookHandlerSource(this.hookUrl);
|
|
1969
|
+
const nextPluginDocument = buildOpenClawPluginDocumentSource();
|
|
1970
|
+
const nextPluginFile = buildOpenClawPluginSource(this.hookUrl);
|
|
1957
1971
|
return [
|
|
1958
1972
|
renderColoredDiff(
|
|
1959
1973
|
this.configPath,
|
|
@@ -1971,6 +1985,18 @@ var OpenClawSetup = class {
|
|
|
1971
1985
|
this.hookHandlerPath,
|
|
1972
1986
|
currentHookHandler,
|
|
1973
1987
|
nextHookHandler
|
|
1988
|
+
),
|
|
1989
|
+
"",
|
|
1990
|
+
renderColoredDiff(
|
|
1991
|
+
this.pluginDocumentPath,
|
|
1992
|
+
currentPluginDocument,
|
|
1993
|
+
nextPluginDocument
|
|
1994
|
+
),
|
|
1995
|
+
"",
|
|
1996
|
+
renderColoredDiff(
|
|
1997
|
+
this.pluginFilePath,
|
|
1998
|
+
currentPluginFile,
|
|
1999
|
+
nextPluginFile
|
|
1974
2000
|
)
|
|
1975
2001
|
].join("\n");
|
|
1976
2002
|
}
|
|
@@ -1978,11 +2004,16 @@ var OpenClawSetup = class {
|
|
|
1978
2004
|
const currentConfigContent = await readOptionalFile(this.configPath);
|
|
1979
2005
|
const currentHookDocument = await readOptionalFile(this.hookDocumentPath);
|
|
1980
2006
|
const currentHookHandler = await readOptionalFile(this.hookHandlerPath);
|
|
2007
|
+
const currentPluginDocument = await readOptionalFile(this.pluginDocumentPath);
|
|
2008
|
+
const currentPluginFile = await readOptionalFile(this.pluginFilePath);
|
|
1981
2009
|
const nextConfigContent = this.buildNextConfigContent(currentConfigContent);
|
|
1982
2010
|
const nextHookDocument = buildOpenClawHookDocumentSource();
|
|
1983
2011
|
const nextHookHandler = buildOpenClawHookHandlerSource(this.hookUrl);
|
|
2012
|
+
const nextPluginDocument = buildOpenClawPluginDocumentSource();
|
|
2013
|
+
const nextPluginFile = buildOpenClawPluginSource(this.hookUrl);
|
|
1984
2014
|
await mkdir2(dirname2(this.configPath), { recursive: true });
|
|
1985
2015
|
await mkdir2(this.hookDirectory, { recursive: true });
|
|
2016
|
+
await mkdir2(this.pluginDirectory, { recursive: true });
|
|
1986
2017
|
if (currentConfigContent !== null) {
|
|
1987
2018
|
await copyFile(this.configPath, this.getBackupPath(this.configPath));
|
|
1988
2019
|
}
|
|
@@ -1998,14 +2029,30 @@ var OpenClawSetup = class {
|
|
|
1998
2029
|
this.getBackupPath(this.hookHandlerPath)
|
|
1999
2030
|
);
|
|
2000
2031
|
}
|
|
2032
|
+
if (currentPluginDocument !== null) {
|
|
2033
|
+
await copyFile(
|
|
2034
|
+
this.pluginDocumentPath,
|
|
2035
|
+
this.getBackupPath(this.pluginDocumentPath)
|
|
2036
|
+
);
|
|
2037
|
+
}
|
|
2038
|
+
if (currentPluginFile !== null) {
|
|
2039
|
+
await copyFile(
|
|
2040
|
+
this.pluginFilePath,
|
|
2041
|
+
this.getBackupPath(this.pluginFilePath)
|
|
2042
|
+
);
|
|
2043
|
+
}
|
|
2001
2044
|
await writeFile2(this.configPath, nextConfigContent, "utf8");
|
|
2002
2045
|
await writeFile2(this.hookDocumentPath, nextHookDocument, "utf8");
|
|
2003
2046
|
await writeFile2(this.hookHandlerPath, nextHookHandler, "utf8");
|
|
2047
|
+
await writeFile2(this.pluginDocumentPath, nextPluginDocument, "utf8");
|
|
2048
|
+
await writeFile2(this.pluginFilePath, nextPluginFile, "utf8");
|
|
2004
2049
|
}
|
|
2005
2050
|
async revert() {
|
|
2006
2051
|
await restoreBackupOrRemove(this.configPath);
|
|
2007
2052
|
await restoreBackupOrRemove(this.hookDocumentPath);
|
|
2008
2053
|
await restoreBackupOrRemove(this.hookHandlerPath);
|
|
2054
|
+
await restoreBackupOrRemove(this.pluginDocumentPath);
|
|
2055
|
+
await restoreBackupOrRemove(this.pluginFilePath);
|
|
2009
2056
|
}
|
|
2010
2057
|
buildNextConfigContent(currentContent) {
|
|
2011
2058
|
const parsedConfig = parseOpenClawSettings(currentContent);
|
|
@@ -2027,6 +2074,15 @@ var OpenClawSetup = class {
|
|
|
2027
2074
|
enabled: true
|
|
2028
2075
|
}
|
|
2029
2076
|
};
|
|
2077
|
+
const currentPlugins = parsedConfig.plugins ?? {};
|
|
2078
|
+
const currentPluginEntries = currentPlugins.entries ?? {};
|
|
2079
|
+
const nextPluginEntries = {
|
|
2080
|
+
...currentPluginEntries,
|
|
2081
|
+
"aisnitch-monitor": {
|
|
2082
|
+
...currentPluginEntries["aisnitch-monitor"] ?? {},
|
|
2083
|
+
enabled: true
|
|
2084
|
+
}
|
|
2085
|
+
};
|
|
2030
2086
|
const nextConfig = {
|
|
2031
2087
|
...parsedConfig,
|
|
2032
2088
|
hooks: {
|
|
@@ -2036,6 +2092,10 @@ var OpenClawSetup = class {
|
|
|
2036
2092
|
enabled: true,
|
|
2037
2093
|
entries: nextEntries
|
|
2038
2094
|
}
|
|
2095
|
+
},
|
|
2096
|
+
plugins: {
|
|
2097
|
+
...currentPlugins,
|
|
2098
|
+
entries: nextPluginEntries
|
|
2039
2099
|
}
|
|
2040
2100
|
};
|
|
2041
2101
|
return `${JSON.stringify(nextConfig, null, 2)}
|
|
@@ -2870,6 +2930,231 @@ export default async function aisnitchForward(event) {
|
|
|
2870
2930
|
}
|
|
2871
2931
|
`;
|
|
2872
2932
|
}
|
|
2933
|
+
function buildOpenClawPluginDocumentSource() {
|
|
2934
|
+
return `# AISnitch Monitor Plugin
|
|
2935
|
+
|
|
2936
|
+
\u{1F4D6} This managed plugin uses OpenClaw's Plugin SDK to forward rich real-time
|
|
2937
|
+
events to the local AISnitch HTTP receiver. Unlike the internal hook handler,
|
|
2938
|
+
the plugin has access to tool-level hooks (before_tool_call, after_tool_call),
|
|
2939
|
+
model-level hooks (model_call_started, model_call_ended), and agent turn hooks
|
|
2940
|
+
(agent_end, before_agent_run) \u2014 providing maximum observability fidelity.
|
|
2941
|
+
|
|
2942
|
+
## Hooked Events
|
|
2943
|
+
|
|
2944
|
+
| Hook | AISnitch Event |
|
|
2945
|
+
|:---|:---|
|
|
2946
|
+
| gateway_start | session.start |
|
|
2947
|
+
| gateway_stop | session.end |
|
|
2948
|
+
| before_agent_run | task.start |
|
|
2949
|
+
| agent_end | task.complete |
|
|
2950
|
+
| before_tool_call | agent.coding / agent.tool_call |
|
|
2951
|
+
| after_tool_call | agent.coding / agent.tool_call + results |
|
|
2952
|
+
| model_call_started | agent.thinking |
|
|
2953
|
+
| model_call_ended | agent.streaming |
|
|
2954
|
+
| before_compaction | agent.compact |
|
|
2955
|
+
| after_compaction | agent.compact |
|
|
2956
|
+
| message_received | context info |
|
|
2957
|
+
|
|
2958
|
+
## Managed by AISnitch
|
|
2959
|
+
|
|
2960
|
+
This file is managed by \`aisnitch setup openclaw\`. Re-running setup will
|
|
2961
|
+
overwrite it. Use \`aisnitch setup openclaw --revert\` to remove it.
|
|
2962
|
+
`;
|
|
2963
|
+
}
|
|
2964
|
+
function buildOpenClawPluginSource(hookUrl) {
|
|
2965
|
+
return `/**
|
|
2966
|
+
* AISnitch OpenClaw Plugin
|
|
2967
|
+
*
|
|
2968
|
+
* \u{1F4D6} Uses OpenClaw's Plugin SDK to forward rich real-time events to AISnitch.
|
|
2969
|
+
* Provides maximum visibility into tool calls, model usage, agent turns,
|
|
2970
|
+
* and lifecycle events \u2014 far beyond what passive file-watching can achieve.
|
|
2971
|
+
*
|
|
2972
|
+
* Managed by \`aisnitch setup openclaw\`. Re-running setup overwrites this file.
|
|
2973
|
+
*/
|
|
2974
|
+
|
|
2975
|
+
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
2976
|
+
|
|
2977
|
+
const AISNITCH_ENDPOINT = ${JSON.stringify(hookUrl)};
|
|
2978
|
+
|
|
2979
|
+
async function postToAISnitch(payload: Record<string, unknown>): Promise<void> {
|
|
2980
|
+
try {
|
|
2981
|
+
await fetch(AISNITCH_ENDPOINT, {
|
|
2982
|
+
method: "POST",
|
|
2983
|
+
headers: { "content-type": "application/json" },
|
|
2984
|
+
body: JSON.stringify(payload),
|
|
2985
|
+
});
|
|
2986
|
+
} catch {
|
|
2987
|
+
// Silently ignore transport errors so OpenClaw keeps running.
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
|
|
2991
|
+
function getSessionKey(ctx: Record<string, unknown> | undefined): string | undefined {
|
|
2992
|
+
if (!ctx) return undefined;
|
|
2993
|
+
return (
|
|
2994
|
+
(typeof ctx.sessionKey === "string" && ctx.sessionKey.length > 0 ? ctx.sessionKey : undefined) ??
|
|
2995
|
+
(typeof ctx.sessionId === "string" && ctx.sessionId.length > 0 ? ctx.sessionId : undefined)
|
|
2996
|
+
);
|
|
2997
|
+
}
|
|
2998
|
+
|
|
2999
|
+
function getWorkspaceDir(ctx: Record<string, unknown> | undefined): string | undefined {
|
|
3000
|
+
if (!ctx) return undefined;
|
|
3001
|
+
return (
|
|
3002
|
+
(typeof ctx.workspaceDir === "string" && ctx.workspaceDir.length > 0 ? ctx.workspaceDir : undefined) ??
|
|
3003
|
+
(typeof ctx.cwd === "string" && ctx.cwd.length > 0 ? ctx.cwd : undefined)
|
|
3004
|
+
);
|
|
3005
|
+
}
|
|
3006
|
+
|
|
3007
|
+
export default definePluginEntry({
|
|
3008
|
+
id: "aisnitch-monitor",
|
|
3009
|
+
name: "AISnitch Monitor",
|
|
3010
|
+
register(api) {
|
|
3011
|
+
// \u2500\u2500 Gateway lifecycle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3012
|
+
|
|
3013
|
+
api.on("gateway_start", (event) => {
|
|
3014
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3015
|
+
void postToAISnitch({
|
|
3016
|
+
event: "gateway:startup",
|
|
3017
|
+
sessionKey: getSessionKey(ctx),
|
|
3018
|
+
context: ctx ?? {},
|
|
3019
|
+
timestamp: new Date().toISOString(),
|
|
3020
|
+
});
|
|
3021
|
+
});
|
|
3022
|
+
|
|
3023
|
+
api.on("gateway_stop", () => {
|
|
3024
|
+
void postToAISnitch({
|
|
3025
|
+
event: "gateway:shutdown",
|
|
3026
|
+
timestamp: new Date().toISOString(),
|
|
3027
|
+
});
|
|
3028
|
+
});
|
|
3029
|
+
|
|
3030
|
+
// \u2500\u2500 Agent turn lifecycle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3031
|
+
|
|
3032
|
+
api.on("before_agent_run", (event) => {
|
|
3033
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3034
|
+
void postToAISnitch({
|
|
3035
|
+
event: "command:new",
|
|
3036
|
+
sessionKey: getSessionKey(ctx),
|
|
3037
|
+
context: {
|
|
3038
|
+
...ctx,
|
|
3039
|
+
message: event.prompt ?? event.message ?? (ctx as any)?.bodyForAgent,
|
|
3040
|
+
},
|
|
3041
|
+
timestamp: new Date().toISOString(),
|
|
3042
|
+
});
|
|
3043
|
+
});
|
|
3044
|
+
|
|
3045
|
+
api.on("agent_end", (event) => {
|
|
3046
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3047
|
+
void postToAISnitch({
|
|
3048
|
+
event: "command:stop",
|
|
3049
|
+
sessionKey: getSessionKey(ctx),
|
|
3050
|
+
context: ctx ?? {},
|
|
3051
|
+
success: event.success,
|
|
3052
|
+
durationMs: event.durationMs,
|
|
3053
|
+
timestamp: new Date().toISOString(),
|
|
3054
|
+
});
|
|
3055
|
+
});
|
|
3056
|
+
|
|
3057
|
+
// \u2500\u2500 Model calls \u2192 thinking / streaming \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3058
|
+
|
|
3059
|
+
api.on("model_call_started", (event) => {
|
|
3060
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3061
|
+
void postToAISnitch({
|
|
3062
|
+
event: "model_call_started",
|
|
3063
|
+
sessionKey: getSessionKey(ctx),
|
|
3064
|
+
cwd: getWorkspaceDir(ctx),
|
|
3065
|
+
context: ctx ?? {},
|
|
3066
|
+
model: event.model,
|
|
3067
|
+
provider: event.provider,
|
|
3068
|
+
timestamp: new Date().toISOString(),
|
|
3069
|
+
});
|
|
3070
|
+
});
|
|
3071
|
+
|
|
3072
|
+
api.on("model_call_ended", (event) => {
|
|
3073
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3074
|
+
void postToAISnitch({
|
|
3075
|
+
event: "model_call_ended",
|
|
3076
|
+
sessionKey: getSessionKey(ctx),
|
|
3077
|
+
cwd: getWorkspaceDir(ctx),
|
|
3078
|
+
context: ctx ?? {},
|
|
3079
|
+
model: event.model,
|
|
3080
|
+
durationMs: event.durationMs,
|
|
3081
|
+
outcome: event.outcome,
|
|
3082
|
+
timestamp: new Date().toISOString(),
|
|
3083
|
+
});
|
|
3084
|
+
});
|
|
3085
|
+
|
|
3086
|
+
// \u2500\u2500 Tool calls \u2014 richest signal for AISnitch \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3087
|
+
|
|
3088
|
+
api.on("before_tool_call", (event) => {
|
|
3089
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3090
|
+
void postToAISnitch({
|
|
3091
|
+
event: "before_tool_call",
|
|
3092
|
+
sessionKey: getSessionKey(ctx),
|
|
3093
|
+
cwd: getWorkspaceDir(ctx),
|
|
3094
|
+
context: ctx ?? {},
|
|
3095
|
+
toolName: event.toolName,
|
|
3096
|
+
toolInput: event.params,
|
|
3097
|
+
timestamp: new Date().toISOString(),
|
|
3098
|
+
});
|
|
3099
|
+
});
|
|
3100
|
+
|
|
3101
|
+
api.on("after_tool_call", (event) => {
|
|
3102
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3103
|
+
void postToAISnitch({
|
|
3104
|
+
event: "tool_result_persist",
|
|
3105
|
+
sessionKey: getSessionKey(ctx),
|
|
3106
|
+
cwd: getWorkspaceDir(ctx),
|
|
3107
|
+
context: ctx ?? {},
|
|
3108
|
+
toolName: event.toolName,
|
|
3109
|
+
toolInput: event.params,
|
|
3110
|
+
error: event.error,
|
|
3111
|
+
duration: event.duration,
|
|
3112
|
+
result: event.result,
|
|
3113
|
+
timestamp: new Date().toISOString(),
|
|
3114
|
+
});
|
|
3115
|
+
});
|
|
3116
|
+
|
|
3117
|
+
// \u2500\u2500 Compaction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3118
|
+
|
|
3119
|
+
api.on("before_compaction", (event) => {
|
|
3120
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3121
|
+
void postToAISnitch({
|
|
3122
|
+
event: "before_compaction",
|
|
3123
|
+
sessionKey: getSessionKey(ctx),
|
|
3124
|
+
cwd: getWorkspaceDir(ctx),
|
|
3125
|
+
context: ctx ?? {},
|
|
3126
|
+
timestamp: new Date().toISOString(),
|
|
3127
|
+
});
|
|
3128
|
+
});
|
|
3129
|
+
|
|
3130
|
+
api.on("after_compaction", (event) => {
|
|
3131
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3132
|
+
void postToAISnitch({
|
|
3133
|
+
event: "session:compact:after",
|
|
3134
|
+
sessionKey: getSessionKey(ctx),
|
|
3135
|
+
cwd: getWorkspaceDir(ctx),
|
|
3136
|
+
context: ctx ?? {},
|
|
3137
|
+
timestamp: new Date().toISOString(),
|
|
3138
|
+
});
|
|
3139
|
+
});
|
|
3140
|
+
|
|
3141
|
+
// \u2500\u2500 Messages \u2014 user input context \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3142
|
+
|
|
3143
|
+
api.on("message_received", (event) => {
|
|
3144
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3145
|
+
void postToAISnitch({
|
|
3146
|
+
event: "message:received",
|
|
3147
|
+
sessionKey: getSessionKey(ctx),
|
|
3148
|
+
cwd: getWorkspaceDir(ctx),
|
|
3149
|
+
context: ctx ?? {},
|
|
3150
|
+
message: event.message,
|
|
3151
|
+
timestamp: new Date().toISOString(),
|
|
3152
|
+
});
|
|
3153
|
+
});
|
|
3154
|
+
},
|
|
3155
|
+
});
|
|
3156
|
+
`;
|
|
3157
|
+
}
|
|
2873
3158
|
function parseOpenClawSettings(currentContent) {
|
|
2874
3159
|
if (currentContent === null || currentContent.trim().length === 0) {
|
|
2875
3160
|
return {};
|
|
@@ -3182,8 +3467,8 @@ function toConfigPathOptions(options) {
|
|
|
3182
3467
|
|
|
3183
3468
|
// src/cli/runtime.ts
|
|
3184
3469
|
import { execFile as execFileCallback14, spawn as spawnChildProcess2 } from "child_process";
|
|
3185
|
-
import { closeSync, openSync } from "fs";
|
|
3186
|
-
import { mkdtemp, readFile as readFile15, rename, rm as rm4, writeFile as writeFile5 } from "fs/promises";
|
|
3470
|
+
import { closeSync, constants as fsConstants4, openSync } from "fs";
|
|
3471
|
+
import { access as access4, mkdtemp, readFile as readFile15, rename, rm as rm4, writeFile as writeFile5 } from "fs/promises";
|
|
3187
3472
|
import { createConnection as createConnection3 } from "net";
|
|
3188
3473
|
import { tmpdir } from "os";
|
|
3189
3474
|
import { basename as basename12, join as join18 } from "path";
|
|
@@ -10725,6 +11010,7 @@ var OpenClawAdapter = class extends BaseAdapter {
|
|
|
10725
11010
|
displayName = "OpenClaw";
|
|
10726
11011
|
name = "openclaw";
|
|
10727
11012
|
strategies = [
|
|
11013
|
+
"plugin",
|
|
10728
11014
|
"hooks",
|
|
10729
11015
|
"log-watch",
|
|
10730
11016
|
"jsonl-watch",
|
|
@@ -10944,11 +11230,32 @@ var OpenClawAdapter = class extends BaseAdapter {
|
|
|
10944
11230
|
await this.emitOpenClawSessionEnd(sharedData, context);
|
|
10945
11231
|
return;
|
|
10946
11232
|
}
|
|
10947
|
-
case "
|
|
10948
|
-
case "before_compaction": {
|
|
11233
|
+
case "model_call_started": {
|
|
10949
11234
|
await this.ensureSessionStarted(sharedData, context);
|
|
10950
11235
|
this.clearThinking(sessionId);
|
|
10951
|
-
await this.emitStateChange("agent.
|
|
11236
|
+
await this.emitStateChange("agent.thinking", sharedData, context);
|
|
11237
|
+
return;
|
|
11238
|
+
}
|
|
11239
|
+
case "model_call_ended": {
|
|
11240
|
+
await this.ensureSessionStarted(sharedData, context);
|
|
11241
|
+
await this.emitStateChange("agent.streaming", {
|
|
11242
|
+
...sharedData,
|
|
11243
|
+
raw: {
|
|
11244
|
+
...sharedData.raw ?? {},
|
|
11245
|
+
durationMs: getNumber7(payload, "durationMs"),
|
|
11246
|
+
outcome: getString9(payload, "outcome"),
|
|
11247
|
+
source: "plugin"
|
|
11248
|
+
}
|
|
11249
|
+
}, context);
|
|
11250
|
+
return;
|
|
11251
|
+
}
|
|
11252
|
+
case "before_tool_call": {
|
|
11253
|
+
await this.ensureSessionStarted(sharedData, context);
|
|
11254
|
+
await this.emitStateChange(
|
|
11255
|
+
isOpenClawCodingTool(sharedData.toolName, sharedData.toolInput) ? "agent.coding" : "agent.tool_call",
|
|
11256
|
+
sharedData,
|
|
11257
|
+
context
|
|
11258
|
+
);
|
|
10952
11259
|
return;
|
|
10953
11260
|
}
|
|
10954
11261
|
case "tool_result_persist": {
|
|
@@ -10961,6 +11268,13 @@ var OpenClawAdapter = class extends BaseAdapter {
|
|
|
10961
11268
|
this.scheduleThinking(sessionId, sharedData, context, POST_TOOL_THINKING_DELAY_MS);
|
|
10962
11269
|
return;
|
|
10963
11270
|
}
|
|
11271
|
+
case "session:compact:before":
|
|
11272
|
+
case "before_compaction": {
|
|
11273
|
+
await this.ensureSessionStarted(sharedData, context);
|
|
11274
|
+
this.clearThinking(sessionId);
|
|
11275
|
+
await this.emitStateChange("agent.compact", sharedData, context);
|
|
11276
|
+
return;
|
|
11277
|
+
}
|
|
10964
11278
|
case "message:received":
|
|
10965
11279
|
case "message:preprocessed":
|
|
10966
11280
|
case "session:compact:after":
|
|
@@ -11420,6 +11734,7 @@ function buildOpenClawEventData(payload) {
|
|
|
11420
11734
|
return {
|
|
11421
11735
|
activeFile: extractOpenClawActiveFile(payload) ?? toolInput?.filePath,
|
|
11422
11736
|
cwd,
|
|
11737
|
+
duration: getNumber7(payload, "duration") ?? getNumber7(payload, "durationMs"),
|
|
11423
11738
|
errorMessage: extractOpenClawErrorMessage(payload),
|
|
11424
11739
|
errorType: inferOpenClawErrorType(payload),
|
|
11425
11740
|
model: extractOpenClawModel(payload),
|
|
@@ -11484,7 +11799,7 @@ function extractOpenClawToolInput(payload) {
|
|
|
11484
11799
|
};
|
|
11485
11800
|
}
|
|
11486
11801
|
function extractOpenClawErrorMessage(payload) {
|
|
11487
|
-
return getString9(payload, "error") ?? getString9(payload, "message") ?? getString9(getRecord8(payload.error), "message") ?? getString9(getRecord8(payload.result), "error");
|
|
11802
|
+
return getString9(payload, "error") ?? getString9(payload, "errorMessage") ?? getString9(payload, "message") ?? getString9(getRecord8(payload.error), "message") ?? getString9(getRecord8(payload.result), "error") ?? getString9(getRecord8(payload.result), "message");
|
|
11488
11803
|
}
|
|
11489
11804
|
function inferOpenClawErrorType(payload) {
|
|
11490
11805
|
const errorMessage = extractOpenClawErrorMessage(payload);
|
|
@@ -15605,6 +15920,20 @@ var DAEMON_READY_POLL_INTERVAL_MS = 100;
|
|
|
15605
15920
|
var DAEMON_STOP_TIMEOUT_MS = 4e3;
|
|
15606
15921
|
var DAEMON_LOG_MAX_BYTES = 5 * 1024 * 1024;
|
|
15607
15922
|
var LAUNCH_AGENT_LABEL = "com.aisnitch.daemon";
|
|
15923
|
+
async function resolveNodeExecutable() {
|
|
15924
|
+
try {
|
|
15925
|
+
await access4(process.execPath, fsConstants4.X_OK);
|
|
15926
|
+
return process.execPath;
|
|
15927
|
+
} catch {
|
|
15928
|
+
return "node";
|
|
15929
|
+
}
|
|
15930
|
+
}
|
|
15931
|
+
function formatSpawnError(error) {
|
|
15932
|
+
if (error instanceof Error) {
|
|
15933
|
+
return error.message;
|
|
15934
|
+
}
|
|
15935
|
+
return String(error);
|
|
15936
|
+
}
|
|
15608
15937
|
function createCliRuntime(dependencies = {}) {
|
|
15609
15938
|
const output = dependencies.output ?? createProcessOutput();
|
|
15610
15939
|
const fetchImplementation = dependencies.fetch ?? globalThis.fetch;
|
|
@@ -16104,11 +16433,11 @@ function createCliRuntime(dependencies = {}) {
|
|
|
16104
16433
|
}
|
|
16105
16434
|
async function fullscreen(options) {
|
|
16106
16435
|
const snapshot = await getStatusSnapshot(options);
|
|
16107
|
-
if (!snapshot.running && options.
|
|
16436
|
+
if (!snapshot.running && options.daemon) {
|
|
16108
16437
|
output.stdout("Starting daemon...\n");
|
|
16109
16438
|
await startDetachedDaemon(options);
|
|
16110
16439
|
}
|
|
16111
|
-
if (!snapshot.running && !options.
|
|
16440
|
+
if (!snapshot.running && !options.daemon) {
|
|
16112
16441
|
throw new Error(
|
|
16113
16442
|
"AISnitch daemon is not running. Start one with `aisnitch start --daemon` or use `aisnitch fs --daemon` to start and open the dashboard."
|
|
16114
16443
|
);
|
|
@@ -16123,7 +16452,8 @@ function createCliRuntime(dependencies = {}) {
|
|
|
16123
16452
|
const distPath = join18(process.cwd(), "examples", "fullscreen-dashboard", "dist");
|
|
16124
16453
|
output.stdout(`Starting dashboard server on port ${dashboardPort}...
|
|
16125
16454
|
`);
|
|
16126
|
-
const
|
|
16455
|
+
const nodeExecutable = await resolveNodeExecutable();
|
|
16456
|
+
const viteProcess = spawnImplementation(nodeExecutable, [
|
|
16127
16457
|
"-e",
|
|
16128
16458
|
`
|
|
16129
16459
|
import { createServer } from 'vite';
|
|
@@ -16155,6 +16485,12 @@ process.stdin.resume();
|
|
|
16155
16485
|
stdio: ["pipe", "pipe", "pipe"]
|
|
16156
16486
|
});
|
|
16157
16487
|
let serverOutput = "";
|
|
16488
|
+
let serverSpawnError;
|
|
16489
|
+
viteProcess.on("error", (error) => {
|
|
16490
|
+
serverSpawnError = error;
|
|
16491
|
+
serverOutput += `Dashboard server process failed: ${formatSpawnError(error)}
|
|
16492
|
+
`;
|
|
16493
|
+
});
|
|
16158
16494
|
viteProcess.stdout?.on("data", (data) => {
|
|
16159
16495
|
serverOutput += data.toString();
|
|
16160
16496
|
});
|
|
@@ -16172,11 +16508,19 @@ process.stdin.resume();
|
|
|
16172
16508
|
}
|
|
16173
16509
|
} catch {
|
|
16174
16510
|
}
|
|
16511
|
+
if (serverSpawnError !== void 0) {
|
|
16512
|
+
break;
|
|
16513
|
+
}
|
|
16175
16514
|
if (!viteProcess.pid) break;
|
|
16176
16515
|
}
|
|
16177
16516
|
if (!serverReady) {
|
|
16178
16517
|
output.stdout(`Server output: ${serverOutput}
|
|
16179
16518
|
`);
|
|
16519
|
+
if (serverSpawnError !== void 0) {
|
|
16520
|
+
throw new Error(
|
|
16521
|
+
`Failed to start dashboard server process with ${nodeExecutable}: ${formatSpawnError(serverSpawnError)}`
|
|
16522
|
+
);
|
|
16523
|
+
}
|
|
16180
16524
|
throw new Error("Failed to start dashboard server");
|
|
16181
16525
|
}
|
|
16182
16526
|
output.stdout(`Dashboard ready at ${dashboardUrl}
|