@link-assistant/agent 0.26.6 → 0.26.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/agent",
3
- "version": "0.26.6",
3
+ "version": "0.26.8",
4
4
  "description": "A minimal, public domain AI CLI agent compatible with OpenCode's JSON interface. Bun-only runtime.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -50,76 +50,77 @@
50
50
  "LICENSE"
51
51
  ],
52
52
  "dependencies": {
53
- "@agentclientprotocol/sdk": "^0.5.1",
54
- "@ai-sdk/amazon-bedrock": "^3.0.74",
55
- "@ai-sdk/anthropic": "^2.0.58",
56
- "@ai-sdk/azure": "^2.0.91",
57
- "@ai-sdk/google": "^2.0.52",
58
- "@ai-sdk/google-vertex": "^3.0.98",
59
- "@ai-sdk/groq": "^2.0.34",
60
- "@ai-sdk/mcp": "^0.0.8",
61
- "@ai-sdk/mistral": "^2.0.27",
62
- "@ai-sdk/openai": "^2.0.89",
63
- "@ai-sdk/openai-compatible": "^2.0.62",
64
- "@ai-sdk/xai": "^2.0.33",
65
- "@clack/prompts": "^0.11.0",
66
- "@hono/standard-validator": "^0.2.0",
67
- "@hono/zod-validator": "^0.7.5",
68
- "@modelcontextprotocol/sdk": "^1.22.0",
69
- "@octokit/graphql": "^9.0.3",
53
+ "@agentclientprotocol/sdk": "^1.5.1",
54
+ "@ai-sdk/amazon-bedrock": "^5.0.101",
55
+ "@ai-sdk/anthropic": "^4.0.68",
56
+ "@ai-sdk/azure": "^4.0.85",
57
+ "@ai-sdk/google": "^4.0.85",
58
+ "@ai-sdk/google-vertex": "^5.0.98",
59
+ "@ai-sdk/groq": "^4.0.52",
60
+ "@ai-sdk/mcp": "^2.0.62",
61
+ "@ai-sdk/mistral": "^4.0.54",
62
+ "@ai-sdk/openai": "^4.0.81",
63
+ "@ai-sdk/openai-compatible": "^3.0.59",
64
+ "@ai-sdk/provider": "^4.0.19",
65
+ "@ai-sdk/xai": "^5.0.12",
66
+ "@clack/prompts": "^1.8.1",
67
+ "@hono/standard-validator": "^0.4.0",
68
+ "@hono/zod-validator": "^0.9.1",
69
+ "@modelcontextprotocol/sdk": "^1.31.0",
70
+ "@octokit/graphql": "^9.0.5",
70
71
  "@octokit/rest": "^22.0.1",
71
72
  "@openauthjs/openauth": "^0.4.3",
72
- "@opencode-ai/sdk": "^1.0.78",
73
- "@openrouter/ai-sdk-provider": "^2.2.3",
74
- "@opentui/core": "0.1.107",
75
- "@opentui/solid": "0.1.107",
76
- "@parcel/watcher": "^2.5.1",
77
- "@solid-primitives/event-bus": "^1.1.2",
78
- "@standard-community/standard-json": "^0.3.5",
79
- "@standard-community/standard-openapi": "^0.2.9",
80
- "@zip.js/zip.js": "^2.8.10",
81
- "ai": "^6.0.235",
82
- "chokidar": "^4.0.3",
83
- "clipboardy": "^5.0.0",
84
- "command-stream": "^0.7.1",
73
+ "@opencode-ai/sdk": "^1.18.33",
74
+ "@openrouter/ai-sdk-provider": "^3.1.0",
75
+ "@opentui/core": "0.5.12",
76
+ "@opentui/solid": "0.5.12",
77
+ "@parcel/watcher": "^2.6.0",
78
+ "@solid-primitives/event-bus": "^1.1.4",
79
+ "@standard-community/standard-json": "^0.3.6",
80
+ "@standard-community/standard-openapi": "^0.2.10",
81
+ "@zip.js/zip.js": "^2.18.2",
82
+ "ai": "^7.0.122",
83
+ "chokidar": "^5.0.0",
84
+ "clipboardy": "^5.3.2",
85
+ "command-stream": "^1.3.0",
85
86
  "decimal.js": "^10.6.0",
86
- "diff": "^8.0.2",
87
- "fuzzysort": "^3.1.0",
88
- "glob": "^10.0.0",
89
- "gpt-tokenizer": "^3.4.0",
87
+ "diff": "^9.0.0",
88
+ "fuzzysort": "^4.0.2",
89
+ "glob": "^13.0.6",
90
+ "gpt-tokenizer": "^4.0.0",
90
91
  "gray-matter": "^4.0.3",
91
- "hono": "^4.10.6",
92
- "hono-openapi": "^1.1.1",
93
- "ignore": "^7.0.5",
92
+ "hono": "^4.13.11",
93
+ "hono-openapi": "^1.3.3",
94
+ "ignore": "^7.0.10",
94
95
  "jsonc-parser": "^3.3.1",
95
- "lino-arguments": "^0.2.5",
96
- "lino-objects-codec": "^0.1.1",
96
+ "lino-arguments": "^0.3.0",
97
+ "lino-objects-codec": "^0.8.0",
97
98
  "log-lazy": "^1.0.4",
98
- "minimatch": "^10.1.1",
99
- "remeda": "^2.32.0",
99
+ "minimatch": "^10.2.6",
100
+ "remeda": "^2.50.0",
100
101
  "solid-js": "1.9.12",
101
- "strip-ansi": "^7.1.2",
102
- "test-anywhere": "^0.7.0",
103
- "tree-sitter-bash": "^0.25.0",
104
- "turndown": "^7.2.2",
105
- "ulid": "^3.0.1",
106
- "vscode-jsonrpc": "^8.2.1",
107
- "vscode-languageserver-types": "^3.17.5",
108
- "web-tree-sitter": "^0.25.10",
102
+ "strip-ansi": "^7.2.0",
103
+ "test-anywhere": "^0.9.1",
104
+ "tree-sitter-bash": "^0.25.1",
105
+ "turndown": "^7.2.4",
106
+ "ulid": "^3.0.2",
107
+ "vscode-jsonrpc": "^9.0.3",
108
+ "vscode-languageserver-types": "^3.18.4",
109
+ "web-tree-sitter": "0.25.10",
109
110
  "xdg-basedir": "^5.1.0",
110
- "yargs": "^18.0.0",
111
- "zod": "^4.1.12"
111
+ "yargs": "^18.2.0",
112
+ "zod": "^4.6.5"
112
113
  },
113
114
  "devDependencies": {
114
- "@changesets/cli": "^2.29.7",
115
- "@eslint/js": "^9.18.0",
116
- "eslint": "^9.38.0",
115
+ "@changesets/cli": "^3.0.3",
116
+ "@eslint/js": "^10.0.1",
117
+ "eslint": "^10.11.0",
117
118
  "eslint-config-prettier": "^10.1.8",
118
- "eslint-plugin-prettier": "^5.5.4",
119
- "eslint-plugin-promise": "^7.2.1",
119
+ "eslint-plugin-prettier": "^5.5.6",
120
+ "eslint-plugin-promise": "^7.3.0",
120
121
  "husky": "^9.1.7",
121
- "lint-staged": "^16.2.6",
122
- "prettier": "^3.6.2"
122
+ "lint-staged": "^17.6.0",
123
+ "prettier": "^3.9.9"
123
124
  },
124
125
  "lint-staged": {
125
126
  "*.{js,mjs,cjs}": [
@@ -134,10 +135,15 @@
134
135
  },
135
136
  "license": "Unlicense",
136
137
  "allowScripts": {
137
- "@parcel/watcher@2.5.1": true,
138
- "tree-sitter-bash@0.25.1": true
138
+ "@parcel/watcher@2.6.0": true,
139
+ "tree-sitter-bash@0.25.1": true,
140
+ "node-pty@1.2.0-beta.15": true
139
141
  },
140
142
  "overrides": {
141
143
  "undici": "^7.16.0"
144
+ },
145
+ "dependencyPins": {
146
+ "solid-js": "https://github.com/anomalyco/opentui/issues/689",
147
+ "web-tree-sitter": "https://github.com/link-assistant/agent/issues/322"
142
148
  }
143
149
  }
@@ -138,10 +138,10 @@ export namespace Agent {
138
138
  const existing = await list();
139
139
  const result = await generateObject({
140
140
  temperature: 0.3,
141
- // The system prompt belongs in `system`, not in `prompt`: the AI SDK
141
+ // The system prompt belongs in `instructions`, not in `prompt`: the AI SDK
142
142
  // warns that a system message inside the prompt enables prompt
143
143
  // injection, and providers are free to treat it as ordinary content.
144
- system: system.map((content) => ({
144
+ instructions: system.map((content) => ({
145
145
  role: 'system' as const,
146
146
  content,
147
147
  })),
@@ -275,7 +275,8 @@ export function parseStreamJsonInput(input) {
275
275
  throw new Error(
276
276
  `Invalid stream-json input frame: ${
277
277
  error instanceof Error ? error.message : String(error)
278
- }`
278
+ }`,
279
+ { cause: error }
279
280
  );
280
281
  }
281
282
 
@@ -100,6 +100,10 @@ export async function parseModelConfig(
100
100
  }
101
101
  }
102
102
 
103
+ if (argv['dry-run'] && !cliModelArg && modelArg === defaultModel) {
104
+ modelArg = 'link-assistant/echo';
105
+ }
106
+
103
107
  // Attestation inputs (#295): record what was requested, and where it came
104
108
  // from, before resolution can rewrite the effective model. `argv.model` is
105
109
  // only treated as a request when it differs from the default, because yargs
@@ -15,7 +15,11 @@
15
15
  * @see https://github.com/link-foundation/lino-objects-codec
16
16
  */
17
17
 
18
- import type { LanguageModelV2, LanguageModelV2CallOptions } from 'ai';
18
+ import type {
19
+ LanguageModelV4,
20
+ LanguageModelV4CallOptions,
21
+ LanguageModelV4GenerateResult,
22
+ } from '@ai-sdk/provider';
19
23
  import { Log } from '../util/log';
20
24
  import { createEchoModel } from './echo';
21
25
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
@@ -33,7 +37,7 @@ const CACHE_ROOT = join(__dirname, '../../data/api-cache');
33
37
  * Generate a cache key from the prompt
34
38
  */
35
39
  function generateCacheKey(
36
- prompt: LanguageModelV2CallOptions['prompt']
40
+ prompt: LanguageModelV4CallOptions['prompt']
37
41
  ): string {
38
42
  // Simple hash of the prompt content
39
43
  const content = JSON.stringify(prompt);
@@ -64,14 +68,43 @@ function generatePartId(): string {
64
68
  /**
65
69
  * Load cached response from file using Links Notation format
66
70
  */
67
- function loadCachedResponse(filePath: string): any | null {
71
+ function loadCachedResponse(
72
+ filePath: string
73
+ ): LanguageModelV4GenerateResult | null {
68
74
  try {
69
75
  if (!existsSync(filePath)) {
70
76
  return null;
71
77
  }
72
78
  const content = readFileSync(filePath, 'utf8');
73
79
  // Decode from Links Notation format
74
- return decode({ notation: content });
80
+ const cached = decode({ notation: content });
81
+ // Existing .lino files may contain AI SDK 6 responses. Normalize their
82
+ // finish reason and usage so they remain usable by AI SDK 7.
83
+ if (typeof cached?.finishReason === 'string') {
84
+ const promptTokens = cached.usage?.promptTokens ?? 0;
85
+ const completionTokens = cached.usage?.completionTokens ?? 0;
86
+ return {
87
+ ...cached,
88
+ finishReason: {
89
+ unified: cached.finishReason,
90
+ raw: cached.finishReason,
91
+ },
92
+ usage: {
93
+ inputTokens: {
94
+ total: promptTokens,
95
+ noCache: promptTokens,
96
+ cacheRead: 0,
97
+ cacheWrite: 0,
98
+ },
99
+ outputTokens: {
100
+ total: completionTokens,
101
+ text: completionTokens,
102
+ reasoning: 0,
103
+ },
104
+ },
105
+ };
106
+ }
107
+ return cached;
75
108
  } catch (error: any) {
76
109
  log.warn('Failed to load cached response', {
77
110
  filePath,
@@ -104,21 +137,21 @@ function saveCachedResponse(filePath: string, response: any): void {
104
137
 
105
138
  /**
106
139
  * Creates a cache language model that stores/retrieves responses
107
- * Implements LanguageModelV2 interface for AI SDK 6.x compatibility
140
+ * Implements the AI SDK 7 language model interface.
108
141
  */
109
142
  export function createCacheModel(
110
143
  providerId: string,
111
144
  modelId: string
112
- ): LanguageModelV2 {
113
- const model: LanguageModelV2 = {
114
- specificationVersion: 'v2',
145
+ ): LanguageModelV4 {
146
+ const model: LanguageModelV4 = {
147
+ specificationVersion: 'v4',
115
148
  provider: 'link-assistant',
116
149
  modelId: `${providerId}/${modelId}`,
117
150
 
118
151
  // No external URLs are supported by this synthetic provider
119
152
  supportedUrls: {},
120
153
 
121
- async doGenerate(options: LanguageModelV2CallOptions) {
154
+ async doGenerate(options: LanguageModelV4CallOptions) {
122
155
  const cacheKey = generateCacheKey(options.prompt);
123
156
  const cachePath = getCachePath(providerId, modelId, cacheKey);
124
157
 
@@ -144,7 +177,7 @@ export function createCacheModel(
144
177
  return response;
145
178
  },
146
179
 
147
- async doStream(options: LanguageModelV2CallOptions) {
180
+ async doStream(options: LanguageModelV4CallOptions) {
148
181
  const cacheKey = generateCacheKey(options.prompt);
149
182
  const cachePath = getCachePath(providerId, modelId, cacheKey);
150
183
 
@@ -163,7 +196,7 @@ export function createCacheModel(
163
196
  cached.content?.[0]?.text || cached.text || 'Cached response';
164
197
  const textPartId = generatePartId();
165
198
 
166
- // Create a ReadableStream with LanguageModelV2StreamPart format
199
+ // Create a ReadableStream with LanguageModelV4StreamPart format.
167
200
  const stream = new ReadableStream({
168
201
  async start(controller) {
169
202
  // Emit text-start
@@ -195,10 +228,19 @@ export function createCacheModel(
195
228
  // Emit finish event
196
229
  controller.enqueue({
197
230
  type: 'finish',
198
- finishReason: 'stop',
231
+ finishReason: { unified: 'stop', raw: 'stop' },
199
232
  usage: cached.usage || {
200
- promptTokens: Math.ceil(echoText.length / 4),
201
- completionTokens: Math.ceil(echoText.length / 4),
233
+ inputTokens: {
234
+ total: Math.ceil(echoText.length / 4),
235
+ noCache: Math.ceil(echoText.length / 4),
236
+ cacheRead: 0,
237
+ cacheWrite: 0,
238
+ },
239
+ outputTokens: {
240
+ total: Math.ceil(echoText.length / 4),
241
+ text: Math.ceil(echoText.length / 4),
242
+ reasoning: 0,
243
+ },
202
244
  },
203
245
  providerMetadata: undefined,
204
246
  });
@@ -211,7 +253,6 @@ export function createCacheModel(
211
253
  stream,
212
254
  request: undefined,
213
255
  response: undefined,
214
- warnings: [],
215
256
  };
216
257
  }
217
258
 
@@ -237,7 +278,7 @@ export function createCacheModel(
237
278
  */
238
279
  export function createCacheProvider(options?: { name?: string }) {
239
280
  return {
240
- languageModel(modelId: string): LanguageModelV2 {
281
+ languageModel(modelId: string): LanguageModelV4 {
241
282
  // Parse provider/model from modelId like "opencode/grok-code"
242
283
  const parts = modelId.split('/');
243
284
  if (parts.length < 2) {
@@ -14,7 +14,10 @@
14
14
  * Input: "How are you?" -> Output: "How are you?"
15
15
  */
16
16
 
17
- import type { LanguageModelV2, LanguageModelV2CallOptions } from 'ai';
17
+ import type {
18
+ LanguageModelV4,
19
+ LanguageModelV4CallOptions,
20
+ } from '@ai-sdk/provider';
18
21
  import { Log } from '../util/log';
19
22
 
20
23
  const log = Log.create({ service: 'provider.echo' });
@@ -23,7 +26,7 @@ const log = Log.create({ service: 'provider.echo' });
23
26
  * Extract text content from the prompt messages
24
27
  */
25
28
  function extractTextFromPrompt(
26
- prompt: LanguageModelV2CallOptions['prompt']
29
+ prompt: LanguageModelV4CallOptions['prompt']
27
30
  ): string {
28
31
  const textParts: string[] = [];
29
32
 
@@ -52,18 +55,18 @@ function generatePartId(): string {
52
55
 
53
56
  /**
54
57
  * Creates an echo language model that echoes back the user's input
55
- * Implements LanguageModelV2 interface for AI SDK 6.x compatibility
58
+ * Implements the AI SDK 7 language model interface.
56
59
  */
57
- export function createEchoModel(modelId: string = 'echo'): LanguageModelV2 {
58
- const model: LanguageModelV2 = {
59
- specificationVersion: 'v2',
60
+ export function createEchoModel(modelId: string = 'echo'): LanguageModelV4 {
61
+ const model: LanguageModelV4 = {
62
+ specificationVersion: 'v4',
60
63
  provider: 'link-assistant',
61
64
  modelId,
62
65
 
63
66
  // No external URLs are supported by this synthetic provider
64
67
  supportedUrls: {},
65
68
 
66
- async doGenerate(options: LanguageModelV2CallOptions) {
69
+ async doGenerate(options: LanguageModelV4CallOptions) {
67
70
  const echoText = extractTextFromPrompt(options.prompt);
68
71
  log.info('echo generate', { modelId, echoText });
69
72
 
@@ -78,10 +81,19 @@ export function createEchoModel(modelId: string = 'echo'): LanguageModelV2 {
78
81
  text: echoText,
79
82
  },
80
83
  ],
81
- finishReason: 'stop' as const,
84
+ finishReason: { unified: 'stop' as const, raw: 'stop' },
82
85
  usage: {
83
- promptTokens,
84
- completionTokens,
86
+ inputTokens: {
87
+ total: promptTokens,
88
+ noCache: promptTokens,
89
+ cacheRead: 0,
90
+ cacheWrite: 0,
91
+ },
92
+ outputTokens: {
93
+ total: completionTokens,
94
+ text: completionTokens,
95
+ reasoning: 0,
96
+ },
85
97
  },
86
98
  warnings: [],
87
99
  providerMetadata: undefined,
@@ -90,7 +102,7 @@ export function createEchoModel(modelId: string = 'echo'): LanguageModelV2 {
90
102
  };
91
103
  },
92
104
 
93
- async doStream(options: LanguageModelV2CallOptions) {
105
+ async doStream(options: LanguageModelV4CallOptions) {
94
106
  const echoText = extractTextFromPrompt(options.prompt);
95
107
  log.info('echo stream', { modelId, echoText });
96
108
 
@@ -100,8 +112,7 @@ export function createEchoModel(modelId: string = 'echo'): LanguageModelV2 {
100
112
 
101
113
  const textPartId = generatePartId();
102
114
 
103
- // Create a ReadableStream with LanguageModelV2StreamPart format
104
- // V2 format uses: text-start -> text-delta (with delta) -> text-end -> finish
115
+ // Stream text-start -> text-delta -> text-end -> finish.
105
116
  const stream = new ReadableStream({
106
117
  async start(controller) {
107
118
  // Emit text-start
@@ -133,10 +144,19 @@ export function createEchoModel(modelId: string = 'echo'): LanguageModelV2 {
133
144
  // Emit finish event with usage information
134
145
  controller.enqueue({
135
146
  type: 'finish',
136
- finishReason: 'stop',
147
+ finishReason: { unified: 'stop', raw: 'stop' },
137
148
  usage: {
138
- promptTokens,
139
- completionTokens,
149
+ inputTokens: {
150
+ total: promptTokens,
151
+ noCache: promptTokens,
152
+ cacheRead: 0,
153
+ cacheWrite: 0,
154
+ },
155
+ outputTokens: {
156
+ total: completionTokens,
157
+ text: completionTokens,
158
+ reasoning: 0,
159
+ },
140
160
  },
141
161
  providerMetadata: undefined,
142
162
  });
@@ -149,7 +169,6 @@ export function createEchoModel(modelId: string = 'echo'): LanguageModelV2 {
149
169
  stream,
150
170
  request: undefined,
151
171
  response: undefined,
152
- warnings: [],
153
172
  };
154
173
  },
155
174
  };
@@ -162,7 +181,7 @@ export function createEchoModel(modelId: string = 'echo'): LanguageModelV2 {
162
181
  */
163
182
  export function createEchoProvider(options?: { name?: string }) {
164
183
  return {
165
- languageModel(modelId: string): LanguageModelV2 {
184
+ languageModel(modelId: string): LanguageModelV4 {
166
185
  return createEchoModel(modelId);
167
186
  },
168
187
  textEmbeddingModel() {
@@ -90,8 +90,7 @@ export namespace OpenCodeZen {
90
90
  }
91
91
 
92
92
  const body = (await response.json().catch(() => undefined)) as
93
- | { data?: Array<{ id?: unknown }> }
94
- | undefined;
93
+ { data?: Array<{ id?: unknown }> } | undefined;
95
94
  const rows = Array.isArray(body?.data) ? body.data : [];
96
95
  return new Set(
97
96
  rows
@@ -730,9 +730,9 @@ export namespace Provider {
730
730
  'link-assistant': async () => {
731
731
  // Echo provider is always available - no external dependencies needed
732
732
  return {
733
- autoload: config.dryRun, // Auto-load only in dry-run mode
733
+ autoload: true, // Also available through --model link-assistant/echo
734
734
  async getModel(_sdk: any, modelID: string) {
735
- // Return our custom echo model that implements LanguageModelV1
735
+ // Return our custom AI SDK language model.
736
736
  return createEchoModel(modelID);
737
737
  },
738
738
  options: {},
@@ -762,7 +762,7 @@ export namespace Provider {
762
762
  const [providerId, ...modelParts] = parts;
763
763
  const actualModelId = modelParts.join('/');
764
764
 
765
- // Return our custom cache model that implements LanguageModelV1
765
+ // Return our custom AI SDK language model.
766
766
  return createCacheModel(providerId, actualModelId);
767
767
  },
768
768
  options: {},
@@ -1772,8 +1772,16 @@ export namespace Provider {
1772
1772
  const isSyntheticProvider =
1773
1773
  providerID === 'link-assistant' || providerID === 'link-assistant/cache';
1774
1774
 
1775
- // For synthetic providers, we don't need model info from the database
1776
- let info = isSyntheticProvider ? null : provider.info.models[modelID];
1775
+ // Synthetic models still need metadata for context limits and accounting.
1776
+ let info =
1777
+ provider.info.models[modelID] ??
1778
+ (isSyntheticProvider
1779
+ ? {
1780
+ ...s.providers['link-assistant'].info.models.echo,
1781
+ id: modelID,
1782
+ name: modelID,
1783
+ }
1784
+ : undefined);
1777
1785
  if (!isSyntheticProvider && !info) {
1778
1786
  // Model not in provider's known list - try refreshing the cache first (#200)
1779
1787
  // This handles stale bundled data or expired cache (1-hour TTL)
@@ -387,7 +387,7 @@ export namespace SessionCompaction {
387
387
  headers: model.info.headers,
388
388
  abortSignal: input.abort,
389
389
  tools: model.info.tool_call ? {} : undefined,
390
- system: system.map((content) => ({ role: 'system', content })),
390
+ instructions: system.map((content) => ({ role: 'system', content })),
391
391
  messages: [
392
392
  ...safeModelMessages,
393
393
  {
@@ -116,7 +116,7 @@ export namespace SessionProcessor {
116
116
  let reasoningMap: Record<string, MessageV2.ReasoningPart> = {};
117
117
  const stream = fn();
118
118
 
119
- for await (const value of stream.fullStream) {
119
+ for await (const value of stream.stream) {
120
120
  input.abort.throwIfAborted();
121
121
  switch (value.type) {
122
122
  case 'start':
@@ -15,7 +15,7 @@ import {
15
15
  type Tool as AITool,
16
16
  tool,
17
17
  wrapLanguageModel,
18
- stepCountIs,
18
+ isStepCount,
19
19
  jsonSchema,
20
20
  } from 'ai';
21
21
  import { SessionCompaction } from './compaction';
@@ -1011,10 +1011,10 @@ export namespace SessionPrompt {
1011
1011
  model.providerID,
1012
1012
  params.options
1013
1013
  ),
1014
- stopWhen: stepCountIs(1),
1014
+ stopWhen: isStepCount(1),
1015
1015
  temperature: params.temperature,
1016
1016
  topP: params.topP,
1017
- system: system.map((content) => ({ role: 'system', content })),
1017
+ instructions: system.map((content) => ({ role: 'system', content })),
1018
1018
  messages: safeModelMessages,
1019
1019
  tools: model.info?.tool_call === false ? undefined : tools,
1020
1020
  model: wrapLanguageModel({
@@ -1059,6 +1059,9 @@ export namespace SessionPrompt {
1059
1059
  if (input.model) {
1060
1060
  return input.model;
1061
1061
  }
1062
+ if (config.dryRun) {
1063
+ return Provider.defaultModel();
1064
+ }
1062
1065
  if (input.agent.model) {
1063
1066
  return input.agent.model;
1064
1067
  }
@@ -1942,7 +1945,7 @@ export namespace SessionPrompt {
1942
1945
  small.providerID,
1943
1946
  options
1944
1947
  ),
1945
- system: safeTitleSystemMessages.map((content) => ({
1948
+ instructions: safeTitleSystemMessages.map((content) => ({
1946
1949
  role: 'system',
1947
1950
  content,
1948
1951
  })),
@@ -222,10 +222,10 @@ export namespace SessionSummary {
222
222
  model.providerID,
223
223
  {}
224
224
  ),
225
- // The system prompt belongs in `system`, not in `messages`: the AI SDK
225
+ // The system prompt belongs in `instructions`, not in `messages`: the AI SDK
226
226
  // warns that a system message inside `messages` enables prompt
227
227
  // injection, and providers are free to treat it as ordinary content.
228
- system: systemPrompts.map((content) => ({
228
+ instructions: systemPrompts.map((content) => ({
229
229
  role: 'system' as const,
230
230
  content,
231
231
  })),