@upx-us/shield 0.2.12-beta
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.
Potentially problematic release.
This version of @upx-us/shield might be problematic. Click here for more details.
- package/LICENSE +38 -0
- package/README.md +96 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +365 -0
- package/dist/src/config.d.ts +43 -0
- package/dist/src/config.js +181 -0
- package/dist/src/events/base.d.ts +110 -0
- package/dist/src/events/base.js +61 -0
- package/dist/src/events/browser/enrich.d.ts +3 -0
- package/dist/src/events/browser/enrich.js +46 -0
- package/dist/src/events/browser/event.d.ts +10 -0
- package/dist/src/events/browser/event.js +2 -0
- package/dist/src/events/browser/index.d.ts +4 -0
- package/dist/src/events/browser/index.js +13 -0
- package/dist/src/events/browser/redactions.d.ts +2 -0
- package/dist/src/events/browser/redactions.js +4 -0
- package/dist/src/events/browser/validations.d.ts +3 -0
- package/dist/src/events/browser/validations.js +10 -0
- package/dist/src/events/cron/enrich.d.ts +3 -0
- package/dist/src/events/cron/enrich.js +44 -0
- package/dist/src/events/cron/event.d.ts +5 -0
- package/dist/src/events/cron/event.js +2 -0
- package/dist/src/events/cron/index.d.ts +4 -0
- package/dist/src/events/cron/index.js +13 -0
- package/dist/src/events/cron/redactions.d.ts +2 -0
- package/dist/src/events/cron/redactions.js +4 -0
- package/dist/src/events/cron/validations.d.ts +3 -0
- package/dist/src/events/cron/validations.js +4 -0
- package/dist/src/events/exec/enrich.d.ts +3 -0
- package/dist/src/events/exec/enrich.js +80 -0
- package/dist/src/events/exec/event.d.ts +11 -0
- package/dist/src/events/exec/event.js +2 -0
- package/dist/src/events/exec/index.d.ts +4 -0
- package/dist/src/events/exec/index.js +13 -0
- package/dist/src/events/exec/redactions.d.ts +3 -0
- package/dist/src/events/exec/redactions.js +12 -0
- package/dist/src/events/exec/validations.d.ts +3 -0
- package/dist/src/events/exec/validations.js +12 -0
- package/dist/src/events/file/enrich.d.ts +3 -0
- package/dist/src/events/file/enrich.js +63 -0
- package/dist/src/events/file/event.d.ts +11 -0
- package/dist/src/events/file/event.js +2 -0
- package/dist/src/events/file/index.d.ts +4 -0
- package/dist/src/events/file/index.js +13 -0
- package/dist/src/events/file/redactions.d.ts +2 -0
- package/dist/src/events/file/redactions.js +8 -0
- package/dist/src/events/file/validations.d.ts +3 -0
- package/dist/src/events/file/validations.js +10 -0
- package/dist/src/events/gateway/enrich.d.ts +3 -0
- package/dist/src/events/gateway/enrich.js +50 -0
- package/dist/src/events/gateway/event.d.ts +5 -0
- package/dist/src/events/gateway/event.js +2 -0
- package/dist/src/events/gateway/index.d.ts +4 -0
- package/dist/src/events/gateway/index.js +13 -0
- package/dist/src/events/gateway/redactions.d.ts +2 -0
- package/dist/src/events/gateway/redactions.js +4 -0
- package/dist/src/events/gateway/validations.d.ts +3 -0
- package/dist/src/events/gateway/validations.js +4 -0
- package/dist/src/events/generic/enrich.d.ts +3 -0
- package/dist/src/events/generic/enrich.js +30 -0
- package/dist/src/events/generic/event.d.ts +5 -0
- package/dist/src/events/generic/event.js +2 -0
- package/dist/src/events/generic/index.d.ts +5 -0
- package/dist/src/events/generic/index.js +14 -0
- package/dist/src/events/generic/redactions.d.ts +2 -0
- package/dist/src/events/generic/redactions.js +4 -0
- package/dist/src/events/generic/validations.d.ts +3 -0
- package/dist/src/events/generic/validations.js +4 -0
- package/dist/src/events/host-telemetry/enrich.d.ts +3 -0
- package/dist/src/events/host-telemetry/enrich.js +28 -0
- package/dist/src/events/host-telemetry/event.d.ts +4 -0
- package/dist/src/events/host-telemetry/event.js +2 -0
- package/dist/src/events/host-telemetry/index.d.ts +4 -0
- package/dist/src/events/host-telemetry/index.js +13 -0
- package/dist/src/events/host-telemetry/redactions.d.ts +2 -0
- package/dist/src/events/host-telemetry/redactions.js +4 -0
- package/dist/src/events/host-telemetry/validations.d.ts +3 -0
- package/dist/src/events/host-telemetry/validations.js +4 -0
- package/dist/src/events/index.d.ts +40 -0
- package/dist/src/events/index.js +39 -0
- package/dist/src/events/message/enrich.d.ts +3 -0
- package/dist/src/events/message/enrich.js +36 -0
- package/dist/src/events/message/event.d.ts +5 -0
- package/dist/src/events/message/event.js +2 -0
- package/dist/src/events/message/index.d.ts +4 -0
- package/dist/src/events/message/index.js +13 -0
- package/dist/src/events/message/redactions.d.ts +2 -0
- package/dist/src/events/message/redactions.js +4 -0
- package/dist/src/events/message/validations.d.ts +3 -0
- package/dist/src/events/message/validations.js +7 -0
- package/dist/src/events/sessions-spawn/enrich.d.ts +3 -0
- package/dist/src/events/sessions-spawn/enrich.js +40 -0
- package/dist/src/events/sessions-spawn/event.d.ts +9 -0
- package/dist/src/events/sessions-spawn/event.js +2 -0
- package/dist/src/events/sessions-spawn/index.d.ts +4 -0
- package/dist/src/events/sessions-spawn/index.js +13 -0
- package/dist/src/events/sessions-spawn/redactions.d.ts +2 -0
- package/dist/src/events/sessions-spawn/redactions.js +4 -0
- package/dist/src/events/sessions-spawn/validations.d.ts +3 -0
- package/dist/src/events/sessions-spawn/validations.js +4 -0
- package/dist/src/events/tool-result/enrich.d.ts +13 -0
- package/dist/src/events/tool-result/enrich.js +46 -0
- package/dist/src/events/tool-result/event.d.ts +7 -0
- package/dist/src/events/tool-result/event.js +2 -0
- package/dist/src/events/tool-result/index.d.ts +4 -0
- package/dist/src/events/tool-result/index.js +9 -0
- package/dist/src/events/tool-result/redactions.d.ts +2 -0
- package/dist/src/events/tool-result/redactions.js +7 -0
- package/dist/src/events/tool-result/validations.d.ts +3 -0
- package/dist/src/events/tool-result/validations.js +9 -0
- package/dist/src/events/web/enrich.d.ts +8 -0
- package/dist/src/events/web/enrich.js +78 -0
- package/dist/src/events/web/event.d.ts +10 -0
- package/dist/src/events/web/event.js +2 -0
- package/dist/src/events/web/index.d.ts +4 -0
- package/dist/src/events/web/index.js +13 -0
- package/dist/src/events/web/redactions.d.ts +2 -0
- package/dist/src/events/web/redactions.js +6 -0
- package/dist/src/events/web/validations.d.ts +3 -0
- package/dist/src/events/web/validations.js +10 -0
- package/dist/src/fetcher.d.ts +12 -0
- package/dist/src/fetcher.js +182 -0
- package/dist/src/host-collector.d.ts +1 -0
- package/dist/src/host-collector.js +200 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +210 -0
- package/dist/src/log.d.ts +39 -0
- package/dist/src/log.js +102 -0
- package/dist/src/redactor/base.d.ts +29 -0
- package/dist/src/redactor/base.js +9 -0
- package/dist/src/redactor/index.d.ts +27 -0
- package/dist/src/redactor/index.js +109 -0
- package/dist/src/redactor/strategies/command.d.ts +2 -0
- package/dist/src/redactor/strategies/command.js +19 -0
- package/dist/src/redactor/strategies/hostname.d.ts +2 -0
- package/dist/src/redactor/strategies/hostname.js +15 -0
- package/dist/src/redactor/strategies/index.d.ts +13 -0
- package/dist/src/redactor/strategies/index.js +25 -0
- package/dist/src/redactor/strategies/path.d.ts +2 -0
- package/dist/src/redactor/strategies/path.js +23 -0
- package/dist/src/redactor/strategies/secret-key.d.ts +2 -0
- package/dist/src/redactor/strategies/secret-key.js +22 -0
- package/dist/src/redactor/strategies/username.d.ts +2 -0
- package/dist/src/redactor/strategies/username.js +12 -0
- package/dist/src/redactor/vault.d.ts +25 -0
- package/dist/src/redactor/vault.js +209 -0
- package/dist/src/sender.d.ts +29 -0
- package/dist/src/sender.js +186 -0
- package/dist/src/setup.d.ts +10 -0
- package/dist/src/setup.js +222 -0
- package/dist/src/transformer.d.ts +26 -0
- package/dist/src/transformer.js +302 -0
- package/dist/src/validator.d.ts +17 -0
- package/dist/src/validator.js +110 -0
- package/dist/src/version.d.ts +1 -0
- package/dist/src/version.js +19 -0
- package/openclaw.plugin.json +52 -0
- package/package.json +64 -0
- package/skills/shield/SKILL.md +38 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MessageSchema = void 0;
|
|
4
|
+
const enrich_1 = require("./enrich");
|
|
5
|
+
const redactions_1 = require("./redactions");
|
|
6
|
+
const validations_1 = require("./validations");
|
|
7
|
+
exports.MessageSchema = {
|
|
8
|
+
category: 'message',
|
|
9
|
+
match: (tool) => tool.name === 'message',
|
|
10
|
+
enrich: enrich_1.enrich,
|
|
11
|
+
redactions: redactions_1.redactions,
|
|
12
|
+
validate: validations_1.validate,
|
|
13
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validate = validate;
|
|
4
|
+
// MessageEvent has no required type-specific fields beyond BaseEvent.
|
|
5
|
+
// Base validations (timestamp, session_id, tool_name, principal.hostname) run
|
|
6
|
+
// automatically before this function — no additional checks needed here.
|
|
7
|
+
function validate(_event) { return { valid: true }; }
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.enrich = enrich;
|
|
4
|
+
const base_1 = require("../base");
|
|
5
|
+
function enrich(tool, ctx) {
|
|
6
|
+
const args = tool.arguments;
|
|
7
|
+
const task = args.task || '';
|
|
8
|
+
const meta = {
|
|
9
|
+
tool_name: 'sessions_spawn',
|
|
10
|
+
'openclaw.session_id': ctx.sessionId,
|
|
11
|
+
'openclaw.agent_id': ctx.agentId,
|
|
12
|
+
sub_action: 'spawn',
|
|
13
|
+
spawn_agent_id: args.agentId || null,
|
|
14
|
+
spawn_label: args.label || null,
|
|
15
|
+
spawn_model: args.model || null,
|
|
16
|
+
spawn_task_has_exec: /\b(exec|run|execute|shell|command|bash|sh)\b/i.test(task),
|
|
17
|
+
spawn_task_has_cred: /\b(password|credential|secret|key|token|ssh)\b/i.test(task),
|
|
18
|
+
spawn_task_has_exfil: /\b(send|upload|post|transfer|exfil)/i.test(task),
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
timestamp: ctx.timestamp,
|
|
22
|
+
event_type: 'TOOL_CALL',
|
|
23
|
+
tool_name: 'sessions_spawn',
|
|
24
|
+
tool_category: 'sessions_spawn',
|
|
25
|
+
session_id: ctx.sessionId,
|
|
26
|
+
model: ctx.model,
|
|
27
|
+
product_name: 'OpenClaw',
|
|
28
|
+
vendor_name: 'UPX',
|
|
29
|
+
principal: {
|
|
30
|
+
hostname: ctx.source.hostname,
|
|
31
|
+
ip: ctx.source.ip_addresses?.[0] || '',
|
|
32
|
+
platform: ctx.source.os.platform,
|
|
33
|
+
user: ctx.agentId,
|
|
34
|
+
},
|
|
35
|
+
arguments_summary: (0, base_1.truncate)(task),
|
|
36
|
+
// target.command_line required by parser for PROCESS_LAUNCH mapping
|
|
37
|
+
target: { command_line: (0, base_1.truncate)(task) },
|
|
38
|
+
tool_metadata: (0, base_1.stringifyMetadata)(meta),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BaseEvent } from '../base';
|
|
2
|
+
export interface SessionsSpawnEvent extends BaseEvent {
|
|
3
|
+
tool_category: 'sessions_spawn';
|
|
4
|
+
arguments_summary?: string;
|
|
5
|
+
/** target.command_line = task description — required by parser for PROCESS_LAUNCH mapping */
|
|
6
|
+
target?: {
|
|
7
|
+
command_line?: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SessionsSpawnSchema = void 0;
|
|
4
|
+
const enrich_1 = require("./enrich");
|
|
5
|
+
const redactions_1 = require("./redactions");
|
|
6
|
+
const validations_1 = require("./validations");
|
|
7
|
+
exports.SessionsSpawnSchema = {
|
|
8
|
+
category: 'sessions_spawn',
|
|
9
|
+
match: (tool) => tool.name === 'sessions_spawn',
|
|
10
|
+
enrich: enrich_1.enrich,
|
|
11
|
+
redactions: redactions_1.redactions,
|
|
12
|
+
validate: validations_1.validate,
|
|
13
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EnrichmentContext } from '../base';
|
|
2
|
+
import { ToolResultEvent } from './event';
|
|
3
|
+
export interface RawToolResult {
|
|
4
|
+
toolName?: string;
|
|
5
|
+
content?: Array<{
|
|
6
|
+
text?: string;
|
|
7
|
+
}> | string;
|
|
8
|
+
details?: {
|
|
9
|
+
exitCode?: number;
|
|
10
|
+
durationMs?: number;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export declare function buildToolResult(raw: RawToolResult, ctx: EnrichmentContext): ToolResultEvent;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildToolResult = buildToolResult;
|
|
4
|
+
const base_1 = require("../base");
|
|
5
|
+
function buildToolResult(raw, ctx) {
|
|
6
|
+
const toolName = raw.toolName || 'unknown';
|
|
7
|
+
const resultText = Array.isArray(raw.content)
|
|
8
|
+
? raw.content.map((c) => c.text || '').join('\n')
|
|
9
|
+
: '';
|
|
10
|
+
const truncated = resultText.length > 300 ? resultText.slice(0, 300) : resultText;
|
|
11
|
+
const meta = {
|
|
12
|
+
tool_name: toolName,
|
|
13
|
+
'openclaw.session_id': ctx.sessionId,
|
|
14
|
+
'openclaw.agent_id': ctx.agentId,
|
|
15
|
+
result_size_bytes: String(resultText.length),
|
|
16
|
+
result_is_large: resultText.length > 50000,
|
|
17
|
+
};
|
|
18
|
+
// ANSI injection detection
|
|
19
|
+
const ansiMatches = resultText.match(/\x1b\[[0-9;]*[a-zA-Z]|\x1b\]|\x07|\x1b\(B/g);
|
|
20
|
+
if (ansiMatches && ansiMatches.length > 0) {
|
|
21
|
+
meta['ansi_content_detected'] = 'true';
|
|
22
|
+
meta['ansi_sequences'] = ansiMatches.slice(0, 10).map((s) => s.replace(/\x1b/g, 'ESC')).join(', ');
|
|
23
|
+
}
|
|
24
|
+
const event = {
|
|
25
|
+
timestamp: ctx.timestamp,
|
|
26
|
+
event_type: 'TOOL_RESULT',
|
|
27
|
+
tool_name: toolName,
|
|
28
|
+
tool_category: 'tool_result',
|
|
29
|
+
session_id: ctx.sessionId,
|
|
30
|
+
product_name: 'OpenClaw',
|
|
31
|
+
vendor_name: 'UPX',
|
|
32
|
+
principal: {
|
|
33
|
+
hostname: ctx.source.hostname,
|
|
34
|
+
ip: ctx.source.ip_addresses?.[0] || '',
|
|
35
|
+
platform: ctx.source.os.platform,
|
|
36
|
+
user: ctx.agentId,
|
|
37
|
+
},
|
|
38
|
+
result_summary: truncated,
|
|
39
|
+
tool_metadata: (0, base_1.stringifyMetadata)(meta),
|
|
40
|
+
};
|
|
41
|
+
if (raw.details?.exitCode !== undefined)
|
|
42
|
+
event.exit_code = String(raw.details.exitCode);
|
|
43
|
+
if (raw.details?.durationMs !== undefined)
|
|
44
|
+
event.duration_ms = String(raw.details.durationMs);
|
|
45
|
+
return event;
|
|
46
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validate = exports.redactions = exports.buildToolResult = void 0;
|
|
4
|
+
var enrich_1 = require("./enrich");
|
|
5
|
+
Object.defineProperty(exports, "buildToolResult", { enumerable: true, get: function () { return enrich_1.buildToolResult; } });
|
|
6
|
+
var redactions_1 = require("./redactions");
|
|
7
|
+
Object.defineProperty(exports, "redactions", { enumerable: true, get: function () { return redactions_1.redactions; } });
|
|
8
|
+
var validations_1 = require("./validations");
|
|
9
|
+
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return validations_1.validate; } });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.redactions = void 0;
|
|
4
|
+
exports.redactions = [
|
|
5
|
+
// result_summary may contain API keys or tokens in command output — scrub them
|
|
6
|
+
{ path: 'result_summary', strategy: 'secret-key' },
|
|
7
|
+
];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validate = validate;
|
|
4
|
+
function validate(event) {
|
|
5
|
+
if (event.result_summary === undefined || event.result_summary === null) {
|
|
6
|
+
return { valid: false, field: 'result_summary', error: 'missing result_summary' };
|
|
7
|
+
}
|
|
8
|
+
return { valid: true };
|
|
9
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RawToolCall, EnrichmentContext } from '../base';
|
|
2
|
+
import { WebEvent } from './event';
|
|
3
|
+
/**
|
|
4
|
+
* Returns true for loopback, RFC 1918, link-local, and cloud metadata endpoints.
|
|
5
|
+
* 169.254.169.254 is the AWS/GCP/Azure instance metadata endpoint — a critical IoC.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isInternalUrl(u: URL): boolean;
|
|
8
|
+
export declare function enrich(tool: RawToolCall, ctx: EnrichmentContext): WebEvent;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isInternalUrl = isInternalUrl;
|
|
4
|
+
exports.enrich = enrich;
|
|
5
|
+
const base_1 = require("../base");
|
|
6
|
+
/**
|
|
7
|
+
* Returns true for loopback, RFC 1918, link-local, and cloud metadata endpoints.
|
|
8
|
+
* 169.254.169.254 is the AWS/GCP/Azure instance metadata endpoint — a critical IoC.
|
|
9
|
+
*/
|
|
10
|
+
function isInternalUrl(u) {
|
|
11
|
+
// Node.js URL parser wraps IPv6 in brackets: [::1] — strip them for comparison
|
|
12
|
+
const h = u.hostname;
|
|
13
|
+
const bare = h.startsWith('[') && h.endsWith(']') ? h.slice(1, -1) : h;
|
|
14
|
+
if (bare === 'localhost' || bare === '127.0.0.1' || bare === '::1')
|
|
15
|
+
return true;
|
|
16
|
+
if (/^169\.254\./.test(bare))
|
|
17
|
+
return true; // link-local / cloud metadata
|
|
18
|
+
if (/^10\./.test(bare))
|
|
19
|
+
return true; // RFC 1918 Class A
|
|
20
|
+
if (/^192\.168\./.test(bare))
|
|
21
|
+
return true; // RFC 1918 Class C
|
|
22
|
+
if (/^172\.(1[6-9]|2\d|3[01])\./.test(bare))
|
|
23
|
+
return true; // RFC 1918 Class B
|
|
24
|
+
if (/\.(local|internal|localhost)$/.test(bare))
|
|
25
|
+
return true; // internal hostnames
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
function enrich(tool, ctx) {
|
|
29
|
+
const args = tool.arguments;
|
|
30
|
+
// web_search args have `query` but no `url` — synthesise a canonical search URL
|
|
31
|
+
// so the parser gets a valid target hostname for NETWORK_HTTP mapping
|
|
32
|
+
const rawUrl = args.url || args.targetUrl || '';
|
|
33
|
+
const url = rawUrl || (tool.name === 'web_search' && args.query
|
|
34
|
+
? `https://search.brave.com/search?q=${encodeURIComponent(String(args.query).slice(0, 200))}`
|
|
35
|
+
: '');
|
|
36
|
+
const event = {
|
|
37
|
+
timestamp: ctx.timestamp,
|
|
38
|
+
event_type: 'TOOL_CALL',
|
|
39
|
+
tool_name: tool.name,
|
|
40
|
+
tool_category: 'web',
|
|
41
|
+
session_id: ctx.sessionId,
|
|
42
|
+
model: ctx.model,
|
|
43
|
+
product_name: 'OpenClaw',
|
|
44
|
+
vendor_name: 'UPX',
|
|
45
|
+
principal: {
|
|
46
|
+
hostname: ctx.source.hostname,
|
|
47
|
+
ip: ctx.source.ip_addresses?.[0] || '',
|
|
48
|
+
platform: ctx.source.os.platform,
|
|
49
|
+
user: ctx.agentId,
|
|
50
|
+
},
|
|
51
|
+
url,
|
|
52
|
+
target: { url },
|
|
53
|
+
network: { session_id: ctx.sessionId, protocol: 'HTTPS', direction: 'OUTBOUND' },
|
|
54
|
+
tool_metadata: (0, base_1.stringifyMetadata)({
|
|
55
|
+
tool_name: tool.name,
|
|
56
|
+
'openclaw.session_id': ctx.sessionId,
|
|
57
|
+
'openclaw.agent_id': ctx.agentId,
|
|
58
|
+
}),
|
|
59
|
+
};
|
|
60
|
+
try {
|
|
61
|
+
const u = new URL(url);
|
|
62
|
+
event.target.hostname = u.hostname;
|
|
63
|
+
event.target.url_domain = u.hostname;
|
|
64
|
+
// Reflect actual protocol (HTTP vs HTTPS) in the network block
|
|
65
|
+
if (event.network) {
|
|
66
|
+
event.network.protocol = u.protocol === 'http:' ? 'HTTP' : 'HTTPS';
|
|
67
|
+
}
|
|
68
|
+
event.tool_metadata = (0, base_1.stringifyMetadata)({
|
|
69
|
+
tool_name: tool.name,
|
|
70
|
+
'openclaw.session_id': ctx.sessionId,
|
|
71
|
+
'openclaw.agent_id': ctx.agentId,
|
|
72
|
+
url_domain: u.hostname,
|
|
73
|
+
url_is_internal: isInternalUrl(u),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch { /* malformed URL — keep defaults */ }
|
|
77
|
+
return event;
|
|
78
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebSchema = void 0;
|
|
4
|
+
const enrich_1 = require("./enrich");
|
|
5
|
+
const redactions_1 = require("./redactions");
|
|
6
|
+
const validations_1 = require("./validations");
|
|
7
|
+
exports.WebSchema = {
|
|
8
|
+
category: 'web',
|
|
9
|
+
match: (tool) => ['web_fetch', 'web_search'].includes(tool.name),
|
|
10
|
+
enrich: enrich_1.enrich,
|
|
11
|
+
redactions: redactions_1.redactions,
|
|
12
|
+
validate: validations_1.validate,
|
|
13
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validate = validate;
|
|
4
|
+
function validate(event) {
|
|
5
|
+
if (!event.url)
|
|
6
|
+
return { valid: false, field: 'url', error: 'missing url' };
|
|
7
|
+
if (!event.network?.protocol)
|
|
8
|
+
return { valid: false, field: 'network.protocol', error: 'missing network.protocol' };
|
|
9
|
+
return { valid: true };
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Config } from './config';
|
|
2
|
+
export interface RawEntry {
|
|
3
|
+
type: string;
|
|
4
|
+
id: string;
|
|
5
|
+
parentId?: string;
|
|
6
|
+
timestamp: string;
|
|
7
|
+
message: any;
|
|
8
|
+
_sessionId: string;
|
|
9
|
+
_agentId: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function fetchNewEntries(config: Config): Promise<RawEntry[]>;
|
|
12
|
+
export declare function commitCursors(config: Config, _entries: RawEntry[]): void;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.fetchNewEntries = fetchNewEntries;
|
|
37
|
+
exports.commitCursors = commitCursors;
|
|
38
|
+
const fs_1 = require("fs");
|
|
39
|
+
const path_1 = require("path");
|
|
40
|
+
const log = __importStar(require("./log"));
|
|
41
|
+
function loadCursors(cursorFile) {
|
|
42
|
+
if ((0, fs_1.existsSync)(cursorFile)) {
|
|
43
|
+
return JSON.parse((0, fs_1.readFileSync)(cursorFile, 'utf-8'));
|
|
44
|
+
}
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Initialize cursors for a new session directory.
|
|
49
|
+
* Sets all file offsets to current file size (skip historical data).
|
|
50
|
+
* Only called for directories that have NO existing cursor entries.
|
|
51
|
+
*/
|
|
52
|
+
function initCursorsForDir(sessionDir, agentId, existingCursors) {
|
|
53
|
+
const init = {};
|
|
54
|
+
let files;
|
|
55
|
+
try {
|
|
56
|
+
files = (0, fs_1.readdirSync)(sessionDir).filter(f => f.endsWith('.jsonl'));
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
log.warn('fetcher', `Cannot read session directory ${sessionDir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
60
|
+
return init;
|
|
61
|
+
}
|
|
62
|
+
let skipped = 0;
|
|
63
|
+
for (const file of files) {
|
|
64
|
+
const cursorKey = `${agentId}/${file}`;
|
|
65
|
+
// Also check legacy key (without agent prefix) for migration
|
|
66
|
+
if (existingCursors[cursorKey] !== undefined || existingCursors[file] !== undefined) {
|
|
67
|
+
// Already tracked — migrate legacy key if needed
|
|
68
|
+
if (existingCursors[file] !== undefined && existingCursors[cursorKey] === undefined) {
|
|
69
|
+
init[cursorKey] = existingCursors[file];
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
// New file — set cursor to current size (skip history)
|
|
74
|
+
const filePath = (0, path_1.join)(sessionDir, file);
|
|
75
|
+
const fd = (0, fs_1.openSync)(filePath, 'r');
|
|
76
|
+
try {
|
|
77
|
+
const size = (0, fs_1.fstatSync)(fd).size;
|
|
78
|
+
init[cursorKey] = size;
|
|
79
|
+
skipped++;
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
(0, fs_1.closeSync)(fd);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (skipped > 0) {
|
|
86
|
+
log.info('fetcher', `Initialized ${skipped} cursors for agent "${agentId}" (skipping historical data)`);
|
|
87
|
+
}
|
|
88
|
+
return init;
|
|
89
|
+
}
|
|
90
|
+
function saveCursors(cursorFile, state) {
|
|
91
|
+
const dir = (0, path_1.dirname)(cursorFile);
|
|
92
|
+
if (!(0, fs_1.existsSync)(dir))
|
|
93
|
+
(0, fs_1.mkdirSync)(dir, { recursive: true });
|
|
94
|
+
const tmp = cursorFile + '.tmp';
|
|
95
|
+
(0, fs_1.writeFileSync)(tmp, JSON.stringify(state, null, 2));
|
|
96
|
+
(0, fs_1.renameSync)(tmp, cursorFile);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Read only the new bytes from a file starting at the given byte offset.
|
|
100
|
+
* Uses low-level fd + read to avoid loading the entire file into memory.
|
|
101
|
+
*/
|
|
102
|
+
function readNewBytes(filePath, offset) {
|
|
103
|
+
const fd = (0, fs_1.openSync)(filePath, 'r');
|
|
104
|
+
try {
|
|
105
|
+
const stat = (0, fs_1.fstatSync)(fd);
|
|
106
|
+
const fileSize = stat.size;
|
|
107
|
+
if (offset >= fileSize) {
|
|
108
|
+
return { content: '', newSize: fileSize };
|
|
109
|
+
}
|
|
110
|
+
const bytesToRead = fileSize - offset;
|
|
111
|
+
const buffer = Buffer.alloc(bytesToRead);
|
|
112
|
+
(0, fs_1.readSync)(fd, buffer, 0, bytesToRead, offset);
|
|
113
|
+
return { content: buffer.toString('utf-8'), newSize: fileSize };
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
(0, fs_1.closeSync)(fd);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// In-memory cursor state for the current poll cycle (committed only after successful send)
|
|
120
|
+
let _pendingCursors = {};
|
|
121
|
+
async function fetchNewEntries(config) {
|
|
122
|
+
const cursors = loadCursors(config.cursorFile);
|
|
123
|
+
_pendingCursors = { ...cursors };
|
|
124
|
+
const results = [];
|
|
125
|
+
for (const sessionDir of config.sessionDirs) {
|
|
126
|
+
if (!(0, fs_1.existsSync)(sessionDir))
|
|
127
|
+
continue;
|
|
128
|
+
// Derive agent name from directory path: .../agents/{agentId}/sessions
|
|
129
|
+
const agentId = (0, path_1.basename)((0, path_1.dirname)(sessionDir));
|
|
130
|
+
// Initialize cursors for newly discovered agents (skip historical data)
|
|
131
|
+
const initCursors = initCursorsForDir(sessionDir, agentId, _pendingCursors);
|
|
132
|
+
Object.assign(_pendingCursors, initCursors);
|
|
133
|
+
let files;
|
|
134
|
+
try {
|
|
135
|
+
files = (0, fs_1.readdirSync)(sessionDir).filter(f => f.endsWith('.jsonl'));
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
for (const file of files) {
|
|
141
|
+
const filePath = (0, path_1.join)(sessionDir, file);
|
|
142
|
+
const sessionId = (0, path_1.basename)(file, '.jsonl');
|
|
143
|
+
// Cursor key includes agent to avoid collisions across agents
|
|
144
|
+
const cursorKey = `${agentId}/${file}`;
|
|
145
|
+
const offset = _pendingCursors[cursorKey] ?? cursors[cursorKey] ?? 0;
|
|
146
|
+
const { content, newSize } = readNewBytes(filePath, offset);
|
|
147
|
+
if (!content) {
|
|
148
|
+
_pendingCursors[cursorKey] = newSize;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const lines = content.split('\n').filter(l => l.trim());
|
|
152
|
+
for (const line of lines) {
|
|
153
|
+
try {
|
|
154
|
+
const entry = JSON.parse(line);
|
|
155
|
+
if (entry.type !== 'message')
|
|
156
|
+
continue;
|
|
157
|
+
const msg = entry.message;
|
|
158
|
+
if (!msg)
|
|
159
|
+
continue;
|
|
160
|
+
if (msg.role === 'assistant' && Array.isArray(msg.content)) {
|
|
161
|
+
const hasToolCall = msg.content.some((c) => c.type === 'toolCall');
|
|
162
|
+
if (hasToolCall) {
|
|
163
|
+
results.push({ ...entry, _sessionId: sessionId, _agentId: agentId });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else if (msg.role === 'toolResult') {
|
|
167
|
+
results.push({ ...entry, _sessionId: sessionId, _agentId: agentId });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch { /* skip malformed lines */ }
|
|
171
|
+
}
|
|
172
|
+
_pendingCursors[cursorKey] = newSize;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return results;
|
|
176
|
+
}
|
|
177
|
+
function commitCursors(config, _entries) {
|
|
178
|
+
if (Object.keys(_pendingCursors).length === 0)
|
|
179
|
+
return;
|
|
180
|
+
saveCursors(config.cursorFile, _pendingCursors);
|
|
181
|
+
_pendingCursors = {};
|
|
182
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function collectHostMetrics(): Promise<any[]>;
|