@wirecat/cli-core 0.421.0 → 0.423.0
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/CHANGELOG.md +29 -1
- package/dist/analysis/settings.d.ts +0 -6
- package/dist/analysis/settings.js +2 -5
- package/dist/cli/analysis-choice.d.ts +0 -1
- package/dist/cli/analysis-choice.js +9 -22
- package/dist/cli/bot/context.js +1 -1
- package/dist/cli/commands-command.js +1 -1
- package/dist/cli/config-command.d.ts +0 -4
- package/dist/cli/config-command.js +36 -26
- package/dist/cli/config-issues.d.ts +52 -0
- package/dist/cli/config-issues.js +187 -0
- package/dist/cli/config-keys.js +4 -28
- package/dist/cli/embedding-choice.d.ts +1 -2
- package/dist/cli/embedding-choice.js +2 -4
- package/dist/cli/first-run.d.ts +0 -16
- package/dist/cli/first-run.js +1 -6
- package/dist/cli/index.d.ts +3 -1
- package/dist/cli/index.js +2 -1
- package/dist/cli/messenger/context.js +1 -1
- package/dist/cli/messenger/conversations-command.js +5 -9
- package/dist/cli/messenger/doctor-command.js +38 -4
- package/dist/cli/messenger/inbox.js +2 -6
- package/dist/cli/messenger/private-people-command.js +1 -2
- package/dist/cli/messenger/review.js +2 -5
- package/dist/cli/permission-keys.d.ts +9 -2
- package/dist/cli/permission-keys.js +21 -6
- package/dist/cli/preview.d.ts +3 -2
- package/dist/cli/preview.js +4 -3
- package/dist/cli/profile.d.ts +2 -0
- package/dist/cli/profile.js +10 -0
- package/dist/cli/program.d.ts +1 -1
- package/dist/cli/program.js +18 -10
- package/dist/cli/settings.d.ts +21 -117
- package/dist/cli/settings.js +107 -114
- package/dist/cli/shared-command-exports.d.ts +4 -232
- package/dist/mcp/surface.js +9 -3
- package/dist/meetings/mcp/index.d.ts +15 -15
- package/dist/models/settings.d.ts +1 -7
- package/dist/models/settings.js +1 -18
- package/dist/ports/app.d.ts +6 -0
- package/dist/search/account-list.js +8 -7
- package/dist/search/dictionary.d.ts +3 -6
- package/dist/search/dictionary.js +2 -1
- package/dist/search/languages.d.ts +28 -0
- package/dist/search/languages.js +7 -0
- package/dist/search/stem.d.ts +5 -4
- package/dist/search/stem.js +3 -2
- package/package.json +1 -1
package/dist/cli/settings.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as v from "valibot";
|
|
|
2
2
|
import { type AISettings } from "../analysis/settings.js";
|
|
3
3
|
import { type AppIdentity } from "../ports/app.js";
|
|
4
4
|
import { type Level, type PermissionKey } from "../sends/permissions.js";
|
|
5
|
+
import { type ConfigIssue } from "./config-issues.js";
|
|
5
6
|
export declare const plain: (rule: string) => (issue: v.BaseIssue<unknown>) => string;
|
|
6
7
|
export declare const count: v.SchemaWithPipe<readonly [v.NumberSchema<(issue: v.BaseIssue<unknown>) => string>, v.IntegerAction<number, (issue: v.BaseIssue<unknown>) => string>, v.MinValueAction<number, 1, (issue: v.BaseIssue<unknown>) => string>]>;
|
|
7
8
|
export declare const flag: v.BooleanSchema<(issue: v.BaseIssue<unknown>) => string>;
|
|
@@ -41,7 +42,6 @@ interface KindSection {
|
|
|
41
42
|
profiles?: Record<string, Scope>;
|
|
42
43
|
}
|
|
43
44
|
export interface Config {
|
|
44
|
-
default_profile?: string;
|
|
45
45
|
defaults?: Scope;
|
|
46
46
|
profiles: Record<string, Scope>;
|
|
47
47
|
personal?: KindSection;
|
|
@@ -127,6 +127,19 @@ export interface Settings extends AISettings {
|
|
|
127
127
|
/** This profile's entries and the shared defaults, for an adapter resolving its own fields with `first`. */
|
|
128
128
|
configured: Scope;
|
|
129
129
|
shared: Scope;
|
|
130
|
+
/**
|
|
131
|
+
* What is wrong in the file; empty unless resolved `withIssues`, which leaves those settings out. Optional for an
|
|
132
|
+
* app that builds `Settings` from a file of its own.
|
|
133
|
+
*/
|
|
134
|
+
configIssues?: ConfigIssue[];
|
|
135
|
+
/**
|
|
136
|
+
* Every permission key saved anywhere in the file, for the program to check against its commands. An app that
|
|
137
|
+
* builds `Settings` itself leaves it out, and only the keys in force are checked.
|
|
138
|
+
*/
|
|
139
|
+
savedPermissions?: {
|
|
140
|
+
key: PermissionKey;
|
|
141
|
+
at: string[];
|
|
142
|
+
}[];
|
|
130
143
|
}
|
|
131
144
|
export interface ResolveOptions {
|
|
132
145
|
env?: NodeJS.ProcessEnv;
|
|
@@ -140,6 +153,11 @@ export interface ResolveOptions {
|
|
|
140
153
|
needsProfile?: boolean;
|
|
141
154
|
/** Read the config file without writing it: no default file. For a dry run. */
|
|
142
155
|
readOnly?: boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Load what is valid and report the rest in `configIssues`, rather than refuse: for `doctor`, which reports,
|
|
158
|
+
* and `config`, which repairs. Invalid JSON loads as an empty file.
|
|
159
|
+
*/
|
|
160
|
+
withIssues?: boolean;
|
|
143
161
|
}
|
|
144
162
|
/** Where `profile` came from when none was named and the command needs none. */
|
|
145
163
|
export declare const NONE_NAMED = "none named";
|
|
@@ -161,25 +179,22 @@ export declare const fromFile: <T>(settings: Pick<Settings, "configured" | "shar
|
|
|
161
179
|
export declare const settingsFor: <T extends object = Record<never, never>>(app: AppIdentity, extension?: SettingsExtension<T>) => {
|
|
162
180
|
resolveSettings: (flags?: GlobalFlags, options?: ResolveOptions) => Settings & T;
|
|
163
181
|
configuredProfiles: (options?: ResolveOptions) => string[];
|
|
164
|
-
changeSetting: (path: string, { profile, setting, value, kind, }: {
|
|
182
|
+
changeSetting: (path: string, { profile, setting, value, kind, root, }: {
|
|
165
183
|
profile: string | undefined;
|
|
166
184
|
setting: string;
|
|
167
185
|
value: string | undefined;
|
|
168
186
|
kind?: ProfileKind | undefined;
|
|
187
|
+
root?: boolean;
|
|
169
188
|
}) => unknown;
|
|
170
189
|
allSettings: string[];
|
|
171
190
|
defaultsOnlyKeys: string[];
|
|
172
191
|
schema: v.StrictObjectSchema<{
|
|
173
|
-
default_profile: v.OptionalSchema<v.StringSchema<(issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
174
192
|
defaults: v.OptionalSchema<v.StrictObjectSchema<{
|
|
175
193
|
embedding_provider: ({
|
|
176
194
|
embeddingProvider: v.OptionalSchema<v.PicklistSchema<["local", "openai"], undefined>, undefined>;
|
|
177
195
|
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
178
196
|
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
179
197
|
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
180
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
181
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
182
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
183
198
|
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
184
199
|
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
185
200
|
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
@@ -191,9 +206,6 @@ export declare const settingsFor: <T extends object = Record<never, never>>(app:
|
|
|
191
206
|
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
192
207
|
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
193
208
|
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
194
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
195
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
196
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
197
209
|
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
198
210
|
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
199
211
|
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
@@ -205,9 +217,6 @@ export declare const settingsFor: <T extends object = Record<never, never>>(app:
|
|
|
205
217
|
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
206
218
|
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
207
219
|
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
208
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
209
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
210
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
211
220
|
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
212
221
|
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
213
222
|
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
@@ -219,65 +228,17 @@ export declare const settingsFor: <T extends object = Record<never, never>>(app:
|
|
|
219
228
|
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
220
229
|
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
221
230
|
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
222
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
223
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
224
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
225
231
|
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
226
232
|
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
227
233
|
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
228
234
|
readonly base_url: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
229
235
|
}, undefined>, undefined>, undefined>;
|
|
230
236
|
})["embeddingDims"];
|
|
231
|
-
analysis_provider: ({
|
|
232
|
-
embeddingProvider: v.OptionalSchema<v.PicklistSchema<["local", "openai"], undefined>, undefined>;
|
|
233
|
-
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
234
|
-
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
235
|
-
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
236
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
237
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
238
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
239
|
-
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
240
|
-
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
241
|
-
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
242
|
-
readonly base_url: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
243
|
-
}, undefined>, undefined>, undefined>;
|
|
244
|
-
})["analysisProvider"];
|
|
245
|
-
analysis_model: ({
|
|
246
|
-
embeddingProvider: v.OptionalSchema<v.PicklistSchema<["local", "openai"], undefined>, undefined>;
|
|
247
|
-
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
248
|
-
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
249
|
-
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
250
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
251
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
252
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
253
|
-
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
254
|
-
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
255
|
-
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
256
|
-
readonly base_url: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
257
|
-
}, undefined>, undefined>, undefined>;
|
|
258
|
-
})["analysisModel"];
|
|
259
|
-
analysis_base_url: ({
|
|
260
|
-
embeddingProvider: v.OptionalSchema<v.PicklistSchema<["local", "openai"], undefined>, undefined>;
|
|
261
|
-
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
262
|
-
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
263
|
-
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
264
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
265
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
266
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
267
|
-
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
268
|
-
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
269
|
-
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
270
|
-
readonly base_url: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
271
|
-
}, undefined>, undefined>, undefined>;
|
|
272
|
-
})["analysisBaseUrl"];
|
|
273
237
|
models: ({
|
|
274
238
|
embeddingProvider: v.OptionalSchema<v.PicklistSchema<["local", "openai"], undefined>, undefined>;
|
|
275
239
|
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
276
240
|
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
277
241
|
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
278
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
279
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
280
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
281
242
|
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
282
243
|
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
283
244
|
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
@@ -306,9 +267,6 @@ export declare const settingsFor: <T extends object = Record<never, never>>(app:
|
|
|
306
267
|
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
307
268
|
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
308
269
|
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
309
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
310
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
311
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
312
270
|
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
313
271
|
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
314
272
|
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
@@ -320,9 +278,6 @@ export declare const settingsFor: <T extends object = Record<never, never>>(app:
|
|
|
320
278
|
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
321
279
|
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
322
280
|
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
323
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
324
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
325
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
326
281
|
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
327
282
|
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
328
283
|
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
@@ -334,9 +289,6 @@ export declare const settingsFor: <T extends object = Record<never, never>>(app:
|
|
|
334
289
|
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
335
290
|
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
336
291
|
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
337
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
338
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
339
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
340
292
|
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
341
293
|
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
342
294
|
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
@@ -348,65 +300,17 @@ export declare const settingsFor: <T extends object = Record<never, never>>(app:
|
|
|
348
300
|
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
349
301
|
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
350
302
|
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
351
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
352
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
353
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
354
303
|
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
355
304
|
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
356
305
|
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
357
306
|
readonly base_url: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
358
307
|
}, undefined>, undefined>, undefined>;
|
|
359
308
|
})["embeddingDims"];
|
|
360
|
-
analysis_provider: ({
|
|
361
|
-
embeddingProvider: v.OptionalSchema<v.PicklistSchema<["local", "openai"], undefined>, undefined>;
|
|
362
|
-
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
363
|
-
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
364
|
-
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
365
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
366
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
367
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
368
|
-
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
369
|
-
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
370
|
-
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
371
|
-
readonly base_url: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
372
|
-
}, undefined>, undefined>, undefined>;
|
|
373
|
-
})["analysisProvider"];
|
|
374
|
-
analysis_model: ({
|
|
375
|
-
embeddingProvider: v.OptionalSchema<v.PicklistSchema<["local", "openai"], undefined>, undefined>;
|
|
376
|
-
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
377
|
-
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
378
|
-
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
379
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
380
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
381
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
382
|
-
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
383
|
-
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
384
|
-
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
385
|
-
readonly base_url: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
386
|
-
}, undefined>, undefined>, undefined>;
|
|
387
|
-
})["analysisModel"];
|
|
388
|
-
analysis_base_url: ({
|
|
389
|
-
embeddingProvider: v.OptionalSchema<v.PicklistSchema<["local", "openai"], undefined>, undefined>;
|
|
390
|
-
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
391
|
-
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
392
|
-
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
393
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
394
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
395
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
396
|
-
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
397
|
-
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
398
|
-
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
399
|
-
readonly base_url: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
400
|
-
}, undefined>, undefined>, undefined>;
|
|
401
|
-
})["analysisBaseUrl"];
|
|
402
309
|
models: ({
|
|
403
310
|
embeddingProvider: v.OptionalSchema<v.PicklistSchema<["local", "openai"], undefined>, undefined>;
|
|
404
311
|
embeddingModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
405
312
|
embeddingBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
406
313
|
embeddingDims: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 65536, undefined>]>, undefined>;
|
|
407
|
-
analysisProvider: v.OptionalSchema<v.PicklistSchema<["agent", "openai", "anthropic"], undefined>, undefined>;
|
|
408
|
-
analysisModel: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
409
|
-
analysisBaseUrl: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "use an HTTP/S endpoint without credentials, query or fragment">]>, undefined>;
|
|
410
314
|
models: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, v.StrictObjectSchema<{
|
|
411
315
|
readonly provider: v.OptionalSchema<v.PicklistSchema<["off", "openai", "anthropic"], undefined>, undefined>;
|
|
412
316
|
readonly model: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
package/dist/cli/settings.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { CliError, configFilePath, resolvePaths, saveConfigFile } from "@wirecat/cli-base";
|
|
3
3
|
import * as v from "valibot";
|
|
4
4
|
import { AI_ENTRIES, resolveAISettings } from "../analysis/settings.js";
|
|
@@ -7,7 +7,7 @@ import { envName, readOnlyLockOf } from "../ports/app.js";
|
|
|
7
7
|
import { assertOverridesTighten, CEILING_KEY, LEVELS, layerPermissions, permissionOverrides, RESOURCES, } from "../sends/permissions.js";
|
|
8
8
|
import { storePath } from "../store/path.js";
|
|
9
9
|
import { sharedConfigPath } from "../store/shared-config.js";
|
|
10
|
-
import {
|
|
10
|
+
import { issueMessage, parseConfigText, publicIssue, savedPermissionKeys, schemaIssues, withoutIssues, } from "./config-issues.js";
|
|
11
11
|
import { DEFAULT_CONFIG, ensureDefaultConfig } from "./default-config.js";
|
|
12
12
|
import { profilesHere } from "./messenger/accounts.js";
|
|
13
13
|
import { usableProfileName } from "./profile.js";
|
|
@@ -108,7 +108,6 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
108
108
|
profiles: v.optional(v.record(v.string(), strictOf(entries), "has to be an object of profiles, by name")),
|
|
109
109
|
}, objectMessage);
|
|
110
110
|
const configEntries = {
|
|
111
|
-
default_profile: v.optional(v.string(plain("has to be a profile name, in quotes"))),
|
|
112
111
|
defaults: v.optional(strictOf(defaultsEntries)),
|
|
113
112
|
profiles: v.optional(v.record(v.string(), strictOf(profileEntries), "has to be an object of profiles, by name"), {}),
|
|
114
113
|
personal: v.optional(kindSection(profileEntries)),
|
|
@@ -117,22 +116,35 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
117
116
|
const schema = strictOf(configEntries);
|
|
118
117
|
const defaultsOnlyKeys = Object.keys(defaultsOnly);
|
|
119
118
|
const botOnlyKeys = Object.keys(BOT_ONLY_ENTRIES);
|
|
120
|
-
const allSettings = [...Object.keys(profileEntries), ...botOnlyKeys, ...defaultsOnlyKeys
|
|
119
|
+
const allSettings = [...Object.keys(profileEntries), ...botOnlyKeys, ...defaultsOnlyKeys];
|
|
121
120
|
const PROFILE = envName(app, "PROFILE");
|
|
122
121
|
const PROFILE_LOCK = envName(app, "PROFILE_LOCK");
|
|
123
122
|
const TIMEOUT = envName(app, "TIMEOUT");
|
|
124
123
|
const REQUESTS_PER_MINUTE = envName(app, "REQUESTS_PER_MINUTE");
|
|
125
124
|
const configPathFor = ({ env = process.env, configDir }) => configFilePath(configDir ?? resolvePaths({ appName: app.appName, prefix: app.envPrefix, env }).config);
|
|
126
|
-
const
|
|
125
|
+
const readSchema = extension.schema ?? schema;
|
|
126
|
+
const context = (file) => ({ file, tool: app.command });
|
|
127
|
+
/** The file as written, `undefined` when there is none, or the issue that says it is not JSON. */
|
|
128
|
+
const readRaw = (path) => {
|
|
129
|
+
let text;
|
|
127
130
|
try {
|
|
128
|
-
|
|
131
|
+
text = readFileSync(path, "utf8");
|
|
129
132
|
}
|
|
130
|
-
catch
|
|
131
|
-
|
|
132
|
-
throw new CliError("configuration_error", message.includes("catch_up_marks_read")
|
|
133
|
-
? `${message}; remove catch_up_marks_read from the config file and use ${app.command} <profile> chats mark-read <chat>`
|
|
134
|
-
: message);
|
|
133
|
+
catch {
|
|
134
|
+
return { raw: undefined };
|
|
135
135
|
}
|
|
136
|
+
return parseConfigText(text, path);
|
|
137
|
+
};
|
|
138
|
+
/** The file with every problem found; what loads is the file without the settings they name. */
|
|
139
|
+
const loadConfig = (path) => {
|
|
140
|
+
const read = readRaw(path);
|
|
141
|
+
if ("issue" in read)
|
|
142
|
+
return { config: { profiles: {} }, issues: [read.issue], raw: undefined };
|
|
143
|
+
if (read.raw === undefined)
|
|
144
|
+
return { config: { profiles: {} }, issues: [], raw: undefined };
|
|
145
|
+
const issues = schemaIssues(read.raw, readSchema, context(path));
|
|
146
|
+
const parsed = v.safeParse(readSchema, withoutIssues(read.raw, issues));
|
|
147
|
+
return { config: (parsed.success ? parsed.output : { profiles: {} }), issues, raw: read.raw };
|
|
136
148
|
};
|
|
137
149
|
/**
|
|
138
150
|
* A lock pins a process to one profile: the owner sets it where an agent runs, and a first word
|
|
@@ -157,10 +169,6 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
157
169
|
const unnamed = (config, env, needed) => {
|
|
158
170
|
if (!needed)
|
|
159
171
|
return { value: NO_PROFILE, from: NONE_NAMED };
|
|
160
|
-
if (config.default_profile !== undefined) {
|
|
161
|
-
throw new CliError("validation_error", `default_profile is no longer read — name the profile: \`${app.command} ${config.default_profile} …\`; ` +
|
|
162
|
-
`\`${app.command} config unset default_profile\` removes it from the config file`, { profiles: profilesOf(config, env) });
|
|
163
|
-
}
|
|
164
172
|
const here = profilesOf(config, env);
|
|
165
173
|
throw new CliError("validation_error", here.length === 0
|
|
166
174
|
? `name a profile: there is none on this computer yet — create one with \`${app.command} personal setup\` ` +
|
|
@@ -178,7 +186,10 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
178
186
|
catch (error) {
|
|
179
187
|
throw new CliError("configuration_error", error instanceof Error ? error.message : String(error));
|
|
180
188
|
}
|
|
181
|
-
const
|
|
189
|
+
const loaded = loadConfig(configPath);
|
|
190
|
+
if (loaded.issues.length > 0 && !options.withIssues)
|
|
191
|
+
throw new CliError("configuration_error", issueMessage(loaded.issues.map(publicIssue)));
|
|
192
|
+
const { config } = loaded;
|
|
182
193
|
const lock = given(env[PROFILE_LOCK]);
|
|
183
194
|
const named = first([
|
|
184
195
|
["first word", flags.profile],
|
|
@@ -202,9 +213,6 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
202
213
|
[extension.sourcePaths ? "config file: defaults" : "config defaults", shared],
|
|
203
214
|
];
|
|
204
215
|
const fromLayers = (key, fallback, only = layers) => first(only.map(([from, scope]) => [from, scope?.[key]]), fallback);
|
|
205
|
-
if (fromLayers("catch_up_marks_read", undefined).value !== undefined) {
|
|
206
|
-
throw new CliError("configuration_error", `remove catch_up_marks_read from the config file and use ${app.command} <profile> chats mark-read <chat>`);
|
|
207
|
-
}
|
|
208
216
|
const kindLayers = layers.filter(([from]) => from.startsWith(`config file: ${kind}.`));
|
|
209
217
|
const limit = flags.limit === undefined ? fromLayers("limit", DEFAULT_LIMIT) : { value: flags.limit, from: "flag" };
|
|
210
218
|
const record = flags.record === undefined ? fromLayers("record", false) : { value: flags.record, from: "flag" };
|
|
@@ -303,6 +311,8 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
303
311
|
},
|
|
304
312
|
configured,
|
|
305
313
|
shared,
|
|
314
|
+
configIssues: loaded.issues.map(publicIssue),
|
|
315
|
+
savedPermissions: savedPermissionKeys(config),
|
|
306
316
|
};
|
|
307
317
|
// The file was checked by the schema; a flag was not, and `--limit abc` is `NaN` by the time it
|
|
308
318
|
// gets here, which slices an array to nothing without complaining.
|
|
@@ -319,16 +329,52 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
319
329
|
const extra = extension.resolve?.({ flags, settings, layers, fromLayers });
|
|
320
330
|
return { ...settings, ...extra?.values, sources: { ...settings.sources, ...extra?.sources } };
|
|
321
331
|
};
|
|
322
|
-
const configuredProfiles = (options = {}) =>
|
|
323
|
-
|
|
324
|
-
|
|
332
|
+
const configuredProfiles = (options = {}) => {
|
|
333
|
+
const { config, issues } = loadConfig(configPathFor(options));
|
|
334
|
+
if (issues.length > 0 && !options.withIssues)
|
|
335
|
+
throw new CliError("configuration_error", issueMessage(issues.map(publicIssue)));
|
|
336
|
+
return namedProfiles(config);
|
|
337
|
+
};
|
|
338
|
+
/**
|
|
339
|
+
* `config set` and `config unset`, on the file as written, so they also run on a file with problems. A set is
|
|
340
|
+
* refused only for a problem it would add; an unset removes the setting whether or not the schema knows it.
|
|
341
|
+
* `root` reaches a path outside any profile or `defaults`, and only one that has a problem.
|
|
342
|
+
*/
|
|
343
|
+
const changeSetting = (path, { profile, setting, value, kind, root = false, }) => {
|
|
325
344
|
const [name = setting, ...rest] = setting.split(".");
|
|
326
345
|
const level = name === "permissions" && rest.length > 0 ? rest.join(".") : undefined;
|
|
327
346
|
const modelField = /^models\.([a-z][a-z0-9-]*)\.(provider|model|base_url)$/.exec(setting);
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
347
|
+
const known = allSettings.includes(setting) || level !== undefined || modelField !== null;
|
|
348
|
+
const read = readRaw(path);
|
|
349
|
+
if ("issue" in read)
|
|
350
|
+
throw new CliError("configuration_error", issueMessage([publicIssue(read.issue)]));
|
|
351
|
+
const raw = read.raw === undefined ? {} : read.raw;
|
|
352
|
+
if (!isScope(raw))
|
|
353
|
+
throw new CliError("configuration_error", `${path}: the file has to be an object, in braces`);
|
|
354
|
+
const scopePath = root
|
|
355
|
+
? []
|
|
356
|
+
: [...(kind === undefined ? [] : [kind]), ...(profile === undefined ? ["defaults"] : ["profiles", profile])];
|
|
357
|
+
const keyPath = root
|
|
358
|
+
? setting.split(".")
|
|
359
|
+
: level !== undefined
|
|
360
|
+
? ["permissions", level]
|
|
361
|
+
: modelField
|
|
362
|
+
? ["models", modelField[1], modelField[2]]
|
|
363
|
+
: [setting];
|
|
364
|
+
const at = [...scopePath, ...keyPath];
|
|
365
|
+
const before = schemaIssues(raw, readSchema, context(path));
|
|
366
|
+
if (value === undefined) {
|
|
367
|
+
if (root && !before.some((issue) => issue.at.join(".") === at.join(".")))
|
|
368
|
+
throw new CliError("validation_error", `${setting} has no problem to remove — name the profile, or add --defaults, to unset a setting`);
|
|
369
|
+
if (!known && valueAt(raw, at) === undefined)
|
|
370
|
+
throw new CliError("validation_error", `no setting called "${setting}" — one of: ${allSettings.join(", ")}`);
|
|
371
|
+
const changed = structuredClone(raw);
|
|
372
|
+
removeAt(changed, at);
|
|
373
|
+
saveConfigFile(path, changed);
|
|
374
|
+
return null;
|
|
331
375
|
}
|
|
376
|
+
if (!known)
|
|
377
|
+
throw new CliError("validation_error", `no setting called "${setting}" — one of: ${allSettings.join(", ")}`);
|
|
332
378
|
if (profile !== undefined && defaultsOnlyKeys.includes(setting)) {
|
|
333
379
|
throw new CliError("validation_error", `${setting} is one setting for the whole program, not per profile — add --defaults`);
|
|
334
380
|
}
|
|
@@ -338,98 +384,45 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
338
384
|
if (kind !== "bot" && botOnlyKeys.includes(setting)) {
|
|
339
385
|
throw new CliError("validation_error", `${setting} is a bot's setting — add --bot`);
|
|
340
386
|
}
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
saveConfigFile(path, rest);
|
|
351
|
-
return null;
|
|
352
|
-
}
|
|
353
|
-
const section = kind === undefined ? undefined : (config[kind] ?? {});
|
|
354
|
-
const current = section === undefined
|
|
355
|
-
? profile === undefined
|
|
356
|
-
? config.defaults
|
|
357
|
-
: config.profiles[profile]
|
|
358
|
-
: profile === undefined
|
|
359
|
-
? section.defaults
|
|
360
|
-
: section.profiles?.[profile];
|
|
361
|
-
const scope = { ...current };
|
|
362
|
-
if (modelField) {
|
|
363
|
-
const purpose = modelField[1];
|
|
364
|
-
const field = modelField[2];
|
|
365
|
-
const models = { ...scope.models };
|
|
366
|
-
const target = { ...models[purpose] };
|
|
367
|
-
if (value === undefined)
|
|
368
|
-
delete target[field];
|
|
369
|
-
else
|
|
370
|
-
target[field] = parseValue(value);
|
|
371
|
-
if (Object.keys(target).length > 0)
|
|
372
|
-
models[purpose] = target;
|
|
373
|
-
else
|
|
374
|
-
delete models[purpose];
|
|
375
|
-
if (Object.keys(models).length > 0)
|
|
376
|
-
scope.models = models;
|
|
377
|
-
else
|
|
378
|
-
delete scope.models;
|
|
379
|
-
}
|
|
380
|
-
else if (level !== undefined) {
|
|
381
|
-
const levels = { ...scope.permissions };
|
|
382
|
-
if (value === undefined)
|
|
383
|
-
delete levels[level];
|
|
384
|
-
else
|
|
385
|
-
levels[level] = value.trim();
|
|
386
|
-
if (Object.keys(levels).length > 0)
|
|
387
|
-
scope.permissions = levels;
|
|
388
|
-
else
|
|
389
|
-
delete scope.permissions;
|
|
390
|
-
}
|
|
391
|
-
else if (value === undefined)
|
|
392
|
-
delete scope[setting];
|
|
393
|
-
else
|
|
394
|
-
scope[setting] = parseValue(value);
|
|
395
|
-
const empty = Object.keys(scope).length === 0;
|
|
396
|
-
let changed;
|
|
397
|
-
if (kind === undefined || section === undefined) {
|
|
398
|
-
changed =
|
|
399
|
-
profile === undefined
|
|
400
|
-
? { ...config, defaults: scope }
|
|
401
|
-
: { ...config, profiles: { ...config.profiles, [profile]: scope } };
|
|
402
|
-
if (profile === undefined && empty)
|
|
403
|
-
delete changed.defaults;
|
|
404
|
-
if (profile !== undefined && empty)
|
|
405
|
-
delete changed.profiles[profile];
|
|
406
|
-
}
|
|
407
|
-
else {
|
|
408
|
-
const next = profile === undefined
|
|
409
|
-
? { ...section, defaults: scope }
|
|
410
|
-
: { ...section, profiles: { ...section.profiles, [profile]: scope } };
|
|
411
|
-
if (profile === undefined && empty)
|
|
412
|
-
delete next.defaults;
|
|
413
|
-
if (profile !== undefined && empty && next.profiles)
|
|
414
|
-
delete next.profiles[profile];
|
|
415
|
-
if (next.profiles && Object.keys(next.profiles).length === 0)
|
|
416
|
-
delete next.profiles;
|
|
417
|
-
changed = { ...config, [kind]: next };
|
|
418
|
-
if (Object.keys(next).length === 0)
|
|
419
|
-
delete changed[kind];
|
|
420
|
-
}
|
|
421
|
-
const checked = v.safeParse(extension.schema ?? schema, changed);
|
|
422
|
-
if (!checked.success) {
|
|
423
|
-
throw new CliError("validation_error", `${setting} cannot be "${value}": ${checked.issues[0]?.message ?? "invalid"}`);
|
|
424
|
-
}
|
|
425
|
-
saveConfigFile(path, checked.output);
|
|
426
|
-
if (modelField)
|
|
427
|
-
return (scope.models?.[modelField[1]]?.[modelField[2]] ??
|
|
428
|
-
null);
|
|
429
|
-
return level === undefined ? (scope[setting] ?? null) : (scope.permissions?.[level] ?? null);
|
|
387
|
+
const changed = structuredClone(raw);
|
|
388
|
+
setAt(changed, at, level === undefined ? parseValue(value) : value.trim());
|
|
389
|
+
const had = new Set(before.map((issue) => issue.at.join(".")));
|
|
390
|
+
const added = schemaIssues(changed, readSchema, context(path)).find((issue) => !had.has(issue.at.join(".")) || issue.at.join(".") === at.join("."));
|
|
391
|
+
if (added)
|
|
392
|
+
throw new CliError("validation_error", `${setting} cannot be "${value}": ${added.what}`);
|
|
393
|
+
const checked = v.safeParse(readSchema, changed);
|
|
394
|
+
saveConfigFile(path, checked.success ? checked.output : changed);
|
|
395
|
+
return valueAt(checked.success ? checked.output : changed, at) ?? null;
|
|
430
396
|
};
|
|
431
397
|
return { resolveSettings, configuredProfiles, changeSetting, allSettings, defaultsOnlyKeys, schema };
|
|
432
398
|
};
|
|
399
|
+
const isScope = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
400
|
+
const valueAt = (node, path) => path.reduce((at, key) => (isScope(at) ? at[key] : undefined), node);
|
|
401
|
+
const setAt = (node, path, value) => {
|
|
402
|
+
let at = node;
|
|
403
|
+
for (const key of path.slice(0, -1)) {
|
|
404
|
+
if (!isScope(at[key]))
|
|
405
|
+
at[key] = {};
|
|
406
|
+
at = at[key];
|
|
407
|
+
}
|
|
408
|
+
at[path.at(-1)] = value;
|
|
409
|
+
};
|
|
410
|
+
/** Removes the value and every section it leaves empty, so an unset leaves no `{}` behind. */
|
|
411
|
+
const removeAt = (node, path) => {
|
|
412
|
+
const [key, ...rest] = path;
|
|
413
|
+
if (key === undefined)
|
|
414
|
+
return;
|
|
415
|
+
if (rest.length === 0) {
|
|
416
|
+
delete node[key];
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
const child = node[key];
|
|
420
|
+
if (!isScope(child))
|
|
421
|
+
return;
|
|
422
|
+
removeAt(child, rest);
|
|
423
|
+
if (Object.keys(child).length === 0)
|
|
424
|
+
delete node[key];
|
|
425
|
+
};
|
|
433
426
|
/** Every profile the file names, in any section. */
|
|
434
427
|
const namedProfiles = (config) => [
|
|
435
428
|
...new Set([
|