@zhin.js/plugin-ledger 1.0.2 → 1.0.3

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/README.md CHANGED
@@ -73,6 +73,24 @@ ledger:
73
73
 
74
74
  发送 `记账日报 开启` 订阅。插件每分钟检查一次,按 `timezone` 到达 `reportTime` 后给订阅者私信当天的合计和分类明细,每人每天最多一次;当天没有记账时默认不发送。在群里开启时会先私信一条确认,私信失败则不开启并提示先私聊 Bot。在 `reportTime` 之后开启的,从第二天开始发送。投递失败只记录日志,当天不重试。
75
75
 
76
+ ## Agent 工具与技能
77
+
78
+ 启用 `@zhin.js/tool` 与 `@zhin.js/skill` Feature 后,本插件提供 `ledger` 技能与以下工具(按当前发送者隔离,群聊遵守同样的金额隐私策略):
79
+
80
+ | 工具 | 权限/属性 | 说明 |
81
+ | --- | --- | --- |
82
+ | `ledger_add` | `requiresApproval: 'always'` | 记录一笔个人支出(`category`、`amount`、可选 `note`) |
83
+ | `ledger_summary` | `readOnly: true` | 查看 `today` / `week` / `month` 的消费汇总(`summary`)或分类统计(`categories`) |
84
+ | `ledger_list` | `readOnly: true` | 查看指定时间段内的账单明细与编号(`#seq`) |
85
+ | `ledger_delete` | `requiresApproval: 'always'` | 按编号 `seq` 删除当前发送者自己的账目 |
86
+
87
+ ## Console 页面与 RPC
88
+
89
+ 启用 `@zhin.js/page` Feature 后,插件暴露声明式页面 `pages/index/index.ts` 与 Console RPC:
90
+
91
+ - `status`(`ledger:read`):返回日报订阅人数、订阅状态摘要(`ownerKey`、`reportLocale`、`lastReportDate`)与运行配置,不暴露个人消费明细或金额。
92
+ - `run-daily-reports`(`ledger:write`):立即触发一次当日日报检查与投递。
93
+
76
94
  ## 开发
77
95
 
78
96
  ```bash
package/lib/config.d.ts CHANGED
@@ -5,11 +5,17 @@ export declare const ledgerConfig: Schema<Schema.InputRecord<{
5
5
  timezone: Schema<string, string> & Schema.Present;
6
6
  reportTime: Schema<string, string> & Schema.Present;
7
7
  reportWhenEmpty: Schema<boolean, boolean> & Schema.Present;
8
- }>, {
9
- timezone: string;
10
- reportTime: string;
11
- reportWhenEmpty: boolean;
12
- } & {}>;
8
+ }>, Schema.RecordTypes<{
9
+ timezone: Schema<string, string> & Schema.Present;
10
+ reportTime: Schema<string, string> & Schema.Present;
11
+ reportWhenEmpty: Schema<boolean, boolean> & Schema.Present;
12
+ }>> & {
13
+ readonly output?: Schema.RecordTypes<{
14
+ timezone: Schema<string, string> & Schema.Present;
15
+ reportTime: Schema<string, string> & Schema.Present;
16
+ reportWhenEmpty: Schema<boolean, boolean> & Schema.Present;
17
+ }> | undefined;
18
+ };
13
19
  export type LedgerConfig = Schema.Output<typeof ledgerConfig>;
14
20
  export interface ResolvedLedgerConfig {
15
21
  readonly timezone: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAChD,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C,eAAO,MAAM,YAAY;;;;;;;;OAIvB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,YAAY,CAAC,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;CACnC;AAaD,kGAAkG;AAClG,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,GAAG,oBAAoB,CAOnG"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAChD,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C,eAAO,MAAM,YAAY;;;;;;;;;;;;;;CAIvB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,YAAY,CAAC,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;CACnC;AAaD,kGAAkG;AAClG,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,GAAG,oBAAoB,CAOnG"}
@@ -0,0 +1,4 @@
1
+ import { type PluginConsoleRpc } from 'zhin.js';
2
+ import type { LedgerService } from './service.js';
3
+ export declare function createLedgerConsoleRpc(service?: LedgerService): PluginConsoleRpc;
4
+ //# sourceMappingURL=console.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,EAEtB,MAAM,SAAS,CAAC;AAEjB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAalD,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,gBAAgB,CA0BhF"}
package/lib/console.js ADDED
@@ -0,0 +1,39 @@
1
+ import { definePluginConsoleRpc, PluginConsoleRpcError, } from 'zhin.js';
2
+ import { ledgerServiceToken } from './runtime.js';
3
+ function resolveService(provided, call) {
4
+ if (provided)
5
+ return provided;
6
+ const runtimeWithUse = call.runtime;
7
+ const fromRuntime = runtimeWithUse?.use?.(ledgerServiceToken);
8
+ if (fromRuntime)
9
+ return fromRuntime;
10
+ throw new PluginConsoleRpcError('unavailable', '记账服务尚未就绪');
11
+ }
12
+ export function createLedgerConsoleRpc(service) {
13
+ const rpc = definePluginConsoleRpc({
14
+ status: {
15
+ page: 'index',
16
+ requiredPermissions: ['ledger:read'],
17
+ async handler(_input, call) {
18
+ return resolveService(service, call).getConsoleSnapshot();
19
+ },
20
+ },
21
+ actions: {
22
+ 'run-daily-reports': {
23
+ page: 'index',
24
+ requiredPermissions: ['ledger:write'],
25
+ async handler(_input, call) {
26
+ const sent = await resolveService(service, call).runDailyReports();
27
+ return { sent };
28
+ },
29
+ },
30
+ },
31
+ });
32
+ const methods = rpc.methods;
33
+ const originalGet = methods.get.bind(methods);
34
+ const originalHas = methods.has.bind(methods);
35
+ methods.get = (key) => originalGet(key === 'runDailyReports' ? 'run-daily-reports' : key);
36
+ methods.has = (key) => originalHas(key === 'runDailyReports' ? 'run-daily-reports' : key);
37
+ return rpc;
38
+ }
39
+ //# sourceMappingURL=console.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.js","sourceRoot":"","sources":["../src/console.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,qBAAqB,GAGtB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGlD,SAAS,cAAc,CACrB,QAAmC,EACnC,IAA0B;IAE1B,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,cAAc,GAAG,IAAI,CAAC,OAAoF,CAAC;IACjH,MAAM,WAAW,GAAG,cAAc,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,CAAC;IAC9D,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IACpC,MAAM,IAAI,qBAAqB,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAuB;IAC5D,MAAM,GAAG,GAAG,sBAAsB,CAAC;QACjC,MAAM,EAAE;YACN,IAAI,EAAE,OAAO;YACb,mBAAmB,EAAE,CAAC,aAAa,CAAC;YACpC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI;gBACxB,OAAO,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,kBAAkB,EAAE,CAAC;YAC5D,CAAC;SACF;QACD,OAAO,EAAE;YACP,mBAAmB,EAAE;gBACnB,IAAI,EAAE,OAAO;gBACb,mBAAmB,EAAE,CAAC,cAAc,CAAC;gBACrC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI;oBACxB,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;oBACnE,OAAO,EAAE,IAAI,EAAE,CAAC;gBAClB,CAAC;aACF;SACF;KACF,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,GAAG,CAAC,OAAsE,CAAC;IAC3F,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,KAAK,iBAAiB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAClG,OAAO,CAAC,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,KAAK,iBAAiB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAClG,OAAO,GAAG,CAAC;AACb,CAAC"}
package/lib/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  export { ledgerConfig, resolveLedgerConfig, DEFAULT_REPORT_TIME, DEFAULT_TIMEZONE, type LedgerConfig, type ResolvedLedgerConfig } from './config.js';
2
+ export { createLedgerConsoleRpc } from './console.js';
2
3
  export { parseEntryInput, ADD_USAGE, MAX_CATEGORY_LENGTH, MAX_NOTE_LENGTH, type EntryInputResult, type ParsedEntryInput } from './entry-input.js';
3
4
  export { ledgerCaller, ledgerOwnerKey, replyLedger, LedgerInputError, type LedgerCaller } from './identity.js';
4
5
  export { formatCents, parseAmountToCents, MASKED_AMOUNT, MAX_ENTRY_CENTS, type AmountParseResult } from './money.js';
5
6
  export { describePeriodRange, isInPeriod, localDateKey, localTimeKey, parsePeriodWord, periodLabel, weekEndKey, weekStartKey, type LedgerPeriod, } from './period.js';
6
7
  export { formatCategoryStatistics, formatEntryList, formatPeriodSummary, summarize, totalsByCategory, MAX_LISTED_ENTRIES, type CategoryTotal, type LedgerReply, type PeriodSummary, } from './report-format.js';
7
8
  export { ledgerServiceToken } from './runtime.js';
8
- export { LedgerService, type DailyReportAction, type LedgerServiceOptions } from './service.js';
9
+ export { LedgerService, type DailyReportAction, type LedgerConsoleSnapshot, type LedgerConsoleSubscriber, type LedgerServiceOptions, } from './service.js';
9
10
  export { defineLedgerTables, LedgerStore, ENTRY_TABLE, USER_TABLE, PRIVATE_TARGET_TABLE, type LedgerEntry, type LedgerUserRecord } from './store.js';
11
+ export { ledgerCallerFromTool, type LedgerToolCallerContext } from './tool-caller.js';
10
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrJ,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,mBAAmB,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAClJ,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC/G,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACrH,OAAO,EACL,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,WAAW,EACX,UAAU,EACV,YAAY,EACZ,KAAK,YAAY,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,oBAAoB,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACrJ,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,mBAAmB,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAClJ,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC/G,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACrH,OAAO,EACL,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,WAAW,EACX,UAAU,EACV,YAAY,EACZ,KAAK,YAAY,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,GAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,oBAAoB,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACrJ,OAAO,EAAE,oBAAoB,EAAE,KAAK,uBAAuB,EAAE,MAAM,kBAAkB,CAAC"}
package/lib/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  export { ledgerConfig, resolveLedgerConfig, DEFAULT_REPORT_TIME, DEFAULT_TIMEZONE } from './config.js';
2
+ export { createLedgerConsoleRpc } from './console.js';
2
3
  export { parseEntryInput, ADD_USAGE, MAX_CATEGORY_LENGTH, MAX_NOTE_LENGTH } from './entry-input.js';
3
4
  export { ledgerCaller, ledgerOwnerKey, replyLedger, LedgerInputError } from './identity.js';
4
5
  export { formatCents, parseAmountToCents, MASKED_AMOUNT, MAX_ENTRY_CENTS } from './money.js';
5
6
  export { describePeriodRange, isInPeriod, localDateKey, localTimeKey, parsePeriodWord, periodLabel, weekEndKey, weekStartKey, } from './period.js';
6
7
  export { formatCategoryStatistics, formatEntryList, formatPeriodSummary, summarize, totalsByCategory, MAX_LISTED_ENTRIES, } from './report-format.js';
7
8
  export { ledgerServiceToken } from './runtime.js';
8
- export { LedgerService } from './service.js';
9
+ export { LedgerService, } from './service.js';
9
10
  export { defineLedgerTables, LedgerStore, ENTRY_TABLE, USER_TABLE, PRIVATE_TARGET_TABLE } from './store.js';
11
+ export { ledgerCallerFromTool } from './tool-caller.js';
10
12
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,gBAAgB,EAAgD,MAAM,aAAa,CAAC;AACrJ,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,mBAAmB,EAAE,eAAe,EAAgD,MAAM,kBAAkB,CAAC;AAClJ,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAqB,MAAM,eAAe,CAAC;AAC/G,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,eAAe,EAA0B,MAAM,YAAY,CAAC;AACrH,OAAO,EACL,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,WAAW,EACX,UAAU,EACV,YAAY,GAEb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,gBAAgB,EAChB,kBAAkB,GAInB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,aAAa,EAAqD,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,oBAAoB,EAA2C,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,gBAAgB,EAAgD,MAAM,aAAa,CAAC;AACrJ,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,mBAAmB,EAAE,eAAe,EAAgD,MAAM,kBAAkB,CAAC;AAClJ,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAqB,MAAM,eAAe,CAAC;AAC/G,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,eAAe,EAA0B,MAAM,YAAY,CAAC;AACrH,OAAO,EACL,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,WAAW,EACX,UAAU,EACV,YAAY,GAEb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,gBAAgB,EAChB,kBAAkB,GAInB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,aAAa,GAKd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,oBAAoB,EAA2C,MAAM,YAAY,CAAC;AACrJ,OAAO,EAAE,oBAAoB,EAAgC,MAAM,kBAAkB,CAAC"}
package/lib/service.d.ts CHANGED
@@ -3,6 +3,18 @@ import type { ResolvedLedgerConfig } from './config.js';
3
3
  import type { LedgerCaller } from './identity.js';
4
4
  import { type LedgerPeriod } from './period.js';
5
5
  export type DailyReportAction = 'on' | 'off' | 'status';
6
+ export type LedgerConsoleSubscriber = {
7
+ readonly ownerKey: string;
8
+ readonly reportLocale: string;
9
+ readonly lastReportDate: string;
10
+ };
11
+ export type LedgerConsoleSnapshot = {
12
+ readonly timezone: string;
13
+ readonly reportTime: string;
14
+ readonly reportWhenEmpty: boolean;
15
+ readonly subscriberCount: number;
16
+ readonly subscribers: readonly LedgerConsoleSubscriber[];
17
+ };
6
18
  export interface LedgerServiceOptions {
7
19
  /** Wall clock; tests pass a fake. */
8
20
  readonly now?: () => number;
@@ -29,5 +41,6 @@ export declare class LedgerService {
29
41
  * not retried that day, so an unreachable user is not messaged every minute.
30
42
  */
31
43
  runDailyReports(): Promise<number>;
44
+ getConsoleSnapshot(): Promise<LedgerConsoleSnapshot>;
32
45
  }
33
46
  //# sourceMappingURL=service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkC,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACrG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAuD,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAYrG,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,KAAK,GAAG,QAAQ,CAAC;AAExD,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,qBAAa,aAAa;;gBAUZ,QAAQ,EAAE,kBAAkB,EAAE,QAAQ,EAAE,YAAY,GAAG,SAAS,EAAE,MAAM,EAAE,oBAAoB,EAAE,OAAO,GAAE,oBAAyB;IAwCxI,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAsB7D,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiB/D,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAM1E,kBAAkB,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAM/E,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA8BxE,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA2BzG;;;;OAIG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;CAuBzC"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkC,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACrG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAuD,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAYrG,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,KAAK,GAAG,QAAQ,CAAC;AAExD,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,SAAS,uBAAuB,EAAE,CAAC;CAC1D,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,qBAAa,aAAa;;gBAUZ,QAAQ,EAAE,kBAAkB,EAAE,QAAQ,EAAE,YAAY,GAAG,SAAS,EAAE,MAAM,EAAE,oBAAoB,EAAE,OAAO,GAAE,oBAAyB;IAwCxI,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAsB7D,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiB/D,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAM1E,kBAAkB,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAM/E,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA8BxE,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA2BzG;;;;OAIG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IAwBlC,kBAAkB,IAAI,OAAO,CAAC,qBAAqB,CAAC;CAc3D"}
package/lib/service.js CHANGED
@@ -205,5 +205,19 @@ export class LedgerService {
205
205
  }
206
206
  return sent;
207
207
  }
208
+ async getConsoleSnapshot() {
209
+ const subscribers = await this.#store.listReportSubscribers();
210
+ return {
211
+ timezone: this.#config.timezone,
212
+ reportTime: this.#config.reportTime,
213
+ reportWhenEmpty: this.#config.reportWhenEmpty,
214
+ subscriberCount: subscribers.length,
215
+ subscribers: subscribers.map((subscriber) => ({
216
+ ownerKey: subscriber.ownerKey,
217
+ reportLocale: resolveLocale(subscriber.reportLocale),
218
+ lastReportDate: subscriber.lastReportDate,
219
+ })),
220
+ };
221
+ }
208
222
  }
209
223
  //# sourceMappingURL=service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { type Locale } from 'zhin.js/i18n';
2
+ import { type DeliveryTarget } from 'zhin.js';
3
+ import { adapterFeatureId } from 'zhin.js/adapter';
4
+ import { type LedgerCaller } from './identity.js';
5
+ export type LedgerToolOrigin = Readonly<{
6
+ kind: 'im';
7
+ platform: string;
8
+ endpoint: string;
9
+ scope: 'private' | 'group' | 'channel';
10
+ sceneId: string;
11
+ messageId?: string;
12
+ threadId?: string;
13
+ conversation?: DeliveryTarget & Readonly<{
14
+ name?: string;
15
+ }>;
16
+ }> | Readonly<{
17
+ kind: Exclude<string, 'im'>;
18
+ [key: string]: unknown;
19
+ }>;
20
+ export interface LedgerToolCallerContext {
21
+ readonly origin: LedgerToolOrigin;
22
+ readonly locale?: Locale;
23
+ readonly senderId?: string;
24
+ readonly principal?: Readonly<{
25
+ subjectId: string;
26
+ roles: readonly string[];
27
+ }>;
28
+ project?<T>(feature: typeof adapterFeatureId): T;
29
+ }
30
+ /** Builds a LedgerCaller from an Agent Tool execution context. */
31
+ export declare function ledgerCallerFromTool(context: LedgerToolCallerContext): LedgerCaller;
32
+ //# sourceMappingURL=tool-caller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-caller.d.ts","sourceRoot":"","sources":["../src/tool-caller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAqB,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEpF,MAAM,MAAM,gBAAgB,GACxB,QAAQ,CAAC;IACP,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,cAAc,GAAG,QAAQ,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7D,CAAC,GACF,QAAQ,CAAC;IAAE,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC,CAAC;AAEtE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC/E,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,gBAAgB,GAAG,CAAC,CAAC;CAClD;AAsDD,kEAAkE;AAClE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,YAAY,CAoBnF"}
@@ -0,0 +1,74 @@
1
+ import { resolveLocale } from 'zhin.js/i18n';
2
+ import { createDeliveryTarget } from 'zhin.js';
3
+ import { adapterFeatureId } from 'zhin.js/adapter';
4
+ import { messages as t } from './i18n.js';
5
+ import { LedgerInputError, ledgerOwnerKey } from './identity.js';
6
+ function isImOrigin(origin) {
7
+ return origin.kind === 'im';
8
+ }
9
+ function resolveToolConversation(context, locale) {
10
+ const origin = context.origin;
11
+ if (!isImOrigin(origin)) {
12
+ throw new LedgerInputError(t(locale, 'actor'));
13
+ }
14
+ let endpointId = origin.conversation?.endpoint.id ?? origin.endpoint;
15
+ if (typeof context.project === 'function') {
16
+ try {
17
+ const index = context.project(adapterFeatureId);
18
+ if (index && typeof index.describe === 'function') {
19
+ const matches = index
20
+ .describe()
21
+ .filter((endpoint) => (String(endpoint.id) === origin.endpoint || endpoint.name === origin.endpoint) &&
22
+ index.clientAdapter(endpoint.id) === origin.platform);
23
+ if (matches.length === 1) {
24
+ endpointId = String(matches[0].id);
25
+ }
26
+ }
27
+ }
28
+ catch {
29
+ // Fall back to origin endpoint when AdapterIndex projection is unavailable in lightweight contexts.
30
+ }
31
+ }
32
+ if (!endpointId) {
33
+ throw new LedgerInputError(t(locale, 'actor'));
34
+ }
35
+ if (origin.conversation) {
36
+ return createDeliveryTarget({
37
+ conversation: {
38
+ ...origin.conversation,
39
+ endpoint: { id: endpointId, adapter: origin.platform },
40
+ },
41
+ });
42
+ }
43
+ return createDeliveryTarget({
44
+ conversation: {
45
+ endpoint: { id: endpointId, adapter: origin.platform },
46
+ kind: origin.scope,
47
+ id: origin.sceneId,
48
+ ...(origin.threadId !== undefined ? { threadId: origin.threadId } : {}),
49
+ },
50
+ });
51
+ }
52
+ /** Builds a LedgerCaller from an Agent Tool execution context. */
53
+ export function ledgerCallerFromTool(context) {
54
+ const locale = resolveLocale(context.locale);
55
+ const senderId = (context.principal?.subjectId ?? context.senderId)?.trim();
56
+ if (!senderId) {
57
+ throw new LedgerInputError(t(locale, 'actor'));
58
+ }
59
+ const conversation = resolveToolConversation(context, locale);
60
+ const endpoint = conversation.endpoint;
61
+ const isPrivate = conversation.kind === 'private';
62
+ const privateTarget = isPrivate
63
+ ? conversation
64
+ : Object.freeze({ endpoint, kind: 'private', id: senderId });
65
+ return {
66
+ ownerKey: ledgerOwnerKey(endpoint.adapter, endpoint.id, senderId),
67
+ senderId,
68
+ locale,
69
+ conversation,
70
+ privateTarget,
71
+ isPrivate,
72
+ };
73
+ }
74
+ //# sourceMappingURL=tool-caller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-caller.js","sourceRoot":"","sources":["../src/tool-caller.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-ledger",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Personal expense ledger for Zhin.js (Plugin Runtime): per-user entries in integer cents, period and category summaries, group privacy and an opt-in daily report",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -16,8 +16,10 @@
16
16
  "README.md",
17
17
  "commands",
18
18
  "lib",
19
+ "pages",
19
20
  "plugin.js",
20
21
  "schedules",
22
+ "skills",
21
23
  "src",
22
24
  "schema.json"
23
25
  ],
@@ -34,10 +36,21 @@
34
36
  "email": "admin@liucl.cn",
35
37
  "url": "https://github.com/lc-cn"
36
38
  },
39
+ "dependencies": {
40
+ "@zhin.js/client": "1.1.25",
41
+ "@zhin.js/console-contract": "1.1.3",
42
+ "@zhin.js/page": "1.1.15",
43
+ "@zhin.js/skill": "1.1.14",
44
+ "@zhin.js/tool": "1.1.16"
45
+ },
37
46
  "peerDependencies": {
38
- "zhin.js": "^1.1.16",
39
- "@zhin.js/command": "^1.1.11",
40
- "@zhin.js/schedule-feature": "^1.1.9"
47
+ "zod": "^4.0.0",
48
+ "zhin.js": "^1.1.22",
49
+ "@zhin.js/command": "^1.1.15",
50
+ "@zhin.js/page": "^1.1.15",
51
+ "@zhin.js/schedule-feature": "^1.1.13",
52
+ "@zhin.js/skill": "^1.1.14",
53
+ "@zhin.js/tool": "^1.1.16"
41
54
  },
42
55
  "peerDependenciesMeta": {
43
56
  "@zhin.js/command": {
@@ -45,14 +58,18 @@
45
58
  },
46
59
  "@zhin.js/schedule-feature": {
47
60
  "optional": true
61
+ },
62
+ "zod": {
63
+ "optional": true
48
64
  }
49
65
  },
50
66
  "devDependencies": {
51
67
  "typescript": "^6.0.3",
52
68
  "vitest": "^4.1.10",
53
- "@zhin.js/schedule-feature": "1.1.9",
54
- "@zhin.js/testing": "1.0.6",
55
- "zhin.js": "1.1.16"
69
+ "zod": "^4.4.3",
70
+ "@zhin.js/schedule-feature": "1.1.13",
71
+ "@zhin.js/testing": "1.0.8",
72
+ "zhin.js": "1.1.22"
56
73
  },
57
74
  "engines": {
58
75
  "node": ">=22.19.0"
@@ -81,6 +98,18 @@
81
98
  {
82
99
  "package": "@zhin.js/schedule-feature",
83
100
  "api": "^1.0.0"
101
+ },
102
+ {
103
+ "package": "@zhin.js/tool",
104
+ "api": "^1.1.0"
105
+ },
106
+ {
107
+ "package": "@zhin.js/skill",
108
+ "api": "^1.0.0"
109
+ },
110
+ {
111
+ "package": "@zhin.js/page",
112
+ "api": "^1.0.0"
84
113
  }
85
114
  ],
86
115
  "plugins": []
@@ -0,0 +1,63 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { definePage } from '@zhin.js/console-contract';
3
+ import { createDeclarativePage } from '@zhin.js/client';
4
+ export const meta = definePage({
5
+ title: '记账本',
6
+ titleI18n: { en: 'Ledger' },
7
+ icon: 'Wallet',
8
+ order: 50,
9
+ requiredPermissions: ['ledger:read'],
10
+ });
11
+ export default createDeclarativePage({
12
+ title: { zh: '记账本', en: 'Ledger' },
13
+ description: {
14
+ zh: '个人记账日报订阅状态与运行配置概览。',
15
+ en: 'Personal expense ledger daily report subscriptions and runtime configuration.',
16
+ },
17
+ stats: [
18
+ {
19
+ key: 'subscriberCount',
20
+ label: { zh: '日报订阅数', en: 'Report Subscribers' },
21
+ value: 'subscriberCount',
22
+ },
23
+ {
24
+ key: 'reportTime',
25
+ label: { zh: '日报发送时间', en: 'Report Time' },
26
+ value: 'reportTime',
27
+ },
28
+ {
29
+ key: 'timezone',
30
+ label: { zh: '统计时区', en: 'Timezone' },
31
+ value: 'timezone',
32
+ },
33
+ ],
34
+ actions: [
35
+ {
36
+ name: 'run-daily-reports',
37
+ label: { zh: '执行日报发送', en: 'Run Daily Reports' },
38
+ variant: 'primary',
39
+ },
40
+ ],
41
+ sections: [
42
+ {
43
+ id: 'subscribers',
44
+ title: { zh: '日报订阅用户', en: 'Daily Report Subscribers' },
45
+ emptyText: { zh: '暂无开启记账日报的用户', en: 'No users have enabled daily reports.' },
46
+ items: 'subscribers',
47
+ columns: [
48
+ { key: 'ownerKey', label: { zh: '用户标识', en: 'Owner Key' } },
49
+ { key: 'reportLocale', label: { zh: '语言', en: 'Locale' } },
50
+ { key: 'lastReportDate', label: { zh: '最近发送日期', en: 'Last Report Date' } },
51
+ ],
52
+ },
53
+ {
54
+ id: 'config',
55
+ title: { zh: '配置详情', en: 'Configuration' },
56
+ entries: (data) => [
57
+ { label: 'Timezone', value: data.timezone },
58
+ { label: 'Report Time', value: data.reportTime },
59
+ { label: 'Report When Empty', value: data.reportWhenEmpty ? 'Yes' : 'No' },
60
+ ],
61
+ },
62
+ ],
63
+ });
@@ -0,0 +1,65 @@
1
+ import { definePage } from '@zhin.js/console-contract';
2
+ import { createDeclarativePage } from '@zhin.js/client';
3
+ import type { LedgerConsoleSnapshot, LedgerConsoleSubscriber } from '../../src/service.js';
4
+
5
+ export const meta = definePage({
6
+ title: '记账本',
7
+ titleI18n: { en: 'Ledger' },
8
+ icon: 'Wallet',
9
+ order: 50,
10
+ requiredPermissions: ['ledger:read'],
11
+ });
12
+
13
+ export default createDeclarativePage<LedgerConsoleSnapshot>({
14
+ title: { zh: '记账本', en: 'Ledger' },
15
+ description: {
16
+ zh: '个人记账日报订阅状态与运行配置概览。',
17
+ en: 'Personal expense ledger daily report subscriptions and runtime configuration.',
18
+ },
19
+ stats: [
20
+ {
21
+ key: 'subscriberCount',
22
+ label: { zh: '日报订阅数', en: 'Report Subscribers' },
23
+ value: 'subscriberCount',
24
+ },
25
+ {
26
+ key: 'reportTime',
27
+ label: { zh: '日报发送时间', en: 'Report Time' },
28
+ value: 'reportTime',
29
+ },
30
+ {
31
+ key: 'timezone',
32
+ label: { zh: '统计时区', en: 'Timezone' },
33
+ value: 'timezone',
34
+ },
35
+ ],
36
+ actions: [
37
+ {
38
+ name: 'run-daily-reports',
39
+ label: { zh: '执行日报发送', en: 'Run Daily Reports' },
40
+ variant: 'primary',
41
+ },
42
+ ],
43
+ sections: [
44
+ {
45
+ id: 'subscribers',
46
+ title: { zh: '日报订阅用户', en: 'Daily Report Subscribers' },
47
+ emptyText: { zh: '暂无开启记账日报的用户', en: 'No users have enabled daily reports.' },
48
+ items: 'subscribers',
49
+ columns: [
50
+ { key: 'ownerKey', label: { zh: '用户标识', en: 'Owner Key' } },
51
+ { key: 'reportLocale', label: { zh: '语言', en: 'Locale' } },
52
+ { key: 'lastReportDate', label: { zh: '最近发送日期', en: 'Last Report Date' } },
53
+ ] satisfies readonly { readonly key: keyof LedgerConsoleSubscriber & string; readonly label: { readonly zh: string; readonly en: string } }[],
54
+ },
55
+ {
56
+ id: 'config',
57
+ title: { zh: '配置详情', en: 'Configuration' },
58
+ entries: (data) => [
59
+ { label: 'Timezone', value: data.timezone },
60
+ { label: 'Report Time', value: data.reportTime },
61
+ { label: 'Report When Empty', value: data.reportWhenEmpty ? 'Yes' : 'No' },
62
+ ],
63
+ },
64
+ ],
65
+ });
package/plugin.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
- import { databaseHostToken, definePlugin, outboundHostToken } from 'zhin.js';
2
+ import { databaseHostToken, definePlugin, outboundHostToken, pluginConsoleRpcToken } from 'zhin.js';
3
3
  import { resolveLedgerConfig } from "./lib/config.js";
4
+ import { createLedgerConsoleRpc } from "./lib/console.js";
4
5
  import { ledgerServiceToken } from "./lib/runtime.js";
5
6
  import { LedgerService } from "./lib/service.js";
6
7
  import { defineLedgerTables } from "./lib/store.js";
@@ -15,5 +16,6 @@ export default definePlugin({
15
16
  const outbound = context.resources.has(outboundHostToken) ? context.resources.use(outboundHostToken) : undefined;
16
17
  const service = new LedgerService(database, outbound, config);
17
18
  context.resources.provide(ledgerServiceToken, service);
19
+ context.resources.provide(pluginConsoleRpcToken, createLedgerConsoleRpc(service));
18
20
  },
19
21
  });
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: ledger
3
+ description: >-
4
+ Personal expense ledger — record expenses, delete entries, view today/week/month spending summaries and category breakdowns.
5
+ keywords:
6
+ - 记账
7
+ - 账单
8
+ - 消费
9
+ - 支出
10
+ - 开销
11
+ - ledger
12
+ - expense
13
+ tags:
14
+ - ledger
15
+ - finance
16
+ tools:
17
+ - ledger_add
18
+ - ledger_summary
19
+ - ledger_list
20
+ - ledger_delete
21
+ ---
22
+
23
+ # 个人记账本 (Personal Ledger)
24
+
25
+ ## 何时使用本技能
26
+
27
+ - 用户想记录一笔消费/支出(如「记一笔午饭 18.5 元」「打车花了 32」)
28
+ - 用户想查看今日、本周或本月的消费汇总或分类占比
29
+ - 用户想列出近期的账单明细或按编号删除某笔账目
30
+
31
+ ## 工作流
32
+
33
+ 1. **记账 (`ledger_add`)**:提取类别(`category`)、金额(`amount`,正数元)与可选备注(`note`)。需要用户批准。
34
+ 2. **消费汇总与分类统计 (`ledger_summary`)**:按 `period`(`today` / `week` / `month`)查看总览(`mode: "summary"`)或分类统计(`mode: "categories"`)。
35
+ 3. **账单明细 (`ledger_list`)**:按 `period` 查看带 `#编号` 的账单列表。
36
+ 4. **删除账目 (`ledger_delete`)**:传入账目编号 `seq` 删除对应记录。需要用户批准。
37
+
38
+ ## 注意
39
+
40
+ - 账目按发送者隔离,用户只能操作自己的账本。
41
+ - 群聊场景下会自动保护金额隐私(优先私信发送完整账单或在群内脱敏显示)。
@@ -0,0 +1,25 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { replyLedger } from "../../../../lib/identity.js";
5
+ import { ledgerServiceToken } from "../../../../lib/runtime.js";
6
+ import { ledgerCallerFromTool } from "../../../../lib/tool-caller.js";
7
+ export default defineAgentTool({
8
+ description: 'Record a personal expense entry in the current user’s ledger with a category, positive amount, and optional note.',
9
+ requiresApproval: 'always',
10
+ tags: ['ledger', 'finance'],
11
+ keywords: ['记账', '消费', '支出', '开销', 'ledger', 'expense'],
12
+ inputSchema: z.object({
13
+ category: z.string().min(1).max(32).describe('Expense category, e.g. 午饭, 打车'),
14
+ amount: z.number().positive().describe('Expense amount in yuan, e.g. 18.5'),
15
+ note: z.string().max(120).optional().describe('Optional note for the expense'),
16
+ }),
17
+ async execute({ category, amount, note }, context) {
18
+ return replyLedger(async () => {
19
+ const caller = ledgerCallerFromTool(context);
20
+ const service = context.use(ledgerServiceToken);
21
+ const text = `${category} ${amount}${note ? ` ${note}` : ''}`;
22
+ return service.addEntry(caller, text);
23
+ });
24
+ },
25
+ });
@@ -0,0 +1,26 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { replyLedger } from '../../../../src/identity.js';
4
+ import { ledgerServiceToken } from '../../../../src/runtime.js';
5
+ import { ledgerCallerFromTool } from '../../../../src/tool-caller.js';
6
+
7
+ export default defineAgentTool({
8
+ description:
9
+ 'Record a personal expense entry in the current user’s ledger with a category, positive amount, and optional note.',
10
+ requiresApproval: 'always',
11
+ tags: ['ledger', 'finance'],
12
+ keywords: ['记账', '消费', '支出', '开销', 'ledger', 'expense'],
13
+ inputSchema: z.object({
14
+ category: z.string().min(1).max(32).describe('Expense category, e.g. 午饭, 打车'),
15
+ amount: z.number().positive().describe('Expense amount in yuan, e.g. 18.5'),
16
+ note: z.string().max(120).optional().describe('Optional note for the expense'),
17
+ }),
18
+ async execute({ category, amount, note }, context) {
19
+ return replyLedger(async () => {
20
+ const caller = ledgerCallerFromTool(context);
21
+ const service = context.use(ledgerServiceToken);
22
+ const text = `${category} ${amount}${note ? ` ${note}` : ''}`;
23
+ return service.addEntry(caller, text);
24
+ });
25
+ },
26
+ });
@@ -0,0 +1,22 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { replyLedger } from "../../../../lib/identity.js";
5
+ import { ledgerServiceToken } from "../../../../lib/runtime.js";
6
+ import { ledgerCallerFromTool } from "../../../../lib/tool-caller.js";
7
+ export default defineAgentTool({
8
+ description: 'Delete one of the current user’s expense entries by its sequence number (#id).',
9
+ requiresApproval: 'always',
10
+ tags: ['ledger', 'finance'],
11
+ keywords: ['删账', '删除记账', 'delete expense', 'ledger delete'],
12
+ inputSchema: z.object({
13
+ seq: z.number().int().positive().describe('Per-user entry sequence number (#id)'),
14
+ }),
15
+ async execute({ seq }, context) {
16
+ return replyLedger(async () => {
17
+ const caller = ledgerCallerFromTool(context);
18
+ const service = context.use(ledgerServiceToken);
19
+ return service.deleteEntry(caller, seq);
20
+ });
21
+ },
22
+ });
@@ -0,0 +1,23 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { replyLedger } from '../../../../src/identity.js';
4
+ import { ledgerServiceToken } from '../../../../src/runtime.js';
5
+ import { ledgerCallerFromTool } from '../../../../src/tool-caller.js';
6
+
7
+ export default defineAgentTool({
8
+ description:
9
+ 'Delete one of the current user’s expense entries by its sequence number (#id).',
10
+ requiresApproval: 'always',
11
+ tags: ['ledger', 'finance'],
12
+ keywords: ['删账', '删除记账', 'delete expense', 'ledger delete'],
13
+ inputSchema: z.object({
14
+ seq: z.number().int().positive().describe('Per-user entry sequence number (#id)'),
15
+ }),
16
+ async execute({ seq }, context) {
17
+ return replyLedger(async () => {
18
+ const caller = ledgerCallerFromTool(context);
19
+ const service = context.use(ledgerServiceToken);
20
+ return service.deleteEntry(caller, seq);
21
+ });
22
+ },
23
+ });
@@ -0,0 +1,23 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { replyLedger } from "../../../../lib/identity.js";
5
+ import { ledgerServiceToken } from "../../../../lib/runtime.js";
6
+ import { ledgerCallerFromTool } from "../../../../lib/tool-caller.js";
7
+ export default defineAgentTool({
8
+ description: 'List personal expense entries for today, this week, or this month with their sequence numbers (#id).',
9
+ requiresApproval: 'never',
10
+ readOnly: true,
11
+ tags: ['ledger', 'finance'],
12
+ keywords: ['账单', '账目列表', '消费明细', 'ledger list', 'expenses'],
13
+ inputSchema: z.object({
14
+ period: z.enum(['today', 'week', 'month']).default('today').describe('Time period: today, week, or month'),
15
+ }),
16
+ async execute({ period = 'today' }, context) {
17
+ return replyLedger(async () => {
18
+ const caller = ledgerCallerFromTool(context);
19
+ const service = context.use(ledgerServiceToken);
20
+ return service.listEntries(caller, period);
21
+ });
22
+ },
23
+ });
@@ -0,0 +1,24 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { replyLedger } from '../../../../src/identity.js';
4
+ import { ledgerServiceToken } from '../../../../src/runtime.js';
5
+ import { ledgerCallerFromTool } from '../../../../src/tool-caller.js';
6
+
7
+ export default defineAgentTool({
8
+ description:
9
+ 'List personal expense entries for today, this week, or this month with their sequence numbers (#id).',
10
+ requiresApproval: 'never',
11
+ readOnly: true,
12
+ tags: ['ledger', 'finance'],
13
+ keywords: ['账单', '账目列表', '消费明细', 'ledger list', 'expenses'],
14
+ inputSchema: z.object({
15
+ period: z.enum(['today', 'week', 'month']).default('today').describe('Time period: today, week, or month'),
16
+ }),
17
+ async execute({ period = 'today' }, context) {
18
+ return replyLedger(async () => {
19
+ const caller = ledgerCallerFromTool(context);
20
+ const service = context.use(ledgerServiceToken);
21
+ return service.listEntries(caller, period);
22
+ });
23
+ },
24
+ });
@@ -0,0 +1,27 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { replyLedger } from "../../../../lib/identity.js";
5
+ import { ledgerServiceToken } from "../../../../lib/runtime.js";
6
+ import { ledgerCallerFromTool } from "../../../../lib/tool-caller.js";
7
+ export default defineAgentTool({
8
+ description: 'View personal spending summary or category statistics for today, this week, or this month.',
9
+ requiresApproval: 'never',
10
+ readOnly: true,
11
+ tags: ['ledger', 'finance'],
12
+ keywords: ['消费汇总', '分类统计', '账单统计', 'ledger summary', 'spending'],
13
+ inputSchema: z.object({
14
+ period: z.enum(['today', 'week', 'month']).default('month').describe('Time period: today, week, or month'),
15
+ mode: z.enum(['summary', 'categories']).default('summary').describe('Summary view or detailed category statistics'),
16
+ }),
17
+ async execute({ period = 'month', mode = 'summary' }, context) {
18
+ return replyLedger(async () => {
19
+ const caller = ledgerCallerFromTool(context);
20
+ const service = context.use(ledgerServiceToken);
21
+ if (mode === 'categories') {
22
+ return service.categoryStatistics(caller, period);
23
+ }
24
+ return service.periodSummary(caller, period);
25
+ });
26
+ },
27
+ });
@@ -0,0 +1,28 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { replyLedger } from '../../../../src/identity.js';
4
+ import { ledgerServiceToken } from '../../../../src/runtime.js';
5
+ import { ledgerCallerFromTool } from '../../../../src/tool-caller.js';
6
+
7
+ export default defineAgentTool({
8
+ description:
9
+ 'View personal spending summary or category statistics for today, this week, or this month.',
10
+ requiresApproval: 'never',
11
+ readOnly: true,
12
+ tags: ['ledger', 'finance'],
13
+ keywords: ['消费汇总', '分类统计', '账单统计', 'ledger summary', 'spending'],
14
+ inputSchema: z.object({
15
+ period: z.enum(['today', 'week', 'month']).default('month').describe('Time period: today, week, or month'),
16
+ mode: z.enum(['summary', 'categories']).default('summary').describe('Summary view or detailed category statistics'),
17
+ }),
18
+ async execute({ period = 'month', mode = 'summary' }, context) {
19
+ return replyLedger(async () => {
20
+ const caller = ledgerCallerFromTool(context);
21
+ const service = context.use(ledgerServiceToken);
22
+ if (mode === 'categories') {
23
+ return service.categoryStatistics(caller, period);
24
+ }
25
+ return service.periodSummary(caller, period);
26
+ });
27
+ },
28
+ });
package/src/console.ts ADDED
@@ -0,0 +1,47 @@
1
+ import {
2
+ definePluginConsoleRpc,
3
+ PluginConsoleRpcError,
4
+ type PluginConsoleRpc,
5
+ type PluginConsoleRpcCall,
6
+ } from 'zhin.js';
7
+ import { ledgerServiceToken } from './runtime.js';
8
+ import type { LedgerService } from './service.js';
9
+
10
+ function resolveService(
11
+ provided: LedgerService | undefined,
12
+ call: PluginConsoleRpcCall,
13
+ ): LedgerService {
14
+ if (provided) return provided;
15
+ const runtimeWithUse = call.runtime as { use?: (token: typeof ledgerServiceToken) => LedgerService } | undefined;
16
+ const fromRuntime = runtimeWithUse?.use?.(ledgerServiceToken);
17
+ if (fromRuntime) return fromRuntime;
18
+ throw new PluginConsoleRpcError('unavailable', '记账服务尚未就绪');
19
+ }
20
+
21
+ export function createLedgerConsoleRpc(service?: LedgerService): PluginConsoleRpc {
22
+ const rpc = definePluginConsoleRpc({
23
+ status: {
24
+ page: 'index',
25
+ requiredPermissions: ['ledger:read'],
26
+ async handler(_input, call) {
27
+ return resolveService(service, call).getConsoleSnapshot();
28
+ },
29
+ },
30
+ actions: {
31
+ 'run-daily-reports': {
32
+ page: 'index',
33
+ requiredPermissions: ['ledger:write'],
34
+ async handler(_input, call) {
35
+ const sent = await resolveService(service, call).runDailyReports();
36
+ return { sent };
37
+ },
38
+ },
39
+ },
40
+ });
41
+ const methods = rpc.methods as Map<string, ReturnType<PluginConsoleRpc['methods']['get']>>;
42
+ const originalGet = methods.get.bind(methods);
43
+ const originalHas = methods.has.bind(methods);
44
+ methods.get = (key: string) => originalGet(key === 'runDailyReports' ? 'run-daily-reports' : key);
45
+ methods.has = (key: string) => originalHas(key === 'runDailyReports' ? 'run-daily-reports' : key);
46
+ return rpc;
47
+ }
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { ledgerConfig, resolveLedgerConfig, DEFAULT_REPORT_TIME, DEFAULT_TIMEZONE, type LedgerConfig, type ResolvedLedgerConfig } from './config.js';
2
+ export { createLedgerConsoleRpc } from './console.js';
2
3
  export { parseEntryInput, ADD_USAGE, MAX_CATEGORY_LENGTH, MAX_NOTE_LENGTH, type EntryInputResult, type ParsedEntryInput } from './entry-input.js';
3
4
  export { ledgerCaller, ledgerOwnerKey, replyLedger, LedgerInputError, type LedgerCaller } from './identity.js';
4
5
  export { formatCents, parseAmountToCents, MASKED_AMOUNT, MAX_ENTRY_CENTS, type AmountParseResult } from './money.js';
@@ -25,5 +26,12 @@ export {
25
26
  type PeriodSummary,
26
27
  } from './report-format.js';
27
28
  export { ledgerServiceToken } from './runtime.js';
28
- export { LedgerService, type DailyReportAction, type LedgerServiceOptions } from './service.js';
29
+ export {
30
+ LedgerService,
31
+ type DailyReportAction,
32
+ type LedgerConsoleSnapshot,
33
+ type LedgerConsoleSubscriber,
34
+ type LedgerServiceOptions,
35
+ } from './service.js';
29
36
  export { defineLedgerTables, LedgerStore, ENTRY_TABLE, USER_TABLE, PRIVATE_TARGET_TABLE, type LedgerEntry, type LedgerUserRecord } from './store.js';
37
+ export { ledgerCallerFromTool, type LedgerToolCallerContext } from './tool-caller.js';
package/src/service.ts CHANGED
@@ -19,6 +19,20 @@ const logger = getLogger('ledger');
19
19
 
20
20
  export type DailyReportAction = 'on' | 'off' | 'status';
21
21
 
22
+ export type LedgerConsoleSubscriber = {
23
+ readonly ownerKey: string;
24
+ readonly reportLocale: string;
25
+ readonly lastReportDate: string;
26
+ };
27
+
28
+ export type LedgerConsoleSnapshot = {
29
+ readonly timezone: string;
30
+ readonly reportTime: string;
31
+ readonly reportWhenEmpty: boolean;
32
+ readonly subscriberCount: number;
33
+ readonly subscribers: readonly LedgerConsoleSubscriber[];
34
+ };
35
+
22
36
  export interface LedgerServiceOptions {
23
37
  /** Wall clock; tests pass a fake. */
24
38
  readonly now?: () => number;
@@ -217,4 +231,19 @@ export class LedgerService {
217
231
  }
218
232
  return sent;
219
233
  }
234
+
235
+ async getConsoleSnapshot(): Promise<LedgerConsoleSnapshot> {
236
+ const subscribers = await this.#store.listReportSubscribers();
237
+ return {
238
+ timezone: this.#config.timezone,
239
+ reportTime: this.#config.reportTime,
240
+ reportWhenEmpty: this.#config.reportWhenEmpty,
241
+ subscriberCount: subscribers.length,
242
+ subscribers: subscribers.map((subscriber) => ({
243
+ ownerKey: subscriber.ownerKey,
244
+ reportLocale: resolveLocale(subscriber.reportLocale),
245
+ lastReportDate: subscriber.lastReportDate,
246
+ })),
247
+ };
248
+ }
220
249
  }
@@ -0,0 +1,101 @@
1
+ import { resolveLocale, type Locale } from 'zhin.js/i18n';
2
+ import { createDeliveryTarget, type DeliveryTarget } from 'zhin.js';
3
+ import { adapterFeatureId, type AdapterIndex } from 'zhin.js/adapter';
4
+ import { messages as t } from './i18n.js';
5
+ import { LedgerInputError, ledgerOwnerKey, type LedgerCaller } from './identity.js';
6
+
7
+ export type LedgerToolOrigin =
8
+ | Readonly<{
9
+ kind: 'im';
10
+ platform: string;
11
+ endpoint: string;
12
+ scope: 'private' | 'group' | 'channel';
13
+ sceneId: string;
14
+ messageId?: string;
15
+ threadId?: string;
16
+ conversation?: DeliveryTarget & Readonly<{ name?: string }>;
17
+ }>
18
+ | Readonly<{ kind: Exclude<string, 'im'>; [key: string]: unknown }>;
19
+
20
+ export interface LedgerToolCallerContext {
21
+ readonly origin: LedgerToolOrigin;
22
+ readonly locale?: Locale;
23
+ readonly senderId?: string;
24
+ readonly principal?: Readonly<{ subjectId: string; roles: readonly string[] }>;
25
+ project?<T>(feature: typeof adapterFeatureId): T;
26
+ }
27
+
28
+ function isImOrigin(
29
+ origin: LedgerToolOrigin,
30
+ ): origin is Extract<LedgerToolOrigin, { readonly kind: 'im' }> {
31
+ return origin.kind === 'im';
32
+ }
33
+
34
+ function resolveToolConversation(context: LedgerToolCallerContext, locale: Locale): DeliveryTarget {
35
+ const origin = context.origin;
36
+ if (!isImOrigin(origin)) {
37
+ throw new LedgerInputError(t(locale, 'actor'));
38
+ }
39
+ let endpointId = origin.conversation?.endpoint.id ?? origin.endpoint;
40
+ if (typeof context.project === 'function') {
41
+ try {
42
+ const index = context.project<AdapterIndex>(adapterFeatureId);
43
+ if (index && typeof index.describe === 'function') {
44
+ const matches = index
45
+ .describe()
46
+ .filter(
47
+ (endpoint) =>
48
+ (String(endpoint.id) === origin.endpoint || endpoint.name === origin.endpoint) &&
49
+ index.clientAdapter(endpoint.id) === origin.platform,
50
+ );
51
+ if (matches.length === 1) {
52
+ endpointId = String(matches[0]!.id);
53
+ }
54
+ }
55
+ } catch {
56
+ // Fall back to origin endpoint when AdapterIndex projection is unavailable in lightweight contexts.
57
+ }
58
+ }
59
+ if (!endpointId) {
60
+ throw new LedgerInputError(t(locale, 'actor'));
61
+ }
62
+ if (origin.conversation) {
63
+ return createDeliveryTarget({
64
+ conversation: {
65
+ ...origin.conversation,
66
+ endpoint: { id: endpointId, adapter: origin.platform },
67
+ },
68
+ });
69
+ }
70
+ return createDeliveryTarget({
71
+ conversation: {
72
+ endpoint: { id: endpointId, adapter: origin.platform },
73
+ kind: origin.scope,
74
+ id: origin.sceneId,
75
+ ...(origin.threadId !== undefined ? { threadId: origin.threadId } : {}),
76
+ },
77
+ });
78
+ }
79
+
80
+ /** Builds a LedgerCaller from an Agent Tool execution context. */
81
+ export function ledgerCallerFromTool(context: LedgerToolCallerContext): LedgerCaller {
82
+ const locale = resolveLocale(context.locale);
83
+ const senderId = (context.principal?.subjectId ?? context.senderId)?.trim();
84
+ if (!senderId) {
85
+ throw new LedgerInputError(t(locale, 'actor'));
86
+ }
87
+ const conversation = resolveToolConversation(context, locale);
88
+ const endpoint = conversation.endpoint;
89
+ const isPrivate = conversation.kind === 'private';
90
+ const privateTarget: DeliveryTarget = isPrivate
91
+ ? conversation
92
+ : Object.freeze({ endpoint, kind: 'private', id: senderId });
93
+ return {
94
+ ownerKey: ledgerOwnerKey(endpoint.adapter, endpoint.id, senderId),
95
+ senderId,
96
+ locale,
97
+ conversation,
98
+ privateTarget,
99
+ isPrivate,
100
+ };
101
+ }