dsh-calorie 0.1.6 → 0.2.1

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
@@ -52,8 +52,8 @@ window.__ModuleLoader__.load({
52
52
  const SKILL_PACKAGE = "skill-calorie";
53
53
  /** 版本行唯一来源(面板展示用;smoke 断言与两处 package.json 一致,防漂移)。
54
54
  * 发版 bump 时同步改这里(与 package.json 同值)。 */
55
- const PLUGIN_VERSION = "0.1.6";
56
- const SKILL_VERSION = "0.1.1";
55
+ const PLUGIN_VERSION = "0.2.0";
56
+ const SKILL_VERSION = "0.2.0";
57
57
  //#endregion
58
58
  //#region src/settings.ts
59
59
  /** 脚手架期唯一设置行:总开关(缺省启用,与官方关闭语义对齐)。 */
@@ -81,7 +81,7 @@ window.__ModuleLoader__.load({
81
81
  * 取数只经 connection.rpc.call 进 host 通道;缺席/错误纯条件渲染,不返空冒充。
82
82
  * 组件 React.createElement 手写,不引入 JSX。
83
83
  */
84
- const inject = ["slots"];
84
+ const inject = ["slots", "connection"];
85
85
  /** 面板视觉(内联 style;颜色走 DSH 主题别名,深浅主题自适应,写死值只做回退)。 */
86
86
  const S = {
87
87
  card: {
@@ -231,7 +231,17 @@ window.__ModuleLoader__.load({
231
231
  let alive = true;
232
232
  const date = todayString();
233
233
  (async () => {
234
- const r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, { date });
234
+ let r;
235
+ try {
236
+ r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, { date });
237
+ } catch (e) {
238
+ if (!alive) return;
239
+ setState({
240
+ kind: "error",
241
+ message: `取数失败:${e instanceof Error ? e.message : String(e)}`
242
+ });
243
+ return;
244
+ }
235
245
  if (!alive) return;
236
246
  if (r.ok) setState({
237
247
  kind: "data",
@@ -268,7 +278,17 @@ window.__ModuleLoader__.load({
268
278
  let alive = true;
269
279
  const date = todayString();
270
280
  (async () => {
271
- const r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, { date });
281
+ let r;
282
+ try {
283
+ r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, { date });
284
+ } catch (e) {
285
+ if (!alive) return;
286
+ setState({
287
+ kind: "error",
288
+ message: `取数失败:${e instanceof Error ? e.message : String(e)}`
289
+ });
290
+ return;
291
+ }
272
292
  if (!alive) return;
273
293
  if (r.ok) setState({
274
294
  kind: "data",
@@ -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-calorie 端口(port):DSH 世界与卡路里 hexagon 之间的契约。\n *\n * browser 安全:零 node 导入。host 适配器(注册 RPC 通道)与 client\n * 适配器(调用 RPC)共用同一份定义;单测与 loader 回路以此为准。\n * 通道命名遵守宿主约束:单段且不等于 /api(见 cookbook「RPC 通道」)。\n */\nexport const RPC_CHANNEL = '/ilife-calorie' as const;\nexport const RPC_ENDPOINT_READ = 'read' as const;\n\n/** 读请求载荷:与技能 CLI 的 key/params 同形(见 skill-calorie SKILL.md)。 */\nexport interface ReadPayload {\n readonly key: string;\n readonly params: 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/** 面板默认读键(与 HITL 一致性对比同键)。 */\nexport const DEFAULT_READ_KEY = 'calorie.view.home' as const;\n\n/** 信封守卫:供 client 拆包前校验(port 拥有信封定义,守卫住 port)。 */\nexport function isRpcResult(raw: unknown): raw is RpcResult {\n if (typeof raw !== 'object' || raw === null) return false;\n const ok = (raw as { ok?: unknown }).ok;\n return ok === true || ok === false;\n}\n","/** dsh-calorie 槽位描述(P10 脚手架,P3 #4 定案)。\n *\n * 写死槽位原生组件:id 命名空间 ilife:calorie,order 75。\n * 注册与打开只走 registerTab/openTab 的路径导航;子页后缀(如 ilife:calorie:*)\n * 只在主面板内导航,不占栏。缺席纯条件渲染,不轮询(本文件无定时器;\n * 有界重试归一由 base-render 拥有,单品不自建)。\n */\n\nexport const SKILL = 'calorie' as const;\nexport const SLOT_ID = 'ilife:calorie' as const;\nexport const SLOT_ORDER = 75 as const;\nexport const SLOT_TITLE = '卡路里' as const;\nexport const PLUGIN = 'dsh-calorie' as const;\nexport const MANAGER_PLUGIN = 'dsh-life-pack' as const;\nexport const SKILL_PACKAGE = 'skill-calorie' as const;\n\n/** 版本行唯一来源(面板展示用;smoke 断言与两处 package.json 一致,防漂移)。\n * 发版 bump 时同步改这里(与 package.json 同值)。 */\nexport const PLUGIN_VERSION = '0.1.6' as const;\nexport const SKILL_VERSION = '0.1.1' 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: 'CaloriePanel' } 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-calorie 设置页(P10 脚手架:设置页住单品包)。\n *\n * 一次 registerTab,两处呈现:边栏 + 号菜单多一项,DSH 设置页侧边卡片\n * 分区自动多一张小卡片(注册表驱动、无硬编码,开关缺省启用)。\n * 本文件只声明本单品自己的设置行;总管不声明设置(见 boundaries 断言)。\n */\n\nexport const SETTINGS_OWNER = 'dsh-calorie' as const;\nexport const SETTINGS_SLOT = 'ilife:calorie' as const;\n\nexport interface SettingRow {\n readonly key: string;\n readonly title: string;\n readonly control: 'switch' | 'text' | 'number';\n}\n\n/** 脚手架期唯一设置行:总开关(缺省启用,与官方关闭语义对齐)。 */\nexport const SETTING_ROWS: readonly SettingRow[] = [\n { key: 'enabled', title: '卡路里面板启用', control: 'switch' },\n];\n","/** dsh-calorie client 适配器(六边形:port=contract+dsh-ctx 镜像,adapter=本文件)。\n *\n * 产物经 tsdown 打成 loader 工厂包(browser/CJS,见 tsdown.config.ts)。\n * 本文件传递闭包:禁 node、禁 DOM 直写(document/window/process)。\n * 注册两处(grill 定案,新术语见 CONTEXT.md):\n * (a) 技能设置页 → 爱生活页签槽(总管声明的 children,各技能自研自家配置页);\n * (b) 技能功能页 → sidebar槽(better-sidebar 服务,非 DSH slot;软依赖,\n * 缺席即跳过,不断链。DSH右侧槽 + sidebar.footer.action 彻底出局,已删)。\n * 有界重试例外依据(唯一允许的定时器):注册重试非数据轮询,照抄\n * dsh-mattpocock-skills-deck/src/client/panelAssembly.js:100-108\n * (betterSidebar 服务可能晚于本模块到达,最多 10 次、间隔 1000ms;卸载清理)。\n * 样式:React 内联 style + DSH 主题别名(var(--dsw-alias-*),带回退),无外部样式表、\n * 无 <style> 注入、无类名冲突;只用 dsh-ctx 镜像内成员(slots.inject/register、\n * connection.rpc.call 经闭包现取、betterSidebar 经 ctx.get 运行时取);\n * 取数只经 connection.rpc.call 进 host 通道;缺席/错误纯条件渲染,不返空冒充。\n * 组件 React.createElement 手写,不引入 JSX。\n */\nimport * as React from 'react';\nimport { RPC_CHANNEL, RPC_ENDPOINT_READ, DEFAULT_READ_KEY, isRpcResult } from './contract.js';\nimport { SLOT_TITLE, PLUGIN, SKILL_PACKAGE, PLUGIN_VERSION, SKILL_VERSION } from './slot.js';\nimport { SETTING_ROWS } from './settings.js';\nimport type { ClientCtx, RpcCallResult } from './dsh-ctx.js';\n\nexport const inject = ['slots'];\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 total: { fontSize: 22, fontWeight: 700, margin: '2px 0 4px' } 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 } 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};\n\n/** 版本行:插件与技能双版本号(用户要求:每技能设置页自报家门)。 */\nfunction VersionLine(): React.ReactElement {\n return React.createElement('div', { style: S.version }, `${PLUGIN} ${PLUGIN_VERSION} · ${SKILL_PACKAGE} ${SKILL_VERSION}`);\n}\n\ntype PanelState =\n | { readonly kind: 'loading' }\n | { readonly kind: 'data'; readonly date: string; readonly total: string }\n | { readonly kind: 'absent'; readonly message: string }\n | { readonly kind: 'error'; readonly message: string };\n\n/** 本地今日 YYYY-MM-DD(与面板默认读键的 date 参数同形)。 */\nfunction todayString(): string {\n const d = new Date();\n const m = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${d.getFullYear()}-${m}-${day}`;\n}\n\n/** 数据态取值:有 total 显示 total,有值无 total 显示原值 JSON,空值返回 null(由调用方进错误态)。 */\nfunction extractTotal(value: unknown): string | null {\n if (value === null || value === undefined) return null;\n if (typeof value === 'string') return value.length > 0 ? value : null;\n if (typeof value === 'object') {\n const total = (value as { total?: unknown }).total;\n if (total !== null && total !== undefined) return String(total);\n try {\n return JSON.stringify(value);\n } catch {\n return null;\n }\n }\n return String(value);\n}\n\ntype ReadOutcome =\n | { readonly ok: true; readonly text: string }\n | { readonly ok: false; readonly absent: boolean; readonly message: string };\n\n/** 请求超时毫秒:与 host 侧 SPAWN_TIMEOUT_MS 同级,UI 永不无限转圈。 */\nconst READ_TIMEOUT_MS = 20_000 as const;\n\n/** 自家赛跑超时(有界:settle 即清 timer;不依赖传输是否搭理 AbortSignal——Desktop 自研传输会忽略 signal)。\n * 注释即 p10 有界重试门要的例外依据(文件内另有 clearTimeout/tries 上限/本注释三件套)。 */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const limit = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n timer = undefined;\n const e = new Error(`取数超时(${Math.round(ms / 1000)}s):宿主未回,先查宿主日志与 DB 环境`);\n e.name = 'TimeoutError';\n reject(e);\n }, ms);\n });\n return Promise.race([\n promise.finally(() => {\n if (timer !== undefined) clearTimeout(timer);\n }),\n limit,\n ]);\n}\n\n/** 单次读数(纯异步函数,无 hook;挂载期调用一次,无轮询)。 */\nasync function fetchRead(call: unknown, key: string, params: Record<string, unknown>): Promise<ReadOutcome> {\n // extractRpc 同式守卫:非函数即缺席态。\n if (typeof call !== 'function') return { ok: false, absent: true, message: '宿主连接缺席:connection.rpc.call 不可用' };\n let result: RpcCallResult;\n try {\n // 防御纵深 + 自家超时双保险(AbortSignal 帮正规传输提前收工;race 保传输忽略 signal 时仍落字)。\n const raw: unknown = await withTimeout(\n call(RPC_CHANNEL, RPC_ENDPOINT_READ, { key, params }, AbortSignal.timeout(READ_TIMEOUT_MS)),\n READ_TIMEOUT_MS,\n );\n if (!isRpcResult(raw)) return { ok: false, absent: false, message: '回执信封异常(非 ok 信封)' };\n result = raw;\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError') return { ok: false, absent: false, message: '取数超时(20s):宿主未回,先查宿主日志与 DB 环境' };\n return { ok: false, absent: false, message: `取数失败:${e instanceof Error ? e.message : String(e)}` };\n }\n if (!result.ok) {\n const code = result.error?.code ?? 'unknown';\n const message = result.error?.message ?? '';\n if (code === 'missing-cli') return { ok: false, absent: true, message: `技能出口缺席(missing-cli):${message}` };\n return { ok: false, absent: false, message: `取数失败(${code}):${message}` };\n }\n const text = extractTotal(result.value);\n if (text === null) return { ok: false, absent: false, message: '取数为空(不冒充正常)' };\n return { ok: true, text };\n}\n\n/** 技能功能页:sidebar槽里展开的干活区(查数调数,不管配置)。挂载期一次 RPC。 */\nfunction CalorieWork(props: { getCall: GetCall }): React.ReactElement {\n const [state, setState] = React.useState<PanelState>({ kind: 'loading' });\n React.useEffect(() => {\n let alive = true;\n const date = todayString();\n void (async () => {\n const r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, { date });\n if (!alive) return;\n if (r.ok) setState({ kind: 'data', date, total: r.text });\n else if (r.absent) setState({ kind: 'absent', message: r.message });\n else setState({ kind: 'error', message: r.message });\n })();\n return () => {\n alive = false;\n };\n }, [props.getCall]);\n if (state.kind === 'loading') {\n return React.createElement('div', { style: S.card }, React.createElement('div', { style: S.muted }, '卡路里加载中…'));\n }\n if (state.kind === 'data') {\n return React.createElement(\n 'div',\n { style: S.card },\n React.createElement('div', { style: S.title }, `卡路里 · ${state.date}`),\n React.createElement('div', { style: S.total }, `total ${state.total}`),\n React.createElement(VersionLine, null),\n );\n }\n return React.createElement(\n 'div',\n { style: S.card },\n React.createElement('div', { style: state.kind === 'absent' ? S.muted : S.error }, state.message),\n React.createElement(VersionLine, null),\n );\n}\n\nfunction controlLabel(control: string): string {\n if (control === 'switch') return '开关(缺省启用,只读)';\n if (control === 'text') return '文本(只读)';\n if (control === 'number') return '数字(只读)';\n return `${control}(只读)`;\n}\n\n/** 技能设置页:爱生活页签条下的一页(只读设置行 + 状态读数 + 版本行,禁做假开关)。 */\nfunction CalorieConfig(props: { getCall: GetCall }): React.ReactElement {\n const [state, setState] = React.useState<PanelState>({ kind: 'loading' });\n React.useEffect(() => {\n let alive = true;\n const date = todayString();\n void (async () => {\n const r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, { date });\n if (!alive) return;\n if (r.ok) setState({ kind: 'data', date, total: r.text });\n else if (r.absent) setState({ kind: 'absent', message: r.message });\n else setState({ kind: 'error', message: r.message });\n })();\n return () => {\n alive = false;\n };\n }, [props.getCall]);\n const status =\n state.kind === 'loading'\n ? React.createElement('div', { style: S.muted }, '状态读取中…')\n : state.kind === 'data'\n ? React.createElement(\n 'div',\n null,\n React.createElement('div', { style: S.title }, SLOT_TITLE),\n React.createElement('div', { style: S.total }, `total ${state.total}`),\n React.createElement('div', { style: S.muted }, `今日 ${state.date}`),\n )\n : React.createElement('div', { style: state.kind === 'absent' ? S.muted : S.error }, state.message);\n return React.createElement(\n 'div',\n { style: S.card },\n status,\n React.createElement(\n 'div',\n { style: S.rows },\n SETTING_ROWS.map((row) =>\n React.createElement('div', { key: row.key }, `${row.title} · ${controlLabel(row.control)}`),\n ),\n ),\n React.createElement(VersionLine, null),\n );\n}\n\ninterface BetterSidebarService {\n registerTab(descriptor: {\n readonly id: string;\n readonly title: string | (() => string);\n readonly order?: number;\n readonly single?: boolean;\n readonly component: (props: unknown) => React.ReactElement | null;\n }): () => void;\n}\n\nexport function apply(ctx: ClientCtx): void {\n // 调用口取用器透传给组件(每次取数现取;非函数由组件判缺席)。\n const getCall: GetCall = () => ctx.connection?.rpc?.call ?? null;\n\n // (a) 技能设置页 → 爱生活页签槽(总管声明;总管缺席时 inject 等待,不断链)。\n ctx.slots.inject('ilife.config-tab', () =>\n ctx.slots.register(\n {\n name: 'ilife.config-tab',\n id: 'dsh-calorie',\n order: 75,\n label: () => SLOT_TITLE,\n },\n () => React.createElement(CalorieConfig, { getCall }),\n ),\n );\n\n // (b) 技能功能页 → sidebar槽(软依赖:betterSidebar 缺席即跳过)。\n const ensureWorkTab = (): boolean => {\n try {\n const get = ctx.get;\n const bs = (typeof get === 'function' ? get('betterSidebar') : undefined) as BetterSidebarService | undefined;\n if (!bs || typeof bs.registerTab !== 'function') return false;\n const dispose = bs.registerTab({\n id: 'ilife-calorie:work',\n title: '卡路里',\n order: 61,\n single: true,\n component: () => React.createElement(CalorieWork, { getCall }),\n });\n ctx.effect(() => () => {\n try {\n dispose();\n } catch {\n /* 卸载清理失败忽略 */\n }\n }, 'dsh-calorie: sidebar work tab');\n return true;\n } catch {\n return false;\n }\n };\n if (!ensureWorkTab()) {\n let tries = 0;\n const timer = setInterval(() => {\n tries++;\n if (ensureWorkTab() || tries >= 10) clearInterval(timer);\n }, 1000);\n ctx.effect(() => () => {\n clearInterval(timer);\n }, 'dsh-calorie: sidebar work tab retry');\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMA,MAAa,cAAc;EAC3B,MAAa,oBAAoB;;EAoCjC,MAAa,mBAAmB;;EAGhC,SAAgB,YAAY,KAAgC;GAC1D,IAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM,OAAO;GACpD,MAAM,KAAM,IAAyB;GACrC,OAAO,OAAO,QAAQ,OAAO;EAC/B;;;ECvCA,MAAa,aAAa;EAC1B,MAAa,SAAS;EAEtB,MAAa,gBAAgB;;;EAI7B,MAAa,iBAAiB;EAC9B,MAAa,gBAAgB;;;;ECF7B,MAAa,eAAsC,CACjD;GAAE,KAAK;GAAW,OAAO;GAAW,SAAS;EAAS,CACxD;;;;;;;;;;;;;;;;;;;;ECIA,MAAa,SAAS,CAAC,OAAO;;EAM9B,MAAM,IAAI;GACR,MAAM;IACJ,SAAS;IACT,cAAc;IACd,QAAQ;IACR,YAAY;IACZ,OAAO;IACP,UAAU;IACV,YAAY;GACd;GACA,OAAO;IAAE,UAAU;IAAI,YAAY;IAAK,cAAc;GAAE;GACxD,OAAO;IAAE,UAAU;IAAI,YAAY;IAAK,QAAQ;GAAY;GAC5D,OAAO;IAAE,OAAO;IAA6C,UAAU;GAAG;GAC1E,OAAO;IAAE,OAAO;IAAiD,UAAU;GAAG;GAC9E,MAAM;IAAE,WAAW;IAAG,WAAW;IAA4D,YAAY;GAAE;GAC3G,SAAS;IACP,WAAW;IACX,YAAY;IACZ,WAAW;IACX,OAAO;IACP,UAAU;GACZ;EACF;;EAGA,SAAS,cAAkC;GACzC,OAAOA,MAAM,cAAc,OAAO,EAAE,OAAO,EAAE,QAAQ,GAAG,GAAG,OAAO,GAAG,eAAe,KAAK,cAAc,GAAG,eAAe;EAC3H;;EASA,SAAS,cAAsB;GAC7B,MAAM,oBAAI,IAAI,KAAK;GACnB,MAAM,IAAI,OAAO,EAAE,SAAS,IAAI,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;GAClD,MAAM,MAAM,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG;GAC/C,OAAO,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG;EACpC;;EAGA,SAAS,aAAa,OAA+B;GACnD,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW,OAAO;GAClD,IAAI,OAAO,UAAU,UAAU,OAAO,MAAM,SAAS,IAAI,QAAQ;GACjE,IAAI,OAAO,UAAU,UAAU;IAC7B,MAAM,QAAS,MAA8B;IAC7C,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW,OAAO,OAAO,KAAK;IAC9D,IAAI;KACF,OAAO,KAAK,UAAU,KAAK;IAC7B,QAAQ;KACN,OAAO;IACT;GACF;GACA,OAAO,OAAO,KAAK;EACrB;;EAOA,MAAM,kBAAkB;;;EAIxB,SAAS,YAAe,SAAqB,IAAwB;GACnE,IAAI;GACJ,MAAM,QAAQ,IAAI,SAAgB,GAAG,WAAW;IAC9C,QAAQ,iBAAiB;KACvB,QAAQ,KAAA;KACR,MAAM,oBAAI,IAAI,MAAM,QAAQ,KAAK,MAAM,KAAK,GAAI,EAAE,sBAAsB;KACxE,EAAE,OAAO;KACT,OAAO,CAAC;IACV,GAAG,EAAE;GACP,CAAC;GACD,OAAO,QAAQ,KAAK,CAClB,QAAQ,cAAc;IACpB,IAAI,UAAU,KAAA,GAAW,aAAa,KAAK;GAC7C,CAAC,GACD,KACF,CAAC;EACH;;EAGA,eAAe,UAAU,MAAe,KAAa,QAAuD;GAE1G,IAAI,OAAO,SAAS,YAAY,OAAO;IAAE,IAAI;IAAO,QAAQ;IAAM,SAAS;GAAiC;GAC5G,IAAI;GACJ,IAAI;IAEF,MAAM,MAAe,MAAM,YACzB,KAAK,aAAa,mBAAmB;KAAE;KAAK;IAAO,GAAG,YAAY,QAAQ,eAAe,CAAC,GAC1F,eACF;IACA,IAAI,CAAC,YAAY,GAAG,GAAG,OAAO;KAAE,IAAI;KAAO,QAAQ;KAAO,SAAS;IAAkB;IACrF,SAAS;GACX,SAAS,GAAG;IACV,IAAI,aAAa,SAAS,EAAE,SAAS,cAAc,OAAO;KAAE,IAAI;KAAO,QAAQ;KAAO,SAAS;IAA+B;IAC9H,OAAO;KAAE,IAAI;KAAO,QAAQ;KAAO,SAAS,QAAQ,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;IAAI;GACnG;GACA,IAAI,CAAC,OAAO,IAAI;IACd,MAAM,OAAO,OAAO,OAAO,QAAQ;IACnC,MAAM,UAAU,OAAO,OAAO,WAAW;IACzC,IAAI,SAAS,eAAe,OAAO;KAAE,IAAI;KAAO,QAAQ;KAAM,SAAS,uBAAuB;IAAU;IACxG,OAAO;KAAE,IAAI;KAAO,QAAQ;KAAO,SAAS,QAAQ,KAAK,IAAI;IAAU;GACzE;GACA,MAAM,OAAO,aAAa,OAAO,KAAK;GACtC,IAAI,SAAS,MAAM,OAAO;IAAE,IAAI;IAAO,QAAQ;IAAO,SAAS;GAAc;GAC7E,OAAO;IAAE,IAAI;IAAM;GAAK;EAC1B;;EAGA,SAAS,YAAY,OAAiD;GACpE,MAAM,CAAC,OAAO,YAAYA,MAAM,SAAqB,EAAE,MAAM,UAAU,CAAC;GACxE,MAAM,gBAAgB;IACpB,IAAI,QAAQ;IACZ,MAAM,OAAO,YAAY;IACzB,CAAM,YAAY;KAChB,MAAM,IAAI,MAAM,UAAU,MAAM,QAAQ,GAAG,kBAAkB,EAAE,KAAK,CAAC;KACrE,IAAI,CAAC,OAAO;KACZ,IAAI,EAAE,IAAI,SAAS;MAAE,MAAM;MAAQ;MAAM,OAAO,EAAE;KAAK,CAAC;UACnD,IAAI,EAAE,QAAQ,SAAS;MAAE,MAAM;MAAU,SAAS,EAAE;KAAQ,CAAC;UAC7D,SAAS;MAAE,MAAM;MAAS,SAAS,EAAE;KAAQ,CAAC;IACrD,EAAA,CAAG;IACH,aAAa;KACX,QAAQ;IACV;GACF,GAAG,CAAC,MAAM,OAAO,CAAC;GAClB,IAAI,MAAM,SAAS,WACjB,OAAOA,MAAM,cAAc,OAAO,EAAE,OAAO,EAAE,KAAK,GAAGA,MAAM,cAAc,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;GAEhH,IAAI,MAAM,SAAS,QACjB,OAAOA,MAAM,cACX,OACA,EAAE,OAAO,EAAE,KAAK,GAChBA,MAAM,cAAc,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,MAAM,MAAM,GACpEA,MAAM,cAAc,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,MAAM,OAAO,GACrEA,MAAM,cAAc,aAAa,IAAI,CACvC;GAEF,OAAOA,MAAM,cACX,OACA,EAAE,OAAO,EAAE,KAAK,GAChBA,MAAM,cAAc,OAAO,EAAE,OAAO,MAAM,SAAS,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,OAAO,GAChGA,MAAM,cAAc,aAAa,IAAI,CACvC;EACF;EAEA,SAAS,aAAa,SAAyB;GAC7C,IAAI,YAAY,UAAU,OAAO;GACjC,IAAI,YAAY,QAAQ,OAAO;GAC/B,IAAI,YAAY,UAAU,OAAO;GACjC,OAAO,GAAG,QAAQ;EACpB;;EAGA,SAAS,cAAc,OAAiD;GACtE,MAAM,CAAC,OAAO,YAAYA,MAAM,SAAqB,EAAE,MAAM,UAAU,CAAC;GACxE,MAAM,gBAAgB;IACpB,IAAI,QAAQ;IACZ,MAAM,OAAO,YAAY;IACzB,CAAM,YAAY;KAChB,MAAM,IAAI,MAAM,UAAU,MAAM,QAAQ,GAAG,kBAAkB,EAAE,KAAK,CAAC;KACrE,IAAI,CAAC,OAAO;KACZ,IAAI,EAAE,IAAI,SAAS;MAAE,MAAM;MAAQ;MAAM,OAAO,EAAE;KAAK,CAAC;UACnD,IAAI,EAAE,QAAQ,SAAS;MAAE,MAAM;MAAU,SAAS,EAAE;KAAQ,CAAC;UAC7D,SAAS;MAAE,MAAM;MAAS,SAAS,EAAE;KAAQ,CAAC;IACrD,EAAA,CAAG;IACH,aAAa;KACX,QAAQ;IACV;GACF,GAAG,CAAC,MAAM,OAAO,CAAC;GAClB,MAAM,SACJ,MAAM,SAAS,YACXA,MAAM,cAAc,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,IACvD,MAAM,SAAS,SACbA,MAAM,cACJ,OACA,MACAA,MAAM,cAAc,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GACzDA,MAAM,cAAc,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,MAAM,OAAO,GACrEA,MAAM,cAAc,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,MAAM,MAAM,CACnE,IACAA,MAAM,cAAc,OAAO,EAAE,OAAO,MAAM,SAAS,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,OAAO;GACxG,OAAOA,MAAM,cACX,OACA,EAAE,OAAO,EAAE,KAAK,GAChB,QACAA,MAAM,cACJ,OACA,EAAE,OAAO,EAAE,KAAK,GAChB,aAAa,KAAK,QAChBA,MAAM,cAAc,OAAO,EAAE,KAAK,IAAI,IAAI,GAAG,GAAG,IAAI,MAAM,KAAK,aAAa,IAAI,OAAO,GAAG,CAC5F,CACF,GACAA,MAAM,cAAc,aAAa,IAAI,CACvC;EACF;EAYA,SAAgB,MAAM,KAAsB;GAE1C,MAAM,gBAAyB,IAAI,YAAY,KAAK,QAAQ;GAG5D,IAAI,MAAM,OAAO,0BACf,IAAI,MAAM,SACR;IACE,MAAM;IACN,IAAI;IACJ,OAAO;IACP,aAAa;GACf,SACMA,MAAM,cAAc,eAAe,EAAE,QAAQ,CAAC,CACtD,CACF;GAGA,MAAM,sBAA+B;IACnC,IAAI;KACF,MAAM,MAAM,IAAI;KAChB,MAAM,KAAM,OAAO,QAAQ,aAAa,IAAI,eAAe,IAAI,KAAA;KAC/D,IAAI,CAAC,MAAM,OAAO,GAAG,gBAAgB,YAAY,OAAO;KACxD,MAAM,UAAU,GAAG,YAAY;MAC7B,IAAI;MACJ,OAAO;MACP,OAAO;MACP,QAAQ;MACR,iBAAiBA,MAAM,cAAc,aAAa,EAAE,QAAQ,CAAC;KAC/D,CAAC;KACD,IAAI,mBAAmB;MACrB,IAAI;OACF,QAAQ;MACV,QAAQ,CAER;KACF,GAAG,+BAA+B;KAClC,OAAO;IACT,QAAQ;KACN,OAAO;IACT;GACF;GACA,IAAI,CAAC,cAAc,GAAG;IACpB,IAAI,QAAQ;IACZ,MAAM,QAAQ,kBAAkB;KAC9B;KACA,IAAI,cAAc,KAAK,SAAS,IAAI,cAAc,KAAK;IACzD,GAAG,GAAI;IACP,IAAI,mBAAmB;KACrB,cAAc,KAAK;IACrB,GAAG,qCAAqC;GAC1C;EACF"}
1
+ {"version":3,"file":"client.js","names":["React"],"sources":["../src/contract.ts","../src/slot.ts","../src/settings.ts","../src/client.ts"],"sourcesContent":["/** dsh-calorie 端口(port):DSH 世界与卡路里 hexagon 之间的契约。\n *\n * browser 安全:零 node 导入。host 适配器(注册 RPC 通道)与 client\n * 适配器(调用 RPC)共用同一份定义;单测与 loader 回路以此为准。\n * 通道命名遵守宿主约束:单段且不等于 /api(见 cookbook「RPC 通道」)。\n */\nexport const RPC_CHANNEL = '/ilife-calorie' as const;\nexport const RPC_ENDPOINT_READ = 'read' as const;\n\n/** 读请求载荷:与技能 CLI 的 key/params 同形(见 skill-calorie SKILL.md)。 */\nexport interface ReadPayload {\n readonly key: string;\n readonly params: 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/** 面板默认读键(与 HITL 一致性对比同键)。 */\nexport const DEFAULT_READ_KEY = 'calorie.view.home' as const;\n\n/** 信封守卫:供 client 拆包前校验(port 拥有信封定义,守卫住 port)。 */\nexport function isRpcResult(raw: unknown): raw is RpcResult {\n if (typeof raw !== 'object' || raw === null) return false;\n const ok = (raw as { ok?: unknown }).ok;\n return ok === true || ok === false;\n}\n","/** dsh-calorie 槽位描述(P10 脚手架,P3 #4 定案)。\n *\n * 写死槽位原生组件:id 命名空间 ilife:calorie,order 75。\n * 注册与打开只走 registerTab/openTab 的路径导航;子页后缀(如 ilife:calorie:*)\n * 只在主面板内导航,不占栏。缺席纯条件渲染,不轮询(本文件无定时器;\n * 有界重试归一由 base-render 拥有,单品不自建)。\n */\n\nexport const SKILL = 'calorie' as const;\nexport const SLOT_ID = 'ilife:calorie' as const;\nexport const SLOT_ORDER = 75 as const;\nexport const SLOT_TITLE = '卡路里' as const;\nexport const PLUGIN = 'dsh-calorie' as const;\nexport const MANAGER_PLUGIN = 'dsh-life-pack' as const;\nexport const SKILL_PACKAGE = 'skill-calorie' as const;\n\n/** 版本行唯一来源(面板展示用;smoke 断言与两处 package.json 一致,防漂移)。\n * 发版 bump 时同步改这里(与 package.json 同值)。 */\nexport const PLUGIN_VERSION = '0.2.0' as const;\nexport const SKILL_VERSION = '0.2.0' 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: 'CaloriePanel' } 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-calorie 设置页(P10 脚手架:设置页住单品包)。\n *\n * 一次 registerTab,两处呈现:边栏 + 号菜单多一项,DSH 设置页侧边卡片\n * 分区自动多一张小卡片(注册表驱动、无硬编码,开关缺省启用)。\n * 本文件只声明本单品自己的设置行;总管不声明设置(见 boundaries 断言)。\n */\n\nexport const SETTINGS_OWNER = 'dsh-calorie' as const;\nexport const SETTINGS_SLOT = 'ilife:calorie' as const;\n\nexport interface SettingRow {\n readonly key: string;\n readonly title: string;\n readonly control: 'switch' | 'text' | 'number';\n}\n\n/** 脚手架期唯一设置行:总开关(缺省启用,与官方关闭语义对齐)。 */\nexport const SETTING_ROWS: readonly SettingRow[] = [\n { key: 'enabled', title: '卡路里面板启用', control: 'switch' },\n];\n","/** dsh-calorie client 适配器(六边形:port=contract+dsh-ctx 镜像,adapter=本文件)。\n *\n * 产物经 tsdown 打成 loader 工厂包(browser/CJS,见 tsdown.config.ts)。\n * 本文件传递闭包:禁 node、禁 DOM 直写(document/window/process)。\n * 注册两处(grill 定案,新术语见 CONTEXT.md):\n * (a) 技能设置页 → 爱生活页签槽(总管声明的 children,各技能自研自家配置页);\n * (b) 技能功能页 → sidebar槽(better-sidebar 服务,非 DSH slot;软依赖,\n * 缺席即跳过,不断链。DSH右侧槽 + sidebar.footer.action 彻底出局,已删)。\n * 有界重试例外依据(唯一允许的定时器):注册重试非数据轮询,照抄\n * dsh-mattpocock-skills-deck/src/client/panelAssembly.js:100-108\n * (betterSidebar 服务可能晚于本模块到达,最多 10 次、间隔 1000ms;卸载清理)。\n * 样式:React 内联 style + DSH 主题别名(var(--dsw-alias-*),带回退),无外部样式表、\n * 无 <style> 注入、无类名冲突;只用 dsh-ctx 镜像内成员(slots.inject/register、\n * connection.rpc.call 经闭包现取、betterSidebar 经 ctx.get 运行时取);\n * 取数只经 connection.rpc.call 进 host 通道;缺席/错误纯条件渲染,不返空冒充。\n * 组件 React.createElement 手写,不引入 JSX。\n */\nimport * as React from 'react';\nimport { RPC_CHANNEL, RPC_ENDPOINT_READ, DEFAULT_READ_KEY, isRpcResult } from './contract.js';\nimport { SLOT_TITLE, PLUGIN, SKILL_PACKAGE, PLUGIN_VERSION, SKILL_VERSION } from './slot.js';\nimport { SETTING_ROWS } from './settings.js';\nimport type { ClientCtx, RpcCallResult } from './dsh-ctx.js';\n\nexport const inject = ['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 total: { fontSize: 22, fontWeight: 700, margin: '2px 0 4px' } 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 } 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};\n\n/** 版本行:插件与技能双版本号(用户要求:每技能设置页自报家门)。 */\nfunction VersionLine(): React.ReactElement {\n return React.createElement('div', { style: S.version }, `${PLUGIN} ${PLUGIN_VERSION} · ${SKILL_PACKAGE} ${SKILL_VERSION}`);\n}\n\ntype PanelState =\n | { readonly kind: 'loading' }\n | { readonly kind: 'data'; readonly date: string; readonly total: string }\n | { readonly kind: 'absent'; readonly message: string }\n | { readonly kind: 'error'; readonly message: string };\n\n/** 本地今日 YYYY-MM-DD(与面板默认读键的 date 参数同形)。 */\nfunction todayString(): string {\n const d = new Date();\n const m = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${d.getFullYear()}-${m}-${day}`;\n}\n\n/** 数据态取值:有 total 显示 total,有值无 total 显示原值 JSON,空值返回 null(由调用方进错误态)。 */\nfunction extractTotal(value: unknown): string | null {\n if (value === null || value === undefined) return null;\n if (typeof value === 'string') return value.length > 0 ? value : null;\n if (typeof value === 'object') {\n const total = (value as { total?: unknown }).total;\n if (total !== null && total !== undefined) return String(total);\n try {\n return JSON.stringify(value);\n } catch {\n return null;\n }\n }\n return String(value);\n}\n\ntype ReadOutcome =\n | { readonly ok: true; readonly text: string }\n | { readonly ok: false; readonly absent: boolean; readonly message: string };\n\n/** 请求超时毫秒:与 host 侧 SPAWN_TIMEOUT_MS 同级,UI 永不无限转圈。 */\nconst READ_TIMEOUT_MS = 20_000 as const;\n\n/** 自家赛跑超时(有界:settle 即清 timer;不依赖传输是否搭理 AbortSignal——Desktop 自研传输会忽略 signal)。\n * 注释即 p10 有界重试门要的例外依据(文件内另有 clearTimeout/tries 上限/本注释三件套)。 */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const limit = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n timer = undefined;\n const e = new Error(`取数超时(${Math.round(ms / 1000)}s):宿主未回,先查宿主日志与 DB 环境`);\n e.name = 'TimeoutError';\n reject(e);\n }, ms);\n });\n return Promise.race([\n promise.finally(() => {\n if (timer !== undefined) clearTimeout(timer);\n }),\n limit,\n ]);\n}\n\n/** 单次读数(纯异步函数,无 hook;挂载期调用一次,无轮询)。 */\nasync function fetchRead(call: unknown, key: string, params: Record<string, unknown>): Promise<ReadOutcome> {\n // extractRpc 同式守卫:非函数即缺席态。\n if (typeof call !== 'function') return { ok: false, absent: true, message: '宿主连接缺席:connection.rpc.call 不可用' };\n let result: RpcCallResult;\n try {\n // 防御纵深 + 自家超时双保险(AbortSignal 帮正规传输提前收工;race 保传输忽略 signal 时仍落字)。\n const raw: unknown = await withTimeout(\n call(RPC_CHANNEL, RPC_ENDPOINT_READ, { key, params }, AbortSignal.timeout(READ_TIMEOUT_MS)),\n READ_TIMEOUT_MS,\n );\n if (!isRpcResult(raw)) return { ok: false, absent: false, message: '回执信封异常(非 ok 信封)' };\n result = raw;\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError') return { ok: false, absent: false, message: '取数超时(20s):宿主未回,先查宿主日志与 DB 环境' };\n return { ok: false, absent: false, message: `取数失败:${e instanceof Error ? e.message : String(e)}` };\n }\n if (!result.ok) {\n const code = result.error?.code ?? 'unknown';\n const message = result.error?.message ?? '';\n if (code === 'missing-cli') return { ok: false, absent: true, message: `技能出口缺席(missing-cli):${message}` };\n return { ok: false, absent: false, message: `取数失败(${code}):${message}` };\n }\n const text = extractTotal(result.value);\n if (text === null) return { ok: false, absent: false, message: '取数为空(不冒充正常)' };\n return { ok: true, text };\n}\n\n/** 技能功能页:sidebar槽里展开的干活区(查数调数,不管配置)。挂载期一次 RPC。 */\nfunction CalorieWork(props: { getCall: GetCall }): React.ReactElement {\n const [state, setState] = React.useState<PanelState>({ kind: 'loading' });\n React.useEffect(() => {\n let alive = true;\n const date = todayString();\n void (async () => {\n let r: ReadOutcome;\n try {\n r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, { date });\n } catch (e) {\n // 调用口同步抛错兜底:fetchRead 之外的错不成不可见 rejection,直接落字。\n if (!alive) return;\n setState({ kind: 'error', message: `取数失败:${e instanceof Error ? e.message : String(e)}` });\n return;\n }\n if (!alive) return;\n if (r.ok) setState({ kind: 'data', date, total: r.text });\n else if (r.absent) setState({ kind: 'absent', message: r.message });\n else setState({ kind: 'error', message: r.message });\n })();\n return () => {\n alive = false;\n };\n }, [props.getCall]);\n if (state.kind === 'loading') {\n return React.createElement('div', { style: S.card }, React.createElement('div', { style: S.muted }, '卡路里加载中…'));\n }\n if (state.kind === 'data') {\n return React.createElement(\n 'div',\n { style: S.card },\n React.createElement('div', { style: S.title }, `卡路里 · ${state.date}`),\n React.createElement('div', { style: S.total }, `total ${state.total}`),\n React.createElement(VersionLine, null),\n );\n }\n return React.createElement(\n 'div',\n { style: S.card },\n React.createElement('div', { style: state.kind === 'absent' ? S.muted : S.error }, state.message),\n React.createElement(VersionLine, null),\n );\n}\n\nfunction controlLabel(control: string): string {\n if (control === 'switch') return '开关(缺省启用,只读)';\n if (control === 'text') return '文本(只读)';\n if (control === 'number') return '数字(只读)';\n return `${control}(只读)`;\n}\n\n/** 技能设置页:爱生活页签条下的一页(只读设置行 + 状态读数 + 版本行,禁做假开关)。 */\nfunction CalorieConfig(props: { getCall: GetCall }): React.ReactElement {\n const [state, setState] = React.useState<PanelState>({ kind: 'loading' });\n React.useEffect(() => {\n let alive = true;\n const date = todayString();\n void (async () => {\n let r: ReadOutcome;\n try {\n r = await fetchRead(props.getCall(), DEFAULT_READ_KEY, { date });\n } catch (e) {\n // 调用口同步抛错兜底:fetchRead 之外的错不成不可见 rejection,直接落字。\n if (!alive) return;\n setState({ kind: 'error', message: `取数失败:${e instanceof Error ? e.message : String(e)}` });\n return;\n }\n if (!alive) return;\n if (r.ok) setState({ kind: 'data', date, total: r.text });\n else if (r.absent) setState({ kind: 'absent', message: r.message });\n else setState({ kind: 'error', message: r.message });\n })();\n return () => {\n alive = false;\n };\n }, [props.getCall]);\n const status =\n state.kind === 'loading'\n ? React.createElement('div', { style: S.muted }, '状态读取中…')\n : state.kind === 'data'\n ? React.createElement(\n 'div',\n null,\n React.createElement('div', { style: S.title }, SLOT_TITLE),\n React.createElement('div', { style: S.total }, `total ${state.total}`),\n React.createElement('div', { style: S.muted }, `今日 ${state.date}`),\n )\n : React.createElement('div', { style: state.kind === 'absent' ? S.muted : S.error }, state.message);\n return React.createElement(\n 'div',\n { style: S.card },\n status,\n React.createElement(\n 'div',\n { style: S.rows },\n SETTING_ROWS.map((row) =>\n React.createElement('div', { key: row.key }, `${row.title} · ${controlLabel(row.control)}`),\n ),\n ),\n React.createElement(VersionLine, null),\n );\n}\n\ninterface BetterSidebarService {\n registerTab(descriptor: {\n readonly id: string;\n readonly title: string | (() => string);\n readonly order?: number;\n readonly single?: boolean;\n readonly component: (props: unknown) => React.ReactElement | null;\n }): () => void;\n}\n\nexport function apply(ctx: ClientCtx): void {\n // 调用口取用器透传给组件(每次取数现取;非函数由组件判缺席)。\n const getCall: GetCall = () => ctx.connection?.rpc?.call ?? null;\n\n // (a) 技能设置页 → 爱生活页签槽(总管声明;总管缺席时 inject 等待,不断链)。\n ctx.slots.inject('ilife.config-tab', () =>\n ctx.slots.register(\n {\n name: 'ilife.config-tab',\n id: 'dsh-calorie',\n order: 75,\n label: () => SLOT_TITLE,\n },\n () => React.createElement(CalorieConfig, { getCall }),\n ),\n );\n\n // (b) 技能功能页 → sidebar槽(软依赖:betterSidebar 缺席即跳过)。\n const ensureWorkTab = (): boolean => {\n try {\n const get = ctx.get;\n const bs = (typeof get === 'function' ? get('betterSidebar') : undefined) as BetterSidebarService | undefined;\n if (!bs || typeof bs.registerTab !== 'function') return false;\n const dispose = bs.registerTab({\n id: 'ilife-calorie:work',\n title: '卡路里',\n order: 61,\n single: true,\n component: () => React.createElement(CalorieWork, { getCall }),\n });\n ctx.effect(() => () => {\n try {\n dispose();\n } catch {\n /* 卸载清理失败忽略 */\n }\n }, 'dsh-calorie: sidebar work tab');\n return true;\n } catch {\n return false;\n }\n };\n if (!ensureWorkTab()) {\n let tries = 0;\n const timer = setInterval(() => {\n tries++;\n if (ensureWorkTab() || tries >= 10) clearInterval(timer);\n }, 1000);\n ctx.effect(() => () => {\n clearInterval(timer);\n }, 'dsh-calorie: sidebar work tab retry');\n }\n}\n"],"mappings":"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"}
package/dist/dsh-ctx.d.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  *
3
3
  * 每条成员的用法出处见 docs/agents/dsh-client-contract.md(附源码路径+行)。
4
4
  * 禁止加镜外成员:要用新能力,先在 cookbook 落出处,再加镜像。用 `import type` 引用本文件。
5
+ * skills 面出处见 cookbook §12(#56 卡路里样板,badge 同形)。
5
6
  */
6
7
  export interface SlotsRegisterOptions {
7
8
  readonly name: string;
@@ -40,12 +41,58 @@ export interface ClientCtx {
40
41
  get?(name: string): unknown;
41
42
  }
42
43
  export type RpcHandler = (endpoint: string, payload: unknown, signal?: AbortSignal) => Promise<unknown>;
44
+ /** 打包技能提供方镜像(cookbook §12,badge 同形;type-only,零运行时)。
45
+ *
46
+ * 出处:`ctx.skills.registerProvider(create)`(`dsh-skill/lib/index.js:147`);
47
+ * candidate 校验红线见 `validateCandidate`(同文件 `:452`),`get` 回定义须与候选同名(同文件 `:259`)。
48
+ */
49
+ export interface SkillInvocationPolicy {
50
+ readonly modelInvocable: boolean;
51
+ readonly userInvocable: boolean;
52
+ }
53
+ export interface SkillCandidate {
54
+ readonly name: string;
55
+ readonly description: string;
56
+ readonly invocation: SkillInvocationPolicy;
57
+ readonly provider: string;
58
+ readonly source: string;
59
+ readonly rank: number;
60
+ readonly locator: unknown;
61
+ readonly resourceBase?: {
62
+ readonly kind: 'directory';
63
+ readonly path: string;
64
+ };
65
+ }
66
+ export interface SkillDefinition {
67
+ readonly name: string;
68
+ readonly description: string;
69
+ readonly invocation: SkillInvocationPolicy;
70
+ readonly provider: string;
71
+ readonly source: string;
72
+ readonly resourceBase?: {
73
+ readonly kind: 'directory';
74
+ readonly path: string;
75
+ };
76
+ readonly content: string;
77
+ }
78
+ export interface SkillProvider {
79
+ readonly name: string;
80
+ list(options?: unknown): Promise<readonly SkillCandidate[]>;
81
+ get(candidate: SkillCandidate, options?: unknown): Promise<SkillDefinition | undefined>;
82
+ }
83
+ export interface SkillsFace {
84
+ registerProvider(create: (control: {
85
+ readonly signal: AbortSignal;
86
+ invalidate(): void;
87
+ }) => SkillProvider): () => void;
88
+ }
43
89
  export interface HostCtx {
44
90
  readonly connection: {
45
91
  readonly rpc: {
46
92
  handle(channel: string, handler: RpcHandler): () => void;
47
93
  };
48
94
  };
95
+ readonly skills: SkillsFace;
49
96
  effect(callback: () => ((() => void) | void), label?: string): () => void;
50
97
  readonly logger?: unknown;
51
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dsh-ctx.d.ts","sourceRoot":"","sources":["../src/dsh-ctx.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC;IACrF,QAAQ,CAAC,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,IAAI,CAAC;CACzE;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC9C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAA;CAAE,CAAC;AAE3I,MAAM,WAAW,WAAW;IAC1B,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACrG;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,CAAC,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;SAAE,CAAA;KAAE,CAAC;IACxE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAC1E,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAExG,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,UAAU,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE;YAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,MAAM,IAAI,CAAA;SAAE,CAAA;KAAE,CAAC;IACpG,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAC1E,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B"}
1
+ {"version":3,"file":"dsh-ctx.d.ts","sourceRoot":"","sources":["../src/dsh-ctx.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export type { SlotDescriptor, TabsPort } from './slot.js';
7
7
  export { SETTINGS_OWNER, SETTINGS_SLOT, SETTING_ROWS } from './settings.js';
8
8
  export type { SettingRow } from './settings.js';
9
9
  export { SKILL_PACKAGE, SKILL_CLI, SKILL_CLI_REL, HOST_CALL_METHOD, MANAGER_MISSING_HINT, SkillBridgeError, cliPath, assertCliPresent, handleHostCall, requestViaHost, readViaCli } from './bridge.js';
10
+ export { PROVIDER_NAME, SKILL_NAME, BUNDLED_SKILL_RANK, SKILL_FILE, skillDir, skillFile, parseSkillText, provider as skillProvider } from './skill-provider.js';
10
11
  export { RPC_CHANNEL, RPC_ENDPOINT_READ, DEFAULT_READ_KEY, ok, fail, parseReadPayload } from './contract.js';
11
12
  export type { ReadPayload, RpcError, RpcResult } from './contract.js';
12
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,cAAc,CAAC;AAExD,eAAO,MAAM,IAAI,gBAAgB,CAAC;AAClC,eAAO,MAAM,MAAM,UAAiB,CAAC;AAqBrC,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAiBxC;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,YAAY,EAAE,MAAM,eAAe,CAAC;AAC5E,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvM,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC7G,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,cAAc,CAAC;AAGxD,eAAO,MAAM,IAAI,gBAAgB,CAAC;AAClC,eAAO,MAAM,MAAM,UAA2B,CAAC;AAqB/C,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAwBxC;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,YAAY,EAAE,MAAM,eAAe,CAAC;AAC5E,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvM,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAChK,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC7G,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -4,11 +4,14 @@
4
4
  * apply 真注册通道,取数只经 bridge.readViaCli(spawn 技能 CLI),
5
5
  * 从不 import 任何技能实现。
6
6
  * 单品硬依赖总管(dependencies,非 peer,见 package.json);设置页住本包。
7
+ * 打包技能提供方见 skill-provider.ts(badge 同形,#56):单份 SKILL.md 按包名解析,
8
+ * rank 内联 600,名用 skill-calorie;面板/桥行为不受其影响。
7
9
  */
8
10
  import { RPC_CHANNEL, RPC_ENDPOINT_READ, ok, fail, parseReadPayload } from './contract.js';
9
11
  import { SkillBridgeError, readViaCli } from './bridge.js';
12
+ import { PROVIDER_NAME, provider as skillProvider } from './skill-provider.js';
10
13
  export const name = 'dsh-calorie';
11
- export const inject = ['connection'];
14
+ export const inject = ['connection', 'skills'];
12
15
  /** RPC 处理函数:endpoint 分发 → 载荷校验 → readViaCli → 信封包装(companion rpc.ts 同形)。 */
13
16
  const handleCalorieRpc = async (endpoint, payload) => {
14
17
  if (endpoint !== RPC_ENDPOINT_READ)
@@ -30,6 +33,15 @@ export function apply(ctx) {
30
33
  const logger = (typeof loggerSource === 'function'
31
34
  ? loggerSource(name)
32
35
  : loggerSource) ?? console;
36
+ try {
37
+ ctx.skills.registerProvider(() => skillProvider);
38
+ }
39
+ catch (error) {
40
+ // 提供方是宿主按名去重的单例:重装配时上一实例可能已注册,此时退让(RPC 通道退让同形),他错重抛。
41
+ if (!String(error?.message ?? error).includes('already registered'))
42
+ throw error;
43
+ logger.warn?.('[dsh-calorie] skill provider ' + PROVIDER_NAME + ' already registered by another instance; yielding');
44
+ }
33
45
  try {
34
46
  const dispose = ctx.connection.rpc.handle(RPC_CHANNEL, handleCalorieRpc);
35
47
  ctx.effect(() => () => dispose(), 'dsh-calorie: rpc channel cleanup');
@@ -46,5 +58,6 @@ export function apply(ctx) {
46
58
  export { SKILL, SLOT_ID, SLOT_ORDER, SLOT_TITLE, PLUGIN, MANAGER_PLUGIN, slotDescriptor, TAB_COMPONENT, registerSingle, openSingle } from './slot.js';
47
59
  export { SETTINGS_OWNER, SETTINGS_SLOT, SETTING_ROWS } from './settings.js';
48
60
  export { SKILL_PACKAGE, SKILL_CLI, SKILL_CLI_REL, HOST_CALL_METHOD, MANAGER_MISSING_HINT, SkillBridgeError, cliPath, assertCliPresent, handleHostCall, requestViaHost, readViaCli } from './bridge.js';
61
+ export { PROVIDER_NAME, SKILL_NAME, BUNDLED_SKILL_RANK, SKILL_FILE, skillDir, skillFile, parseSkillText, provider as skillProvider } from './skill-provider.js';
49
62
  export { RPC_CHANNEL, RPC_ENDPOINT_READ, DEFAULT_READ_KEY, ok, fail, parseReadPayload } from './contract.js';
50
63
  //# 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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"}
@@ -0,0 +1,22 @@
1
+ import type { SkillProvider } from './dsh-ctx.js';
2
+ /** 注册表内的提供方名(bundling 插件;candidate.provider 须与此一致,否则校验抛)。 */
3
+ export declare const PROVIDER_NAME: "dsh-calorie";
4
+ /** 技能名(与 packages/skill-calorie/SKILL.md frontmatter `name` 同值)。 */
5
+ export declare const SKILL_NAME: "skill-calorie";
6
+ /** 打包技能标准优先级(与宿主 `BUNDLED_SKILL_RANK` 同值,内联,零依赖)。 */
7
+ export declare const BUNDLED_SKILL_RANK: 600;
8
+ export declare const SKILL_FILE: "SKILL.md";
9
+ /** 按包名定位技能包根目录(安装态 `node_modules/skill-calorie`,单仓 dev 态 workspace 链接)。 */
10
+ export declare function skillDir(): string;
11
+ export declare function skillFile(): string;
12
+ interface ParsedSkill {
13
+ readonly name: string;
14
+ readonly description: string;
15
+ readonly body: string;
16
+ }
17
+ /** 最小 frontmatter 解析(host 零依赖,不引 yaml;缺头/缺字段返回 null,由调用方按缺席记)。 */
18
+ export declare function parseSkillText(text: string): ParsedSkill | null;
19
+ /** badge 同形 provider(`list` 给摘要,`get` 给全文;`get` 忽略 locator 外的候选字段,只认名)。 */
20
+ export declare const provider: SkillProvider;
21
+ export {};
22
+ //# sourceMappingURL=skill-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-provider.d.ts","sourceRoot":"","sources":["../src/skill-provider.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAmC,aAAa,EAAE,MAAM,cAAc,CAAC;AAGnF,6DAA6D;AAC7D,eAAO,MAAM,aAAa,EAAG,aAAsB,CAAC;AAEpD,oEAAoE;AACpE,eAAO,MAAM,UAAU,EAAG,eAAwB,CAAC;AAEnD,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,EAAG,GAAY,CAAC;AAE/C,eAAO,MAAM,UAAU,EAAG,UAAmB,CAAC;AAE9C,2EAA2E;AAC3E,wBAAgB,QAAQ,IAAI,MAAM,CAGjC;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAqB/D;AAqDD,2EAA2E;AAC3E,eAAO,MAAM,QAAQ,EAAE,aAItB,CAAC"}
@@ -0,0 +1,123 @@
1
+ /** dsh-calorie 打包技能提供方(#56 卡路里样板,badge 同形)。
2
+ *
3
+ * 形态对照 `dsh-skill-badge`(出处见 docs/agents/dsh-client-contract.md §12):
4
+ * cordis 侧 `inject` 加 `skills`(见 index.ts),本文件只提供 provider 对象,
5
+ * 由 `apply` 经 `ctx.skills.registerProvider(() => provider)` 注册。
6
+ *
7
+ * 单份 SKILL.md 按包名解析(`createRequire.resolve('skill-calorie/package.json')`
8
+ * 再拼 `SKILL.md`,不复制,避 R2 修法②双份腐化;不走 `exports` 子路径,
9
+ * 免补 `./SKILL.md` 导出);`name` 用 `skill-calorie`(与 SKILL.md frontmatter 同值,
10
+ * 描述取文件实测值,不在插件内硬编码第二份);`rank` 内联 600(`BUNDLED_SKILL_RANK`,
11
+ * 不从宿主 import,保持零依赖);`source` 为 `bundled`;`content` 取 frontmatter
12
+ * 后正文(filesystem `parseSkillFile` 同形;badge 无 frontmatter 才整文返回,不照抄)。
13
+ *
14
+ * 本文件只读消费技能包的 SKILL.md(文本),从不 import 任何技能实现。
15
+ */
16
+ import { readFile } from 'node:fs/promises';
17
+ import { createRequire } from 'node:module';
18
+ import { dirname, join } from 'node:path';
19
+ import { SKILL_PACKAGE } from './bridge.js';
20
+ /** 注册表内的提供方名(bundling 插件;candidate.provider 须与此一致,否则校验抛)。 */
21
+ export const PROVIDER_NAME = 'dsh-calorie';
22
+ /** 技能名(与 packages/skill-calorie/SKILL.md frontmatter `name` 同值)。 */
23
+ export const SKILL_NAME = 'skill-calorie';
24
+ /** 打包技能标准优先级(与宿主 `BUNDLED_SKILL_RANK` 同值,内联,零依赖)。 */
25
+ export const BUNDLED_SKILL_RANK = 600;
26
+ export const SKILL_FILE = 'SKILL.md';
27
+ /** 按包名定位技能包根目录(安装态 `node_modules/skill-calorie`,单仓 dev 态 workspace 链接)。 */
28
+ export function skillDir() {
29
+ const pkgJson = createRequire(import.meta.url).resolve(SKILL_PACKAGE + '/package.json');
30
+ return dirname(pkgJson);
31
+ }
32
+ export function skillFile() {
33
+ return join(skillDir(), SKILL_FILE);
34
+ }
35
+ /** 最小 frontmatter 解析(host 零依赖,不引 yaml;缺头/缺字段返回 null,由调用方按缺席记)。 */
36
+ export function parseSkillText(text) {
37
+ const normalized = text.replace(/\r\n/g, '\n');
38
+ if (!normalized.startsWith('---\n'))
39
+ return null;
40
+ const lines = normalized.split('\n');
41
+ const end = lines.indexOf('---', 1);
42
+ if (end < 2)
43
+ return null;
44
+ const data = {};
45
+ for (const ln of lines.slice(1, end)) {
46
+ const m = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(ln);
47
+ if (!m)
48
+ return null;
49
+ let v = (m[2] ?? '').trim();
50
+ if (v.length >= 2 && ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'")))) {
51
+ v = v.slice(1, -1);
52
+ }
53
+ data[m[1]] = v;
54
+ }
55
+ const name = data['name'];
56
+ const description = data['description'];
57
+ if (!name || !description)
58
+ return null;
59
+ if (!/^[\p{L}0-9]+(?:-[\p{L}0-9]+)*$/u.test(name))
60
+ return null;
61
+ return { name, description, body: lines.slice(end + 1).join('\n').trim() };
62
+ }
63
+ async function loadSkill() {
64
+ let dir;
65
+ try {
66
+ dir = skillDir();
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ let raw;
72
+ try {
73
+ raw = await readFile(join(dir, SKILL_FILE), 'utf8');
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ const parsed = parseSkillText(raw);
79
+ if (!parsed)
80
+ return null;
81
+ return { dir, parsed };
82
+ }
83
+ async function listSkills() {
84
+ const loaded = await loadSkill();
85
+ if (!loaded)
86
+ return [];
87
+ return [
88
+ {
89
+ name: loaded.parsed.name,
90
+ description: loaded.parsed.description,
91
+ invocation: { modelInvocable: true, userInvocable: true },
92
+ provider: PROVIDER_NAME,
93
+ source: 'bundled',
94
+ resourceBase: { kind: 'directory', path: loaded.dir },
95
+ rank: BUNDLED_SKILL_RANK,
96
+ locator: { path: join(loaded.dir, SKILL_FILE) },
97
+ },
98
+ ];
99
+ }
100
+ async function getSkill(candidate) {
101
+ const loaded = await loadSkill();
102
+ if (!loaded)
103
+ return undefined;
104
+ // 候选过期(注册后 SKILL.md 改名)按宿主契约失效,不抛。
105
+ if (!candidate || candidate.name !== loaded.parsed.name)
106
+ return undefined;
107
+ return {
108
+ name: loaded.parsed.name,
109
+ description: loaded.parsed.description,
110
+ invocation: { modelInvocable: true, userInvocable: true },
111
+ provider: PROVIDER_NAME,
112
+ source: 'bundled',
113
+ resourceBase: { kind: 'directory', path: loaded.dir },
114
+ content: loaded.parsed.body,
115
+ };
116
+ }
117
+ /** badge 同形 provider(`list` 给摘要,`get` 给全文;`get` 忽略 locator 外的候选字段,只认名)。 */
118
+ export const provider = {
119
+ name: PROVIDER_NAME,
120
+ list: () => listSkills(),
121
+ get: (candidate) => getSkill(candidate),
122
+ };
123
+ //# sourceMappingURL=skill-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-provider.js","sourceRoot":"","sources":["../src/skill-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,6DAA6D;AAC7D,MAAM,CAAC,MAAM,aAAa,GAAG,aAAsB,CAAC;AAEpD,oEAAoE;AACpE,MAAM,CAAC,MAAM,UAAU,GAAG,eAAwB,CAAC;AAEnD,qDAAqD;AACrD,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAY,CAAC;AAE/C,MAAM,CAAC,MAAM,UAAU,GAAG,UAAmB,CAAC;AAE9C,2EAA2E;AAC3E,MAAM,UAAU,QAAQ;IACtB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,aAAa,GAAG,eAAe,CAAC,CAAC;IACxF,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,IAAI,CAAC,QAAQ,EAAE,EAAE,UAAU,CAAC,CAAC;AACtC,CAAC;AAQD,kEAAkE;AAClE,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC/C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACpC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,4BAA4B,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACpB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACxG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,CAAC,CAAW,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;IACxC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IACvC,IAAI,CAAC,iCAAiC,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/D,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;AAC7E,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,QAAQ,EAAE,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACzB,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;IACjC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAO;QACL;YACE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;YACxB,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;YACtC,UAAU,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;YACzD,QAAQ,EAAE,aAAa;YACvB,MAAM,EAAE,SAAS;YACjB,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE;YACrD,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE;SAChD;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,SAAyB;IAC/C,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;IACjC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,mCAAmC;IACnC,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC1E,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;QACxB,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;QACtC,UAAU,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;QACzD,QAAQ,EAAE,aAAa;QACvB,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE;QACrD,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;KAC5B,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,QAAQ,GAAkB;IACrC,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;IACxB,GAAG,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;CACxC,CAAC"}
package/dist/slot.d.ts CHANGED
@@ -14,8 +14,8 @@ export declare const MANAGER_PLUGIN: "dsh-life-pack";
14
14
  export declare const SKILL_PACKAGE: "skill-calorie";
15
15
  /** 版本行唯一来源(面板展示用;smoke 断言与两处 package.json 一致,防漂移)。
16
16
  * 发版 bump 时同步改这里(与 package.json 同值)。 */
17
- export declare const PLUGIN_VERSION: "0.1.6";
18
- export declare const SKILL_VERSION: "0.1.1";
17
+ export declare const PLUGIN_VERSION: "0.2.0";
18
+ export declare const SKILL_VERSION: "0.2.0";
19
19
  export interface SlotDescriptor {
20
20
  readonly skill: string;
21
21
  readonly slotId: string;
package/dist/slot.js CHANGED
@@ -14,8 +14,8 @@ export const MANAGER_PLUGIN = 'dsh-life-pack';
14
14
  export const SKILL_PACKAGE = 'skill-calorie';
15
15
  /** 版本行唯一来源(面板展示用;smoke 断言与两处 package.json 一致,防漂移)。
16
16
  * 发版 bump 时同步改这里(与 package.json 同值)。 */
17
- export const PLUGIN_VERSION = '0.1.6';
18
- export const SKILL_VERSION = '0.1.1';
17
+ export const PLUGIN_VERSION = '0.2.0';
18
+ export const SKILL_VERSION = '0.2.0';
19
19
  export function slotDescriptor() {
20
20
  return { skill: SKILL, slotId: SLOT_ID, order: SLOT_ORDER, title: SLOT_TITLE, kind: 'page' };
21
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-calorie",
3
- "version": "0.1.6",
3
+ "version": "0.2.1",
4
4
  "description": "爱生活单品插件 P10 脚手架:卡路里(ilife:calorie order 75),硬依赖总管 dsh-life-pack",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,8 +25,8 @@
25
25
  "node": ">=22.13"
26
26
  },
27
27
  "dependencies": {
28
- "dsh-life-pack": "^0.1.0",
29
- "skill-calorie": "^0.1.0"
28
+ "dsh-life-pack": "^0.2.0",
29
+ "skill-calorie": "^0.2.0"
30
30
  },
31
31
  "dsh": {
32
32
  "bundle": {
package/dist/client.d.ts DELETED
@@ -1,19 +0,0 @@
1
- /** dsh-calorie 客户端存根(P10 脚手架)。
2
- *
3
- * 写死槽位原生组件,不做动态按需加载,不做外嵌页。
4
- * 面板取数只经 host.call 进 host 桥(见 bridge.ts),不 import 技能实现。
5
- * 缺席纯条件渲染,无轮询(本文件无任何定时器)。
6
- */
7
- import type { TabsPort } from './slot.js';
8
- export interface HostCaller {
9
- call(method: string, args: unknown): Promise<unknown>;
10
- }
11
- export declare const CLIENT_COMPONENT: {
12
- readonly kind: "native";
13
- readonly name: "CaloriePanel";
14
- };
15
- export declare const CLIENT_METHOD: "ilife.calorie.read";
16
- export declare function mountSingleClient(port: TabsPort): (() => void) | null;
17
- export declare function openSingleClient(port: TabsPort, sessionId?: string): void;
18
- export declare function requestReadViaHost(host: HostCaller, key: string, params?: Record<string, unknown>): Promise<unknown>;
19
- //# sourceMappingURL=client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvD;AAED,eAAO,MAAM,gBAAgB;;;CAAgB,CAAC;AAC9C,eAAO,MAAM,aAAa,sBAAmB,CAAC;AAE9C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAErE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAEzE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAExH"}