@wirecat/cli-core 0.559.0 → 0.560.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 +43 -0
- package/dist/background/schedules.d.ts +2 -0
- package/dist/cli/effects.d.ts +13 -2
- package/dist/cli/effects.js +23 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +2 -2
- package/dist/cli/meeting-findings-input.d.ts +3 -0
- package/dist/cli/meeting-findings-input.js +4 -0
- package/dist/cli/messenger/conversation-answers.d.ts +3 -0
- package/dist/cli/messenger/message-answers.d.ts +3 -0
- package/dist/cli/messenger/message-writes.d.ts +6 -0
- package/dist/cli/schedule/schedule-command.d.ts +6 -1
- package/dist/cli/schedule/schedule-command.js +24 -2
- package/dist/entities/contact-context.d.ts +6 -0
- package/dist/entities/conversation-results.d.ts +6 -0
- package/dist/entities/evidence.d.ts +24 -0
- package/dist/entities/index.d.ts +190 -0
- package/dist/entities/index.js +3 -0
- package/dist/entities/listener.d.ts +12 -0
- package/dist/entities/mail-findings.d.ts +116 -0
- package/dist/entities/mail-findings.js +68 -0
- package/dist/entities/message-context.d.ts +9 -0
- package/dist/entities/message-write.d.ts +12 -0
- package/dist/entities/message.d.ts +6 -0
- package/dist/entities/message.js +6 -0
- package/dist/entities/store-records.d.ts +3 -0
- package/dist/errors/reasons.js +2 -0
- package/dist/mail/cli/marks.d.ts +1 -0
- package/dist/mail/cli/marks.js +11 -4
- package/dist/mail/cli/review.js +10 -2
- package/dist/mail/findings.d.ts +55 -0
- package/dist/mail/findings.js +140 -0
- package/dist/mail/index.d.ts +2 -1
- package/dist/mail/index.js +2 -1
- package/dist/mail/marks.d.ts +10 -3
- package/dist/mail/marks.js +34 -5
- package/dist/meetings/findings-rules.d.ts +24 -0
- package/dist/meetings/findings-rules.js +136 -116
- package/dist/meetings/index.d.ts +2 -1
- package/dist/meetings/index.js +2 -1
- package/dist/meetings/mcp/index.d.ts +15 -15
- package/dist/services/proposals/kinds/mail-findings.d.ts +8 -0
- package/dist/services/proposals/kinds/mail-findings.js +87 -0
- package/dist/services/proposals/registry.js +3 -1
- package/dist/services/proposals/types.d.ts +2 -0
- package/dist/store/decisions.d.ts +1 -1
- package/dist/store/decisions.js +1 -1
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.js +1 -0
- package/dist/store/mail-findings.d.ts +51 -0
- package/dist/store/mail-findings.js +1 -0
- package/dist/store/path.d.ts +2 -0
- package/dist/store/path.js +21 -1
- package/dist/store/sqlite/email-activity.d.ts +8 -0
- package/dist/store/sqlite/email-activity.js +31 -5
- package/dist/store/sqlite/findings-core.d.ts +1 -0
- package/dist/store/sqlite/findings-core.js +1 -1
- package/dist/store/sqlite/mail-findings.d.ts +3 -0
- package/dist/store/sqlite/mail-findings.js +333 -0
- package/dist/store/sqlite/manifest.js +1 -0
- package/dist/store/sqlite/memories.d.ts +4 -1
- package/dist/store/sqlite/memories.js +48 -43
- package/dist/store/sqlite/migrations.generated.js +6 -0
- package/dist/store/sqlite/open-store.d.ts +1 -1
- package/dist/store/sqlite/open-store.js +4 -1
- package/dist/store/sqlite/open.js +2 -1
- package/dist/store/sqlite/proposed-actions.js +2 -1
- package/dist/store/sqlite/tasks.d.ts +2 -0
- package/dist/store/sqlite/tasks.js +26 -24
- package/dist/store/sqlite/test-accounts.d.ts +8 -0
- package/dist/store/sqlite/test-accounts.js +31 -0
- package/dist/store/sqlite/work-tasks.d.ts +1 -0
- package/dist/store/sqlite/work-tasks.js +6 -0
- package/dist/store/store.d.ts +3 -0
- package/dist/store/store.js +5 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,49 @@ shape of this file.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.560.0 — 02.11.2026
|
|
11
|
+
|
|
12
|
+
### Changed — may break callers
|
|
13
|
+
|
|
14
|
+
- **Agents no longer decide for the owner by default; the owner turns it on.**
|
|
15
|
+
`DEFAULT_DECISION_POLICY.agentDecisions` is now `false`, so a store opened without `decisions` refuses every agent
|
|
16
|
+
confirm or reject with `proposals.agent-decisions-off`; before, an agent with a reason could decide facts, memories,
|
|
17
|
+
links and project findings. A host turns it back on only from the owner's explicit config, `"agent_decisions": true`,
|
|
18
|
+
passed as `openStore({ decisions: { ...DEFAULT_DECISION_POLICY, agentDecisions: true } })`. Owner-only proposals
|
|
19
|
+
(mail and meeting findings, task close suggestions) stay refused either way.
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **A `propose` tier under `<PREFIX>_READ_ONLY`.** `proposesOnly(command)` marks a command that only stages
|
|
24
|
+
something for the owner or moves its caller's own mark; the lock lets it run only when its path also ends with one
|
|
25
|
+
of `PROPOSE_COMMANDS` — `messages acknowledge` and `mail findings add` — a closed list. `isStoreChange` applies it,
|
|
26
|
+
so every host's lock does. `messages acknowledge` moved from `destroysNothing` to this tier.
|
|
27
|
+
- **Mail findings for the owner** (`mail_findings` in `proposed_actions`, no schema change): `store.mailFindings`
|
|
28
|
+
stages one batch per mailbox and run (`key` `<holder>:<through_id>`), of up to 30 findings — `task`,
|
|
29
|
+
`task_update` (close, due, detail), `fact`, `memory`, `link` (address → person, person → organization, thread →
|
|
30
|
+
project) and `new_contact` — each citing 1–8 `msg:email/…` emails by fingerprint, at most five per sender. Changed
|
|
31
|
+
or partial mail refuses the batch. Only the owner decides one, whatever `agent_decisions` says; the registry kind
|
|
32
|
+
`mail_findings` is owner-only too (`ProposalKind.ownerOnly`). `parseMailFindingsJson` reads the file;
|
|
33
|
+
the `mail_findings` entity describes it.
|
|
34
|
+
- **Mail `review` items carry what a pipeline cites and checks:** each email's evidence `fingerprint`, `new_sender`
|
|
35
|
+
(no earlier stored email from the address) and `sender_identities`. `review --holder` also leaves out senders whose
|
|
36
|
+
score is demoted, counted as `suspicious` in the mark.
|
|
37
|
+
- **`schedule agent --on-new-mail <holder>`,** where the host passes `newMail` (`holderHasMail`): the agent starts
|
|
38
|
+
only when mail is stored past the holder's mark, and may check every 5 minutes; a run with nothing new costs no
|
|
39
|
+
model call and records nothing. Mail that is only skipped moves the holder's mark without the agent.
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
43
|
+
- **A test can no longer open the owner's real store.** Under vitest, opening a file in the owner's WireCat folder
|
|
44
|
+
(found from the account's home, not `HOME`) throws, read-only or not. This holds in every CLI's tests that open the
|
|
45
|
+
store through cli-core. cli-core's own suite now refuses vitest's threads pool. There a test env without `HOME`
|
|
46
|
+
reached the real home folder: on 2026-10-18 a `--pool=threads` run wrote test rows into the real store.
|
|
47
|
+
- **The test rows that leaked into a real store are removed (store version 48).** A store that holds an account of
|
|
48
|
+
the test messenger `chat` gets a mark from the migration. The next writable open then removes every such account
|
|
49
|
+
with all it holds, as `cache clear` removes one, so the search and vector indexes stay in step. A store without
|
|
50
|
+
one is unchanged. If the removal fails, the store still opens: a warning names the error and the next open tries
|
|
51
|
+
again.
|
|
52
|
+
|
|
10
53
|
## 0.559.0 — 02.11.2026
|
|
11
54
|
|
|
12
55
|
### Added
|
|
@@ -17,6 +17,8 @@ export interface Schedule {
|
|
|
17
17
|
/** The variables the run gets on top of the timer's: the profile, where the files are, PATH. Never a credential. */
|
|
18
18
|
environment: Record<string, string>;
|
|
19
19
|
createdAt: string;
|
|
20
|
+
/** A holder whose mark gates the run: it starts only when mail is stored past that mark. */
|
|
21
|
+
onNewMail?: string;
|
|
20
22
|
}
|
|
21
23
|
export interface LastRun {
|
|
22
24
|
at: string;
|
package/dist/cli/effects.d.ts
CHANGED
|
@@ -39,6 +39,16 @@ export declare const isLogin: (command: Command) => boolean;
|
|
|
39
39
|
* (merge/unmerge, claim/release) or keeps the old value in the task's history; under the lock a close only suggests.
|
|
40
40
|
*/
|
|
41
41
|
export declare const destroysNothing: <T extends Command>(command: T) => T;
|
|
42
|
+
/**
|
|
43
|
+
* The `propose` tier, a closed list: the only commands `<PREFIX>_READ_ONLY` lets stage something for the owner. Each
|
|
44
|
+
* appends a proposal the owner decides or moves its caller's own processing mark, and nothing else. A command must
|
|
45
|
+
* be marked `proposesOnly` **and** end with one of these paths; adding a path widens what a read-only agent can
|
|
46
|
+
* write, so it needs its own review.
|
|
47
|
+
*/
|
|
48
|
+
export declare const PROPOSE_COMMANDS: readonly ["messages acknowledge", "mail findings add"];
|
|
49
|
+
/** Marks a command of the `propose` tier; the lock lets it through only when its path is in `PROPOSE_COMMANDS`. */
|
|
50
|
+
export declare const proposesOnly: <T extends Command>(command: T) => T;
|
|
51
|
+
export declare const isProposal: (command: Command) => boolean;
|
|
42
52
|
/** A local edit remains an edit even when it first fetches metadata from the messenger. */
|
|
43
53
|
export declare const changesStore: <T extends Command>(command: T) => T;
|
|
44
54
|
/**
|
|
@@ -66,8 +76,9 @@ export declare const readsOverMcp: (command: Command) => boolean;
|
|
|
66
76
|
export declare const readsOverMcpAt: (root: Command) => (path: readonly string[]) => boolean;
|
|
67
77
|
/**
|
|
68
78
|
* Whether `<PREFIX>_READ_ONLY` refuses the command as a change to the store. Every write that stays on this machine
|
|
69
|
-
* is refused unless `destroysNothing` marks it, so a new one fails closed
|
|
70
|
-
* keeps receiving, a remote write is `changesMessenger`'s, and an authority
|
|
79
|
+
* is refused unless `destroysNothing` marks it or it is of the `propose` tier, so a new one fails closed
|
|
80
|
+
* (WC-PERM-12). A fetch (`remote: "read"`) keeps receiving, a remote write is `changesMessenger`'s, and an authority
|
|
81
|
+
* change has its own refusal.
|
|
71
82
|
*/
|
|
72
83
|
export declare const isStoreChange: (command: Command) => boolean;
|
|
73
84
|
export declare const STORE_CHANGE_REFUSAL = "change the message store";
|
package/dist/cli/effects.js
CHANGED
|
@@ -60,6 +60,25 @@ export const destroysNothing = (command) => {
|
|
|
60
60
|
KEPT_UNDER_LOCK.add(command);
|
|
61
61
|
return command;
|
|
62
62
|
};
|
|
63
|
+
/**
|
|
64
|
+
* The `propose` tier, a closed list: the only commands `<PREFIX>_READ_ONLY` lets stage something for the owner. Each
|
|
65
|
+
* appends a proposal the owner decides or moves its caller's own processing mark, and nothing else. A command must
|
|
66
|
+
* be marked `proposesOnly` **and** end with one of these paths; adding a path widens what a read-only agent can
|
|
67
|
+
* write, so it needs its own review.
|
|
68
|
+
*/
|
|
69
|
+
export const PROPOSE_COMMANDS = ["messages acknowledge", "mail findings add"];
|
|
70
|
+
const PROPOSES = new WeakSet();
|
|
71
|
+
/** Marks a command of the `propose` tier; the lock lets it through only when its path is in `PROPOSE_COMMANDS`. */
|
|
72
|
+
export const proposesOnly = (command) => {
|
|
73
|
+
PROPOSES.add(command);
|
|
74
|
+
return command;
|
|
75
|
+
};
|
|
76
|
+
export const isProposal = (command) => {
|
|
77
|
+
if (!PROPOSES.has(command))
|
|
78
|
+
return false;
|
|
79
|
+
const path = pathOf(command).join(" ");
|
|
80
|
+
return PROPOSE_COMMANDS.some((listed) => path === listed || path.endsWith(` ${listed}`));
|
|
81
|
+
};
|
|
63
82
|
const STORE_WRITES = new WeakSet();
|
|
64
83
|
/** A local edit remains an edit even when it first fetches metadata from the messenger. */
|
|
65
84
|
export const changesStore = (command) => {
|
|
@@ -125,14 +144,16 @@ export const readsOverMcpAt = (root) => (path) => {
|
|
|
125
144
|
};
|
|
126
145
|
/**
|
|
127
146
|
* Whether `<PREFIX>_READ_ONLY` refuses the command as a change to the store. Every write that stays on this machine
|
|
128
|
-
* is refused unless `destroysNothing` marks it, so a new one fails closed
|
|
129
|
-
* keeps receiving, a remote write is `changesMessenger`'s, and an authority
|
|
147
|
+
* is refused unless `destroysNothing` marks it or it is of the `propose` tier, so a new one fails closed
|
|
148
|
+
* (WC-PERM-12). A fetch (`remote: "read"`) keeps receiving, a remote write is `changesMessenger`'s, and an authority
|
|
149
|
+
* change has its own refusal.
|
|
130
150
|
*/
|
|
131
151
|
export const isStoreChange = (command) => {
|
|
132
152
|
const effects = metaOf(command).effects;
|
|
133
153
|
return ((effects?.remote === "none" || STORE_WRITES.has(command)) &&
|
|
134
154
|
effects?.local === "write" &&
|
|
135
155
|
!KEPT_UNDER_LOCK.has(command) &&
|
|
156
|
+
!isProposal(command) &&
|
|
136
157
|
!changesAuthority(command) &&
|
|
137
158
|
writesFileNow(command));
|
|
138
159
|
};
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -69,7 +69,7 @@ export { sharedCommandTemplate } from "./contract-templates.js";
|
|
|
69
69
|
export { type Closeable, withDeadline } from "./deadline.js";
|
|
70
70
|
export { DEFAULT_CONFIG, ensureDefaultConfig } from "./default-config.js";
|
|
71
71
|
export { DISCOVERY_DESCRIPTIONS } from "./discovery-descriptions.js";
|
|
72
|
-
export { changesAuthority, changesAuthorityAt, changesAuthorityNow, destroysNothing, FETCH, fetchesOnly, fetchesOnlyAt, grantsAuthority, isLogin, isOtherServiceCall, isStoreChange, judgedEffects, judgedTargets, LOCAL_READ, LOCAL_WRITE, logsInOrOut, NO_EFFECTS, ownerOnlyOption, previewFlag, REMOTE_READ, REMOTE_WRITE, reachesOtherService, readsOverMcp, readsOverMcpAt, refuseUnderReadOnly, storeChangeRefusal, writesFileOnlyWith, } from "./effects.js";
|
|
72
|
+
export { changesAuthority, changesAuthorityAt, changesAuthorityNow, destroysNothing, FETCH, fetchesOnly, fetchesOnlyAt, grantsAuthority, isLogin, isOtherServiceCall, isProposal, isStoreChange, judgedEffects, judgedTargets, LOCAL_READ, LOCAL_WRITE, logsInOrOut, NO_EFFECTS, ownerOnlyOption, PROPOSE_COMMANDS, previewFlag, proposesOnly, REMOTE_READ, REMOTE_WRITE, reachesOtherService, readsOverMcp, readsOverMcpAt, refuseUnderReadOnly, storeChangeRefusal, writesFileOnlyWith, } from "./effects.js";
|
|
73
73
|
export { type CliEntry, type EntryContext, type EntryIo, openBrowser, startCli } from "./entry.js";
|
|
74
74
|
export { type AnswerOutput, answerSchema, type Body, type ItemBody, isBody, itemAnswer, itemOf, jsonlRecords, judgedAnswer, type ListBody, type ListInput, listOf, metaNow, printItem, renderAnswer, sealed, snakeKeys, snakeKeysKeeping, } from "./envelope.js";
|
|
75
75
|
export { withAbort } from "./execution.js";
|
|
@@ -85,7 +85,7 @@ export { commandPath, LIST_QUERY_GUIDE, listQuery, nativeField, nativeTermLists,
|
|
|
85
85
|
export { MCP_HTTP_DEFAULT_PORT, type McpServerOptions, type McpServerTarget, mcpServerCommand, } from "./mcp-server-command.js";
|
|
86
86
|
export { formatMeetingBatch, prepareMeetingBatch } from "./meeting-batch.js";
|
|
87
87
|
export { meetingEvidenceItem, meetingPersonContextItem } from "./meeting-evidence-answer.js";
|
|
88
|
-
export { parseEvidenceFindingsJson, parseMeetingFindingsJson } from "./meeting-findings-input.js";
|
|
88
|
+
export { parseEvidenceFindingsJson, parseMailFindingsJson, parseMeetingFindingsJson, } from "./meeting-findings-input.js";
|
|
89
89
|
export { meetingPreparationAnswer } from "./meeting-preparation-answer.js";
|
|
90
90
|
export { type MeetingPreparationReader, meetingPreparationInput, readMeetingPreparation, } from "./meeting-preparation-read.js";
|
|
91
91
|
export { readMeetingProjectCandidates } from "./meeting-project-candidates-read.js";
|
package/dist/cli/index.js
CHANGED
|
@@ -61,7 +61,7 @@ export { sharedCommandTemplate } from "./contract-templates.js";
|
|
|
61
61
|
export { withDeadline } from "./deadline.js";
|
|
62
62
|
export { DEFAULT_CONFIG, ensureDefaultConfig } from "./default-config.js";
|
|
63
63
|
export { DISCOVERY_DESCRIPTIONS } from "./discovery-descriptions.js";
|
|
64
|
-
export { changesAuthority, changesAuthorityAt, changesAuthorityNow, destroysNothing, FETCH, fetchesOnly, fetchesOnlyAt, grantsAuthority, isLogin, isOtherServiceCall, isStoreChange, judgedEffects, judgedTargets, LOCAL_READ, LOCAL_WRITE, logsInOrOut, NO_EFFECTS, ownerOnlyOption, previewFlag, REMOTE_READ, REMOTE_WRITE, reachesOtherService, readsOverMcp, readsOverMcpAt, refuseUnderReadOnly, storeChangeRefusal, writesFileOnlyWith, } from "./effects.js";
|
|
64
|
+
export { changesAuthority, changesAuthorityAt, changesAuthorityNow, destroysNothing, FETCH, fetchesOnly, fetchesOnlyAt, grantsAuthority, isLogin, isOtherServiceCall, isProposal, isStoreChange, judgedEffects, judgedTargets, LOCAL_READ, LOCAL_WRITE, logsInOrOut, NO_EFFECTS, ownerOnlyOption, PROPOSE_COMMANDS, previewFlag, proposesOnly, REMOTE_READ, REMOTE_WRITE, reachesOtherService, readsOverMcp, readsOverMcpAt, refuseUnderReadOnly, storeChangeRefusal, writesFileOnlyWith, } from "./effects.js";
|
|
65
65
|
export { openBrowser, startCli } from "./entry.js";
|
|
66
66
|
export { answerSchema, isBody, itemAnswer, itemOf, jsonlRecords, judgedAnswer, listOf, metaNow, printItem, renderAnswer, sealed, snakeKeys, snakeKeysKeeping, } from "./envelope.js";
|
|
67
67
|
export { withAbort } from "./execution.js";
|
|
@@ -77,7 +77,7 @@ export { commandPath, LIST_QUERY_GUIDE, listQuery, nativeField, nativeTermLists,
|
|
|
77
77
|
export { MCP_HTTP_DEFAULT_PORT, mcpServerCommand, } from "./mcp-server-command.js";
|
|
78
78
|
export { formatMeetingBatch, prepareMeetingBatch } from "./meeting-batch.js";
|
|
79
79
|
export { meetingEvidenceItem, meetingPersonContextItem } from "./meeting-evidence-answer.js";
|
|
80
|
-
export { parseEvidenceFindingsJson, parseMeetingFindingsJson } from "./meeting-findings-input.js";
|
|
80
|
+
export { parseEvidenceFindingsJson, parseMailFindingsJson, parseMeetingFindingsJson, } from "./meeting-findings-input.js";
|
|
81
81
|
export { meetingPreparationAnswer } from "./meeting-preparation-answer.js";
|
|
82
82
|
export { meetingPreparationInput, readMeetingPreparation, } from "./meeting-preparation-read.js";
|
|
83
83
|
export { readMeetingProjectCandidates } from "./meeting-project-candidates-read.js";
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { type MailFindingsInput } from "../mail/findings.js";
|
|
1
2
|
import { type FindingsInput, type MeetingFindingsInput } from "../meetings/index.js";
|
|
2
3
|
export declare const parseMeetingFindingsJson: (text: string) => MeetingFindingsInput;
|
|
3
4
|
export declare const parseEvidenceFindingsJson: (text: string) => FindingsInput;
|
|
5
|
+
/** A mail findings batch as `mail findings add` reads it: snake_case JSON, checked for shape before the store. */
|
|
6
|
+
export declare const parseMailFindingsJson: (text: string) => MailFindingsInput;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
|
+
import { validateMailFindings } from "../mail/findings.js";
|
|
2
3
|
import { validateMeetingFindings } from "../meetings/index.js";
|
|
3
4
|
import { validateEvidenceFindings } from "../store/evidence-findings.js";
|
|
4
5
|
const keys = {
|
|
@@ -6,6 +7,7 @@ const keys = {
|
|
|
6
7
|
due_at: "dueAt",
|
|
7
8
|
due_evidence: "dueEvidence",
|
|
8
9
|
assignee_evidence: "assigneeEvidence",
|
|
10
|
+
memory_kind: "memoryKind",
|
|
9
11
|
};
|
|
10
12
|
const parseFindingsJson = (text, label, validate) => {
|
|
11
13
|
if (Buffer.byteLength(text, "utf8") > 65536)
|
|
@@ -40,3 +42,5 @@ const parseFindingsJson = (text, label, validate) => {
|
|
|
40
42
|
};
|
|
41
43
|
export const parseMeetingFindingsJson = (text) => parseFindingsJson(text, "meeting findings", validateMeetingFindings);
|
|
42
44
|
export const parseEvidenceFindingsJson = (text) => parseFindingsJson(text, "evidence findings", validateEvidenceFindings);
|
|
45
|
+
/** A mail findings batch as `mail findings add` reads it: snake_case JSON, checked for shape before the store. */
|
|
46
|
+
export const parseMailFindingsJson = (text) => parseFindingsJson(text, "mail findings", validateMailFindings);
|
|
@@ -251,6 +251,9 @@ export declare const conversationShown: (account: AccountKey, { summary, message
|
|
|
251
251
|
bulk?: boolean | undefined;
|
|
252
252
|
list_id?: string | null | undefined;
|
|
253
253
|
rule_id?: number | null | undefined;
|
|
254
|
+
fingerprint?: string | undefined;
|
|
255
|
+
new_sender?: boolean | undefined;
|
|
256
|
+
sender_identities?: number | undefined;
|
|
254
257
|
} | undefined;
|
|
255
258
|
provider_metadata?: {
|
|
256
259
|
[x: string]: unknown;
|
|
@@ -228,6 +228,9 @@ export declare const threadAnswer: ({ items, ...thread }: ThreadContext, reader:
|
|
|
228
228
|
bulk?: boolean | undefined;
|
|
229
229
|
list_id?: string | null | undefined;
|
|
230
230
|
rule_id?: number | null | undefined;
|
|
231
|
+
fingerprint?: string | undefined;
|
|
232
|
+
new_sender?: boolean | undefined;
|
|
233
|
+
sender_identities?: number | undefined;
|
|
231
234
|
} | undefined;
|
|
232
235
|
provider_metadata?: {
|
|
233
236
|
[x: string]: unknown;
|
|
@@ -232,6 +232,9 @@ export declare const writtenAnswer: ({ operationId, sendId, message, messages, s
|
|
|
232
232
|
bulk?: boolean | undefined;
|
|
233
233
|
list_id?: string | null | undefined;
|
|
234
234
|
rule_id?: number | null | undefined;
|
|
235
|
+
fingerprint?: string | undefined;
|
|
236
|
+
new_sender?: boolean | undefined;
|
|
237
|
+
sender_identities?: number | undefined;
|
|
235
238
|
} | undefined;
|
|
236
239
|
provider_metadata?: {
|
|
237
240
|
[x: string]: unknown;
|
|
@@ -454,6 +457,9 @@ export declare const writtenAnswer: ({ operationId, sendId, message, messages, s
|
|
|
454
457
|
bulk?: boolean | undefined;
|
|
455
458
|
list_id?: string | null | undefined;
|
|
456
459
|
rule_id?: number | null | undefined;
|
|
460
|
+
fingerprint?: string | undefined;
|
|
461
|
+
new_sender?: boolean | undefined;
|
|
462
|
+
sender_identities?: number | undefined;
|
|
457
463
|
} | undefined;
|
|
458
464
|
provider_metadata?: {
|
|
459
465
|
[x: string]: unknown;
|
|
@@ -9,10 +9,15 @@ export interface ScheduleHost {
|
|
|
9
9
|
env: NodeJS.ProcessEnv;
|
|
10
10
|
profile: string;
|
|
11
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Whether mail is stored past the holder's mark (`holderHasMail`). Given, `schedule agent` takes `--on-new-mail`:
|
|
14
|
+
* the agent then runs only after a sync stored mail it has not processed.
|
|
15
|
+
*/
|
|
16
|
+
newMail?: (command: Command, holder: string) => Promise<boolean>;
|
|
12
17
|
}
|
|
13
18
|
/**
|
|
14
19
|
* Runs the CLI's own commands, or an agent, later or on a timer — through systemd (Linux), launchd
|
|
15
20
|
* (macOS) or Task Scheduler (Windows). Every timer runs `schedule exec <file>`; the schedule file holds
|
|
16
21
|
* the rest, so what runs and with which variables is the same on all three.
|
|
17
22
|
*/
|
|
18
|
-
export declare const scheduleCommandFor: ({ app, context: contextOf }: ScheduleHost) => Command;
|
|
23
|
+
export declare const scheduleCommandFor: ({ app, context: contextOf, newMail }: ScheduleHost) => Command;
|
|
@@ -7,6 +7,7 @@ import { describeWhen, findProgram, lastRun, listSchedules, readSchedule, runSch
|
|
|
7
7
|
import { thisMachine } from "../../background/system.js";
|
|
8
8
|
import { locationVariables } from "../../background/units.js";
|
|
9
9
|
import { parseDuration } from "../../domain/duration.js";
|
|
10
|
+
import { HOLDER } from "../../mail/marks.js";
|
|
10
11
|
import { readOnlyLockOf } from "../../ports/app.js";
|
|
11
12
|
import { aheadOf } from "../../services/moment.js";
|
|
12
13
|
import { storePath } from "../../store/path.js";
|
|
@@ -18,6 +19,8 @@ import { SCHEDULES_QUERY, scheduleFilter } from "../messenger/list-result-querie
|
|
|
18
19
|
import { lineOf } from "../steps.js";
|
|
19
20
|
/** Each run of an agent is a paid model call that reads chats; keeping the store current is `serve`'s job. */
|
|
20
21
|
const AGENT_MINIMUM_MINUTES = 60;
|
|
22
|
+
/** A run gated on new mail costs a store read when nothing came, so it may check as often as mail syncs. */
|
|
23
|
+
const GATED_AGENT_MINIMUM_MINUTES = 5;
|
|
21
24
|
const COMMAND_MINIMUM_MINUTES = 1;
|
|
22
25
|
const HARNESSES = ["claude", "codex"];
|
|
23
26
|
const whenOf = ({ every, at, atTime }, minimum) => {
|
|
@@ -78,7 +81,7 @@ const promptExample = (app) => app.messenger === false
|
|
|
78
81
|
* (macOS) or Task Scheduler (Windows). Every timer runs `schedule exec <file>`; the schedule file holds
|
|
79
82
|
* the rest, so what runs and with which variables is the same on all three.
|
|
80
83
|
*/
|
|
81
|
-
export const scheduleCommandFor = ({ app, context: contextOf }) => {
|
|
84
|
+
export const scheduleCommandFor = ({ app, context: contextOf, newMail }) => {
|
|
82
85
|
const command = new Command("schedule").description(`run a ${app.command} command or an agent later or on a timer (systemd, launchd, Task Scheduler); an agent cannot send`);
|
|
83
86
|
const prepare = (self, resolving = {}) => {
|
|
84
87
|
const context = contextOf(self, resolving);
|
|
@@ -114,6 +117,13 @@ export const scheduleCommandFor = ({ app, context: contextOf }) => {
|
|
|
114
117
|
};
|
|
115
118
|
return { context, system, state, say, timer, environment, save };
|
|
116
119
|
};
|
|
120
|
+
/** A schedule gated on new mail waits while nothing is stored past its holder's mark. */
|
|
121
|
+
const waits = async (self, file) => {
|
|
122
|
+
const holder = existsSync(file) ? readSchedule(file).onNewMail : undefined;
|
|
123
|
+
if (holder === undefined || !newMail || (await newMail(self, holder)))
|
|
124
|
+
return undefined;
|
|
125
|
+
return holder;
|
|
126
|
+
};
|
|
117
127
|
withWhen(grantsAuthority(annotate(command.command("command"), {
|
|
118
128
|
literal_after_dashes: true,
|
|
119
129
|
effects: LOCAL_WRITE,
|
|
@@ -151,6 +161,8 @@ export const scheduleCommandFor = ({ app, context: contextOf }) => {
|
|
|
151
161
|
.addOption(new Option("--max-cost <usd>", "claude only: stop a run that costs more than this, in US dollars").argParser(Number))).action(async function (name, harness, prompt) {
|
|
152
162
|
const { context, system, environment, save } = prepare(this);
|
|
153
163
|
const options = this.opts();
|
|
164
|
+
if (options.onNewMail !== undefined && !HOLDER.test(options.onNewMail))
|
|
165
|
+
throw new CliError("validation_error", `--on-new-mail takes a holder: lower-case letters, digits and dashes`);
|
|
154
166
|
const program = findProgram(harness, context.env, system.platform);
|
|
155
167
|
if (!program)
|
|
156
168
|
throw new CliError("not_found", `${harness} is not on PATH`);
|
|
@@ -188,11 +200,16 @@ export const scheduleCommandFor = ({ app, context: contextOf }) => {
|
|
|
188
200
|
name: scheduleName(name),
|
|
189
201
|
kind: "agent",
|
|
190
202
|
argv,
|
|
191
|
-
when: whenOf(options, AGENT_MINIMUM_MINUTES),
|
|
203
|
+
when: whenOf(options, options.onNewMail ? GATED_AGENT_MINIMUM_MINUTES : AGENT_MINIMUM_MINUTES),
|
|
192
204
|
environment: environment(),
|
|
193
205
|
createdAt: new Date().toISOString(),
|
|
206
|
+
...(options.onNewMail ? { onNewMail: options.onNewMail } : {}),
|
|
194
207
|
});
|
|
195
208
|
});
|
|
209
|
+
if (newMail)
|
|
210
|
+
command.commands
|
|
211
|
+
.find((one) => one.name() === "agent")
|
|
212
|
+
?.option("--on-new-mail <holder>", `run only when mail is stored past this holder's mark — after a sync brought new mail; may check every ${GATED_AGENT_MINIMUM_MINUTES}m`);
|
|
196
213
|
withQuery(annotate(command.command("list"), {
|
|
197
214
|
effects: LOCAL_READ,
|
|
198
215
|
examples: [`${app.command} personal schedule list`, `${app.command} personal schedule list kind:agent`],
|
|
@@ -241,6 +258,9 @@ export const scheduleCommandFor = ({ app, context: contextOf }) => {
|
|
|
241
258
|
.argument("<name>", "the schedule's name, as `schedule list` shows it")
|
|
242
259
|
.action(async function (name) {
|
|
243
260
|
const { context, system, state, say, timer } = prepare(this);
|
|
261
|
+
const holder = await waits(this, scheduleFile(state, scheduleName(name)));
|
|
262
|
+
if (holder !== undefined)
|
|
263
|
+
return say({ name, skipped: true, holder }, [`${name}: skipped — no mail stored past ${holder}'s mark`]);
|
|
244
264
|
const last = await untilChildEnds(this, (signal) => runSchedule(app, system, context.env, scheduleFile(state, scheduleName(name)), {
|
|
245
265
|
timer: timer(),
|
|
246
266
|
...(signal ? { signal } : {}),
|
|
@@ -273,6 +293,8 @@ export const scheduleCommandFor = ({ app, context: contextOf }) => {
|
|
|
273
293
|
.action(async function (file) {
|
|
274
294
|
// A timer starts it with no profile named; the schedule's own environment carries the profile.
|
|
275
295
|
const { context, system, timer } = prepare(this, { needsProfile: false });
|
|
296
|
+
if ((await waits(this, file)) !== undefined)
|
|
297
|
+
return;
|
|
276
298
|
const last = await untilChildEnds(this, (signal) => runSchedule(app, system, context.env, file, {
|
|
277
299
|
timer: timer(),
|
|
278
300
|
untilUnlocked: true,
|
|
@@ -349,6 +349,9 @@ export declare const contactMessages: v.StrictObjectSchema<{
|
|
|
349
349
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
350
350
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
351
351
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
352
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
353
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
354
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
352
355
|
readonly reply_to: v.ArraySchema<v.StrictObjectSchema<{
|
|
353
356
|
readonly name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
354
357
|
readonly address: v.StringSchema<undefined>;
|
|
@@ -1124,6 +1127,9 @@ export declare const contactContext: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
1124
1127
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
1125
1128
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
1126
1129
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
1130
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
1131
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
1132
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
1127
1133
|
readonly reply_to: v.ArraySchema<v.StrictObjectSchema<{
|
|
1128
1134
|
readonly name: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
1129
1135
|
readonly address: v.StringSchema<undefined>;
|
|
@@ -227,6 +227,9 @@ export declare const conversationDetails: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
227
227
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
228
228
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
229
229
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
230
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
231
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
232
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
230
233
|
}, undefined>, undefined>;
|
|
231
234
|
readonly provider_metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
232
235
|
}, undefined>, undefined>;
|
|
@@ -447,6 +450,9 @@ export declare const conversationDetails: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
447
450
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
448
451
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
449
452
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
453
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
454
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
455
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
450
456
|
}, undefined>, undefined>;
|
|
451
457
|
readonly provider_metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
452
458
|
}, undefined>], undefined>;
|
|
@@ -218,6 +218,9 @@ export declare const contribution: v.StrictObjectSchema<{
|
|
|
218
218
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
219
219
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
220
220
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
221
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
222
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
223
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
221
224
|
}, undefined>, undefined>;
|
|
222
225
|
readonly provider_metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
223
226
|
}, undefined>, "entries" | "~run" | "~standard" | "~types"> & {
|
|
@@ -438,6 +441,9 @@ export declare const contribution: v.StrictObjectSchema<{
|
|
|
438
441
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
439
442
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
440
443
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
444
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
445
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
446
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
441
447
|
}, undefined>, undefined>;
|
|
442
448
|
readonly provider_metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
443
449
|
}, "chat_title" | "ref" | "sender_name" | "text" | "timestamp">;
|
|
@@ -696,6 +702,9 @@ export declare const contribution: v.StrictObjectSchema<{
|
|
|
696
702
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
697
703
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
698
704
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
705
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
706
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
707
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
699
708
|
}, undefined>, undefined>;
|
|
700
709
|
readonly provider_metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
701
710
|
}, undefined>, "entries" | "~run" | "~standard" | "~types"> & {
|
|
@@ -916,6 +925,9 @@ export declare const contribution: v.StrictObjectSchema<{
|
|
|
916
925
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
917
926
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
918
927
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
928
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
929
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
930
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
919
931
|
}, undefined>, undefined>;
|
|
920
932
|
readonly provider_metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
921
933
|
}, "chat_title" | "ref" | "sender_name" | "text" | "timestamp">;
|
|
@@ -1210,6 +1222,9 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
1210
1222
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
1211
1223
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
1212
1224
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
1225
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
1226
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
1227
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
1213
1228
|
}, undefined>, undefined>;
|
|
1214
1229
|
readonly provider_metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
1215
1230
|
}, undefined>, "entries" | "~run" | "~standard" | "~types"> & {
|
|
@@ -1430,6 +1445,9 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
1430
1445
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
1431
1446
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
1432
1447
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
1448
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
1449
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
1450
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
1433
1451
|
}, undefined>, undefined>;
|
|
1434
1452
|
readonly provider_metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
1435
1453
|
}, "chat_title" | "ref" | "sender_name" | "text" | "timestamp">;
|
|
@@ -1688,6 +1706,9 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
1688
1706
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
1689
1707
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
1690
1708
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
1709
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
1710
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
1711
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
1691
1712
|
}, undefined>, undefined>;
|
|
1692
1713
|
readonly provider_metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
1693
1714
|
}, undefined>, "entries" | "~run" | "~standard" | "~types"> & {
|
|
@@ -1908,6 +1929,9 @@ export declare const evidence: v.UnionSchema<[v.StrictObjectSchema<{
|
|
|
1908
1929
|
readonly bulk: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
1909
1930
|
readonly list_id: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
1910
1931
|
readonly rule_id: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
1932
|
+
readonly fingerprint: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
1933
|
+
readonly new_sender: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
1934
|
+
readonly sender_identities: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
1911
1935
|
}, undefined>, undefined>;
|
|
1912
1936
|
readonly provider_metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
1913
1937
|
}, "chat_title" | "ref" | "sender_name" | "text" | "timestamp">;
|