dsh-feishu-notifier 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/client.js.map +1 -1
- package/lib/index.js +4 -4
- package/package.json +16 -17
package/README.md
CHANGED
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["useState","Button"],"sources":["../src/client/FeishuSettingsSection.tsx","../src/client/index.ts"],"sourcesContent":["import { useEffect, useState } from 'react'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport { Button } from '@deepseek-ai/dsh-client-ui-primitives'\n\nexport interface FeishuConfigView {\n enabled: boolean\n webhookConfigured: boolean\n}\n\nexport interface FeishuController {\n config?: FeishuConfigView\n load: () => Promise<FeishuConfigView>\n update: (patch: { enabled?: boolean; webhook?: string }) => Promise<FeishuConfigView>\n test: () => Promise<string>\n}\n\ntype Props = PropsRuntime<'settings.section'> & { controller: FeishuController }\n\ntype ViewState =\n | { status: 'loading' }\n | { status: 'ready'; config: FeishuConfigView }\n\nexport function FeishuSettingsSection({ controller }: Props) {\n const [view, setView] = useState<ViewState>({ status: 'loading' })\n const [webhook, setWebhook] = useState('')\n const [busy, setBusy] = useState(false)\n const [status, setStatus] = useState('')\n\n useEffect(() => {\n let active = true\n void controller.load()\n .then(config => {\n if (active) setView({ status: 'ready', config })\n })\n .catch(error => {\n if (active) setStatus(error instanceof Error ? error.message : String(error))\n })\n return () => { active = false }\n }, [controller])\n\n const config = view.status === 'ready' ? view.config : { enabled: true, webhookConfigured: false }\n\n const save = async (patch: { enabled?: boolean; webhook?: string }, message: string) => {\n setBusy(true)\n setStatus('正在保存…')\n try {\n const next = await controller.update(patch)\n setView({ status: 'ready', config: next })\n setStatus(message)\n } catch (error) {\n setStatus(error instanceof Error ? error.message : String(error))\n } finally {\n setBusy(false)\n }\n }\n\n const saveWebhook = async () => {\n const value = webhook.trim()\n if (value === '') {\n setStatus('请输入 Webhook 地址')\n return\n }\n await save({ webhook: value }, 'Webhook 已保存到 DSH 设置文件')\n setWebhook('')\n }\n\n const sendTest = async () => {\n setBusy(true)\n setStatus('正在发送测试消息…')\n try {\n setStatus(await controller.test())\n } catch (error) {\n setStatus(error instanceof Error ? error.message : String(error))\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <section style={{ maxWidth: 680, display: 'grid', gap: 24 }}>\n <div>\n <h2 style={{ margin: 0, fontSize: 24 }}>飞书通知</h2>\n <p style={{ color: 'var(--dsw-alias-label-secondary)', lineHeight: 1.6 }}>\n 当智能体等待你的批准、需要回答问题,或一轮对话结束时,向飞书机器人发送提醒。\n </p>\n </div>\n <div style={{ display: 'grid', gap: 16, padding: 20, border: '1px solid var(--dsw-alias-border-l1)', borderRadius: 16 }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16 }}>\n <span>\n <strong style={{ display: 'block' }}>启用通知</strong>\n <small style={{ color: 'var(--dsw-alias-label-secondary)' }}>关闭后不会发送任何飞书消息。</small>\n </span>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={config.enabled}\n aria-label=\"启用通知\"\n disabled={busy || view.status === 'loading'}\n onClick={() => { void save({ enabled: !config.enabled }, !config.enabled ? '通知已开启' : '通知已关闭') }}\n style={{\n position: 'relative',\n width: 44,\n height: 26,\n padding: 2,\n borderRadius: 999,\n border: '1px solid var(--dsw-alias-border-l1)',\n background: config.enabled ? 'var(--dsw-alias-bg-accent, #165DFF)' : 'var(--dsw-alias-bg-layer-3, #e5e7eb)',\n cursor: busy || view.status === 'loading' ? 'not-allowed' : 'pointer',\n opacity: busy || view.status === 'loading' ? 0.6 : 1,\n transition: 'background 150ms ease, opacity 150ms ease',\n flexShrink: 0,\n }}\n >\n <span\n aria-hidden\n style={{\n display: 'block',\n width: 20,\n height: 20,\n borderRadius: 999,\n background: '#fff',\n boxShadow: '0 1px 3px rgba(0,0,0,0.2)',\n transform: config.enabled ? 'translateX(18px)' : 'translateX(0)',\n transition: 'transform 150ms ease',\n }}\n />\n </button>\n </div>\n <label style={{ display: 'grid', gap: 8 }}>\n <span><strong>Webhook 地址</strong></span>\n <input\n aria-label=\"Webhook 地址\"\n type=\"url\"\n value={webhook}\n placeholder={config.webhookConfigured ? '已配置地址;输入新地址以替换' : '请输入飞书机器人 Webhook'}\n disabled={busy || view.status === 'loading'}\n onChange={event => { setWebhook(event.target.value); setStatus('') }}\n style={{ minHeight: 40, padding: '0 12px', borderRadius: 10, border: '1px solid var(--dsw-alias-border-l1)', background: 'var(--dsw-alias-bg-layer-1)', color: 'inherit' }}\n />\n </label>\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>\n <Button variant=\"primary\" size=\"sm\" disabled={busy || view.status === 'loading'} onClick={() => { void saveWebhook() }}>保存 Webhook</Button>\n <Button variant=\"outline\" size=\"sm\" disabled={busy || view.status === 'loading' || !config.webhookConfigured} onClick={() => { void sendTest() }}>发送测试消息</Button>\n </div>\n {status !== '' && <p role=\"status\" style={{ margin: 0, color: 'var(--dsw-alias-label-secondary)' }}>{status}</p>}\n </div>\n </section>\n )\n}\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport { FeishuSettingsSection, type FeishuController } from './FeishuSettingsSection.tsx'\n\nexport const inject = ['slots']\n\nexport function apply(ctx: ClientContext): void {\n const controller: FeishuController = {\n load: async () => {\n const response = await fetch('/api/feishu-notifier/config')\n const result = await response.json() as { ok?: boolean; message?: string; config?: FeishuController['config'] }\n if (!response.ok || result.ok !== true || result.config === undefined) {\n throw new Error(result.message ?? `HTTP ${String(response.status)}`)\n }\n return result.config\n },\n update: async (patch) => {\n const response = await fetch('/api/feishu-notifier/config', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(patch),\n })\n const result = await response.json() as { ok?: boolean; message?: string; config?: FeishuController['config'] }\n if (!response.ok || result.ok !== true || result.config === undefined) {\n throw new Error(result.message ?? `HTTP ${String(response.status)}`)\n }\n return result.config\n },\n test: async () => {\n const response = await fetch('/api/feishu-notifier/test', { method: 'POST' })\n const result = await response.json() as { ok?: boolean; message?: string }\n if (!response.ok || result.ok !== true) throw new Error(result.message ?? `HTTP ${String(response.status)}`)\n return result.message ?? '测试消息已发送'\n },\n }\n\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'feishu-notifier',\n order: 25,\n label: () => '飞书通知',\n inject: (): { controller: FeishuController } => ({ controller }),\n }, FeishuSettingsSection))\n}\n"],"mappings":";;;;;;;;;;EAsBA,SAAgB,sBAAsB,EAAE,cAAqB;GAC3D,MAAM,CAAC,MAAM,YAAA,GAAWA,MAAAA,SAAAA,CAAoB,EAAE,QAAQ,UAAU,CAAC;GACjE,MAAM,CAAC,SAAS,eAAA,GAAcA,MAAAA,SAAAA,CAAS,EAAE;GACzC,MAAM,CAAC,MAAM,YAAA,GAAWA,MAAAA,SAAAA,CAAS,KAAK;GACtC,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAAS,EAAE;GAEvC,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,SAAS;IACb,WAAgB,KAAK,CAAC,CACnB,MAAK,WAAU;KACd,IAAI,QAAQ,QAAQ;MAAE,QAAQ;MAAS;KAAO,CAAC;IACjD,CAAC,CAAC,CACD,OAAM,UAAS;KACd,IAAI,QAAQ,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;IAC9E,CAAC;IACH,aAAa;KAAE,SAAS;IAAM;GAChC,GAAG,CAAC,UAAU,CAAC;GAEf,MAAM,SAAS,KAAK,WAAW,UAAU,KAAK,SAAS;IAAE,SAAS;IAAM,mBAAmB;GAAM;GAEjG,MAAM,OAAO,OAAO,OAAgD,YAAoB;IACtF,QAAQ,IAAI;IACZ,UAAU,OAAO;IACjB,IAAI;KACF,MAAM,OAAO,MAAM,WAAW,OAAO,KAAK;KAC1C,QAAQ;MAAE,QAAQ;MAAS,QAAQ;KAAK,CAAC;KACzC,UAAU,OAAO;IACnB,SAAS,OAAO;KACd,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;IAClE,UAAU;KACR,QAAQ,KAAK;IACf;GACF;GAEA,MAAM,cAAc,YAAY;IAC9B,MAAM,QAAQ,QAAQ,KAAK;IAC3B,IAAI,UAAU,IAAI;KAChB,UAAU,gBAAgB;KAC1B;IACF;IACA,MAAM,KAAK,EAAE,SAAS,MAAM,GAAG,uBAAuB;IACtD,WAAW,EAAE;GACf;GAEA,MAAM,WAAW,YAAY;IAC3B,QAAQ,IAAI;IACZ,UAAU,WAAW;IACrB,IAAI;KACF,UAAU,MAAM,WAAW,KAAK,CAAC;IACnC,SAAS,OAAO;KACd,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;IAClE,UAAU;KACR,QAAQ,KAAK;IACf;GACF;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD;IAAS,OAAO;KAAE,UAAU;KAAK,SAAS;KAAQ,KAAK;IAAG;IAA1D,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;KAAI,OAAO;MAAE,QAAQ;MAAG,UAAU;KAAG;KAAG,UAAA;IAAQ,CAAA,GAChD,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;KAAG,OAAO;MAAE,OAAO;MAAoC,YAAY;KAAI;KAAG,UAAA;IAEvE,CAAA,CACA,EAAA,CAAA,GACL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,KAAK;MAAI,SAAS;MAAI,QAAQ;MAAwC,cAAc;KAAG;KAAtH,UAAA;MACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,OAAO;QAAE,SAAS;QAAQ,YAAY;QAAU,gBAAgB;QAAiB,KAAK;OAAG;OAA9F,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,OAAO,EAAE,SAAS,QAAQ;QAAG,UAAA;OAAY,CAAA,GACjD,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;QAAO,OAAO,EAAE,OAAO,mCAAmC;QAAG,UAAA;OAAqB,CAAA,CAC9E,EAAA,CAAA,GACN,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QACE,MAAK;QACL,MAAK;QACL,gBAAc,OAAO;QACrB,cAAW;QACX,UAAU,QAAQ,KAAK,WAAW;QAClC,eAAe;SAAE,KAAU,EAAE,SAAS,CAAC,OAAO,QAAQ,GAAG,CAAC,OAAO,UAAU,UAAU,OAAO;QAAE;QAC9F,OAAO;SACL,UAAU;SACV,OAAO;SACP,QAAQ;SACR,SAAS;SACT,cAAc;SACd,QAAQ;SACR,YAAY,OAAO,UAAU,wCAAwC;SACrE,QAAQ,QAAQ,KAAK,WAAW,YAAY,gBAAgB;SAC5D,SAAS,QAAQ,KAAK,WAAW,YAAY,KAAM;SACnD,YAAY;SACZ,YAAY;QACd;QAEA,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;SACE,eAAA;SACA,OAAO;UACL,SAAS;UACT,OAAO;UACP,QAAQ;UACR,cAAc;UACd,YAAY;UACZ,WAAW;UACX,WAAW,OAAO,UAAU,qBAAqB;UACjD,YAAY;SACd;QACD,CAAA;OACK,CAAA,CACL;;MACL,iBAAA,GAAA,kBAAA,KAAA,CAAC,SAAD;OAAO,OAAO;QAAE,SAAS;QAAQ,KAAK;OAAE;OAAxC,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAM,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD,EAAA,UAAQ,aAAkB,CAAA,EAAO,CAAA,GACvC,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;QACE,cAAW;QACX,MAAK;QACL,OAAO;QACP,aAAa,OAAO,oBAAoB,mBAAmB;QAC3D,UAAU,QAAQ,KAAK,WAAW;QAClC,WAAU,UAAS;SAAE,WAAW,MAAM,OAAO,KAAK;SAAG,UAAU,EAAE;QAAE;QACnE,OAAO;SAAE,WAAW;SAAI,SAAS;SAAU,cAAc;SAAI,QAAQ;SAAwC,YAAY;SAA+B,OAAO;QAAU;OAC1K,CAAA,CACI;;MACP,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,OAAO;QAAE,SAAS;QAAQ,UAAU;QAAQ,KAAK;OAAG;OAAzD,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,sCAAAA,QAAD;QAAQ,SAAQ;QAAU,MAAK;QAAK,UAAU,QAAQ,KAAK,WAAW;QAAW,eAAe;SAAE,YAAiB;QAAE;QAAG,UAAA;OAAkB,CAAA,GAC1I,iBAAA,GAAA,kBAAA,IAAA,CAACA,sCAAAA,QAAD;QAAQ,SAAQ;QAAU,MAAK;QAAK,UAAU,QAAQ,KAAK,WAAW,aAAa,CAAC,OAAO;QAAmB,eAAe;SAAE,SAAc;QAAE;QAAG,UAAA;OAAc,CAAA,CAC7J;;MACJ,WAAW,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,MAAK;OAAS,OAAO;QAAE,QAAQ;QAAG,OAAO;OAAmC;OAAI,UAAA;MAAU,CAAA;KAC5G;IACE,CAAA,CAAA;;EAEb;;;EC/IA,MAAa,SAAS,CAAC,OAAO;EAE9B,SAAgB,MAAM,KAA0B;GAC9C,MAAM,aAA+B;IACnC,MAAM,YAAY;KAChB,MAAM,WAAW,MAAM,MAAM,6BAA6B;KAC1D,MAAM,SAAS,MAAM,SAAS,KAAK;KACnC,IAAI,CAAC,SAAS,MAAM,OAAO,OAAO,QAAQ,OAAO,WAAW,KAAA,GAC1D,MAAM,IAAI,MAAM,OAAO,WAAW,QAAQ,OAAO,SAAS,MAAM,GAAG;KAErE,OAAO,OAAO;IAChB;IACA,QAAQ,OAAO,UAAU;KACvB,MAAM,WAAW,MAAM,MAAM,+BAA+B;MAC1D,QAAQ;MACR,SAAS,EAAE,gBAAgB,mBAAmB;MAC9C,MAAM,KAAK,UAAU,KAAK;KAC5B,CAAC;KACD,MAAM,SAAS,MAAM,SAAS,KAAK;KACnC,IAAI,CAAC,SAAS,MAAM,OAAO,OAAO,QAAQ,OAAO,WAAW,KAAA,GAC1D,MAAM,IAAI,MAAM,OAAO,WAAW,QAAQ,OAAO,SAAS,MAAM,GAAG;KAErE,OAAO,OAAO;IAChB;IACA,MAAM,YAAY;KAChB,MAAM,WAAW,MAAM,MAAM,6BAA6B,EAAE,QAAQ,OAAO,CAAC;KAC5E,MAAM,SAAS,MAAM,SAAS,KAAK;KACnC,IAAI,CAAC,SAAS,MAAM,OAAO,OAAO,MAAM,MAAM,IAAI,MAAM,OAAO,WAAW,QAAQ,OAAO,SAAS,MAAM,GAAG;KAC3G,OAAO,OAAO,WAAW;IAC3B;GACF;GAEA,IAAI,MAAM,OAAO,0BAA0B,IAAI,MAAM,SAAS;IAC5D,MAAM;IACN,IAAI;IACJ,OAAO;IACP,aAAa;IACb,eAAiD,EAAE,WAAW;GAChE,GAAG,qBAAqB,CAAC;EAC3B"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["useState","Button"],"sources":["../src/client/FeishuSettingsSection.tsx","../src/client/index.ts"],"sourcesContent":["import { useEffect, useState } from 'react'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport { Button } from '@deepseek-ai/dsh-client-ui-primitives'\n\nexport interface FeishuConfigView {\n enabled: boolean\n webhookConfigured: boolean\n}\n\nexport interface FeishuController {\n config?: FeishuConfigView\n load: () => Promise<FeishuConfigView>\n update: (patch: { enabled?: boolean; webhook?: string }) => Promise<FeishuConfigView>\n test: () => Promise<string>\n}\n\ntype Props = PropsRuntime<'settings.section'> & { controller: FeishuController }\n\ntype ViewState =\n | { status: 'loading' }\n | { status: 'ready'; config: FeishuConfigView }\n\nexport function FeishuSettingsSection({ controller }: Props) {\n const [view, setView] = useState<ViewState>({ status: 'loading' })\n const [webhook, setWebhook] = useState('')\n const [busy, setBusy] = useState(false)\n const [status, setStatus] = useState('')\n\n useEffect(() => {\n let active = true\n void controller.load()\n .then(config => {\n if (active) setView({ status: 'ready', config })\n })\n .catch(error => {\n if (active) setStatus(error instanceof Error ? error.message : String(error))\n })\n return () => { active = false }\n }, [controller])\n\n const config = view.status === 'ready' ? view.config : { enabled: true, webhookConfigured: false }\n\n const save = async (patch: { enabled?: boolean; webhook?: string }, message: string) => {\n setBusy(true)\n setStatus('正在保存…')\n try {\n const next = await controller.update(patch)\n setView({ status: 'ready', config: next })\n setStatus(message)\n } catch (error) {\n setStatus(error instanceof Error ? error.message : String(error))\n } finally {\n setBusy(false)\n }\n }\n\n const saveWebhook = async () => {\n const value = webhook.trim()\n if (value === '') {\n setStatus('请输入 Webhook 地址')\n return\n }\n await save({ webhook: value }, 'Webhook 已保存到 DSH 设置文件')\n setWebhook('')\n }\n\n const sendTest = async () => {\n setBusy(true)\n setStatus('正在发送测试消息…')\n try {\n setStatus(await controller.test())\n } catch (error) {\n setStatus(error instanceof Error ? error.message : String(error))\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <section style={{ maxWidth: 680, display: 'grid', gap: 24 }}>\n <div>\n <h2 style={{ margin: 0, fontSize: 24 }}>飞书通知</h2>\n <p style={{ color: 'var(--dsw-alias-label-secondary)', lineHeight: 1.6 }}>\n 当智能体等待你的批准、需要回答问题,或一轮对话结束时,向飞书机器人发送提醒。\n </p>\n </div>\n <div style={{ display: 'grid', gap: 16, padding: 20, border: '1px solid var(--dsw-alias-border-l1)', borderRadius: 16 }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16 }}>\n <span>\n <strong style={{ display: 'block' }}>启用通知</strong>\n <small style={{ color: 'var(--dsw-alias-label-secondary)' }}>关闭后不会发送任何飞书消息。</small>\n </span>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={config.enabled}\n aria-label=\"启用通知\"\n disabled={busy || view.status === 'loading'}\n onClick={() => { void save({ enabled: !config.enabled }, !config.enabled ? '通知已开启' : '通知已关闭') }}\n style={{\n position: 'relative',\n width: 44,\n height: 26,\n padding: 2,\n borderRadius: 999,\n border: '1px solid var(--dsw-alias-border-l1)',\n background: config.enabled ? 'var(--dsw-alias-bg-accent, #165DFF)' : 'var(--dsw-alias-bg-layer-3, #e5e7eb)',\n cursor: busy || view.status === 'loading' ? 'not-allowed' : 'pointer',\n opacity: busy || view.status === 'loading' ? 0.6 : 1,\n transition: 'background 150ms ease, opacity 150ms ease',\n flexShrink: 0,\n }}\n >\n <span\n aria-hidden\n style={{\n display: 'block',\n width: 20,\n height: 20,\n borderRadius: 999,\n background: '#fff',\n boxShadow: '0 1px 3px rgba(0,0,0,0.2)',\n transform: config.enabled ? 'translateX(18px)' : 'translateX(0)',\n transition: 'transform 150ms ease',\n }}\n />\n </button>\n </div>\n <label style={{ display: 'grid', gap: 8 }}>\n <span><strong>Webhook 地址</strong></span>\n <input\n aria-label=\"Webhook 地址\"\n type=\"url\"\n value={webhook}\n placeholder={config.webhookConfigured ? '已配置地址;输入新地址以替换' : '请输入飞书机器人 Webhook'}\n disabled={busy || view.status === 'loading'}\n onChange={event => { setWebhook(event.target.value); setStatus('') }}\n style={{ minHeight: 40, padding: '0 12px', borderRadius: 10, border: '1px solid var(--dsw-alias-border-l1)', background: 'var(--dsw-alias-bg-layer-1)', color: 'inherit' }}\n />\n </label>\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>\n <Button variant=\"primary\" size=\"sm\" disabled={busy || view.status === 'loading'} onClick={() => { void saveWebhook() }}>保存 Webhook</Button>\n <Button variant=\"outline\" size=\"sm\" disabled={busy || view.status === 'loading' || !config.webhookConfigured} onClick={() => { void sendTest() }}>发送测试消息</Button>\n </div>\n {status !== '' && <p role=\"status\" style={{ margin: 0, color: 'var(--dsw-alias-label-secondary)' }}>{status}</p>}\n </div>\n </section>\n )\n}\n","import type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport { FeishuSettingsSection, type FeishuController } from './FeishuSettingsSection.tsx'\n\nexport const inject = ['slots']\n\nexport function apply(ctx: ClientContext): void {\n const controller: FeishuController = {\n load: async () => {\n const response = await fetch('/api/feishu-notifier/config')\n const result = await response.json() as { ok?: boolean; message?: string; config?: FeishuController['config'] }\n if (!response.ok || result.ok !== true || result.config === undefined) {\n throw new Error(result.message ?? `HTTP ${String(response.status)}`)\n }\n return result.config\n },\n update: async (patch) => {\n const response = await fetch('/api/feishu-notifier/config', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(patch),\n })\n const result = await response.json() as { ok?: boolean; message?: string; config?: FeishuController['config'] }\n if (!response.ok || result.ok !== true || result.config === undefined) {\n throw new Error(result.message ?? `HTTP ${String(response.status)}`)\n }\n return result.config\n },\n test: async () => {\n const response = await fetch('/api/feishu-notifier/test', { method: 'POST' })\n const result = await response.json() as { ok?: boolean; message?: string }\n if (!response.ok || result.ok !== true) throw new Error(result.message ?? `HTTP ${String(response.status)}`)\n return result.message ?? '测试消息已发送'\n },\n }\n\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'feishu-notifier',\n order: 25,\n label: () => '飞书通知',\n inject: (): { controller: FeishuController } => ({ controller }),\n }, FeishuSettingsSection))\n}\n"],"mappings":"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"}
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import z from "@deepseek-ai/schemastery";
|
|
2
|
-
import { settingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
3
2
|
//#region src/index.ts
|
|
4
3
|
const name = "dsh-feishu-notifier";
|
|
5
4
|
const inject = ["settings", "webServer"];
|
|
@@ -7,7 +6,7 @@ const Config = z.object({
|
|
|
7
6
|
enabled: z.boolean().default(true),
|
|
8
7
|
webhook: z.string().role("secret").default("")
|
|
9
8
|
});
|
|
10
|
-
const SETTINGS_NAMESPACE =
|
|
9
|
+
const SETTINGS_NAMESPACE = "feishu-notifier";
|
|
11
10
|
const CONFIG_PATH = "/api/feishu-notifier/config";
|
|
12
11
|
const TEST_PATH = "/api/feishu-notifier/test";
|
|
13
12
|
function textFor(kind, detail) {
|
|
@@ -18,7 +17,8 @@ function recordOf(value) {
|
|
|
18
17
|
}
|
|
19
18
|
function turnReasonText(reason) {
|
|
20
19
|
const value = recordOf(reason);
|
|
21
|
-
|
|
20
|
+
if (value === void 0) return typeof reason === "string" ? reason : "结束原因未知";
|
|
21
|
+
switch (typeof value.kind === "string" ? value.kind : void 0) {
|
|
22
22
|
case "completed": return "正常完成";
|
|
23
23
|
case "blocked": return "被策略阻止";
|
|
24
24
|
case "max-tokens": return "达到最大 token 限制";
|
|
@@ -33,7 +33,7 @@ function turnReasonText(reason) {
|
|
|
33
33
|
if (typeof cause?.kind === "string") return `已中止(${cause.kind})`;
|
|
34
34
|
return "已中止";
|
|
35
35
|
}
|
|
36
|
-
default: return
|
|
36
|
+
default: return "结束原因未知";
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
function configView(config) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-feishu-notifier",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Send DeepSeek Harness interaction and turn notifications to a Feishu bot",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -41,34 +41,33 @@
|
|
|
41
41
|
"client": {
|
|
42
42
|
"platform": "web",
|
|
43
43
|
"inject": [
|
|
44
|
-
"@deepseek-ai/dsh-client-runtime",
|
|
45
44
|
"@deepseek-ai/dsh-client-ui-settings"
|
|
46
45
|
]
|
|
47
46
|
}
|
|
48
47
|
},
|
|
49
48
|
"scripts": {
|
|
50
|
-
"build": "
|
|
49
|
+
"build": "node ./scripts/build.mjs",
|
|
51
50
|
"prepare": "pnpm run build",
|
|
52
51
|
"prepublishOnly": "pnpm run build",
|
|
53
52
|
"pack:check": "pnpm pack --dry-run"
|
|
54
53
|
},
|
|
55
54
|
"peerDependencies": {
|
|
56
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
57
|
-
"@deepseek-ai/dsh-settings": "^0.1.
|
|
58
|
-
"@deepseek-ai/schemastery": "^3.18.
|
|
55
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
56
|
+
"@deepseek-ai/dsh-settings": "^0.1.5-rc.1",
|
|
57
|
+
"@deepseek-ai/schemastery": "^3.18.2"
|
|
59
58
|
},
|
|
60
59
|
"devDependencies": {
|
|
61
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
62
|
-
"@deepseek-ai/dsh-agent": "^0.1.
|
|
63
|
-
"@deepseek-ai/dsh-client-
|
|
64
|
-
"@deepseek-ai/dsh-client-ui-
|
|
65
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.
|
|
66
|
-
"@deepseek-ai/dsh-client-ui-slots": "^0.1.
|
|
67
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.
|
|
68
|
-
"@deepseek-ai/dsh-session": "^0.1.
|
|
69
|
-
"@deepseek-ai/dsh-settings": "^0.1.
|
|
70
|
-
"@deepseek-ai/dsh-user-approval": "^0.1.
|
|
71
|
-
"@deepseek-ai/schemastery": "^3.18.
|
|
60
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
61
|
+
"@deepseek-ai/dsh-agent": "^0.1.5-rc.1",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-rc.1",
|
|
63
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.1",
|
|
64
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.1",
|
|
65
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.1",
|
|
66
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.1",
|
|
67
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.1",
|
|
68
|
+
"@deepseek-ai/dsh-settings": "^0.1.5-rc.1",
|
|
69
|
+
"@deepseek-ai/dsh-user-approval": "^0.1.5-rc.1",
|
|
70
|
+
"@deepseek-ai/schemastery": "^3.18.2",
|
|
72
71
|
"@types/react": "^18.3.1",
|
|
73
72
|
"react": "^18.2.0",
|
|
74
73
|
"tsdown": "^0.22.2",
|