clawcontainer 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/CONTRIBUTING.md +76 -0
  2. package/DOCS.md +370 -0
  3. package/LICENSE +21 -0
  4. package/README.md +147 -0
  5. package/black_logo.png +0 -0
  6. package/dist/assets/abap-DLDM7-KI.js +1 -0
  7. package/dist/assets/apex-DNDY2TF8.js +1 -0
  8. package/dist/assets/azcli-Y6nb8tq_.js +1 -0
  9. package/dist/assets/bat-BwHxbl9M.js +1 -0
  10. package/dist/assets/bicep-CFznDFnq.js +2 -0
  11. package/dist/assets/cameligo-Bf6VGUru.js +1 -0
  12. package/dist/assets/clojure-Dnu-v4kV.js +1 -0
  13. package/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
  14. package/dist/assets/coffee-Bd8akH9Z.js +1 -0
  15. package/dist/assets/cpp-BbWJElDN.js +1 -0
  16. package/dist/assets/csharp-Co3qMtFm.js +1 -0
  17. package/dist/assets/csp-D-4FJmMZ.js +1 -0
  18. package/dist/assets/css-DdJfP1eB.js +3 -0
  19. package/dist/assets/css.worker-GxEd3MMM.js +93 -0
  20. package/dist/assets/cssMode-DM_ONlf-.js +1 -0
  21. package/dist/assets/cypher-cTPe9QuQ.js +1 -0
  22. package/dist/assets/dart-BOtBlQCF.js +1 -0
  23. package/dist/assets/dockerfile-BG73LgW2.js +1 -0
  24. package/dist/assets/ecl-BEgZUVRK.js +1 -0
  25. package/dist/assets/elixir-BkW5O-1t.js +1 -0
  26. package/dist/assets/flow9-BeJ5waoc.js +1 -0
  27. package/dist/assets/freemarker2-VbwzOQPq.js +3 -0
  28. package/dist/assets/fsharp-PahG7c26.js +1 -0
  29. package/dist/assets/go-acbASCJo.js +1 -0
  30. package/dist/assets/graphql-BxJiqAUM.js +1 -0
  31. package/dist/assets/handlebars-DLvQ802u.js +1 -0
  32. package/dist/assets/hcl-DtV1sZF8.js +1 -0
  33. package/dist/assets/html-DuEPBzmS.js +1 -0
  34. package/dist/assets/html.worker-lU17Tx2m.js +470 -0
  35. package/dist/assets/htmlMode-BfeYTJaB.js +1 -0
  36. package/dist/assets/index-BnBKg8GZ.js +1291 -0
  37. package/dist/assets/index-Dq3FlPWe.css +32 -0
  38. package/dist/assets/ini-Kd9XrMLS.js +1 -0
  39. package/dist/assets/java-CXBNlu9o.js +1 -0
  40. package/dist/assets/javascript-DQO1Leza.js +1 -0
  41. package/dist/assets/json.worker-CUJs-dtA.js +58 -0
  42. package/dist/assets/jsonMode--qsURhHr.js +7 -0
  43. package/dist/assets/julia-cl7-CwDS.js +1 -0
  44. package/dist/assets/kotlin-s7OhZKlX.js +1 -0
  45. package/dist/assets/less-9HpZscsL.js +2 -0
  46. package/dist/assets/lexon-OrD6JF1K.js +1 -0
  47. package/dist/assets/liquid-PL6MZtM8.js +1 -0
  48. package/dist/assets/lspLanguageFeatures-Cy5rDFeq.js +4 -0
  49. package/dist/assets/lua-Cyyb5UIc.js +1 -0
  50. package/dist/assets/m3-B8OfTtLu.js +1 -0
  51. package/dist/assets/markdown-BFxVWTOG.js +1 -0
  52. package/dist/assets/mdx-Cb3Jy14X.js +1 -0
  53. package/dist/assets/mips-CiqrrVzr.js +1 -0
  54. package/dist/assets/msdax-DmeGPVcC.js +1 -0
  55. package/dist/assets/mysql-C_tMU-Nz.js +1 -0
  56. package/dist/assets/objective-c-BDtDVThU.js +1 -0
  57. package/dist/assets/pascal-vHIfCaH5.js +1 -0
  58. package/dist/assets/pascaligo-DtZ0uQbO.js +1 -0
  59. package/dist/assets/perl-Ub6l9XKa.js +1 -0
  60. package/dist/assets/pgsql-BlNEE0v7.js +1 -0
  61. package/dist/assets/php-BBUBE1dy.js +1 -0
  62. package/dist/assets/pla-DSh2-awV.js +1 -0
  63. package/dist/assets/postiats-CocnycG-.js +1 -0
  64. package/dist/assets/powerquery-tScXyioY.js +1 -0
  65. package/dist/assets/powershell-COWaemsV.js +1 -0
  66. package/dist/assets/protobuf-Brw8urJB.js +2 -0
  67. package/dist/assets/pug-8SOpv6rk.js +1 -0
  68. package/dist/assets/python-Usm4OUwq.js +1 -0
  69. package/dist/assets/qsharp-Bw9ernYp.js +1 -0
  70. package/dist/assets/r-j7ic8hl3.js +1 -0
  71. package/dist/assets/razor-BIOole7a.js +1 -0
  72. package/dist/assets/redis-Bu5POkcn.js +1 -0
  73. package/dist/assets/redshift-Bs9aos_-.js +1 -0
  74. package/dist/assets/restructuredtext-CqXO7rUv.js +1 -0
  75. package/dist/assets/ruby-zBfavPgS.js +1 -0
  76. package/dist/assets/rust-BzKRNQWT.js +1 -0
  77. package/dist/assets/sb-BBc9UKZt.js +1 -0
  78. package/dist/assets/scala-D9hQfWCl.js +1 -0
  79. package/dist/assets/scheme-BPhDTwHR.js +1 -0
  80. package/dist/assets/scss-CBJaRo0y.js +3 -0
  81. package/dist/assets/shell-DiJ1NA_G.js +1 -0
  82. package/dist/assets/solidity-Db0IVjzk.js +1 -0
  83. package/dist/assets/sophia-CnS9iZB_.js +1 -0
  84. package/dist/assets/sparql-CJmd_6j2.js +1 -0
  85. package/dist/assets/sql-ClhHkBeG.js +1 -0
  86. package/dist/assets/st-CHwy0fLd.js +1 -0
  87. package/dist/assets/swift-Bqt4WxQ4.js +3 -0
  88. package/dist/assets/systemverilog-Bs9z6M-B.js +1 -0
  89. package/dist/assets/tcl-Dm6ycUr_.js +1 -0
  90. package/dist/assets/ts.worker-Dy9lDQQT.js +67731 -0
  91. package/dist/assets/tsMode-CDjF3DWK.js +11 -0
  92. package/dist/assets/twig-Csy3S7wG.js +1 -0
  93. package/dist/assets/typescript-CJR4sLnG.js +1 -0
  94. package/dist/assets/typespec-Btyra-wh.js +1 -0
  95. package/dist/assets/vb-Db0cS2oM.js +1 -0
  96. package/dist/assets/wgsl-DumH7NcR.js +298 -0
  97. package/dist/assets/xml-CJZS3uh7.js +1 -0
  98. package/dist/assets/yaml-DB88cW5z.js +1 -0
  99. package/dist/audit.d.ts +48 -0
  100. package/dist/container.d.ts +100 -0
  101. package/dist/event-emitter.d.ts +7 -0
  102. package/dist/favicon.png +0 -0
  103. package/dist/git-service.d.ts +31 -0
  104. package/dist/index.html +188 -0
  105. package/dist/logo-sm.png +0 -0
  106. package/dist/logo.png +0 -0
  107. package/dist/main.d.ts +1 -0
  108. package/dist/monaco-editor.d.ts +11 -0
  109. package/dist/monacoeditorwork/css.worker.bundle.js +54264 -0
  110. package/dist/monacoeditorwork/editor.worker.bundle.js +14317 -0
  111. package/dist/monacoeditorwork/html.worker.bundle.js +30449 -0
  112. package/dist/monacoeditorwork/json.worker.bundle.js +22085 -0
  113. package/dist/monacoeditorwork/ts.worker.bundle.js +225552 -0
  114. package/dist/net-intercept.d.ts +2 -0
  115. package/dist/network-hook.d.ts +1 -0
  116. package/dist/plugin.d.ts +20 -0
  117. package/dist/policy.d.ts +58 -0
  118. package/dist/sdk.d.ts +61 -0
  119. package/dist/tab-manager.d.ts +11 -0
  120. package/dist/templates.d.ts +46 -0
  121. package/dist/terminal.d.ts +19 -0
  122. package/dist/types.d.ts +109 -0
  123. package/dist/ui.d.ts +81 -0
  124. package/dist/workspace.d.ts +16 -0
  125. package/index.html +159 -0
  126. package/logo.png +0 -0
  127. package/package.json +31 -0
  128. package/public/favicon.png +0 -0
  129. package/public/logo-sm.png +0 -0
  130. package/public/logo.png +0 -0
  131. package/src/audit.ts +196 -0
  132. package/src/container.ts +723 -0
  133. package/src/event-emitter.ts +28 -0
  134. package/src/git-service.ts +202 -0
  135. package/src/main.ts +9 -0
  136. package/src/monaco-editor.ts +111 -0
  137. package/src/net-intercept.ts +74 -0
  138. package/src/network-hook.ts +248 -0
  139. package/src/plugin.ts +63 -0
  140. package/src/policy.ts +403 -0
  141. package/src/sdk.ts +355 -0
  142. package/src/style.css +432 -0
  143. package/src/tab-manager.ts +30 -0
  144. package/src/templates.ts +271 -0
  145. package/src/terminal.ts +78 -0
  146. package/src/types.ts +113 -0
  147. package/src/ui.ts +1266 -0
  148. package/src/workspace.ts +107 -0
  149. package/tsconfig.json +20 -0
  150. package/vite.config.ts +52 -0
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "clawcontainer",
3
+ "version": "1.0.0",
4
+ "description": "A serverless browser-based runtime for Claw AI Agents powered by WebContainers",
5
+ "type": "module",
6
+ "main": "dist/sdk.js",
7
+ "types": "dist/sdk.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/sdk.js",
11
+ "types": "./dist/sdk.d.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "dev": "vite",
16
+ "build": "vite build && tsc",
17
+ "build:lib": "tsc && vite build --mode lib",
18
+ "preview": "vite preview"
19
+ },
20
+ "dependencies": {
21
+ "@webcontainer/api": "^1.5.0",
22
+ "@xterm/addon-fit": "^0.10.0",
23
+ "@xterm/xterm": "^5.5.0",
24
+ "monaco-editor": "^0.55.1"
25
+ },
26
+ "devDependencies": {
27
+ "typescript": "^5.4.0",
28
+ "vite": "^5.2.0",
29
+ "vite-plugin-monaco-editor": "^1.1.0"
30
+ }
31
+ }
Binary file
Binary file
Binary file
package/src/audit.ts ADDED
@@ -0,0 +1,196 @@
1
+ // ─── Generic WebContainer Audit Log ─────────────────────────────────────────
2
+
3
+ export type AuditSource = 'boot' | 'user' | 'agent' | 'system' | 'policy';
4
+ export type AuditLevel = 'info' | 'warn' | 'error';
5
+
6
+ export type AuditEvent =
7
+ | 'process.spawn'
8
+ | 'process.exit'
9
+ | 'file.read'
10
+ | 'file.write'
11
+ | 'io.stdout'
12
+ | 'io.stdin'
13
+ | 'env.configure'
14
+ | 'server.ready'
15
+ | 'status.change'
16
+ | 'policy.deny'
17
+ | 'policy.load'
18
+ | 'boot.mount'
19
+ | 'net.request'
20
+ | 'net.response'
21
+ | 'git.clone'
22
+ | 'git.push';
23
+
24
+ export interface AuditEntry {
25
+ timestamp: string;
26
+ event: AuditEvent;
27
+ detail: string;
28
+ meta?: Record<string, unknown>;
29
+ source?: AuditSource;
30
+ level?: AuditLevel;
31
+ }
32
+
33
+ const IO_BUFFER_MS = 500;
34
+ const IO_MAX_CHARS = 2000;
35
+ const NET_BODY_MAX_CHARS = 4000;
36
+
37
+ const SENSITIVE_HEADER_KEYS = /^(authorization|x-api-key|api-key|x-goog-api-key)$/i;
38
+ const SENSITIVE_HEADER_PARTIAL = /secret|token/i;
39
+
40
+ /** Order in which source sections appear in toText(). */
41
+ const SOURCE_ORDER: AuditSource[] = ['boot', 'system', 'policy', 'user', 'agent'];
42
+
43
+ export class AuditLog {
44
+ private entries: AuditEntry[] = [];
45
+ private listeners: Array<(entry: AuditEntry) => void> = [];
46
+
47
+ // Throttle buffers for stdout/stdin
48
+ private stdoutBuf = '';
49
+ private stdinBuf = '';
50
+ private stdoutTimer: ReturnType<typeof setTimeout> | null = null;
51
+ private stdinTimer: ReturnType<typeof setTimeout> | null = null;
52
+
53
+ /** Return a snapshot of all entries. */
54
+ getEntries(): AuditEntry[] {
55
+ return this.entries;
56
+ }
57
+
58
+ /** Subscribe to new entries. Returns unsubscribe function. */
59
+ onEntry(fn: (entry: AuditEntry) => void): () => void {
60
+ this.listeners.push(fn);
61
+ return () => { this.listeners = this.listeners.filter(l => l !== fn); };
62
+ }
63
+
64
+ /** Append an audit entry. */
65
+ log(
66
+ event: AuditEvent,
67
+ detail: string,
68
+ meta?: Record<string, unknown>,
69
+ opts?: { source?: AuditSource; level?: AuditLevel },
70
+ ): void {
71
+ const entry: AuditEntry = {
72
+ timestamp: new Date().toISOString(),
73
+ event,
74
+ detail,
75
+ ...(meta ? { meta } : {}),
76
+ source: opts?.source ?? 'system',
77
+ level: opts?.level ?? 'info',
78
+ };
79
+ this.entries.push(entry);
80
+ for (const fn of this.listeners) fn(entry);
81
+ }
82
+
83
+ /** Buffer stdout data; flushes after 500ms of quiet. */
84
+ logStdout(data: string): void {
85
+ this.stdoutBuf += data;
86
+ if (this.stdoutTimer) clearTimeout(this.stdoutTimer);
87
+ this.stdoutTimer = setTimeout(() => {
88
+ const text = this.stdoutBuf.slice(0, IO_MAX_CHARS);
89
+ this.stdoutBuf = '';
90
+ this.stdoutTimer = null;
91
+ this.log('io.stdout', text.length < this.stdoutBuf.length + text.length
92
+ ? text + '…[truncated]' : text, undefined, { source: 'agent' });
93
+ }, IO_BUFFER_MS);
94
+ }
95
+
96
+ /** Buffer stdin data; flushes after 500ms of quiet. */
97
+ logStdin(data: string): void {
98
+ this.stdinBuf += data;
99
+ if (this.stdinTimer) clearTimeout(this.stdinTimer);
100
+ this.stdinTimer = setTimeout(() => {
101
+ const text = this.stdinBuf.slice(0, IO_MAX_CHARS);
102
+ this.stdinBuf = '';
103
+ this.stdinTimer = null;
104
+ this.log('io.stdin', text.length < this.stdinBuf.length + text.length
105
+ ? text + '…[truncated]' : text, undefined, { source: 'agent' });
106
+ }, IO_BUFFER_MS);
107
+ }
108
+
109
+ /** Format all entries as downloadable text, grouped by source. */
110
+ toText(): string {
111
+ if (this.entries.length === 0) return '=== AUDIT LOG (empty) ===';
112
+
113
+ const first = this.entries[0].timestamp;
114
+ const last = this.entries[this.entries.length - 1].timestamp;
115
+
116
+ const lines: string[] = [];
117
+ lines.push(`=== AUDIT LOG (${first} — ${last}) ===`);
118
+ lines.push(`Total entries: ${this.entries.length}`);
119
+
120
+ // Group entries by source
121
+ const grouped = new Map<AuditSource, AuditEntry[]>();
122
+ for (const entry of this.entries) {
123
+ const src = entry.source ?? 'system';
124
+ if (!grouped.has(src)) grouped.set(src, []);
125
+ grouped.get(src)!.push(entry);
126
+ }
127
+
128
+ for (const source of SOURCE_ORDER) {
129
+ const entries = grouped.get(source);
130
+ if (!entries || entries.length === 0) continue;
131
+
132
+ const label = source.toUpperCase();
133
+ lines.push('');
134
+ lines.push(`── ${label} ${'─'.repeat(Math.max(0, 40 - label.length - 4))}`);
135
+
136
+ for (const e of entries) {
137
+ const time = e.timestamp.slice(11, 19); // HH:mm:ss
138
+ const lvl = (e.level ?? 'info').toUpperCase().padEnd(5);
139
+ let line = `[${time}] ${lvl} ${e.event.padEnd(16)} ${e.detail}`;
140
+ if (e.meta) line += ` ${JSON.stringify(e.meta)}`;
141
+ lines.push(line);
142
+ }
143
+ }
144
+
145
+ return lines.join('\n');
146
+ }
147
+
148
+ /** Export all entries as indented JSON. */
149
+ toJSON(): string {
150
+ return JSON.stringify(
151
+ {
152
+ exported: new Date().toISOString(),
153
+ count: this.entries.length,
154
+ entries: this.entries,
155
+ },
156
+ null,
157
+ 2,
158
+ );
159
+ }
160
+
161
+ /** Filter entries by source, level, and/or event type. */
162
+ filter(opts: { source?: AuditSource; level?: AuditLevel; event?: AuditEvent }): AuditEntry[] {
163
+ return this.entries.filter(e => {
164
+ if (opts.source && e.source !== opts.source) return false;
165
+ if (opts.level && e.level !== opts.level) return false;
166
+ if (opts.event && e.event !== opts.event) return false;
167
+ return true;
168
+ });
169
+ }
170
+
171
+ /** Mask a secret key: show first 7 + last 4 chars. */
172
+ static maskKey(val: string): string {
173
+ if (val.length <= 12) return '****';
174
+ return `${val.slice(0, 7)}…${val.slice(-4)}`;
175
+ }
176
+
177
+ /** Mask sensitive header values (authorization, api-key, tokens, etc.). */
178
+ static maskHeaders(headers: Record<string, string>): Record<string, string> {
179
+ const masked: Record<string, string> = {};
180
+ for (const [k, v] of Object.entries(headers)) {
181
+ if (SENSITIVE_HEADER_KEYS.test(k) || SENSITIVE_HEADER_PARTIAL.test(k)) {
182
+ masked[k] = AuditLog.maskKey(v);
183
+ } else {
184
+ masked[k] = v;
185
+ }
186
+ }
187
+ return masked;
188
+ }
189
+
190
+ /** Truncate a request/response body for audit logging. */
191
+ static truncateBody(body: string | undefined): string | undefined {
192
+ if (!body) return body;
193
+ if (body.length <= NET_BODY_MAX_CHARS) return body;
194
+ return body.slice(0, NET_BODY_MAX_CHARS) + '…[truncated]';
195
+ }
196
+ }