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.cjs
CHANGED
|
@@ -771,7 +771,7 @@ var import_commander = require("commander");
|
|
|
771
771
|
|
|
772
772
|
// src/package-info.ts
|
|
773
773
|
var AISNITCH_PACKAGE_NAME = "aisnitch";
|
|
774
|
-
var AISNITCH_VERSION = "0.2.
|
|
774
|
+
var AISNITCH_VERSION = "0.2.24";
|
|
775
775
|
var AISNITCH_DESCRIPTION = "Universal bridge for AI coding tool activity \u2014 capture, normalize, stream.";
|
|
776
776
|
|
|
777
777
|
// src/core/events/schema.ts
|
|
@@ -1955,6 +1955,9 @@ var OpenClawSetup = class {
|
|
|
1955
1955
|
hookHandlerPath;
|
|
1956
1956
|
hookUrl;
|
|
1957
1957
|
openclawHomeDirectory;
|
|
1958
|
+
pluginDirectory;
|
|
1959
|
+
pluginFilePath;
|
|
1960
|
+
pluginDocumentPath;
|
|
1958
1961
|
toolName = "openclaw";
|
|
1959
1962
|
constructor(httpPort, dependencies = {}) {
|
|
1960
1963
|
this.binaryExists = dependencies.binaryExists ?? isBinaryAvailable;
|
|
@@ -1968,6 +1971,13 @@ var OpenClawSetup = class {
|
|
|
1968
1971
|
this.hookDocumentPath = (0, import_node_path2.join)(this.hookDirectory, "HOOK.md");
|
|
1969
1972
|
this.hookHandlerPath = (0, import_node_path2.join)(this.hookDirectory, "handler.ts");
|
|
1970
1973
|
this.hookUrl = `http://localhost:${httpPort}/hooks/openclaw`;
|
|
1974
|
+
this.pluginDirectory = (0, import_node_path2.join)(
|
|
1975
|
+
this.openclawHomeDirectory,
|
|
1976
|
+
"plugins",
|
|
1977
|
+
"aisnitch-monitor"
|
|
1978
|
+
);
|
|
1979
|
+
this.pluginFilePath = (0, import_node_path2.join)(this.pluginDirectory, "index.ts");
|
|
1980
|
+
this.pluginDocumentPath = (0, import_node_path2.join)(this.pluginDirectory, "README.md");
|
|
1971
1981
|
}
|
|
1972
1982
|
async detect() {
|
|
1973
1983
|
return await this.binaryExists("openclaw") || await fileExists(this.openclawHomeDirectory) || await fileExists("/Applications/OpenClaw.app");
|
|
@@ -1979,9 +1989,13 @@ var OpenClawSetup = class {
|
|
|
1979
1989
|
const currentConfigContent = await readOptionalFile(this.configPath);
|
|
1980
1990
|
const currentHookDocument = await readOptionalFile(this.hookDocumentPath);
|
|
1981
1991
|
const currentHookHandler = await readOptionalFile(this.hookHandlerPath);
|
|
1992
|
+
const currentPluginDocument = await readOptionalFile(this.pluginDocumentPath);
|
|
1993
|
+
const currentPluginFile = await readOptionalFile(this.pluginFilePath);
|
|
1982
1994
|
const nextConfigContent = this.buildNextConfigContent(currentConfigContent);
|
|
1983
1995
|
const nextHookDocument = buildOpenClawHookDocumentSource();
|
|
1984
1996
|
const nextHookHandler = buildOpenClawHookHandlerSource(this.hookUrl);
|
|
1997
|
+
const nextPluginDocument = buildOpenClawPluginDocumentSource();
|
|
1998
|
+
const nextPluginFile = buildOpenClawPluginSource(this.hookUrl);
|
|
1985
1999
|
return [
|
|
1986
2000
|
renderColoredDiff(
|
|
1987
2001
|
this.configPath,
|
|
@@ -1999,6 +2013,18 @@ var OpenClawSetup = class {
|
|
|
1999
2013
|
this.hookHandlerPath,
|
|
2000
2014
|
currentHookHandler,
|
|
2001
2015
|
nextHookHandler
|
|
2016
|
+
),
|
|
2017
|
+
"",
|
|
2018
|
+
renderColoredDiff(
|
|
2019
|
+
this.pluginDocumentPath,
|
|
2020
|
+
currentPluginDocument,
|
|
2021
|
+
nextPluginDocument
|
|
2022
|
+
),
|
|
2023
|
+
"",
|
|
2024
|
+
renderColoredDiff(
|
|
2025
|
+
this.pluginFilePath,
|
|
2026
|
+
currentPluginFile,
|
|
2027
|
+
nextPluginFile
|
|
2002
2028
|
)
|
|
2003
2029
|
].join("\n");
|
|
2004
2030
|
}
|
|
@@ -2006,11 +2032,16 @@ var OpenClawSetup = class {
|
|
|
2006
2032
|
const currentConfigContent = await readOptionalFile(this.configPath);
|
|
2007
2033
|
const currentHookDocument = await readOptionalFile(this.hookDocumentPath);
|
|
2008
2034
|
const currentHookHandler = await readOptionalFile(this.hookHandlerPath);
|
|
2035
|
+
const currentPluginDocument = await readOptionalFile(this.pluginDocumentPath);
|
|
2036
|
+
const currentPluginFile = await readOptionalFile(this.pluginFilePath);
|
|
2009
2037
|
const nextConfigContent = this.buildNextConfigContent(currentConfigContent);
|
|
2010
2038
|
const nextHookDocument = buildOpenClawHookDocumentSource();
|
|
2011
2039
|
const nextHookHandler = buildOpenClawHookHandlerSource(this.hookUrl);
|
|
2040
|
+
const nextPluginDocument = buildOpenClawPluginDocumentSource();
|
|
2041
|
+
const nextPluginFile = buildOpenClawPluginSource(this.hookUrl);
|
|
2012
2042
|
await (0, import_promises2.mkdir)((0, import_node_path2.dirname)(this.configPath), { recursive: true });
|
|
2013
2043
|
await (0, import_promises2.mkdir)(this.hookDirectory, { recursive: true });
|
|
2044
|
+
await (0, import_promises2.mkdir)(this.pluginDirectory, { recursive: true });
|
|
2014
2045
|
if (currentConfigContent !== null) {
|
|
2015
2046
|
await (0, import_promises2.copyFile)(this.configPath, this.getBackupPath(this.configPath));
|
|
2016
2047
|
}
|
|
@@ -2026,14 +2057,30 @@ var OpenClawSetup = class {
|
|
|
2026
2057
|
this.getBackupPath(this.hookHandlerPath)
|
|
2027
2058
|
);
|
|
2028
2059
|
}
|
|
2060
|
+
if (currentPluginDocument !== null) {
|
|
2061
|
+
await (0, import_promises2.copyFile)(
|
|
2062
|
+
this.pluginDocumentPath,
|
|
2063
|
+
this.getBackupPath(this.pluginDocumentPath)
|
|
2064
|
+
);
|
|
2065
|
+
}
|
|
2066
|
+
if (currentPluginFile !== null) {
|
|
2067
|
+
await (0, import_promises2.copyFile)(
|
|
2068
|
+
this.pluginFilePath,
|
|
2069
|
+
this.getBackupPath(this.pluginFilePath)
|
|
2070
|
+
);
|
|
2071
|
+
}
|
|
2029
2072
|
await (0, import_promises2.writeFile)(this.configPath, nextConfigContent, "utf8");
|
|
2030
2073
|
await (0, import_promises2.writeFile)(this.hookDocumentPath, nextHookDocument, "utf8");
|
|
2031
2074
|
await (0, import_promises2.writeFile)(this.hookHandlerPath, nextHookHandler, "utf8");
|
|
2075
|
+
await (0, import_promises2.writeFile)(this.pluginDocumentPath, nextPluginDocument, "utf8");
|
|
2076
|
+
await (0, import_promises2.writeFile)(this.pluginFilePath, nextPluginFile, "utf8");
|
|
2032
2077
|
}
|
|
2033
2078
|
async revert() {
|
|
2034
2079
|
await restoreBackupOrRemove(this.configPath);
|
|
2035
2080
|
await restoreBackupOrRemove(this.hookDocumentPath);
|
|
2036
2081
|
await restoreBackupOrRemove(this.hookHandlerPath);
|
|
2082
|
+
await restoreBackupOrRemove(this.pluginDocumentPath);
|
|
2083
|
+
await restoreBackupOrRemove(this.pluginFilePath);
|
|
2037
2084
|
}
|
|
2038
2085
|
buildNextConfigContent(currentContent) {
|
|
2039
2086
|
const parsedConfig = parseOpenClawSettings(currentContent);
|
|
@@ -2055,6 +2102,15 @@ var OpenClawSetup = class {
|
|
|
2055
2102
|
enabled: true
|
|
2056
2103
|
}
|
|
2057
2104
|
};
|
|
2105
|
+
const currentPlugins = parsedConfig.plugins ?? {};
|
|
2106
|
+
const currentPluginEntries = currentPlugins.entries ?? {};
|
|
2107
|
+
const nextPluginEntries = {
|
|
2108
|
+
...currentPluginEntries,
|
|
2109
|
+
"aisnitch-monitor": {
|
|
2110
|
+
...currentPluginEntries["aisnitch-monitor"] ?? {},
|
|
2111
|
+
enabled: true
|
|
2112
|
+
}
|
|
2113
|
+
};
|
|
2058
2114
|
const nextConfig = {
|
|
2059
2115
|
...parsedConfig,
|
|
2060
2116
|
hooks: {
|
|
@@ -2064,6 +2120,10 @@ var OpenClawSetup = class {
|
|
|
2064
2120
|
enabled: true,
|
|
2065
2121
|
entries: nextEntries
|
|
2066
2122
|
}
|
|
2123
|
+
},
|
|
2124
|
+
plugins: {
|
|
2125
|
+
...currentPlugins,
|
|
2126
|
+
entries: nextPluginEntries
|
|
2067
2127
|
}
|
|
2068
2128
|
};
|
|
2069
2129
|
return `${JSON.stringify(nextConfig, null, 2)}
|
|
@@ -2898,6 +2958,231 @@ export default async function aisnitchForward(event) {
|
|
|
2898
2958
|
}
|
|
2899
2959
|
`;
|
|
2900
2960
|
}
|
|
2961
|
+
function buildOpenClawPluginDocumentSource() {
|
|
2962
|
+
return `# AISnitch Monitor Plugin
|
|
2963
|
+
|
|
2964
|
+
\u{1F4D6} This managed plugin uses OpenClaw's Plugin SDK to forward rich real-time
|
|
2965
|
+
events to the local AISnitch HTTP receiver. Unlike the internal hook handler,
|
|
2966
|
+
the plugin has access to tool-level hooks (before_tool_call, after_tool_call),
|
|
2967
|
+
model-level hooks (model_call_started, model_call_ended), and agent turn hooks
|
|
2968
|
+
(agent_end, before_agent_run) \u2014 providing maximum observability fidelity.
|
|
2969
|
+
|
|
2970
|
+
## Hooked Events
|
|
2971
|
+
|
|
2972
|
+
| Hook | AISnitch Event |
|
|
2973
|
+
|:---|:---|
|
|
2974
|
+
| gateway_start | session.start |
|
|
2975
|
+
| gateway_stop | session.end |
|
|
2976
|
+
| before_agent_run | task.start |
|
|
2977
|
+
| agent_end | task.complete |
|
|
2978
|
+
| before_tool_call | agent.coding / agent.tool_call |
|
|
2979
|
+
| after_tool_call | agent.coding / agent.tool_call + results |
|
|
2980
|
+
| model_call_started | agent.thinking |
|
|
2981
|
+
| model_call_ended | agent.streaming |
|
|
2982
|
+
| before_compaction | agent.compact |
|
|
2983
|
+
| after_compaction | agent.compact |
|
|
2984
|
+
| message_received | context info |
|
|
2985
|
+
|
|
2986
|
+
## Managed by AISnitch
|
|
2987
|
+
|
|
2988
|
+
This file is managed by \`aisnitch setup openclaw\`. Re-running setup will
|
|
2989
|
+
overwrite it. Use \`aisnitch setup openclaw --revert\` to remove it.
|
|
2990
|
+
`;
|
|
2991
|
+
}
|
|
2992
|
+
function buildOpenClawPluginSource(hookUrl) {
|
|
2993
|
+
return `/**
|
|
2994
|
+
* AISnitch OpenClaw Plugin
|
|
2995
|
+
*
|
|
2996
|
+
* \u{1F4D6} Uses OpenClaw's Plugin SDK to forward rich real-time events to AISnitch.
|
|
2997
|
+
* Provides maximum visibility into tool calls, model usage, agent turns,
|
|
2998
|
+
* and lifecycle events \u2014 far beyond what passive file-watching can achieve.
|
|
2999
|
+
*
|
|
3000
|
+
* Managed by \`aisnitch setup openclaw\`. Re-running setup overwrites this file.
|
|
3001
|
+
*/
|
|
3002
|
+
|
|
3003
|
+
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
3004
|
+
|
|
3005
|
+
const AISNITCH_ENDPOINT = ${JSON.stringify(hookUrl)};
|
|
3006
|
+
|
|
3007
|
+
async function postToAISnitch(payload: Record<string, unknown>): Promise<void> {
|
|
3008
|
+
try {
|
|
3009
|
+
await fetch(AISNITCH_ENDPOINT, {
|
|
3010
|
+
method: "POST",
|
|
3011
|
+
headers: { "content-type": "application/json" },
|
|
3012
|
+
body: JSON.stringify(payload),
|
|
3013
|
+
});
|
|
3014
|
+
} catch {
|
|
3015
|
+
// Silently ignore transport errors so OpenClaw keeps running.
|
|
3016
|
+
}
|
|
3017
|
+
}
|
|
3018
|
+
|
|
3019
|
+
function getSessionKey(ctx: Record<string, unknown> | undefined): string | undefined {
|
|
3020
|
+
if (!ctx) return undefined;
|
|
3021
|
+
return (
|
|
3022
|
+
(typeof ctx.sessionKey === "string" && ctx.sessionKey.length > 0 ? ctx.sessionKey : undefined) ??
|
|
3023
|
+
(typeof ctx.sessionId === "string" && ctx.sessionId.length > 0 ? ctx.sessionId : undefined)
|
|
3024
|
+
);
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
function getWorkspaceDir(ctx: Record<string, unknown> | undefined): string | undefined {
|
|
3028
|
+
if (!ctx) return undefined;
|
|
3029
|
+
return (
|
|
3030
|
+
(typeof ctx.workspaceDir === "string" && ctx.workspaceDir.length > 0 ? ctx.workspaceDir : undefined) ??
|
|
3031
|
+
(typeof ctx.cwd === "string" && ctx.cwd.length > 0 ? ctx.cwd : undefined)
|
|
3032
|
+
);
|
|
3033
|
+
}
|
|
3034
|
+
|
|
3035
|
+
export default definePluginEntry({
|
|
3036
|
+
id: "aisnitch-monitor",
|
|
3037
|
+
name: "AISnitch Monitor",
|
|
3038
|
+
register(api) {
|
|
3039
|
+
// \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
|
|
3040
|
+
|
|
3041
|
+
api.on("gateway_start", (event) => {
|
|
3042
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3043
|
+
void postToAISnitch({
|
|
3044
|
+
event: "gateway:startup",
|
|
3045
|
+
sessionKey: getSessionKey(ctx),
|
|
3046
|
+
context: ctx ?? {},
|
|
3047
|
+
timestamp: new Date().toISOString(),
|
|
3048
|
+
});
|
|
3049
|
+
});
|
|
3050
|
+
|
|
3051
|
+
api.on("gateway_stop", () => {
|
|
3052
|
+
void postToAISnitch({
|
|
3053
|
+
event: "gateway:shutdown",
|
|
3054
|
+
timestamp: new Date().toISOString(),
|
|
3055
|
+
});
|
|
3056
|
+
});
|
|
3057
|
+
|
|
3058
|
+
// \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
|
|
3059
|
+
|
|
3060
|
+
api.on("before_agent_run", (event) => {
|
|
3061
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3062
|
+
void postToAISnitch({
|
|
3063
|
+
event: "command:new",
|
|
3064
|
+
sessionKey: getSessionKey(ctx),
|
|
3065
|
+
context: {
|
|
3066
|
+
...ctx,
|
|
3067
|
+
message: event.prompt ?? event.message ?? (ctx as any)?.bodyForAgent,
|
|
3068
|
+
},
|
|
3069
|
+
timestamp: new Date().toISOString(),
|
|
3070
|
+
});
|
|
3071
|
+
});
|
|
3072
|
+
|
|
3073
|
+
api.on("agent_end", (event) => {
|
|
3074
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3075
|
+
void postToAISnitch({
|
|
3076
|
+
event: "command:stop",
|
|
3077
|
+
sessionKey: getSessionKey(ctx),
|
|
3078
|
+
context: ctx ?? {},
|
|
3079
|
+
success: event.success,
|
|
3080
|
+
durationMs: event.durationMs,
|
|
3081
|
+
timestamp: new Date().toISOString(),
|
|
3082
|
+
});
|
|
3083
|
+
});
|
|
3084
|
+
|
|
3085
|
+
// \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
|
|
3086
|
+
|
|
3087
|
+
api.on("model_call_started", (event) => {
|
|
3088
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3089
|
+
void postToAISnitch({
|
|
3090
|
+
event: "model_call_started",
|
|
3091
|
+
sessionKey: getSessionKey(ctx),
|
|
3092
|
+
cwd: getWorkspaceDir(ctx),
|
|
3093
|
+
context: ctx ?? {},
|
|
3094
|
+
model: event.model,
|
|
3095
|
+
provider: event.provider,
|
|
3096
|
+
timestamp: new Date().toISOString(),
|
|
3097
|
+
});
|
|
3098
|
+
});
|
|
3099
|
+
|
|
3100
|
+
api.on("model_call_ended", (event) => {
|
|
3101
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3102
|
+
void postToAISnitch({
|
|
3103
|
+
event: "model_call_ended",
|
|
3104
|
+
sessionKey: getSessionKey(ctx),
|
|
3105
|
+
cwd: getWorkspaceDir(ctx),
|
|
3106
|
+
context: ctx ?? {},
|
|
3107
|
+
model: event.model,
|
|
3108
|
+
durationMs: event.durationMs,
|
|
3109
|
+
outcome: event.outcome,
|
|
3110
|
+
timestamp: new Date().toISOString(),
|
|
3111
|
+
});
|
|
3112
|
+
});
|
|
3113
|
+
|
|
3114
|
+
// \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
|
|
3115
|
+
|
|
3116
|
+
api.on("before_tool_call", (event) => {
|
|
3117
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3118
|
+
void postToAISnitch({
|
|
3119
|
+
event: "before_tool_call",
|
|
3120
|
+
sessionKey: getSessionKey(ctx),
|
|
3121
|
+
cwd: getWorkspaceDir(ctx),
|
|
3122
|
+
context: ctx ?? {},
|
|
3123
|
+
toolName: event.toolName,
|
|
3124
|
+
toolInput: event.params,
|
|
3125
|
+
timestamp: new Date().toISOString(),
|
|
3126
|
+
});
|
|
3127
|
+
});
|
|
3128
|
+
|
|
3129
|
+
api.on("after_tool_call", (event) => {
|
|
3130
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3131
|
+
void postToAISnitch({
|
|
3132
|
+
event: "tool_result_persist",
|
|
3133
|
+
sessionKey: getSessionKey(ctx),
|
|
3134
|
+
cwd: getWorkspaceDir(ctx),
|
|
3135
|
+
context: ctx ?? {},
|
|
3136
|
+
toolName: event.toolName,
|
|
3137
|
+
toolInput: event.params,
|
|
3138
|
+
error: event.error,
|
|
3139
|
+
duration: event.duration,
|
|
3140
|
+
result: event.result,
|
|
3141
|
+
timestamp: new Date().toISOString(),
|
|
3142
|
+
});
|
|
3143
|
+
});
|
|
3144
|
+
|
|
3145
|
+
// \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
|
|
3146
|
+
|
|
3147
|
+
api.on("before_compaction", (event) => {
|
|
3148
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3149
|
+
void postToAISnitch({
|
|
3150
|
+
event: "before_compaction",
|
|
3151
|
+
sessionKey: getSessionKey(ctx),
|
|
3152
|
+
cwd: getWorkspaceDir(ctx),
|
|
3153
|
+
context: ctx ?? {},
|
|
3154
|
+
timestamp: new Date().toISOString(),
|
|
3155
|
+
});
|
|
3156
|
+
});
|
|
3157
|
+
|
|
3158
|
+
api.on("after_compaction", (event) => {
|
|
3159
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3160
|
+
void postToAISnitch({
|
|
3161
|
+
event: "session:compact:after",
|
|
3162
|
+
sessionKey: getSessionKey(ctx),
|
|
3163
|
+
cwd: getWorkspaceDir(ctx),
|
|
3164
|
+
context: ctx ?? {},
|
|
3165
|
+
timestamp: new Date().toISOString(),
|
|
3166
|
+
});
|
|
3167
|
+
});
|
|
3168
|
+
|
|
3169
|
+
// \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
|
|
3170
|
+
|
|
3171
|
+
api.on("message_received", (event) => {
|
|
3172
|
+
const ctx = event.ctx as Record<string, unknown> | undefined;
|
|
3173
|
+
void postToAISnitch({
|
|
3174
|
+
event: "message:received",
|
|
3175
|
+
sessionKey: getSessionKey(ctx),
|
|
3176
|
+
cwd: getWorkspaceDir(ctx),
|
|
3177
|
+
context: ctx ?? {},
|
|
3178
|
+
message: event.message,
|
|
3179
|
+
timestamp: new Date().toISOString(),
|
|
3180
|
+
});
|
|
3181
|
+
});
|
|
3182
|
+
},
|
|
3183
|
+
});
|
|
3184
|
+
`;
|
|
3185
|
+
}
|
|
2901
3186
|
function parseOpenClawSettings(currentContent) {
|
|
2902
3187
|
if (currentContent === null || currentContent.trim().length === 0) {
|
|
2903
3188
|
return {};
|
|
@@ -10751,6 +11036,7 @@ var OpenClawAdapter = class extends BaseAdapter {
|
|
|
10751
11036
|
displayName = "OpenClaw";
|
|
10752
11037
|
name = "openclaw";
|
|
10753
11038
|
strategies = [
|
|
11039
|
+
"plugin",
|
|
10754
11040
|
"hooks",
|
|
10755
11041
|
"log-watch",
|
|
10756
11042
|
"jsonl-watch",
|
|
@@ -10970,11 +11256,32 @@ var OpenClawAdapter = class extends BaseAdapter {
|
|
|
10970
11256
|
await this.emitOpenClawSessionEnd(sharedData, context);
|
|
10971
11257
|
return;
|
|
10972
11258
|
}
|
|
10973
|
-
case "
|
|
10974
|
-
case "before_compaction": {
|
|
11259
|
+
case "model_call_started": {
|
|
10975
11260
|
await this.ensureSessionStarted(sharedData, context);
|
|
10976
11261
|
this.clearThinking(sessionId);
|
|
10977
|
-
await this.emitStateChange("agent.
|
|
11262
|
+
await this.emitStateChange("agent.thinking", sharedData, context);
|
|
11263
|
+
return;
|
|
11264
|
+
}
|
|
11265
|
+
case "model_call_ended": {
|
|
11266
|
+
await this.ensureSessionStarted(sharedData, context);
|
|
11267
|
+
await this.emitStateChange("agent.streaming", {
|
|
11268
|
+
...sharedData,
|
|
11269
|
+
raw: {
|
|
11270
|
+
...sharedData.raw ?? {},
|
|
11271
|
+
durationMs: getNumber7(payload, "durationMs"),
|
|
11272
|
+
outcome: getString9(payload, "outcome"),
|
|
11273
|
+
source: "plugin"
|
|
11274
|
+
}
|
|
11275
|
+
}, context);
|
|
11276
|
+
return;
|
|
11277
|
+
}
|
|
11278
|
+
case "before_tool_call": {
|
|
11279
|
+
await this.ensureSessionStarted(sharedData, context);
|
|
11280
|
+
await this.emitStateChange(
|
|
11281
|
+
isOpenClawCodingTool(sharedData.toolName, sharedData.toolInput) ? "agent.coding" : "agent.tool_call",
|
|
11282
|
+
sharedData,
|
|
11283
|
+
context
|
|
11284
|
+
);
|
|
10978
11285
|
return;
|
|
10979
11286
|
}
|
|
10980
11287
|
case "tool_result_persist": {
|
|
@@ -10987,6 +11294,13 @@ var OpenClawAdapter = class extends BaseAdapter {
|
|
|
10987
11294
|
this.scheduleThinking(sessionId, sharedData, context, POST_TOOL_THINKING_DELAY_MS);
|
|
10988
11295
|
return;
|
|
10989
11296
|
}
|
|
11297
|
+
case "session:compact:before":
|
|
11298
|
+
case "before_compaction": {
|
|
11299
|
+
await this.ensureSessionStarted(sharedData, context);
|
|
11300
|
+
this.clearThinking(sessionId);
|
|
11301
|
+
await this.emitStateChange("agent.compact", sharedData, context);
|
|
11302
|
+
return;
|
|
11303
|
+
}
|
|
10990
11304
|
case "message:received":
|
|
10991
11305
|
case "message:preprocessed":
|
|
10992
11306
|
case "session:compact:after":
|
|
@@ -11446,6 +11760,7 @@ function buildOpenClawEventData(payload) {
|
|
|
11446
11760
|
return {
|
|
11447
11761
|
activeFile: extractOpenClawActiveFile(payload) ?? toolInput?.filePath,
|
|
11448
11762
|
cwd,
|
|
11763
|
+
duration: getNumber7(payload, "duration") ?? getNumber7(payload, "durationMs"),
|
|
11449
11764
|
errorMessage: extractOpenClawErrorMessage(payload),
|
|
11450
11765
|
errorType: inferOpenClawErrorType(payload),
|
|
11451
11766
|
model: extractOpenClawModel(payload),
|
|
@@ -11510,7 +11825,7 @@ function extractOpenClawToolInput(payload) {
|
|
|
11510
11825
|
};
|
|
11511
11826
|
}
|
|
11512
11827
|
function extractOpenClawErrorMessage(payload) {
|
|
11513
|
-
return getString9(payload, "error") ?? getString9(payload, "message") ?? getString9(getRecord8(payload.error), "message") ?? getString9(getRecord8(payload.result), "error");
|
|
11828
|
+
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");
|
|
11514
11829
|
}
|
|
11515
11830
|
function inferOpenClawErrorType(payload) {
|
|
11516
11831
|
const errorMessage = extractOpenClawErrorMessage(payload);
|
|
@@ -15631,6 +15946,20 @@ var DAEMON_READY_POLL_INTERVAL_MS = 100;
|
|
|
15631
15946
|
var DAEMON_STOP_TIMEOUT_MS = 4e3;
|
|
15632
15947
|
var DAEMON_LOG_MAX_BYTES = 5 * 1024 * 1024;
|
|
15633
15948
|
var LAUNCH_AGENT_LABEL = "com.aisnitch.daemon";
|
|
15949
|
+
async function resolveNodeExecutable() {
|
|
15950
|
+
try {
|
|
15951
|
+
await (0, import_promises22.access)(process.execPath, import_node_fs7.constants.X_OK);
|
|
15952
|
+
return process.execPath;
|
|
15953
|
+
} catch {
|
|
15954
|
+
return "node";
|
|
15955
|
+
}
|
|
15956
|
+
}
|
|
15957
|
+
function formatSpawnError(error) {
|
|
15958
|
+
if (error instanceof Error) {
|
|
15959
|
+
return error.message;
|
|
15960
|
+
}
|
|
15961
|
+
return String(error);
|
|
15962
|
+
}
|
|
15634
15963
|
function createCliRuntime(dependencies = {}) {
|
|
15635
15964
|
const output = dependencies.output ?? createProcessOutput();
|
|
15636
15965
|
const fetchImplementation = dependencies.fetch ?? globalThis.fetch;
|
|
@@ -16130,11 +16459,11 @@ function createCliRuntime(dependencies = {}) {
|
|
|
16130
16459
|
}
|
|
16131
16460
|
async function fullscreen(options) {
|
|
16132
16461
|
const snapshot = await getStatusSnapshot(options);
|
|
16133
|
-
if (!snapshot.running && options.
|
|
16462
|
+
if (!snapshot.running && options.daemon) {
|
|
16134
16463
|
output.stdout("Starting daemon...\n");
|
|
16135
16464
|
await startDetachedDaemon(options);
|
|
16136
16465
|
}
|
|
16137
|
-
if (!snapshot.running && !options.
|
|
16466
|
+
if (!snapshot.running && !options.daemon) {
|
|
16138
16467
|
throw new Error(
|
|
16139
16468
|
"AISnitch daemon is not running. Start one with `aisnitch start --daemon` or use `aisnitch fs --daemon` to start and open the dashboard."
|
|
16140
16469
|
);
|
|
@@ -16149,7 +16478,8 @@ function createCliRuntime(dependencies = {}) {
|
|
|
16149
16478
|
const distPath = (0, import_node_path22.join)(process.cwd(), "examples", "fullscreen-dashboard", "dist");
|
|
16150
16479
|
output.stdout(`Starting dashboard server on port ${dashboardPort}...
|
|
16151
16480
|
`);
|
|
16152
|
-
const
|
|
16481
|
+
const nodeExecutable = await resolveNodeExecutable();
|
|
16482
|
+
const viteProcess = spawnImplementation(nodeExecutable, [
|
|
16153
16483
|
"-e",
|
|
16154
16484
|
`
|
|
16155
16485
|
import { createServer } from 'vite';
|
|
@@ -16181,6 +16511,12 @@ process.stdin.resume();
|
|
|
16181
16511
|
stdio: ["pipe", "pipe", "pipe"]
|
|
16182
16512
|
});
|
|
16183
16513
|
let serverOutput = "";
|
|
16514
|
+
let serverSpawnError;
|
|
16515
|
+
viteProcess.on("error", (error) => {
|
|
16516
|
+
serverSpawnError = error;
|
|
16517
|
+
serverOutput += `Dashboard server process failed: ${formatSpawnError(error)}
|
|
16518
|
+
`;
|
|
16519
|
+
});
|
|
16184
16520
|
viteProcess.stdout?.on("data", (data) => {
|
|
16185
16521
|
serverOutput += data.toString();
|
|
16186
16522
|
});
|
|
@@ -16198,11 +16534,19 @@ process.stdin.resume();
|
|
|
16198
16534
|
}
|
|
16199
16535
|
} catch {
|
|
16200
16536
|
}
|
|
16537
|
+
if (serverSpawnError !== void 0) {
|
|
16538
|
+
break;
|
|
16539
|
+
}
|
|
16201
16540
|
if (!viteProcess.pid) break;
|
|
16202
16541
|
}
|
|
16203
16542
|
if (!serverReady) {
|
|
16204
16543
|
output.stdout(`Server output: ${serverOutput}
|
|
16205
16544
|
`);
|
|
16545
|
+
if (serverSpawnError !== void 0) {
|
|
16546
|
+
throw new Error(
|
|
16547
|
+
`Failed to start dashboard server process with ${nodeExecutable}: ${formatSpawnError(serverSpawnError)}`
|
|
16548
|
+
);
|
|
16549
|
+
}
|
|
16206
16550
|
throw new Error("Failed to start dashboard server");
|
|
16207
16551
|
}
|
|
16208
16552
|
output.stdout(`Dashboard ready at ${dashboardUrl}
|