@antelopejs/dms-ai 0.1.2 → 0.1.4
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.
- package/README.md +49 -0
- package/dist/channels/bridge.d.ts +22 -0
- package/dist/channels/bridge.js +87 -0
- package/dist/channels/bridge.js.map +1 -0
- package/dist/channels/channel-service.d.ts +5 -0
- package/dist/channels/channel-service.js +68 -0
- package/dist/channels/channel-service.js.map +1 -0
- package/dist/channels/message-budget.d.ts +3 -0
- package/dist/channels/message-budget.js +29 -0
- package/dist/channels/message-budget.js.map +1 -0
- package/dist/channels/registry.d.ts +7 -0
- package/dist/channels/registry.js +47 -0
- package/dist/channels/registry.js.map +1 -0
- package/dist/channels/sse-stream.d.ts +19 -0
- package/dist/channels/sse-stream.js +59 -0
- package/dist/channels/sse-stream.js.map +1 -0
- package/dist/chatbox/passthrough.d.ts +3 -0
- package/dist/chatbox/passthrough.js +53 -0
- package/dist/chatbox/passthrough.js.map +1 -0
- package/dist/constants/channels.d.ts +30 -0
- package/dist/constants/channels.js +38 -0
- package/dist/constants/channels.js.map +1 -0
- package/dist/constants/chatbox.d.ts +10 -0
- package/dist/constants/chatbox.js +35 -0
- package/dist/constants/chatbox.js.map +1 -0
- package/dist/constants/sidecar.d.ts +4 -0
- package/dist/constants/sidecar.js +3 -1
- package/dist/constants/sidecar.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/sidecar-socket.d.ts +2 -0
- package/dist/lifecycle/sidecar-socket.js +37 -0
- package/dist/lifecycle/sidecar-socket.js.map +1 -0
- package/dist/lifecycle/sidecar-unavailable-error.d.ts +3 -0
- package/dist/lifecycle/sidecar-unavailable-error.js +10 -0
- package/dist/lifecycle/sidecar-unavailable-error.js.map +1 -0
- package/dist/pages/settings/page.js.map +1 -1
- package/dist/routes/channels.d.ts +8 -0
- package/dist/routes/channels.js +52 -0
- package/dist/routes/channels.js.map +1 -0
- package/dist/routes/chatbox.d.ts +7 -0
- package/dist/routes/chatbox.js +47 -0
- package/dist/routes/chatbox.js.map +1 -0
- package/dist/routes/index.d.ts +2 -0
- package/dist/routes/index.js +2 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/sidecar-info.js +0 -2
- package/dist/routes/sidecar-info.js.map +1 -1
- package/frontend-vue/app/components/SettingsView.vue +19 -22
- package/frontend-vue/app/plugins/ai.client.ts +137 -58
- package/frontend-vue/app/runtime/channel-client.ts +265 -0
- package/frontend-vue/app/runtime/chat-transport.ts +82 -0
- package/frontend-vue/app/runtime/constants.ts +31 -15
- package/frontend-vue/app/runtime/current-page.ts +9 -5
- package/frontend-vue/app/runtime/event-stream.ts +75 -0
- package/frontend-vue/app/runtime/overlay.ts +23 -6
- package/frontend-vue/app/runtime/sidecar-status.ts +10 -25
- package/frontend-vue/app/runtime/theme-bridge.ts +16 -4
- package/frontend-vue/package.json +3 -0
- package/frontend-vue/tests/backoff.test.ts +15 -15
- package/frontend-vue/tests/channel-client.test.ts +247 -0
- package/frontend-vue/tests/chat-transport.test.ts +67 -0
- package/frontend-vue/tests/sidecar-status.test.ts +39 -0
- package/package.json +5 -3
- package/sidecar/chatbox/dist/assets/index-C8u7mkHn.css +1 -0
- package/sidecar/chatbox/dist/assets/index-tdZvY7ee.js +52 -0
- package/sidecar/chatbox/dist/index.html +2 -2
- package/sidecar/dist/agent/disposals.d.ts +5 -0
- package/sidecar/dist/agent/disposals.js +17 -0
- package/sidecar/dist/agent/disposals.js.map +1 -0
- package/sidecar/dist/agent/effective-mode.d.ts +2 -0
- package/sidecar/dist/agent/effective-mode.js +20 -0
- package/sidecar/dist/agent/effective-mode.js.map +1 -0
- package/sidecar/dist/agent/provider.d.ts +2 -2
- package/sidecar/dist/agent/runner-events.d.ts +9 -1
- package/sidecar/dist/agent/runner.d.ts +2 -2
- package/sidecar/dist/agent/runner.js +11 -5
- package/sidecar/dist/agent/runner.js.map +1 -1
- package/sidecar/dist/agent/session.d.ts +3 -3
- package/sidecar/dist/agent/session.js +54 -34
- package/sidecar/dist/agent/session.js.map +1 -1
- package/sidecar/dist/agent/switching-runner.js +16 -14
- package/sidecar/dist/agent/switching-runner.js.map +1 -1
- package/sidecar/dist/agent/turn-end-reasons.d.ts +3 -0
- package/sidecar/dist/agent/turn-end-reasons.js +24 -0
- package/sidecar/dist/agent/turn-end-reasons.js.map +1 -0
- package/sidecar/dist/constants/agent.d.ts +6 -1
- package/sidecar/dist/constants/agent.js +13 -1
- package/sidecar/dist/constants/agent.js.map +1 -1
- package/sidecar/dist/constants/claude.d.ts +27 -1
- package/sidecar/dist/constants/claude.js +49 -0
- package/sidecar/dist/constants/claude.js.map +1 -1
- package/sidecar/dist/constants/codex.d.ts +6 -0
- package/sidecar/dist/constants/codex.js +13 -0
- package/sidecar/dist/constants/codex.js.map +1 -1
- package/sidecar/dist/constants/settings.js.map +1 -1
- package/sidecar/dist/constants/timing.d.ts +1 -0
- package/sidecar/dist/constants/timing.js +1 -0
- package/sidecar/dist/constants/timing.js.map +1 -1
- package/sidecar/dist/protocol/events.d.ts +36 -0
- package/sidecar/dist/protocol/events.js +13 -0
- package/sidecar/dist/protocol/events.js.map +1 -1
- package/sidecar/dist/providers/claude/activity.d.ts +5 -0
- package/sidecar/dist/providers/claude/activity.js +63 -0
- package/sidecar/dist/providers/claude/activity.js.map +1 -0
- package/sidecar/dist/providers/claude/adapter.js +21 -13
- package/sidecar/dist/providers/claude/adapter.js.map +1 -1
- package/sidecar/dist/providers/claude/config.d.ts +2 -1
- package/sidecar/dist/providers/claude/config.js +4 -0
- package/sidecar/dist/providers/claude/config.js.map +1 -1
- package/sidecar/dist/providers/claude/provider.js +18 -25
- package/sidecar/dist/providers/claude/provider.js.map +1 -1
- package/sidecar/dist/providers/claude/result.d.ts +3 -0
- package/sidecar/dist/providers/claude/result.js +61 -0
- package/sidecar/dist/providers/claude/result.js.map +1 -0
- package/sidecar/dist/providers/claude/safe-mode.d.ts +4 -0
- package/sidecar/dist/providers/claude/safe-mode.js +24 -0
- package/sidecar/dist/providers/claude/safe-mode.js.map +1 -0
- package/sidecar/dist/providers/codex/adapter.js +8 -2
- package/sidecar/dist/providers/codex/adapter.js.map +1 -1
- package/sidecar/dist/providers/codex/client.d.ts +1 -0
- package/sidecar/dist/providers/codex/client.js +1 -0
- package/sidecar/dist/providers/codex/client.js.map +1 -1
- package/sidecar/dist/providers/codex/config.js +2 -1
- package/sidecar/dist/providers/codex/config.js.map +1 -1
- package/sidecar/dist/providers/codex/process.js +113 -33
- package/sidecar/dist/providers/codex/process.js.map +1 -1
- package/sidecar/dist/providers/codex/provider.js +6 -4
- package/sidecar/dist/providers/codex/provider.js.map +1 -1
- package/sidecar/dist/server/routing.js +39 -21
- package/sidecar/dist/server/routing.js.map +1 -1
- package/sidecar/dist/server/turn-progress.d.ts +13 -0
- package/sidecar/dist/server/turn-progress.js +72 -0
- package/sidecar/dist/server/turn-progress.js.map +1 -0
- package/sidecar/dist/server/ws.js +4 -2
- package/sidecar/dist/server/ws.js.map +1 -1
- package/sidecar/dist/state/types.d.ts +2 -1
- package/sidecar/dist/state/types.js +1 -0
- package/sidecar/dist/state/types.js.map +1 -1
- package/sidecar/package.json +1 -1
- package/frontend-vue/app/runtime/ws-client.ts +0 -196
- package/frontend-vue/tests/sidecar-auth.test.ts +0 -87
- package/sidecar/chatbox/dist/assets/index-CEZ1NLp9.js +0 -52
- package/sidecar/chatbox/dist/assets/index-D_51Vqqk.css +0 -1
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import { createBackoff, nextDelay, resetBackoff } from './backoff'
|
|
2
|
-
import {
|
|
3
|
-
HELLO_MESSAGE_TYPE,
|
|
4
|
-
HOST_ROLE,
|
|
5
|
-
LOG_PREFIX,
|
|
6
|
-
PAGE_PROTOCOL_SECURE,
|
|
7
|
-
WS_HOST_PATH,
|
|
8
|
-
WS_PROTOCOL_INSECURE,
|
|
9
|
-
WS_PROTOCOL_SECURE,
|
|
10
|
-
WS_RECONNECT_DELAYS_MS,
|
|
11
|
-
WS_STATUS_CONNECTED,
|
|
12
|
-
WS_STATUS_CONNECTING,
|
|
13
|
-
WS_STATUS_DISCONNECTED,
|
|
14
|
-
WS_STATUS_RECONNECTING,
|
|
15
|
-
} from './constants'
|
|
16
|
-
|
|
17
|
-
export type ConnectionStatus =
|
|
18
|
-
| typeof WS_STATUS_CONNECTING
|
|
19
|
-
| typeof WS_STATUS_CONNECTED
|
|
20
|
-
| typeof WS_STATUS_DISCONNECTED
|
|
21
|
-
| typeof WS_STATUS_RECONNECTING
|
|
22
|
-
|
|
23
|
-
interface CreateHostWsClientOptions {
|
|
24
|
-
sidecarHost: string
|
|
25
|
-
// The sidecar's port is read fresh on every (re)connect: an idle-exit + respawn
|
|
26
|
-
// lands on a new random port, so a fixed port could never reconnect. Returns
|
|
27
|
-
// null while no port is known yet, in which case connecting is deferred.
|
|
28
|
-
getPort: () => number | null
|
|
29
|
-
getClientToken: () => string | null
|
|
30
|
-
onMessage?: (raw: unknown) => void
|
|
31
|
-
onStatusChange?: (status: ConnectionStatus) => void
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface HostWsClient {
|
|
35
|
-
close: () => void
|
|
36
|
-
isConnected: () => boolean
|
|
37
|
-
send: (msg: unknown) => void
|
|
38
|
-
getStatus: () => ConnectionStatus
|
|
39
|
-
// Drop any pending backoff and reconnect immediately against the current port.
|
|
40
|
-
// Called when the status controller has relearned a fresh port.
|
|
41
|
-
reconnectNow: () => void
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function buildWsUrl(host: string, port: number): string {
|
|
45
|
-
const isSecure = window.location.protocol === PAGE_PROTOCOL_SECURE
|
|
46
|
-
const scheme = isSecure ? WS_PROTOCOL_SECURE : WS_PROTOCOL_INSECURE
|
|
47
|
-
return `${scheme}//${host}:${port}${WS_HOST_PATH}`
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
interface ConnectHandlers {
|
|
51
|
-
onOpen: (socket: WebSocket) => void
|
|
52
|
-
onClose: () => void
|
|
53
|
-
onError: (event: Event) => void
|
|
54
|
-
onMessage: (raw: unknown) => void
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function connect(
|
|
58
|
-
url: string,
|
|
59
|
-
handlers: ConnectHandlers,
|
|
60
|
-
token: string,
|
|
61
|
-
): WebSocket {
|
|
62
|
-
const socket = new WebSocket(url, `dms-ai.${token}`)
|
|
63
|
-
socket.addEventListener('open', () => handlers.onOpen(socket))
|
|
64
|
-
socket.addEventListener('close', () => handlers.onClose())
|
|
65
|
-
socket.addEventListener('error', (event) => handlers.onError(event))
|
|
66
|
-
socket.addEventListener('message', (event) => handlers.onMessage(event.data))
|
|
67
|
-
return socket
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function sendHello(socket: WebSocket): void {
|
|
71
|
-
const payload = { type: HELLO_MESSAGE_TYPE, role: HOST_ROLE }
|
|
72
|
-
socket.send(JSON.stringify(payload))
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function logError(event: Event): void {
|
|
76
|
-
console.error(`${LOG_PREFIX} ws error`, event)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function buildOnMessage(
|
|
80
|
-
options: CreateHostWsClientOptions,
|
|
81
|
-
): (raw: unknown) => void {
|
|
82
|
-
const handler = options.onMessage
|
|
83
|
-
if (handler === undefined) return () => {}
|
|
84
|
-
return handler
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
interface StatusController {
|
|
88
|
-
get: () => ConnectionStatus
|
|
89
|
-
set: (next: ConnectionStatus) => void
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function createStatusController(
|
|
93
|
-
notify: (status: ConnectionStatus) => void,
|
|
94
|
-
): StatusController {
|
|
95
|
-
let current: ConnectionStatus = WS_STATUS_CONNECTING
|
|
96
|
-
return {
|
|
97
|
-
get: () => current,
|
|
98
|
-
set: (next) => {
|
|
99
|
-
if (current === next) return
|
|
100
|
-
current = next
|
|
101
|
-
notify(next)
|
|
102
|
-
},
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function buildStatusNotifier(
|
|
107
|
-
options: CreateHostWsClientOptions,
|
|
108
|
-
): (status: ConnectionStatus) => void {
|
|
109
|
-
const handler = options.onStatusChange
|
|
110
|
-
if (handler === undefined) return () => {}
|
|
111
|
-
return handler
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function createHostWsClient(
|
|
115
|
-
options: CreateHostWsClientOptions,
|
|
116
|
-
): HostWsClient {
|
|
117
|
-
const onMessage = buildOnMessage(options)
|
|
118
|
-
const status = createStatusController(buildStatusNotifier(options))
|
|
119
|
-
const backoff = createBackoff()
|
|
120
|
-
let socket: WebSocket | null = null
|
|
121
|
-
let retryTimer: ReturnType<typeof setTimeout> | null = null
|
|
122
|
-
let isIntentionallyClosed = false
|
|
123
|
-
const open = () => {
|
|
124
|
-
if (isIntentionallyClosed) return
|
|
125
|
-
const port = options.getPort()
|
|
126
|
-
const token = options.getClientToken()
|
|
127
|
-
// No port yet (sidecar reviving): stay in reconnecting and wait — the
|
|
128
|
-
// controller calls reconnectNow() once it relearns one.
|
|
129
|
-
if (port === null || !token) {
|
|
130
|
-
status.set(WS_STATUS_RECONNECTING)
|
|
131
|
-
scheduleRetry()
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
socket = connect(
|
|
135
|
-
buildWsUrl(options.sidecarHost, port),
|
|
136
|
-
{
|
|
137
|
-
onOpen: (s) => {
|
|
138
|
-
resetBackoff(backoff)
|
|
139
|
-
status.set(WS_STATUS_CONNECTED)
|
|
140
|
-
sendHello(s)
|
|
141
|
-
},
|
|
142
|
-
onClose: () => handleClose(),
|
|
143
|
-
onError: logError,
|
|
144
|
-
onMessage,
|
|
145
|
-
},
|
|
146
|
-
token,
|
|
147
|
-
)
|
|
148
|
-
}
|
|
149
|
-
const scheduleRetry = () => {
|
|
150
|
-
if (retryTimer !== null) return
|
|
151
|
-
const delay = nextDelay(backoff, WS_RECONNECT_DELAYS_MS)
|
|
152
|
-
retryTimer = setTimeout(() => {
|
|
153
|
-
retryTimer = null
|
|
154
|
-
open()
|
|
155
|
-
}, delay)
|
|
156
|
-
}
|
|
157
|
-
const handleClose = () => {
|
|
158
|
-
socket = null
|
|
159
|
-
if (isIntentionallyClosed) {
|
|
160
|
-
status.set(WS_STATUS_DISCONNECTED)
|
|
161
|
-
return
|
|
162
|
-
}
|
|
163
|
-
status.set(WS_STATUS_RECONNECTING)
|
|
164
|
-
scheduleRetry()
|
|
165
|
-
}
|
|
166
|
-
status.set(WS_STATUS_CONNECTING)
|
|
167
|
-
open()
|
|
168
|
-
return {
|
|
169
|
-
close: () => {
|
|
170
|
-
isIntentionallyClosed = true
|
|
171
|
-
if (retryTimer !== null) {
|
|
172
|
-
clearTimeout(retryTimer)
|
|
173
|
-
retryTimer = null
|
|
174
|
-
}
|
|
175
|
-
socket?.close()
|
|
176
|
-
},
|
|
177
|
-
isConnected: () => socket?.readyState === WebSocket.OPEN,
|
|
178
|
-
send: (msg: unknown) => socket?.send(JSON.stringify(msg)),
|
|
179
|
-
getStatus: () => status.get(),
|
|
180
|
-
reconnectNow: () => {
|
|
181
|
-
if (isIntentionallyClosed) return
|
|
182
|
-
if (retryTimer !== null) {
|
|
183
|
-
clearTimeout(retryTimer)
|
|
184
|
-
retryTimer = null
|
|
185
|
-
}
|
|
186
|
-
resetBackoff(backoff)
|
|
187
|
-
// A live socket on the old port is stale after a port change; drop it and
|
|
188
|
-
// reopen. If it was already open on the right port, onClose reopens too.
|
|
189
|
-
if (socket !== null) {
|
|
190
|
-
socket.close()
|
|
191
|
-
return
|
|
192
|
-
}
|
|
193
|
-
open()
|
|
194
|
-
},
|
|
195
|
-
}
|
|
196
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
-
import { createSidecarStatusController } from '../app/runtime/sidecar-status'
|
|
3
|
-
import { createHostWsClient } from '../app/runtime/ws-client'
|
|
4
|
-
|
|
5
|
-
class FakeWebSocket extends EventTarget {
|
|
6
|
-
static OPEN = 1
|
|
7
|
-
readyState = 0
|
|
8
|
-
send = vi.fn()
|
|
9
|
-
close = vi.fn()
|
|
10
|
-
constructor(
|
|
11
|
-
public url: string,
|
|
12
|
-
public protocols?: string | string[],
|
|
13
|
-
) {
|
|
14
|
-
super()
|
|
15
|
-
sockets.push(this)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const sockets: FakeWebSocket[] = []
|
|
20
|
-
afterEach(() => {
|
|
21
|
-
sockets.length = 0
|
|
22
|
-
vi.unstubAllGlobals()
|
|
23
|
-
vi.useRealTimers()
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
describe('sidecar client credential lifecycle', () => {
|
|
27
|
-
it('requires an authenticated bootstrap result and relearns credentials after restart', async () => {
|
|
28
|
-
const fetchInfo = vi
|
|
29
|
-
.fn()
|
|
30
|
-
.mockResolvedValueOnce({
|
|
31
|
-
port: 41001,
|
|
32
|
-
clientToken: 'first',
|
|
33
|
-
isRunning: true,
|
|
34
|
-
})
|
|
35
|
-
.mockResolvedValueOnce({
|
|
36
|
-
port: 41002,
|
|
37
|
-
clientToken: 'second',
|
|
38
|
-
isRunning: true,
|
|
39
|
-
})
|
|
40
|
-
const controller = createSidecarStatusController(fetchInfo)
|
|
41
|
-
expect(await controller.init()).toBe(true)
|
|
42
|
-
expect(controller.getClientToken()).toBe('first')
|
|
43
|
-
controller.reportWsDown()
|
|
44
|
-
await vi.waitFor(() => expect(controller.getClientToken()).toBe('second'))
|
|
45
|
-
expect(controller.getPort()).toBe(41002)
|
|
46
|
-
controller.dispose()
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
it('does not report a legacy unauthenticated sidecar as connected', async () => {
|
|
50
|
-
const controller = createSidecarStatusController(async () => ({
|
|
51
|
-
port: 41001,
|
|
52
|
-
isRunning: true,
|
|
53
|
-
}))
|
|
54
|
-
await controller.init()
|
|
55
|
-
expect(controller.getStatus()).not.toBe('connected')
|
|
56
|
-
expect(controller.getClientToken()).toBeNull()
|
|
57
|
-
controller.dispose()
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('sends the credential only as a WS subprotocol and updates it on reconnect', () => {
|
|
61
|
-
vi.stubGlobal('WebSocket', FakeWebSocket)
|
|
62
|
-
let token: string | null = 'first'
|
|
63
|
-
const client = createHostWsClient({
|
|
64
|
-
sidecarHost: 'localhost',
|
|
65
|
-
getPort: () => 41001,
|
|
66
|
-
getClientToken: () => token,
|
|
67
|
-
})
|
|
68
|
-
expect(sockets[0]?.protocols).toBe('dms-ai.first')
|
|
69
|
-
expect(sockets[0]?.url).toBe('ws://localhost:41001/ws/host')
|
|
70
|
-
sockets[0]?.dispatchEvent(new Event('close'))
|
|
71
|
-
token = 'second'
|
|
72
|
-
client.reconnectNow()
|
|
73
|
-
expect(sockets[1]?.protocols).toBe('dms-ai.second')
|
|
74
|
-
client.close()
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('does not open a socket before a credential is available', () => {
|
|
78
|
-
vi.stubGlobal('WebSocket', FakeWebSocket)
|
|
79
|
-
const client = createHostWsClient({
|
|
80
|
-
sidecarHost: 'localhost',
|
|
81
|
-
getPort: () => 41001,
|
|
82
|
-
getClientToken: () => null,
|
|
83
|
-
})
|
|
84
|
-
expect(sockets).toHaveLength(0)
|
|
85
|
-
client.close()
|
|
86
|
-
})
|
|
87
|
-
})
|