forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfakeAcpSubprocess.mjs
More file actions
86 lines (80 loc) · 2.76 KB
/
Copy pathfakeAcpSubprocess.mjs
File metadata and controls
86 lines (80 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/bin/env node
// Fake ACP peer for the real-subprocess integration test. Speaks just enough
// JSON-RPC 2.0 over stdio to exercise the adapter's real spawn/readline/kill
// machinery without any actual coding-agent install:
// initialize -> ack
// session/new -> mints a native session id
// session/prompt -> streams one agent_message_chunk echoing the prompt text,
// then resolves with a stop reason + usage
// Console noise goes to stderr; stdout is pure JSON-RPC (ACP requirement).
/* eslint-disable @typescript-eslint/explicit-function-return-type -- plain JS fixture */
import { createInterface } from 'node:readline'
const rl = createInterface({ input: process.stdin, terminal: false })
function send(message) {
process.stdout.write(`${JSON.stringify({ jsonrpc: '2.0', ...message })}\n`)
}
rl.on('line', (line) => {
if (!line.trim()) return
let msg
try {
msg = JSON.parse(line)
} catch {
console.error(`[fake-acp] unparseable line: ${line.slice(0, 120)}`)
return
}
if (msg.id === undefined || !msg.method) return // response or notification — ignore
switch (msg.method) {
case 'initialize':
send({ id: msg.id, result: { protocolVersion: 1 } })
break
case 'session/new':
send({ id: msg.id, result: { sessionId: 'fake-native-session' } })
break
case 'session/set_mode':
// openBinding pins the session permission mode after session/new.
send({ id: msg.id, result: {} })
break
case 'session/prompt': {
const text = (msg.params?.prompt ?? [])
.filter((block) => block.type === 'text')
.map((block) => block.text)
.join(' ')
send({
method: 'session/update',
params: {
sessionId: 'fake-native-session',
update: {
sessionUpdate: 'agent_message_chunk',
content: { type: 'text', text: `echo: ${text}` }
}
}
})
// Cost arrives via the standard usage_update notification (cumulative
// session cost), like @agentclientprotocol/claude-agent-acp emits it.
send({
method: 'session/update',
params: {
sessionId: 'fake-native-session',
update: {
sessionUpdate: 'usage_update',
used: 7,
size: 200000,
cost: { amount: 0.002, currency: 'USD' }
}
}
})
send({
id: msg.id,
result: {
stopReason: 'end_turn',
usage: { inputTokens: 3, outputTokens: 4, cachedReadTokens: 0, cachedWriteTokens: 0 },
_meta: { costUsd: 0.001 }
}
})
break
}
default:
send({ id: msg.id, error: { code: -32601, message: `unhandled: ${msg.method}` } })
}
})
process.stdin.on('end', () => process.exit(0))