@wirecat/cli-core 0.544.0 → 0.546.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 +88 -0
- package/dist/calendar/busy.js +4 -1
- package/dist/calendar/cli/answers.d.ts +31 -0
- package/dist/calendar/cli/answers.js +8 -0
- package/dist/calendar/cli/index.d.ts +6 -0
- package/dist/calendar/cli/index.js +43 -4
- package/dist/calendar/cli/remind.js +2 -1
- package/dist/calendar/expand.d.ts +17 -0
- package/dist/calendar/expand.js +340 -0
- package/dist/calendar/feeds.d.ts +96 -0
- package/dist/calendar/feeds.js +324 -0
- package/dist/calendar/ics.d.ts +15 -4
- package/dist/calendar/ics.js +18 -7
- package/dist/calendar/index.d.ts +3 -1
- package/dist/calendar/index.js +2 -0
- package/dist/calendar/server-search.js +3 -1
- package/dist/calendar/writes.js +15 -4
- package/dist/cli/after-dashes.d.ts +16 -0
- package/dist/cli/after-dashes.js +41 -0
- package/dist/cli/bot/context.d.ts +1 -1
- package/dist/cli/bot/context.js +9 -1
- package/dist/cli/bot/messages.js +2 -0
- package/dist/cli/bot/setup.js +1 -0
- package/dist/cli/contract-templates.js +2 -2
- package/dist/cli/entry.d.ts +2 -0
- package/dist/cli/entry.js +3 -2
- package/dist/cli/index.d.ts +2 -1
- package/dist/cli/index.js +2 -1
- package/dist/cli/messenger/admin-commands.js +5 -1
- package/dist/cli/messenger/admin-contacts-command.js +5 -1
- package/dist/cli/messenger/admin-folders-command.js +5 -1
- package/dist/cli/messenger/archive-commands.js +20 -2
- package/dist/cli/messenger/backfill-command.js +13 -2
- package/dist/cli/messenger/complete-command.js +1 -0
- package/dist/cli/messenger/context.js +3 -0
- package/dist/cli/messenger/history-gaps.d.ts +12 -0
- package/dist/cli/messenger/history-gaps.js +41 -0
- package/dist/cli/messenger/messages-command.js +9 -22
- package/dist/cli/messenger/messages-edit-command.js +1 -0
- package/dist/cli/messenger/messages-press-command.js +1 -0
- package/dist/cli/messenger/messages-search-command.js +5 -1
- package/dist/cli/messenger/messages-send-command.js +1 -0
- package/dist/cli/messenger/observed.js +2 -2
- package/dist/cli/messenger/polls-command.js +1 -0
- package/dist/cli/messenger/private-people-command.js +5 -1
- package/dist/cli/messenger/search-answers.d.ts +3 -2
- package/dist/cli/messenger/search-answers.js +12 -5
- package/dist/cli/messenger/search-command.js +3 -1
- package/dist/cli/messenger/stored.d.ts +6 -1
- package/dist/cli/messenger/stored.js +94 -5
- package/dist/cli/messenger/topics-command.js +1 -1
- package/dist/cli/program.js +17 -6
- package/dist/cli/schedule/schedule-command.js +1 -0
- package/dist/cli/settings.d.ts +9 -0
- package/dist/cli/settings.js +20 -0
- package/dist/cli/shared-command-exports.d.ts +24 -0
- package/dist/cli/steps.js +1 -0
- package/dist/domain/message-link.d.ts +3 -0
- package/dist/domain/message-link.js +9 -14
- package/dist/domain/money-words.d.ts +11 -0
- package/dist/domain/money-words.js +38 -0
- package/dist/domain/providers.d.ts +2 -0
- package/dist/domain/providers.js +15 -3
- package/dist/domain/ref-arguments.d.ts +31 -0
- package/dist/domain/ref-arguments.js +79 -0
- package/dist/domain/references.d.ts +20 -2
- package/dist/domain/references.js +132 -47
- package/dist/entities/index.d.ts +1 -0
- package/dist/entities/message-transfer.d.ts +4 -0
- package/dist/entities/message-transfer.js +2 -0
- package/dist/errors/reasons.js +18 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/meetings/mcp/index.d.ts +15 -15
- package/dist/oauth/client-file.d.ts +14 -0
- package/dist/oauth/client-file.js +28 -0
- package/dist/oauth/index.d.ts +1 -0
- package/dist/oauth/index.js +1 -0
- package/dist/ports/messenger.d.ts +3 -2
- package/dist/resolve.d.ts +3 -1
- package/dist/resolve.js +8 -0
- package/dist/search/task-signature.d.ts +5 -1
- package/dist/search/task-signature.js +27 -9
- package/dist/services/agenda.d.ts +5 -0
- package/dist/services/agenda.js +3 -1
- package/dist/services/history-limits.d.ts +45 -0
- package/dist/services/history-limits.js +50 -0
- package/dist/services/index.d.ts +5 -1
- package/dist/services/index.js +5 -1
- package/dist/services/message-resolution.d.ts +4 -1
- package/dist/services/message-resolution.js +19 -3
- package/dist/services/messages.js +15 -13
- package/dist/services/money-words.d.ts +3 -0
- package/dist/services/money-words.js +5 -0
- package/dist/services/questions.d.ts +7 -2
- package/dist/services/questions.js +13 -4
- package/dist/services/stored-project-gathering.d.ts +9 -0
- package/dist/services/stored-project-gathering.js +9 -4
- package/dist/services/task-categories.d.ts +2 -0
- package/dist/services/task-categories.js +19 -8
- package/dist/store/chats.d.ts +10 -0
- package/dist/store/chats.js +25 -0
- package/dist/store/sqlite/chats.js +2 -1
- package/dist/store/sqlite/evidence-sources.js +2 -2
- package/dist/store/sqlite/history-skips.d.ts +24 -0
- package/dist/store/sqlite/history-skips.js +95 -0
- package/dist/store/sqlite/identities.js +1 -1
- package/dist/store/sqlite/knowledge.js +7 -2
- package/dist/store/sqlite/notes.js +4 -4
- package/dist/store/sqlite/things.d.ts +0 -1
- package/dist/store/sqlite/things.js +25 -24
- package/dist/store/store.d.ts +1 -0
- package/package.json +1 -1
- package/parity.json +4 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
|
+
import { chatReferenceOf, ensureAccount } from "../../domain/ref-arguments.js";
|
|
2
3
|
import { capability, throughWrapper, } from "../../ports/messenger.js";
|
|
3
4
|
import { foldName, isId, pickPerson } from "../../resolve.js";
|
|
4
5
|
import { codeOf } from "../../sends/guarded.js";
|
|
5
|
-
import {
|
|
6
|
+
import { limitBatch } from "../../services/history-limits.js";
|
|
7
|
+
import { chatIdIn, profilesOnAccount } from "../../services/message-resolution.js";
|
|
6
8
|
const REKEY_PACING = { lockMs: 50, pauseMs: 25 };
|
|
7
9
|
/**
|
|
8
10
|
* The adapter, with what each read answers written to the store. **A failed write never fails the
|
|
@@ -12,8 +14,37 @@ const REKEY_PACING = { lockMs: 50, pauseMs: 25 };
|
|
|
12
14
|
* would erase what `chats list` stored. Nor are `chat` and `contact`: a card's member list is not
|
|
13
15
|
* known to be whole, and `saveMembers` replaces the list.
|
|
14
16
|
*/
|
|
15
|
-
export const stored = (messenger, { account, store, warn, events, pending, announcing, deletedWithoutChat, profile, rekeyed, rekeyPacing = REKEY_PACING, closing, namesFromStore, recipientIds, countsUnread = false, }) => {
|
|
17
|
+
export const stored = (messenger, { account, store, warn, events, pending, announcing, deletedWithoutChat, profile, rekeyed, rekeyPacing = REKEY_PACING, closing, namesFromStore, recipientIds, countsUnread = false, historyLimits, command = "cli", }) => {
|
|
16
18
|
let warned = false;
|
|
19
|
+
let limitedNoted = false;
|
|
20
|
+
const limited = async (opened, batch) => {
|
|
21
|
+
if (!historyLimits || !batch.messages?.length)
|
|
22
|
+
return { batch, skipped: new Map() };
|
|
23
|
+
const shapes = await opened.chats.historyShapes(account, [...new Set(batch.messages.map((one) => one.chatId))]);
|
|
24
|
+
return limitBatch(batch, (chatId) => shapes.get(chatId), (chatId) => shapes.get(chatId)?.included === true, historyLimits);
|
|
25
|
+
};
|
|
26
|
+
const noteLimited = (skipped) => {
|
|
27
|
+
if (skipped.size === 0)
|
|
28
|
+
return;
|
|
29
|
+
const counts = {
|
|
30
|
+
chats: skipped.size,
|
|
31
|
+
messages: 0,
|
|
32
|
+
group_too_large: 0,
|
|
33
|
+
older_than_window: 0,
|
|
34
|
+
};
|
|
35
|
+
for (const skip of skipped.values()) {
|
|
36
|
+
counts.messages = (counts.messages ?? 0) + skip.messages;
|
|
37
|
+
counts[skip.reason] = (counts[skip.reason] ?? 0) + 1;
|
|
38
|
+
}
|
|
39
|
+
const warning = { event: "warning", code: "history_limited", operation: "history.save", counts };
|
|
40
|
+
events(warning);
|
|
41
|
+
if (limitedNoted)
|
|
42
|
+
return;
|
|
43
|
+
limitedNoted = true;
|
|
44
|
+
warn(`history limits left out ${counts.messages} pushed messages of ${skipped.size} chats (big groups, older ` +
|
|
45
|
+
`than the window) — \`${command} store status\` lists them; \`${command} messages sync <chat> --full-history\` ` +
|
|
46
|
+
"fetches one and keeps it in full", warning);
|
|
47
|
+
};
|
|
17
48
|
let recorded = profile === undefined;
|
|
18
49
|
const notWritten = (operation, error) => {
|
|
19
50
|
const warning = { event: "warning", code: "store_not_written", operation };
|
|
@@ -155,7 +186,13 @@ export const stored = (messenger, { account, store, warn, events, pending, annou
|
|
|
155
186
|
// A refused re-key leaves its chat split, never the others or the batch's history unsaved.
|
|
156
187
|
const saving = previous.then(async () => {
|
|
157
188
|
await saveRekeys(rekeys, round);
|
|
158
|
-
return attempt(operation, (opened) =>
|
|
189
|
+
return attempt(operation, async (opened) => {
|
|
190
|
+
const { batch: kept, skipped } = await limited(opened, batch);
|
|
191
|
+
await fill(opened, account, kept);
|
|
192
|
+
if (skipped.size > 0)
|
|
193
|
+
await opened.chats.recordHistorySkips(account, skipped);
|
|
194
|
+
noteLimited(skipped);
|
|
195
|
+
});
|
|
159
196
|
});
|
|
160
197
|
previous = saving;
|
|
161
198
|
pending?.add(saving);
|
|
@@ -165,12 +202,12 @@ export const stored = (messenger, { account, store, warn, events, pending, annou
|
|
|
165
202
|
pending?.delete(saving);
|
|
166
203
|
rekeysOnly.delete(saving);
|
|
167
204
|
});
|
|
168
|
-
void onBatch(batch);
|
|
205
|
+
void onBatch(batch, saving);
|
|
169
206
|
return saving;
|
|
170
207
|
};
|
|
171
208
|
};
|
|
172
209
|
// A method not listed here saves nothing and passes through; a lane that should save adds its line.
|
|
173
|
-
|
|
210
|
+
const wrapped = throughWrapper(messenger, {
|
|
174
211
|
...(messenger.forumState
|
|
175
212
|
? {
|
|
176
213
|
forumState: async (chatId) => {
|
|
@@ -429,6 +466,58 @@ export const stored = (messenger, { account, store, warn, events, pending, annou
|
|
|
429
466
|
return sent;
|
|
430
467
|
},
|
|
431
468
|
});
|
|
469
|
+
const chatOf = async (typed) => {
|
|
470
|
+
const named = chatReferenceOf(typed, account.provider);
|
|
471
|
+
if (!named)
|
|
472
|
+
return typed;
|
|
473
|
+
let known;
|
|
474
|
+
try {
|
|
475
|
+
known = account.account;
|
|
476
|
+
}
|
|
477
|
+
catch { }
|
|
478
|
+
await ensureAccount(named, { account: known, ...(profile ? { profile: profile.name } : {}) }, async (other) => {
|
|
479
|
+
const opened = await store();
|
|
480
|
+
return opened && profilesOnAccount(opened, profile?.app, account.provider)(other);
|
|
481
|
+
});
|
|
482
|
+
return named.chat;
|
|
483
|
+
};
|
|
484
|
+
return withChatReferences(wrapped, chatOf);
|
|
485
|
+
};
|
|
486
|
+
/** The adapter methods whose first argument is a chat as typed: an id, a title, or a `chat:` or `msg:` reference. */
|
|
487
|
+
const TYPED_CHAT = [
|
|
488
|
+
"resolve",
|
|
489
|
+
"chat",
|
|
490
|
+
"history",
|
|
491
|
+
"around",
|
|
492
|
+
"historyAfter",
|
|
493
|
+
"historyBefore",
|
|
494
|
+
"historyFrom",
|
|
495
|
+
"topics",
|
|
496
|
+
"topic",
|
|
497
|
+
"topicHistory",
|
|
498
|
+
"download",
|
|
499
|
+
"transcribe",
|
|
500
|
+
"scheduled",
|
|
501
|
+
"admins",
|
|
502
|
+
"chatEvents",
|
|
503
|
+
"leave",
|
|
504
|
+
"group",
|
|
505
|
+
"officialChatStats",
|
|
506
|
+
];
|
|
507
|
+
/**
|
|
508
|
+
* A reference is read here, not in each adapter: an adapter resolves a typed chat as an id or a title, and would take
|
|
509
|
+
* `chat:max/…` for a title. One of another account is refused before the messenger is asked.
|
|
510
|
+
*/
|
|
511
|
+
const withChatReferences = (adapter, chatOf) => {
|
|
512
|
+
const methods = adapter;
|
|
513
|
+
const own = Object.fromEntries(TYPED_CHAT.flatMap((name) => {
|
|
514
|
+
const method = methods[name];
|
|
515
|
+
if (typeof method !== "function")
|
|
516
|
+
return [];
|
|
517
|
+
const call = async (typed, ...rest) => method.call(adapter, await chatOf(typed), ...rest);
|
|
518
|
+
return [[name, call]];
|
|
519
|
+
}));
|
|
520
|
+
return throughWrapper(adapter, own);
|
|
432
521
|
};
|
|
433
522
|
/**
|
|
434
523
|
* A write is saved under the chat the messenger answered, not the one typed: WhatsApp answers a re-keyed person's
|
|
@@ -68,7 +68,7 @@ export const topicsCommand = (messenger) => {
|
|
|
68
68
|
const done = await context.withServices((services) => services.topics.enable(chat, { upgrade: this.opts().upgrade === true }));
|
|
69
69
|
renderAnswer(this, context, itemOf(snakeKeys(done)));
|
|
70
70
|
});
|
|
71
|
-
annotate(topics.command("create"), { effects: REMOTE_WRITE })
|
|
71
|
+
annotate(topics.command("create"), { effects: REMOTE_WRITE, literal_after_dashes: true })
|
|
72
72
|
.description("create a named topic in an existing forum; never enable or upgrade a group implicitly")
|
|
73
73
|
.argument("<chat>", messenger.chatArgument)
|
|
74
74
|
.argument("<title>", "the topic title, at most 128 UTF-8 bytes")
|
package/dist/cli/program.js
CHANGED
|
@@ -13,6 +13,7 @@ import { recorded, wasSettled } from "../runs/recording.js";
|
|
|
13
13
|
import { runContextOf } from "../runs/run-context.js";
|
|
14
14
|
import { processRun, useAsProcessRun } from "../runs/scope.js";
|
|
15
15
|
import { AUTHORITY_KEY, BOT_API_KEY, isBotApi, keyForCommand } from "../sends/permissions.js";
|
|
16
|
+
import { liftOptionsAfterDashes } from "./after-dashes.js";
|
|
16
17
|
import { logParsedArgv, logVersion } from "./argv-log.js";
|
|
17
18
|
import { commandAvailability } from "./command-availability.js";
|
|
18
19
|
import { commandPathOf } from "./command-contract.js";
|
|
@@ -135,15 +136,16 @@ export const run = async (argv, definition, options = {}) => {
|
|
|
135
136
|
useAsProcessRun(outer);
|
|
136
137
|
}
|
|
137
138
|
};
|
|
139
|
+
const isMachine = (words) => words.some((word) => word === "--json" || word.startsWith("--json=") || word === "--jsonl");
|
|
138
140
|
const runOnce = async (argv, definition, options) => {
|
|
139
141
|
const streams = options.streams ?? processStreams;
|
|
140
142
|
if (!options.streams)
|
|
141
143
|
quietBrokenPipes();
|
|
142
144
|
const delimiter = argv.indexOf("--");
|
|
143
145
|
const flags = argv.slice(0, delimiter < 0 ? undefined : delimiter);
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
let machine = isMachine(flags);
|
|
147
|
+
let debug = flags.includes("--debug");
|
|
148
|
+
let reporting = machine ? { ...options, tty: false } : options;
|
|
147
149
|
const control = execution(streams, { maxOutputBytes: 0 });
|
|
148
150
|
let restoreInput;
|
|
149
151
|
let signalExit;
|
|
@@ -439,12 +441,21 @@ const runOnce = async (argv, definition, options) => {
|
|
|
439
441
|
forEachCommand(program, (child) => child.exitOverride());
|
|
440
442
|
// Before commander, not inside it: commander has no hook that runs before it decides which
|
|
441
443
|
// subcommand it is looking at.
|
|
442
|
-
const
|
|
444
|
+
const profiled = liftProfile(argv, commandWords(program), valuedOptions(program));
|
|
445
|
+
const { profile } = profiled;
|
|
446
|
+
// An agent's call builds its own argv, with its values after `--` on purpose: none of them may become an option.
|
|
447
|
+
const lifted = options.agent
|
|
448
|
+
? profiled.rest
|
|
449
|
+
: liftOptionsAfterDashes(profiled.rest, (words) => commandAt(program, commandPath(program, words)));
|
|
450
|
+
const liftedEnd = lifted.indexOf("--");
|
|
451
|
+
const liftedFlags = lifted.slice(0, liftedEnd < 0 ? undefined : liftedEnd);
|
|
452
|
+
machine ||= isMachine(liftedFlags);
|
|
453
|
+
debug ||= liftedFlags.includes("--debug");
|
|
454
|
+
reporting = machine ? { ...options, tty: false } : options;
|
|
443
455
|
// `wa 'chats list' --help` reads "chats list" as a profile and prints the root help with exit 0.
|
|
444
456
|
try {
|
|
445
457
|
// Only before `--`: what follows is a positional, an agent's text among them, never a command word.
|
|
446
|
-
const
|
|
447
|
-
for (const words of [flags, end < 0 ? lifted : lifted.slice(0, end)])
|
|
458
|
+
for (const words of [flags, liftedFlags])
|
|
448
459
|
refuseJoinedPath(program, words.filter((word) => !word.startsWith("-")), profile !== undefined && !/\s/.test(profile) ? [profile] : []);
|
|
449
460
|
}
|
|
450
461
|
catch (failure) {
|
|
@@ -110,6 +110,7 @@ export const scheduleCommandFor = ({ app, context: contextOf }) => {
|
|
|
110
110
|
return { context, system, state, say, timer, environment, save };
|
|
111
111
|
};
|
|
112
112
|
withWhen(grantsAuthority(annotate(command.command("command"), {
|
|
113
|
+
literal_after_dashes: true,
|
|
113
114
|
effects: LOCAL_WRITE,
|
|
114
115
|
examples: [
|
|
115
116
|
`${app.command} personal schedule command health --every 1h -- doctor`,
|
package/dist/cli/settings.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { type AISettings } from "../analysis/settings.js";
|
|
|
4
4
|
import { type AppIdentity } from "../ports/app.js";
|
|
5
5
|
import type { RecordInput } from "../runs/run-context.js";
|
|
6
6
|
import { type Level, type PermissionKey } from "../sends/permissions.js";
|
|
7
|
+
import { type HistoryLimits } from "../services/history-limits.js";
|
|
7
8
|
import { type ConfigIssue } from "./config-issues.js";
|
|
8
9
|
import type { CommandPermissions } from "./permission-keys.js";
|
|
9
10
|
export declare const plain: (rule: string) => (issue: v.BaseIssue<unknown>) => string;
|
|
@@ -94,6 +95,8 @@ export interface Settings extends AISettings {
|
|
|
94
95
|
color: boolean | undefined;
|
|
95
96
|
senderColors: boolean;
|
|
96
97
|
searchCatchUp?: boolean;
|
|
98
|
+
/** How much pushed history the store keeps, by chat kind; a messenger that answers history on request ignores it. */
|
|
99
|
+
historyLimits?: HistoryLimits;
|
|
97
100
|
/** Search and `images embed` read the pictures themselves, with a model on this machine. Off until set. */
|
|
98
101
|
pictureSearch?: boolean;
|
|
99
102
|
/** The reranker that orders `search messages --discover`'s first hits once it is downloaded, or `off`. */
|
|
@@ -300,6 +303,9 @@ export declare const settingsFor: <T extends object = Record<never, never>>(app:
|
|
|
300
303
|
transcribe_with: v.OptionalSchema<v.PicklistSchema<["auto", "messenger", "local"], (issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
301
304
|
speech_model: v.OptionalSchema<v.StringSchema<(issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
302
305
|
search_catch_up: v.OptionalSchema<v.BooleanSchema<(issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
306
|
+
history_dialog_days: v.OptionalSchema<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>, v.MaxValueAction<number, 1095, (issue: v.BaseIssue<unknown>) => string>]>, undefined>;
|
|
307
|
+
history_group_days: v.OptionalSchema<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>, v.MaxValueAction<number, 1095, (issue: v.BaseIssue<unknown>) => string>]>, undefined>;
|
|
308
|
+
history_group_members_max: v.OptionalSchema<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>]>, undefined>;
|
|
303
309
|
picture_search: v.OptionalSchema<v.BooleanSchema<(issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
304
310
|
search_reranker: v.OptionalSchema<v.PicklistSchema<[...string[], "off"], (issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
305
311
|
update_check: v.OptionalSchema<v.BooleanSchema<(issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
@@ -376,6 +382,9 @@ export declare const settingsFor: <T extends object = Record<never, never>>(app:
|
|
|
376
382
|
transcribe_with: v.OptionalSchema<v.PicklistSchema<["auto", "messenger", "local"], (issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
377
383
|
speech_model: v.OptionalSchema<v.StringSchema<(issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
378
384
|
search_catch_up: v.OptionalSchema<v.BooleanSchema<(issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
385
|
+
history_dialog_days: v.OptionalSchema<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>, v.MaxValueAction<number, 1095, (issue: v.BaseIssue<unknown>) => string>]>, undefined>;
|
|
386
|
+
history_group_days: v.OptionalSchema<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>, v.MaxValueAction<number, 1095, (issue: v.BaseIssue<unknown>) => string>]>, undefined>;
|
|
387
|
+
history_group_members_max: v.OptionalSchema<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>]>, undefined>;
|
|
379
388
|
picture_search: v.OptionalSchema<v.BooleanSchema<(issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
380
389
|
search_reranker: v.OptionalSchema<v.PicklistSchema<[...string[], "off"], (issue: v.BaseIssue<unknown>) => string>, undefined>;
|
|
381
390
|
}, (issue: v.StrictObjectIssue) => string>, "has to be an object of profiles, by name">, {}>;
|
package/dist/cli/settings.js
CHANGED
|
@@ -7,6 +7,7 @@ import { DEFAULT_RERANK_MODEL, RERANK_MODELS } from "../embeddings/models.js";
|
|
|
7
7
|
import { envName, readOnlyLockOf } from "../ports/app.js";
|
|
8
8
|
import { KEEP_SUCCESSFUL_RUNS_FOR_DAYS, RUNS_SIZE_LIMIT_MB } from "../runs/run.js";
|
|
9
9
|
import { assertOverridesTighten, CEILING_KEY, COMMAND_PATH_KEY, LEVELS, layerPermissions, permissionOverrides, RESOURCE_KEY, RESOURCES, } from "../sends/permissions.js";
|
|
10
|
+
import { DEFAULT_HISTORY_LIMITS, HISTORY_MAX_DAYS } from "../services/history-limits.js";
|
|
10
11
|
import { storePath } from "../store/path.js";
|
|
11
12
|
import { sharedConfigPath } from "../store/shared-config.js";
|
|
12
13
|
import { checkConfigText, issueMessage, readConfigFile, readConfigText, savedPermissionKeys, schemaIssues, settingPathOf, withoutPath, } from "./config-issues.js";
|
|
@@ -34,6 +35,8 @@ export const count = v.pipe(v.number(wholeNumber), v.integer(wholeNumber), v.min
|
|
|
34
35
|
const zeroOrMore = plain("has to be a whole number, 0 or more");
|
|
35
36
|
const countOrZero = v.pipe(v.number(zeroOrMore), v.integer(zeroOrMore), v.minValue(0, zeroOrMore));
|
|
36
37
|
export const flag = v.boolean(plain("has to be true or false"));
|
|
38
|
+
const historyDaysMessage = plain(`has to be a whole number of days, 1 to ${HISTORY_MAX_DAYS}`);
|
|
39
|
+
const historyDays = v.pipe(v.number(historyDaysMessage), v.integer(historyDaysMessage), v.minValue(1, historyDaysMessage), v.maxValue(HISTORY_MAX_DAYS, historyDaysMessage));
|
|
37
40
|
/** `record_input`: true, false, or "failed" — the words typed kept only in a run that failed. */
|
|
38
41
|
export const recordInputSetting = v.union([v.boolean(), v.literal("failed")], plain('has to be true, false or "failed"'));
|
|
39
42
|
const wholeOrZero = (text, name) => {
|
|
@@ -71,6 +74,9 @@ const SHARED_PROFILE_ENTRIES = {
|
|
|
71
74
|
transcribe_with: v.optional(v.picklist(["auto", "messenger", "local"], plain("has to be auto, messenger or local"))),
|
|
72
75
|
speech_model: v.optional(v.string(plain("has to be a model id from `models list`, in quotes"))),
|
|
73
76
|
search_catch_up: v.optional(flag),
|
|
77
|
+
history_dialog_days: v.optional(historyDays),
|
|
78
|
+
history_group_days: v.optional(historyDays),
|
|
79
|
+
history_group_members_max: v.optional(count),
|
|
74
80
|
picture_search: v.optional(flag),
|
|
75
81
|
search_reranker: v.optional(v.picklist([...RERANK_MODELS.map((model) => model.id), "off"], plain(`has to be off or a reranker id: ${RERANK_MODELS.map((model) => model.id).join(", ")}`))),
|
|
76
82
|
...AI_ENTRIES,
|
|
@@ -91,6 +97,9 @@ export const MESSENGER_ONLY_SETTINGS = [
|
|
|
91
97
|
"sends_per_hour",
|
|
92
98
|
"transcribe_with",
|
|
93
99
|
"search_catch_up",
|
|
100
|
+
"history_dialog_days",
|
|
101
|
+
"history_group_days",
|
|
102
|
+
"history_group_members_max",
|
|
94
103
|
"read_other_bots",
|
|
95
104
|
];
|
|
96
105
|
/** One program, one version: whether to look for a newer one is not a per-profile matter. */
|
|
@@ -255,6 +264,9 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
255
264
|
const color = fromLayers("color", undefined);
|
|
256
265
|
const senderColors = fromLayers("sender_colors", false);
|
|
257
266
|
const searchCatchUp = fromLayers("search_catch_up", false);
|
|
267
|
+
const historyDialogDays = fromLayers("history_dialog_days", DEFAULT_HISTORY_LIMITS.dialogDays);
|
|
268
|
+
const historyGroupDays = fromLayers("history_group_days", DEFAULT_HISTORY_LIMITS.groupDays);
|
|
269
|
+
const historyGroupMembersMax = fromLayers("history_group_members_max", DEFAULT_HISTORY_LIMITS.groupMembersMax);
|
|
258
270
|
const pictureSearch = fromLayers("picture_search", false);
|
|
259
271
|
const searchReranker = fromLayers("search_reranker", DEFAULT_RERANK_MODEL);
|
|
260
272
|
const recordInput = fromLayers("record_input", true);
|
|
@@ -306,6 +318,11 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
306
318
|
color: color.value,
|
|
307
319
|
senderColors: senderColors.value,
|
|
308
320
|
searchCatchUp: searchCatchUp.value,
|
|
321
|
+
historyLimits: {
|
|
322
|
+
dialogDays: historyDialogDays.value,
|
|
323
|
+
groupDays: historyGroupDays.value,
|
|
324
|
+
groupMembersMax: historyGroupMembersMax.value,
|
|
325
|
+
},
|
|
309
326
|
pictureSearch: pictureSearch.value,
|
|
310
327
|
searchReranker: searchReranker.value,
|
|
311
328
|
limit: limit.value,
|
|
@@ -343,6 +360,9 @@ export const settingsFor = (app, extension = {}) => {
|
|
|
343
360
|
color: color.from,
|
|
344
361
|
senderColors: senderColors.from,
|
|
345
362
|
searchCatchUp: searchCatchUp.from,
|
|
363
|
+
historyDialogDays: historyDialogDays.from,
|
|
364
|
+
historyGroupDays: historyGroupDays.from,
|
|
365
|
+
historyGroupMembersMax: historyGroupMembersMax.from,
|
|
346
366
|
pictureSearch: pictureSearch.from,
|
|
347
367
|
searchReranker: searchReranker.from,
|
|
348
368
|
record: record.from,
|
|
@@ -82,6 +82,9 @@ export declare const appDoctorCommand: (app: import("./entry.js").AppIdentity, c
|
|
|
82
82
|
transcribe_with: import("valibot").OptionalSchema<import("valibot").PicklistSchema<["auto", "messenger", "local"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
83
83
|
speech_model: import("valibot").OptionalSchema<import("valibot").StringSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
84
84
|
search_catch_up: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
85
|
+
history_dialog_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
86
|
+
history_group_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
87
|
+
history_group_members_max: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
85
88
|
picture_search: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
86
89
|
search_reranker: import("valibot").OptionalSchema<import("valibot").PicklistSchema<[...string[], "off"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
87
90
|
update_check: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
@@ -158,6 +161,9 @@ export declare const appDoctorCommand: (app: import("./entry.js").AppIdentity, c
|
|
|
158
161
|
transcribe_with: import("valibot").OptionalSchema<import("valibot").PicklistSchema<["auto", "messenger", "local"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
159
162
|
speech_model: import("valibot").OptionalSchema<import("valibot").StringSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
160
163
|
search_catch_up: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
164
|
+
history_dialog_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
165
|
+
history_group_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
166
|
+
history_group_members_max: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
161
167
|
picture_search: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
162
168
|
search_reranker: import("valibot").OptionalSchema<import("valibot").PicklistSchema<[...string[], "off"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
163
169
|
}, (issue: import("valibot").StrictObjectIssue) => string>, "has to be an object of profiles, by name">, {}>;
|
|
@@ -256,6 +262,9 @@ export declare const appMcpCommand: (app: import("./entry.js").AppIdentity, conf
|
|
|
256
262
|
transcribe_with: import("valibot").OptionalSchema<import("valibot").PicklistSchema<["auto", "messenger", "local"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
257
263
|
speech_model: import("valibot").OptionalSchema<import("valibot").StringSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
258
264
|
search_catch_up: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
265
|
+
history_dialog_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
266
|
+
history_group_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
267
|
+
history_group_members_max: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
259
268
|
picture_search: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
260
269
|
search_reranker: import("valibot").OptionalSchema<import("valibot").PicklistSchema<[...string[], "off"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
261
270
|
update_check: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
@@ -332,6 +341,9 @@ export declare const appMcpCommand: (app: import("./entry.js").AppIdentity, conf
|
|
|
332
341
|
transcribe_with: import("valibot").OptionalSchema<import("valibot").PicklistSchema<["auto", "messenger", "local"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
333
342
|
speech_model: import("valibot").OptionalSchema<import("valibot").StringSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
334
343
|
search_catch_up: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
344
|
+
history_dialog_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
345
|
+
history_group_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
346
|
+
history_group_members_max: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
335
347
|
picture_search: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
336
348
|
search_reranker: import("valibot").OptionalSchema<import("valibot").PicklistSchema<[...string[], "off"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
337
349
|
}, (issue: import("valibot").StrictObjectIssue) => string>, "has to be an object of profiles, by name">, {}>;
|
|
@@ -437,6 +449,9 @@ export declare const configCommand: (app: import("./entry.js").AppIdentity, conf
|
|
|
437
449
|
transcribe_with: import("valibot").OptionalSchema<import("valibot").PicklistSchema<["auto", "messenger", "local"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
438
450
|
speech_model: import("valibot").OptionalSchema<import("valibot").StringSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
439
451
|
search_catch_up: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
452
|
+
history_dialog_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
453
|
+
history_group_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
454
|
+
history_group_members_max: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
440
455
|
picture_search: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
441
456
|
search_reranker: import("valibot").OptionalSchema<import("valibot").PicklistSchema<[...string[], "off"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
442
457
|
update_check: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
@@ -513,6 +528,9 @@ export declare const configCommand: (app: import("./entry.js").AppIdentity, conf
|
|
|
513
528
|
transcribe_with: import("valibot").OptionalSchema<import("valibot").PicklistSchema<["auto", "messenger", "local"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
514
529
|
speech_model: import("valibot").OptionalSchema<import("valibot").StringSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
515
530
|
search_catch_up: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
531
|
+
history_dialog_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
532
|
+
history_group_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
533
|
+
history_group_members_max: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
516
534
|
picture_search: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
517
535
|
search_reranker: import("valibot").OptionalSchema<import("valibot").PicklistSchema<[...string[], "off"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
518
536
|
}, (issue: import("valibot").StrictObjectIssue) => string>, "has to be an object of profiles, by name">, {}>;
|
|
@@ -646,6 +664,9 @@ export declare const completeCommand: (messenger: import("./index.js").Messenger
|
|
|
646
664
|
transcribe_with: import("valibot").OptionalSchema<import("valibot").PicklistSchema<["auto", "messenger", "local"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
647
665
|
speech_model: import("valibot").OptionalSchema<import("valibot").StringSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
648
666
|
search_catch_up: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
667
|
+
history_dialog_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
668
|
+
history_group_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
669
|
+
history_group_members_max: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
649
670
|
picture_search: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
650
671
|
search_reranker: import("valibot").OptionalSchema<import("valibot").PicklistSchema<[...string[], "off"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
651
672
|
update_check: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
@@ -722,6 +743,9 @@ export declare const completeCommand: (messenger: import("./index.js").Messenger
|
|
|
722
743
|
transcribe_with: import("valibot").OptionalSchema<import("valibot").PicklistSchema<["auto", "messenger", "local"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
723
744
|
speech_model: import("valibot").OptionalSchema<import("valibot").StringSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
724
745
|
search_catch_up: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
746
|
+
history_dialog_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
747
|
+
history_group_days: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MaxValueAction<number, 1095, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
748
|
+
history_group_members_max: import("valibot").OptionalSchema<import("valibot").SchemaWithPipe<readonly [import("valibot").NumberSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").IntegerAction<number, (issue: import("valibot").BaseIssue<unknown>) => string>, import("valibot").MinValueAction<number, 1, (issue: import("valibot").BaseIssue<unknown>) => string>]>, undefined>;
|
|
725
749
|
picture_search: import("valibot").OptionalSchema<import("valibot").BooleanSchema<(issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
726
750
|
search_reranker: import("valibot").OptionalSchema<import("valibot").PicklistSchema<[...string[], "off"], (issue: import("valibot").BaseIssue<unknown>) => string>, undefined>;
|
|
727
751
|
}, (issue: import("valibot").StrictObjectIssue) => string>, "has to be an object of profiles, by name">, {}>;
|
package/dist/cli/steps.js
CHANGED
|
@@ -16,6 +16,7 @@ export const STEPS = defineSteps([
|
|
|
16
16
|
{ name: "all", required: false },
|
|
17
17
|
{ name: "since_time", required: false },
|
|
18
18
|
{ name: "background", required: false },
|
|
19
|
+
{ name: "full_history", required: false },
|
|
19
20
|
],
|
|
20
21
|
why: "the local copy is missing messages; syncing brings them in",
|
|
21
22
|
},
|
|
@@ -24,13 +24,16 @@ export type MessageLink = MessagePermalink & {
|
|
|
24
24
|
files?: FileLink[];
|
|
25
25
|
};
|
|
26
26
|
export declare const fileLinks: (attachments: readonly Attachment[]) => FileLink[];
|
|
27
|
+
/** A chat and a message id, or one reference naming both; a reference's account is for the caller to check. */
|
|
27
28
|
export declare const messageLinkTarget: (reference: string, message: string | undefined, provider: string) => {
|
|
28
29
|
chat: string;
|
|
29
30
|
message: string;
|
|
30
31
|
account: string;
|
|
32
|
+
text: string;
|
|
31
33
|
} | {
|
|
32
34
|
chat: string;
|
|
33
35
|
message: string;
|
|
34
36
|
account: undefined;
|
|
37
|
+
text: string;
|
|
35
38
|
};
|
|
36
39
|
export declare const validatePermalink: (link: MessagePermalink) => MessagePermalink;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
2
|
import { hitFiles } from "./attachments.js";
|
|
3
|
-
import {
|
|
3
|
+
import { chatReferenceOf } from "./ref-arguments.js";
|
|
4
4
|
export const fileLinks = (attachments) => hitFiles(attachments).map(({ position, kind, name }) => ({
|
|
5
5
|
position,
|
|
6
6
|
kind,
|
|
@@ -8,28 +8,23 @@ export const fileLinks = (attachments) => hitFiles(attachments).map(({ position,
|
|
|
8
8
|
url: null,
|
|
9
9
|
reason: "unsupported_provider",
|
|
10
10
|
}));
|
|
11
|
+
/** A chat and a message id, or one reference naming both; a reference's account is for the caller to check. */
|
|
11
12
|
export const messageLinkTarget = (reference, message, provider) => {
|
|
12
|
-
|
|
13
|
+
const named = chatReferenceOf(reference, provider, "message");
|
|
14
|
+
if (named?.message !== undefined) {
|
|
13
15
|
if (message !== undefined)
|
|
14
16
|
throw new CliError("validation_error", "a locator already names the message");
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
target = parseLocator(reference);
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
throw new CliError("validation_error", "expected msg:<provider>/<account>/<chat>/<message>");
|
|
21
|
-
}
|
|
22
|
-
if (target.provider !== provider)
|
|
23
|
-
throw new CliError("validation_error", "that locator belongs to another messenger");
|
|
24
|
-
validMessageId(target.message);
|
|
25
|
-
return { chat: target.chat, message: target.message, account: target.account };
|
|
17
|
+
validMessageId(named.message);
|
|
18
|
+
return { chat: named.chat, message: named.message, account: named.account, text: named.text };
|
|
26
19
|
}
|
|
27
20
|
if (message === undefined)
|
|
28
21
|
throw new CliError("validation_error", "which message? give its id after the chat");
|
|
29
22
|
validMessageId(message);
|
|
23
|
+
if (named)
|
|
24
|
+
return { chat: named.chat, message, account: named.account, text: named.text };
|
|
30
25
|
if (!reference.trim())
|
|
31
26
|
throw new CliError("validation_error", "which chat? give its id or title");
|
|
32
|
-
return { chat: reference, message, account: undefined };
|
|
27
|
+
return { chat: reference, message, account: undefined, text: reference };
|
|
33
28
|
};
|
|
34
29
|
const validMessageId = (id) => {
|
|
35
30
|
if (!id ||
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TaskCategory } from "./task-categories.js";
|
|
2
|
+
/**
|
|
3
|
+
* Verb classes for reading money in a chat, matched by stem as task categories are. A stem cannot tell the imperative
|
|
4
|
+
* from the past tense (`оплати`, `оплатил` → `оплат`) or from a promise (`pagué`, `pagaré` → `pag`), so a stem that
|
|
5
|
+
* several classes share is listed once, under the request, and a word only counts where its stem is its own. The
|
|
6
|
+
* signal that reads these keeps the sender's side (owner or other) to decide the direction.
|
|
7
|
+
*/
|
|
8
|
+
export declare const MONEY_REQUEST = "money-request";
|
|
9
|
+
export declare const MONEY_DONE = "money-done";
|
|
10
|
+
export declare const PROMISE = "promise";
|
|
11
|
+
export declare const MONEY_WORDS: readonly TaskCategory[];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verb classes for reading money in a chat, matched by stem as task categories are. A stem cannot tell the imperative
|
|
3
|
+
* from the past tense (`оплати`, `оплатил` → `оплат`) or from a promise (`pagué`, `pagaré` → `pag`), so a stem that
|
|
4
|
+
* several classes share is listed once, under the request, and a word only counts where its stem is its own. The
|
|
5
|
+
* signal that reads these keeps the sender's side (owner or other) to decide the direction.
|
|
6
|
+
*/
|
|
7
|
+
export const MONEY_REQUEST = "money-request";
|
|
8
|
+
export const MONEY_DONE = "money-done";
|
|
9
|
+
export const PROMISE = "promise";
|
|
10
|
+
export const MONEY_WORDS = [
|
|
11
|
+
{
|
|
12
|
+
name: MONEY_REQUEST,
|
|
13
|
+
meaning: "asks for a payment or sends an invoice",
|
|
14
|
+
triggers: {
|
|
15
|
+
en: ["pay", "send", "transfer", "invoice", "owe", "refund", "remit"],
|
|
16
|
+
ru: ["переведи", "оплати", "заплати", "вышли", "отправь", "скинь", "верни", "счёт", "выстави", "должен"],
|
|
17
|
+
es: ["envía", "transfiere", "factura", "debes", "devuelve", "abona"],
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: MONEY_DONE,
|
|
22
|
+
meaning: "says a payment was made or received",
|
|
23
|
+
triggers: {
|
|
24
|
+
en: ["paid", "sent", "received", "settled"],
|
|
25
|
+
ru: ["перевёл", "перевела", "выслал", "вернул", "скинул", "получил", "получила"],
|
|
26
|
+
es: ["recibido"],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: PROMISE,
|
|
31
|
+
meaning: "promises to pay or send later",
|
|
32
|
+
triggers: {
|
|
33
|
+
en: ["promise", "promised", "guarantee"],
|
|
34
|
+
ru: ["оплачу", "заплачу", "отправлю", "обещаю", "гарантирую"],
|
|
35
|
+
es: ["prometo", "transferiré", "devolveré"],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
];
|
|
@@ -11,6 +11,8 @@ export interface ProviderEntry {
|
|
|
11
11
|
}
|
|
12
12
|
/** The seed: what cli-core knows before any CLI has written its entry into the store. */
|
|
13
13
|
export declare const PROVIDERS: readonly ProviderEntry[];
|
|
14
|
+
/** How a text names a provider to a person: `MAX`, not `max`. */
|
|
15
|
+
export declare const providerLabel: (provider: Provider) => string;
|
|
14
16
|
/**
|
|
15
17
|
* A notes folder is an `accounts` row of one of these providers; people call every one `notes`. `obsidian` is a vault,
|
|
16
18
|
* `local` a plain folder (store version 32). `folder` is what they were before, and what Drive's stand-in folders and
|
package/dist/domain/providers.js
CHANGED
|
@@ -3,11 +3,11 @@ import { CliError } from "@wirecat/cli-base";
|
|
|
3
3
|
export const KINDS = ["messages", "mail", "notes", "documents", "meetings", "events"];
|
|
4
4
|
/** The seed: what cli-core knows before any CLI has written its entry into the store. */
|
|
5
5
|
export const PROVIDERS = [
|
|
6
|
-
{ name: "telegram", kind: "messages", aliases: ["tg"] },
|
|
6
|
+
{ name: "telegram", kind: "messages", aliases: ["tg"], command: "tg" },
|
|
7
7
|
{ name: "telegram-bot", kind: "messages", aliases: ["tg-bot"] },
|
|
8
|
-
{ name: "max", kind: "messages", aliases: [] },
|
|
8
|
+
{ name: "max", kind: "messages", aliases: [], command: "max" },
|
|
9
9
|
{ name: "max-bot", kind: "messages", aliases: [] },
|
|
10
|
-
{ name: "whatsapp", kind: "messages", aliases: ["wa"] },
|
|
10
|
+
{ name: "whatsapp", kind: "messages", aliases: ["wa"], command: "wa" },
|
|
11
11
|
{ name: "whatsapp-bot", kind: "messages", aliases: ["wa-bot"] },
|
|
12
12
|
{ name: "email", kind: "mail", aliases: [] },
|
|
13
13
|
{ name: "notes", kind: "notes", aliases: [] },
|
|
@@ -15,6 +15,18 @@ export const PROVIDERS = [
|
|
|
15
15
|
{ name: "obsidian", kind: "notes", aliases: [] },
|
|
16
16
|
{ name: "zoom", kind: "meetings", aliases: [] },
|
|
17
17
|
];
|
|
18
|
+
const LABELS = {
|
|
19
|
+
telegram: "Telegram",
|
|
20
|
+
"telegram-bot": "Telegram bot",
|
|
21
|
+
max: "MAX",
|
|
22
|
+
"max-bot": "MAX bot",
|
|
23
|
+
whatsapp: "WhatsApp",
|
|
24
|
+
"whatsapp-bot": "WhatsApp bot",
|
|
25
|
+
"google-drive": "Google Drive",
|
|
26
|
+
email: "mail",
|
|
27
|
+
};
|
|
28
|
+
/** How a text names a provider to a person: `MAX`, not `max`. */
|
|
29
|
+
export const providerLabel = (provider) => LABELS[provider] ?? provider;
|
|
18
30
|
/**
|
|
19
31
|
* A notes folder is an `accounts` row of one of these providers; people call every one `notes`. `obsidian` is a vault,
|
|
20
32
|
* `local` a plain folder (store version 32). `folder` is what they were before, and what Drive's stand-in folders and
|