@wirecat/cli-core 0.550.0 → 0.552.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 +235 -0
- package/README.md +1 -1
- package/THIRD_PARTY_NOTICES +41 -0
- package/dist/background/schedules.d.ts +12 -1
- package/dist/background/schedules.js +65 -24
- package/dist/background/units.d.ts +16 -9
- package/dist/background/units.js +26 -11
- package/dist/calendar/ics.d.ts +1 -1
- package/dist/calendar/ics.js +5 -2
- package/dist/calendar/windows-zones.generated.d.ts +1 -0
- package/dist/calendar/windows-zones.generated.js +146 -0
- package/dist/cli/compact.js +2 -0
- package/dist/cli/context.d.ts +2 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +3 -0
- package/dist/cli/meeting-findings-input.js +4 -3
- package/dist/cli/meeting-preparation-answer.d.ts +3 -0
- package/dist/cli/meeting-preparation-projects.d.ts +3 -0
- package/dist/cli/meeting-preparation-read.d.ts +3 -0
- package/dist/cli/messenger/backfill-command.js +28 -1
- package/dist/cli/messenger/context.js +1 -0
- package/dist/cli/messenger/history-gaps.js +4 -4
- package/dist/cli/messenger/mcp-command.js +1 -0
- package/dist/cli/messenger/messages-delete-command.js +7 -8
- package/dist/cli/messenger/projects-command.js +47 -2
- package/dist/cli/messenger/search-answers.js +8 -1
- package/dist/cli/messenger/serve-catch-up.d.ts +43 -0
- package/dist/cli/messenger/serve-catch-up.js +90 -0
- package/dist/cli/messenger/serve-command.js +54 -1
- package/dist/cli/messenger/server-command.d.ts +4 -3
- package/dist/cli/messenger/server-command.js +30 -12
- package/dist/cli/payment-query.d.ts +8 -0
- package/dist/cli/payment-query.js +27 -0
- package/dist/cli/program.js +9 -4
- package/dist/cli/project-status-rows.d.ts +8 -0
- package/dist/cli/project-status-rows.js +102 -0
- package/dist/cli/project-status.d.ts +132 -0
- package/dist/cli/project-status.js +248 -0
- package/dist/cli/schedule/schedule-command.js +5 -1
- package/dist/cli/steps.js +4 -1
- package/dist/domain/knowledge.d.ts +1 -1
- package/dist/domain/knowledge.js +1 -1
- package/dist/domain/status-words.d.ts +3 -0
- package/dist/domain/status-words.js +44 -0
- package/dist/entities/fact.d.ts +12 -1
- package/dist/entities/fact.js +13 -0
- package/dist/entities/hit.d.ts +5 -0
- package/dist/entities/hit.js +5 -0
- package/dist/entities/index.d.ts +45 -2
- package/dist/entities/listener.d.ts +6 -0
- package/dist/entities/listener.js +1 -0
- package/dist/entities/meeting-findings.d.ts +1 -1
- package/dist/entities/meeting-preparation.d.ts +3 -0
- package/dist/entities/message-transfer.d.ts +16 -0
- package/dist/entities/message-transfer.js +6 -0
- package/dist/errors/reasons.js +1 -0
- package/dist/mcp/app-server.js +1 -0
- package/dist/mcp/http/oauth.d.ts +2 -1
- package/dist/mcp/http/oauth.js +2 -2
- package/dist/mcp/http/serve.d.ts +2 -0
- package/dist/mcp/http/serve.js +2 -1
- package/dist/mcp/meeting-preparation.d.ts +3 -0
- package/dist/mcp/server.js +1 -0
- package/dist/mcp/surface.js +1 -1
- package/dist/meetings/answers.d.ts +5 -0
- package/dist/meetings/answers.js +8 -0
- package/dist/meetings/cli/index.js +14 -0
- package/dist/meetings/findings-rules.d.ts +14 -3
- package/dist/meetings/findings-rules.js +16 -2
- package/dist/meetings/index.d.ts +5 -3
- package/dist/meetings/index.js +3 -1
- package/dist/meetings/ingest.js +2 -1
- package/dist/meetings/language.d.ts +5 -0
- package/dist/meetings/language.js +57 -0
- package/dist/meetings/mcp/search.d.ts +3 -0
- package/dist/meetings/meeting-context.d.ts +2 -3
- package/dist/meetings/meeting-context.js +3 -4
- package/dist/meetings/payment.d.ts +27 -0
- package/dist/meetings/payment.js +81 -0
- package/dist/meetings/project-evidence-answer.d.ts +3 -0
- package/dist/meetings/result-items.d.ts +9 -0
- package/dist/meetings/result-items.js +7 -0
- package/dist/meetings/store.d.ts +22 -0
- package/dist/meetings/testing/memory.js +3 -0
- package/dist/meetings/transcription.d.ts +2 -0
- package/dist/meetings/transcription.js +5 -1
- package/dist/search/lucene/types.d.ts +7 -0
- package/dist/search/lucene/types.js +11 -1
- package/dist/services/archive.d.ts +13 -0
- package/dist/services/archive.js +56 -5
- package/dist/services/deps.d.ts +3 -0
- package/dist/services/history-limits.d.ts +2 -0
- package/dist/services/index.d.ts +4 -1
- package/dist/services/index.js +4 -1
- package/dist/services/job-query.d.ts +5 -2
- package/dist/services/job-query.js +5 -2
- package/dist/services/link-scorers/alias-hits.d.ts +7 -0
- package/dist/services/link-scorers/alias-hits.js +54 -0
- package/dist/services/link-scorers/chat-senders.d.ts +6 -0
- package/dist/services/link-scorers/chat-senders.js +56 -0
- package/dist/services/link-scorers/chat-title.d.ts +6 -0
- package/dist/services/link-scorers/chat-title.js +44 -0
- package/dist/services/link-scorers/email-domain.d.ts +6 -0
- package/dist/services/link-scorers/email-domain.js +64 -0
- package/dist/services/link-scorers/index.d.ts +9 -0
- package/dist/services/link-scorers/index.js +8 -0
- package/dist/services/link-scorers/mail-thread.d.ts +3 -0
- package/dist/services/link-scorers/mail-thread.js +74 -0
- package/dist/services/link-scorers/member-chats.d.ts +3 -0
- package/dist/services/link-scorers/member-chats.js +40 -0
- package/dist/services/link-scorers/member-dialog.d.ts +3 -0
- package/dist/services/link-scorers/member-dialog.js +34 -0
- package/dist/services/link-scorers/scan.d.ts +41 -0
- package/dist/services/link-scorers/scan.js +244 -0
- package/dist/services/link-scorers/shared.d.ts +26 -0
- package/dist/services/link-scorers/shared.js +48 -0
- package/dist/services/link-scorers/types.d.ts +77 -0
- package/dist/services/link-scorers/types.js +1 -0
- package/dist/services/messages-archive-search.js +3 -2
- package/dist/services/messages-combined.js +2 -2
- package/dist/services/messages-discovery.js +2 -2
- package/dist/services/notes-search.js +4 -5
- package/dist/services/project-status/index.d.ts +71 -0
- package/dist/services/project-status/index.js +196 -0
- package/dist/services/project-status/items.d.ts +10 -0
- package/dist/services/project-status/items.js +23 -0
- package/dist/services/project-status/signals/amounts.d.ts +20 -0
- package/dist/services/project-status/signals/amounts.js +91 -0
- package/dist/services/project-status/signals/children.d.ts +13 -0
- package/dist/services/project-status/signals/children.js +28 -0
- package/dist/services/project-status/signals/coverage.d.ts +13 -0
- package/dist/services/project-status/signals/coverage.js +30 -0
- package/dist/services/project-status/signals/index.d.ts +3 -0
- package/dist/services/project-status/signals/index.js +21 -0
- package/dist/services/project-status/signals/last-message.d.ts +4 -0
- package/dist/services/project-status/signals/last-message.js +22 -0
- package/dist/services/project-status/signals/payments.d.ts +9 -0
- package/dist/services/project-status/signals/payments.js +24 -0
- package/dist/services/project-status/signals/promises.d.ts +17 -0
- package/dist/services/project-status/signals/promises.js +109 -0
- package/dist/services/project-status/signals/questions.d.ts +8 -0
- package/dist/services/project-status/signals/questions.js +38 -0
- package/dist/services/project-status/signals/reply-next.d.ts +19 -0
- package/dist/services/project-status/signals/reply-next.js +75 -0
- package/dist/services/project-status/signals/topics.d.ts +10 -0
- package/dist/services/project-status/signals/topics.js +50 -0
- package/dist/services/project-status/types.d.ts +84 -0
- package/dist/services/project-status/types.js +1 -0
- package/dist/services/proposals/index.d.ts +1 -0
- package/dist/services/proposals/index.js +1 -0
- package/dist/services/proposals/kinds/findings.d.ts +3 -0
- package/dist/services/proposals/kinds/findings.js +8 -1
- package/dist/services/search-all-meetings.d.ts +3 -0
- package/dist/services/search-all-meetings.js +6 -1
- package/dist/speech/local.d.ts +2 -0
- package/dist/speech/local.js +8 -1
- package/dist/speech/models.d.ts +2 -0
- package/dist/speech/models.js +2 -0
- package/dist/store/decisions.d.ts +5 -1
- package/dist/store/decisions.js +5 -1
- package/dist/store/driver.d.ts +11 -0
- package/dist/store/driver.js +13 -0
- package/dist/store/drivers/node-sqlite.d.ts +1 -1
- package/dist/store/drivers/node-sqlite.js +3 -0
- package/dist/store/evidence-findings.js +1 -0
- package/dist/store/index.d.ts +2 -1
- package/dist/store/index.js +1 -0
- package/dist/store/project-transfer/request.d.ts +1 -1
- package/dist/store/project-transfer/schema.d.ts +2 -2
- package/dist/store/project-transfer/snapshot-model.d.ts +2 -2
- package/dist/store/sqlite/evidence-findings.js +5 -1
- package/dist/store/sqlite/facts.d.ts +13 -0
- package/dist/store/sqlite/facts.js +64 -6
- package/dist/store/sqlite/findings-core.js +14 -1
- package/dist/store/sqlite/knowledge.d.ts +16 -2
- package/dist/store/sqlite/knowledge.js +1 -0
- package/dist/store/sqlite/lucene.d.ts +1 -1
- package/dist/store/sqlite/lucene.js +33 -7
- package/dist/store/sqlite/meeting-hit-search.js +10 -3
- package/dist/store/sqlite/meeting-languages.d.ts +4 -0
- package/dist/store/sqlite/meeting-languages.js +36 -0
- package/dist/store/sqlite/meetings.d.ts +2 -1
- package/dist/store/sqlite/meetings.js +9 -3
- package/dist/store/sqlite/note-search.js +2 -2
- package/dist/store/sqlite/project-transfer/snapshot.d.ts +1 -1
- package/dist/store/sqlite/relation-proposals.d.ts +29 -2
- package/dist/store/sqlite/relation-proposals.js +75 -4
- package/dist/store/store.d.ts +1 -0
- package/package.json +3 -3
- package/parity.json +11 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { transcriptLanguage } from "../../meetings/index.js";
|
|
2
|
+
import { positiveReadInteger } from "./meeting-reads.js";
|
|
3
|
+
import { read, writeBatch } from "./transaction.js";
|
|
4
|
+
export const meetingLanguagesOver = ({ database }) => ({
|
|
5
|
+
async fillTranscriptLanguages({ accountId, apply, now }) {
|
|
6
|
+
positiveReadInteger(accountId, "accountId");
|
|
7
|
+
const found = read(database, () => {
|
|
8
|
+
const rows = database.prepare("SELECT text FROM meeting_transcript_rows WHERE meeting_transcript_id = ?");
|
|
9
|
+
return database
|
|
10
|
+
.prepare(`SELECT t.id FROM meeting_transcripts t JOIN meetings m ON m.id = t.meeting_id
|
|
11
|
+
WHERE m.account_id = ? AND t.language IS NULL AND t.deleted_at IS NULL ORDER BY t.id`)
|
|
12
|
+
.all(accountId)
|
|
13
|
+
.map(({ id }) => ({
|
|
14
|
+
id: Number(id),
|
|
15
|
+
language: transcriptLanguage(rows.all(Number(id)).map((row) => String(row.text))),
|
|
16
|
+
}));
|
|
17
|
+
});
|
|
18
|
+
if (apply) {
|
|
19
|
+
const update = database.prepare("UPDATE meeting_transcripts SET language = ?, updated_at = ? WHERE id = ? AND language IS NULL");
|
|
20
|
+
writeBatch(database, () => {
|
|
21
|
+
for (const { id, language } of found)
|
|
22
|
+
if (language !== null)
|
|
23
|
+
update.run(language, now, id);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
const counts = new Map();
|
|
27
|
+
for (const { language } of found)
|
|
28
|
+
counts.set(language, (counts.get(language) ?? 0) + 1);
|
|
29
|
+
return {
|
|
30
|
+
accountId,
|
|
31
|
+
applied: apply,
|
|
32
|
+
transcripts: found.length,
|
|
33
|
+
languages: [...counts].map(([language, transcripts]) => ({ language, transcripts })),
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Attachment, MeetingChatLinesStore, MeetingContextStore, MeetingParticipantSearchStore, MeetingPreparationContextStore, MeetingPreparationKnowledgeStore, MeetingPreparationNotesStore, MeetingRelatedHistoryStore, MeetingReviewStore, MeetingSearchIndexStore, MeetingSearchStore, MeetingSeriesHistoryStore, MeetingStatsStore, MeetingStore, MeetingTranscriptReceiptStore, MeetingTranscriptStore, NewRecord } from "../../meetings/index.js";
|
|
2
2
|
import type { CacheDatabase } from "../driver.js";
|
|
3
|
+
import { type MeetingLanguageStore } from "./meeting-languages.js";
|
|
3
4
|
import { type MeetingContextReadCapabilities, type MeetingReadCapabilities } from "./meeting-reads.js";
|
|
4
5
|
import type { StoreContext } from "./open.js";
|
|
5
6
|
type Row = Record<string, unknown>;
|
|
@@ -11,7 +12,7 @@ export declare const saveAttachment: (database: CacheDatabase, type: string, par
|
|
|
11
12
|
export declare const drainMeetingIndex: (database: CacheDatabase, batch?: number) => number;
|
|
12
13
|
/** Each word of the query, as a prefix, all required. */
|
|
13
14
|
export declare const wordsQuery: (query: string) => string | null;
|
|
14
|
-
export type StoredMeetings = MeetingStore & MeetingPreparationContextStore & MeetingPreparationKnowledgeStore & MeetingPreparationNotesStore & MeetingRelatedHistoryStore & MeetingSeriesHistoryStore & MeetingTranscriptStore & MeetingReadCapabilities & MeetingContextReadCapabilities & MeetingParticipantSearchStore & MeetingSearchStore & MeetingTranscriptReceiptStore & MeetingContextStore & MeetingSearchIndexStore & MeetingStatsStore & MeetingReviewStore & MeetingChatLinesStore;
|
|
15
|
+
export type StoredMeetings = MeetingStore & MeetingPreparationContextStore & MeetingPreparationKnowledgeStore & MeetingPreparationNotesStore & MeetingRelatedHistoryStore & MeetingSeriesHistoryStore & MeetingTranscriptStore & MeetingReadCapabilities & MeetingContextReadCapabilities & MeetingParticipantSearchStore & MeetingSearchStore & MeetingTranscriptReceiptStore & MeetingContextStore & MeetingSearchIndexStore & MeetingStatsStore & MeetingReviewStore & MeetingChatLinesStore & MeetingLanguageStore;
|
|
15
16
|
/** The `MeetingStore` of `src/meetings/` over the shared store. */
|
|
16
17
|
export declare const meetingStoreOver: (context: StoreContext) => StoredMeetings;
|
|
17
18
|
export {};
|
|
@@ -11,6 +11,7 @@ import { meetingContextLinksOver } from "./meeting-context-links.js";
|
|
|
11
11
|
import { meetingHitIndexOver } from "./meeting-hit-index.js";
|
|
12
12
|
import { meetingHitSearchOver } from "./meeting-hit-search.js";
|
|
13
13
|
import { INDEX_CODES, indexedText, meetingRowid, summaryOf } from "./meeting-index-values.js";
|
|
14
|
+
import { meetingLanguagesOver } from "./meeting-languages.js";
|
|
14
15
|
import { meetingParticipantSearchOver } from "./meeting-participant-search.js";
|
|
15
16
|
import { meetingPreparationContextOver } from "./meeting-preparation-context.js";
|
|
16
17
|
import { meetingPreparationKnowledgeOver } from "./meeting-preparation-knowledge.js";
|
|
@@ -516,17 +517,18 @@ const search = (database, query, filter) => {
|
|
|
516
517
|
.prepare(`WITH hit AS (SELECT rowid AS r FROM meeting_words WHERE meeting_words MATCH ?),
|
|
517
518
|
picked AS (SELECT id, row_number() OVER (ORDER BY coalesce(started_at, 0) DESC, id) AS n FROM (${picked.sql}))
|
|
518
519
|
SELECT p.n, 0 AS kind, t.id AS a, r.position AS b, r.id, t.meeting_id, r.start_ms, coalesce(length(CAST(r.text AS BLOB)),0) AS bytes,
|
|
519
|
-
r.speaker_name AS speaker, m.account_id
|
|
520
|
+
r.speaker_name AS speaker, m.account_id, t.language,
|
|
521
|
+
(SELECT count(*) FROM meeting_transcript_rows n WHERE n.meeting_transcript_id = t.id) AS lines_total
|
|
520
522
|
FROM hit h JOIN meeting_transcript_rows r ON h.r % 4 = 1 AND r.id = h.r / 4
|
|
521
523
|
JOIN meeting_transcripts t ON t.id = r.meeting_transcript_id
|
|
522
524
|
AND t.superseded_at IS NULL AND t.deleted_at IS NULL
|
|
523
525
|
JOIN picked p ON p.id = t.meeting_id JOIN meetings m ON m.id = t.meeting_id
|
|
524
526
|
UNION ALL
|
|
525
|
-
SELECT p.n, 1, c.id, 0, c.id, c.meeting_id, NULL, coalesce(length(CAST(c.text AS BLOB)),0), NULL, NULL
|
|
527
|
+
SELECT p.n, 1, c.id, 0, c.id, c.meeting_id, NULL, coalesce(length(CAST(c.text AS BLOB)),0), NULL, NULL, NULL, NULL
|
|
526
528
|
FROM hit h JOIN meeting_chat_messages c ON h.r % 4 = 2 AND c.id = h.r / 4
|
|
527
529
|
JOIN picked p ON p.id = c.meeting_id
|
|
528
530
|
UNION ALL
|
|
529
|
-
SELECT p.n, 2, s.id, 0, s.id, s.meeting_id, NULL, coalesce(length(CAST(s.title AS BLOB)),0)+coalesce(length(CAST(s.overview AS BLOB)),0)+coalesce(length(CAST(s.sections AS BLOB)),0)+coalesce(length(CAST(s.next_steps AS BLOB)),0)+coalesce(length(CAST(s.content AS BLOB)),0), NULL, NULL
|
|
531
|
+
SELECT p.n, 2, s.id, 0, s.id, s.meeting_id, NULL, coalesce(length(CAST(s.title AS BLOB)),0)+coalesce(length(CAST(s.overview AS BLOB)),0)+coalesce(length(CAST(s.sections AS BLOB)),0)+coalesce(length(CAST(s.next_steps AS BLOB)),0)+coalesce(length(CAST(s.content AS BLOB)),0), NULL, NULL, NULL, NULL
|
|
530
532
|
FROM hit h JOIN meeting_summaries s ON h.r % 4 = 3 AND s.id = h.r / 4
|
|
531
533
|
JOIN picked p ON p.id = s.meeting_id
|
|
532
534
|
ORDER BY 1, 2, 3, 4 LIMIT 10001`)
|
|
@@ -551,6 +553,9 @@ const search = (database, query, filter) => {
|
|
|
551
553
|
cuePosition: Number(row.b),
|
|
552
554
|
}),
|
|
553
555
|
speakerName: row.speaker === null ? null : String(row.speaker),
|
|
556
|
+
language: row.language === null ? null : String(row.language),
|
|
557
|
+
line: Number(row.b) + 1,
|
|
558
|
+
linesTotal: Number(row.lines_total),
|
|
554
559
|
}
|
|
555
560
|
: {};
|
|
556
561
|
return {
|
|
@@ -596,6 +601,7 @@ export const meetingStoreOver = (context) => {
|
|
|
596
601
|
...meetingParticipantSearchOver(context),
|
|
597
602
|
...meetingHitIndexOver(context),
|
|
598
603
|
...meetingContextLinksOver(context),
|
|
604
|
+
...meetingLanguagesOver(context),
|
|
599
605
|
async appendTranscriptsWithReceipt(input) {
|
|
600
606
|
try {
|
|
601
607
|
return append(context, input);
|
|
@@ -2,7 +2,7 @@ import { CliError } from "@wirecat/cli-base";
|
|
|
2
2
|
import { tagOf } from "../../domain/tags.js";
|
|
3
3
|
import { compileAutomaton, foldRegex, wildcardPattern, } from "../../search/lucene/automaton.js";
|
|
4
4
|
import { isStemmed } from "../../search/lucene/resolved.js";
|
|
5
|
-
import { exhausted, QUERY_LIMITS, searchError } from "../../search/lucene/types.js";
|
|
5
|
+
import { exhausted, outOfTime, QUERY_LIMITS, searchError } from "../../search/lucene/types.js";
|
|
6
6
|
import { normalize } from "../normalize.js";
|
|
7
7
|
import { contextDocumentTime } from "./context-document-source.js";
|
|
8
8
|
import { documentPicturesOver } from "./document-pictures.js";
|
|
@@ -126,7 +126,7 @@ export const searchCorpus = (context, query, corpus) => {
|
|
|
126
126
|
if (query.signal?.aborted)
|
|
127
127
|
throw new CliError("validation_error", "search was aborted", { reason: "query.aborted", complete: false });
|
|
128
128
|
if (context.now() - started > QUERY_LIMITS.milliseconds)
|
|
129
|
-
|
|
129
|
+
outOfTime();
|
|
130
130
|
};
|
|
131
131
|
const tests = new Map();
|
|
132
132
|
const fragments = new Map();
|
|
@@ -5,7 +5,7 @@ export declare const projectAnnotationSnapshot: (database: CacheDatabase, projec
|
|
|
5
5
|
format: "wirecat.project-annotations";
|
|
6
6
|
facts: {
|
|
7
7
|
ref: string;
|
|
8
|
-
type: "decision" | "fact" | "promise" | "question" | "statement";
|
|
8
|
+
type: "decision" | "fact" | "payment" | "promise" | "question" | "statement";
|
|
9
9
|
statement: string;
|
|
10
10
|
status: "accepted" | "proposed" | "rejected" | "reversed" | "superseded";
|
|
11
11
|
subject: string | null;
|
|
@@ -5,6 +5,7 @@ import { type Link } from "./notes.js";
|
|
|
5
5
|
import type { StoreContext } from "./open.js";
|
|
6
6
|
import { type ProposedAction } from "./proposed-actions.js";
|
|
7
7
|
import { type Thing } from "./things.js";
|
|
8
|
+
type Row = Record<string, unknown>;
|
|
8
9
|
export interface KnowledgeRelation {
|
|
9
10
|
id: string;
|
|
10
11
|
from: string;
|
|
@@ -32,7 +33,23 @@ export interface RelateInput {
|
|
|
32
33
|
export declare const relationOf: (link: Link) => KnowledgeRelation;
|
|
33
34
|
/** `relationship` proposals in `proposed_actions`: an agent's or a rule's, and the rejected ones a scan skips. */
|
|
34
35
|
export declare const relationProposalsOver: (context: StoreContext) => {
|
|
35
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Where a pair stands before a scan proposes it: a link joins it, a `relationship` proposal for it was rejected,
|
|
38
|
+
* or one is pending. A rejection is matched by the pair alone, whoever proposed it and with whatever scorer.
|
|
39
|
+
*/
|
|
40
|
+
state: (paired: () => {
|
|
41
|
+
from: Thing;
|
|
42
|
+
existing: Row | undefined;
|
|
43
|
+
}, { to, kind }: {
|
|
44
|
+
to: string;
|
|
45
|
+
kind: string;
|
|
46
|
+
}) => {
|
|
47
|
+
linked: boolean;
|
|
48
|
+
confirmed: boolean;
|
|
49
|
+
rejected: boolean;
|
|
50
|
+
pending: ProposedAction | null;
|
|
51
|
+
} | undefined;
|
|
52
|
+
/** The same pending pair returns the proposal already held; a scored one updates its score in place. */
|
|
36
53
|
propose: (from: Thing, input: {
|
|
37
54
|
from: string;
|
|
38
55
|
to: string;
|
|
@@ -41,7 +58,7 @@ export declare const relationProposalsOver: (context: StoreContext) => {
|
|
|
41
58
|
purpose?: string;
|
|
42
59
|
evidence?: string[];
|
|
43
60
|
reason?: string;
|
|
44
|
-
}, by: Exclude<Author, "owner">) => ProposedAction;
|
|
61
|
+
} & Scored, by: Exclude<Author, "owner">) => ProposedAction;
|
|
45
62
|
rejected: (link: Link, by: Decider, reason?: string) => void;
|
|
46
63
|
update: (link: Link, input: RelationUpdate) => Link;
|
|
47
64
|
proposeUpdate: (link: Link, input: RelationUpdate & {
|
|
@@ -62,6 +79,15 @@ export declare const relationProposalsOver: (context: StoreContext) => {
|
|
|
62
79
|
/** Decides an unconfirmed link written before proposals were stored; only the owner may, as its author is unknown. */
|
|
63
80
|
decideLink: (id: string, decision: LinkDecision) => Link | null;
|
|
64
81
|
};
|
|
82
|
+
/** What a scan adds to a relationship proposal: the combined score and each scorer's part in it. */
|
|
83
|
+
export interface Scored {
|
|
84
|
+
score?: number;
|
|
85
|
+
signals?: {
|
|
86
|
+
scorer: string;
|
|
87
|
+
weight: number;
|
|
88
|
+
why: string;
|
|
89
|
+
}[];
|
|
90
|
+
}
|
|
65
91
|
/** A relationship's role and purpose to set; `null` clears one. */
|
|
66
92
|
export interface RelationUpdate {
|
|
67
93
|
role?: string | null;
|
|
@@ -72,3 +98,4 @@ export interface LinkDecision {
|
|
|
72
98
|
by: Decider;
|
|
73
99
|
reason?: string;
|
|
74
100
|
}
|
|
101
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CliError } from "@wirecat/cli-base";
|
|
2
|
-
import { assertMayDecide, deciderAuthor } from "../decisions.js";
|
|
2
|
+
import { assertMayDecide, botKey, deciderAuthor } from "../decisions.js";
|
|
3
3
|
import { actorOfOrigin, botNamed, ownerPerson } from "./actors.js";
|
|
4
4
|
import { insertLink, linkOf, purposeOf } from "./notes.js";
|
|
5
5
|
import { proposalOperationsOver, proposerOfAction } from "./proposed-actions.js";
|
|
@@ -47,19 +47,74 @@ export const relationProposalsOver = (context) => {
|
|
|
47
47
|
.run(Number("role" in changes), changes.role ?? null, Number("purpose" in changes), changes.purpose ?? null, now(), Number(link.id));
|
|
48
48
|
return linkOf(database, database.prepare("SELECT * FROM links WHERE id = ?").get(Number(link.id)));
|
|
49
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* A scan's newer score on a pending proposal, in place under the same id. A rule's own row takes the new score,
|
|
52
|
+
* signals, evidence and purpose; another proposer's row keeps its author, evidence and purpose and gains the signals.
|
|
53
|
+
*/
|
|
54
|
+
const rescored = (action, input, scored, by) => {
|
|
55
|
+
const proposer = proposerOfAction(action);
|
|
56
|
+
const own = proposer.type === "bot" && proposer.kind === "rule" && botKey(proposer.name) === botKey(by.bot);
|
|
57
|
+
const before = action.payload;
|
|
58
|
+
const payload = own
|
|
59
|
+
? {
|
|
60
|
+
...before,
|
|
61
|
+
...scored,
|
|
62
|
+
evidence: input.evidence ?? [],
|
|
63
|
+
...(input.purpose === undefined ? {} : { purpose: purposeOf(input.purpose) }),
|
|
64
|
+
}
|
|
65
|
+
: { ...before, ...scored };
|
|
66
|
+
const reason = own && input.reason !== undefined ? input.reason : action.reason;
|
|
67
|
+
if (JSON.stringify(payload) === JSON.stringify(before) && reason === action.reason)
|
|
68
|
+
return action;
|
|
69
|
+
database
|
|
70
|
+
.prepare("UPDATE proposed_actions SET payload = ?, reason = ?, updated_at = ? WHERE id = ? AND status = 'proposed'")
|
|
71
|
+
.run(JSON.stringify(payload), reason, now(), Number(action.id));
|
|
72
|
+
return operations.get(action.id);
|
|
73
|
+
};
|
|
50
74
|
return {
|
|
51
|
-
/**
|
|
75
|
+
/**
|
|
76
|
+
* Where a pair stands before a scan proposes it: a link joins it, a `relationship` proposal for it was rejected,
|
|
77
|
+
* or one is pending. A rejection is matched by the pair alone, whoever proposed it and with whatever scorer.
|
|
78
|
+
*/
|
|
79
|
+
state: (paired, { to, kind }) => {
|
|
80
|
+
let found;
|
|
81
|
+
try {
|
|
82
|
+
found = paired();
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error instanceof CliError && (error.code === "not_found" || error.code === "validation_error"))
|
|
86
|
+
return;
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
const { from, existing } = found;
|
|
90
|
+
const rows = database
|
|
91
|
+
.prepare("SELECT id, status FROM proposed_actions WHERE kind='relationship' AND status IN ('proposed','rejected') " +
|
|
92
|
+
"AND target_type=? AND target_id=? AND json_extract(payload,'$.to')=? AND json_extract(payload,'$.kind')=? " +
|
|
93
|
+
"ORDER BY id")
|
|
94
|
+
.all(from.type, from.id, to, kind);
|
|
95
|
+
const pending = rows.find((row) => row.status === "proposed");
|
|
96
|
+
return {
|
|
97
|
+
linked: existing !== undefined,
|
|
98
|
+
confirmed: existing !== undefined && Number(existing.confirmed) === 1,
|
|
99
|
+
rejected: rows.some((row) => row.status === "rejected"),
|
|
100
|
+
pending: pending ? operations.get(String(pending.id)) : null,
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
/** The same pending pair returns the proposal already held; a scored one updates its score in place. */
|
|
52
104
|
propose: (from, input, by) => {
|
|
53
105
|
const evidence = input.evidence ?? [];
|
|
54
106
|
if (!Array.isArray(evidence) || evidence.length > 5 || evidence.some((ref) => typeof ref !== "string"))
|
|
55
107
|
throw new CliError("validation_error", "a relationship proposal cites up to 5 references");
|
|
108
|
+
const scored = scoredOf(input);
|
|
56
109
|
return write(database, () => {
|
|
57
110
|
const held = database
|
|
58
111
|
.prepare("SELECT id FROM proposed_actions WHERE kind='relationship' AND status='proposed' AND target_type=? AND target_id=? " +
|
|
59
112
|
"AND json_extract(payload,'$.to')=? AND json_extract(payload,'$.kind')=? ORDER BY id LIMIT 1")
|
|
60
113
|
.get(from.type, from.id, input.to, input.kind);
|
|
61
|
-
if (held)
|
|
62
|
-
|
|
114
|
+
if (held) {
|
|
115
|
+
const action = operations.get(String(held.id));
|
|
116
|
+
return scored ? rescored(action, input, scored, by) : action;
|
|
117
|
+
}
|
|
63
118
|
return operations.propose({
|
|
64
119
|
kind: "relationship",
|
|
65
120
|
by,
|
|
@@ -71,6 +126,7 @@ export const relationProposalsOver = (context) => {
|
|
|
71
126
|
...(input.role === undefined ? {} : { role: input.role }),
|
|
72
127
|
...(input.purpose === undefined ? {} : { purpose: purposeOf(input.purpose) }),
|
|
73
128
|
evidence,
|
|
129
|
+
...scored,
|
|
74
130
|
},
|
|
75
131
|
...(input.reason === undefined ? {} : { reason: input.reason }),
|
|
76
132
|
});
|
|
@@ -174,6 +230,21 @@ export const relationProposalsOver = (context) => {
|
|
|
174
230
|
}),
|
|
175
231
|
};
|
|
176
232
|
};
|
|
233
|
+
const scoredOf = (input) => {
|
|
234
|
+
if (input.score === undefined && input.signals === undefined)
|
|
235
|
+
return undefined;
|
|
236
|
+
const { score, signals } = input;
|
|
237
|
+
if (typeof score !== "number" || !(score >= 0 && score <= 1) || !Array.isArray(signals) || signals.length > 20)
|
|
238
|
+
throw new CliError("validation_error", "a scored proposal takes a score of 0–1 and up to 20 signals");
|
|
239
|
+
for (const signal of signals)
|
|
240
|
+
if (typeof signal?.scorer !== "string" ||
|
|
241
|
+
typeof signal.why !== "string" ||
|
|
242
|
+
signal.why.length > 500 ||
|
|
243
|
+
typeof signal.weight !== "number" ||
|
|
244
|
+
!(signal.weight >= 0 && signal.weight <= 1))
|
|
245
|
+
throw new CliError("validation_error", "a signal names its scorer, a weight of 0–1 and why, up to 500 characters");
|
|
246
|
+
return { score, signals: signals.map(({ scorer, weight, why }) => ({ scorer, weight, why })) };
|
|
247
|
+
};
|
|
177
248
|
/** What a relationship update sets, checked; `null` clears a field and an absent one is left alone. */
|
|
178
249
|
const changesOf = (input) => {
|
|
179
250
|
const changes = {};
|
package/dist/store/store.d.ts
CHANGED
|
@@ -112,6 +112,7 @@ export interface MessageStore {
|
|
|
112
112
|
forAccount(key: AccountKey): AccountStore;
|
|
113
113
|
close(): Promise<void>;
|
|
114
114
|
}
|
|
115
|
+
export type { PaymentFilter } from "./sqlite/facts.js";
|
|
115
116
|
export type { ChatHistoryShape, StoredHistorySkip } from "./sqlite/history-skips.js";
|
|
116
117
|
export { BACKFILL_ON_OPEN, type StoreOptions } from "./sqlite/open-store.js";
|
|
117
118
|
export { fileFacts, readStoreTables, type TableKind } from "./sqlite/store-tables.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.552.0",
|
|
4
4
|
"description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|
|
@@ -251,7 +251,7 @@
|
|
|
251
251
|
"@types/node": "^22.20.5",
|
|
252
252
|
"@types/pngjs": "6.0.5",
|
|
253
253
|
"@vitest/coverage-v8": "^5.0.5",
|
|
254
|
-
"@wirecat/cli-base": "0.
|
|
254
|
+
"@wirecat/cli-base": "0.75.0",
|
|
255
255
|
"@wirecat/cli-core-legacy-tags": "npm:@wirecat/cli-core@0.414.0",
|
|
256
256
|
"commander": "15.0.0",
|
|
257
257
|
"cspell": "10.4.0",
|
|
@@ -271,7 +271,7 @@
|
|
|
271
271
|
},
|
|
272
272
|
"peerDependencies": {
|
|
273
273
|
"@napi-rs/canvas": ">=0.1.69 <2",
|
|
274
|
-
"@wirecat/cli-base": ">=0.
|
|
274
|
+
"@wirecat/cli-base": ">=0.75.0 <0.76.0",
|
|
275
275
|
"commander": ">=15"
|
|
276
276
|
},
|
|
277
277
|
"bin": {
|
package/parity.json
CHANGED
|
@@ -3715,6 +3715,17 @@
|
|
|
3715
3715
|
"--sync-time": "all"
|
|
3716
3716
|
}
|
|
3717
3717
|
},
|
|
3718
|
+
"projects status": {
|
|
3719
|
+
"in": ["max", "tg"],
|
|
3720
|
+
"planned": {
|
|
3721
|
+
"wa": "wa backlog: mount projectsCommand once wa is on cli-core 0.504.0"
|
|
3722
|
+
},
|
|
3723
|
+
"options": {
|
|
3724
|
+
"--before-time": "all",
|
|
3725
|
+
"--context-query": "all",
|
|
3726
|
+
"--since-time": "all"
|
|
3727
|
+
}
|
|
3728
|
+
},
|
|
3718
3729
|
"reactions": {
|
|
3719
3730
|
"in": "all"
|
|
3720
3731
|
},
|