@link-assistant/agent 0.0.8 → 0.0.11

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 (104) hide show
  1. package/EXAMPLES.md +80 -1
  2. package/MODELS.md +72 -24
  3. package/README.md +95 -2
  4. package/TOOLS.md +20 -0
  5. package/package.json +36 -2
  6. package/src/agent/agent.ts +68 -54
  7. package/src/auth/claude-oauth.ts +426 -0
  8. package/src/auth/index.ts +28 -26
  9. package/src/auth/plugins.ts +876 -0
  10. package/src/bun/index.ts +53 -43
  11. package/src/bus/global.ts +5 -5
  12. package/src/bus/index.ts +59 -53
  13. package/src/cli/bootstrap.js +12 -12
  14. package/src/cli/bootstrap.ts +6 -6
  15. package/src/cli/cmd/agent.ts +97 -92
  16. package/src/cli/cmd/auth.ts +468 -0
  17. package/src/cli/cmd/cmd.ts +2 -2
  18. package/src/cli/cmd/export.ts +41 -41
  19. package/src/cli/cmd/mcp.ts +210 -53
  20. package/src/cli/cmd/models.ts +30 -29
  21. package/src/cli/cmd/run.ts +269 -213
  22. package/src/cli/cmd/stats.ts +185 -146
  23. package/src/cli/error.ts +17 -13
  24. package/src/cli/ui.ts +78 -0
  25. package/src/command/index.ts +26 -26
  26. package/src/config/config.ts +528 -288
  27. package/src/config/markdown.ts +15 -15
  28. package/src/file/ripgrep.ts +201 -169
  29. package/src/file/time.ts +21 -18
  30. package/src/file/watcher.ts +51 -42
  31. package/src/file.ts +1 -1
  32. package/src/flag/flag.ts +26 -11
  33. package/src/format/formatter.ts +206 -162
  34. package/src/format/index.ts +61 -61
  35. package/src/global/index.ts +21 -21
  36. package/src/id/id.ts +47 -33
  37. package/src/index.js +554 -332
  38. package/src/json-standard/index.ts +173 -0
  39. package/src/mcp/index.ts +135 -128
  40. package/src/patch/index.ts +336 -267
  41. package/src/project/bootstrap.ts +15 -15
  42. package/src/project/instance.ts +43 -36
  43. package/src/project/project.ts +47 -47
  44. package/src/project/state.ts +37 -33
  45. package/src/provider/models-macro.ts +5 -5
  46. package/src/provider/models.ts +32 -32
  47. package/src/provider/opencode.js +19 -19
  48. package/src/provider/provider.ts +518 -277
  49. package/src/provider/transform.ts +143 -102
  50. package/src/server/project.ts +21 -21
  51. package/src/server/server.ts +111 -105
  52. package/src/session/agent.js +66 -60
  53. package/src/session/compaction.ts +136 -111
  54. package/src/session/index.ts +189 -156
  55. package/src/session/message-v2.ts +312 -268
  56. package/src/session/message.ts +73 -57
  57. package/src/session/processor.ts +180 -166
  58. package/src/session/prompt.ts +678 -533
  59. package/src/session/retry.ts +26 -23
  60. package/src/session/revert.ts +76 -62
  61. package/src/session/status.ts +26 -26
  62. package/src/session/summary.ts +97 -76
  63. package/src/session/system.ts +77 -63
  64. package/src/session/todo.ts +22 -16
  65. package/src/snapshot/index.ts +92 -76
  66. package/src/storage/storage.ts +157 -120
  67. package/src/tool/bash.ts +116 -106
  68. package/src/tool/batch.ts +73 -59
  69. package/src/tool/codesearch.ts +60 -53
  70. package/src/tool/edit.ts +319 -263
  71. package/src/tool/glob.ts +32 -28
  72. package/src/tool/grep.ts +72 -53
  73. package/src/tool/invalid.ts +7 -7
  74. package/src/tool/ls.ts +77 -64
  75. package/src/tool/multiedit.ts +30 -21
  76. package/src/tool/patch.ts +121 -94
  77. package/src/tool/read.ts +140 -122
  78. package/src/tool/registry.ts +38 -38
  79. package/src/tool/task.ts +93 -60
  80. package/src/tool/todo.ts +16 -16
  81. package/src/tool/tool.ts +45 -36
  82. package/src/tool/webfetch.ts +97 -74
  83. package/src/tool/websearch.ts +78 -64
  84. package/src/tool/write.ts +21 -15
  85. package/src/util/binary.ts +27 -19
  86. package/src/util/context.ts +8 -8
  87. package/src/util/defer.ts +7 -5
  88. package/src/util/error.ts +24 -19
  89. package/src/util/eventloop.ts +16 -10
  90. package/src/util/filesystem.ts +37 -33
  91. package/src/util/fn.ts +11 -8
  92. package/src/util/iife.ts +1 -1
  93. package/src/util/keybind.ts +44 -44
  94. package/src/util/lazy.ts +7 -7
  95. package/src/util/locale.ts +20 -16
  96. package/src/util/lock.ts +43 -38
  97. package/src/util/log.ts +95 -85
  98. package/src/util/queue.ts +8 -8
  99. package/src/util/rpc.ts +35 -23
  100. package/src/util/scrap.ts +4 -4
  101. package/src/util/signal.ts +5 -5
  102. package/src/util/timeout.ts +6 -6
  103. package/src/util/token.ts +2 -2
  104. package/src/util/wildcard.ts +38 -27
@@ -1,359 +1,415 @@
1
- import type { Argv } from "yargs"
2
- import path from "path"
3
- import { UI } from "../ui"
4
- import { cmd } from "./cmd"
5
- import { Flag } from "../../flag/flag"
6
- import { bootstrap } from "../bootstrap"
7
- import { Command } from "../../command"
8
- import { EOL } from "os"
9
- import { select } from "@clack/prompts"
10
- import { createOpencodeClient, type OpencodeClient } from "@opencode-ai/sdk"
11
- import { Provider } from "../../provider/provider"
1
+ import type { Argv } from 'yargs';
2
+ import path from 'path';
3
+ import { UI } from '../ui';
4
+ import { cmd } from './cmd';
5
+ import { Flag } from '../../flag/flag';
6
+ import { Log } from '../../util/log';
7
+ import { bootstrap } from '../bootstrap';
8
+ import { Command } from '../../command';
9
+ import { EOL } from 'os';
10
+ import { select } from '@clack/prompts';
11
+ import { createOpencodeClient, type OpencodeClient } from '@opencode-ai/sdk';
12
+ import { Provider } from '../../provider/provider';
12
13
 
13
14
  const TOOL: Record<string, [string, string]> = {
14
- todowrite: ["Todo", UI.Style.TEXT_WARNING_BOLD],
15
- todoread: ["Todo", UI.Style.TEXT_WARNING_BOLD],
16
- bash: ["Bash", UI.Style.TEXT_DANGER_BOLD],
17
- edit: ["Edit", UI.Style.TEXT_SUCCESS_BOLD],
18
- glob: ["Glob", UI.Style.TEXT_INFO_BOLD],
19
- grep: ["Grep", UI.Style.TEXT_INFO_BOLD],
20
- list: ["List", UI.Style.TEXT_INFO_BOLD],
21
- read: ["Read", UI.Style.TEXT_HIGHLIGHT_BOLD],
22
- write: ["Write", UI.Style.TEXT_SUCCESS_BOLD],
23
- websearch: ["Search", UI.Style.TEXT_DIM_BOLD],
24
- }
15
+ todowrite: ['Todo', UI.Style.TEXT_WARNING_BOLD],
16
+ todoread: ['Todo', UI.Style.TEXT_WARNING_BOLD],
17
+ bash: ['Bash', UI.Style.TEXT_DANGER_BOLD],
18
+ edit: ['Edit', UI.Style.TEXT_SUCCESS_BOLD],
19
+ glob: ['Glob', UI.Style.TEXT_INFO_BOLD],
20
+ grep: ['Grep', UI.Style.TEXT_INFO_BOLD],
21
+ list: ['List', UI.Style.TEXT_INFO_BOLD],
22
+ read: ['Read', UI.Style.TEXT_HIGHLIGHT_BOLD],
23
+ write: ['Write', UI.Style.TEXT_SUCCESS_BOLD],
24
+ websearch: ['Search', UI.Style.TEXT_DIM_BOLD],
25
+ };
25
26
 
26
27
  export const RunCommand = cmd({
27
- command: "run [message..]",
28
- describe: "run opencode with a message",
28
+ command: 'run [message..]',
29
+ describe: 'run opencode with a message',
29
30
  builder: (yargs: Argv) => {
30
31
  return yargs
31
- .positional("message", {
32
- describe: "message to send",
33
- type: "string",
32
+ .positional('message', {
33
+ describe: 'message to send',
34
+ type: 'string',
34
35
  array: true,
35
36
  default: [],
36
37
  })
37
- .option("command", {
38
- describe: "the command to run, use message for args",
39
- type: "string",
38
+ .option('command', {
39
+ describe: 'the command to run, use message for args',
40
+ type: 'string',
40
41
  })
41
- .option("continue", {
42
- alias: ["c"],
43
- describe: "continue the last session",
44
- type: "boolean",
42
+ .option('continue', {
43
+ alias: ['c'],
44
+ describe: 'continue the last session',
45
+ type: 'boolean',
45
46
  })
46
- .option("session", {
47
- alias: ["s"],
48
- describe: "session id to continue",
49
- type: "string",
47
+ .option('session', {
48
+ alias: ['s'],
49
+ describe: 'session id to continue',
50
+ type: 'string',
50
51
  })
51
- .option("model", {
52
- type: "string",
53
- alias: ["m"],
54
- describe: "model to use in the format of provider/model",
52
+ .option('model', {
53
+ type: 'string',
54
+ alias: ['m'],
55
+ describe: 'model to use in the format of provider/model',
55
56
  })
56
- .option("agent", {
57
- type: "string",
58
- describe: "agent to use",
57
+ .option('agent', {
58
+ type: 'string',
59
+ describe: 'agent to use',
59
60
  })
60
- .option("format", {
61
- type: "string",
62
- choices: ["default", "json"],
63
- default: "default",
64
- describe: "format: default (formatted) or json (raw JSON events)",
61
+ .option('format', {
62
+ type: 'string',
63
+ choices: ['default', 'json'],
64
+ default: 'default',
65
+ describe: 'format: default (formatted) or json (raw JSON events)',
65
66
  })
66
- .option("file", {
67
- alias: ["f"],
68
- type: "string",
67
+ .option('file', {
68
+ alias: ['f'],
69
+ type: 'string',
69
70
  array: true,
70
- describe: "file(s) to attach to message",
71
+ describe: 'file(s) to attach to message',
71
72
  })
72
- .option("title", {
73
- type: "string",
74
- describe: "title for the session (uses truncated prompt if no value provided)",
73
+ .option('title', {
74
+ type: 'string',
75
+ describe:
76
+ 'title for the session (uses truncated prompt if no value provided)',
75
77
  })
76
- .option("attach", {
77
- type: "string",
78
- describe: "attach to a running opencode server (e.g., http://localhost:4096)",
78
+ .option('attach', {
79
+ type: 'string',
80
+ describe:
81
+ 'attach to a running opencode server (e.g., http://localhost:4096)',
79
82
  })
80
- .option("port", {
81
- type: "number",
82
- describe: "port for the local server (defaults to random port if no value provided)",
83
- })
84
- .option("system-message", {
85
- type: "string",
86
- describe: "full override of the system message",
87
- })
88
- .option("system-message-file", {
89
- type: "string",
90
- describe: "full override of the system message from file",
91
- })
92
- .option("append-system-message", {
93
- type: "string",
94
- describe: "append to the default system message",
95
- })
96
- .option("append-system-message-file", {
97
- type: "string",
98
- describe: "append to the default system message from file",
99
- })
83
+ .option('port', {
84
+ type: 'number',
85
+ describe:
86
+ 'port for the local server (defaults to random port if no value provided)',
87
+ })
88
+ .option('system-message', {
89
+ type: 'string',
90
+ describe: 'full override of the system message',
91
+ })
92
+ .option('system-message-file', {
93
+ type: 'string',
94
+ describe: 'full override of the system message from file',
95
+ })
96
+ .option('append-system-message', {
97
+ type: 'string',
98
+ describe: 'append to the default system message',
99
+ })
100
+ .option('append-system-message-file', {
101
+ type: 'string',
102
+ describe: 'append to the default system message from file',
103
+ })
104
+ .option('verbose', {
105
+ type: 'boolean',
106
+ describe:
107
+ 'enable verbose mode to debug API requests (shows system prompt, token counts, etc.)',
108
+ default: false,
109
+ });
100
110
  },
101
- handler: async (args) => {
102
- let message = args.message.join(" ")
111
+ handler: async (args) => {
112
+ // Set verbose mode if requested
113
+ if (args.verbose) {
114
+ Flag.setVerbose(true);
115
+ await Log.init({ print: true, level: 'DEBUG' });
116
+ }
117
+ let message = args.message.join(' ');
103
118
 
104
- const fileParts: any[] = []
119
+ const fileParts: any[] = [];
105
120
  if (args.file) {
106
- const files = Array.isArray(args.file) ? args.file : [args.file]
121
+ const files = Array.isArray(args.file) ? args.file : [args.file];
107
122
 
108
123
  for (const filePath of files) {
109
- const resolvedPath = path.resolve(process.cwd(), filePath)
110
- const file = Bun.file(resolvedPath)
111
- const stats = await file.stat().catch(() => {})
124
+ const resolvedPath = path.resolve(process.cwd(), filePath);
125
+ const file = Bun.file(resolvedPath);
126
+ const stats = await file.stat().catch(() => {});
112
127
  if (!stats) {
113
- UI.error(`File not found: ${filePath}`)
114
- process.exit(1)
128
+ UI.error(`File not found: ${filePath}`);
129
+ process.exit(1);
115
130
  }
116
131
  if (!(await file.exists())) {
117
- UI.error(`File not found: ${filePath}`)
118
- process.exit(1)
132
+ UI.error(`File not found: ${filePath}`);
133
+ process.exit(1);
119
134
  }
120
135
 
121
- const stat = await file.stat()
122
- const mime = stat.isDirectory() ? "application/x-directory" : "text/plain"
136
+ const stat = await file.stat();
137
+ const mime = stat.isDirectory()
138
+ ? 'application/x-directory'
139
+ : 'text/plain';
123
140
 
124
141
  fileParts.push({
125
- type: "file",
142
+ type: 'file',
126
143
  url: `file://${resolvedPath}`,
127
144
  filename: path.basename(resolvedPath),
128
145
  mime,
129
- })
146
+ });
130
147
  }
131
148
  }
132
149
 
133
150
  // Read system message files
134
- if (args["system-message-file"]) {
135
- const resolvedPath = path.resolve(process.cwd(), args["system-message-file"])
136
- const file = Bun.file(resolvedPath)
151
+ if (args['system-message-file']) {
152
+ const resolvedPath = path.resolve(
153
+ process.cwd(),
154
+ args['system-message-file']
155
+ );
156
+ const file = Bun.file(resolvedPath);
137
157
  if (!(await file.exists())) {
138
- UI.error(`System message file not found: ${args["system-message-file"]}`)
139
- process.exit(1)
158
+ UI.error(
159
+ `System message file not found: ${args['system-message-file']}`
160
+ );
161
+ process.exit(1);
140
162
  }
141
- args["system-message"] = await file.text()
163
+ args['system-message'] = await file.text();
142
164
  }
143
165
 
144
- if (args["append-system-message-file"]) {
145
- const resolvedPath = path.resolve(process.cwd(), args["append-system-message-file"])
146
- const file = Bun.file(resolvedPath)
166
+ if (args['append-system-message-file']) {
167
+ const resolvedPath = path.resolve(
168
+ process.cwd(),
169
+ args['append-system-message-file']
170
+ );
171
+ const file = Bun.file(resolvedPath);
147
172
  if (!(await file.exists())) {
148
- UI.error(`Append system message file not found: ${args["append-system-message-file"]}`)
149
- process.exit(1)
173
+ UI.error(
174
+ `Append system message file not found: ${args['append-system-message-file']}`
175
+ );
176
+ process.exit(1);
150
177
  }
151
- args["append-system-message"] = await file.text()
178
+ args['append-system-message'] = await file.text();
152
179
  }
153
180
 
154
- if (!process.stdin.isTTY) message += "\n" + (await Bun.stdin.text())
181
+ if (!process.stdin.isTTY) message += '\n' + (await Bun.stdin.text());
155
182
 
156
183
  if (message.trim().length === 0 && !args.command) {
157
- UI.error("You must provide a message or a command")
158
- process.exit(1)
184
+ UI.error('You must provide a message or a command');
185
+ process.exit(1);
159
186
  }
160
187
 
161
188
  const execute = async (sdk: OpencodeClient, sessionID: string) => {
162
189
  const printEvent = (color: string, type: string, title: string) => {
163
190
  UI.println(
164
191
  color + `|`,
165
- UI.Style.TEXT_NORMAL + UI.Style.TEXT_DIM + ` ${type.padEnd(7, " ")}`,
166
- "",
167
- UI.Style.TEXT_NORMAL + title,
168
- )
169
- }
192
+ UI.Style.TEXT_NORMAL + UI.Style.TEXT_DIM + ` ${type.padEnd(7, ' ')}`,
193
+ '',
194
+ UI.Style.TEXT_NORMAL + title
195
+ );
196
+ };
170
197
 
171
198
  const outputJsonEvent = (type: string, data: any) => {
172
- if (args.format === "json") {
173
- process.stdout.write(JSON.stringify({ type, timestamp: Date.now(), sessionID, ...data }) + EOL)
174
- return true
199
+ if (args.format === 'json') {
200
+ process.stdout.write(
201
+ JSON.stringify({
202
+ type,
203
+ timestamp: Date.now(),
204
+ sessionID,
205
+ ...data,
206
+ }) + EOL
207
+ );
208
+ return true;
175
209
  }
176
- return false
177
- }
210
+ return false;
211
+ };
178
212
 
179
- const events = await sdk.event.subscribe()
180
- let errorMsg: string | undefined
213
+ const events = await sdk.event.subscribe();
214
+ let errorMsg: string | undefined;
181
215
 
182
216
  const eventProcessor = (async () => {
183
217
  for await (const event of events.stream) {
184
- if (event.type === "message.part.updated") {
185
- const part = event.properties.part
186
- if (part.sessionID !== sessionID) continue
187
-
188
- if (part.type === "tool" && part.state.status === "completed") {
189
- if (outputJsonEvent("tool_use", { part })) continue
190
- const [tool, color] = TOOL[part.tool] ?? [part.tool, UI.Style.TEXT_INFO_BOLD]
218
+ if (event.type === 'message.part.updated') {
219
+ const part = event.properties.part;
220
+ if (part.sessionID !== sessionID) continue;
221
+
222
+ if (part.type === 'tool' && part.state.status === 'completed') {
223
+ if (outputJsonEvent('tool_use', { part })) continue;
224
+ const [tool, color] = TOOL[part.tool] ?? [
225
+ part.tool,
226
+ UI.Style.TEXT_INFO_BOLD,
227
+ ];
191
228
  const title =
192
229
  part.state.title ||
193
- (Object.keys(part.state.input).length > 0 ? JSON.stringify(part.state.input) : "Unknown")
194
- printEvent(color, tool, title)
195
- if (part.tool === "bash" && part.state.output?.trim()) {
196
- UI.println()
197
- UI.println(part.state.output)
230
+ (Object.keys(part.state.input).length > 0
231
+ ? JSON.stringify(part.state.input)
232
+ : 'Unknown');
233
+ printEvent(color, tool, title);
234
+ if (part.tool === 'bash' && part.state.output?.trim()) {
235
+ UI.println();
236
+ UI.println(part.state.output);
198
237
  }
199
238
  }
200
239
 
201
- if (part.type === "step-start") {
202
- if (outputJsonEvent("step_start", { part })) continue
240
+ if (part.type === 'step-start') {
241
+ if (outputJsonEvent('step_start', { part })) continue;
203
242
  }
204
243
 
205
- if (part.type === "step-finish") {
206
- if (outputJsonEvent("step_finish", { part })) continue
244
+ if (part.type === 'step-finish') {
245
+ if (outputJsonEvent('step_finish', { part })) continue;
207
246
  }
208
247
 
209
- if (part.type === "text" && part.time?.end) {
210
- if (outputJsonEvent("text", { part })) continue
211
- const isPiped = !process.stdout.isTTY
212
- if (!isPiped) UI.println()
213
- process.stdout.write((isPiped ? part.text : UI.markdown(part.text)) + EOL)
214
- if (!isPiped) UI.println()
248
+ if (part.type === 'text' && part.time?.end) {
249
+ if (outputJsonEvent('text', { part })) continue;
250
+ const isPiped = !process.stdout.isTTY;
251
+ if (!isPiped) UI.println();
252
+ process.stdout.write(
253
+ (isPiped ? part.text : UI.markdown(part.text)) + EOL
254
+ );
255
+ if (!isPiped) UI.println();
215
256
  }
216
257
  }
217
258
 
218
- if (event.type === "session.error") {
219
- const props = event.properties
220
- if (props.sessionID !== sessionID || !props.error) continue
221
- let err = String(props.error.name)
222
- if ("data" in props.error && props.error.data && "message" in props.error.data) {
223
- err = String(props.error.data.message)
259
+ if (event.type === 'session.error') {
260
+ const props = event.properties;
261
+ if (props.sessionID !== sessionID || !props.error) continue;
262
+ let err = String(props.error.name);
263
+ if (
264
+ 'data' in props.error &&
265
+ props.error.data &&
266
+ 'message' in props.error.data
267
+ ) {
268
+ err = String(props.error.data.message);
224
269
  }
225
- errorMsg = errorMsg ? errorMsg + EOL + err : err
226
- if (outputJsonEvent("error", { error: props.error })) continue
227
- UI.error(err)
270
+ errorMsg = errorMsg ? errorMsg + EOL + err : err;
271
+ if (outputJsonEvent('error', { error: props.error })) continue;
272
+ UI.error(err);
228
273
  }
229
274
 
230
- if (event.type === "session.idle" && event.properties.sessionID === sessionID) {
231
- break
275
+ if (
276
+ event.type === 'session.idle' &&
277
+ event.properties.sessionID === sessionID
278
+ ) {
279
+ break;
232
280
  }
233
281
 
234
- if (event.type === "permission.updated") {
235
- const permission = event.properties
236
- if (permission.sessionID !== sessionID) continue
282
+ if (event.type === 'permission.updated') {
283
+ const permission = event.properties;
284
+ if (permission.sessionID !== sessionID) continue;
237
285
  const result = await select({
238
286
  message: `Permission required to run: ${permission.title}`,
239
287
  options: [
240
- { value: "once", label: "Allow once" },
241
- { value: "always", label: "Always allow" },
242
- { value: "reject", label: "Reject" },
288
+ { value: 'once', label: 'Allow once' },
289
+ { value: 'always', label: 'Always allow' },
290
+ { value: 'reject', label: 'Reject' },
243
291
  ],
244
- initialValue: "once",
245
- }).catch(() => "reject")
246
- const response = (result.toString().includes("cancel") ? "reject" : result) as "once" | "always" | "reject"
292
+ initialValue: 'once',
293
+ }).catch(() => 'reject');
294
+ const response = (
295
+ result.toString().includes('cancel') ? 'reject' : result
296
+ ) as 'once' | 'always' | 'reject';
247
297
  await sdk.postSessionIdPermissionsPermissionId({
248
298
  path: { id: sessionID, permissionID: permission.id },
249
299
  body: { response },
250
- })
300
+ });
251
301
  }
252
302
  }
253
- })()
303
+ })();
254
304
 
255
305
  if (args.command) {
256
306
  await sdk.session.command({
257
307
  path: { id: sessionID },
258
308
  body: {
259
- agent: args.agent || "build",
309
+ agent: args.agent || 'build',
260
310
  model: args.model,
261
- system: args["system-message"],
262
- appendSystem: args["append-system-message"],
311
+ system: args['system-message'],
312
+ appendSystem: args['append-system-message'],
263
313
  command: args.command,
264
314
  arguments: message,
265
315
  },
266
- })
316
+ });
267
317
  } else {
268
- const modelParam = args.model ? Provider.parseModel(args.model) : undefined
318
+ const modelParam = args.model
319
+ ? Provider.parseModel(args.model)
320
+ : undefined;
269
321
  await sdk.session.prompt({
270
322
  path: { id: sessionID },
271
323
  body: {
272
- agent: args.agent || "build",
324
+ agent: args.agent || 'build',
273
325
  model: modelParam,
274
- system: args["system-message"],
275
- appendSystem: args["append-system-message"],
276
- parts: [...fileParts, { type: "text", text: message }],
326
+ system: args['system-message'],
327
+ appendSystem: args['append-system-message'],
328
+ parts: [...fileParts, { type: 'text', text: message }],
277
329
  },
278
- })
330
+ });
279
331
  }
280
332
 
281
- await eventProcessor
282
- if (errorMsg) process.exit(1)
283
- }
333
+ await eventProcessor;
334
+ if (errorMsg) process.exit(1);
335
+ };
284
336
 
285
337
  if (args.attach) {
286
- const sdk = createOpencodeClient({ baseUrl: args.attach })
338
+ const sdk = createOpencodeClient({ baseUrl: args.attach });
287
339
 
288
340
  const sessionID = await (async () => {
289
341
  if (args.continue) {
290
- const result = await sdk.session.list()
291
- return result.data?.find((s) => !s.parentID)?.id
342
+ const result = await sdk.session.list();
343
+ return result.data?.find((s) => !s.parentID)?.id;
292
344
  }
293
- if (args.session) return args.session
345
+ if (args.session) return args.session;
294
346
 
295
347
  const title =
296
348
  args.title !== undefined
297
- ? args.title === ""
298
- ? message.slice(0, 50) + (message.length > 50 ? "..." : "")
349
+ ? args.title === ''
350
+ ? message.slice(0, 50) + (message.length > 50 ? '...' : '')
299
351
  : args.title
300
- : undefined
352
+ : undefined;
301
353
 
302
- const result = await sdk.session.create({ body: title ? { title } : {} })
303
- return result.data?.id
304
- })()
354
+ const result = await sdk.session.create({
355
+ body: title ? { title } : {},
356
+ });
357
+ return result.data?.id;
358
+ })();
305
359
 
306
360
  if (!sessionID) {
307
- UI.error("Session not found")
308
- process.exit(1)
361
+ UI.error('Session not found');
362
+ process.exit(1);
309
363
  }
310
364
 
311
365
  // Share not supported - removed auto-share logic
312
366
 
313
- return await execute(sdk, sessionID)
367
+ return await execute(sdk, sessionID);
314
368
  }
315
369
 
316
370
  await bootstrap(process.cwd(), async () => {
317
371
  // Server not supported - this code path should not be reached
318
- throw new Error("Server mode not supported in agent-cli")
372
+ throw new Error('Server mode not supported in agent-cli');
319
373
 
320
374
  if (args.command) {
321
- const exists = await Command.get(args.command)
375
+ const exists = await Command.get(args.command);
322
376
  if (!exists) {
323
- server.stop()
324
- UI.error(`Command "${args.command}" not found`)
325
- process.exit(1)
377
+ server.stop();
378
+ UI.error(`Command "${args.command}" not found`);
379
+ process.exit(1);
326
380
  }
327
381
  }
328
382
 
329
383
  const sessionID = await (async () => {
330
384
  if (args.continue) {
331
- const result = await sdk.session.list()
332
- return result.data?.find((s) => !s.parentID)?.id
385
+ const result = await sdk.session.list();
386
+ return result.data?.find((s) => !s.parentID)?.id;
333
387
  }
334
- if (args.session) return args.session
388
+ if (args.session) return args.session;
335
389
 
336
390
  const title =
337
391
  args.title !== undefined
338
- ? args.title === ""
339
- ? message.slice(0, 50) + (message.length > 50 ? "..." : "")
392
+ ? args.title === ''
393
+ ? message.slice(0, 50) + (message.length > 50 ? '...' : '')
340
394
  : args.title
341
- : undefined
395
+ : undefined;
342
396
 
343
- const result = await sdk.session.create({ body: title ? { title } : {} })
344
- return result.data?.id
345
- })()
397
+ const result = await sdk.session.create({
398
+ body: title ? { title } : {},
399
+ });
400
+ return result.data?.id;
401
+ })();
346
402
 
347
403
  if (!sessionID) {
348
- server.stop()
349
- UI.error("Session not found")
350
- process.exit(1)
404
+ server.stop();
405
+ UI.error('Session not found');
406
+ process.exit(1);
351
407
  }
352
408
 
353
409
  // Share not supported - removed auto-share logic
354
410
 
355
- await execute(sdk, sessionID)
356
- server.stop()
357
- })
411
+ await execute(sdk, sessionID);
412
+ server.stop();
413
+ });
358
414
  },
359
- })
415
+ });