@alisio/core 0.1.0-alpha.9 → 0.1.1
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 +52 -7
- package/dist/agents/active.d.ts +99 -0
- package/dist/agents/active.js +218 -0
- package/dist/agents/capabilities.d.ts +26 -0
- package/dist/agents/capabilities.js +120 -0
- package/dist/agents/create-agent-skill.d.ts +11 -0
- package/dist/agents/create-agent-skill.js +60 -0
- package/dist/agents/definitions.d.ts +88 -0
- package/dist/agents/definitions.js +404 -0
- package/dist/agents/draft.d.ts +41 -0
- package/dist/agents/draft.js +133 -0
- package/dist/agents/service.d.ts +57 -0
- package/dist/agents/service.js +86 -0
- package/dist/agents/templates.d.ts +8 -0
- package/dist/agents/templates.js +102 -0
- package/dist/analysis/capabilities.d.ts +48 -0
- package/dist/analysis/capabilities.js +90 -0
- package/dist/analysis/data/csv.d.ts +46 -0
- package/dist/analysis/data/csv.js +240 -0
- package/dist/analysis/data/datasets.d.ts +132 -0
- package/dist/analysis/data/datasets.js +441 -0
- package/dist/analysis/data/describe.d.ts +27 -0
- package/dist/analysis/data/describe.js +103 -0
- package/dist/analysis/data/engine-client.d.ts +58 -0
- package/dist/analysis/data/engine-client.js +304 -0
- package/dist/analysis/data/engine-entry.d.ts +1 -0
- package/dist/analysis/data/engine-entry.js +59 -0
- package/dist/analysis/data/engine-source.d.ts +4 -0
- package/dist/analysis/data/engine-source.js +6 -0
- package/dist/analysis/data/engine-types.d.ts +86 -0
- package/dist/analysis/data/engine-types.js +7 -0
- package/dist/analysis/data/infer.d.ts +42 -0
- package/dist/analysis/data/infer.js +118 -0
- package/dist/analysis/data/ingest-worker.d.ts +17 -0
- package/dist/analysis/data/ingest-worker.js +365 -0
- package/dist/analysis/data/json.d.ts +19 -0
- package/dist/analysis/data/json.js +44 -0
- package/dist/analysis/data/query-worker.d.ts +12 -0
- package/dist/analysis/data/query-worker.js +75 -0
- package/dist/analysis/data/rows.d.ts +39 -0
- package/dist/analysis/data/rows.js +120 -0
- package/dist/analysis/data/sql-guard.d.ts +20 -0
- package/dist/analysis/data/sql-guard.js +129 -0
- package/dist/analysis/data/stats.d.ts +18 -0
- package/dist/analysis/data/stats.js +77 -0
- package/dist/analysis/install-hints.d.ts +33 -0
- package/dist/analysis/install-hints.js +144 -0
- package/dist/analysis/janitor.d.ts +60 -0
- package/dist/analysis/janitor.js +264 -0
- package/dist/analysis/jobs.d.ts +94 -0
- package/dist/analysis/jobs.js +165 -0
- package/dist/analysis/oci.d.ts +129 -0
- package/dist/analysis/oci.js +330 -0
- package/dist/analysis/python/sources.d.ts +2 -0
- package/dist/analysis/python/sources.js +10 -0
- package/dist/analysis/requirements.d.ts +32 -0
- package/dist/analysis/requirements.js +73 -0
- package/dist/analysis/rerun.d.ts +40 -0
- package/dist/analysis/rerun.js +136 -0
- package/dist/analysis/runtime-manager.d.ts +146 -0
- package/dist/analysis/runtime-manager.js +472 -0
- package/dist/analysis/status.d.ts +21 -0
- package/dist/analysis/status.js +52 -0
- package/dist/application.d.ts +105 -3
- package/dist/application.js +446 -18
- package/dist/artifacts/kinds.d.ts +35 -0
- package/dist/artifacts/kinds.js +177 -0
- package/dist/artifacts/publisher.d.ts +7 -0
- package/dist/artifacts/publisher.js +29 -0
- package/dist/artifacts/store.d.ts +119 -0
- package/dist/artifacts/store.js +581 -0
- package/dist/background/janitor.d.ts +22 -0
- package/dist/background/janitor.js +62 -0
- package/dist/background/mirror.d.ts +14 -0
- package/dist/background/mirror.js +41 -0
- package/dist/background/notify.d.ts +58 -0
- package/dist/background/notify.js +172 -0
- package/dist/background/output.d.ts +46 -0
- package/dist/background/output.js +179 -0
- package/dist/background/service.d.ts +137 -0
- package/dist/background/service.js +410 -0
- package/dist/background/store.d.ts +103 -0
- package/dist/background/store.js +195 -0
- package/dist/changelog/data.d.ts +6 -0
- package/dist/changelog/data.js +306 -0
- package/dist/changelog/index.d.ts +5 -0
- package/dist/changelog/index.js +7 -0
- package/dist/changelog/parse.d.ts +53 -0
- package/dist/changelog/parse.js +160 -0
- package/dist/commands/builtins.d.ts +10 -0
- package/dist/commands/builtins.js +161 -0
- package/dist/commands/catalog.d.ts +86 -0
- package/dist/commands/catalog.js +304 -0
- package/dist/config.d.ts +206 -6
- package/dist/config.js +426 -20
- package/dist/core/compaction.js +13 -2
- package/dist/core/contracts.d.ts +180 -3
- package/dist/core/opt-in.d.ts +12 -0
- package/dist/core/opt-in.js +12 -0
- package/dist/core/output-limit.d.ts +34 -0
- package/dist/core/output-limit.js +39 -0
- package/dist/core/run-stats.d.ts +16 -0
- package/dist/core/run-stats.js +8 -0
- package/dist/core/runner.d.ts +134 -4
- package/dist/core/runner.js +780 -138
- package/dist/core/timeout.d.ts +15 -0
- package/dist/core/timeout.js +61 -0
- package/dist/core/truncation.d.ts +30 -0
- package/dist/core/truncation.js +83 -0
- package/dist/goal/blockers.d.ts +45 -0
- package/dist/goal/blockers.js +51 -0
- package/dist/goal/budget.d.ts +24 -0
- package/dist/goal/budget.js +53 -0
- package/dist/goal/command.d.ts +36 -0
- package/dist/goal/command.js +98 -0
- package/dist/goal/format.d.ts +19 -0
- package/dist/goal/format.js +102 -0
- package/dist/goal/host.d.ts +29 -0
- package/dist/goal/host.js +42 -0
- package/dist/goal/index.d.ts +9 -0
- package/dist/goal/index.js +9 -0
- package/dist/goal/machine.d.ts +186 -0
- package/dist/goal/machine.js +344 -0
- package/dist/goal/prompts.d.ts +10 -0
- package/dist/goal/prompts.js +75 -0
- package/dist/goal/service.d.ts +113 -0
- package/dist/goal/service.js +273 -0
- package/dist/goal/store.d.ts +59 -0
- package/dist/goal/store.js +184 -0
- package/dist/index.d.ts +50 -5
- package/dist/index.js +49 -4
- package/dist/mcp/connector.js +38 -6
- package/dist/mcp/rich.d.ts +41 -0
- package/dist/mcp/rich.js +362 -0
- package/dist/permissions/modes.d.ts +72 -0
- package/dist/permissions/modes.js +98 -0
- package/dist/plan/exit-plan.d.ts +25 -0
- package/dist/plan/exit-plan.js +130 -0
- package/dist/plan/state.d.ts +102 -0
- package/dist/plan/state.js +165 -0
- package/dist/plugins/host.d.ts +34 -1
- package/dist/plugins/host.js +143 -9
- package/dist/providers/settings.d.ts +15 -0
- package/dist/providers/settings.js +38 -0
- package/dist/reload.d.ts +75 -0
- package/dist/reload.js +204 -0
- package/dist/resources/context.js +6 -1
- package/dist/runtime/access.d.ts +62 -0
- package/dist/runtime/access.js +115 -0
- package/dist/runtime/blobs.d.ts +51 -0
- package/dist/runtime/blobs.js +177 -0
- package/dist/runtime/diff.d.ts +23 -0
- package/dist/runtime/diff.js +154 -0
- package/dist/runtime/ids.d.ts +8 -0
- package/dist/runtime/ids.js +32 -0
- package/dist/runtime/paths.d.ts +11 -0
- package/dist/runtime/paths.js +17 -1
- package/dist/runtime/process.d.ts +22 -0
- package/dist/runtime/process.js +100 -15
- package/dist/runtime/sqlite.d.ts +2 -0
- package/dist/runtime/sqlite.js +18 -0
- package/dist/runtime/store.d.ts +91 -3
- package/dist/runtime/store.js +465 -11
- package/dist/runtime/zip.d.ts +24 -0
- package/dist/runtime/zip.js +126 -0
- package/dist/sessions/children.js +17 -1
- package/dist/sessions/side-questions.d.ts +57 -0
- package/dist/sessions/side-questions.js +161 -0
- package/dist/tools/analysis.d.ts +37 -0
- package/dist/tools/analysis.js +573 -0
- package/dist/tools/artifacts.d.ts +14 -0
- package/dist/tools/artifacts.js +143 -0
- package/dist/tools/background.d.ts +7 -0
- package/dist/tools/background.js +165 -0
- package/dist/tools/data.d.ts +7 -0
- package/dist/tools/data.js +160 -0
- package/dist/tools/execute.d.ts +5 -0
- package/dist/tools/execute.js +15 -3
- package/dist/tools/goal.d.ts +19 -0
- package/dist/tools/goal.js +126 -0
- package/dist/tools/search.d.ts +17 -3
- package/dist/tools/search.js +153 -0
- package/dist/tools/standard.d.ts +4 -1
- package/dist/tools/standard.js +99 -18
- package/dist/version.d.ts +5 -3
- package/dist/version.js +35 -6
- package/package.json +2 -2
package/dist/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { chmod, mkdir, open, readFile, rename, unlink } from "node:fs/promises";
|
|
1
|
+
import { chmod, mkdir, open, readFile, realpath, rename, unlink } from "node:fs/promises";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
import { z } from "zod";
|
|
@@ -75,12 +75,25 @@ const serversSchema = (value) => z.record(z.string(), value).superRefine((server
|
|
|
75
75
|
message: "MCP server names may contain only letters, numbers, dot, underscore and dash",
|
|
76
76
|
});
|
|
77
77
|
});
|
|
78
|
+
/**
|
|
79
|
+
* A container image reference pinned by digest. Anchored at the start with a letter or digit so a
|
|
80
|
+
* value can never be read as an option by the container CLI.
|
|
81
|
+
*/
|
|
82
|
+
export const OCI_IMAGE_PATTERN = /^[a-zA-Z0-9][^\s@]*@sha256:[a-f0-9]{64}$/;
|
|
83
|
+
/** Analysis keys only the user (global) layer decides; a project layer cannot set them. */
|
|
84
|
+
const GLOBAL_ONLY_ANALYSIS = ["runtime", "oci", "retention"];
|
|
78
85
|
const configObjectSchema = z
|
|
79
86
|
.object({
|
|
80
87
|
schemaVersion: z.literal(1).default(1),
|
|
81
88
|
provider: providerSchema.default(() => providerSchema.parse({})),
|
|
82
89
|
plugins: z.array(z.string()).default([]),
|
|
83
90
|
skills: z.array(z.string()).default([]),
|
|
91
|
+
/**
|
|
92
|
+
* Extra directories the mediated path policy may touch outside the workspace. Resolved
|
|
93
|
+
* relative to the defining configuration file and canonicalized on load. Additive across
|
|
94
|
+
* layers like `plugins`/`skills`: a lower layer can only ADD, never clear the global list.
|
|
95
|
+
*/
|
|
96
|
+
additionalDirectories: z.array(z.string().trim().min(1)).default([]),
|
|
84
97
|
/** Project-local enable/disable overrides for effective non-plugin skills. */
|
|
85
98
|
skillOverrides: z.record(z.string(), z.object({ enabled: z.boolean() }).strict()).default({}),
|
|
86
99
|
mcp: z
|
|
@@ -140,7 +153,15 @@ const configObjectSchema = z
|
|
|
140
153
|
websearch: z
|
|
141
154
|
.object({
|
|
142
155
|
provider: z
|
|
143
|
-
.enum([
|
|
156
|
+
.enum([
|
|
157
|
+
"searxng",
|
|
158
|
+
"duckduckgo-instant",
|
|
159
|
+
"duckduckgo-html",
|
|
160
|
+
"tavily",
|
|
161
|
+
"brave",
|
|
162
|
+
"serpapi",
|
|
163
|
+
"native",
|
|
164
|
+
])
|
|
144
165
|
.optional(),
|
|
145
166
|
searxngUrl: z.string().optional(),
|
|
146
167
|
apiKeyEnv: z.string().optional(),
|
|
@@ -151,23 +172,231 @@ const configObjectSchema = z
|
|
|
151
172
|
.default(() => ({ nativeToolType: "web_search" })),
|
|
152
173
|
limits: z
|
|
153
174
|
.object({
|
|
154
|
-
maxTurns: z.number().int().min(1).max(100).default(
|
|
155
|
-
timeoutMs: z.number().int().min(100).default(
|
|
156
|
-
|
|
157
|
-
|
|
175
|
+
maxTurns: z.number().int().min(1).max(100).default(100),
|
|
176
|
+
timeoutMs: z.number().int().min(100).default(600000),
|
|
177
|
+
/**
|
|
178
|
+
* Stop a model request that stays completely silent (no text, reasoning or tool-call
|
|
179
|
+
* delta) this long, so a queued or stuck provider is cut after 90 s instead of the
|
|
180
|
+
* whole-run `timeoutMs`. 0 disables it (models that do not stream their reasoning can stay
|
|
181
|
+
* silent for minutes: raise or disable it for those).
|
|
182
|
+
*/
|
|
183
|
+
firstTokenTimeoutMs: z.number().int().min(0).default(90000),
|
|
184
|
+
/**
|
|
185
|
+
* How many times the SAME request is sent again after it stayed silent for
|
|
186
|
+
* `firstTokenTimeoutMs` (a stalled connection usually answers on the next try). 0
|
|
187
|
+
* disables the retry. Never counts as a turn.
|
|
188
|
+
*/
|
|
189
|
+
firstTokenRetries: z.number().int().min(0).max(3).default(1),
|
|
190
|
+
/**
|
|
191
|
+
* How many times a turn is requested again after the model's response was cut off by
|
|
192
|
+
* `maxOutputTokens` before it was usable (no text and no tool call, or a tool call with
|
|
193
|
+
* incomplete arguments). The truncated calls are never executed. 0 disables the
|
|
194
|
+
* recovery. Never counts as a turn.
|
|
195
|
+
*/
|
|
196
|
+
truncationRecoveries: z.number().int().min(0).max(5).default(2),
|
|
197
|
+
maxContextChars: z.number().int().positive().default(800000),
|
|
198
|
+
/**
|
|
199
|
+
* Per-call output token budget for one agent turn. Deliberately WITHOUT a schema default:
|
|
200
|
+
* when unset, the budget of each request is the model catalog's declared maximum (capped
|
|
201
|
+
* at 65536) or 16384 (see `core/output-limit.ts`), so "set by the user" stays
|
|
202
|
+
* distinguishable from "defaulted". A value set here always wins. 4096 starves
|
|
203
|
+
* reasoning-heavy models, which can spend the whole budget on `reasoning_content`
|
|
204
|
+
* before any usable text arrives.
|
|
205
|
+
*/
|
|
206
|
+
maxOutputTokens: z.number().int().positive().optional(),
|
|
158
207
|
/** Cumulative tokens per run; default is proportional to the context window. */
|
|
159
208
|
maxTokens: z.number().int().positive().optional(),
|
|
160
209
|
})
|
|
161
210
|
.default(() => ({
|
|
162
|
-
maxTurns:
|
|
163
|
-
timeoutMs:
|
|
164
|
-
|
|
165
|
-
|
|
211
|
+
maxTurns: 100,
|
|
212
|
+
timeoutMs: 600000,
|
|
213
|
+
firstTokenTimeoutMs: 90000,
|
|
214
|
+
firstTokenRetries: 1,
|
|
215
|
+
truncationRecoveries: 2,
|
|
216
|
+
maxContextChars: 800000,
|
|
217
|
+
})),
|
|
218
|
+
/**
|
|
219
|
+
* Python analysis and downloadable artifacts. `enabled: false` registers none of the
|
|
220
|
+
* analysis tools. The interpreter is discovered automatically (or pinned with `--python`).
|
|
221
|
+
*/
|
|
222
|
+
analysis: z
|
|
223
|
+
.object({
|
|
224
|
+
enabled: z.boolean().default(true),
|
|
225
|
+
/**
|
|
226
|
+
* Where `python_run` executes. `managed` is the discovered Python (not a sandbox); `oci`
|
|
227
|
+
* is a Docker or Podman container started from a pinned image. GLOBAL ONLY: a project
|
|
228
|
+
* layer cannot choose the runtime or the image (it is ignored with a diagnostic).
|
|
229
|
+
*/
|
|
230
|
+
runtime: z.enum(["managed", "oci"]).default("managed"),
|
|
231
|
+
/** Container runtime settings (global only). Used when `runtime` is `oci`. */
|
|
232
|
+
oci: z
|
|
233
|
+
.object({
|
|
234
|
+
engine: z.enum(["docker", "podman"]).default("docker"),
|
|
235
|
+
/** `name@sha256:<digest>`: an image without a digest is rejected at load time. */
|
|
236
|
+
image: z
|
|
237
|
+
.string()
|
|
238
|
+
.regex(OCI_IMAGE_PATTERN, "analysis.oci.image must be pinned by digest: <name>@sha256:<64 hex characters>")
|
|
239
|
+
.optional(),
|
|
240
|
+
memoryMb: z.number().int().min(256).max(65_536).default(2048),
|
|
241
|
+
cpus: z.number().min(0.5).max(64).default(2),
|
|
242
|
+
})
|
|
243
|
+
.strict()
|
|
244
|
+
.default(() => ({ engine: "docker", memoryMb: 2048, cpus: 2 })),
|
|
245
|
+
limits: z
|
|
246
|
+
.object({
|
|
247
|
+
/** Default and maximum run time of one python_run call. */
|
|
248
|
+
timeoutMs: z.number().int().min(1000).max(900_000).default(120_000),
|
|
249
|
+
/** Files published by one execution. */
|
|
250
|
+
maxFiles: z.number().int().min(1).max(1000).default(200),
|
|
251
|
+
maxFileBytes: z
|
|
252
|
+
.number()
|
|
253
|
+
.int()
|
|
254
|
+
.positive()
|
|
255
|
+
.default(100 * 1024 * 1024),
|
|
256
|
+
/** Total bytes published by one execution. */
|
|
257
|
+
maxOutputBytes: z
|
|
258
|
+
.number()
|
|
259
|
+
.int()
|
|
260
|
+
.positive()
|
|
261
|
+
.default(500 * 1024 * 1024),
|
|
262
|
+
/** Size cap of each stdout/stderr log of a job. */
|
|
263
|
+
maxLogBytes: z
|
|
264
|
+
.number()
|
|
265
|
+
.int()
|
|
266
|
+
.positive()
|
|
267
|
+
.default(10 * 1024 * 1024),
|
|
268
|
+
})
|
|
269
|
+
.strict()
|
|
270
|
+
.default(() => ({
|
|
271
|
+
timeoutMs: 120_000,
|
|
272
|
+
maxFiles: 200,
|
|
273
|
+
maxFileBytes: 100 * 1024 * 1024,
|
|
274
|
+
maxOutputBytes: 500 * 1024 * 1024,
|
|
275
|
+
maxLogBytes: 10 * 1024 * 1024,
|
|
276
|
+
})),
|
|
277
|
+
/** Tabular data (CSV, TSV, JSON, JSONL, XLSX) ingested into one SQLite file per dataset. */
|
|
278
|
+
data: z
|
|
279
|
+
.object({
|
|
280
|
+
/** Largest file ingested (an upload or a workspace file). */
|
|
281
|
+
maxUploadBytes: z
|
|
282
|
+
.number()
|
|
283
|
+
.int()
|
|
284
|
+
.positive()
|
|
285
|
+
.default(200 * 1024 * 1024),
|
|
286
|
+
/** Rows per sheet; a larger file stops the ingestion and leaves no dataset. */
|
|
287
|
+
maxRows: z.number().int().positive().default(5_000_000),
|
|
288
|
+
/** Time limit of one `data_query` statement; the engine process is killed past it. */
|
|
289
|
+
queryTimeoutMs: z.number().int().min(100).max(60_000).default(5000),
|
|
290
|
+
/** Sorting and filtering are disabled above this many rows (the file has no indexes). */
|
|
291
|
+
maxInteractiveRows: z.number().int().positive().default(1_000_000),
|
|
292
|
+
})
|
|
293
|
+
.strict()
|
|
294
|
+
.default(() => ({
|
|
295
|
+
maxUploadBytes: 200 * 1024 * 1024,
|
|
296
|
+
maxRows: 5_000_000,
|
|
297
|
+
queryTimeoutMs: 5000,
|
|
298
|
+
maxInteractiveRows: 1_000_000,
|
|
299
|
+
})),
|
|
300
|
+
/**
|
|
301
|
+
* Retention of analysis data (`0` disables the automatic deletion of that class). Global
|
|
302
|
+
* only: one sweep covers every workspace, so a project layer cannot shorten it.
|
|
303
|
+
*/
|
|
304
|
+
retention: z
|
|
305
|
+
.object({
|
|
306
|
+
/** Logs and staging of a job; its script and inputs once no artifact is `ready`. */
|
|
307
|
+
jobsDays: z.number().int().min(0).max(3650).default(30),
|
|
308
|
+
/** The scratch folder (`work/`) of a job. */
|
|
309
|
+
intermediateDays: z.number().int().min(0).max(3650).default(7),
|
|
310
|
+
/** Artifacts older than this become `expired` (folder deleted, row kept). 0 = keep. */
|
|
311
|
+
artifactsDays: z.number().int().min(0).max(3650).default(0),
|
|
312
|
+
})
|
|
313
|
+
.strict()
|
|
314
|
+
.default(() => ({ jobsDays: 30, intermediateDays: 7, artifactsDays: 0 })),
|
|
315
|
+
})
|
|
316
|
+
.strict()
|
|
317
|
+
.default(() => ({
|
|
318
|
+
enabled: true,
|
|
319
|
+
runtime: "managed",
|
|
320
|
+
oci: { engine: "docker", memoryMb: 2048, cpus: 2 },
|
|
321
|
+
retention: { jobsDays: 30, intermediateDays: 7, artifactsDays: 0 },
|
|
322
|
+
limits: {
|
|
323
|
+
timeoutMs: 120_000,
|
|
324
|
+
maxFiles: 200,
|
|
325
|
+
maxFileBytes: 100 * 1024 * 1024,
|
|
326
|
+
maxOutputBytes: 500 * 1024 * 1024,
|
|
327
|
+
maxLogBytes: 10 * 1024 * 1024,
|
|
328
|
+
},
|
|
329
|
+
data: {
|
|
330
|
+
maxUploadBytes: 200 * 1024 * 1024,
|
|
331
|
+
maxRows: 5_000_000,
|
|
332
|
+
queryTimeoutMs: 5000,
|
|
333
|
+
maxInteractiveRows: 1_000_000,
|
|
334
|
+
},
|
|
335
|
+
})),
|
|
336
|
+
/**
|
|
337
|
+
* Background tasks (`bg_run`, `bg_list`, `bg_output`, `bg_stop`). They are ordinary child
|
|
338
|
+
* processes of Alisio (not detached, not sandboxed): they end when Alisio ends. `enabled:
|
|
339
|
+
* false` registers none of the tools (applies from the next start). `retentionDays` is
|
|
340
|
+
* global-only: one sweep covers every workspace, so a project layer cannot shorten it.
|
|
341
|
+
*/
|
|
342
|
+
tasks: z
|
|
343
|
+
.object({
|
|
344
|
+
enabled: z.boolean().default(true),
|
|
345
|
+
/** Live (queued, running or stopping) tasks per root session. */
|
|
346
|
+
maxPerSession: z.number().int().min(1).max(32).default(4),
|
|
347
|
+
/** Watchdog: a task still running after this long is stopped and fails with `timeout`. */
|
|
348
|
+
maxRunMs: z.number().int().min(1000).max(86_400_000).default(3_600_000),
|
|
349
|
+
/** Size limit of one task log (the head is kept, a short tail is added when it ends). */
|
|
350
|
+
maxOutputBytes: z.number().int().min(65_536).max(104_857_600).default(2_097_152),
|
|
351
|
+
/** Finished task rows and their logs are deleted after this many days (0 keeps them). */
|
|
352
|
+
retentionDays: z.number().int().min(0).max(3650).default(7),
|
|
353
|
+
})
|
|
354
|
+
.strict()
|
|
355
|
+
.default(() => ({
|
|
356
|
+
enabled: true,
|
|
357
|
+
maxPerSession: 4,
|
|
358
|
+
maxRunMs: 3_600_000,
|
|
359
|
+
maxOutputBytes: 2_097_152,
|
|
360
|
+
retentionDays: 7,
|
|
361
|
+
})),
|
|
362
|
+
/**
|
|
363
|
+
* `/goal`: a session objective the runtime keeps working on, with hard caps. The token budget
|
|
364
|
+
* is NOT a setting (none unless the user gives one with `budget=`); without it only the turn
|
|
365
|
+
* and time caps stop a goal. `maxTurns` counts runs (a goal turn is one run); `maxMinutes` is
|
|
366
|
+
* the time spent inside runs. The breakers pause a goal that makes no progress.
|
|
367
|
+
*/
|
|
368
|
+
goal: z
|
|
369
|
+
.object({
|
|
370
|
+
enabled: z.boolean().default(true),
|
|
371
|
+
maxTurns: z.number().int().min(1).max(1000).default(50),
|
|
372
|
+
maxMinutes: z.number().int().min(1).max(1440).default(120),
|
|
373
|
+
/** Pause after this many consecutive identical replies (observed, nudged, then paused). */
|
|
374
|
+
repeatedReplyLimit: z.number().int().min(2).max(20).default(3),
|
|
375
|
+
/** Pause after this many consecutive turns without a tool call. */
|
|
376
|
+
noToolTurnsLimit: z.number().int().min(2).max(20).default(3),
|
|
377
|
+
/** Consecutive turns in which the model must report the same blocker before it stops. */
|
|
378
|
+
blockedRepeats: z.number().int().min(1).max(10).default(2),
|
|
379
|
+
})
|
|
380
|
+
.strict()
|
|
381
|
+
.default(() => ({
|
|
382
|
+
enabled: true,
|
|
383
|
+
maxTurns: 50,
|
|
384
|
+
maxMinutes: 120,
|
|
385
|
+
repeatedReplyLimit: 3,
|
|
386
|
+
noToolTurnsLimit: 3,
|
|
387
|
+
blockedRepeats: 2,
|
|
166
388
|
})),
|
|
167
389
|
tui: z
|
|
168
390
|
.object({
|
|
169
|
-
/** Horizontal padding (columns) around the editor input box. */
|
|
391
|
+
/** Horizontal padding (columns) around the editor input box. Editor-only. */
|
|
170
392
|
paddingX: z.number().int().min(0).max(4).default(1),
|
|
393
|
+
/**
|
|
394
|
+
* Horizontal inset (columns) applied to each side of the transcript content, so
|
|
395
|
+
* agent-written rows keep breathing room from the window borders. Independent of
|
|
396
|
+
* `paddingX` (which styles only the editor input box). Clamped on narrow terminals so the
|
|
397
|
+
* content column never collapses below a usable width.
|
|
398
|
+
*/
|
|
399
|
+
contentPaddingX: z.number().int().min(0).max(12).default(2),
|
|
171
400
|
/**
|
|
172
401
|
* Offer effective skills as first-class `skill:<id>` editor slash-autocomplete entries.
|
|
173
402
|
* Off hides those entries; the `/skills` manager and its argument completion stay available.
|
|
@@ -175,7 +404,28 @@ const configObjectSchema = z
|
|
|
175
404
|
skillSlashCommands: z.boolean().default(true),
|
|
176
405
|
})
|
|
177
406
|
.strict()
|
|
178
|
-
.default(() => ({ paddingX: 1, skillSlashCommands: true })),
|
|
407
|
+
.default(() => ({ paddingX: 1, contentPaddingX: 2, skillSlashCommands: true })),
|
|
408
|
+
/**
|
|
409
|
+
* The ACTIVE agent drives the main session: its system prompt is appended to every prompt and
|
|
410
|
+
* its optional model selector is offered when the agent is chosen (`/agents`). `build` is the
|
|
411
|
+
* built-in default (full-power, no added persona); `plan` is the built-in read-only planner.
|
|
412
|
+
* `effort` holds a reasoning effort level chosen with `/effort` for a model that advertises
|
|
413
|
+
* `effort.supportedLevels`; it is validated against the ACTIVE model on use, falling back to
|
|
414
|
+
* the model's default level when unsupported.
|
|
415
|
+
*/
|
|
416
|
+
agents: z
|
|
417
|
+
.object({
|
|
418
|
+
active: z
|
|
419
|
+
.string()
|
|
420
|
+
.trim()
|
|
421
|
+
.min(1)
|
|
422
|
+
.max(100)
|
|
423
|
+
.regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]*$/, "invalid agent name")
|
|
424
|
+
.default("build"),
|
|
425
|
+
effort: z.string().trim().min(1).max(50).optional(),
|
|
426
|
+
})
|
|
427
|
+
.strict()
|
|
428
|
+
.default(() => ({ active: "build" })),
|
|
179
429
|
})
|
|
180
430
|
.strict()
|
|
181
431
|
.superRefine((config, context) => {
|
|
@@ -204,6 +454,26 @@ function isUsableLegacyModel(model) {
|
|
|
204
454
|
const normalized = model.trim();
|
|
205
455
|
return normalized !== "" && normalized !== LEGACY_PROVIDER_MODEL_PLACEHOLDER;
|
|
206
456
|
}
|
|
457
|
+
/**
|
|
458
|
+
* Appends the entries of `selected` after the `global` list, dropping exact duplicates so the
|
|
459
|
+
* global entries keep their order and the selected layer only ever ADDS to the collection. An
|
|
460
|
+
* empty `selected` list therefore leaves the global list intact. Entries were already resolved
|
|
461
|
+
* per layer by `parseLayer`, so deduplication happens on the resolved strings.
|
|
462
|
+
*/
|
|
463
|
+
function mergeUnique(global, selected) {
|
|
464
|
+
const seen = new Set(global);
|
|
465
|
+
const merged = [...global];
|
|
466
|
+
for (const entry of selected)
|
|
467
|
+
if (!seen.has(entry)) {
|
|
468
|
+
seen.add(entry);
|
|
469
|
+
merged.push(entry);
|
|
470
|
+
}
|
|
471
|
+
return merged;
|
|
472
|
+
}
|
|
473
|
+
/** Absolute, canonical directory when it exists; a missing path keeps its resolved absolute form. */
|
|
474
|
+
async function canonicalDirectory(path) {
|
|
475
|
+
return realpath(path).catch(() => resolve(path));
|
|
476
|
+
}
|
|
207
477
|
/**
|
|
208
478
|
* Whether legacy provider selection should take priority over a saved plugin profile for this
|
|
209
479
|
* run: an explicit endpoint override, or a trusted project/explicit layer whose parsed root
|
|
@@ -236,6 +506,9 @@ export async function loadConfigWithProvenance(workspace, options = {}) {
|
|
|
236
506
|
const raw = (await readJson(file)) ?? {};
|
|
237
507
|
const config = configSchema.parse(raw);
|
|
238
508
|
config.skills = config.skills.map((p) => resolve(file, "..", p));
|
|
509
|
+
// Extra tool roots are paths relative to the config file; canonicalize so containment checks
|
|
510
|
+
// compare real directories (a symlinked root never escapes its declared location).
|
|
511
|
+
config.additionalDirectories = await Promise.all(config.additionalDirectories.map((p) => canonicalDirectory(resolve(file, "..", p))));
|
|
239
512
|
// Plugin entries are paths (relative to the config file) or npm package names.
|
|
240
513
|
config.plugins = config.plugins.map((p) => (isPathSpec(p) ? resolve(file, "..", p) : p));
|
|
241
514
|
for (const server of Object.values(config.mcp.servers))
|
|
@@ -259,7 +532,17 @@ export async function loadConfigWithProvenance(workspace, options = {}) {
|
|
|
259
532
|
form: canonical && name in canonical ? "canonical" : "alias",
|
|
260
533
|
},
|
|
261
534
|
]));
|
|
262
|
-
|
|
535
|
+
const analysisRaw = object.analysis && typeof object.analysis === "object" && !Array.isArray(object.analysis)
|
|
536
|
+
? object.analysis
|
|
537
|
+
: {};
|
|
538
|
+
const tasksRaw = object.tasks && typeof object.tasks === "object" && !Array.isArray(object.tasks)
|
|
539
|
+
? object.tasks
|
|
540
|
+
: {};
|
|
541
|
+
const ignored = [
|
|
542
|
+
...GLOBAL_ONLY_ANALYSIS.filter((key) => key in analysisRaw).map((key) => `analysis.${key}`),
|
|
543
|
+
...("retentionDays" in tasksRaw ? ["tasks.retentionDays"] : []),
|
|
544
|
+
];
|
|
545
|
+
return { config, keys: new Set(Object.keys(object)), sources, ignored, file };
|
|
263
546
|
};
|
|
264
547
|
const global = await parseLayer(globalFile, "global");
|
|
265
548
|
// Skill activation is deliberately project-local; never carry a similarly named global field
|
|
@@ -270,15 +553,72 @@ export async function loadConfigWithProvenance(workspace, options = {}) {
|
|
|
270
553
|
// Parsed `provider.model` of the selected layer itself (before env/CLI overrides), used to
|
|
271
554
|
// decide whether its legacy root `provider` is usable against a saved `/connect` profile.
|
|
272
555
|
let selectedLegacyModel = "";
|
|
556
|
+
let ignoredKeys = [];
|
|
273
557
|
if (selectedFile && selectedFile !== globalFile) {
|
|
274
558
|
const selected = await parseLayer(selectedFile, options.file ? "explicit" : "project");
|
|
559
|
+
ignoredKeys = selected.ignored;
|
|
275
560
|
selectedLegacyModel = selected.config.provider.model;
|
|
276
561
|
const overlaid = { ...config };
|
|
277
562
|
for (const key of selected.keys) {
|
|
278
563
|
if (key === "mcp" || key === "mcpServers")
|
|
279
564
|
continue;
|
|
280
|
-
if (key in selected.config)
|
|
281
|
-
|
|
565
|
+
if (!(key in selected.config))
|
|
566
|
+
continue;
|
|
567
|
+
// Additive collections: the selected layer ADDS to the global list (global entries
|
|
568
|
+
// first, exact duplicates dropped); an empty selected list never clears the global one.
|
|
569
|
+
if (key === "plugins") {
|
|
570
|
+
overlaid.plugins = mergeUnique(overlaid.plugins, selected.config.plugins);
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
if (key === "skills") {
|
|
574
|
+
overlaid.skills = mergeUnique(overlaid.skills, selected.config.skills);
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
if (key === "additionalDirectories") {
|
|
578
|
+
overlaid.additionalDirectories = mergeUnique(overlaid.additionalDirectories, selected.config.additionalDirectories);
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
// Additive records: merge by key, the selected layer wins per key.
|
|
582
|
+
if (key === "pluginOverrides") {
|
|
583
|
+
overlaid.pluginOverrides = {
|
|
584
|
+
...overlaid.pluginOverrides,
|
|
585
|
+
...selected.config.pluginOverrides,
|
|
586
|
+
};
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
if (key === "skillOverrides") {
|
|
590
|
+
// Global skill overrides were reset above (skill activation is project-local); the
|
|
591
|
+
// selected overrides still merge into that empty record and win per key.
|
|
592
|
+
overlaid.skillOverrides = { ...overlaid.skillOverrides, ...selected.config.skillOverrides };
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
if (key === "builtinPlugins") {
|
|
596
|
+
// Per-plugin options merge by plugin id: the selected entry wins per id, so
|
|
597
|
+
// `{id: {enabled: false}}` in the selected layer still disables that built-in while
|
|
598
|
+
// every other global entry stays.
|
|
599
|
+
overlaid.builtinPlugins = { ...overlaid.builtinPlugins, ...selected.config.builtinPlugins };
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
if (key === "analysis") {
|
|
603
|
+
// `runtime`, `oci` and `retention` are global-only (a repository must not pick the binary
|
|
604
|
+
// that runs scripts, nor shorten the retention of every workspace's data).
|
|
605
|
+
overlaid.analysis = {
|
|
606
|
+
...selected.config.analysis,
|
|
607
|
+
runtime: global.config.analysis.runtime,
|
|
608
|
+
oci: global.config.analysis.oci,
|
|
609
|
+
retention: global.config.analysis.retention,
|
|
610
|
+
};
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
if (key === "tasks") {
|
|
614
|
+
// `retentionDays` is global-only (one sweep deletes the data of every workspace).
|
|
615
|
+
overlaid.tasks = {
|
|
616
|
+
...selected.config.tasks,
|
|
617
|
+
retentionDays: global.config.tasks.retentionDays,
|
|
618
|
+
};
|
|
619
|
+
continue;
|
|
620
|
+
}
|
|
621
|
+
overlaid[key] = selected.config[key];
|
|
282
622
|
}
|
|
283
623
|
if (selected.keys.has("mcp") || selected.keys.has("mcpServers"))
|
|
284
624
|
// Only servers merge upward; `mcp.allow` is a global/user preference and is deliberately
|
|
@@ -316,6 +656,7 @@ export async function loadConfigWithProvenance(workspace, options = {}) {
|
|
|
316
656
|
},
|
|
317
657
|
}
|
|
318
658
|
: {}),
|
|
659
|
+
...(ignoredKeys.length ? { ignored: ignoredKeys } : {}),
|
|
319
660
|
},
|
|
320
661
|
};
|
|
321
662
|
}
|
|
@@ -422,7 +763,13 @@ const SETTABLE_SECTIONS = {
|
|
|
422
763
|
pluginHooks: configObjectSchema.shape.pluginHooks.removeDefault(),
|
|
423
764
|
tui: configObjectSchema.shape.tui.removeDefault(),
|
|
424
765
|
websearch: configObjectSchema.shape.websearch.removeDefault(),
|
|
766
|
+
agents: configObjectSchema.shape.agents.removeDefault(),
|
|
767
|
+
analysis: configObjectSchema.shape.analysis.removeDefault(),
|
|
768
|
+
tasks: configObjectSchema.shape.tasks.removeDefault(),
|
|
769
|
+
goal: configObjectSchema.shape.goal.removeDefault(),
|
|
425
770
|
};
|
|
771
|
+
const ANALYSIS_LIMITS = SETTABLE_SECTIONS.analysis.shape.limits.removeDefault();
|
|
772
|
+
const ANALYSIS_RETENTION = SETTABLE_SECTIONS.analysis.shape.retention.removeDefault();
|
|
426
773
|
const SETTABLE_KEYS = {
|
|
427
774
|
"compaction.auto": SETTABLE_SECTIONS.compaction.shape.auto,
|
|
428
775
|
"compaction.threshold": SETTABLE_SECTIONS.compaction.shape.threshold,
|
|
@@ -434,14 +781,63 @@ const SETTABLE_KEYS = {
|
|
|
434
781
|
"limits.maxOutputTokens": SETTABLE_SECTIONS.limits.shape.maxOutputTokens,
|
|
435
782
|
"limits.maxContextChars": SETTABLE_SECTIONS.limits.shape.maxContextChars,
|
|
436
783
|
"limits.timeoutMs": SETTABLE_SECTIONS.limits.shape.timeoutMs,
|
|
784
|
+
"limits.firstTokenTimeoutMs": SETTABLE_SECTIONS.limits.shape.firstTokenTimeoutMs,
|
|
785
|
+
"limits.firstTokenRetries": SETTABLE_SECTIONS.limits.shape.firstTokenRetries,
|
|
786
|
+
"limits.truncationRecoveries": SETTABLE_SECTIONS.limits.shape.truncationRecoveries,
|
|
437
787
|
"pluginHooks.timeoutMs": SETTABLE_SECTIONS.pluginHooks.shape.timeoutMs,
|
|
438
788
|
"tui.paddingX": SETTABLE_SECTIONS.tui.shape.paddingX,
|
|
789
|
+
"tui.contentPaddingX": SETTABLE_SECTIONS.tui.shape.contentPaddingX,
|
|
439
790
|
"tui.skillSlashCommands": SETTABLE_SECTIONS.tui.shape.skillSlashCommands,
|
|
440
791
|
"websearch.provider": SETTABLE_SECTIONS.websearch.shape.provider,
|
|
792
|
+
"agents.active": SETTABLE_SECTIONS.agents.shape.active,
|
|
793
|
+
"agents.effort": SETTABLE_SECTIONS.agents.shape.effort,
|
|
794
|
+
"analysis.enabled": SETTABLE_SECTIONS.analysis.shape.enabled,
|
|
795
|
+
"analysis.limits.timeoutMs": ANALYSIS_LIMITS.shape.timeoutMs,
|
|
796
|
+
"analysis.retention.jobsDays": ANALYSIS_RETENTION.shape.jobsDays,
|
|
797
|
+
"analysis.retention.intermediateDays": ANALYSIS_RETENTION.shape.intermediateDays,
|
|
798
|
+
"analysis.retention.artifactsDays": ANALYSIS_RETENTION.shape.artifactsDays,
|
|
799
|
+
"tasks.enabled": SETTABLE_SECTIONS.tasks.shape.enabled,
|
|
800
|
+
"tasks.maxPerSession": SETTABLE_SECTIONS.tasks.shape.maxPerSession,
|
|
801
|
+
"tasks.maxRunMs": SETTABLE_SECTIONS.tasks.shape.maxRunMs,
|
|
802
|
+
"tasks.maxOutputBytes": SETTABLE_SECTIONS.tasks.shape.maxOutputBytes,
|
|
803
|
+
"tasks.retentionDays": SETTABLE_SECTIONS.tasks.shape.retentionDays,
|
|
804
|
+
"goal.enabled": SETTABLE_SECTIONS.goal.shape.enabled,
|
|
805
|
+
"goal.maxTurns": SETTABLE_SECTIONS.goal.shape.maxTurns,
|
|
806
|
+
"goal.maxMinutes": SETTABLE_SECTIONS.goal.shape.maxMinutes,
|
|
807
|
+
"goal.repeatedReplyLimit": SETTABLE_SECTIONS.goal.shape.repeatedReplyLimit,
|
|
808
|
+
"goal.noToolTurnsLimit": SETTABLE_SECTIONS.goal.shape.noToolTurnsLimit,
|
|
809
|
+
"goal.blockedRepeats": SETTABLE_SECTIONS.goal.shape.blockedRepeats,
|
|
441
810
|
};
|
|
442
811
|
export function isSettableSettingKey(key) {
|
|
443
812
|
return Object.prototype.hasOwnProperty.call(SETTABLE_KEYS, key);
|
|
444
813
|
}
|
|
814
|
+
/** Unwraps optional/default/nullable wrappers down to the value schema. */
|
|
815
|
+
function settingLeaf(schema) {
|
|
816
|
+
let current = schema;
|
|
817
|
+
for (let depth = 0; depth < 8; depth++) {
|
|
818
|
+
const type = current.def?.type;
|
|
819
|
+
if ((type === "optional" || type === "default" || type === "nullable") &&
|
|
820
|
+
current.def?.innerType)
|
|
821
|
+
current = current.def.innerType;
|
|
822
|
+
else
|
|
823
|
+
break;
|
|
824
|
+
}
|
|
825
|
+
return current;
|
|
826
|
+
}
|
|
827
|
+
/** Every settable key with its value kind (and enum options), for settings editors. */
|
|
828
|
+
export function settableSettings() {
|
|
829
|
+
return Object.keys(SETTABLE_KEYS).map((key) => {
|
|
830
|
+
const leaf = settingLeaf(SETTABLE_KEYS[key]);
|
|
831
|
+
const type = leaf.def?.type;
|
|
832
|
+
if (type === "enum")
|
|
833
|
+
return { key, kind: "enum", options: (leaf.options ?? []).map((o) => String(o)) };
|
|
834
|
+
if (type === "boolean")
|
|
835
|
+
return { key, kind: "boolean" };
|
|
836
|
+
if (type === "number" || type === "int")
|
|
837
|
+
return { key, kind: "number" };
|
|
838
|
+
return { key, kind: "string" };
|
|
839
|
+
});
|
|
840
|
+
}
|
|
445
841
|
/**
|
|
446
842
|
* Atomically sets one user-facing setting in the global config file (`<config home>/config.json`)
|
|
447
843
|
* while preserving every unrelated JSON field. The value is validated against the same zod leaf
|
|
@@ -467,11 +863,21 @@ export async function setConfigValue(input) {
|
|
|
467
863
|
throw new Error("Global Alisio configuration must be a JSON object");
|
|
468
864
|
raw = existing;
|
|
469
865
|
}
|
|
470
|
-
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
866
|
+
// Keys are `section.leaf` or `section.group.leaf`: every object on the path keeps its other fields.
|
|
867
|
+
const path = input.key.split(".");
|
|
868
|
+
const setPath = (target, depth) => {
|
|
869
|
+
const name = path[depth];
|
|
870
|
+
if (depth === path.length - 1)
|
|
871
|
+
return { ...target, [name]: parsed.data };
|
|
872
|
+
const child = target[name];
|
|
873
|
+
return {
|
|
874
|
+
...target,
|
|
875
|
+
[name]: setPath(child && typeof child === "object" && !Array.isArray(child)
|
|
876
|
+
? child
|
|
877
|
+
: {}, depth + 1),
|
|
878
|
+
};
|
|
879
|
+
};
|
|
880
|
+
raw = setPath(raw, 0);
|
|
475
881
|
raw.schemaVersion ??= 1;
|
|
476
882
|
await mkdir(dirname(file), { recursive: true, mode: 0o700 });
|
|
477
883
|
const temporary = `${file}.${process.pid}.${crypto.randomUUID()}.tmp`;
|
package/dist/core/compaction.js
CHANGED
|
@@ -116,6 +116,10 @@ function clampMessage(message, maxToolResultChars, maxTextChars) {
|
|
|
116
116
|
let used = 0;
|
|
117
117
|
let changed = false;
|
|
118
118
|
const content = message.result.content.map((part) => {
|
|
119
|
+
// Only the text projection is clipped: ui/image parts are display-only transcript data and
|
|
120
|
+
// are never truncated (raw bytes never reach the model, which only sees the projection).
|
|
121
|
+
if (part.type !== "text")
|
|
122
|
+
return part;
|
|
119
123
|
const room = maxToolResultChars - used;
|
|
120
124
|
const text = room <= 0
|
|
121
125
|
? TRUNCATION_MARKER
|
|
@@ -213,7 +217,8 @@ export function reduceMessagesToBudget(messages, targetChars, options = {}) {
|
|
|
213
217
|
: m.role === "assistant"
|
|
214
218
|
? m.text.length > textCap
|
|
215
219
|
: m.role === "tool" &&
|
|
216
|
-
m.result.content.reduce((a, p) => a + p.text.length, 0) >
|
|
220
|
+
m.result.content.reduce((a, p) => a + (p.type === "text" ? p.text.length : 0), 0) >
|
|
221
|
+
toolCap;
|
|
217
222
|
if (over) {
|
|
218
223
|
best = i;
|
|
219
224
|
bestSize = current;
|
|
@@ -260,7 +265,12 @@ export function serializeForSummary(messages, maxItemChars = 4_000) {
|
|
|
260
265
|
lines.push(`TOOL CALL ${c.id} ${c.name}: ${clip(c.arguments, maxItemChars)}`);
|
|
261
266
|
}
|
|
262
267
|
else {
|
|
263
|
-
|
|
268
|
+
// Only the text projection is summarized: ui/image parts are display data and never
|
|
269
|
+
// reach the summarizer (raw image bytes in particular stay out of the checkpoint).
|
|
270
|
+
const text = m.result.content
|
|
271
|
+
.filter((p) => p.type === "text")
|
|
272
|
+
.map((c) => c.text)
|
|
273
|
+
.join("\n");
|
|
264
274
|
lines.push(`TOOL RESULT ${m.callId}${m.result.isError ? " (error)" : ""}: ${clip(text, maxItemChars)}`);
|
|
265
275
|
}
|
|
266
276
|
}
|
|
@@ -381,6 +391,7 @@ async function completeTextWithMeta(provider, request) {
|
|
|
381
391
|
signal: request.signal,
|
|
382
392
|
...(request.model ? { model: request.model } : {}),
|
|
383
393
|
...(request.sessionId ? { sessionId: request.sessionId } : {}),
|
|
394
|
+
...(request.reasoningEffort ? { reasoningEffort: request.reasoningEffort } : {}),
|
|
384
395
|
})) {
|
|
385
396
|
request.signal.throwIfAborted();
|
|
386
397
|
if (event.type === "completed") {
|