@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.

Files changed (159) hide show
  1. package/LICENSE +38 -0
  2. package/README.md +96 -0
  3. package/dist/index.d.ts +43 -0
  4. package/dist/index.js +365 -0
  5. package/dist/src/config.d.ts +43 -0
  6. package/dist/src/config.js +181 -0
  7. package/dist/src/events/base.d.ts +110 -0
  8. package/dist/src/events/base.js +61 -0
  9. package/dist/src/events/browser/enrich.d.ts +3 -0
  10. package/dist/src/events/browser/enrich.js +46 -0
  11. package/dist/src/events/browser/event.d.ts +10 -0
  12. package/dist/src/events/browser/event.js +2 -0
  13. package/dist/src/events/browser/index.d.ts +4 -0
  14. package/dist/src/events/browser/index.js +13 -0
  15. package/dist/src/events/browser/redactions.d.ts +2 -0
  16. package/dist/src/events/browser/redactions.js +4 -0
  17. package/dist/src/events/browser/validations.d.ts +3 -0
  18. package/dist/src/events/browser/validations.js +10 -0
  19. package/dist/src/events/cron/enrich.d.ts +3 -0
  20. package/dist/src/events/cron/enrich.js +44 -0
  21. package/dist/src/events/cron/event.d.ts +5 -0
  22. package/dist/src/events/cron/event.js +2 -0
  23. package/dist/src/events/cron/index.d.ts +4 -0
  24. package/dist/src/events/cron/index.js +13 -0
  25. package/dist/src/events/cron/redactions.d.ts +2 -0
  26. package/dist/src/events/cron/redactions.js +4 -0
  27. package/dist/src/events/cron/validations.d.ts +3 -0
  28. package/dist/src/events/cron/validations.js +4 -0
  29. package/dist/src/events/exec/enrich.d.ts +3 -0
  30. package/dist/src/events/exec/enrich.js +80 -0
  31. package/dist/src/events/exec/event.d.ts +11 -0
  32. package/dist/src/events/exec/event.js +2 -0
  33. package/dist/src/events/exec/index.d.ts +4 -0
  34. package/dist/src/events/exec/index.js +13 -0
  35. package/dist/src/events/exec/redactions.d.ts +3 -0
  36. package/dist/src/events/exec/redactions.js +12 -0
  37. package/dist/src/events/exec/validations.d.ts +3 -0
  38. package/dist/src/events/exec/validations.js +12 -0
  39. package/dist/src/events/file/enrich.d.ts +3 -0
  40. package/dist/src/events/file/enrich.js +63 -0
  41. package/dist/src/events/file/event.d.ts +11 -0
  42. package/dist/src/events/file/event.js +2 -0
  43. package/dist/src/events/file/index.d.ts +4 -0
  44. package/dist/src/events/file/index.js +13 -0
  45. package/dist/src/events/file/redactions.d.ts +2 -0
  46. package/dist/src/events/file/redactions.js +8 -0
  47. package/dist/src/events/file/validations.d.ts +3 -0
  48. package/dist/src/events/file/validations.js +10 -0
  49. package/dist/src/events/gateway/enrich.d.ts +3 -0
  50. package/dist/src/events/gateway/enrich.js +50 -0
  51. package/dist/src/events/gateway/event.d.ts +5 -0
  52. package/dist/src/events/gateway/event.js +2 -0
  53. package/dist/src/events/gateway/index.d.ts +4 -0
  54. package/dist/src/events/gateway/index.js +13 -0
  55. package/dist/src/events/gateway/redactions.d.ts +2 -0
  56. package/dist/src/events/gateway/redactions.js +4 -0
  57. package/dist/src/events/gateway/validations.d.ts +3 -0
  58. package/dist/src/events/gateway/validations.js +4 -0
  59. package/dist/src/events/generic/enrich.d.ts +3 -0
  60. package/dist/src/events/generic/enrich.js +30 -0
  61. package/dist/src/events/generic/event.d.ts +5 -0
  62. package/dist/src/events/generic/event.js +2 -0
  63. package/dist/src/events/generic/index.d.ts +5 -0
  64. package/dist/src/events/generic/index.js +14 -0
  65. package/dist/src/events/generic/redactions.d.ts +2 -0
  66. package/dist/src/events/generic/redactions.js +4 -0
  67. package/dist/src/events/generic/validations.d.ts +3 -0
  68. package/dist/src/events/generic/validations.js +4 -0
  69. package/dist/src/events/host-telemetry/enrich.d.ts +3 -0
  70. package/dist/src/events/host-telemetry/enrich.js +28 -0
  71. package/dist/src/events/host-telemetry/event.d.ts +4 -0
  72. package/dist/src/events/host-telemetry/event.js +2 -0
  73. package/dist/src/events/host-telemetry/index.d.ts +4 -0
  74. package/dist/src/events/host-telemetry/index.js +13 -0
  75. package/dist/src/events/host-telemetry/redactions.d.ts +2 -0
  76. package/dist/src/events/host-telemetry/redactions.js +4 -0
  77. package/dist/src/events/host-telemetry/validations.d.ts +3 -0
  78. package/dist/src/events/host-telemetry/validations.js +4 -0
  79. package/dist/src/events/index.d.ts +40 -0
  80. package/dist/src/events/index.js +39 -0
  81. package/dist/src/events/message/enrich.d.ts +3 -0
  82. package/dist/src/events/message/enrich.js +36 -0
  83. package/dist/src/events/message/event.d.ts +5 -0
  84. package/dist/src/events/message/event.js +2 -0
  85. package/dist/src/events/message/index.d.ts +4 -0
  86. package/dist/src/events/message/index.js +13 -0
  87. package/dist/src/events/message/redactions.d.ts +2 -0
  88. package/dist/src/events/message/redactions.js +4 -0
  89. package/dist/src/events/message/validations.d.ts +3 -0
  90. package/dist/src/events/message/validations.js +7 -0
  91. package/dist/src/events/sessions-spawn/enrich.d.ts +3 -0
  92. package/dist/src/events/sessions-spawn/enrich.js +40 -0
  93. package/dist/src/events/sessions-spawn/event.d.ts +9 -0
  94. package/dist/src/events/sessions-spawn/event.js +2 -0
  95. package/dist/src/events/sessions-spawn/index.d.ts +4 -0
  96. package/dist/src/events/sessions-spawn/index.js +13 -0
  97. package/dist/src/events/sessions-spawn/redactions.d.ts +2 -0
  98. package/dist/src/events/sessions-spawn/redactions.js +4 -0
  99. package/dist/src/events/sessions-spawn/validations.d.ts +3 -0
  100. package/dist/src/events/sessions-spawn/validations.js +4 -0
  101. package/dist/src/events/tool-result/enrich.d.ts +13 -0
  102. package/dist/src/events/tool-result/enrich.js +46 -0
  103. package/dist/src/events/tool-result/event.d.ts +7 -0
  104. package/dist/src/events/tool-result/event.js +2 -0
  105. package/dist/src/events/tool-result/index.d.ts +4 -0
  106. package/dist/src/events/tool-result/index.js +9 -0
  107. package/dist/src/events/tool-result/redactions.d.ts +2 -0
  108. package/dist/src/events/tool-result/redactions.js +7 -0
  109. package/dist/src/events/tool-result/validations.d.ts +3 -0
  110. package/dist/src/events/tool-result/validations.js +9 -0
  111. package/dist/src/events/web/enrich.d.ts +8 -0
  112. package/dist/src/events/web/enrich.js +78 -0
  113. package/dist/src/events/web/event.d.ts +10 -0
  114. package/dist/src/events/web/event.js +2 -0
  115. package/dist/src/events/web/index.d.ts +4 -0
  116. package/dist/src/events/web/index.js +13 -0
  117. package/dist/src/events/web/redactions.d.ts +2 -0
  118. package/dist/src/events/web/redactions.js +6 -0
  119. package/dist/src/events/web/validations.d.ts +3 -0
  120. package/dist/src/events/web/validations.js +10 -0
  121. package/dist/src/fetcher.d.ts +12 -0
  122. package/dist/src/fetcher.js +182 -0
  123. package/dist/src/host-collector.d.ts +1 -0
  124. package/dist/src/host-collector.js +200 -0
  125. package/dist/src/index.d.ts +1 -0
  126. package/dist/src/index.js +210 -0
  127. package/dist/src/log.d.ts +39 -0
  128. package/dist/src/log.js +102 -0
  129. package/dist/src/redactor/base.d.ts +29 -0
  130. package/dist/src/redactor/base.js +9 -0
  131. package/dist/src/redactor/index.d.ts +27 -0
  132. package/dist/src/redactor/index.js +109 -0
  133. package/dist/src/redactor/strategies/command.d.ts +2 -0
  134. package/dist/src/redactor/strategies/command.js +19 -0
  135. package/dist/src/redactor/strategies/hostname.d.ts +2 -0
  136. package/dist/src/redactor/strategies/hostname.js +15 -0
  137. package/dist/src/redactor/strategies/index.d.ts +13 -0
  138. package/dist/src/redactor/strategies/index.js +25 -0
  139. package/dist/src/redactor/strategies/path.d.ts +2 -0
  140. package/dist/src/redactor/strategies/path.js +23 -0
  141. package/dist/src/redactor/strategies/secret-key.d.ts +2 -0
  142. package/dist/src/redactor/strategies/secret-key.js +22 -0
  143. package/dist/src/redactor/strategies/username.d.ts +2 -0
  144. package/dist/src/redactor/strategies/username.js +12 -0
  145. package/dist/src/redactor/vault.d.ts +25 -0
  146. package/dist/src/redactor/vault.js +209 -0
  147. package/dist/src/sender.d.ts +29 -0
  148. package/dist/src/sender.js +186 -0
  149. package/dist/src/setup.d.ts +10 -0
  150. package/dist/src/setup.js +222 -0
  151. package/dist/src/transformer.d.ts +26 -0
  152. package/dist/src/transformer.js +302 -0
  153. package/dist/src/validator.d.ts +17 -0
  154. package/dist/src/validator.js +110 -0
  155. package/dist/src/version.d.ts +1 -0
  156. package/dist/src/version.js +19 -0
  157. package/openclaw.plugin.json +52 -0
  158. package/package.json +64 -0
  159. 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,2 @@
1
+ import { FieldRedaction } from '../base';
2
+ export declare const redactions: FieldRedaction[];
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.redactions = void 0;
4
+ exports.redactions = [];
@@ -0,0 +1,3 @@
1
+ import { ValidationResult } from '../base';
2
+ import { MessageEvent } from './event';
3
+ export declare function validate(_event: MessageEvent): ValidationResult;
@@ -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,3 @@
1
+ import { RawToolCall, EnrichmentContext } from '../base';
2
+ import { SessionsSpawnEvent } from './event';
3
+ export declare function enrich(tool: RawToolCall, ctx: EnrichmentContext): SessionsSpawnEvent;
@@ -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,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ import { EventSchema } from '../base';
2
+ import { SessionsSpawnEvent } from './event';
3
+ export type { SessionsSpawnEvent };
4
+ export declare const SessionsSpawnSchema: EventSchema<SessionsSpawnEvent>;
@@ -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,2 @@
1
+ import { FieldRedaction } from '../base';
2
+ export declare const redactions: FieldRedaction[];
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.redactions = void 0;
4
+ exports.redactions = [];
@@ -0,0 +1,3 @@
1
+ import { ValidationResult } from '../base';
2
+ import { SessionsSpawnEvent } from './event';
3
+ export declare function validate(_event: SessionsSpawnEvent): ValidationResult;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validate = validate;
4
+ function validate(_event) { return { valid: true }; }
@@ -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,7 @@
1
+ import { BaseEvent } from '../base';
2
+ export interface ToolResultEvent extends BaseEvent {
3
+ tool_category: 'tool_result';
4
+ result_summary: string;
5
+ exit_code?: string;
6
+ duration_ms?: string;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export type { ToolResultEvent } from './event';
2
+ export { buildToolResult } from './enrich';
3
+ export { redactions } from './redactions';
4
+ export { validate } from './validations';
@@ -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,2 @@
1
+ import { FieldRedaction } from '../base';
2
+ export declare const redactions: FieldRedaction[];
@@ -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,3 @@
1
+ import { ValidationResult } from '../base';
2
+ import { ToolResultEvent } from './event';
3
+ export declare function validate(event: ToolResultEvent): ValidationResult;
@@ -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,10 @@
1
+ import { BaseEvent, NetworkBlock } from '../base';
2
+ export interface WebEvent extends BaseEvent, NetworkBlock {
3
+ tool_category: 'web';
4
+ url: string;
5
+ target: {
6
+ url: string;
7
+ hostname?: string;
8
+ url_domain?: string;
9
+ };
10
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ import { EventSchema } from '../base';
2
+ import { WebEvent } from './event';
3
+ export type { WebEvent };
4
+ export declare const WebSchema: EventSchema<WebEvent>;
@@ -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,2 @@
1
+ import { FieldRedaction } from '../base';
2
+ export declare const redactions: FieldRedaction[];
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.redactions = void 0;
4
+ exports.redactions = [
5
+ // URLs are kept as-is for detection value; no PII expected in URLs at this layer
6
+ ];
@@ -0,0 +1,3 @@
1
+ import { ValidationResult } from '../base';
2
+ import { WebEvent } from './event';
3
+ export declare function validate(event: WebEvent): ValidationResult;
@@ -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[]>;