@wirecat/cli-core 0.284.0 → 0.285.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/dist/attachments/markup.d.ts.map +1 -1
- package/dist/attachments/markup.js +54 -19
- package/dist/attachments/markup.js.map +1 -1
- package/dist/background/units.d.ts.map +1 -1
- package/dist/background/units.js +1 -0
- package/dist/background/units.js.map +1 -1
- package/dist/cli/index.d.ts +3 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +3 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/list-query.d.ts +9 -2
- package/dist/cli/list-query.d.ts.map +1 -1
- package/dist/cli/list-query.js +39 -13
- package/dist/cli/list-query.js.map +1 -1
- package/dist/cli/messenger/mention-points.d.ts.map +1 -1
- package/dist/cli/messenger/mention-points.js +1 -1
- package/dist/cli/messenger/mention-points.js.map +1 -1
- package/dist/cli/messenger/mentions-command.d.ts.map +1 -1
- package/dist/cli/messenger/mentions-command.js +33 -3
- package/dist/cli/messenger/mentions-command.js.map +1 -1
- package/dist/cli/messenger/messages-search-command.d.ts +2 -3
- package/dist/cli/messenger/messages-search-command.d.ts.map +1 -1
- package/dist/cli/messenger/messages-search-command.js +24 -54
- package/dist/cli/messenger/messages-search-command.js.map +1 -1
- package/dist/cli/messenger/review.js +2 -1
- package/dist/cli/messenger/review.js.map +1 -1
- package/dist/cli/messenger/search-answers.d.ts +3 -0
- package/dist/cli/messenger/search-answers.d.ts.map +1 -1
- package/dist/cli/messenger/search-answers.js +2 -0
- package/dist/cli/messenger/search-answers.js.map +1 -1
- package/dist/cli/messenger/search-command.d.ts.map +1 -1
- package/dist/cli/messenger/search-command.js +15 -15
- package/dist/cli/messenger/search-command.js.map +1 -1
- package/dist/cli/messenger/serve-command.js +3 -2
- package/dist/cli/messenger/serve-command.js.map +1 -1
- package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
- package/dist/cli/messenger/tasks-command.d.ts.map +1 -1
- package/dist/cli/messenger/tasks-command.js +83 -8
- package/dist/cli/messenger/tasks-command.js.map +1 -1
- package/dist/cli/moved.d.ts +13 -0
- package/dist/cli/moved.d.ts.map +1 -0
- package/dist/cli/moved.js +18 -0
- package/dist/cli/moved.js.map +1 -0
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +16 -0
- package/dist/cli/program.js.map +1 -1
- package/dist/cli/reasons.d.ts.map +1 -1
- package/dist/cli/reasons.js +3 -0
- package/dist/cli/reasons.js.map +1 -1
- package/dist/cli/store-settings.d.ts +1 -2
- package/dist/cli/store-settings.d.ts.map +1 -1
- package/dist/cli/store-settings.js +53 -3
- package/dist/cli/store-settings.js.map +1 -1
- package/dist/domain/mentions.d.ts +14 -0
- package/dist/domain/mentions.d.ts.map +1 -1
- package/dist/domain/mentions.js +25 -0
- package/dist/domain/mentions.js.map +1 -1
- package/dist/domain/models.d.ts +1 -0
- package/dist/domain/models.d.ts.map +1 -1
- package/dist/domain/task-categories.d.ts +25 -0
- package/dist/domain/task-categories.d.ts.map +1 -0
- package/dist/domain/task-categories.js +155 -0
- package/dist/domain/task-categories.js.map +1 -0
- package/dist/entities/fact.d.ts +5 -0
- package/dist/entities/fact.d.ts.map +1 -1
- package/dist/entities/fact.js +2 -0
- package/dist/entities/fact.js.map +1 -1
- package/dist/entities/index.d.ts +18 -1
- package/dist/entities/index.d.ts.map +1 -1
- package/dist/entities/index.js +3 -1
- package/dist/entities/index.js.map +1 -1
- package/dist/entities/relationship.d.ts +16 -0
- package/dist/entities/relationship.d.ts.map +1 -0
- package/dist/entities/relationship.js +18 -0
- package/dist/entities/relationship.js.map +1 -0
- package/dist/mcp/http/oauth.d.ts.map +1 -1
- package/dist/mcp/http/oauth.js +1 -0
- package/dist/mcp/http/oauth.js.map +1 -1
- package/dist/mcp/instructions.d.ts.map +1 -1
- package/dist/mcp/instructions.js +3 -2
- package/dist/mcp/instructions.js.map +1 -1
- package/dist/mcp/meeting-preparation.d.ts +7 -3
- package/dist/mcp/meeting-preparation.d.ts.map +1 -1
- package/dist/mcp/meeting-preparation.js +7 -3
- package/dist/mcp/meeting-preparation.js.map +1 -1
- package/dist/mcp/surface.d.ts.map +1 -1
- package/dist/mcp/surface.js +4 -0
- package/dist/mcp/surface.js.map +1 -1
- package/dist/mcp/text.d.ts +1 -2
- package/dist/mcp/text.d.ts.map +1 -1
- package/dist/mcp/text.js +2 -9
- package/dist/mcp/text.js.map +1 -1
- package/dist/mcp/tool.d.ts +1 -3
- package/dist/mcp/tool.d.ts.map +1 -1
- package/dist/mcp/tool.js +2 -3
- package/dist/mcp/tool.js.map +1 -1
- package/dist/mcp/tools/search-tools.d.ts.map +1 -1
- package/dist/mcp/tools/search-tools.js +21 -36
- package/dist/mcp/tools/search-tools.js.map +1 -1
- package/dist/mcp/tools/search.d.ts +0 -12
- package/dist/mcp/tools/search.d.ts.map +1 -1
- package/dist/mcp/tools/search.js +0 -12
- package/dist/mcp/tools/search.js.map +1 -1
- package/dist/mcp/tools/tasks.d.ts.map +1 -1
- package/dist/mcp/tools/tasks.js +121 -7
- package/dist/mcp/tools/tasks.js.map +1 -1
- package/dist/meetings/mcp/agent-text.d.ts +23 -0
- package/dist/meetings/mcp/agent-text.d.ts.map +1 -0
- package/dist/meetings/mcp/agent-text.js +43 -0
- package/dist/meetings/mcp/agent-text.js.map +1 -0
- package/dist/meetings/mcp/index.d.ts +3 -38
- package/dist/meetings/mcp/index.d.ts.map +1 -1
- package/dist/meetings/mcp/index.js +9 -3
- package/dist/meetings/mcp/index.js.map +1 -1
- package/dist/meetings/mcp/passage.d.ts +7 -3
- package/dist/meetings/mcp/passage.d.ts.map +1 -1
- package/dist/meetings/mcp/passage.js +4 -3
- package/dist/meetings/mcp/passage.js.map +1 -1
- package/dist/meetings/mcp/project-evidence.d.ts +7 -3
- package/dist/meetings/mcp/project-evidence.d.ts.map +1 -1
- package/dist/meetings/mcp/project-evidence.js +7 -3
- package/dist/meetings/mcp/project-evidence.js.map +1 -1
- package/dist/meetings/mcp/search.d.ts +7 -3
- package/dist/meetings/mcp/search.d.ts.map +1 -1
- package/dist/meetings/mcp/search.js +7 -3
- package/dist/meetings/mcp/search.js.map +1 -1
- package/dist/parity/manifest.d.ts.map +1 -1
- package/dist/parity/manifest.js +4 -0
- package/dist/parity/manifest.js.map +1 -1
- package/dist/readers/doc/index.d.ts.map +1 -1
- package/dist/readers/doc/index.js +1 -0
- package/dist/readers/doc/index.js.map +1 -1
- package/dist/readers/html/index.d.ts.map +1 -1
- package/dist/readers/html/index.js +16 -1
- package/dist/readers/html/index.js.map +1 -1
- package/dist/search/account-list.js +1 -1
- package/dist/search/account-list.js.map +1 -1
- package/dist/sends/permissions.d.ts.map +1 -1
- package/dist/sends/permissions.js +4 -0
- package/dist/sends/permissions.js.map +1 -1
- package/dist/services/agenda.d.ts +4 -0
- package/dist/services/agenda.d.ts.map +1 -1
- package/dist/services/agenda.js +6 -1
- package/dist/services/agenda.js.map +1 -1
- package/dist/services/inbox.d.ts.map +1 -1
- package/dist/services/inbox.js +5 -1
- package/dist/services/inbox.js.map +1 -1
- package/dist/services/mentions.d.ts +16 -2
- package/dist/services/mentions.d.ts.map +1 -1
- package/dist/services/mentions.js +33 -3
- package/dist/services/mentions.js.map +1 -1
- package/dist/services/messages-search.d.ts.map +1 -1
- package/dist/services/messages-search.js +1 -1
- package/dist/services/messages-search.js.map +1 -1
- package/dist/services/search-kind.js +2 -2
- package/dist/services/search-kind.js.map +1 -1
- package/dist/services/task-categories.d.ts +2 -12
- package/dist/services/task-categories.d.ts.map +1 -1
- package/dist/services/task-categories.js +2 -74
- package/dist/services/task-categories.js.map +1 -1
- package/dist/services/task-rules.d.ts +5 -1
- package/dist/services/task-rules.d.ts.map +1 -1
- package/dist/services/task-rules.js +13 -13
- package/dist/services/task-rules.js.map +1 -1
- package/dist/services/tasks.d.ts +38 -3
- package/dist/services/tasks.d.ts.map +1 -1
- package/dist/services/tasks.js +83 -8
- package/dist/services/tasks.js.map +1 -1
- package/dist/store/index.d.ts +2 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +1 -0
- package/dist/store/index.js.map +1 -1
- package/dist/store/sqlite/lucene.d.ts.map +1 -1
- package/dist/store/sqlite/lucene.js +13 -22
- package/dist/store/sqlite/lucene.js.map +1 -1
- package/dist/store/sqlite/manifest.d.ts.map +1 -1
- package/dist/store/sqlite/manifest.js +2 -0
- package/dist/store/sqlite/manifest.js.map +1 -1
- package/dist/store/sqlite/mention-drain.d.ts +24 -1
- package/dist/store/sqlite/mention-drain.d.ts.map +1 -1
- package/dist/store/sqlite/mention-drain.js +40 -3
- package/dist/store/sqlite/mention-drain.js.map +1 -1
- package/dist/store/sqlite/mentions.d.ts +6 -3
- package/dist/store/sqlite/mentions.d.ts.map +1 -1
- package/dist/store/sqlite/mentions.js +29 -12
- package/dist/store/sqlite/mentions.js.map +1 -1
- package/dist/store/sqlite/migrations.generated.d.ts.map +1 -1
- package/dist/store/sqlite/migrations.generated.js +23 -0
- package/dist/store/sqlite/migrations.generated.js.map +1 -1
- package/dist/store/sqlite/note-search.d.ts.map +1 -1
- package/dist/store/sqlite/note-search.js +11 -2
- package/dist/store/sqlite/note-search.js.map +1 -1
- package/dist/store/sqlite/schema.d.ts +231 -0
- package/dist/store/sqlite/schema.d.ts.map +1 -1
- package/dist/store/sqlite/schema.js +23 -0
- package/dist/store/sqlite/schema.js.map +1 -1
- package/dist/store/sqlite/task-candidates.d.ts +2 -0
- package/dist/store/sqlite/task-candidates.d.ts.map +1 -1
- package/dist/store/sqlite/task-candidates.js +14 -1
- package/dist/store/sqlite/task-candidates.js.map +1 -1
- package/dist/store/sqlite/task-category-settings.d.ts +9 -0
- package/dist/store/sqlite/task-category-settings.d.ts.map +1 -0
- package/dist/store/sqlite/task-category-settings.js +21 -0
- package/dist/store/sqlite/task-category-settings.js.map +1 -0
- package/dist/store/sqlite/task-pairs.d.ts +69 -0
- package/dist/store/sqlite/task-pairs.d.ts.map +1 -0
- package/dist/store/sqlite/task-pairs.js +262 -0
- package/dist/store/sqlite/task-pairs.js.map +1 -0
- package/dist/store/sqlite/task-relations.d.ts.map +1 -1
- package/dist/store/sqlite/task-relations.js +20 -8
- package/dist/store/sqlite/task-relations.js.map +1 -1
- package/dist/store/sqlite/tasks.d.ts +7 -1
- package/dist/store/sqlite/tasks.d.ts.map +1 -1
- package/dist/store/sqlite/tasks.js +23 -3
- package/dist/store/sqlite/tasks.js.map +1 -1
- package/dist/store/store.d.ts +4 -3
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +1 -0
- package/dist/store/store.js.map +1 -1
- package/dist/store/ulid.d.ts.map +1 -1
- package/dist/store/ulid.js +1 -0
- package/dist/store/ulid.js.map +1 -1
- package/dist/tasks/service.d.ts +3 -1
- package/dist/tasks/service.d.ts.map +1 -1
- package/dist/tasks/service.js +8 -4
- package/dist/tasks/service.js.map +1 -1
- package/dist/tasks/store.d.ts +9 -1
- package/dist/tasks/store.d.ts.map +1 -1
- package/dist/tasks/store.js.map +1 -1
- package/package.json +1 -1
- package/parity.json +84 -20
- package/skills/follow-ups/SKILL.md +2 -0
|
@@ -38,12 +38,12 @@ export const listedAccounts = async (store, account, source, app, kind) => {
|
|
|
38
38
|
*/
|
|
39
39
|
export const accountsOfKind = (kind, chosen, held, explicit, command = "tg", mailAccount, listed = false) => {
|
|
40
40
|
if (mailAccount !== undefined && kind !== "mail")
|
|
41
|
-
throw new CliError("validation_error", "--account names a mail account — search mail reads it");
|
|
41
|
+
throw new CliError("validation_error", "--account names a mail account — memo search mail reads it");
|
|
42
42
|
if (kind === undefined)
|
|
43
43
|
return chosen;
|
|
44
44
|
if (kind === "messages") {
|
|
45
45
|
if (explicit === MAIL)
|
|
46
|
-
throw new CliError("validation_error",
|
|
46
|
+
throw new CliError("validation_error", "mail is searched with `memo search mail`, not search messages");
|
|
47
47
|
return chosen.filter(({ provider }) => kindOf(provider) === "messages");
|
|
48
48
|
}
|
|
49
49
|
if (explicit !== undefined && explicit !== MAIL && explicit !== "all")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-kind.js","sourceRoot":"","sources":["../../src/services/search-kind.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"search-kind.js","sourceRoot":"","sources":["../../src/services/search-kind.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,EAAwC,MAAM,2BAA2B,CAAA;AAKvH,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAA;AAEhC,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAA;AAC3B,kHAAkH;AAClH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAChC,KAAmB,EACnB,OAAmB,EACnB,GAA4B,EAC5B,MAAwB,EACF,EAAE;IACxB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;IACpD,2DAA2D;IAC3D,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC;QAClG,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,UAAmB,EAAE,CAAC,CAAA;IAC3E,OAAO;QACL,IAAI;QACJ,MAAM,EAAE,MAAM,KAAK,CAAC,aAAa,EAAE;QACnC,QAAQ,EAAE,MAAM,KAAK,CAAC,QAAQ,EAAE;QAChC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;KAClF,CAAA;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,KAAmB,EACnB,OAAmB,EACnB,MAA0B,EAC1B,GAA4B,EAC5B,IAAiB,EAC0D,EAAE;IAC7E,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAC1C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,cAAc,EAAE,CAAA;IAC3C,iGAAiG;IACjG,MAAM,UAAU,GACd,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAA;IAChH,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAA;IAC3D,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAA;IACvF,OAAO,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,EAAE,OAAO,IAAI,IAAI,WAAW,IAAI,IAAI,UAAU,EAAE,CAAC,CAAA;AACvH,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,IAA4B,EAC5B,MAAoB,EACpB,IAA2B,EAC3B,QAA4B,EAC5B,OAAO,GAAG,IAAI,EACd,WAAoB,EACpB,MAAM,GAAG,KAAK,EACA,EAAE;IAChB,IAAI,WAAW,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM;QAC9C,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,4DAA4D,CAAC,CAAA;IACtG,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,MAAM,CAAA;IACrC,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,IAAI,QAAQ,KAAK,IAAI;YACnB,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,+DAA+D,CAAC,CAAA;QACzG,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,UAAU,CAAC,CAAA;IACzE,CAAC;IACD,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,KAAK;QACnE,MAAM,IAAI,QAAQ,CAChB,kBAAkB,EAClB,mCAAmC,OAAO,+BAA+B,QAAQ,EAAE,CACpF,CAAA;IACH,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,MAAM,CAAC,CAAA;IAC3F,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QACnB,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,8EAA8E,EAAE;YAC9G,MAAM,EAAE,OAAO;SAChB,CAAC,CAAA;IACJ,MAAM,OAAO,GAAG,WAAW,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IACjD,MAAM,UAAU,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,KAAK,OAAO,CAAC,CAAA;IACnG,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QACzB,MAAM,IAAI,QAAQ,CAChB,WAAW,EACX,mBAAmB,WAAW,4BAA4B,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC1G,CAAA;IACH,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAA;AAC3E,CAAC,CAAA"}
|
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
meaning: string;
|
|
4
|
-
/** Words that point at the category, per language; a rule matches their stems against the source message. */
|
|
5
|
-
triggers: Readonly<Record<"en" | "ru" | "es", readonly string[]>>;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* The fixed list a task's category comes from. One list, so "finance", "payments" and "деньги" never coexist;
|
|
9
|
-
* `other` is what a rule picks when no trigger word matches.
|
|
10
|
-
*/
|
|
11
|
-
export declare const DEFAULT_TASK_CATEGORIES: readonly TaskCategory[];
|
|
12
|
-
export declare const FALLBACK_CATEGORY = "other";
|
|
1
|
+
import { type TaskCategory } from "../domain/task-categories.js";
|
|
2
|
+
export { DEFAULT_TASK_CATEGORIES, FALLBACK_CATEGORY, parseTaskCategory, type TaskCategory, withTaskCategory, } from "../domain/task-categories.js";
|
|
13
3
|
/** A category the list holds, or a refusal that names the list. */
|
|
14
4
|
export declare const taskCategoryOf: (categories?: readonly TaskCategory[], flag?: string) => (typed: string) => string;
|
|
15
5
|
/** The category whose trigger stems the text shares most; none shared is `other`. A tie goes to the earlier one. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-categories.d.ts","sourceRoot":"","sources":["../../src/services/task-categories.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"task-categories.d.ts","sourceRoot":"","sources":["../../src/services/task-categories.ts"],"names":[],"mappings":"AACA,OAAO,EAA8C,KAAK,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAG5G,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,YAAY,EACjB,gBAAgB,GACjB,MAAM,8BAA8B,CAAA;AAIrC,mEAAmE;AACnE,eAAO,MAAM,cAAc,gBACZ,SAAS,YAAY,EAAE,4BAC5B,MAAM,KAAG,MAQhB,CAAA;AAgBH,oHAAoH;AACpH,eAAO,MAAM,UAAU,SAAU,MAAM,eAAc,SAAS,YAAY,EAAE,KAA6B,MAUxG,CAAA"}
|
|
@@ -1,79 +1,7 @@
|
|
|
1
1
|
import { CliError, singleLine } from "@wirecat/cli-base";
|
|
2
|
+
import { DEFAULT_TASK_CATEGORIES, FALLBACK_CATEGORY } from "../domain/task-categories.js";
|
|
2
3
|
import { createStemmer } from "../search/stem.js";
|
|
3
|
-
|
|
4
|
-
* The fixed list a task's category comes from. One list, so "finance", "payments" and "деньги" never coexist;
|
|
5
|
-
* `other` is what a rule picks when no trigger word matches.
|
|
6
|
-
*/
|
|
7
|
-
export const DEFAULT_TASK_CATEGORIES = [
|
|
8
|
-
{
|
|
9
|
-
name: "money",
|
|
10
|
-
meaning: "pay, invoice, refund, a price or a debt",
|
|
11
|
-
triggers: {
|
|
12
|
-
en: ["pay", "payment", "invoice", "bill", "refund", "price", "money", "transfer", "debt", "salary", "cost"],
|
|
13
|
-
ru: [
|
|
14
|
-
"оплата",
|
|
15
|
-
"оплатить",
|
|
16
|
-
"платёж",
|
|
17
|
-
"счёт",
|
|
18
|
-
"деньги",
|
|
19
|
-
"перевод",
|
|
20
|
-
"перевести",
|
|
21
|
-
"долг",
|
|
22
|
-
"цена",
|
|
23
|
-
"стоимость",
|
|
24
|
-
"возврат",
|
|
25
|
-
],
|
|
26
|
-
es: ["pagar", "pago", "factura", "dinero", "transferencia", "deuda", "precio", "reembolso", "cobrar"],
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
name: "documents",
|
|
31
|
-
meaning: "a file, contract, scan, form or signature to send or receive",
|
|
32
|
-
triggers: {
|
|
33
|
-
en: ["document", "contract", "file", "scan", "sign", "signature", "form", "passport", "certificate", "pdf"],
|
|
34
|
-
ru: ["документ", "договор", "файл", "скан", "подписать", "подпись", "паспорт", "справка", "анкета", "акт"],
|
|
35
|
-
es: ["documento", "contrato", "archivo", "escaneo", "firmar", "firma", "formulario", "pasaporte", "certificado"],
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
name: "meeting",
|
|
40
|
-
meaning: "a call, meeting or appointment to arrange or attend",
|
|
41
|
-
triggers: {
|
|
42
|
-
en: ["meeting", "meet", "call", "appointment", "schedule", "zoom", "reschedule", "agenda"],
|
|
43
|
-
ru: ["встреча", "встретиться", "созвон", "созвониться", "звонок", "приём", "запись", "перенести"],
|
|
44
|
-
es: ["reunión", "reunirse", "llamada", "cita", "quedar", "agenda", "videollamada"],
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
name: "delivery",
|
|
49
|
-
meaning: "a parcel, order or shipment to send, track or collect",
|
|
50
|
-
triggers: {
|
|
51
|
-
en: ["delivery", "deliver", "parcel", "package", "shipment", "ship", "order", "courier", "tracking", "pickup"],
|
|
52
|
-
ru: ["доставка", "доставить", "посылка", "заказ", "курьер", "отправить", "отправка", "трек", "забрать"],
|
|
53
|
-
es: ["entrega", "entregar", "paquete", "envío", "enviar", "pedido", "mensajero", "recoger"],
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
name: "access",
|
|
58
|
-
meaning: "a login, password, key, invite or permission to give or get",
|
|
59
|
-
triggers: {
|
|
60
|
-
en: ["access", "password", "login", "account", "key", "token", "invite", "permission", "credentials"],
|
|
61
|
-
ru: ["доступ", "пароль", "логин", "аккаунт", "ключ", "токен", "приглашение", "права"],
|
|
62
|
-
es: ["acceso", "contraseña", "usuario", "cuenta", "clave", "invitación", "permiso"],
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: "personal",
|
|
67
|
-
meaning: "family, friends, health, a gift or a favour",
|
|
68
|
-
triggers: {
|
|
69
|
-
en: ["birthday", "gift", "family", "mum", "mom", "dad", "doctor", "health", "favour", "favor", "party"],
|
|
70
|
-
ru: ["день рождения", "подарок", "семья", "мама", "папа", "врач", "здоровье", "просьба", "праздник"],
|
|
71
|
-
es: ["cumpleaños", "regalo", "familia", "mamá", "papá", "médico", "salud", "favor", "fiesta"],
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
{ name: "other", meaning: "none of the above", triggers: { en: [], ru: [], es: [] } },
|
|
75
|
-
];
|
|
76
|
-
export const FALLBACK_CATEGORY = "other";
|
|
4
|
+
export { DEFAULT_TASK_CATEGORIES, FALLBACK_CATEGORY, parseTaskCategory, withTaskCategory, } from "../domain/task-categories.js";
|
|
77
5
|
const names = (categories) => categories.map(({ name }) => name).join(", ");
|
|
78
6
|
/** A category the list holds, or a refusal that names the list. */
|
|
79
7
|
export const taskCategoryOf = (categories = DEFAULT_TASK_CATEGORIES, flag = "--category") => (typed) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-categories.js","sourceRoot":"","sources":["../../src/services/task-categories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"task-categories.js","sourceRoot":"","sources":["../../src/services/task-categories.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { Message, ReviewChat } from "../domain/models.js";
|
|
2
2
|
import type { AccountKey, MessageStore } from "../store/store.js";
|
|
3
3
|
import { type TaskStore } from "../tasks/index.js";
|
|
4
|
+
import { type TaskCategory } from "./task-categories.js";
|
|
4
5
|
export interface RuleResult {
|
|
5
6
|
added: number;
|
|
6
7
|
closed: number;
|
|
8
|
+
/** Opened tasks that may be the same job as another: on the review list (`tasks duplicates`). */
|
|
9
|
+
review: number;
|
|
7
10
|
}
|
|
8
11
|
export declare const taskAccount: ({ provider, account }: AccountKey) => string;
|
|
9
12
|
/**
|
|
@@ -15,10 +18,11 @@ export declare const taskAccount: ({ provider, account }: AccountKey) => string;
|
|
|
15
18
|
*/
|
|
16
19
|
export declare const applyTaskRules: (review: {
|
|
17
20
|
chats: Pick<ReviewChat, "id" | "messages">[];
|
|
18
|
-
}, { store, account, now }: {
|
|
21
|
+
}, { store, account, now, categories, }: {
|
|
19
22
|
store: TaskStore;
|
|
20
23
|
account: AccountKey;
|
|
21
24
|
now?: () => Date;
|
|
25
|
+
categories?: readonly TaskCategory[];
|
|
22
26
|
}) => Promise<RuleResult>;
|
|
23
27
|
/** How far back `serve` looks when a message arrives: enough to see whether it answers a recent question. */
|
|
24
28
|
export declare const ARRIVAL_WINDOW = 50;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-rules.d.ts","sourceRoot":"","sources":["../../src/services/task-rules.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAM,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACjE,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"task-rules.d.ts","sourceRoot":"","sources":["../../src/services/task-rules.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAM,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACjE,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAEpF,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEpE,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,iGAAiG;IACjG,MAAM,EAAE,MAAM,CAAA;CACf;AAED,eAAO,MAAM,WAAW,0BAA2B,UAAU,KAAG,MAAkC,CAAA;AAElG;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,WACjB;IAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,UAAU,CAAC,EAAE,CAAA;CAAE,wCAMrD;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,UAAU,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IAAC,UAAU,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;CAAE,KACnG,OAAO,CAAC,UAAU,CAyCpB,CAAA;AAED,6GAA6G;AAC7G,eAAO,MAAM,cAAc,KAAK,CAAA;AAEhC,mHAAmH;AACnH,eAAO,MAAM,uBAAuB,UAC3B,YAAY,WACV,UAAU,WACV,OAAO,KACf,OAAO,CAAC,UAAU,CASpB,CAAA;AAED,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAErC;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,UAC1B,YAAY,WACV,UAAU,UACX,MAAM,cACF,MAAM,KACjB,OAAO,CAAC,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAwB/C,CAAA;AAED,uHAAuH;AACvH,eAAO,MAAM,eAAe,KAAK,CAAA;AAEjC;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,UAC/B,YAAY,WACV,UAAU,iBAElB,OAAO,CAAC,UAAU,CAMpB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,UAAiB,YAAY,WAAW,UAAU,WAAW,OAAO,KAAG,OAAO,CAAC,OAAO,CAgBjH,CAAA"}
|
|
@@ -10,23 +10,24 @@ export const taskAccount = ({ provider, account }) => `${provider}:${account}`;
|
|
|
10
10
|
* Only the owner's answers count: the store knows no admins, and a review without `--unanswered` asks
|
|
11
11
|
* for none. A mention is one the messenger marks by id; an `@handle` is not seen.
|
|
12
12
|
*/
|
|
13
|
-
export const applyTaskRules = async (review, { store, account, now }) => {
|
|
13
|
+
export const applyTaskRules = async (review, { store, account, now, categories, }) => {
|
|
14
14
|
const tasks = createTaskService({ store, ...(now ? { now } : {}) });
|
|
15
15
|
const owner = taskAccount(account);
|
|
16
|
-
const result = { added: 0, closed: 0 };
|
|
16
|
+
const result = { added: 0, closed: 0, review: 0 };
|
|
17
17
|
const sourceOf = (message) => formatLocator({ provider: account.provider, account: account.account, chat: message.chatId, message: message.id });
|
|
18
18
|
const open = async (message, group, kind) => {
|
|
19
|
-
const { created } = await tasks.add({
|
|
19
|
+
const { created, review = 0 } = await tasks.add({
|
|
20
20
|
source: sourceOf(message),
|
|
21
21
|
sourceKind: "message",
|
|
22
22
|
account: owner,
|
|
23
23
|
group,
|
|
24
24
|
kind,
|
|
25
25
|
origin: "rule",
|
|
26
|
-
category: categorize(message.text),
|
|
26
|
+
category: categorize(message.text, categories),
|
|
27
27
|
});
|
|
28
28
|
if (created)
|
|
29
29
|
result.added += 1;
|
|
30
|
+
result.review += review;
|
|
30
31
|
};
|
|
31
32
|
const close = async (message, kind, answer) => {
|
|
32
33
|
for (const task of await store.findBySource(owner, sourceOf(message))) {
|
|
@@ -62,7 +63,7 @@ export const ARRIVAL_WINDOW = 50;
|
|
|
62
63
|
export const applyTaskRulesOnArrival = async (store, account, message) => {
|
|
63
64
|
const page = await store.messages(account, message.chatId, { limit: ARRIVAL_WINDOW });
|
|
64
65
|
const messages = [...page.items.filter((one) => one.id !== message.id), message].sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));
|
|
65
|
-
return applyTaskRules({ chats: [{ id: message.chatId, messages }] }, { store: store.tasks, account });
|
|
66
|
+
return applyTaskRules({ chats: [{ id: message.chatId, messages }] }, { store: store.tasks, account, categories: await store.tasks.categories() });
|
|
66
67
|
};
|
|
67
68
|
/** The most messages one chat gives a stored pass, however many arrived since the last. */
|
|
68
69
|
export const STORED_PASS_LIMIT = 1000;
|
|
@@ -73,7 +74,8 @@ export const STORED_PASS_LIMIT = 1000;
|
|
|
73
74
|
* only what changed. A chat with more new messages than STORED_PASS_LIMIT has its oldest left unread.
|
|
74
75
|
*/
|
|
75
76
|
export const applyTaskRulesToStored = async (store, account, since, newerThan) => {
|
|
76
|
-
const result = { added: 0, closed: 0, until: since ?? null };
|
|
77
|
+
const result = { added: 0, closed: 0, review: 0, until: since ?? null };
|
|
78
|
+
const categories = await store.tasks.categories();
|
|
77
79
|
for (const chat of await store.chatStats(account)) {
|
|
78
80
|
if (chat.lastStoredAt === null || (since !== undefined && chat.lastStoredAt <= since))
|
|
79
81
|
continue;
|
|
@@ -87,12 +89,10 @@ export const applyTaskRulesToStored = async (store, account, since, newerThan) =
|
|
|
87
89
|
const page = await store.messages(account, chat.chatId, {
|
|
88
90
|
limit: Math.min(ARRIVAL_WINDOW + fresh, STORED_PASS_LIMIT),
|
|
89
91
|
});
|
|
90
|
-
const pass = await applyTaskRules({ chats: [{ id: chat.chatId, messages: page.items }] }, {
|
|
91
|
-
store: store.tasks,
|
|
92
|
-
account,
|
|
93
|
-
});
|
|
92
|
+
const pass = await applyTaskRules({ chats: [{ id: chat.chatId, messages: page.items }] }, { store: store.tasks, account, categories });
|
|
94
93
|
result.added += pass.added;
|
|
95
94
|
result.closed += pass.closed;
|
|
95
|
+
result.review += pass.review;
|
|
96
96
|
if (result.until === null || chat.lastStoredAt > result.until)
|
|
97
97
|
result.until = chat.lastStoredAt;
|
|
98
98
|
}
|
|
@@ -108,10 +108,10 @@ export const FIRST_PASS_DAYS = 14;
|
|
|
108
108
|
export const applyTaskRulesSinceLastPass = async (store, account, now = new Date()) => {
|
|
109
109
|
const since = await store.taskRulesStop(account);
|
|
110
110
|
const newerThan = since === null ? new Date(now.getTime() - FIRST_PASS_DAYS * 86_400_000).toISOString() : undefined;
|
|
111
|
-
const { added, closed, until } = await applyTaskRulesToStored(store, account, since ?? undefined, newerThan);
|
|
111
|
+
const { added, closed, review, until } = await applyTaskRulesToStored(store, account, since ?? undefined, newerThan);
|
|
112
112
|
if (until !== null && until !== since)
|
|
113
113
|
await store.setTaskRulesStop(account, until);
|
|
114
|
-
return { added, closed };
|
|
114
|
+
return { added, closed, review };
|
|
115
115
|
};
|
|
116
116
|
/**
|
|
117
117
|
* A reply rule's `task` action: one `request` task pointing at the message. The service gives back
|
|
@@ -130,7 +130,7 @@ export const openRequestTask = async (store, account, message) => {
|
|
|
130
130
|
group: message.chatId,
|
|
131
131
|
kind: "request",
|
|
132
132
|
origin: "rule",
|
|
133
|
-
category: categorize(message.text),
|
|
133
|
+
category: categorize(message.text, await store.tasks.categories()),
|
|
134
134
|
});
|
|
135
135
|
return created;
|
|
136
136
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-rules.js","sourceRoot":"","sources":["../../src/services/task-rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAGpD,OAAO,EAAE,iBAAiB,EAAiC,MAAM,mBAAmB,CAAA;AACpF,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"task-rules.js","sourceRoot":"","sources":["../../src/services/task-rules.ts"],"names":[],"mappings":"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"}
|
package/dist/services/tasks.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type QueryAst } from "@wirecat/cli-base/query";
|
|
2
2
|
import type * as v from "valibot";
|
|
3
3
|
import { task as taskEntity } from "../entities/task.js";
|
|
4
|
-
import { type SimilarTask, type TaskDraft, type TaskRelation } from "../store/index.js";
|
|
4
|
+
import { type SimilarTask, type TaskDraft, type TaskPair, type TaskRelation } from "../store/index.js";
|
|
5
5
|
import type { AccountKey, MessageStore, TaskDetails, ThingLink } from "../store/store.js";
|
|
6
6
|
import { type ClosedState, type GroupStats, TASK_KINDS, TASK_STATES, type Task, type TaskKind, type TaskOrigin } from "../tasks/index.js";
|
|
7
7
|
import type { ServiceDeps } from "./deps.js";
|
|
@@ -57,6 +57,17 @@ export type TaskLinkKind = (typeof TASK_LINK_KINDS)[number];
|
|
|
57
57
|
/** `tasks link --kind`: a link's kinds, and a `task:` target's relation kinds; `related-to` is both. */
|
|
58
58
|
export declare const TASK_LINK_OPTION_KINDS: readonly ["related-to", "evidence", "created-from", "blocked-by", "follow-up-of", "duplicate-of", "discovered-from"];
|
|
59
59
|
export type TaskLinkOptionKind = (typeof TASK_LINK_OPTION_KINDS)[number];
|
|
60
|
+
/**
|
|
61
|
+
* What `tasks add` does when tasks like the new one exist: nothing yet (it refuses and lists them), `attach` links
|
|
62
|
+
* the message to one of them instead, `new` opens the task anyway.
|
|
63
|
+
*/
|
|
64
|
+
export interface DuplicateChoice {
|
|
65
|
+
attach?: string;
|
|
66
|
+
new?: boolean;
|
|
67
|
+
}
|
|
68
|
+
/** How many candidates a refused `tasks add` lists. */
|
|
69
|
+
export declare const REFUSAL_CANDIDATES = 5;
|
|
70
|
+
export type DuplicateCandidate = Pick<SimilarTask, "ref" | "key" | "title" | "status" | "score" | "band" | "reasons">;
|
|
60
71
|
export interface TaskCard extends TaskDetails {
|
|
61
72
|
links: ThingLink[];
|
|
62
73
|
}
|
|
@@ -70,11 +81,34 @@ export interface TasksService {
|
|
|
70
81
|
similar(subject: string | TaskDraft, options?: {
|
|
71
82
|
limit?: number;
|
|
72
83
|
}): Promise<SimilarTask[]>;
|
|
73
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Refused (`task.duplicate-candidates`, with the candidates) while an open or recent task is likely or maybe the
|
|
86
|
+
* same job, unless `choice` says to attach the message to one of them or to open the task anyway.
|
|
87
|
+
*/
|
|
88
|
+
add(message: string, type: TaskKind, origin: TaskOrigin, plan?: TaskPlan, choice?: DuplicateChoice): Promise<{
|
|
74
89
|
task: TaskView;
|
|
75
90
|
created: boolean;
|
|
91
|
+
attached?: boolean;
|
|
76
92
|
card?: TaskCard;
|
|
77
93
|
}>;
|
|
94
|
+
/** Pairs a rule left for review — or, with `unsure`, the ones the reviewing agent passed to the owner — newest first. */
|
|
95
|
+
duplicates(options: {
|
|
96
|
+
unsure: boolean;
|
|
97
|
+
limit: number;
|
|
98
|
+
offset: number;
|
|
99
|
+
}): Promise<TaskPair[]>;
|
|
100
|
+
/** `rejected`: not the same job, never offered again. `unsure`: the owner decides. */
|
|
101
|
+
decideDuplicate(dup: string, task: string, decision: "rejected" | "unsure", by: TaskOrigin): Promise<TaskPair>;
|
|
102
|
+
/** Links every message of `dup` to `into` and closes `dup` as its duplicate; `unmerge` undoes it. */
|
|
103
|
+
merge(dup: string, into: string, by: TaskOrigin): Promise<{
|
|
104
|
+
pair: TaskPair;
|
|
105
|
+
linked: number;
|
|
106
|
+
task: TaskCard;
|
|
107
|
+
}>;
|
|
108
|
+
unmerge(dup: string, by: TaskOrigin): Promise<{
|
|
109
|
+
pair: TaskPair;
|
|
110
|
+
task: TaskCard;
|
|
111
|
+
}>;
|
|
78
112
|
close(id: string, options: {
|
|
79
113
|
as: ClosedState;
|
|
80
114
|
reason?: string;
|
|
@@ -101,7 +135,7 @@ export interface TasksService {
|
|
|
101
135
|
}>;
|
|
102
136
|
show(id: string): Promise<TaskCard>;
|
|
103
137
|
/** The list a task's category comes from, with what each one means. */
|
|
104
|
-
categories(): readonly TaskCategory[]
|
|
138
|
+
categories(): Promise<readonly TaskCategory[]>;
|
|
105
139
|
/** Takes an open task for `holder` for `forMs`; refused, naming the holder, while someone else holds it. */
|
|
106
140
|
claim(id: string, holder: string, forMs: number): Promise<TaskCard>;
|
|
107
141
|
/** Gives a task back; only its holder or the owner may. */
|
|
@@ -115,6 +149,7 @@ export declare const taskStateOf: (typed: string) => "dismissed" | "done" | "ope
|
|
|
115
149
|
export declare const closedStateOf: (typed: string) => "dismissed" | "done";
|
|
116
150
|
export declare const taskLinkKindOf: (typed: string) => "blocked-by" | "created-from" | "discovered-from" | "duplicate-of" | "evidence" | "follow-up-of" | "related-to";
|
|
117
151
|
export declare const taskTypesOf: (typed: string) => TaskKind[];
|
|
152
|
+
/** `categories` fixes the list; left out, each call reads the store's (`config set task_categories.*`). */
|
|
118
153
|
export declare const tasksService: (deps: ServiceDeps, categories?: readonly TaskCategory[]) => TasksService;
|
|
119
154
|
/** A stored task as the `task` entity: its chat as a `chat:` reference, its times in ISO 8601. */
|
|
120
155
|
export declare const taskItem: (account: AccountKey, { task, title, updatedAt }: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/services/tasks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAgD,MAAM,yBAAyB,CAAA;AACrG,OAAO,KAAK,KAAK,CAAC,MAAM,SAAS,CAAA;AAGjC,OAAO,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,SAAS,EACd,KAAK,YAAY,EAElB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAEzF,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,UAAU,EACf,UAAU,EACV,WAAW,EACX,KAAK,IAAI,EACT,KAAK,QAAQ,EACb,KAAK,UAAU,EAChB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,OAAO,
|
|
1
|
+
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/services/tasks.ts"],"names":[],"mappings":"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"}
|
package/dist/services/tasks.js
CHANGED
|
@@ -7,7 +7,7 @@ import { TASK_RELATION_KINDS, } from "../store/index.js";
|
|
|
7
7
|
import { queryFilter } from "../store/store.js";
|
|
8
8
|
import { createTaskService, TASK_KINDS, TASK_STATES, } from "../tasks/index.js";
|
|
9
9
|
import { storedChatId } from "./message-resolution.js";
|
|
10
|
-
import { categorize,
|
|
10
|
+
import { categorize, taskCategoryOf } from "./task-categories.js";
|
|
11
11
|
import { taskAccount } from "./task-rules.js";
|
|
12
12
|
export { TASK_KINDS, TASK_STATES };
|
|
13
13
|
export const TASK_QUERY = {
|
|
@@ -67,6 +67,8 @@ export const TASK_LINK_OPTION_KINDS = [
|
|
|
67
67
|
"duplicate-of",
|
|
68
68
|
"discovered-from",
|
|
69
69
|
];
|
|
70
|
+
/** How many candidates a refused `tasks add` lists. */
|
|
71
|
+
export const REFUSAL_CANDIDATES = 5;
|
|
70
72
|
/** An owner-project task's id, `task:<id>` written without its prefix, or a project key such as `HRB-12`. */
|
|
71
73
|
const BARE_TASK = /^(\d+|[A-Z][A-Z0-9]*-\d+)$/;
|
|
72
74
|
/** How long a claim lasts when the caller names no time: a crashed agent never holds a task for long. */
|
|
@@ -88,8 +90,10 @@ export const taskTypesOf = (typed) => [
|
|
|
88
90
|
.filter((one) => one.trim() !== "")
|
|
89
91
|
.map(taskTypeOf)),
|
|
90
92
|
];
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
/** `categories` fixes the list; left out, each call reads the store's (`config set task_categories.*`). */
|
|
94
|
+
export const tasksService = (deps, categories) => {
|
|
95
|
+
const listOf = async (store) => categories ?? (await store.tasks.categories());
|
|
96
|
+
const categoryOf = async (store, name) => taskCategoryOf(await listOf(store))(name);
|
|
93
97
|
const inStore = async (work) => work(await deps.store(), await deps.account());
|
|
94
98
|
const service = (store) => createTaskService({ store: store.tasks });
|
|
95
99
|
const groupOf = async (store, account, chat) => chat === undefined ? undefined : storedChatId(deps.messenger, chat, store, account);
|
|
@@ -108,7 +112,7 @@ export const tasksService = (deps, categories = DEFAULT_TASK_CATEGORIES) => {
|
|
|
108
112
|
};
|
|
109
113
|
const planOf = async (store, id, plan, by) => {
|
|
110
114
|
if (plan.category !== undefined)
|
|
111
|
-
plan = { ...plan, category: categoryOf(plan.category) };
|
|
115
|
+
plan = { ...plan, category: await categoryOf(store, plan.category) };
|
|
112
116
|
const open = (await store.tasks.get(id))?.state === "open";
|
|
113
117
|
if (!open && (plan.dueAt != null || plan.nextCheckAt != null))
|
|
114
118
|
throw new CliError("validation_error", "a closed task takes no due date or next check; it stays closed");
|
|
@@ -130,8 +134,8 @@ export const tasksService = (deps, categories = DEFAULT_TASK_CATEGORIES) => {
|
|
|
130
134
|
...(previews ? { previews: await Promise.all(shown.map(({ task }) => taskView(store, account, task))) } : {}),
|
|
131
135
|
};
|
|
132
136
|
}),
|
|
133
|
-
add: (message, type, origin, { category: named, ...plan } = {}) => inStore(async (store, account) => {
|
|
134
|
-
const chosen = named === undefined ? undefined : categoryOf(named);
|
|
137
|
+
add: (message, type, origin, { category: named, ...plan } = {}, choice = {}) => inStore(async (store, account) => {
|
|
138
|
+
const chosen = named === undefined ? undefined : await categoryOf(store, named);
|
|
135
139
|
const source = message.trim();
|
|
136
140
|
const native = isNoteReference(source);
|
|
137
141
|
if (!native && !isLocator(source)) {
|
|
@@ -152,6 +156,57 @@ export const tasksService = (deps, categories = DEFAULT_TASK_CATEGORIES) => {
|
|
|
152
156
|
return { task: await taskView(store, account, existing), created: false };
|
|
153
157
|
}
|
|
154
158
|
}
|
|
159
|
+
const held = (await store.tasks.findBySource(taskAccount(account), note ? note.ref : source)).find((one) => one.kind === type);
|
|
160
|
+
if (held)
|
|
161
|
+
return { task: await taskView(store, account, held), created: false };
|
|
162
|
+
if (choice.attach !== undefined && choice.new)
|
|
163
|
+
throw new CliError("validation_error", "choose one: --attach <task> or --new");
|
|
164
|
+
const draft = {
|
|
165
|
+
title: plan.title ?? "",
|
|
166
|
+
...(plan.description === undefined ? {} : { description: plan.description }),
|
|
167
|
+
...(note ? {} : { source }),
|
|
168
|
+
...(chosen === undefined ? {} : { category: chosen }),
|
|
169
|
+
...(plan.dueAt ? { due: plan.dueAt } : {}),
|
|
170
|
+
};
|
|
171
|
+
const subject = { account: taskAccount(account), draft };
|
|
172
|
+
const by = origin === "owner" ? "owner" : { bot: origin };
|
|
173
|
+
if (choice.attach !== undefined) {
|
|
174
|
+
const target = await owned(store, account, choice.attach);
|
|
175
|
+
const similarity = await store.tasks.compare(subject, target.id);
|
|
176
|
+
const link = {
|
|
177
|
+
from: (await store.tasks.details(target.id)).ref,
|
|
178
|
+
kind: "evidence",
|
|
179
|
+
origin: origin === "owner" ? "owner" : "suggested",
|
|
180
|
+
};
|
|
181
|
+
try {
|
|
182
|
+
await store.notes.addLink({ ...link, to: note ? note.ref : source });
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
// A message the store has not saved yet is linked by its locator as written.
|
|
186
|
+
if (!(error instanceof CliError && error.code === "not_found" && !note))
|
|
187
|
+
throw error;
|
|
188
|
+
await store.notes.addLink({ ...link, targetText: source });
|
|
189
|
+
}
|
|
190
|
+
await store.tasks.recordPair({ source, other: target.id, decision: "attached", similarity, by });
|
|
191
|
+
return { task: await taskView(store, account, target), created: false, attached: true };
|
|
192
|
+
}
|
|
193
|
+
const candidates = (await store.tasks.similar(subject, { limit: 40 })).filter((one) => one.band !== "different");
|
|
194
|
+
if (candidates.length > 0 && !choice.new) {
|
|
195
|
+
const shown = candidates
|
|
196
|
+
.slice(0, REFUSAL_CANDIDATES)
|
|
197
|
+
.map(({ ref, key, title, status, score, band, reasons }) => ({
|
|
198
|
+
ref,
|
|
199
|
+
key,
|
|
200
|
+
title,
|
|
201
|
+
status,
|
|
202
|
+
score,
|
|
203
|
+
band,
|
|
204
|
+
reasons,
|
|
205
|
+
}));
|
|
206
|
+
throw new CliError("validation_error", `${candidates.length === 1 ? "a task" : `${candidates.length} tasks`} may be the same job: ` +
|
|
207
|
+
`${shown.map((one) => `${one.key} (${one.band}, ${one.score}: ${one.reasons.join(", ")})`).join("; ")}` +
|
|
208
|
+
" — attach the message to one with --attach <task>, or open it anyway with --new", { reason: "task.duplicate-candidates", candidates: shown });
|
|
209
|
+
}
|
|
155
210
|
const sourceText = async () => note
|
|
156
211
|
? note.text
|
|
157
212
|
: locator
|
|
@@ -165,16 +220,36 @@ export const tasksService = (deps, categories = DEFAULT_TASK_CATEGORIES) => {
|
|
|
165
220
|
kind: type,
|
|
166
221
|
origin,
|
|
167
222
|
...(plan.dueAt ? { dueAt: plan.dueAt } : {}),
|
|
168
|
-
category: chosen ?? categorize(await sourceText(),
|
|
223
|
+
category: chosen ?? categorize(await sourceText(), await listOf(store)),
|
|
169
224
|
});
|
|
170
225
|
const task = (await store.tasks.get(added.id)) ?? added;
|
|
226
|
+
if (created)
|
|
227
|
+
for (const one of candidates)
|
|
228
|
+
await store.tasks.recordPair({ task: task.id, other: one.ref, decision: "new", similarity: one, by });
|
|
171
229
|
// A source that already has a task keeps its plan: adding again is not editing.
|
|
172
230
|
if (!created || Object.keys(plan).length === 0)
|
|
173
231
|
return { task: await taskView(store, account, task), created };
|
|
174
232
|
const card = await planOf(store, task.id, plan, origin);
|
|
175
233
|
return { task: await taskView(store, account, task), created, card };
|
|
176
234
|
}),
|
|
177
|
-
categories: () =>
|
|
235
|
+
categories: () => inStore(async (store) => listOf(store)),
|
|
236
|
+
duplicates: ({ unsure, limit, offset }) => inStore(async (store, account) => store.tasks.pairs(taskAccount(account), { decision: unsure ? "unsure" : "review", limit, offset })),
|
|
237
|
+
decideDuplicate: (dup, task, decision, by) => inStore(async (store, account) => {
|
|
238
|
+
await owned(store, account, dup);
|
|
239
|
+
await owned(store, account, task);
|
|
240
|
+
return store.tasks.decidePair(dup, task, decision, by === "owner" ? "owner" : { bot: by });
|
|
241
|
+
}),
|
|
242
|
+
merge: (dup, into, by) => inStore(async (store, account) => {
|
|
243
|
+
await owned(store, account, dup);
|
|
244
|
+
await owned(store, account, into);
|
|
245
|
+
const merged = await store.tasks.merge(dup, into, by === "owner" ? "owner" : { bot: by });
|
|
246
|
+
return { ...merged, task: await cardOf(store, into) };
|
|
247
|
+
}),
|
|
248
|
+
unmerge: (dup, by) => inStore(async (store, account) => {
|
|
249
|
+
await owned(store, account, dup);
|
|
250
|
+
const { pair } = await store.tasks.unmerge(dup, by === "owner" ? "owner" : { bot: by });
|
|
251
|
+
return { pair, task: await cardOf(store, dup) };
|
|
252
|
+
}),
|
|
178
253
|
claim: (id, holder, forMs) => inStore(async (store, account) => {
|
|
179
254
|
await owned(store, account, id);
|
|
180
255
|
await store.tasks.claim(id, holder, new Date(Date.now() + forMs));
|