dsh-bill-ilife 0.2.2 → 0.3.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/client.js CHANGED
@@ -51,7 +51,7 @@ window.__ModuleLoader__.load({
51
51
  }
52
52
  //#endregion
53
53
  //#region src/slot.ts
54
- const SLOT_TITLE = "记账";
54
+ const SLOT_TITLE = "饼干记账";
55
55
  const PLUGIN = "dsh-bill-ilife";
56
56
  //#endregion
57
57
  //#region src/settings.ts
@@ -61,7 +61,7 @@ window.__ModuleLoader__.load({
61
61
  key: "db.dir",
62
62
  title: "数据目录",
63
63
  tier: "common",
64
- control: "text",
64
+ control: "directory",
65
65
  hint: "库文件与备份的根目录。留空=按默认落点(配置目录下的 data/),也就是改造前那个位置。"
66
66
  },
67
67
  {
@@ -92,7 +92,7 @@ window.__ModuleLoader__.load({
92
92
  key: "backup.dir",
93
93
  title: "备份目录",
94
94
  tier: "advanced",
95
- control: "text",
95
+ control: "directory",
96
96
  hint: "备份与恢复读写的位置。留空=库目录下的 backups。恢复时按文件名取最新一份。"
97
97
  },
98
98
  {
@@ -147,6 +147,10 @@ window.__ModuleLoader__.load({
147
147
  cur[parts[parts.length - 1]] = value;
148
148
  }
149
149
  //#endregion
150
+ //#region src/dsh-ctx.ts
151
+ /** 宿主目录选择命名空间的服务名(#736;出处与禁令见 cookbook §13)。 */
152
+ const REMOTE_DIRECTORY_PICKER = "remote.directoryPicker";
153
+ //#endregion
150
154
  //#region src/client.ts
151
155
  /** dsh-bill-ilife client 适配器(六边形:port=contract,adapter=本文件)。
152
156
  *
@@ -163,6 +167,8 @@ window.__ModuleLoader__.load({
163
167
  * 宿主再 spawn 技能 CLI 的 `bill.config.*` 三个 key。本文件仍禁 node:不读盘、不算默认值。
164
168
  * 照 CONTEXT.md,「技能设置页」只配置、不干活:本页没有查账、记一笔之类的入口。
165
169
  */
170
+ /** client 短名声明:只有这两个(#736 的目录选择走**可选查找**,不写进来——
171
+ * 写进来=硬依赖,提供方缺席时整包被停靠,设置页会跟着装不上;见 cookbook §13)。 */
166
172
  const inject = ["slots", "connection"];
167
173
  /** 面板视觉(内联 style;颜色走 DSH 主题别名,深浅主题自适应,写死值只做回退)。 */
168
174
  const S = {
@@ -172,26 +178,25 @@ window.__ModuleLoader__.load({
172
178
  border: "1px solid var(--dsw-alias-border, rgba(128,128,128,.35))",
173
179
  background: "var(--dsw-alias-bg-base, transparent)",
174
180
  color: "var(--dsw-alias-label-primary, inherit)",
175
- fontSize: 13,
176
181
  lineHeight: 1.6
177
182
  },
178
183
  title: {
179
- fontSize: 14,
184
+ fontSize: "1.08em",
180
185
  fontWeight: 700,
181
186
  marginBottom: 8
182
187
  },
183
188
  muted: {
184
189
  color: "var(--dsw-alias-label-secondary, #9a9a9a)",
185
- fontSize: 12
190
+ fontSize: "0.92em"
186
191
  },
187
192
  error: {
188
193
  color: "var(--dsw-alias-state-error-primary, #ff6b6b)",
189
- fontSize: 13,
194
+ fontSize: "1em",
190
195
  whiteSpace: "pre-wrap"
191
196
  },
192
197
  okText: {
193
198
  color: "var(--dsw-alias-state-success-primary, #12805c)",
194
- fontSize: 12.5
199
+ fontSize: "0.96em"
195
200
  },
196
201
  rows: {
197
202
  marginTop: 8,
@@ -203,22 +208,19 @@ window.__ModuleLoader__.load({
203
208
  paddingTop: 8,
204
209
  borderTop: "1px dashed var(--dsw-alias-border, rgba(128,128,128,.25))",
205
210
  color: "var(--dsw-alias-label-tertiary, #8a8a8a)",
206
- fontSize: 12
211
+ fontSize: "0.92em"
207
212
  },
208
213
  info: {
214
+ fontSize: "0.92em",
209
215
  margin: "6px 0 0",
210
- font: "12px/1.5 ui-monospace,Consolas,monospace",
211
216
  color: "var(--dsw-alias-label-secondary, #9a9a9a)",
212
- wordBreak: "break-all"
217
+ overflowWrap: "anywhere"
213
218
  },
214
219
  row: { marginTop: 10 },
215
- label: {
216
- fontSize: 12.5,
217
- fontWeight: 600
218
- },
220
+ label: { fontWeight: 600 },
219
221
  hint: {
220
222
  color: "var(--dsw-alias-label-tertiary, #8a8a8a)",
221
- fontSize: 11.5,
223
+ fontSize: "0.92em",
222
224
  margin: "1px 0 4px"
223
225
  },
224
226
  input: {
@@ -228,8 +230,22 @@ window.__ModuleLoader__.load({
228
230
  borderRadius: 6,
229
231
  border: "1px solid var(--dsw-alias-border, rgba(128,128,128,.45))",
230
232
  background: "var(--dsw-alias-bg-base, transparent)",
233
+ color: "var(--dsw-alias-label-primary, inherit)"
234
+ },
235
+ pickRow: {
236
+ display: "flex",
237
+ gap: 6,
238
+ alignItems: "center"
239
+ },
240
+ btnPick: {
241
+ flex: "0 0 auto",
242
+ padding: "4px 10px",
243
+ borderRadius: 6,
244
+ border: "1px solid var(--dsw-alias-border, rgba(128,128,128,.45))",
245
+ background: "var(--dsw-alias-bg-base, transparent)",
231
246
  color: "var(--dsw-alias-label-primary, inherit)",
232
- font: "12.5px/1.5 ui-monospace,Consolas,monospace"
247
+ whiteSpace: "nowrap",
248
+ cursor: "pointer"
233
249
  },
234
250
  bar: {
235
251
  marginTop: 14,
@@ -244,7 +260,6 @@ window.__ModuleLoader__.load({
244
260
  border: "1px solid var(--dsw-alias-border, rgba(128,128,128,.45))",
245
261
  background: "var(--dsw-alias-bg-base, transparent)",
246
262
  color: "var(--dsw-alias-label-primary, inherit)",
247
- fontSize: 12.5,
248
263
  cursor: "pointer"
249
264
  },
250
265
  btnPrimary: {
@@ -253,7 +268,6 @@ window.__ModuleLoader__.load({
253
268
  border: "1px solid var(--dsw-alias-brand-primary, #2f6fed)",
254
269
  background: "var(--dsw-alias-brand-primary, #2f6fed)",
255
270
  color: "#fff",
256
- fontSize: 12.5,
257
271
  cursor: "pointer"
258
272
  },
259
273
  adv: {
@@ -263,7 +277,6 @@ window.__ModuleLoader__.load({
263
277
  },
264
278
  advSummary: {
265
279
  cursor: "pointer",
266
- fontSize: 12.5,
267
280
  fontWeight: 600
268
281
  }
269
282
  };
@@ -375,7 +388,55 @@ window.__ModuleLoader__.load({
375
388
  }
376
389
  return values;
377
390
  }
378
- /** 一行输入(三种控件对齐受限 YAML 子集:文本/数字/布尔)。 */
391
+ /** 形状守卫:拿到的那个东西像不像目录选择命名空间(本包只认 `pick` 是函数)。 */
392
+ function isDirectoryPicker(raw) {
393
+ if (typeof raw !== "object" || raw === null) return false;
394
+ return typeof raw.pick === "function";
395
+ }
396
+ /** 现取目录选择命名空间:**软依赖**,拿不到回 null(页面据此不出入口)。
397
+ *
398
+ * 为什么不用 `inject` 声明:见 cookbook §13——写进声明=硬依赖,提供方缺席时整包被停靠,
399
+ * 设置页会跟着装不上。这里按平台给的「可选查找」办:缺席只是没有入口。
400
+ * 守卫拒绝或提供方中途卸载会抛,一律当「没有」,绝不把设置页带下来。 */
401
+ function resolveDirectoryPicker(getService) {
402
+ if (typeof getService !== "function") return null;
403
+ try {
404
+ const raw = getService(REMOTE_DIRECTORY_PICKER);
405
+ return isDirectoryPicker(raw) ? raw : null;
406
+ } catch {
407
+ return null;
408
+ }
409
+ }
410
+ /** 唤起一次系统文件夹选择器并归一结果(**永不抛**)。 */
411
+ async function pickDirectory(picker) {
412
+ try {
413
+ const picked = await picker.pick();
414
+ if (typeof picked === "string" && picked.trim() !== "") return {
415
+ kind: "picked",
416
+ path: picked
417
+ };
418
+ return { kind: "cancelled" };
419
+ } catch (e) {
420
+ return {
421
+ kind: "unavailable",
422
+ message: "这台部署用不了系统文件夹对话框(" + (e instanceof Error ? e.message : String(e)) + "):请直接在框里填绝对路径。"
423
+ };
424
+ }
425
+ }
426
+ /** 「选择文件夹」按钮的真装配函数(目录行渲染出来的按钮,onClick 就是它)。
427
+ *
428
+ * 回 Promise 是为了本地可判(用例直接 await);接进 React 时调用方 `void` 掉。 */
429
+ function createBrowseHandler(deps) {
430
+ return async (key) => {
431
+ const outcome = await pickDirectory(deps.picker);
432
+ if (outcome.kind === "picked") deps.onChange(key, outcome.path);
433
+ else if (outcome.kind === "unavailable") deps.onUnavailable(outcome.message);
434
+ };
435
+ }
436
+ /** 一行输入(四种控件对齐受限 YAML 子集:文本/数字/布尔/目录)。
437
+ *
438
+ * 目录档=文本框 + 一枚唤起系统文件夹选择器的按钮;`onBrowse` 缺席(命名空间拿不到、
439
+ * 或这条路已被拒)时不画按钮,文本框照旧——那是该缝自己的契约(供不了就收起入口,不是失败)。 */
379
440
  function Row(props) {
380
441
  const { item } = props;
381
442
  const onChange = (e) => props.onChange(item.key, e.target.value);
@@ -392,13 +453,20 @@ window.__ModuleLoader__.load({
392
453
  spellCheck: false,
393
454
  onChange
394
455
  });
395
- return react.createElement("div", { style: S.row }, react.createElement("div", { style: S.label }, item.title), react.createElement("div", { style: S.hint }, item.hint), control);
456
+ const browse = item.control === "directory" && props.onBrowse !== void 0 ? react.createElement("button", {
457
+ style: S.btnPick,
458
+ type: "button",
459
+ disabled: props.disabled,
460
+ onClick: () => props.onBrowse?.(item.key)
461
+ }, "选择文件夹…") : null;
462
+ return react.createElement("div", { style: S.row }, react.createElement("div", { style: S.label }, item.title), react.createElement("div", { style: S.hint }, item.hint), browse === null ? control : react.createElement("div", { style: S.pickRow }, control, browse));
396
463
  }
397
464
  /** 技能设置页:承载饼干记账自己的全部可配置项(只配置,不干活)。
398
465
  *
399
466
  * 三态:loading(一次 RPC 内)/ready(真表单)/failed(人话报错 + 指引,不返空、不转圈)。 */
400
467
  function BillConfig(props) {
401
468
  const [state, setState] = react.useState({ kind: "loading" });
469
+ const [pickerGone, setPickerGone] = react.useState(false);
402
470
  const [draft, setDraft] = react.useState({});
403
471
  const [busy, setBusy] = react.useState(false);
404
472
  const [notice, setNotice] = react.useState(null);
@@ -443,6 +511,16 @@ window.__ModuleLoader__.load({
443
511
  setNotice(null);
444
512
  setError(null);
445
513
  }, []);
514
+ /** 目录选择:拿不到命名空间就没有入口;被拒一次即收起入口(不留死按钮)。 */
515
+ const picker = pickerGone ? null : props.getPicker();
516
+ const onBrowse = react.useMemo(() => picker === null ? void 0 : createBrowseHandler({
517
+ picker,
518
+ onChange,
519
+ onUnavailable: (message) => {
520
+ setError(message);
521
+ setPickerGone(true);
522
+ }
523
+ }), [picker, onChange]);
446
524
  const surface = state.kind === "ready" ? state.surface : null;
447
525
  const dirty = surface !== null && CONFIG_ITEMS.some((i) => (draft[i.key] ?? "") !== (toDraft(surface.values)[i.key] ?? ""));
448
526
  const onSave = react.useCallback(async () => {
@@ -489,7 +567,8 @@ window.__ModuleLoader__.load({
489
567
  item,
490
568
  value: draft[item.key] ?? "",
491
569
  disabled: busy,
492
- onChange
570
+ onChange,
571
+ onBrowse
493
572
  });
494
573
  return react.createElement("div", { style: S.card }, head, react.createElement("div", { style: S.rows }, common.map(renderRow)), react.createElement("details", { style: S.adv }, react.createElement("summary", { style: S.advSummary }, ADVANCED_GROUP_TITLE), react.createElement("div", { style: S.muted }, ADVANCED_GROUP_NOTE), advanced.map(renderRow)), react.createElement("div", { style: S.bar }, react.createElement("button", {
495
574
  style: dirty ? S.btnPrimary : S.btn,
@@ -510,21 +589,30 @@ window.__ModuleLoader__.load({
510
589
  }
511
590
  function apply(ctx) {
512
591
  const getCall = () => ctx.connection?.rpc?.call ?? null;
592
+ const getPicker = () => typeof ctx.get === "function" ? resolveDirectoryPicker((name) => ctx.get?.(name)) : null;
513
593
  ctx.slots.inject("ilife.config-tab", () => ctx.slots.register({
514
594
  name: "ilife.config-tab",
515
595
  id: PLUGIN,
516
596
  order: 95,
517
597
  label: () => SLOT_TITLE,
518
598
  channel: RPC_CHANNEL
519
- }, () => react.createElement(BillConfig, { getCall })));
599
+ }, () => react.createElement(BillConfig, {
600
+ getCall,
601
+ getPicker
602
+ })));
520
603
  }
521
604
  //#endregion
605
+ exports.Row = Row;
522
606
  exports.apply = apply;
607
+ exports.createBrowseHandler = createBrowseHandler;
523
608
  exports.fetchConfigSurface = fetchConfigSurface;
524
609
  exports.fromDraft = fromDraft;
525
610
  exports.humanizeConfigFailure = humanizeConfigFailure;
526
611
  exports.inject = inject;
612
+ exports.isDirectoryPicker = isDirectoryPicker;
613
+ exports.pickDirectory = pickDirectory;
527
614
  exports.resetConfigSurface = resetConfigSurface;
615
+ exports.resolveDirectoryPicker = resolveDirectoryPicker;
528
616
  exports.saveConfigSurface = saveConfigSurface;
529
617
  exports.toDraft = toDraft;
530
618
  return module.exports;
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["React"],"sources":["../src/contract.ts","../src/slot.ts","../src/settings.ts","../src/client.ts"],"sourcesContent":["/** dsh-bill-ilife 端口(port):DSH 世界与饼干记账 hexagon 之间的契约。\n *\n * browser 安全:零 node 导入。host 适配器(注册 RPC 通道)与 client\n * 适配器(调用 RPC)共用同一份定义;单测与 loader 回路以此为准。\n * 通道命名遵守宿主约束:单段且不等于 /api(见 cookbook「RPC 通道」)。\n *\n * 照 #56 卡路里样板同形(`packages/plugin-calorie/src/contract.ts`):记账插件原先\n * **没有任何 RPC 通道**,本件是它第一份端口定义(#677)。\n */\nexport const RPC_CHANNEL = '/ilife-bill-ilife' as const;\nexport const RPC_ENDPOINT_READ = 'read' as const;\n\n/** #677 配置端点:读设置页整面、保存一份取值、重置为默认。同走一条通道,靠端点名分发。 */\nexport const RPC_ENDPOINT_CONFIG_GET = 'config.get' as const;\nexport const RPC_ENDPOINT_CONFIG_SAVE = 'config.save' as const;\nexport const RPC_ENDPOINT_CONFIG_RESET = 'config.reset' as const;\n/** #706 配置体检端点:只读一次,回一份报告(判据由技能侧出,本包只透传,不重写一个字)。\n *\n * 端点名与技能侧那条只读命令同名(`<技能>.config.check`);报告形状的唯一真相在技能侧\n * `packages/skill-<技能>/src/health.ts`,面板侧镜像在 `packages/plugin-manager/src/health-contract.ts`。 */\nexport const RPC_ENDPOINT_CONFIG_CHECK = 'config.check' as const;\n\n/** 读请求载荷:与技能 CLI 的 key/params 同形(见 skill-bill SKILL.md)。 */\nexport interface ReadPayload {\n readonly key: string;\n readonly params: Record<string, unknown>;\n}\n\n/** 保存载荷:一份键值(键路径 → 值)。缺项由技能侧按默认值补齐,故只收用户真改的那些。 */\nexport interface SavePayload {\n readonly values: Record<string, unknown>;\n}\n\nexport interface RpcError {\n readonly code: string;\n readonly message: string;\n readonly details: Record<string, unknown>;\n}\n\nexport type RpcResult =\n | { readonly ok: true; readonly value: unknown }\n | { readonly ok: false; readonly error: RpcError };\n\nexport function ok(value: unknown): RpcResult {\n return { ok: true, value };\n}\n\nexport function fail(code: string, message: string): RpcResult {\n return { ok: false, error: { code, message, details: {} } };\n}\n\n/** 读载荷校验:形状不对返回 null,由调用方按 bad-request 回绝(不抛)。 */\nexport function parseReadPayload(raw: unknown): ReadPayload | null {\n if (typeof raw !== 'object' || raw === null) return null;\n const { key, params } = raw as { key?: unknown; params?: unknown };\n if (typeof key !== 'string' || key.length === 0) return null;\n if (typeof params !== 'object' || params === null || Array.isArray(params)) return null;\n return { key, params: params as Record<string, unknown> };\n}\n\n/** 保存载荷校验:形状不对返回 null,由调用方按 bad-request 回绝(不抛)。 */\nexport function parseSavePayload(raw: unknown): SavePayload | null {\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) return null;\n const { values } = raw as { values?: unknown };\n if (typeof values !== 'object' || values === null || Array.isArray(values)) return null;\n return { values: values as Record<string, unknown> };\n}\n\n/** 配置面回执:形状与技能侧 `bill.config.read` 的 data 逐字段同形(唯一定义地在那边的 cli/config.ts)。 */\nexport interface ConfigSurfaceReply {\n /** 配置文件绝对路径。 */\n readonly path: string;\n /** 数据目录绝对路径。 */\n readonly dataDir: string;\n /** 本次是不是「文件不存在、按默认值落了一份」。 */\n readonly created: boolean;\n /** 当前取值(文件里的 ⊕ 缺项按默认值补)。 */\n readonly values: Record<string, unknown>;\n}\n\n/** 信封守卫:供 client 拆包前校验(port 拥有信封定义,守卫住 port)。 */\nexport function isRpcResult(raw: unknown): raw is RpcResult {\n if (typeof raw !== 'object' || raw === null) return false;\n const okFlag = (raw as { ok?: unknown }).ok;\n return okFlag === true || okFlag === false;\n}\n","/** dsh-bill-ilife 槽位描述(P10 脚手架,P3 #4 定案)。\n *\n * 写死槽位原生组件:id 命名空间 ilife:cookie,order 95。\n * 注册与打开只走 registerTab/openTab 的路径导航;子页后缀(如 ilife:cookie:*)\n * 只在主面板内导航,不占栏。缺席纯条件渲染,不轮询(本文件无定时器;\n * 有界重试归一由 base-render 拥有,单品不自建)。\n */\n\nexport const SKILL = 'bill' as const;\nexport const SLOT_ID = 'ilife:cookie' as const;\nexport const SLOT_ORDER = 95 as const;\nexport const SLOT_TITLE = '记账' as const;\nexport const PLUGIN = 'dsh-bill-ilife' as const;\nexport const MANAGER_PLUGIN = 'dsh-life-pack' as const;\n\nexport interface SlotDescriptor {\n readonly skill: string;\n readonly slotId: string;\n readonly order: number;\n readonly title: string;\n readonly kind: 'page';\n}\n\nexport function slotDescriptor(): SlotDescriptor {\n return { skill: SKILL, slotId: SLOT_ID, order: SLOT_ORDER, title: SLOT_TITLE, kind: 'page' };\n}\n\n/** 写死原生组件描述(纯数据,无按需加载,无外嵌页)。 */\nexport const TAB_COMPONENT = { kind: 'native', name: 'BillPanel' } as const;\n\nexport interface TabsPort {\n hasTabs(): boolean;\n registerTab(entry: { readonly id: string; readonly title: string; readonly order: number; readonly single: boolean; readonly component: unknown }): () => void;\n openTab(seed: { readonly type: string; readonly path: string }, scope?: { readonly sessionId?: string }): void;\n}\n\n/** 自注册:幂等(调用方持 disposer),失败返回 false 由调用方决定重试。 */\nexport function registerSingle(port: TabsPort): (() => void) | null {\n if (!port.hasTabs()) return null;\n return port.registerTab({ id: SLOT_ID, title: SLOT_TITLE, order: SLOT_ORDER, single: true, component: TAB_COMPONENT });\n}\n\n/** 内容型打开:path seed,折叠面板自动展开。 */\nexport function openSingle(port: TabsPort, sessionId?: string): void {\n if (!port.hasTabs()) return;\n port.openTab({ type: SLOT_ID, path: SLOT_ID }, sessionId ? { sessionId } : undefined);\n}\n","/** dsh-bill-ilife 设置页元数据(#677:从只读脚手架换成真配置页)。\n *\n * 本文件是**设置页的行表**:一个可配置项一行,写清它在配置文件里的键、中文标题、\n * 分级(常用 / 高级)、控件种类与人话指引。它是页面渲染的唯一依据。\n *\n * **本文件必须零 node 依赖**:`tsconfig.client.json` 把它收进 client 侧编译,\n * 浏览器产物不许带 node 内建。取值一律由宿主经技能 CLI 的 `bill.config.read` 端点现取\n * (见 bridge.ts)。\n *\n * 口径:\n * · 配置表形状(键与默认值)的**唯一定义地**是技能侧 `packages/skill-bill/src/config.ts`\n * 的 `BILL_CONFIG_DEFAULTS`(本文件是它在页面上的投影,逐键对齐由\n * `test/config-surface-677.test.mjs` 用编译产物锁死);\n * · **空串=按默认落点**(老落点由技能各取用处算),所以「空」不是「没配」,\n * 而是「还走改造前那个位置」,老数据不会看起来丢了——行文案按这个语义写。\n *\n * 清单出处:「六家技能的路径类配置全量调查」记账 8 项去掉 1 项包内固定(包内页面模板目录)\n * =**上设置页候选 7 项**;其中「产物文件名主体」在源码里是两个值,故行数为 8。\n */\nexport const SETTINGS_OWNER = 'dsh-bill-ilife' as const;\nexport const SETTINGS_SLOT = 'ilife:cookie' as const;\n\n/** 配置文件主体名:落点 `~/.ilife/bill.yaml`(`ILIFE_CONFIG_DIR` 可整体接管)。 */\nexport const CONFIG_STEM = 'bill' as const;\n\n/** 分级:常用项直接画在页面上,其余进默认收起的「高级」组(#675 冻结口径)。 */\nexport type ConfigTier = 'common' | 'advanced';\n\n/** 控件种类:只有这三种(与受限 YAML 子集的字符串/数字/布尔一一对应,没有数组)。 */\nexport type ConfigControl = 'text' | 'number' | 'switch';\n\nexport interface ConfigItem {\n /** 配置文件里的键路径,一层嵌套用 `.` 连接,例 `html.helpStem`。 */\n readonly key: string;\n /** 页面上那一行的中文标题。 */\n readonly title: string;\n readonly tier: ConfigTier;\n readonly control: ConfigControl;\n /** 一行人话:这一项管什么、留空会怎样。 */\n readonly hint: string;\n}\n\n/** 常用项:改了就影响「库与产物落在哪」,放页面上。 */\nconst COMMON: readonly ConfigItem[] = [\n {\n key: 'db.dir',\n title: '数据目录',\n tier: 'common',\n control: 'text',\n hint: '库文件与备份的根目录。留空=按默认落点(配置目录下的 data/),也就是改造前那个位置。',\n },\n {\n key: 'db.name',\n title: '库文件名',\n tier: 'common',\n control: 'text',\n hint: '数据目录下的数据库文件名。改它等于换一个账本,老账留在旧文件里不会跟过来。',\n },\n {\n key: 'db.goals',\n title: '预算/账户文件名',\n tier: 'common',\n control: 'text',\n hint: '跟库同目录的那份预算与账户数据。改它之后旧的预算与账户不会被读出来。',\n },\n {\n key: 'html.dir',\n title: 'HELP 产物目录名',\n tier: 'common',\n control: 'text',\n hint: '数据目录下放 HELP 与速查表文件的子目录名。改它之后新产物落新地方,旧的留在原处。',\n },\n];\n\n/** 高级项:默认收起。改错了多半只是自己撞上麻烦,不确定就别动。 */\nconst ADVANCED: readonly ConfigItem[] = [\n {\n key: 'backup.dir',\n title: '备份目录',\n tier: 'advanced',\n control: 'text',\n hint: '备份与恢复读写的位置。留空=库目录下的 backups。恢复时按文件名取最新一份。',\n },\n {\n key: 'backup.stem',\n title: '备份名主体',\n tier: 'advanced',\n control: 'text',\n hint: '备份文件名的前缀,后面自动跟时间戳。改它之后旧的备份不再被当成恢复候选。',\n },\n {\n key: 'html.helpStem',\n title: '产物名主体 · HELP',\n tier: 'advanced',\n control: 'text',\n hint: 'HELP 文件的文件名前缀。改它之后旧的 HELP 产物不再被复用。',\n },\n {\n key: 'html.quickRefStem',\n title: '产物名主体 · 速查表',\n tier: 'advanced',\n control: 'text',\n hint: '速查表文件的文件名前缀。',\n },\n];\n\n/** 设置页的行表,顺序即页面顺序。 */\nexport const CONFIG_ITEMS: readonly ConfigItem[] = [...COMMON, ...ADVANCED];\n\n/** 常用项行数(页面上直接画出来的那些)。 */\nexport const COMMON_ITEM_COUNT = COMMON.length;\n\n/** 高级组标题与副文案。 */\nexport const ADVANCED_GROUP_TITLE = '高级' as const;\nexport const ADVANCED_GROUP_NOTE = '不常改。留空=按默认落点(改造前那个位置),不确定就别动。' as const;\n\n/** 按 `a.b` 路径从配置取值里读(缺层或类型不符一律回 undefined)。 */\nexport function readPath(values: Record<string, unknown>, key: string): unknown {\n const parts = key.split('.');\n let cur: unknown = values;\n for (const part of parts) {\n if (typeof cur !== 'object' || cur === null || Array.isArray(cur)) return undefined;\n cur = (cur as Record<string, unknown>)[part];\n }\n return cur;\n}\n\n/** 按 `a.b` 路径把值写进配置取值(中间层缺就建一层空组;已存在非组即覆盖成组)。 */\nexport function writePath(values: Record<string, unknown>, key: string, value: unknown): void {\n const parts = key.split('.');\n let cur: Record<string, unknown> = values;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!;\n const next = cur[part];\n if (typeof next !== 'object' || next === null || Array.isArray(next)) cur[part] = {};\n cur = cur[part] as Record<string, unknown>;\n }\n cur[parts[parts.length - 1]!] = value;\n}\n","/** dsh-bill-ilife client 适配器(六边形:port=contract,adapter=本文件)。\n *\n * 产物经 tsdown 打成 loader 工厂包(browser/CJS,见 tsdown.config.ts)。\n * 本文件传递闭包:禁 node、禁 DOM 直写(document/window/process)。\n * 注册一处:**技能设置页** → 爱生活页签槽(总管声明的 children,各技能自研自家配置页)。\n * 样式:React 内联 style + DSH 主题别名(var(--dsw-alias-*),带回退),无外部样式表、\n * 无 <style> 注入、无类名冲突;只用 dsh-ctx 镜像内成员(slots.inject/register、\n * connection.rpc.call 经闭包现取);取数只经 connection.rpc.call 进 host 通道;\n * 缺席/错误纯条件渲染,不返空冒充。组件 React.createElement 手写,不引入 JSX。\n *\n * #677:技能设置页从「只读设置行」换成**真配置页**——行表来自 settings.ts,\n * 取值与保存经宿主三个端点(`config.get`/`config.save`/`config.reset`),\n * 宿主再 spawn 技能 CLI 的 `bill.config.*` 三个 key。本文件仍禁 node:不读盘、不算默认值。\n * 照 CONTEXT.md,「技能设置页」只配置、不干活:本页没有查账、记一笔之类的入口。\n */\nimport * as React from 'react';\nimport { RPC_CHANNEL, RPC_ENDPOINT_CONFIG_GET, RPC_ENDPOINT_CONFIG_SAVE, RPC_ENDPOINT_CONFIG_RESET, isRpcResult } from './contract.js';\nimport type { ConfigSurfaceReply } from './contract.js';\nimport { PLUGIN, SLOT_ORDER, SLOT_TITLE } from './slot.js';\nimport { CONFIG_ITEMS, COMMON_ITEM_COUNT, ADVANCED_GROUP_TITLE, ADVANCED_GROUP_NOTE, readPath, writePath } from './settings.js';\nimport type { ConfigItem } from './settings.js';\nimport type { ClientCtx, RpcCallFace, RpcCallResult } from './dsh-ctx.js';\n\nexport const inject: readonly string[] = ['slots', 'connection'];\n\n/** 调用口取用器:每次取数时现取(connection 后到也不永久缺席)。 */\nexport type GetCall = () => unknown;\n\n/** 面板视觉(内联 style;颜色走 DSH 主题别名,深浅主题自适应,写死值只做回退)。 */\nconst S = {\n card: {\n padding: '12px 14px',\n borderRadius: 10,\n border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.35))',\n background: 'var(--dsw-alias-bg-base, transparent)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n fontSize: 13,\n lineHeight: 1.6,\n } as React.CSSProperties,\n title: { fontSize: 14, fontWeight: 700, marginBottom: 8 } as React.CSSProperties,\n muted: { color: 'var(--dsw-alias-label-secondary, #9a9a9a)', fontSize: 12 } as React.CSSProperties,\n error: { color: 'var(--dsw-alias-state-error-primary, #ff6b6b)', fontSize: 13, whiteSpace: 'pre-wrap' } as React.CSSProperties,\n okText: { color: 'var(--dsw-alias-state-success-primary, #12805c)', fontSize: 12.5 } as React.CSSProperties,\n rows: { marginTop: 8, borderTop: '1px solid var(--dsw-alias-border, rgba(128,128,128,.25))', paddingTop: 8 } as React.CSSProperties,\n version: {\n marginTop: 8,\n paddingTop: 8,\n borderTop: '1px dashed var(--dsw-alias-border, rgba(128,128,128,.25))',\n color: 'var(--dsw-alias-label-tertiary, #8a8a8a)',\n fontSize: 12,\n } as React.CSSProperties,\n info: {\n margin: '6px 0 0',\n font: '12px/1.5 ui-monospace,Consolas,monospace',\n color: 'var(--dsw-alias-label-secondary, #9a9a9a)',\n wordBreak: 'break-all',\n } as React.CSSProperties,\n row: { marginTop: 10 } as React.CSSProperties,\n label: { fontSize: 12.5, fontWeight: 600 } as React.CSSProperties,\n hint: { color: 'var(--dsw-alias-label-tertiary, #8a8a8a)', fontSize: 11.5, margin: '1px 0 4px' } as React.CSSProperties,\n input: {\n width: '100%',\n boxSizing: 'border-box',\n padding: '4px 8px',\n borderRadius: 6,\n border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.45))',\n background: 'var(--dsw-alias-bg-base, transparent)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n font: '12.5px/1.5 ui-monospace,Consolas,monospace',\n } as React.CSSProperties,\n bar: { marginTop: 14, display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' } as React.CSSProperties,\n btn: {\n padding: '5px 14px',\n borderRadius: 7,\n border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.45))',\n background: 'var(--dsw-alias-bg-base, transparent)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n fontSize: 12.5,\n cursor: 'pointer',\n } as React.CSSProperties,\n btnPrimary: {\n padding: '5px 14px',\n borderRadius: 7,\n border: '1px solid var(--dsw-alias-brand-primary, #2f6fed)',\n background: 'var(--dsw-alias-brand-primary, #2f6fed)',\n color: '#fff',\n fontSize: 12.5,\n cursor: 'pointer',\n } as React.CSSProperties,\n adv: {\n marginTop: 12,\n paddingTop: 8,\n borderTop: '1px solid var(--dsw-alias-border, rgba(128,128,128,.25))',\n } as React.CSSProperties,\n advSummary: { cursor: 'pointer', fontSize: 12.5, fontWeight: 600 } as React.CSSProperties,\n};\n\n/** 请求超时毫秒:与 host 侧 SPAWN_TIMEOUT_MS 同级,UI 永不无限转圈。 */\nconst READ_TIMEOUT_MS = 20_000 as const;\n\n/** 有界等待:借平台 `AbortSignal.timeout` 的 abort 事件做**一次**超时拒绝。\n *\n * 为什么不自建定时器:本包的冻结边界是「无数据轮询」(`test/plugin-p10-boundaries.test.mjs`:\n * 单品 src 里出现计时器就要有清理 + 次数上限 + 例外依据三件套),而设置页等的是一次 RPC 回执,\n * 不是轮询;用平台自带的一次性超时既守住边界的本意,也照样把「不转圈」落到实处。\n * 同一个 signal 也交给 transport,双保险:它搭理 signal 就早收工,不理也有这一道兜底。\n */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n const signal = AbortSignal.timeout(ms);\n const limit = new Promise<never>((_, reject) => {\n signal.addEventListener(\n 'abort',\n () => {\n const e = new Error(`配置超时(${Math.round(ms / 1000)}s):宿主未回,先查宿主日志`);\n e.name = 'TimeoutError';\n reject(e);\n },\n { once: true },\n );\n });\n return Promise.race([promise, limit]);\n}\n\ntype ConfigState =\n | { readonly kind: 'loading' }\n | { readonly kind: 'ready'; readonly surface: ConfigSurfaceReply }\n | { readonly kind: 'failed'; readonly message: string };\n\n/** 配置面报错 → 人话指引。\n *\n * 报文由技能侧给出(base-link-core 的 `ConfigError` 已带行号与文件名,技能 `cli/config.ts`\n * 原样交出,插件 bridge 原样带上),所以这里**不重写报文**,只按报错类补一句「接下来怎么办」。\n */\nexport function humanizeConfigFailure(code: string, message: string): string {\n const text = message.trim().length > 0 ? message.trim() : `(${code},宿主未给报文)`;\n if (/解析|YAML|parse/i.test(text)) return `${text}\\n改回「键: 值」的写法,或点「重置为默认」重来一份(重置会先留一份 .bak)。`;\n if (/不认识|未知键|UNKNOWN_KEY/i.test(text)) return `${text}\\n本页只认表里这些项;多余的行删掉,或点「重置为默认」。`;\n if (/类型|TYPE_MISMATCH/i.test(text)) return `${text}\\n按本页给的形状填(文本填文本、数字填数字),或点「重置为默认」。`;\n if (/缺席|missing-cli/.test(text)) return `${text}\\n技能出口没找着:先确认技能包已构建(packages/skill-bill/dist/cli/cmd_read.js)。`;\n return `${text}\\n改不动就点「重置为默认」(会先留一份 .bak),或照报文里的路径手工改配置文件。`;\n}\n\ntype ConfigOutcome =\n | { readonly ok: true; readonly surface: ConfigSurfaceReply }\n | { readonly ok: false; readonly message: string };\n\n/** 一次配置 RPC(永不抛,失败落字;UI 因此不转圈、不返空)。 */\nasync function configRpc(call: unknown, method: string, payload: Record<string, unknown>): Promise<ConfigOutcome> {\n if (typeof call !== 'function') return { ok: false, message: '宿主连接缺席:connection.rpc.call 不可用' };\n try {\n const raw: unknown = await withTimeout(\n (call as RpcCallFace)('/api', RPC_CHANNEL.slice(1), { method, payload }, AbortSignal.timeout(READ_TIMEOUT_MS)),\n READ_TIMEOUT_MS,\n );\n if (!isRpcResult(raw)) return { ok: false, message: '回执信封异常(非 ok 信封)' };\n const res = raw as RpcCallResult;\n if (!res.ok) return { ok: false, message: humanizeConfigFailure(res.error?.code ?? 'unknown', res.error?.message ?? '') };\n return { ok: true, surface: res.value as ConfigSurfaceReply };\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError') return { ok: false, message: `配置读取超时(${Math.round(READ_TIMEOUT_MS / 1000)}s):宿主未回` };\n if (e instanceof Error && e.name === 'TimeoutError') return { ok: false, message: e.message };\n return { ok: false, message: `配置失败:${e instanceof Error ? e.message : String(e)}` };\n }\n}\n\n/** 读设置页整面。 */\nexport function fetchConfigSurface(call: unknown): Promise<ConfigOutcome> {\n return configRpc(call, RPC_ENDPOINT_CONFIG_GET, {});\n}\n\n/** 保存(回全表;技能侧做组内合并)。 */\nexport function saveConfigSurface(call: unknown, values: Record<string, unknown>): Promise<ConfigOutcome> {\n return configRpc(call, RPC_ENDPOINT_CONFIG_SAVE, { values });\n}\n\n/** 重置为默认(技能侧先落 .bak;回执不含 values,故重置后重新读一次整面)。 */\nexport async function resetConfigSurface(call: unknown): Promise<ConfigOutcome> {\n const r = await configRpc(call, RPC_ENDPOINT_CONFIG_RESET, {});\n if (!r.ok) return r;\n return fetchConfigSurface(call);\n}\n\n/** 把配置取值铺成「行键 → 输入框文本」(页面表单态;值缺项即空串,不返空留白)。 */\nexport function toDraft(values: Record<string, unknown>): Record<string, string> {\n const draft: Record<string, string> = {};\n for (const item of CONFIG_ITEMS) {\n const v = readPath(values, item.key);\n draft[item.key] = v === undefined || v === null ? '' : String(v);\n }\n return draft;\n}\n\n/** 表单态 → 配置取值(按控件种类还原类型;空串对文本项照收,语义由「按默认落点」承担)。 */\nexport function fromDraft(draft: Record<string, string>): Record<string, unknown> {\n const values: Record<string, unknown> = {};\n for (const item of CONFIG_ITEMS) {\n const raw = draft[item.key] ?? '';\n if (item.control === 'number') {\n const n = Number(raw);\n writePath(values, item.key, Number.isFinite(n) ? n : 0);\n } else if (item.control === 'switch') {\n writePath(values, item.key, raw === 'true');\n } else {\n writePath(values, item.key, raw);\n }\n }\n return values;\n}\n\n/** 一行输入(三种控件对齐受限 YAML 子集:文本/数字/布尔)。 */\nfunction Row(props: {\n readonly item: ConfigItem;\n readonly value: string;\n readonly disabled: boolean;\n readonly onChange: (key: string, next: string) => void;\n}): React.ReactElement {\n const { item } = props;\n const onChange = (e: React.ChangeEvent<HTMLInputElement>) => props.onChange(item.key, e.target.value);\n const control =\n item.control === 'switch'\n ? React.createElement('input', {\n type: 'checkbox',\n checked: props.value === 'true',\n disabled: props.disabled,\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => props.onChange(item.key, e.target.checked ? 'true' : 'false'),\n })\n : React.createElement('input', {\n style: S.input,\n type: item.control === 'number' ? 'number' : 'text',\n value: props.value,\n disabled: props.disabled,\n spellCheck: false,\n onChange,\n });\n return React.createElement(\n 'div',\n { style: S.row },\n React.createElement('div', { style: S.label }, item.title),\n React.createElement('div', { style: S.hint }, item.hint),\n control,\n );\n}\n\n/** 技能设置页:承载饼干记账自己的全部可配置项(只配置,不干活)。\n *\n * 三态:loading(一次 RPC 内)/ready(真表单)/failed(人话报错 + 指引,不返空、不转圈)。 */\nfunction BillConfig(props: { getCall: GetCall }): React.ReactElement {\n const [state, setState] = React.useState<ConfigState>({ kind: 'loading' });\n const [draft, setDraft] = React.useState<Record<string, string>>({});\n const [busy, setBusy] = React.useState(false);\n const [notice, setNotice] = React.useState<string | null>(null);\n const [error, setError] = React.useState<string | null>(null);\n\n const apply = React.useCallback((surface: ConfigSurfaceReply) => {\n setState({ kind: 'ready', surface });\n setDraft(toDraft(surface.values));\n }, []);\n\n const load = React.useCallback(async () => {\n setNotice(null);\n setError(null);\n const r = await fetchConfigSurface(props.getCall());\n if (r.ok) apply(r.surface);\n else setState({ kind: 'failed', message: r.message });\n }, [apply, props.getCall]);\n\n React.useEffect(() => {\n let alive = true;\n void (async () => {\n const r = await fetchConfigSurface(props.getCall());\n if (!alive) return;\n if (r.ok) apply(r.surface);\n else setState({ kind: 'failed', message: r.message });\n })();\n return () => {\n alive = false;\n };\n }, [apply, props.getCall]);\n\n const onChange = React.useCallback((key: string, next: string) => {\n setDraft((prev) => ({ ...prev, [key]: next }));\n setNotice(null);\n setError(null);\n }, []);\n\n const surface = state.kind === 'ready' ? state.surface : null;\n const dirty = surface !== null && CONFIG_ITEMS.some((i) => (draft[i.key] ?? '') !== (toDraft(surface.values)[i.key] ?? ''));\n\n const onSave = React.useCallback(async () => {\n setBusy(true);\n setNotice(null);\n setError(null);\n const r = await saveConfigSurface(props.getCall(), fromDraft(draft));\n setBusy(false);\n if (r.ok) {\n apply(r.surface);\n setNotice('已保存,立即生效(不用重启宿主)');\n } else {\n setError(r.message);\n }\n }, [apply, draft, props.getCall]);\n\n const onReset = React.useCallback(async () => {\n setBusy(true);\n setNotice(null);\n setError(null);\n const r = await resetConfigSurface(props.getCall());\n setBusy(false);\n if (r.ok) {\n apply(r.surface);\n setNotice('已重置为默认(原配置已另存一份 .bak)');\n } else {\n setError(r.message);\n }\n }, [apply, props.getCall]);\n\n const head = React.createElement(\n 'div',\n null,\n React.createElement('div', { style: S.title }, `${SLOT_TITLE} · 配置`),\n surface !== null\n ? React.createElement(\n 'div',\n null,\n React.createElement('div', { style: S.info }, `配置文件 ${surface.path}`),\n React.createElement('div', { style: S.info }, `数据目录 ${surface.dataDir}`),\n surface.created ? React.createElement('div', { style: S.muted }, '(这份配置是刚按默认值建出来的)') : null,\n )\n : null,\n );\n\n if (state.kind === 'loading') {\n return React.createElement('div', { style: S.card }, head, React.createElement('div', { style: S.muted }, '配置读取中…'));\n }\n\n if (state.kind === 'failed') {\n return React.createElement(\n 'div',\n { style: S.card },\n React.createElement('div', { style: S.title }, `${SLOT_TITLE} · 配置`),\n React.createElement('div', { style: S.error }, state.message),\n React.createElement(\n 'div',\n { style: S.bar },\n React.createElement('button', { style: S.btn, type: 'button', onClick: () => void load() }, '重试'),\n React.createElement('button', { style: S.btn, type: 'button', onClick: () => void onReset() }, '重置为默认'),\n ),\n React.createElement('div', { style: S.version }, `${PLUGIN} 设置页住单品包;本页只配置,不干活`),\n );\n }\n\n const common = CONFIG_ITEMS.slice(0, COMMON_ITEM_COUNT);\n const advanced = CONFIG_ITEMS.slice(COMMON_ITEM_COUNT);\n const renderRow = (item: ConfigItem) =>\n React.createElement(Row, { key: item.key, item, value: draft[item.key] ?? '', disabled: busy, onChange });\n\n return React.createElement(\n 'div',\n { style: S.card },\n head,\n React.createElement('div', { style: S.rows }, common.map(renderRow)),\n React.createElement(\n 'details',\n { style: S.adv },\n React.createElement('summary', { style: S.advSummary }, ADVANCED_GROUP_TITLE),\n React.createElement('div', { style: S.muted }, ADVANCED_GROUP_NOTE),\n advanced.map(renderRow),\n ),\n React.createElement(\n 'div',\n { style: S.bar },\n React.createElement(\n 'button',\n { style: dirty ? S.btnPrimary : S.btn, type: 'button', disabled: busy || !dirty, onClick: () => void onSave() },\n busy ? '处理中…' : '保存',\n ),\n React.createElement('button', { style: S.btn, type: 'button', disabled: busy, onClick: () => void onReset() }, '重置为默认'),\n React.createElement('button', { style: S.btn, type: 'button', disabled: busy, onClick: () => void load() }, '重新读取'),\n ),\n notice !== null ? React.createElement('div', { style: S.okText }, notice) : null,\n error !== null ? React.createElement('div', { style: S.error }, error) : null,\n React.createElement('div', { style: S.version }, `${PLUGIN} 设置页住单品包;本页只配置,不干活`),\n );\n}\n\nexport function apply(ctx: ClientCtx): void {\n // 调用口取用器透传给组件(每次取数现取;非函数由组件判缺席)。\n const getCall: GetCall = () => ctx.connection?.rpc?.call ?? null;\n\n // 技能设置页 → 爱生活页签槽(总管声明;总管缺席时 inject 等待,不断链)。\n ctx.slots.inject('ilife.config-tab', () =>\n ctx.slots.register(\n {\n name: 'ilife.config-tab',\n id: PLUGIN,\n order: SLOT_ORDER,\n label: () => SLOT_TITLE,\n // #706:本包自己那条 RPC 通道交给总管(各家都写这一格),总管据此调配置体检——\n // 它因此不必在源码里写死任何一家的通道名(零单品依赖照旧成立)。\n channel: RPC_CHANNEL,\n },\n () => React.createElement(BillConfig, { getCall }),\n ),\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["React"],"sources":["../src/contract.ts","../src/slot.ts","../src/settings.ts","../src/dsh-ctx.ts","../src/client.ts"],"sourcesContent":["/** dsh-bill-ilife 端口(port):DSH 世界与饼干记账 hexagon 之间的契约。\n *\n * browser 安全:零 node 导入。host 适配器(注册 RPC 通道)与 client\n * 适配器(调用 RPC)共用同一份定义;单测与 loader 回路以此为准。\n * 通道命名遵守宿主约束:单段且不等于 /api(见 cookbook「RPC 通道」)。\n *\n * 照 #56 卡路里样板同形(`packages/plugin-calorie/src/contract.ts`):记账插件原先\n * **没有任何 RPC 通道**,本件是它第一份端口定义(#677)。\n */\nexport const RPC_CHANNEL = '/ilife-bill-ilife' as const;\nexport const RPC_ENDPOINT_READ = 'read' as const;\n\n/** #677 配置端点:读设置页整面、保存一份取值、重置为默认。同走一条通道,靠端点名分发。 */\nexport const RPC_ENDPOINT_CONFIG_GET = 'config.get' as const;\nexport const RPC_ENDPOINT_CONFIG_SAVE = 'config.save' as const;\nexport const RPC_ENDPOINT_CONFIG_RESET = 'config.reset' as const;\n/** #706 配置体检端点:只读一次,回一份报告(判据由技能侧出,本包只透传,不重写一个字)。\n *\n * 端点名与技能侧那条只读命令同名(`<技能>.config.check`);报告形状的唯一真相在技能侧\n * `packages/skill-<技能>/src/health.ts`,面板侧镜像在 `packages/plugin-manager/src/health-contract.ts`。 */\nexport const RPC_ENDPOINT_CONFIG_CHECK = 'config.check' as const;\n\n/** 读请求载荷:与技能 CLI 的 key/params 同形(见 skill-bill SKILL.md)。 */\nexport interface ReadPayload {\n readonly key: string;\n readonly params: Record<string, unknown>;\n}\n\n/** 保存载荷:一份键值(键路径 → 值)。缺项由技能侧按默认值补齐,故只收用户真改的那些。 */\nexport interface SavePayload {\n readonly values: Record<string, unknown>;\n}\n\nexport interface RpcError {\n readonly code: string;\n readonly message: string;\n readonly details: Record<string, unknown>;\n}\n\nexport type RpcResult =\n | { readonly ok: true; readonly value: unknown }\n | { readonly ok: false; readonly error: RpcError };\n\nexport function ok(value: unknown): RpcResult {\n return { ok: true, value };\n}\n\nexport function fail(code: string, message: string): RpcResult {\n return { ok: false, error: { code, message, details: {} } };\n}\n\n/** 读载荷校验:形状不对返回 null,由调用方按 bad-request 回绝(不抛)。 */\nexport function parseReadPayload(raw: unknown): ReadPayload | null {\n if (typeof raw !== 'object' || raw === null) return null;\n const { key, params } = raw as { key?: unknown; params?: unknown };\n if (typeof key !== 'string' || key.length === 0) return null;\n if (typeof params !== 'object' || params === null || Array.isArray(params)) return null;\n return { key, params: params as Record<string, unknown> };\n}\n\n/** 保存载荷校验:形状不对返回 null,由调用方按 bad-request 回绝(不抛)。 */\nexport function parseSavePayload(raw: unknown): SavePayload | null {\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) return null;\n const { values } = raw as { values?: unknown };\n if (typeof values !== 'object' || values === null || Array.isArray(values)) return null;\n return { values: values as Record<string, unknown> };\n}\n\n/** 配置面回执:形状与技能侧 `bill.config.read` 的 data 逐字段同形(唯一定义地在那边的 cli/config.ts)。 */\nexport interface ConfigSurfaceReply {\n /** 配置文件绝对路径。 */\n readonly path: string;\n /** 数据目录绝对路径。 */\n readonly dataDir: string;\n /** 本次是不是「文件不存在、按默认值落了一份」。 */\n readonly created: boolean;\n /** 当前取值(文件里的 ⊕ 缺项按默认值补)。 */\n readonly values: Record<string, unknown>;\n}\n\n/** 信封守卫:供 client 拆包前校验(port 拥有信封定义,守卫住 port)。 */\nexport function isRpcResult(raw: unknown): raw is RpcResult {\n if (typeof raw !== 'object' || raw === null) return false;\n const okFlag = (raw as { ok?: unknown }).ok;\n return okFlag === true || okFlag === false;\n}\n","/** dsh-bill-ilife 槽位描述(P10 脚手架,P3 #4 定案)。\n *\n * 写死槽位原生组件:id 命名空间 ilife:cookie,order 95。\n * 注册与打开只走 registerTab/openTab 的路径导航;子页后缀(如 ilife:cookie:*)\n * 只在主面板内导航,不占栏。缺席纯条件渲染,不轮询(本文件无定时器;\n * 有界重试归一由 base-render 拥有,单品不自建)。\n */\n\nexport const SKILL = 'bill' as const;\nexport const SLOT_ID = 'ilife:cookie' as const;\nexport const SLOT_ORDER = 95 as const;\nexport const SLOT_TITLE = '饼干记账' as const;\nexport const PLUGIN = 'dsh-bill-ilife' as const;\nexport const MANAGER_PLUGIN = 'dsh-life-pack' as const;\n\nexport interface SlotDescriptor {\n readonly skill: string;\n readonly slotId: string;\n readonly order: number;\n readonly title: string;\n readonly kind: 'page';\n}\n\nexport function slotDescriptor(): SlotDescriptor {\n return { skill: SKILL, slotId: SLOT_ID, order: SLOT_ORDER, title: SLOT_TITLE, kind: 'page' };\n}\n\n/** 写死原生组件描述(纯数据,无按需加载,无外嵌页)。 */\nexport const TAB_COMPONENT = { kind: 'native', name: 'BillPanel' } as const;\n\nexport interface TabsPort {\n hasTabs(): boolean;\n registerTab(entry: { readonly id: string; readonly title: string; readonly order: number; readonly single: boolean; readonly component: unknown }): () => void;\n openTab(seed: { readonly type: string; readonly path: string }, scope?: { readonly sessionId?: string }): void;\n}\n\n/** 自注册:幂等(调用方持 disposer),失败返回 false 由调用方决定重试。 */\nexport function registerSingle(port: TabsPort): (() => void) | null {\n if (!port.hasTabs()) return null;\n return port.registerTab({ id: SLOT_ID, title: SLOT_TITLE, order: SLOT_ORDER, single: true, component: TAB_COMPONENT });\n}\n\n/** 内容型打开:path seed,折叠面板自动展开。 */\nexport function openSingle(port: TabsPort, sessionId?: string): void {\n if (!port.hasTabs()) return;\n port.openTab({ type: SLOT_ID, path: SLOT_ID }, sessionId ? { sessionId } : undefined);\n}\n","/** dsh-bill-ilife 设置页元数据(#677:从只读脚手架换成真配置页)。\n *\n * 本文件是**设置页的行表**:一个可配置项一行,写清它在配置文件里的键、中文标题、\n * 分级(常用 / 高级)、控件种类与人话指引。它是页面渲染的唯一依据。\n *\n * **本文件必须零 node 依赖**:`tsconfig.client.json` 把它收进 client 侧编译,\n * 浏览器产物不许带 node 内建。取值一律由宿主经技能 CLI 的 `bill.config.read` 端点现取\n * (见 bridge.ts)。\n *\n * 口径:\n * · 配置表形状(键与默认值)的**唯一定义地**是技能侧 `packages/skill-bill/src/config.ts`\n * 的 `BILL_CONFIG_DEFAULTS`(本文件是它在页面上的投影,逐键对齐由\n * `test/config-surface-677.test.mjs` 用编译产物锁死);\n * · **空串=按默认落点**(老落点由技能各取用处算),所以「空」不是「没配」,\n * 而是「还走改造前那个位置」,老数据不会看起来丢了——行文案按这个语义写。\n *\n * 清单出处:「六家技能的路径类配置全量调查」记账 8 项去掉 1 项包内固定(包内页面模板目录)\n * =**上设置页候选 7 项**;其中「产物文件名主体」在源码里是两个值,故行数为 8。\n */\nexport const SETTINGS_OWNER = 'dsh-bill-ilife' as const;\nexport const SETTINGS_SLOT = 'ilife:cookie' as const;\n\n/** 配置文件主体名:落点 `~/.ilife/bill.yaml`(`ILIFE_CONFIG_DIR` 可整体接管)。 */\nexport const CONFIG_STEM = 'bill' as const;\n\n/** 分级:常用项直接画在页面上,其余进默认收起的「高级」组(#675 冻结口径)。 */\nexport type ConfigTier = 'common' | 'advanced';\n\n/** 控件种类:只有这四种(前三种与受限 YAML 子集的字符串/数字/布尔一一对应,没有数组;\n * `directory` 是**字符串那一档的页面形态**——取值仍是串,只是多一个唤起系统文件夹选择器的入口,见 #736)。 */\nexport type ConfigControl = 'text' | 'number' | 'switch' | 'directory';\n\nexport interface ConfigItem {\n /** 配置文件里的键路径,一层嵌套用 `.` 连接,例 `html.helpStem`。 */\n readonly key: string;\n /** 页面上那一行的中文标题。 */\n readonly title: string;\n readonly tier: ConfigTier;\n readonly control: ConfigControl;\n /** 一行人话:这一项管什么、留空会怎样。 */\n readonly hint: string;\n}\n\n/** 常用项:改了就影响「库与产物落在哪」,放页面上。 */\nconst COMMON: readonly ConfigItem[] = [\n {\n key: 'db.dir',\n title: '数据目录',\n tier: 'common',\n control: 'directory',\n hint: '库文件与备份的根目录。留空=按默认落点(配置目录下的 data/),也就是改造前那个位置。',\n },\n {\n key: 'db.name',\n title: '库文件名',\n tier: 'common',\n control: 'text',\n hint: '数据目录下的数据库文件名。改它等于换一个账本,老账留在旧文件里不会跟过来。',\n },\n {\n key: 'db.goals',\n title: '预算/账户文件名',\n tier: 'common',\n control: 'text',\n hint: '跟库同目录的那份预算与账户数据。改它之后旧的预算与账户不会被读出来。',\n },\n {\n key: 'html.dir',\n title: 'HELP 产物目录名',\n tier: 'common',\n control: 'text',\n hint: '数据目录下放 HELP 与速查表文件的子目录名。改它之后新产物落新地方,旧的留在原处。',\n },\n];\n\n/** 高级项:默认收起。改错了多半只是自己撞上麻烦,不确定就别动。 */\nconst ADVANCED: readonly ConfigItem[] = [\n {\n key: 'backup.dir',\n title: '备份目录',\n tier: 'advanced',\n control: 'directory',\n hint: '备份与恢复读写的位置。留空=库目录下的 backups。恢复时按文件名取最新一份。',\n },\n {\n key: 'backup.stem',\n title: '备份名主体',\n tier: 'advanced',\n control: 'text',\n hint: '备份文件名的前缀,后面自动跟时间戳。改它之后旧的备份不再被当成恢复候选。',\n },\n {\n key: 'html.helpStem',\n title: '产物名主体 · HELP',\n tier: 'advanced',\n control: 'text',\n hint: 'HELP 文件的文件名前缀。改它之后旧的 HELP 产物不再被复用。',\n },\n {\n key: 'html.quickRefStem',\n title: '产物名主体 · 速查表',\n tier: 'advanced',\n control: 'text',\n hint: '速查表文件的文件名前缀。',\n },\n];\n\n/** 设置页的行表,顺序即页面顺序。 */\nexport const CONFIG_ITEMS: readonly ConfigItem[] = [...COMMON, ...ADVANCED];\n\n/** 常用项行数(页面上直接画出来的那些)。 */\nexport const COMMON_ITEM_COUNT = COMMON.length;\n\n/** 高级组标题与副文案。 */\nexport const ADVANCED_GROUP_TITLE = '高级' as const;\nexport const ADVANCED_GROUP_NOTE = '不常改。留空=按默认落点(改造前那个位置),不确定就别动。' as const;\n\n/** 按 `a.b` 路径从配置取值里读(缺层或类型不符一律回 undefined)。 */\nexport function readPath(values: Record<string, unknown>, key: string): unknown {\n const parts = key.split('.');\n let cur: unknown = values;\n for (const part of parts) {\n if (typeof cur !== 'object' || cur === null || Array.isArray(cur)) return undefined;\n cur = (cur as Record<string, unknown>)[part];\n }\n return cur;\n}\n\n/** 按 `a.b` 路径把值写进配置取值(中间层缺就建一层空组;已存在非组即覆盖成组)。 */\nexport function writePath(values: Record<string, unknown>, key: string, value: unknown): void {\n const parts = key.split('.');\n let cur: Record<string, unknown> = values;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!;\n const next = cur[part];\n if (typeof next !== 'object' || next === null || Array.isArray(next)) cur[part] = {};\n cur = cur[part] as Record<string, unknown>;\n }\n cur[parts[parts.length - 1]!] = value;\n}\n","/** DSH ctx 最小镜像(只含本仓实际使用的面;**除末尾那枚服务名常量外全是 type-only**,\n * 构建期擦除——那枚常量是为 #736 的目录选择软依赖加的,是本文件唯一的运行期值)。\n *\n * skills 面出处见 `docs/agents/dsh-client-contract.md` §12(#56 卡路里样板,#150 记账同形):\n * `ctx.skills.registerProvider(create)`(`dsh-skill/lib/index.js:147`);\n * candidate 校验红线见 `validateCandidate`(同文件 `:452`);`get` 回定义须与候选同名(同文件 `:259`)。\n * slots 面出处见 cookbook §5(总管单卡方案):\n * `inject(key, cb)` 等声明同步跑否则等待(`dsh-client-ui-renderer/lib/client.js:1015`);\n * `register` list 必 `{id}`(`dsh-client-ui-slots/lib/index.js:72`);\n * 爱生活页签槽注册形见 cookbook §11(`{name:'ilife.config-tab', id, order, label}`)。\n * 禁止加镜外成员:要用新能力,先在 cookbook 落出处,再加镜像。用 `import type` 引用本文件。\n *\n * 本插件 host 侧用 skills 面,client 侧用 slots 面(最小静态注册,不取数,故无 connection)。\n */\n\n/** 爱生活页签槽注册项(cookbook §5 options 全形子集,只取本次用到的面)。 */\nexport interface SlotsRegisterOptions {\n readonly name: string;\n readonly id?: string;\n readonly order?: number;\n readonly label?: string | (() => string);\n readonly locale?: string;\n /** 本包自己那条 RPC 通道(单段):注册时交出去,总管据此**通用地**调配置体检(票 #706)。 */\n readonly channel?: string;\n readonly inject?: () => Record<string, unknown>;\n}\n\n/** 总管声明的爱生活页签槽面(client 侧只用 inject+register)。 */\nexport interface SlotsFace {\n inject(key: string, callback: () => (() => void) | Iterable<() => void>): () => void;\n register(options: SlotsRegisterOptions, component: unknown): () => void;\n}\n\n/** 记账 client 上下文(#677 起:从「只读 slots」扩到 connection——设置页要经宿主读改配置)。 */\nexport interface ClientCtx {\n readonly slots: SlotsFace;\n /** 宿主连接面:客户端经它把请求送进宿主注册的 /api 路由。缺席即由组件判「宿主连接缺席」。 */\n readonly connection?: ConnectionFace;\n /** 服务取用(本包暂不用,保留面以对齐兄弟件镜像)。 */\n get?(name: string): unknown;\n /** 卸载清理登记。 */\n effect?(fn: () => void, label?: string): void;\n}\n\n/** rpc.call 的调用口(每次取数时现取:connection 后到也不永久缺席)。 */\nexport type RpcCallFace = (\n path: string,\n channel: string,\n body: unknown,\n signal?: AbortSignal,\n) => Promise<unknown>;\n\n/** rpc.call 的回执形状(只列本包读的两处)。 */\nexport interface RpcCallResult {\n readonly ok: boolean;\n readonly value?: unknown;\n readonly error?: { readonly code?: string; readonly message?: string };\n}\n\n/** 宿主连接面(cookbook 的 connection 服务,本包只用 rpc.call)。 */\nexport interface ConnectionFace {\n readonly rpc?: { readonly call?: RpcCallFace };\n}\n\n/** 技能的调用策略(模型可调/用户可调)。 */\nexport interface SkillInvocationPolicy {\n readonly modelInvocable: boolean;\n readonly userInvocable: boolean;\n}\n\n/** 候选摘要(宿主 `list` 的返回项;`provider` 须等于注册名,否则宿主校验抛)。 */\nexport interface SkillCandidate {\n readonly name: string;\n readonly description: string;\n readonly invocation: SkillInvocationPolicy;\n readonly provider: string;\n readonly source: string;\n readonly rank: number;\n readonly locator: unknown;\n readonly resourceBase?: { readonly kind: 'directory'; readonly path: string };\n}\n\n/** 技能全文(宿主 `get` 的返回项;`content` 为 frontmatter 后正文)。 */\nexport interface SkillDefinition {\n readonly name: string;\n readonly description: string;\n readonly invocation: SkillInvocationPolicy;\n readonly provider: string;\n readonly source: string;\n readonly resourceBase?: { readonly kind: 'directory'; readonly path: string };\n readonly content: string;\n}\n\nexport interface SkillProvider {\n readonly name: string;\n list(options?: unknown): Promise<readonly SkillCandidate[]>;\n get(candidate: SkillCandidate, options?: unknown): Promise<SkillDefinition | undefined>;\n}\n\nexport interface SkillsFace {\n registerProvider(\n create: (control: { readonly signal: AbortSignal; invalidate(): void }) => SkillProvider,\n ): () => void;\n}\n\n/** RPC 处理函数:端点 + 载荷 → 信封回执(照 #56 卡路里样板同形)。 */\nexport type RpcHandler = (endpoint: string, payload: unknown) => Promise<unknown>;\n\n/** 宿主 fetch 路由注册面(`ctx.connection.fetch.register`)。 */\nexport interface HostConnectionFace {\n readonly fetch: { register(options: Record<string, unknown>): () => void };\n}\n\n/** 本插件用到的宿主面(apply 入参)。 */\nexport interface SkillHostCtx {\n readonly skills: SkillsFace;\n /** 模型工具注册表(#734):本包把技能唯一出口开成 agent 工具。 */\n readonly tools?: ToolsFace;\n /** 宿主连接面:设置页的三个配置端点注册在这上面(#677 起用)。 */\n readonly connection?: HostConnectionFace;\n /** 卸载清理登记。 */\n readonly effect?: (fn: () => void, label?: string) => void;\n readonly logger?: unknown;\n}\n\n/** 宿主目录选择命名空间的服务名(#736;出处与禁令见 cookbook §13)。 */\nexport const REMOTE_DIRECTORY_PICKER = 'remote.directoryPicker' as const;\n\n/** 宿主目录选择命名空间(DSH 平台提供)。本包**只用 `pick` 这一格**:\n * 不给 signal(平台那格可选),用户取消回 `null`。 */\nexport interface DirectoryPickerFace {\n pick(): Promise<string | null>;\n}\n\n/** 模型工具面镜像(#734;出处见 cookbook §14)。\n *\n * 出处:`@deepseek-ai/dsh-tools/lib/index.js` 的 `defineTool` 与 `ToolRuntime.register`——\n * 工具对象的形状是 `name`/`description`/`parameters`(JSON Schema)/`output{schema,render}`/\n * `execute`;`register` 只校验 `output.render` 是函数、`output.schema` 受支持、`timeoutMs` 为正、\n * 名字不是保留名 `run_code`,**不要求 `defineTool` 产物** ⇒ 本包按形状手写、零依赖。 */\nexport interface ToolTextPart {\n readonly type: 'text';\n readonly text: string;\n}\n\nexport interface ToolDefinitionMirror {\n readonly name: string;\n readonly description: string;\n readonly parameters: Record<string, unknown>;\n readonly output: {\n readonly schema: Record<string, unknown>;\n render(args: unknown, value: string): readonly ToolTextPart[];\n };\n execute(args: Record<string, unknown>, exec?: unknown): Promise<unknown>;\n}\n\nexport interface ToolsFace {\n register(definition: ToolDefinitionMirror): () => void;\n}\n","/** dsh-bill-ilife client 适配器(六边形:port=contract,adapter=本文件)。\n *\n * 产物经 tsdown 打成 loader 工厂包(browser/CJS,见 tsdown.config.ts)。\n * 本文件传递闭包:禁 node、禁 DOM 直写(document/window/process)。\n * 注册一处:**技能设置页** → 爱生活页签槽(总管声明的 children,各技能自研自家配置页)。\n * 样式:React 内联 style + DSH 主题别名(var(--dsw-alias-*),带回退),无外部样式表、\n * 无 <style> 注入、无类名冲突;只用 dsh-ctx 镜像内成员(slots.inject/register、\n * connection.rpc.call 经闭包现取);取数只经 connection.rpc.call 进 host 通道;\n * 缺席/错误纯条件渲染,不返空冒充。组件 React.createElement 手写,不引入 JSX。\n *\n * #677:技能设置页从「只读设置行」换成**真配置页**——行表来自 settings.ts,\n * 取值与保存经宿主三个端点(`config.get`/`config.save`/`config.reset`),\n * 宿主再 spawn 技能 CLI 的 `bill.config.*` 三个 key。本文件仍禁 node:不读盘、不算默认值。\n * 照 CONTEXT.md,「技能设置页」只配置、不干活:本页没有查账、记一笔之类的入口。\n */\nimport * as React from 'react';\nimport { RPC_CHANNEL, RPC_ENDPOINT_CONFIG_GET, RPC_ENDPOINT_CONFIG_SAVE, RPC_ENDPOINT_CONFIG_RESET, isRpcResult } from './contract.js';\nimport type { ConfigSurfaceReply } from './contract.js';\nimport { PLUGIN, SLOT_ORDER, SLOT_TITLE } from './slot.js';\nimport { CONFIG_ITEMS, COMMON_ITEM_COUNT, ADVANCED_GROUP_TITLE, ADVANCED_GROUP_NOTE, readPath, writePath } from './settings.js';\nimport type { ConfigItem } from './settings.js';\nimport { REMOTE_DIRECTORY_PICKER } from './dsh-ctx.js';\nimport type { ClientCtx, RpcCallFace, RpcCallResult, DirectoryPickerFace } from './dsh-ctx.js';\n\n/** client 短名声明:只有这两个(#736 的目录选择走**可选查找**,不写进来——\n * 写进来=硬依赖,提供方缺席时整包被停靠,设置页会跟着装不上;见 cookbook §13)。 */\nexport const inject: readonly string[] = ['slots', 'connection'];\n\n/** 调用口取用器:每次取数时现取(connection 后到也不永久缺席)。 */\nexport type GetCall = () => unknown;\n\n/** 面板视觉(内联 style;颜色走 DSH 主题别名,深浅主题自适应,写死值只做回退)。 */\nconst S = {\n card: {\n padding: '12px 14px',\n borderRadius: 10,\n border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.35))',\n background: 'var(--dsw-alias-bg-base, transparent)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n lineHeight: 1.6,\n } as React.CSSProperties,\n title: { fontSize: '1.08em', fontWeight: 700, marginBottom: 8 } as React.CSSProperties,\n muted: { color: 'var(--dsw-alias-label-secondary, #9a9a9a)', fontSize: '0.92em'} as React.CSSProperties,\n error: { color: 'var(--dsw-alias-state-error-primary, #ff6b6b)', fontSize: '1em', whiteSpace: 'pre-wrap' } as React.CSSProperties,\n okText: { color: 'var(--dsw-alias-state-success-primary, #12805c)', fontSize: '0.96em'} as React.CSSProperties,\n rows: { marginTop: 8, borderTop: '1px solid var(--dsw-alias-border, rgba(128,128,128,.25))', paddingTop: 8 } as React.CSSProperties,\n version: {\n marginTop: 8,\n paddingTop: 8,\n borderTop: '1px dashed var(--dsw-alias-border, rgba(128,128,128,.25))',\n color: 'var(--dsw-alias-label-tertiary, #8a8a8a)',\n fontSize: '0.92em',\n } as React.CSSProperties,\n info: {\n fontSize: '0.92em',\n margin: '6px 0 0',\n color: 'var(--dsw-alias-label-secondary, #9a9a9a)',\n overflowWrap: 'anywhere',\n } as React.CSSProperties,\n row: { marginTop: 10 } as React.CSSProperties,\n label: { fontWeight: 600 } as React.CSSProperties,\n hint: { color: 'var(--dsw-alias-label-tertiary, #8a8a8a)', fontSize: '0.92em', margin: '1px 0 4px' } as React.CSSProperties,\n input: {\n width: '100%',\n boxSizing: 'border-box',\n padding: '4px 8px',\n borderRadius: 6,\n border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.45))',\n background: 'var(--dsw-alias-bg-base, transparent)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n } as React.CSSProperties,\n pickRow: { display: 'flex', gap: 6, alignItems: 'center' } as React.CSSProperties,\n btnPick: {\n flex: '0 0 auto',\n padding: '4px 10px',\n borderRadius: 6,\n border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.45))',\n background: 'var(--dsw-alias-bg-base, transparent)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n whiteSpace: 'nowrap',\n cursor: 'pointer',\n } as React.CSSProperties,\n bar: { marginTop: 14, display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' } as React.CSSProperties,\n btn: {\n padding: '5px 14px',\n borderRadius: 7,\n border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.45))',\n background: 'var(--dsw-alias-bg-base, transparent)',\n color: 'var(--dsw-alias-label-primary, inherit)',\n cursor: 'pointer',\n } as React.CSSProperties,\n btnPrimary: {\n padding: '5px 14px',\n borderRadius: 7,\n border: '1px solid var(--dsw-alias-brand-primary, #2f6fed)',\n background: 'var(--dsw-alias-brand-primary, #2f6fed)',\n color: '#fff',\n cursor: 'pointer',\n } as React.CSSProperties,\n adv: {\n marginTop: 12,\n paddingTop: 8,\n borderTop: '1px solid var(--dsw-alias-border, rgba(128,128,128,.25))',\n } as React.CSSProperties,\n advSummary: { cursor: 'pointer', fontWeight: 600 } as React.CSSProperties,\n};\n\n/** 请求超时毫秒:与 host 侧 SPAWN_TIMEOUT_MS 同级,UI 永不无限转圈。 */\nconst READ_TIMEOUT_MS = 20_000 as const;\n\n/** 有界等待:借平台 `AbortSignal.timeout` 的 abort 事件做**一次**超时拒绝。\n *\n * 为什么不自建定时器:本包的冻结边界是「无数据轮询」(`test/plugin-p10-boundaries.test.mjs`:\n * 单品 src 里出现计时器就要有清理 + 次数上限 + 例外依据三件套),而设置页等的是一次 RPC 回执,\n * 不是轮询;用平台自带的一次性超时既守住边界的本意,也照样把「不转圈」落到实处。\n * 同一个 signal 也交给 transport,双保险:它搭理 signal 就早收工,不理也有这一道兜底。\n */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n const signal = AbortSignal.timeout(ms);\n const limit = new Promise<never>((_, reject) => {\n signal.addEventListener(\n 'abort',\n () => {\n const e = new Error(`配置超时(${Math.round(ms / 1000)}s):宿主未回,先查宿主日志`);\n e.name = 'TimeoutError';\n reject(e);\n },\n { once: true },\n );\n });\n return Promise.race([promise, limit]);\n}\n\ntype ConfigState =\n | { readonly kind: 'loading' }\n | { readonly kind: 'ready'; readonly surface: ConfigSurfaceReply }\n | { readonly kind: 'failed'; readonly message: string };\n\n/** 配置面报错 → 人话指引。\n *\n * 报文由技能侧给出(base-link-core 的 `ConfigError` 已带行号与文件名,技能 `cli/config.ts`\n * 原样交出,插件 bridge 原样带上),所以这里**不重写报文**,只按报错类补一句「接下来怎么办」。\n */\nexport function humanizeConfigFailure(code: string, message: string): string {\n const text = message.trim().length > 0 ? message.trim() : `(${code},宿主未给报文)`;\n if (/解析|YAML|parse/i.test(text)) return `${text}\\n改回「键: 值」的写法,或点「重置为默认」重来一份(重置会先留一份 .bak)。`;\n if (/不认识|未知键|UNKNOWN_KEY/i.test(text)) return `${text}\\n本页只认表里这些项;多余的行删掉,或点「重置为默认」。`;\n if (/类型|TYPE_MISMATCH/i.test(text)) return `${text}\\n按本页给的形状填(文本填文本、数字填数字),或点「重置为默认」。`;\n if (/缺席|missing-cli/.test(text)) return `${text}\\n技能出口没找着:先确认技能包已构建(packages/skill-bill/dist/cli/cmd_read.js)。`;\n return `${text}\\n改不动就点「重置为默认」(会先留一份 .bak),或照报文里的路径手工改配置文件。`;\n}\n\ntype ConfigOutcome =\n | { readonly ok: true; readonly surface: ConfigSurfaceReply }\n | { readonly ok: false; readonly message: string };\n\n/** 一次配置 RPC(永不抛,失败落字;UI 因此不转圈、不返空)。 */\nasync function configRpc(call: unknown, method: string, payload: Record<string, unknown>): Promise<ConfigOutcome> {\n if (typeof call !== 'function') return { ok: false, message: '宿主连接缺席:connection.rpc.call 不可用' };\n try {\n const raw: unknown = await withTimeout(\n (call as RpcCallFace)('/api', RPC_CHANNEL.slice(1), { method, payload }, AbortSignal.timeout(READ_TIMEOUT_MS)),\n READ_TIMEOUT_MS,\n );\n if (!isRpcResult(raw)) return { ok: false, message: '回执信封异常(非 ok 信封)' };\n const res = raw as RpcCallResult;\n if (!res.ok) return { ok: false, message: humanizeConfigFailure(res.error?.code ?? 'unknown', res.error?.message ?? '') };\n return { ok: true, surface: res.value as ConfigSurfaceReply };\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError') return { ok: false, message: `配置读取超时(${Math.round(READ_TIMEOUT_MS / 1000)}s):宿主未回` };\n if (e instanceof Error && e.name === 'TimeoutError') return { ok: false, message: e.message };\n return { ok: false, message: `配置失败:${e instanceof Error ? e.message : String(e)}` };\n }\n}\n\n/** 读设置页整面。 */\nexport function fetchConfigSurface(call: unknown): Promise<ConfigOutcome> {\n return configRpc(call, RPC_ENDPOINT_CONFIG_GET, {});\n}\n\n/** 保存(回全表;技能侧做组内合并)。 */\nexport function saveConfigSurface(call: unknown, values: Record<string, unknown>): Promise<ConfigOutcome> {\n return configRpc(call, RPC_ENDPOINT_CONFIG_SAVE, { values });\n}\n\n/** 重置为默认(技能侧先落 .bak;回执不含 values,故重置后重新读一次整面)。 */\nexport async function resetConfigSurface(call: unknown): Promise<ConfigOutcome> {\n const r = await configRpc(call, RPC_ENDPOINT_CONFIG_RESET, {});\n if (!r.ok) return r;\n return fetchConfigSurface(call);\n}\n\n/** 把配置取值铺成「行键 → 输入框文本」(页面表单态;值缺项即空串,不返空留白)。 */\nexport function toDraft(values: Record<string, unknown>): Record<string, string> {\n const draft: Record<string, string> = {};\n for (const item of CONFIG_ITEMS) {\n const v = readPath(values, item.key);\n draft[item.key] = v === undefined || v === null ? '' : String(v);\n }\n return draft;\n}\n\n/** 表单态 → 配置取值(按控件种类还原类型;空串对文本项照收,语义由「按默认落点」承担)。 */\nexport function fromDraft(draft: Record<string, string>): Record<string, unknown> {\n const values: Record<string, unknown> = {};\n for (const item of CONFIG_ITEMS) {\n const raw = draft[item.key] ?? '';\n if (item.control === 'number') {\n const n = Number(raw);\n writePath(values, item.key, Number.isFinite(n) ? n : 0);\n } else if (item.control === 'switch') {\n writePath(values, item.key, raw === 'true');\n } else {\n writePath(values, item.key, raw);\n }\n }\n return values;\n}\n\n/** 目录选择的三种结果(注入 picker 的纯归一:选中/取消/这条路供不了)。 */\nexport type PickOutcome =\n | { readonly kind: 'picked'; readonly path: string }\n | { readonly kind: 'cancelled' }\n | { readonly kind: 'unavailable'; readonly message: string };\n\n/** 形状守卫:拿到的那个东西像不像目录选择命名空间(本包只认 `pick` 是函数)。 */\nexport function isDirectoryPicker(raw: unknown): raw is DirectoryPickerFace {\n if (typeof raw !== 'object' || raw === null) return false;\n return typeof (raw as { pick?: unknown }).pick === 'function';\n}\n\n/** 现取目录选择命名空间:**软依赖**,拿不到回 null(页面据此不出入口)。\n *\n * 为什么不用 `inject` 声明:见 cookbook §13——写进声明=硬依赖,提供方缺席时整包被停靠,\n * 设置页会跟着装不上。这里按平台给的「可选查找」办:缺席只是没有入口。\n * 守卫拒绝或提供方中途卸载会抛,一律当「没有」,绝不把设置页带下来。 */\nexport function resolveDirectoryPicker(getService: unknown): DirectoryPickerFace | null {\n if (typeof getService !== 'function') return null;\n try {\n const raw = (getService as (name: string) => unknown)(REMOTE_DIRECTORY_PICKER);\n return isDirectoryPicker(raw) ? raw : null;\n } catch {\n return null;\n }\n}\n\n/** 唤起一次系统文件夹选择器并归一结果(**永不抛**)。 */\nexport async function pickDirectory(picker: DirectoryPickerFace): Promise<PickOutcome> {\n try {\n const picked = await picker.pick();\n if (typeof picked === 'string' && picked.trim() !== '') return { kind: 'picked', path: picked };\n return { kind: 'cancelled' };\n } catch (e) {\n const reason = e instanceof Error ? e.message : String(e);\n return { kind: 'unavailable', message: '这台部署用不了系统文件夹对话框(' + reason + '):请直接在框里填绝对路径。' };\n }\n}\n\n/** 「选择文件夹」按钮的真装配函数(目录行渲染出来的按钮,onClick 就是它)。\n *\n * 回 Promise 是为了本地可判(用例直接 await);接进 React 时调用方 `void` 掉。 */\nexport function createBrowseHandler(deps: {\n readonly picker: DirectoryPickerFace;\n readonly onChange: (key: string, next: string) => void;\n readonly onUnavailable: (message: string) => void;\n}): (key: string) => Promise<void> {\n return async (key: string) => {\n const outcome = await pickDirectory(deps.picker);\n if (outcome.kind === 'picked') deps.onChange(key, outcome.path);\n else if (outcome.kind === 'unavailable') deps.onUnavailable(outcome.message);\n };\n}\n\n/** 一行输入(四种控件对齐受限 YAML 子集:文本/数字/布尔/目录)。\n *\n * 目录档=文本框 + 一枚唤起系统文件夹选择器的按钮;`onBrowse` 缺席(命名空间拿不到、\n * 或这条路已被拒)时不画按钮,文本框照旧——那是该缝自己的契约(供不了就收起入口,不是失败)。 */\nexport function Row(props: {\n readonly item: ConfigItem;\n readonly value: string;\n readonly disabled: boolean;\n readonly onChange: (key: string, next: string) => void;\n /** 目录行才有:唤起系统文件夹选择器。 */\n readonly onBrowse?: ((key: string) => void) | undefined;\n}): React.ReactElement {\n const { item } = props;\n const onChange = (e: React.ChangeEvent<HTMLInputElement>) => props.onChange(item.key, e.target.value);\n const control =\n item.control === 'switch'\n ? React.createElement('input', {\n type: 'checkbox',\n checked: props.value === 'true',\n disabled: props.disabled,\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => props.onChange(item.key, e.target.checked ? 'true' : 'false'),\n })\n : React.createElement('input', {\n style: S.input,\n type: item.control === 'number' ? 'number' : 'text',\n value: props.value,\n disabled: props.disabled,\n spellCheck: false,\n onChange,\n });\n const browse =\n item.control === 'directory' && props.onBrowse !== undefined\n ? React.createElement(\n 'button',\n {\n style: S.btnPick,\n type: 'button',\n disabled: props.disabled,\n // 回这枚 Promise 是有意的:React 不看 onClick 的返回值,而用例能直接 await 它,\n // 拿到「唤一次 pick → 回填这一行」的确定性读数(本地可判)。\n onClick: () => props.onBrowse?.(item.key),\n },\n '选择文件夹…',\n )\n : null;\n return React.createElement(\n 'div',\n { style: S.row },\n React.createElement('div', { style: S.label }, item.title),\n React.createElement('div', { style: S.hint }, item.hint),\n browse === null ? control : React.createElement('div', { style: S.pickRow }, control, browse),\n );\n}\n\n/** 技能设置页:承载饼干记账自己的全部可配置项(只配置,不干活)。\n *\n * 三态:loading(一次 RPC 内)/ready(真表单)/failed(人话报错 + 指引,不返空、不转圈)。 */\nfunction BillConfig(props: { getCall: GetCall; getPicker: () => DirectoryPickerFace | null }): React.ReactElement {\n const [state, setState] = React.useState<ConfigState>({ kind: 'loading' });\n const [pickerGone, setPickerGone] = React.useState(false);\n const [draft, setDraft] = React.useState<Record<string, string>>({});\n const [busy, setBusy] = React.useState(false);\n const [notice, setNotice] = React.useState<string | null>(null);\n const [error, setError] = React.useState<string | null>(null);\n\n const apply = React.useCallback((surface: ConfigSurfaceReply) => {\n setState({ kind: 'ready', surface });\n setDraft(toDraft(surface.values));\n }, []);\n\n const load = React.useCallback(async () => {\n setNotice(null);\n setError(null);\n const r = await fetchConfigSurface(props.getCall());\n if (r.ok) apply(r.surface);\n else setState({ kind: 'failed', message: r.message });\n }, [apply, props.getCall]);\n\n React.useEffect(() => {\n let alive = true;\n void (async () => {\n const r = await fetchConfigSurface(props.getCall());\n if (!alive) return;\n if (r.ok) apply(r.surface);\n else setState({ kind: 'failed', message: r.message });\n })();\n return () => {\n alive = false;\n };\n }, [apply, props.getCall]);\n\n const onChange = React.useCallback((key: string, next: string) => {\n setDraft((prev) => ({ ...prev, [key]: next }));\n setNotice(null);\n setError(null);\n }, []);\n\n /** 目录选择:拿不到命名空间就没有入口;被拒一次即收起入口(不留死按钮)。 */\n const picker = pickerGone ? null : props.getPicker();\n const onBrowse = React.useMemo(\n () =>\n picker === null\n ? undefined\n : createBrowseHandler({\n picker,\n onChange,\n onUnavailable: (message: string) => {\n setError(message);\n setPickerGone(true);\n },\n }),\n [picker, onChange],\n );\n\n const surface = state.kind === 'ready' ? state.surface : null;\n const dirty = surface !== null && CONFIG_ITEMS.some((i) => (draft[i.key] ?? '') !== (toDraft(surface.values)[i.key] ?? ''));\n\n const onSave = React.useCallback(async () => {\n setBusy(true);\n setNotice(null);\n setError(null);\n const r = await saveConfigSurface(props.getCall(), fromDraft(draft));\n setBusy(false);\n if (r.ok) {\n apply(r.surface);\n setNotice('已保存,立即生效(不用重启宿主)');\n } else {\n setError(r.message);\n }\n }, [apply, draft, props.getCall]);\n\n const onReset = React.useCallback(async () => {\n setBusy(true);\n setNotice(null);\n setError(null);\n const r = await resetConfigSurface(props.getCall());\n setBusy(false);\n if (r.ok) {\n apply(r.surface);\n setNotice('已重置为默认(原配置已另存一份 .bak)');\n } else {\n setError(r.message);\n }\n }, [apply, props.getCall]);\n\n const head = React.createElement(\n 'div',\n null,\n React.createElement('div', { style: S.title }, `${SLOT_TITLE} · 配置`),\n surface !== null\n ? React.createElement(\n 'div',\n null,\n React.createElement('div', { style: S.info }, `配置文件 ${surface.path}`),\n React.createElement('div', { style: S.info }, `数据目录 ${surface.dataDir}`),\n surface.created ? React.createElement('div', { style: S.muted }, '(这份配置是刚按默认值建出来的)') : null,\n )\n : null,\n );\n\n if (state.kind === 'loading') {\n return React.createElement('div', { style: S.card }, head, React.createElement('div', { style: S.muted }, '配置读取中…'));\n }\n\n if (state.kind === 'failed') {\n return React.createElement(\n 'div',\n { style: S.card },\n React.createElement('div', { style: S.title }, `${SLOT_TITLE} · 配置`),\n React.createElement('div', { style: S.error }, state.message),\n React.createElement(\n 'div',\n { style: S.bar },\n React.createElement('button', { style: S.btn, type: 'button', onClick: () => void load() }, '重试'),\n React.createElement('button', { style: S.btn, type: 'button', onClick: () => void onReset() }, '重置为默认'),\n ),\n React.createElement('div', { style: S.version }, `${PLUGIN} 设置页住单品包;本页只配置,不干活`),\n );\n }\n\n const common = CONFIG_ITEMS.slice(0, COMMON_ITEM_COUNT);\n const advanced = CONFIG_ITEMS.slice(COMMON_ITEM_COUNT);\n const renderRow = (item: ConfigItem) =>\n React.createElement(Row, { key: item.key, item, value: draft[item.key] ?? '', disabled: busy, onChange, onBrowse });\n\n return React.createElement(\n 'div',\n { style: S.card },\n head,\n React.createElement('div', { style: S.rows }, common.map(renderRow)),\n React.createElement(\n 'details',\n { style: S.adv },\n React.createElement('summary', { style: S.advSummary }, ADVANCED_GROUP_TITLE),\n React.createElement('div', { style: S.muted }, ADVANCED_GROUP_NOTE),\n advanced.map(renderRow),\n ),\n React.createElement(\n 'div',\n { style: S.bar },\n React.createElement(\n 'button',\n { style: dirty ? S.btnPrimary : S.btn, type: 'button', disabled: busy || !dirty, onClick: () => void onSave() },\n busy ? '处理中…' : '保存',\n ),\n React.createElement('button', { style: S.btn, type: 'button', disabled: busy, onClick: () => void onReset() }, '重置为默认'),\n React.createElement('button', { style: S.btn, type: 'button', disabled: busy, onClick: () => void load() }, '重新读取'),\n ),\n notice !== null ? React.createElement('div', { style: S.okText }, notice) : null,\n error !== null ? React.createElement('div', { style: S.error }, error) : null,\n React.createElement('div', { style: S.version }, `${PLUGIN} 设置页住单品包;本页只配置,不干活`),\n );\n}\n\nexport function apply(ctx: ClientCtx): void {\n // 调用口取用器透传给组件(每次取数现取;非函数由组件判缺席)。\n const getCall: GetCall = () => ctx.connection?.rpc?.call ?? null;\n // #736 目录选择:**软依赖**,每次渲染现取(提供方后到/中途卸载都不留痕);\n // 拿不到就只是没有入口,设置页照常(不声明、不停靠,见 cookbook §13)。\n const getPicker = (): DirectoryPickerFace | null =>\n typeof ctx.get === 'function' ? resolveDirectoryPicker((name: string) => ctx.get?.(name)) : null;\n\n // 技能设置页 → 爱生活页签槽(总管声明;总管缺席时 inject 等待,不断链)。\n ctx.slots.inject('ilife.config-tab', () =>\n ctx.slots.register(\n {\n name: 'ilife.config-tab',\n id: PLUGIN,\n order: SLOT_ORDER,\n label: () => SLOT_TITLE,\n // #706:本包自己那条 RPC 通道交给总管(各家都写这一格),总管据此调配置体检——\n // 它因此不必在源码里写死任何一家的通道名(零单品依赖照旧成立)。\n channel: RPC_CHANNEL,\n },\n () => React.createElement(BillConfig, { getCall, getPicker }),\n ),\n );\n}\n"],"mappings":"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"}
package/dist/dsh-ctx.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- /** DSH ctx 最小镜像(只含本仓实际使用的面;type-only,构建期擦除,零运行时)。
1
+ /** DSH ctx 最小镜像(只含本仓实际使用的面;**除末尾那枚服务名常量外全是 type-only**,
2
+ * 构建期擦除——那枚常量是为 #736 的目录选择软依赖加的,是本文件唯一的运行期值)。
2
3
  *
3
4
  * skills 面出处见 `docs/agents/dsh-client-contract.md` §12(#56 卡路里样板,#150 记账同形):
4
5
  * `ctx.skills.registerProvider(create)`(`dsh-skill/lib/index.js:147`);
@@ -108,10 +109,42 @@ export interface HostConnectionFace {
108
109
  /** 本插件用到的宿主面(apply 入参)。 */
109
110
  export interface SkillHostCtx {
110
111
  readonly skills: SkillsFace;
112
+ /** 模型工具注册表(#734):本包把技能唯一出口开成 agent 工具。 */
113
+ readonly tools?: ToolsFace;
111
114
  /** 宿主连接面:设置页的三个配置端点注册在这上面(#677 起用)。 */
112
115
  readonly connection?: HostConnectionFace;
113
116
  /** 卸载清理登记。 */
114
117
  readonly effect?: (fn: () => void, label?: string) => void;
115
118
  readonly logger?: unknown;
116
119
  }
120
+ /** 宿主目录选择命名空间的服务名(#736;出处与禁令见 cookbook §13)。 */
121
+ export declare const REMOTE_DIRECTORY_PICKER: "remote.directoryPicker";
122
+ /** 宿主目录选择命名空间(DSH 平台提供)。本包**只用 `pick` 这一格**:
123
+ * 不给 signal(平台那格可选),用户取消回 `null`。 */
124
+ export interface DirectoryPickerFace {
125
+ pick(): Promise<string | null>;
126
+ }
127
+ /** 模型工具面镜像(#734;出处见 cookbook §14)。
128
+ *
129
+ * 出处:`@deepseek-ai/dsh-tools/lib/index.js` 的 `defineTool` 与 `ToolRuntime.register`——
130
+ * 工具对象的形状是 `name`/`description`/`parameters`(JSON Schema)/`output{schema,render}`/
131
+ * `execute`;`register` 只校验 `output.render` 是函数、`output.schema` 受支持、`timeoutMs` 为正、
132
+ * 名字不是保留名 `run_code`,**不要求 `defineTool` 产物** ⇒ 本包按形状手写、零依赖。 */
133
+ export interface ToolTextPart {
134
+ readonly type: 'text';
135
+ readonly text: string;
136
+ }
137
+ export interface ToolDefinitionMirror {
138
+ readonly name: string;
139
+ readonly description: string;
140
+ readonly parameters: Record<string, unknown>;
141
+ readonly output: {
142
+ readonly schema: Record<string, unknown>;
143
+ render(args: unknown, value: string): readonly ToolTextPart[];
144
+ };
145
+ execute(args: Record<string, unknown>, exec?: unknown): Promise<unknown>;
146
+ }
147
+ export interface ToolsFace {
148
+ register(definition: ToolDefinitionMirror): () => void;
149
+ }
117
150
  //# sourceMappingURL=dsh-ctx.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dsh-ctx.d.ts","sourceRoot":"","sources":["../src/dsh-ctx.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dsh-ctx.d.ts","sourceRoot":"","sources":["../src/dsh-ctx.ts"],"names":[],"mappings":"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"}
package/dist/dsh-ctx.js CHANGED
@@ -1,4 +1,5 @@
1
- /** DSH ctx 最小镜像(只含本仓实际使用的面;type-only,构建期擦除,零运行时)。
1
+ /** DSH ctx 最小镜像(只含本仓实际使用的面;**除末尾那枚服务名常量外全是 type-only**,
2
+ * 构建期擦除——那枚常量是为 #736 的目录选择软依赖加的,是本文件唯一的运行期值)。
2
3
  *
3
4
  * skills 面出处见 `docs/agents/dsh-client-contract.md` §12(#56 卡路里样板,#150 记账同形):
4
5
  * `ctx.skills.registerProvider(create)`(`dsh-skill/lib/index.js:147`);
@@ -11,5 +12,6 @@
11
12
  *
12
13
  * 本插件 host 侧用 skills 面,client 侧用 slots 面(最小静态注册,不取数,故无 connection)。
13
14
  */
14
- export {};
15
+ /** 宿主目录选择命名空间的服务名(#736;出处与禁令见 cookbook §13)。 */
16
+ export const REMOTE_DIRECTORY_PICKER = 'remote.directoryPicker';
15
17
  //# sourceMappingURL=dsh-ctx.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dsh-ctx.js","sourceRoot":"","sources":["../src/dsh-ctx.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
1
+ {"version":3,"file":"dsh-ctx.js","sourceRoot":"","sources":["../src/dsh-ctx.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAgHH,gDAAgD;AAChD,MAAM,CAAC,MAAM,uBAAuB,GAAG,wBAAiC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -11,4 +11,5 @@ export { RPC_CHANNEL, RPC_ENDPOINT_READ, RPC_ENDPOINT_CONFIG_GET, RPC_ENDPOINT_C
11
11
  export type { ReadPayload, SavePayload, ConfigSurfaceReply, RpcError, RpcResult } from './contract.js';
12
12
  export { PROVIDER_NAME, SKILL_NAME, BUNDLED_SKILL_RANK, SKILL_FILE, skillDir, skillFile, parseSkillText, provider as skillProvider } from './skill-provider.js';
13
13
  export type { SkillCandidate, SkillDefinition, SkillProvider, SkillInvocationPolicy, SkillsFace, SkillHostCtx } from './dsh-ctx.js';
14
+ export { SKILL_TOOL_NAME, createSkillTool, resolveSkillEntry } from './skill-tool.js';
14
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,cAAc,CAAC;AAE7D,eAAO,MAAM,IAAI,mBAAmB,CAAC;AACrC,eAAO,MAAM,MAAM,EAAE,SAAS,MAAM,EAA0C,CAAC;AAsC/E,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAkD7C;AAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACtJ,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC5K,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC7V,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACnO,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAKvG,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAChK,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,qBAAqB,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,cAAc,CAAC;AAG7D,eAAO,MAAM,IAAI,mBAAmB,CAAC;AACrC,eAAO,MAAM,MAAM,EAAE,SAAS,MAAM,EAAmD,CAAC;AAsCxF,wBAAgB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAgE7C;AAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACtJ,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC5K,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC7V,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACnO,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAKvG,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAChK,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,qBAAqB,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACpI,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -14,8 +14,9 @@
14
14
  import { RPC_CHANNEL, RPC_ENDPOINT_READ, RPC_ENDPOINT_CONFIG_GET, RPC_ENDPOINT_CONFIG_SAVE, RPC_ENDPOINT_CONFIG_RESET, RPC_ENDPOINT_CONFIG_CHECK, ok, fail, parseReadPayload, parseSavePayload } from './contract.js';
15
15
  import { SkillBridgeError, readViaCli, readConfigSurface, writeConfigValues, resetConfigToDefaults, readConfigHealth } from './bridge.js';
16
16
  import { PROVIDER_NAME, provider as skillProvider } from './skill-provider.js';
17
+ import { SKILL_TOOL_NAME, createSkillTool } from './skill-tool.js';
17
18
  export const name = 'dsh-bill-ilife';
18
- export const inject = ['skills', 'connection', 'webServer'];
19
+ export const inject = ['skills', 'connection', 'webServer', 'tools'];
19
20
  /** RPC 处理函数:endpoint 分发 → 载荷校验 → bridge → 信封包装(#56 卡路里样板同形)。
20
21
  *
21
22
  * #677 起多三个配置端点(`config.get`/`config.save`/`config.reset`):设置页只经它们
@@ -66,6 +67,24 @@ export function apply(ctx) {
66
67
  throw error;
67
68
  logger.warn?.('[dsh-bill-ilife] skill provider ' + PROVIDER_NAME + ' already registered by another instance; yielding');
68
69
  }
70
+ // #734 路线①:把技能唯一出口开成 agent 工具。宿主进程里 spawn(自带运行时,不读 PATH),
71
+ // 纯 DSH 机器上会话没有 `node` 也照样能用。契约与两级回退见 docs/agents/技能调用契约.md。
72
+ try {
73
+ const disposeTool = ctx.tools?.register(createSkillTool());
74
+ if (disposeTool)
75
+ ctx.effect?.(() => disposeTool, 'dsh-bill-ilife: skill tool cleanup');
76
+ else
77
+ logger.warn?.('[dsh-bill-ilife] tools face missing; agent tool ' + SKILL_TOOL_NAME + ' not registered');
78
+ }
79
+ catch (error) {
80
+ // 工具名是宿主按名去重的单例:重装配时上一实例可能已注册,此时退让(提供方/通道退让同形)。
81
+ if (/already registered|duplicate/.test(String(error?.message ?? error))) {
82
+ logger.warn?.('[dsh-bill-ilife] agent tool ' + SKILL_TOOL_NAME + ' already registered by another instance; yielding');
83
+ }
84
+ else {
85
+ throw error;
86
+ }
87
+ }
69
88
  const conn = ctx.connection;
70
89
  if (conn === undefined || typeof conn.fetch?.register !== 'function') {
71
90
  // 宿主没给连接面(老宿主/单测直调 apply):退让并留痕,不抛——提供方那半照常生效。
@@ -123,4 +142,5 @@ export { RPC_CHANNEL, RPC_ENDPOINT_READ, RPC_ENDPOINT_CONFIG_GET, RPC_ENDPOINT_C
123
142
  // 不是 ESM 模块;值导出会让插件树在启动期报整棵树起不来,连 type-only 引用也会把 client.ts
124
143
  // 拉进宿主 `tsc -b` 的编译程序,把 loader 工厂包覆写成裸 ESM。HostCaller 现只住 client.ts(浏览器侧)。
125
144
  export { PROVIDER_NAME, SKILL_NAME, BUNDLED_SKILL_RANK, SKILL_FILE, skillDir, skillFile, parseSkillText, provider as skillProvider } from './skill-provider.js';
145
+ export { SKILL_TOOL_NAME, createSkillTool, resolveSkillEntry } from './skill-tool.js';
126
146
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -23,8 +23,9 @@ export declare const SETTINGS_SLOT: "ilife:cookie";
23
23
  export declare const CONFIG_STEM: "bill";
24
24
  /** 分级:常用项直接画在页面上,其余进默认收起的「高级」组(#675 冻结口径)。 */
25
25
  export type ConfigTier = 'common' | 'advanced';
26
- /** 控件种类:只有这三种(与受限 YAML 子集的字符串/数字/布尔一一对应,没有数组)。 */
27
- export type ConfigControl = 'text' | 'number' | 'switch';
26
+ /** 控件种类:只有这四种(前三种与受限 YAML 子集的字符串/数字/布尔一一对应,没有数组;
27
+ * `directory` 是**字符串那一档的页面形态**——取值仍是串,只是多一个唤起系统文件夹选择器的入口,见 #736)。 */
28
+ export type ConfigControl = 'text' | 'number' | 'switch' | 'directory';
28
29
  export interface ConfigItem {
29
30
  /** 配置文件里的键路径,一层嵌套用 `.` 连接,例 `html.helpStem`。 */
30
31
  readonly key: string;
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,cAAc,EAAG,gBAAyB,CAAC;AACxD,eAAO,MAAM,aAAa,EAAG,cAAuB,CAAC;AAErD,iEAAiE;AACjE,eAAO,MAAM,WAAW,EAAG,MAAe,CAAC;AAE3C,8CAA8C;AAC9C,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE/C,kDAAkD;AAClD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEzD,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mBAAmB;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,yBAAyB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAkED,sBAAsB;AACtB,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAA6B,CAAC;AAE5E,0BAA0B;AAC1B,eAAO,MAAM,iBAAiB,QAAgB,CAAC;AAE/C,iBAAiB;AACjB,eAAO,MAAM,oBAAoB,EAAG,cAAa,CAAC;AAClD,eAAO,MAAM,mBAAmB,EAAG,gLAAwC,CAAC;AAE5E,+CAA+C;AAC/C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ9E;AAED,iDAAiD;AACjD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAU5F"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,cAAc,EAAG,gBAAyB,CAAC;AACxD,eAAO,MAAM,aAAa,EAAG,cAAuB,CAAC;AAErD,iEAAiE;AACjE,eAAO,MAAM,WAAW,EAAG,MAAe,CAAC;AAE3C,8CAA8C;AAC9C,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE/C;qEACqE;AACrE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEvE,MAAM,WAAW,UAAU;IACzB,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mBAAmB;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,yBAAyB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAkED,sBAAsB;AACtB,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAA6B,CAAC;AAE5E,0BAA0B;AAC1B,eAAO,MAAM,iBAAiB,QAAgB,CAAC;AAE/C,iBAAiB;AACjB,eAAO,MAAM,oBAAoB,EAAG,cAAa,CAAC;AAClD,eAAO,MAAM,mBAAmB,EAAG,gLAAwC,CAAC;AAE5E,+CAA+C;AAC/C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ9E;AAED,iDAAiD;AACjD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAU5F"}
package/dist/settings.js CHANGED
@@ -27,7 +27,7 @@ const COMMON = [
27
27
  key: 'db.dir',
28
28
  title: '数据目录',
29
29
  tier: 'common',
30
- control: 'text',
30
+ control: 'directory',
31
31
  hint: '库文件与备份的根目录。留空=按默认落点(配置目录下的 data/),也就是改造前那个位置。',
32
32
  },
33
33
  {
@@ -58,7 +58,7 @@ const ADVANCED = [
58
58
  key: 'backup.dir',
59
59
  title: '备份目录',
60
60
  tier: 'advanced',
61
- control: 'text',
61
+ control: 'directory',
62
62
  hint: '备份与恢复读写的位置。留空=库目录下的 backups。恢复时按文件名取最新一份。',
63
63
  },
64
64
  {
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAyB,CAAC;AACxD,MAAM,CAAC,MAAM,aAAa,GAAG,cAAuB,CAAC;AAErD,iEAAiE;AACjE,MAAM,CAAC,MAAM,WAAW,GAAG,MAAe,CAAC;AAoB3C,+BAA+B;AAC/B,MAAM,MAAM,GAA0B;IACpC;QACE,GAAG,EAAE,QAAQ;QACb,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,WAAW;QACpB,IAAI,EAAE,+CAA+C;KACtD;IACD;QACE,GAAG,EAAE,SAAS;QACd,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,uCAAuC;KAC9C;IACD;QACE,GAAG,EAAE,UAAU;QACf,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,oCAAoC;KAC3C;IACD;QACE,GAAG,EAAE,UAAU;QACf,KAAK,EAAE,YAAY;QACnB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,6CAA6C;KACpD;CACF,CAAC;AAEF,qCAAqC;AACrC,MAAM,QAAQ,GAA0B;IACtC;QACE,GAAG,EAAE,YAAY;QACjB,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,WAAW;QACpB,IAAI,EAAE,2CAA2C;KAClD;IACD;QACE,GAAG,EAAE,aAAa;QAClB,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,sCAAsC;KAC7C;IACD;QACE,GAAG,EAAE,eAAe;QACpB,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,oCAAoC;KAC3C;IACD;QACE,GAAG,EAAE,mBAAmB;QACxB,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,cAAc;KACrB;CACF,CAAC;AAEF,sBAAsB;AACtB,MAAM,CAAC,MAAM,YAAY,GAA0B,CAAC,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC;AAE5E,0BAA0B;AAC1B,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC;AAE/C,iBAAiB;AACjB,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAa,CAAC;AAClD,MAAM,CAAC,MAAM,mBAAmB,GAAG,+BAAwC,CAAC;AAE5E,+CAA+C;AAC/C,MAAM,UAAU,QAAQ,CAAC,MAA+B,EAAE,GAAW;IACnE,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,GAAG,GAAY,MAAM,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QACpF,GAAG,GAAI,GAA+B,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,SAAS,CAAC,MAA+B,EAAE,GAAW,EAAE,KAAc;IACpF,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,GAAG,GAA4B,MAAM,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACvB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACrF,GAAG,GAAG,GAAG,CAAC,IAAI,CAA4B,CAAC;IAC7C,CAAC;IACD,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,GAAG,KAAK,CAAC;AACxC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ToolDefinitionMirror } from './dsh-ctx.js';
2
+ /** 模型看到的工具名(DSH 工具名用下划线小写,照 `read_file` 同形)。 */
3
+ export declare const SKILL_TOOL_NAME: "run_bill_command";
4
+ /** 纯函数:给技能包根目录,读它的 `package.json`,回 `bin` 声明的入口绝对路径。 */
5
+ export declare function resolveSkillEntry(packageDir: string, readFile?: (path: string) => string): string;
6
+ interface SpawnOutcome {
7
+ readonly status: number | null;
8
+ readonly stdout: string;
9
+ readonly stderr: string;
10
+ readonly error?: Error;
11
+ }
12
+ /** 可注入的三个边界(默认走真实现):入口解析、宿主运行时、spawn。 */
13
+ export interface SkillToolDeps {
14
+ readonly entry?: () => string;
15
+ readonly execPath?: () => string;
16
+ readonly run?: (bin: string, argv: readonly string[], env: Record<string, string | undefined>) => SpawnOutcome;
17
+ }
18
+ /** 造工具定义(宿主 `ctx.tools.register` 消费;形状与 `defineTool` 产物一致,见 dsh-ctx 出处)。 */
19
+ export declare function createSkillTool(deps?: SkillToolDeps): ToolDefinitionMirror;
20
+ export {};
21
+ //# sourceMappingURL=skill-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-tool.d.ts","sourceRoot":"","sources":["../src/skill-tool.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGzD,gDAAgD;AAChD,eAAO,MAAM,eAAe,EAAG,kBAA2B,CAAC;AAoB3D,wDAAwD;AACxD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAuC,GAAG,MAAM,CAWjI;AAeD,UAAU,YAAY;IAAG,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE;AAEnI,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KAAK,YAAY,CAAC;CAChH;AAOD,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,IAAI,GAAE,aAAkB,GAAG,oBAAoB,CAqC9E"}
@@ -0,0 +1,109 @@
1
+ /** 记账技能的 agent 调用通道(#734 路线①):把「宿主进程里跑技能唯一出口」这点开给模型。
2
+ *
3
+ * 为什么需要(`docs/agents/技能调用契约.md` §二):DSH 会话 PATH 上只有宿主自己的
4
+ * `dsh`/`pnpm` 两条命令,纯 DSH 机器上会话里连 `node` 都没有 ⇒ 技能说明面里那句
5
+ * 「跑 bill-cmd-read」在 DSH 里结构性不可解析。本工具**不经会话 shell、不读 PATH**:
6
+ * 在宿主进程里用宿主自带运行时(`resolveNodeBin`,Electron 宿主=该二进制加
7
+ * `ELECTRON_RUN_AS_NODE=1`)spawn 技能唯一出口,把 envelope 原样交给模型。
8
+ *
9
+ * 入口按技能包 `package.json` 的 `bin` 声明解析,不写字面路径(契约 §四):今天=
10
+ * `node_modules/skill-bill/dist/cli/cmd_read.js`;目录若搬动,这里不用改。
11
+ */
12
+ import { spawnSync } from 'node:child_process';
13
+ import { readFileSync } from 'node:fs';
14
+ import { dirname, join } from 'node:path';
15
+ import { createRequire } from 'node:module';
16
+ import { SKILL_PACKAGE, SPAWN_TIMEOUT_MS, SkillBridgeError, assertCliPresent, resolveNodeBin } from './bridge.js';
17
+ /** 模型看到的工具名(DSH 工具名用下划线小写,照 `read_file` 同形)。 */
18
+ export const SKILL_TOOL_NAME = 'run_bill_command';
19
+ const TOOL_DESCRIPTION = '运行记账技能的唯一出口(argv+JSON+exit),返回 envelope JSON。'
20
+ + '写完/看完记账数据的唯一途径;不经 shell、不依赖 PATH。'
21
+ + 'key 例:bill.help.lookup(饼干记账HELP)、bill.record.add(记一笔)。';
22
+ /** 技能包 `package.json` 的 `bin` 声明里,唯一出口那一条的名字后缀。 */
23
+ const EXIT_BIN_SUFFIX = '-cmd-read';
24
+ /** 从 `bin` 声明里挑唯一出口:优先名字以 `-cmd-read` 结尾那条,其次只有一条时用它。 */
25
+ function pickExitBin(bin) {
26
+ if (typeof bin === 'string')
27
+ return bin;
28
+ if (bin === null || typeof bin !== 'object')
29
+ return undefined;
30
+ const entries = Object.entries(bin).filter(([, v]) => typeof v === 'string');
31
+ const named = entries.find(([name]) => name.endsWith(EXIT_BIN_SUFFIX));
32
+ if (named)
33
+ return named[1];
34
+ return entries.length === 1 ? entries[0][1] : undefined;
35
+ }
36
+ /** 纯函数:给技能包根目录,读它的 `package.json`,回 `bin` 声明的入口绝对路径。 */
37
+ export function resolveSkillEntry(packageDir, readFile = (p) => readFileSync(p, 'utf8')) {
38
+ const manifestPath = join(packageDir, 'package.json');
39
+ let manifest;
40
+ try {
41
+ manifest = JSON.parse(readFile(manifestPath));
42
+ }
43
+ catch (cause) {
44
+ throw new SkillBridgeError('missing-cli', '技能包清单读不了:' + manifestPath + '(' + String(cause?.message ?? cause) + ')');
45
+ }
46
+ const entry = pickExitBin(manifest?.bin);
47
+ if (!entry)
48
+ throw new SkillBridgeError('missing-cli', '技能包清单没声明唯一出口(bin):' + manifestPath);
49
+ return join(packageDir, entry);
50
+ }
51
+ /** 默认入口解析:按包名定位已装的技能包(与桥同一处包名定义),再按 `bin` 取入口。 */
52
+ function entryFromInstalledPackage() {
53
+ let packageDir;
54
+ try {
55
+ packageDir = dirname(createRequire(import.meta.url).resolve(SKILL_PACKAGE + '/package.json'));
56
+ }
57
+ catch (cause) {
58
+ throw new SkillBridgeError('missing-cli', '技能包 ' + SKILL_PACKAGE + ' 没装进来:' + String(cause?.message ?? cause));
59
+ }
60
+ const entry = resolveSkillEntry(packageDir);
61
+ assertCliPresent(entry);
62
+ return entry;
63
+ }
64
+ function defaultRun(bin, argv, env) {
65
+ const r = spawnSync(bin, [...argv], { encoding: 'utf8', timeout: SPAWN_TIMEOUT_MS, env, windowsHide: true });
66
+ return { status: r.status, stdout: r.stdout ?? '', stderr: r.stderr ?? '', ...(r.error ? { error: r.error } : {}) };
67
+ }
68
+ /** 造工具定义(宿主 `ctx.tools.register` 消费;形状与 `defineTool` 产物一致,见 dsh-ctx 出处)。 */
69
+ export function createSkillTool(deps = {}) {
70
+ const entryOf = deps.entry ?? entryFromInstalledPackage;
71
+ const execPathOf = deps.execPath ?? (() => process.execPath);
72
+ const run = deps.run ?? defaultRun;
73
+ return {
74
+ name: SKILL_TOOL_NAME,
75
+ description: TOOL_DESCRIPTION,
76
+ parameters: {
77
+ type: 'object',
78
+ properties: {
79
+ key: { type: 'string', description: '命令(bill.* 键),例如 bill.help.lookup' },
80
+ params: { type: 'object', description: '可选参数对象,原样交技能出口(--params JSON)' },
81
+ },
82
+ required: ['key'],
83
+ },
84
+ output: {
85
+ schema: { type: 'string' },
86
+ render: (_args, value) => [{ type: 'text', text: value }],
87
+ },
88
+ async execute(args) {
89
+ const key = args?.key;
90
+ if (typeof key !== 'string' || key.trim().length === 0) {
91
+ throw new Error('缺 key:要跑哪条记账命令(例如 bill.help.lookup)');
92
+ }
93
+ const entry = entryOf();
94
+ const { bin, extraEnv } = resolveNodeBin(execPathOf());
95
+ const outcome = run(bin, [entry, key, '--params', JSON.stringify(args?.params ?? {})], { ...process.env, ...extraEnv });
96
+ const stdout = outcome.stdout.trim();
97
+ if (outcome.error)
98
+ throw new Error('技能出口起不来:' + String(outcome.error.message) + '(' + entry + ')');
99
+ if (outcome.status !== 0) {
100
+ // 技能契约:非 0 走 stderr,stdout 只承载 envelope;两路都交回,模型据此改用别的命令或报给人看。
101
+ throw new Error('技能出口 exit=' + String(outcome.status) + ':' + (outcome.stderr.trim() || stdout || '(无输出)'));
102
+ }
103
+ if (stdout.length === 0)
104
+ throw new Error('技能出口没给 envelope(stdout 空):' + entry);
105
+ return stdout;
106
+ },
107
+ };
108
+ }
109
+ //# sourceMappingURL=skill-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-tool.js","sourceRoot":"","sources":["../src/skill-tool.ts"],"names":[],"mappings":"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"}
package/dist/slot.d.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  export declare const SKILL: "bill";
9
9
  export declare const SLOT_ID: "ilife:cookie";
10
10
  export declare const SLOT_ORDER: 95;
11
- export declare const SLOT_TITLE: "\u8BB0\u8D26";
11
+ export declare const SLOT_TITLE: "\u997C\u5E72\u8BB0\u8D26";
12
12
  export declare const PLUGIN: "dsh-bill-ilife";
13
13
  export declare const MANAGER_PLUGIN: "dsh-life-pack";
14
14
  export interface SlotDescriptor {
@@ -1 +1 @@
1
- {"version":3,"file":"slot.d.ts","sourceRoot":"","sources":["../src/slot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,KAAK,EAAG,MAAe,CAAC;AACrC,eAAO,MAAM,OAAO,EAAG,cAAuB,CAAC;AAC/C,eAAO,MAAM,UAAU,EAAG,EAAW,CAAC;AACtC,eAAO,MAAM,UAAU,EAAG,cAAa,CAAC;AACxC,eAAO,MAAM,MAAM,EAAG,gBAAyB,CAAC;AAChD,eAAO,MAAM,cAAc,EAAG,eAAwB,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,cAAc,IAAI,cAAc,CAE/C;AAED,gCAAgC;AAChC,eAAO,MAAM,aAAa;;;CAAiD,CAAC;AAE5E,MAAM,WAAW,QAAQ;IACvB,OAAO,IAAI,OAAO,CAAC;IACnB,WAAW,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,IAAI,CAAC;IAC/J,OAAO,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAChH;AAED,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAGlE;AAED,gCAAgC;AAChC,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAGnE"}
1
+ {"version":3,"file":"slot.d.ts","sourceRoot":"","sources":["../src/slot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,KAAK,EAAG,MAAe,CAAC;AACrC,eAAO,MAAM,OAAO,EAAG,cAAuB,CAAC;AAC/C,eAAO,MAAM,UAAU,EAAG,EAAW,CAAC;AACtC,eAAO,MAAM,UAAU,EAAG,0BAAe,CAAC;AAC1C,eAAO,MAAM,MAAM,EAAG,gBAAyB,CAAC;AAChD,eAAO,MAAM,cAAc,EAAG,eAAwB,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,cAAc,IAAI,cAAc,CAE/C;AAED,gCAAgC;AAChC,eAAO,MAAM,aAAa;;;CAAiD,CAAC;AAE5E,MAAM,WAAW,QAAQ;IACvB,OAAO,IAAI,OAAO,CAAC;IACnB,WAAW,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,IAAI,CAAC;IAC/J,OAAO,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAChH;AAED,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAGlE;AAED,gCAAgC;AAChC,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAGnE"}
package/dist/slot.js CHANGED
@@ -8,7 +8,7 @@
8
8
  export const SKILL = 'bill';
9
9
  export const SLOT_ID = 'ilife:cookie';
10
10
  export const SLOT_ORDER = 95;
11
- export const SLOT_TITLE = '记账';
11
+ export const SLOT_TITLE = '饼干记账';
12
12
  export const PLUGIN = 'dsh-bill-ilife';
13
13
  export const MANAGER_PLUGIN = 'dsh-life-pack';
14
14
  export function slotDescriptor() {
package/dist/slot.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"slot.js","sourceRoot":"","sources":["../src/slot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,KAAK,GAAG,MAAe,CAAC;AACrC,MAAM,CAAC,MAAM,OAAO,GAAG,cAAuB,CAAC;AAC/C,MAAM,CAAC,MAAM,UAAU,GAAG,EAAW,CAAC;AACtC,MAAM,CAAC,MAAM,UAAU,GAAG,IAAa,CAAC;AACxC,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAyB,CAAC;AAChD,MAAM,CAAC,MAAM,cAAc,GAAG,eAAwB,CAAC;AAUvD,MAAM,UAAU,cAAc;IAC5B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC/F,CAAC;AAED,gCAAgC;AAChC,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAW,CAAC;AAQ5E,iDAAiD;AACjD,MAAM,UAAU,cAAc,CAAC,IAAc;IAC3C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;AACzH,CAAC;AAED,gCAAgC;AAChC,MAAM,UAAU,UAAU,CAAC,IAAc,EAAE,SAAkB;IAC3D,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;QAAE,OAAO;IAC5B,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AACxF,CAAC"}
1
+ {"version":3,"file":"slot.js","sourceRoot":"","sources":["../src/slot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,KAAK,GAAG,MAAe,CAAC;AACrC,MAAM,CAAC,MAAM,OAAO,GAAG,cAAuB,CAAC;AAC/C,MAAM,CAAC,MAAM,UAAU,GAAG,EAAW,CAAC;AACtC,MAAM,CAAC,MAAM,UAAU,GAAG,MAAe,CAAC;AAC1C,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAyB,CAAC;AAChD,MAAM,CAAC,MAAM,cAAc,GAAG,eAAwB,CAAC;AAUvD,MAAM,UAAU,cAAc;IAC5B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC/F,CAAC;AAED,gCAAgC;AAChC,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAW,CAAC;AAQ5E,iDAAiD;AACjD,MAAM,UAAU,cAAc,CAAC,IAAc;IAC3C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;AACzH,CAAC;AAED,gCAAgC;AAChC,MAAM,UAAU,UAAU,CAAC,IAAc,EAAE,SAAkB;IAC3D,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;QAAE,OAAO;IAC5B,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AACxF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-bill-ilife",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "爱生活单品插件 P10 脚手架:记账(ilife:cookie order 95),硬依赖总管 dsh-life-pack",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,7 +25,7 @@
25
25
  "node": ">=22.13"
26
26
  },
27
27
  "dependencies": {
28
- "dsh-life-pack": "^0.2.6",
28
+ "dsh-life-pack": "^0.3.0",
29
29
  "skill-bill": "0.2.2"
30
30
  },
31
31
  "dsh": {