@stonerzju/opencode 1.2.16-offline.1 → 1.2.18

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 (262) hide show
  1. package/bin/opencode +29 -157
  2. package/package.json +29 -29
  3. package/src/acp/agent.ts +4 -4
  4. package/src/acp/session.ts +1 -1
  5. package/src/agent/agent.ts +3 -3
  6. package/src/bun/index.ts +2 -2
  7. package/src/cli/cmd/acp.ts +3 -3
  8. package/src/cli/cmd/debug/file.ts +1 -1
  9. package/src/cli/cmd/github.ts +2 -2
  10. package/src/cli/cmd/pr.ts +1 -1
  11. package/src/cli/cmd/tui/app.tsx +24 -24
  12. package/src/cli/cmd/tui/attach.ts +3 -3
  13. package/src/cli/cmd/tui/component/dialog-agent.tsx +3 -3
  14. package/src/cli/cmd/tui/component/dialog-command.tsx +3 -3
  15. package/src/cli/cmd/tui/component/dialog-mcp.tsx +5 -5
  16. package/src/cli/cmd/tui/component/dialog-model.tsx +4 -4
  17. package/src/cli/cmd/tui/component/dialog-provider.tsx +4 -4
  18. package/src/cli/cmd/tui/component/dialog-session-list.tsx +5 -5
  19. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +3 -3
  20. package/src/cli/cmd/tui/component/dialog-skill.tsx +3 -3
  21. package/src/cli/cmd/tui/component/dialog-stash.tsx +3 -3
  22. package/src/cli/cmd/tui/component/dialog-status.tsx +2 -2
  23. package/src/cli/cmd/tui/component/dialog-tag.tsx +3 -3
  24. package/src/cli/cmd/tui/component/logo.tsx +2 -2
  25. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +6 -6
  26. package/src/cli/cmd/tui/component/prompt/frecency.tsx +2 -2
  27. package/src/cli/cmd/tui/component/prompt/history.tsx +2 -2
  28. package/src/cli/cmd/tui/component/prompt/index.tsx +14 -14
  29. package/src/cli/cmd/tui/component/prompt/stash.tsx +2 -2
  30. package/src/cli/cmd/tui/component/textarea-keybindings.ts +1 -1
  31. package/src/cli/cmd/tui/component/tips.tsx +1 -1
  32. package/src/cli/cmd/tui/context/directory.ts +1 -1
  33. package/src/cli/cmd/tui/context/exit.tsx +1 -1
  34. package/src/cli/cmd/tui/context/keybind.tsx +2 -2
  35. package/src/cli/cmd/tui/context/kv.tsx +2 -2
  36. package/src/cli/cmd/tui/context/local.tsx +6 -6
  37. package/src/cli/cmd/tui/context/sync.tsx +4 -4
  38. package/src/cli/cmd/tui/context/theme/opencode.json +245 -0
  39. package/src/cli/cmd/tui/context/theme.tsx +2 -2
  40. package/src/cli/cmd/tui/context/tui-config.tsx +1 -1
  41. package/src/cli/cmd/tui/event.ts +2 -2
  42. package/src/cli/cmd/tui/routes/home.tsx +6 -6
  43. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +6 -6
  44. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +6 -6
  45. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +2 -2
  46. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +3 -3
  47. package/src/cli/cmd/tui/routes/session/header.tsx +5 -5
  48. package/src/cli/cmd/tui/routes/session/index.tsx +32 -32
  49. package/src/cli/cmd/tui/routes/session/permission.tsx +4 -4
  50. package/src/cli/cmd/tui/routes/session/sidebar.tsx +4 -4
  51. package/src/cli/cmd/tui/thread.ts +9 -9
  52. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +1 -1
  53. package/src/cli/cmd/tui/ui/dialog-help.tsx +2 -2
  54. package/src/cli/cmd/tui/ui/dialog-select.tsx +5 -5
  55. package/src/cli/cmd/tui/ui/dialog.tsx +3 -3
  56. package/src/cli/cmd/tui/ui/toast.tsx +1 -1
  57. package/src/cli/cmd/tui/util/editor.ts +3 -3
  58. package/src/cli/cmd/tui/util/transcript.ts +1 -1
  59. package/src/cli/cmd/tui/worker.ts +10 -10
  60. package/src/cli/error.ts +1 -1
  61. package/src/cli/ui.ts +1 -1
  62. package/src/cli/upgrade.ts +4 -4
  63. package/src/command/index.ts +1 -1
  64. package/src/config/config.ts +10 -10
  65. package/src/config/markdown.ts +1 -1
  66. package/src/config/migrate-tui-config.ts +5 -5
  67. package/src/config/paths.ts +4 -4
  68. package/src/config/tui.ts +4 -4
  69. package/src/control/control.sql.ts +1 -1
  70. package/src/control/index.ts +1 -1
  71. package/src/control-plane/adaptors/worktree.ts +1 -1
  72. package/src/control-plane/session-proxy-middleware.ts +1 -1
  73. package/src/control-plane/workspace.sql.ts +1 -1
  74. package/src/control-plane/workspace.ts +7 -7
  75. package/src/file/index.ts +1 -1
  76. package/src/file/ripgrep.ts +2 -2
  77. package/src/file/watcher.ts +5 -5
  78. package/src/format/formatter.ts +1 -1
  79. package/src/ide/index.ts +3 -3
  80. package/src/index.ts +1 -1
  81. package/src/installation/index.ts +3 -3
  82. package/src/lsp/client.ts +3 -3
  83. package/src/lsp/index.ts +3 -3
  84. package/src/mcp/index.ts +4 -4
  85. package/src/permission/index.ts +2 -2
  86. package/src/permission/next.ts +10 -10
  87. package/src/plugin/codex.ts +1 -1
  88. package/src/plugin/copilot.ts +2 -2
  89. package/src/plugin/index.ts +1 -1
  90. package/src/project/bootstrap.ts +2 -2
  91. package/src/project/instance.ts +4 -4
  92. package/src/project/project.sql.ts +1 -1
  93. package/src/project/project.ts +5 -5
  94. package/src/project/state.ts +1 -1
  95. package/src/project/vcs.ts +4 -4
  96. package/src/provider/auth.ts +4 -4
  97. package/src/provider/error.ts +1 -1
  98. package/src/provider/models-snapshot.ts +2 -0
  99. package/src/provider/models.ts +1 -1
  100. package/src/provider/provider.ts +2 -2
  101. package/src/provider/transform.ts +2 -2
  102. package/src/pty/index.ts +5 -5
  103. package/src/question/index.ts +5 -5
  104. package/src/server/event.ts +1 -1
  105. package/src/server/mdns.ts +1 -1
  106. package/src/server/routes/global.ts +3 -3
  107. package/src/server/routes/permission.ts +1 -1
  108. package/src/server/routes/pty.ts +1 -1
  109. package/src/server/routes/session.ts +4 -4
  110. package/src/server/routes/tui.ts +1 -1
  111. package/src/server/server.ts +3 -3
  112. package/src/session/compaction.ts +7 -7
  113. package/src/session/index.ts +10 -10
  114. package/src/session/instruction.ts +1 -1
  115. package/src/session/llm.ts +11 -11
  116. package/src/session/message-v2.ts +10 -10
  117. package/src/session/message.ts +1 -1
  118. package/src/session/processor.ts +10 -10
  119. package/src/session/prompt.ts +8 -8
  120. package/src/session/retry.ts +2 -2
  121. package/src/session/revert.ts +1 -1
  122. package/src/session/session.sql.ts +3 -3
  123. package/src/session/status.ts +3 -3
  124. package/src/session/summary.ts +5 -5
  125. package/src/session/system.ts +1 -1
  126. package/src/session/todo.ts +2 -2
  127. package/src/share/share-next.ts +7 -7
  128. package/src/share/share.sql.ts +1 -1
  129. package/src/shell/shell.ts +3 -3
  130. package/src/skill/skill.ts +6 -6
  131. package/src/storage/db.ts +1 -1
  132. package/src/storage/storage.ts +1 -1
  133. package/src/tool/bash.ts +6 -6
  134. package/src/tool/edit.ts +1 -1
  135. package/src/tool/registry.ts +2 -2
  136. package/src/tool/skill.ts +1 -1
  137. package/src/tool/task.ts +3 -3
  138. package/src/util/array.ts +10 -0
  139. package/src/util/binary.ts +41 -0
  140. package/src/util/encode.ts +51 -0
  141. package/src/util/error.ts +54 -0
  142. package/src/util/identifier.ts +48 -0
  143. package/src/util/lazy.ts +4 -16
  144. package/src/util/path.ts +37 -0
  145. package/src/util/retry.ts +41 -0
  146. package/src/util/slug.ts +74 -0
  147. package/src/worktree/index.ts +3 -3
  148. package/AGENTS.md +0 -10
  149. package/BUN_SHELL_MIGRATION_PLAN.md +0 -136
  150. package/Dockerfile +0 -18
  151. package/README.md +0 -15
  152. package/bunfig.toml +0 -7
  153. package/drizzle.config.ts +0 -10
  154. package/package.json.bak +0 -140
  155. package/script/build.ts +0 -224
  156. package/script/check-migrations.ts +0 -16
  157. package/script/postinstall.mjs +0 -131
  158. package/script/publish.ts +0 -181
  159. package/script/schema.ts +0 -63
  160. package/script/seed-e2e.ts +0 -50
  161. package/sst-env.d.ts +0 -10
  162. package/test/AGENTS.md +0 -81
  163. package/test/acp/agent-interface.test.ts +0 -51
  164. package/test/acp/event-subscription.test.ts +0 -683
  165. package/test/agent/agent.test.ts +0 -689
  166. package/test/bun.test.ts +0 -53
  167. package/test/cli/github-action.test.ts +0 -197
  168. package/test/cli/github-remote.test.ts +0 -80
  169. package/test/cli/import.test.ts +0 -38
  170. package/test/cli/plugin-auth-picker.test.ts +0 -120
  171. package/test/cli/tui/transcript.test.ts +0 -322
  172. package/test/config/agent-color.test.ts +0 -71
  173. package/test/config/config.test.ts +0 -1886
  174. package/test/config/fixtures/empty-frontmatter.md +0 -4
  175. package/test/config/fixtures/frontmatter.md +0 -28
  176. package/test/config/fixtures/markdown-header.md +0 -11
  177. package/test/config/fixtures/no-frontmatter.md +0 -1
  178. package/test/config/fixtures/weird-model-id.md +0 -13
  179. package/test/config/markdown.test.ts +0 -228
  180. package/test/config/tui.test.ts +0 -510
  181. package/test/control-plane/session-proxy-middleware.test.ts +0 -147
  182. package/test/control-plane/sse.test.ts +0 -56
  183. package/test/control-plane/workspace-server-sse.test.ts +0 -65
  184. package/test/control-plane/workspace-sync.test.ts +0 -97
  185. package/test/file/ignore.test.ts +0 -10
  186. package/test/file/index.test.ts +0 -394
  187. package/test/file/path-traversal.test.ts +0 -198
  188. package/test/file/ripgrep.test.ts +0 -39
  189. package/test/file/time.test.ts +0 -361
  190. package/test/fixture/db.ts +0 -11
  191. package/test/fixture/fixture.ts +0 -45
  192. package/test/fixture/lsp/fake-lsp-server.js +0 -77
  193. package/test/fixture/skills/agents-sdk/SKILL.md +0 -152
  194. package/test/fixture/skills/agents-sdk/references/callable.md +0 -92
  195. package/test/fixture/skills/cloudflare/SKILL.md +0 -211
  196. package/test/fixture/skills/index.json +0 -6
  197. package/test/ide/ide.test.ts +0 -82
  198. package/test/keybind.test.ts +0 -421
  199. package/test/lsp/client.test.ts +0 -95
  200. package/test/mcp/headers.test.ts +0 -153
  201. package/test/mcp/oauth-browser.test.ts +0 -249
  202. package/test/memory/abort-leak.test.ts +0 -136
  203. package/test/patch/patch.test.ts +0 -348
  204. package/test/permission/arity.test.ts +0 -33
  205. package/test/permission/next.test.ts +0 -689
  206. package/test/permission-task.test.ts +0 -319
  207. package/test/plugin/auth-override.test.ts +0 -44
  208. package/test/plugin/codex.test.ts +0 -123
  209. package/test/preload.ts +0 -80
  210. package/test/project/project.test.ts +0 -348
  211. package/test/project/worktree-remove.test.ts +0 -65
  212. package/test/provider/amazon-bedrock.test.ts +0 -446
  213. package/test/provider/copilot/convert-to-copilot-messages.test.ts +0 -523
  214. package/test/provider/copilot/copilot-chat-model.test.ts +0 -592
  215. package/test/provider/gitlab-duo.test.ts +0 -262
  216. package/test/provider/provider.test.ts +0 -2220
  217. package/test/provider/transform.test.ts +0 -2353
  218. package/test/pty/pty-output-isolation.test.ts +0 -140
  219. package/test/question/question.test.ts +0 -300
  220. package/test/scheduler.test.ts +0 -73
  221. package/test/server/global-session-list.test.ts +0 -89
  222. package/test/server/session-list.test.ts +0 -90
  223. package/test/server/session-select.test.ts +0 -78
  224. package/test/session/compaction.test.ts +0 -423
  225. package/test/session/instruction.test.ts +0 -170
  226. package/test/session/llm.test.ts +0 -667
  227. package/test/session/message-v2.test.ts +0 -924
  228. package/test/session/prompt.test.ts +0 -211
  229. package/test/session/retry.test.ts +0 -188
  230. package/test/session/revert-compact.test.ts +0 -285
  231. package/test/session/session.test.ts +0 -71
  232. package/test/session/structured-output-integration.test.ts +0 -233
  233. package/test/session/structured-output.test.ts +0 -385
  234. package/test/skill/discovery.test.ts +0 -110
  235. package/test/skill/skill.test.ts +0 -388
  236. package/test/snapshot/snapshot.test.ts +0 -1180
  237. package/test/storage/json-migration.test.ts +0 -846
  238. package/test/tool/__snapshots__/tool.test.ts.snap +0 -9
  239. package/test/tool/apply_patch.test.ts +0 -566
  240. package/test/tool/bash.test.ts +0 -402
  241. package/test/tool/edit.test.ts +0 -496
  242. package/test/tool/external-directory.test.ts +0 -127
  243. package/test/tool/fixtures/large-image.png +0 -0
  244. package/test/tool/fixtures/models-api.json +0 -38413
  245. package/test/tool/grep.test.ts +0 -110
  246. package/test/tool/question.test.ts +0 -107
  247. package/test/tool/read.test.ts +0 -504
  248. package/test/tool/registry.test.ts +0 -122
  249. package/test/tool/skill.test.ts +0 -112
  250. package/test/tool/truncation.test.ts +0 -160
  251. package/test/tool/webfetch.test.ts +0 -100
  252. package/test/tool/write.test.ts +0 -348
  253. package/test/util/filesystem.test.ts +0 -443
  254. package/test/util/format.test.ts +0 -59
  255. package/test/util/glob.test.ts +0 -164
  256. package/test/util/iife.test.ts +0 -36
  257. package/test/util/lazy.test.ts +0 -50
  258. package/test/util/lock.test.ts +0 -72
  259. package/test/util/process.test.ts +0 -59
  260. package/test/util/timeout.test.ts +0 -21
  261. package/test/util/wildcard.test.ts +0 -90
  262. package/tsconfig.json +0 -16
@@ -1,523 +0,0 @@
1
- import { convertToOpenAICompatibleChatMessages as convertToCopilotMessages } from "@/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages"
2
- import { describe, test, expect } from "bun:test"
3
-
4
- describe("system messages", () => {
5
- test("should convert system message content to string", () => {
6
- const result = convertToCopilotMessages([
7
- {
8
- role: "system",
9
- content: "You are a helpful assistant with AGENTS.md instructions.",
10
- },
11
- ])
12
-
13
- expect(result).toEqual([
14
- {
15
- role: "system",
16
- content: "You are a helpful assistant with AGENTS.md instructions.",
17
- },
18
- ])
19
- })
20
- })
21
-
22
- describe("user messages", () => {
23
- test("should convert messages with only a text part to a string content", () => {
24
- const result = convertToCopilotMessages([
25
- {
26
- role: "user",
27
- content: [{ type: "text", text: "Hello" }],
28
- },
29
- ])
30
-
31
- expect(result).toEqual([{ role: "user", content: "Hello" }])
32
- })
33
-
34
- test("should convert messages with image parts", () => {
35
- const result = convertToCopilotMessages([
36
- {
37
- role: "user",
38
- content: [
39
- { type: "text", text: "Hello" },
40
- {
41
- type: "file",
42
- data: Buffer.from([0, 1, 2, 3]).toString("base64"),
43
- mediaType: "image/png",
44
- },
45
- ],
46
- },
47
- ])
48
-
49
- expect(result).toEqual([
50
- {
51
- role: "user",
52
- content: [
53
- { type: "text", text: "Hello" },
54
- {
55
- type: "image_url",
56
- image_url: { url: "data:image/png;base64,AAECAw==" },
57
- },
58
- ],
59
- },
60
- ])
61
- })
62
-
63
- test("should convert messages with image parts from Uint8Array", () => {
64
- const result = convertToCopilotMessages([
65
- {
66
- role: "user",
67
- content: [
68
- { type: "text", text: "Hi" },
69
- {
70
- type: "file",
71
- data: new Uint8Array([0, 1, 2, 3]),
72
- mediaType: "image/png",
73
- },
74
- ],
75
- },
76
- ])
77
-
78
- expect(result).toEqual([
79
- {
80
- role: "user",
81
- content: [
82
- { type: "text", text: "Hi" },
83
- {
84
- type: "image_url",
85
- image_url: { url: "data:image/png;base64,AAECAw==" },
86
- },
87
- ],
88
- },
89
- ])
90
- })
91
-
92
- test("should handle URL-based images", () => {
93
- const result = convertToCopilotMessages([
94
- {
95
- role: "user",
96
- content: [
97
- {
98
- type: "file",
99
- data: new URL("https://example.com/image.jpg"),
100
- mediaType: "image/*",
101
- },
102
- ],
103
- },
104
- ])
105
-
106
- expect(result).toEqual([
107
- {
108
- role: "user",
109
- content: [
110
- {
111
- type: "image_url",
112
- image_url: { url: "https://example.com/image.jpg" },
113
- },
114
- ],
115
- },
116
- ])
117
- })
118
-
119
- test("should handle multiple text parts without flattening", () => {
120
- const result = convertToCopilotMessages([
121
- {
122
- role: "user",
123
- content: [
124
- { type: "text", text: "Part 1" },
125
- { type: "text", text: "Part 2" },
126
- ],
127
- },
128
- ])
129
-
130
- expect(result).toEqual([
131
- {
132
- role: "user",
133
- content: [
134
- { type: "text", text: "Part 1" },
135
- { type: "text", text: "Part 2" },
136
- ],
137
- },
138
- ])
139
- })
140
- })
141
-
142
- describe("assistant messages", () => {
143
- test("should convert assistant text messages", () => {
144
- const result = convertToCopilotMessages([
145
- {
146
- role: "assistant",
147
- content: [{ type: "text", text: "Hello back!" }],
148
- },
149
- ])
150
-
151
- expect(result).toEqual([
152
- {
153
- role: "assistant",
154
- content: "Hello back!",
155
- tool_calls: undefined,
156
- reasoning_text: undefined,
157
- reasoning_opaque: undefined,
158
- },
159
- ])
160
- })
161
-
162
- test("should handle assistant message with null content when only tool calls", () => {
163
- const result = convertToCopilotMessages([
164
- {
165
- role: "assistant",
166
- content: [
167
- {
168
- type: "tool-call",
169
- toolCallId: "call1",
170
- toolName: "calculator",
171
- input: { a: 1, b: 2 },
172
- },
173
- ],
174
- },
175
- ])
176
-
177
- expect(result).toEqual([
178
- {
179
- role: "assistant",
180
- content: null,
181
- tool_calls: [
182
- {
183
- id: "call1",
184
- type: "function",
185
- function: {
186
- name: "calculator",
187
- arguments: JSON.stringify({ a: 1, b: 2 }),
188
- },
189
- },
190
- ],
191
- reasoning_text: undefined,
192
- reasoning_opaque: undefined,
193
- },
194
- ])
195
- })
196
-
197
- test("should concatenate multiple text parts", () => {
198
- const result = convertToCopilotMessages([
199
- {
200
- role: "assistant",
201
- content: [
202
- { type: "text", text: "First part. " },
203
- { type: "text", text: "Second part." },
204
- ],
205
- },
206
- ])
207
-
208
- expect(result[0].content).toBe("First part. Second part.")
209
- })
210
- })
211
-
212
- describe("tool calls", () => {
213
- test("should stringify arguments to tool calls", () => {
214
- const result = convertToCopilotMessages([
215
- {
216
- role: "assistant",
217
- content: [
218
- {
219
- type: "tool-call",
220
- input: { foo: "bar123" },
221
- toolCallId: "quux",
222
- toolName: "thwomp",
223
- },
224
- ],
225
- },
226
- {
227
- role: "tool",
228
- content: [
229
- {
230
- type: "tool-result",
231
- toolCallId: "quux",
232
- toolName: "thwomp",
233
- output: { type: "json", value: { oof: "321rab" } },
234
- },
235
- ],
236
- },
237
- ])
238
-
239
- expect(result).toEqual([
240
- {
241
- role: "assistant",
242
- content: null,
243
- tool_calls: [
244
- {
245
- id: "quux",
246
- type: "function",
247
- function: {
248
- name: "thwomp",
249
- arguments: JSON.stringify({ foo: "bar123" }),
250
- },
251
- },
252
- ],
253
- reasoning_text: undefined,
254
- reasoning_opaque: undefined,
255
- },
256
- {
257
- role: "tool",
258
- tool_call_id: "quux",
259
- content: JSON.stringify({ oof: "321rab" }),
260
- },
261
- ])
262
- })
263
-
264
- test("should handle text output type in tool results", () => {
265
- const result = convertToCopilotMessages([
266
- {
267
- role: "tool",
268
- content: [
269
- {
270
- type: "tool-result",
271
- toolCallId: "call-1",
272
- toolName: "getWeather",
273
- output: { type: "text", value: "It is sunny today" },
274
- },
275
- ],
276
- },
277
- ])
278
-
279
- expect(result).toEqual([
280
- {
281
- role: "tool",
282
- tool_call_id: "call-1",
283
- content: "It is sunny today",
284
- },
285
- ])
286
- })
287
-
288
- test("should handle multiple tool results as separate messages", () => {
289
- const result = convertToCopilotMessages([
290
- {
291
- role: "tool",
292
- content: [
293
- {
294
- type: "tool-result",
295
- toolCallId: "call1",
296
- toolName: "api1",
297
- output: { type: "text", value: "Result 1" },
298
- },
299
- {
300
- type: "tool-result",
301
- toolCallId: "call2",
302
- toolName: "api2",
303
- output: { type: "text", value: "Result 2" },
304
- },
305
- ],
306
- },
307
- ])
308
-
309
- expect(result).toHaveLength(2)
310
- expect(result[0]).toEqual({
311
- role: "tool",
312
- tool_call_id: "call1",
313
- content: "Result 1",
314
- })
315
- expect(result[1]).toEqual({
316
- role: "tool",
317
- tool_call_id: "call2",
318
- content: "Result 2",
319
- })
320
- })
321
-
322
- test("should handle text plus multiple tool calls", () => {
323
- const result = convertToCopilotMessages([
324
- {
325
- role: "assistant",
326
- content: [
327
- { type: "text", text: "Checking... " },
328
- {
329
- type: "tool-call",
330
- toolCallId: "call1",
331
- toolName: "searchTool",
332
- input: { query: "Weather" },
333
- },
334
- { type: "text", text: "Almost there..." },
335
- {
336
- type: "tool-call",
337
- toolCallId: "call2",
338
- toolName: "mapsTool",
339
- input: { location: "Paris" },
340
- },
341
- ],
342
- },
343
- ])
344
-
345
- expect(result).toEqual([
346
- {
347
- role: "assistant",
348
- content: "Checking... Almost there...",
349
- tool_calls: [
350
- {
351
- id: "call1",
352
- type: "function",
353
- function: {
354
- name: "searchTool",
355
- arguments: JSON.stringify({ query: "Weather" }),
356
- },
357
- },
358
- {
359
- id: "call2",
360
- type: "function",
361
- function: {
362
- name: "mapsTool",
363
- arguments: JSON.stringify({ location: "Paris" }),
364
- },
365
- },
366
- ],
367
- reasoning_text: undefined,
368
- reasoning_opaque: undefined,
369
- },
370
- ])
371
- })
372
- })
373
-
374
- describe("reasoning (copilot-specific)", () => {
375
- test("should omit reasoning_text without reasoning_opaque", () => {
376
- const result = convertToCopilotMessages([
377
- {
378
- role: "assistant",
379
- content: [
380
- { type: "reasoning", text: "Let me think about this..." },
381
- { type: "text", text: "The answer is 42." },
382
- ],
383
- },
384
- ])
385
-
386
- expect(result).toEqual([
387
- {
388
- role: "assistant",
389
- content: "The answer is 42.",
390
- tool_calls: undefined,
391
- reasoning_text: undefined,
392
- reasoning_opaque: undefined,
393
- },
394
- ])
395
- })
396
-
397
- test("should include reasoning_opaque from providerOptions", () => {
398
- const result = convertToCopilotMessages([
399
- {
400
- role: "assistant",
401
- content: [
402
- {
403
- type: "reasoning",
404
- text: "Thinking...",
405
- providerOptions: {
406
- copilot: { reasoningOpaque: "opaque-signature-123" },
407
- },
408
- },
409
- { type: "text", text: "Done!" },
410
- ],
411
- },
412
- ])
413
-
414
- expect(result).toEqual([
415
- {
416
- role: "assistant",
417
- content: "Done!",
418
- tool_calls: undefined,
419
- reasoning_text: "Thinking...",
420
- reasoning_opaque: "opaque-signature-123",
421
- },
422
- ])
423
- })
424
-
425
- test("should include reasoning_opaque from text part providerOptions", () => {
426
- const result = convertToCopilotMessages([
427
- {
428
- role: "assistant",
429
- content: [
430
- {
431
- type: "text",
432
- text: "Done!",
433
- providerOptions: {
434
- copilot: { reasoningOpaque: "opaque-text-456" },
435
- },
436
- },
437
- ],
438
- },
439
- ])
440
-
441
- expect(result).toEqual([
442
- {
443
- role: "assistant",
444
- content: "Done!",
445
- tool_calls: undefined,
446
- reasoning_text: undefined,
447
- reasoning_opaque: "opaque-text-456",
448
- },
449
- ])
450
- })
451
-
452
- test("should handle reasoning-only assistant message", () => {
453
- const result = convertToCopilotMessages([
454
- {
455
- role: "assistant",
456
- content: [
457
- {
458
- type: "reasoning",
459
- text: "Just thinking, no response yet",
460
- providerOptions: {
461
- copilot: { reasoningOpaque: "sig-abc" },
462
- },
463
- },
464
- ],
465
- },
466
- ])
467
-
468
- expect(result).toEqual([
469
- {
470
- role: "assistant",
471
- content: null,
472
- tool_calls: undefined,
473
- reasoning_text: "Just thinking, no response yet",
474
- reasoning_opaque: "sig-abc",
475
- },
476
- ])
477
- })
478
- })
479
-
480
- describe("full conversation", () => {
481
- test("should convert a multi-turn conversation with reasoning", () => {
482
- const result = convertToCopilotMessages([
483
- {
484
- role: "system",
485
- content: "You are a helpful assistant.",
486
- },
487
- {
488
- role: "user",
489
- content: [{ type: "text", text: "What is 2+2?" }],
490
- },
491
- {
492
- role: "assistant",
493
- content: [
494
- {
495
- type: "reasoning",
496
- text: "Let me calculate 2+2...",
497
- providerOptions: {
498
- copilot: { reasoningOpaque: "sig-abc" },
499
- },
500
- },
501
- { type: "text", text: "2+2 equals 4." },
502
- ],
503
- },
504
- {
505
- role: "user",
506
- content: [{ type: "text", text: "What about 3+3?" }],
507
- },
508
- ])
509
-
510
- expect(result).toHaveLength(4)
511
-
512
- const systemMsg = result[0]
513
- expect(systemMsg.role).toBe("system")
514
-
515
- // Assistant message should have reasoning fields
516
- const assistantMsg = result[2] as {
517
- reasoning_text?: string
518
- reasoning_opaque?: string
519
- }
520
- expect(assistantMsg.reasoning_text).toBe("Let me calculate 2+2...")
521
- expect(assistantMsg.reasoning_opaque).toBe("sig-abc")
522
- })
523
- })