micro-models-agent 0.31.0 → 0.33.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.
@@ -0,0 +1,194 @@
1
+ import { createRequire } from 'module'
2
+ import readline from 'readline'
3
+
4
+ const require = createRequire(import.meta.url)
5
+ const { chromium } = require('playwright')
6
+
7
+ const CONSOLE_CAP = 500
8
+ const NETWORK_CAP = 100
9
+ let maxLineChars = 400
10
+
11
+ let browser = null
12
+ let context = null
13
+ let page = null
14
+ let consoleBuf = []
15
+ let networkBuf = []
16
+ let lastUrl = ''
17
+
18
+ function pushConsole(type, text) {
19
+ if (consoleBuf.length >= CONSOLE_CAP) return
20
+ const clean = String(text).replace(/\s+/g, ' ').trim()
21
+ if (!clean) return
22
+ const line = clean.length > maxLineChars ? clean.slice(0, maxLineChars) + '…' : clean
23
+ consoleBuf.push({ type, text: line })
24
+ }
25
+
26
+ function pushNetwork(err) {
27
+ if (networkBuf.length >= NETWORK_CAP) return
28
+ networkBuf.push(err)
29
+ }
30
+
31
+ function drain() {
32
+ const consoleEvents = consoleBuf
33
+ const networkEvents = networkBuf
34
+ consoleBuf = []
35
+ networkBuf = []
36
+ return { console: consoleEvents, network: networkEvents }
37
+ }
38
+
39
+ function readInt(v, fallback) {
40
+ const n = Number(v)
41
+ return Number.isFinite(n) && n > 0 ? n : fallback
42
+ }
43
+
44
+ async function handleLaunch(params) {
45
+ if (browser) return { ok: true }
46
+ maxLineChars = readInt(params?.maxConsoleLineChars, 400)
47
+ browser = await chromium.launch({
48
+ headless: params?.headless !== false,
49
+ timeout: readInt(params?.timeoutMs, 30000),
50
+ })
51
+ context = await browser.newContext({
52
+ viewport: params?.viewport || { width: 1280, height: 720 },
53
+ })
54
+ page = await context.newPage()
55
+ page.setDefaultTimeout(readInt(params?.timeoutMs, 30000))
56
+
57
+ page.on('console', (msg) => pushConsole(msg.type(), msg.text()))
58
+ page.on('pageerror', (err) => pushConsole('pageerror', `Page error: ${err.message}`))
59
+ page.on('requestfailed', (req) => {
60
+ const failure = req.failure()
61
+ pushNetwork({ method: req.method(), url: req.url(), error: failure?.errorText || 'unknown' })
62
+ })
63
+
64
+ return { ok: true }
65
+ }
66
+
67
+ async function handleGoto(params) {
68
+ if (!page) return { ok: false, error: 'No page open' }
69
+ const url = String(params?.url || '')
70
+ const timeoutMs = readInt(params?.timeoutMs, 15000)
71
+ consoleBuf = []
72
+ networkBuf = []
73
+ try {
74
+ await page.goto(url, { waitUntil: 'domcontentloaded', timeout: timeoutMs })
75
+ lastUrl = page.url()
76
+ return { ok: true, data: { url: lastUrl } }
77
+ } catch (err) {
78
+ lastUrl = page.url()
79
+ return { ok: false, error: err.message, data: { url: lastUrl } }
80
+ }
81
+ }
82
+
83
+ async function handleEvaluate(params) {
84
+ if (!page) return { ok: false, error: 'No page open' }
85
+ const js = String(params?.js || '')
86
+ try {
87
+ const result = await page.evaluate(js)
88
+ return { ok: true, data: { result } }
89
+ } catch (err) {
90
+ return { ok: false, error: err.message }
91
+ }
92
+ }
93
+
94
+ async function handleClose() {
95
+ try {
96
+ if (page) await page.close()
97
+ } catch {}
98
+ try {
99
+ if (context) await context.close()
100
+ } catch {}
101
+ try {
102
+ if (browser) await browser.close()
103
+ } catch {}
104
+ page = null
105
+ context = null
106
+ browser = null
107
+ return { ok: true }
108
+ }
109
+
110
+ const handlers = {
111
+ ping: async () => ({ ok: true, data: { pong: true, runtime: process.version } }),
112
+ launch: handleLaunch,
113
+ goto: handleGoto,
114
+ evaluate: handleEvaluate,
115
+ content: async () => ({ ok: true, data: { html: page ? await page.content() : '' } }),
116
+ title: async () => ({ ok: true, data: { title: page ? await page.title() : '' } }),
117
+ url: async () => ({ ok: true, data: { url: page ? page.url() : lastUrl } }),
118
+ waitLoad: async (params) => {
119
+ if (!page) return { ok: false, error: 'No page open' }
120
+ try {
121
+ await page.waitForLoadState('domcontentloaded', { timeout: readInt(params?.timeoutMs, 15000) })
122
+ } catch {}
123
+ return { ok: true }
124
+ },
125
+ screenshot: async () => {
126
+ if (!page) return { ok: false, error: 'No page open' }
127
+ try {
128
+ const buf = await page.screenshot({ type: 'png', fullPage: false })
129
+ return { ok: true, data: { base64: buf.toString('base64') } }
130
+ } catch (err) {
131
+ return { ok: false, error: err.message }
132
+ }
133
+ },
134
+ cookies: async () => {
135
+ if (!context) return { ok: true, data: { cookies: [] } }
136
+ const cookies = await context.cookies()
137
+ return { ok: true, data: { cookies } }
138
+ },
139
+ setCookies: async (params) => {
140
+ if (!context) return { ok: false, error: 'No context' }
141
+ const cookies = Array.isArray(params?.cookies) ? params.cookies : []
142
+ if (cookies.length > 0) {
143
+ try {
144
+ await context.addCookies(cookies)
145
+ } catch (err) {
146
+ return { ok: false, error: err.message }
147
+ }
148
+ }
149
+ return { ok: true }
150
+ },
151
+ back: async (params) => {
152
+ if (!page) return { ok: false, error: 'No page open' }
153
+ try {
154
+ await page.goBack({ waitUntil: 'domcontentloaded', timeout: readInt(params?.timeoutMs, 15000) })
155
+ } catch {}
156
+ lastUrl = page.url()
157
+ return { ok: true, data: { url: lastUrl } }
158
+ },
159
+ forward: async (params) => {
160
+ if (!page) return { ok: false, error: 'No page open' }
161
+ try {
162
+ await page.goForward({ waitUntil: 'domcontentloaded', timeout: readInt(params?.timeoutMs, 15000) })
163
+ } catch {}
164
+ lastUrl = page.url()
165
+ return { ok: true, data: { url: lastUrl } }
166
+ },
167
+ close: handleClose,
168
+ }
169
+
170
+ const rl = readline.createInterface({ input: process.stdin })
171
+ rl.on('line', async (line) => {
172
+ let req
173
+ try {
174
+ req = JSON.parse(line)
175
+ } catch {
176
+ return
177
+ }
178
+ const handler = handlers[req.cmd]
179
+ let resp
180
+ if (!handler) {
181
+ resp = { id: req.id, ok: false, error: `Unknown command: ${req.cmd}`, ...drain() }
182
+ } else {
183
+ try {
184
+ const result = await handler(req.params || {})
185
+ resp = { id: req.id, ...result, ...drain() }
186
+ } catch (err) {
187
+ resp = { id: req.id, ok: false, error: err.message, ...drain() }
188
+ }
189
+ }
190
+ process.stdout.write(JSON.stringify(resp) + '\n')
191
+ })
192
+
193
+ process.on('SIGTERM', () => process.exit(0))
194
+ process.on('SIGINT', () => process.exit(0))
package/package.json CHANGED
@@ -1,45 +1,45 @@
1
- {
2
- "name": "micro-models-agent",
3
- "version": "0.31.0",
4
- "description": "Micro Models Agent (MMA) — LLM agent harness for small models (Qwen3.5-9B, 32K-64K context)",
5
- "type": "module",
6
- "bin": {
7
- "mma": "bin/mma.mjs"
8
- },
9
- "files": [
10
- "dist/",
11
- "bin/"
12
- ],
13
- "engines": {
14
- "node": ">=20"
15
- },
16
- "scripts": {
17
- "mma": "bun run src/cli/main.ts",
18
- "build": "bun run build:tsc && bun run build:copy-assets",
19
- "build:tsc": "tsc -p tsconfig.build.json",
20
- "build:copy-assets": "bun run scripts/copy-assets.ts",
21
- "build:prod": "bun run 'build:bundle' && bun run 'build:copy-assets'",
22
- "build:clean": "cmd /c \"if exist dist rmdir /s /q dist\"",
23
- "build:bundle": "bun build ./src/cli/main.ts --outfile ./dist/main.js --target node --format esm --external playwright",
24
- "dev": "bun --watch src/cli/main.ts",
25
- "typecheck": "tsc --noEmit",
26
- "test": "vitest run",
27
- "test:watch": "vitest",
28
- "test:integration": "vitest run --config vitest.integration.config.ts"
29
- },
30
- "dependencies": {
31
- "commander": "^12.0.0",
32
- "js-tiktoken": "^1.0.0",
33
- "jsonrepair": "^3.15.0",
34
- "picocolors": "^1.1.1",
35
- "playwright": "^1.62.0",
36
- "string-width": "^8.2.2",
37
- "yaml": "^2.9.0"
38
- },
39
- "devDependencies": {
40
- "@types/bun": "^1.3.14",
41
- "@types/node": "^22.20.1",
42
- "typescript": "^5.9.3",
43
- "vitest": "^4.1.10"
44
- }
45
- }
1
+ {
2
+ "name": "micro-models-agent",
3
+ "version": "0.33.0",
4
+ "description": "Micro Models Agent (MMA) — LLM agent harness for small models (Qwen3.5-9B, 32K-64K context)",
5
+ "type": "module",
6
+ "bin": {
7
+ "mma": "bin/mma.mjs"
8
+ },
9
+ "files": [
10
+ "dist/",
11
+ "bin/"
12
+ ],
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
16
+ "scripts": {
17
+ "mma": "bun run src/cli/main.ts",
18
+ "build": "bun run build:tsc && bun run build:copy-assets",
19
+ "build:tsc": "tsc -p tsconfig.build.json",
20
+ "build:copy-assets": "bun run scripts/copy-assets.ts",
21
+ "build:prod": "bun run 'build:bundle' && bun run 'build:copy-assets'",
22
+ "build:clean": "cmd /c \"if exist dist rmdir /s /q dist\"",
23
+ "build:bundle": "bun build ./src/cli/main.ts --outfile ./dist/main.js --target node --format esm --external playwright",
24
+ "dev": "bun --watch src/cli/main.ts",
25
+ "typecheck": "tsc --noEmit",
26
+ "test": "vitest run",
27
+ "test:watch": "vitest",
28
+ "test:integration": "vitest run --config vitest.integration.config.ts"
29
+ },
30
+ "dependencies": {
31
+ "commander": "^12.0.0",
32
+ "js-tiktoken": "^1.0.0",
33
+ "jsonrepair": "^3.15.0",
34
+ "picocolors": "^1.1.1",
35
+ "playwright": "^1.62.0",
36
+ "string-width": "^8.2.2",
37
+ "yaml": "^2.9.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/bun": "^1.3.14",
41
+ "@types/node": "^22.20.1",
42
+ "typescript": "^5.9.3",
43
+ "vitest": "^4.1.10"
44
+ }
45
+ }