@antelopejs/dms-ai 0.1.2 → 0.1.3

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 (144) hide show
  1. package/README.md +49 -0
  2. package/dist/channels/bridge.d.ts +22 -0
  3. package/dist/channels/bridge.js +87 -0
  4. package/dist/channels/bridge.js.map +1 -0
  5. package/dist/channels/channel-service.d.ts +5 -0
  6. package/dist/channels/channel-service.js +68 -0
  7. package/dist/channels/channel-service.js.map +1 -0
  8. package/dist/channels/message-budget.d.ts +3 -0
  9. package/dist/channels/message-budget.js +29 -0
  10. package/dist/channels/message-budget.js.map +1 -0
  11. package/dist/channels/registry.d.ts +7 -0
  12. package/dist/channels/registry.js +47 -0
  13. package/dist/channels/registry.js.map +1 -0
  14. package/dist/channels/sse-stream.d.ts +19 -0
  15. package/dist/channels/sse-stream.js +59 -0
  16. package/dist/channels/sse-stream.js.map +1 -0
  17. package/dist/chatbox/passthrough.d.ts +3 -0
  18. package/dist/chatbox/passthrough.js +53 -0
  19. package/dist/chatbox/passthrough.js.map +1 -0
  20. package/dist/constants/channels.d.ts +30 -0
  21. package/dist/constants/channels.js +38 -0
  22. package/dist/constants/channels.js.map +1 -0
  23. package/dist/constants/chatbox.d.ts +10 -0
  24. package/dist/constants/chatbox.js +35 -0
  25. package/dist/constants/chatbox.js.map +1 -0
  26. package/dist/constants/sidecar.d.ts +4 -0
  27. package/dist/constants/sidecar.js +3 -1
  28. package/dist/constants/sidecar.js.map +1 -1
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.js +5 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/lifecycle/sidecar-socket.d.ts +2 -0
  33. package/dist/lifecycle/sidecar-socket.js +37 -0
  34. package/dist/lifecycle/sidecar-socket.js.map +1 -0
  35. package/dist/lifecycle/sidecar-unavailable-error.d.ts +3 -0
  36. package/dist/lifecycle/sidecar-unavailable-error.js +10 -0
  37. package/dist/lifecycle/sidecar-unavailable-error.js.map +1 -0
  38. package/dist/routes/channels.d.ts +8 -0
  39. package/dist/routes/channels.js +52 -0
  40. package/dist/routes/channels.js.map +1 -0
  41. package/dist/routes/chatbox.d.ts +7 -0
  42. package/dist/routes/chatbox.js +47 -0
  43. package/dist/routes/chatbox.js.map +1 -0
  44. package/dist/routes/index.d.ts +2 -0
  45. package/dist/routes/index.js +2 -0
  46. package/dist/routes/index.js.map +1 -1
  47. package/dist/routes/sidecar-info.js +0 -2
  48. package/dist/routes/sidecar-info.js.map +1 -1
  49. package/frontend-vue/app/components/SettingsView.vue +8 -0
  50. package/frontend-vue/app/plugins/ai.client.ts +137 -58
  51. package/frontend-vue/app/runtime/channel-client.ts +265 -0
  52. package/frontend-vue/app/runtime/chat-transport.ts +82 -0
  53. package/frontend-vue/app/runtime/constants.ts +30 -14
  54. package/frontend-vue/app/runtime/current-page.ts +9 -5
  55. package/frontend-vue/app/runtime/event-stream.ts +75 -0
  56. package/frontend-vue/app/runtime/overlay.ts +23 -6
  57. package/frontend-vue/app/runtime/sidecar-status.ts +10 -25
  58. package/frontend-vue/app/runtime/theme-bridge.ts +16 -4
  59. package/frontend-vue/package.json +3 -0
  60. package/frontend-vue/tests/backoff.test.ts +15 -15
  61. package/frontend-vue/tests/channel-client.test.ts +247 -0
  62. package/frontend-vue/tests/chat-transport.test.ts +67 -0
  63. package/frontend-vue/tests/sidecar-status.test.ts +39 -0
  64. package/package.json +5 -3
  65. package/sidecar/chatbox/dist/assets/index-C8u7mkHn.css +1 -0
  66. package/sidecar/chatbox/dist/assets/index-tdZvY7ee.js +52 -0
  67. package/sidecar/chatbox/dist/index.html +2 -2
  68. package/sidecar/dist/agent/disposals.d.ts +5 -0
  69. package/sidecar/dist/agent/disposals.js +17 -0
  70. package/sidecar/dist/agent/disposals.js.map +1 -0
  71. package/sidecar/dist/agent/effective-mode.d.ts +2 -0
  72. package/sidecar/dist/agent/effective-mode.js +20 -0
  73. package/sidecar/dist/agent/effective-mode.js.map +1 -0
  74. package/sidecar/dist/agent/provider.d.ts +2 -2
  75. package/sidecar/dist/agent/runner-events.d.ts +9 -1
  76. package/sidecar/dist/agent/runner.d.ts +2 -2
  77. package/sidecar/dist/agent/runner.js +11 -5
  78. package/sidecar/dist/agent/runner.js.map +1 -1
  79. package/sidecar/dist/agent/session.d.ts +3 -3
  80. package/sidecar/dist/agent/session.js +54 -34
  81. package/sidecar/dist/agent/session.js.map +1 -1
  82. package/sidecar/dist/agent/switching-runner.js +16 -14
  83. package/sidecar/dist/agent/switching-runner.js.map +1 -1
  84. package/sidecar/dist/agent/turn-end-reasons.d.ts +3 -0
  85. package/sidecar/dist/agent/turn-end-reasons.js +24 -0
  86. package/sidecar/dist/agent/turn-end-reasons.js.map +1 -0
  87. package/sidecar/dist/constants/agent.d.ts +6 -1
  88. package/sidecar/dist/constants/agent.js +13 -1
  89. package/sidecar/dist/constants/agent.js.map +1 -1
  90. package/sidecar/dist/constants/claude.d.ts +27 -1
  91. package/sidecar/dist/constants/claude.js +49 -0
  92. package/sidecar/dist/constants/claude.js.map +1 -1
  93. package/sidecar/dist/constants/codex.d.ts +6 -0
  94. package/sidecar/dist/constants/codex.js +13 -0
  95. package/sidecar/dist/constants/codex.js.map +1 -1
  96. package/sidecar/dist/constants/settings.js.map +1 -1
  97. package/sidecar/dist/constants/timing.d.ts +1 -0
  98. package/sidecar/dist/constants/timing.js +1 -0
  99. package/sidecar/dist/constants/timing.js.map +1 -1
  100. package/sidecar/dist/protocol/events.d.ts +36 -0
  101. package/sidecar/dist/protocol/events.js +13 -0
  102. package/sidecar/dist/protocol/events.js.map +1 -1
  103. package/sidecar/dist/providers/claude/activity.d.ts +5 -0
  104. package/sidecar/dist/providers/claude/activity.js +63 -0
  105. package/sidecar/dist/providers/claude/activity.js.map +1 -0
  106. package/sidecar/dist/providers/claude/adapter.js +21 -13
  107. package/sidecar/dist/providers/claude/adapter.js.map +1 -1
  108. package/sidecar/dist/providers/claude/config.d.ts +2 -1
  109. package/sidecar/dist/providers/claude/config.js +4 -0
  110. package/sidecar/dist/providers/claude/config.js.map +1 -1
  111. package/sidecar/dist/providers/claude/provider.js +18 -25
  112. package/sidecar/dist/providers/claude/provider.js.map +1 -1
  113. package/sidecar/dist/providers/claude/result.d.ts +3 -0
  114. package/sidecar/dist/providers/claude/result.js +61 -0
  115. package/sidecar/dist/providers/claude/result.js.map +1 -0
  116. package/sidecar/dist/providers/claude/safe-mode.d.ts +4 -0
  117. package/sidecar/dist/providers/claude/safe-mode.js +24 -0
  118. package/sidecar/dist/providers/claude/safe-mode.js.map +1 -0
  119. package/sidecar/dist/providers/codex/adapter.js +8 -2
  120. package/sidecar/dist/providers/codex/adapter.js.map +1 -1
  121. package/sidecar/dist/providers/codex/client.d.ts +1 -0
  122. package/sidecar/dist/providers/codex/client.js +1 -0
  123. package/sidecar/dist/providers/codex/client.js.map +1 -1
  124. package/sidecar/dist/providers/codex/config.js +2 -1
  125. package/sidecar/dist/providers/codex/config.js.map +1 -1
  126. package/sidecar/dist/providers/codex/process.js +113 -33
  127. package/sidecar/dist/providers/codex/process.js.map +1 -1
  128. package/sidecar/dist/providers/codex/provider.js +6 -4
  129. package/sidecar/dist/providers/codex/provider.js.map +1 -1
  130. package/sidecar/dist/server/routing.js +39 -21
  131. package/sidecar/dist/server/routing.js.map +1 -1
  132. package/sidecar/dist/server/turn-progress.d.ts +13 -0
  133. package/sidecar/dist/server/turn-progress.js +72 -0
  134. package/sidecar/dist/server/turn-progress.js.map +1 -0
  135. package/sidecar/dist/server/ws.js +4 -2
  136. package/sidecar/dist/server/ws.js.map +1 -1
  137. package/sidecar/dist/state/types.d.ts +2 -1
  138. package/sidecar/dist/state/types.js +1 -0
  139. package/sidecar/dist/state/types.js.map +1 -1
  140. package/sidecar/package.json +1 -1
  141. package/frontend-vue/app/runtime/ws-client.ts +0 -196
  142. package/frontend-vue/tests/sidecar-auth.test.ts +0 -87
  143. package/sidecar/chatbox/dist/assets/index-CEZ1NLp9.js +0 -52
  144. 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
- })