dsh-connect 0.7.2 → 0.8.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.
Files changed (114) hide show
  1. package/README.md +68 -32
  2. package/README.zh.md +67 -31
  3. package/client/client.js +387 -0
  4. package/client/client.js.map +7 -0
  5. package/client/settings-client.mjs +177 -0
  6. package/examples/minimal.config.json +16 -0
  7. package/lib/channels/dingtalk/adapter.d.ts +59 -0
  8. package/lib/channels/dingtalk/adapter.d.ts.map +1 -0
  9. package/lib/channels/dingtalk/adapter.js +123 -0
  10. package/lib/channels/dingtalk/adapter.js.map +1 -0
  11. package/lib/channels/dingtalk/i18n.d.ts +14 -0
  12. package/lib/channels/dingtalk/i18n.d.ts.map +1 -0
  13. package/lib/channels/dingtalk/i18n.js +16 -0
  14. package/lib/channels/dingtalk/i18n.js.map +1 -0
  15. package/lib/channels/dingtalk/index.d.ts +127 -0
  16. package/lib/channels/dingtalk/index.d.ts.map +1 -0
  17. package/lib/channels/dingtalk/index.js +144 -0
  18. package/lib/channels/dingtalk/index.js.map +1 -0
  19. package/lib/channels/dingtalk/message.d.ts +49 -0
  20. package/lib/channels/dingtalk/message.d.ts.map +1 -0
  21. package/lib/channels/dingtalk/message.js +43 -0
  22. package/lib/channels/dingtalk/message.js.map +1 -0
  23. package/lib/channels/dingtalk/stomp.d.ts +36 -0
  24. package/lib/channels/dingtalk/stomp.d.ts.map +1 -0
  25. package/lib/channels/dingtalk/stomp.js +107 -0
  26. package/lib/channels/dingtalk/stomp.js.map +1 -0
  27. package/lib/channels/dingtalk/stream.d.ts +53 -0
  28. package/lib/channels/dingtalk/stream.d.ts.map +1 -0
  29. package/lib/channels/dingtalk/stream.js +199 -0
  30. package/lib/channels/dingtalk/stream.js.map +1 -0
  31. package/lib/channels/dingtalk/webhook.d.ts +84 -0
  32. package/lib/channels/dingtalk/webhook.d.ts.map +1 -0
  33. package/lib/channels/dingtalk/webhook.js +143 -0
  34. package/lib/channels/dingtalk/webhook.js.map +1 -0
  35. package/lib/channels/feishu/adapter.d.ts +139 -0
  36. package/lib/channels/feishu/adapter.d.ts.map +1 -0
  37. package/lib/channels/feishu/adapter.js +677 -0
  38. package/lib/channels/feishu/adapter.js.map +1 -0
  39. package/lib/channels/feishu/i18n.d.ts +28 -0
  40. package/lib/channels/feishu/i18n.d.ts.map +1 -0
  41. package/lib/channels/feishu/i18n.js +40 -0
  42. package/lib/channels/feishu/i18n.js.map +1 -0
  43. package/lib/channels/feishu/index.d.ts +61 -0
  44. package/lib/channels/feishu/index.d.ts.map +1 -0
  45. package/lib/channels/feishu/index.js +77 -0
  46. package/lib/channels/feishu/index.js.map +1 -0
  47. package/lib/channels/feishu/onboard.d.ts +16 -0
  48. package/lib/channels/feishu/onboard.d.ts.map +1 -0
  49. package/lib/channels/feishu/onboard.js +86 -0
  50. package/lib/channels/feishu/onboard.js.map +1 -0
  51. package/lib/channels/telegram/adapter.d.ts +70 -0
  52. package/lib/channels/telegram/adapter.d.ts.map +1 -0
  53. package/lib/channels/telegram/adapter.js +454 -0
  54. package/lib/channels/telegram/adapter.js.map +1 -0
  55. package/lib/channels/telegram/client.d.ts +115 -0
  56. package/lib/channels/telegram/client.d.ts.map +1 -0
  57. package/lib/channels/telegram/client.js +198 -0
  58. package/lib/channels/telegram/client.js.map +1 -0
  59. package/lib/channels/telegram/i18n.d.ts +14 -0
  60. package/lib/channels/telegram/i18n.d.ts.map +1 -0
  61. package/lib/channels/telegram/i18n.js +18 -0
  62. package/lib/channels/telegram/i18n.js.map +1 -0
  63. package/lib/channels/telegram/index.d.ts +46 -0
  64. package/lib/channels/telegram/index.d.ts.map +1 -0
  65. package/lib/channels/telegram/index.js +54 -0
  66. package/lib/channels/telegram/index.js.map +1 -0
  67. package/lib/channels/web/adapter.d.ts +103 -0
  68. package/lib/channels/web/adapter.d.ts.map +1 -0
  69. package/lib/channels/web/adapter.js +161 -0
  70. package/lib/channels/web/adapter.js.map +1 -0
  71. package/lib/channels/web/index.d.ts +47 -0
  72. package/lib/channels/web/index.d.ts.map +1 -0
  73. package/lib/channels/web/index.js +59 -0
  74. package/lib/channels/web/index.js.map +1 -0
  75. package/lib/index.d.ts +68 -11
  76. package/lib/index.d.ts.map +1 -1
  77. package/lib/index.js +141 -8
  78. package/lib/index.js.map +1 -1
  79. package/lib/runner.d.ts +1 -2
  80. package/lib/runner.d.ts.map +1 -1
  81. package/lib/runner.js.map +1 -1
  82. package/lib/service.d.ts +1 -1
  83. package/lib/service.d.ts.map +1 -1
  84. package/lib/service.js +1 -1
  85. package/lib/service.js.map +1 -1
  86. package/lib/settings/channels.d.ts +51 -0
  87. package/lib/settings/channels.d.ts.map +1 -0
  88. package/lib/settings/channels.js +101 -0
  89. package/lib/settings/channels.js.map +1 -0
  90. package/lib/settings/credential-store.d.ts +39 -0
  91. package/lib/settings/credential-store.d.ts.map +1 -0
  92. package/lib/settings/credential-store.js +68 -0
  93. package/lib/settings/credential-store.js.map +1 -0
  94. package/lib/settings/index.d.ts +14 -0
  95. package/lib/settings/index.d.ts.map +1 -0
  96. package/lib/settings/index.js +14 -0
  97. package/lib/settings/index.js.map +1 -0
  98. package/lib/settings/rpc-client.d.ts +36 -0
  99. package/lib/settings/rpc-client.d.ts.map +1 -0
  100. package/lib/settings/rpc-client.js +45 -0
  101. package/lib/settings/rpc-client.js.map +1 -0
  102. package/lib/settings/settings-model.d.ts +107 -0
  103. package/lib/settings/settings-model.d.ts.map +1 -0
  104. package/lib/settings/settings-model.js +110 -0
  105. package/lib/settings/settings-model.js.map +1 -0
  106. package/lib/settings/settings-rpc.d.ts +62 -0
  107. package/lib/settings/settings-rpc.d.ts.map +1 -0
  108. package/lib/settings/settings-rpc.js +90 -0
  109. package/lib/settings/settings-rpc.js.map +1 -0
  110. package/lib/settings/settings-service.d.ts +27 -0
  111. package/lib/settings/settings-service.d.ts.map +1 -0
  112. package/lib/settings/settings-service.js +103 -0
  113. package/lib/settings/settings-service.js.map +1 -0
  114. package/package.json +48 -6
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Host-side RPC facade for the dsh-connect web settings pane.
3
+ *
4
+ * Mirrors dsh-im's host RPC pattern: a plugin registers a single channel on
5
+ * `ctx.connection.rpc.handle(...)` and a handler dispatches dotted endpoints,
6
+ * returning `{ ok: true, value }` on success or `{ ok: false, error }` on
7
+ * failure (see dsh-im `plugin-src/host/update-rpc.mjs`).
8
+ *
9
+ * Endpoints:
10
+ * - `settings.get` — current non-secret config + enabled channels + credential presence.
11
+ * - `settings.save` — persist non-secret config (payload must be non-empty).
12
+ * - `credentials.save` — persist secrets to the DSH credential store (payload
13
+ * `{ channel, values }`, values are {configKey: secret}).
14
+ * - `settings.status` — fresh status snapshot.
15
+ *
16
+ * @module dsh-connect/settings/settings-rpc
17
+ */
18
+ /** RPC channel the settings pane calls. */
19
+ export declare const SETTINGS_RPC_CHANNEL = "/dsh-connect";
20
+ /** Endpoints the settings pane can invoke on the channel. */
21
+ export declare const SETTINGS_ENDPOINTS: readonly string[];
22
+ /** A settings pane `settings.get`/status snapshot. */
23
+ export interface SettingsSnapshot {
24
+ /** The current plugin config (non-secret fields). */
25
+ config: Record<string, unknown>;
26
+ /** The channel names currently enabled. */
27
+ enabled: string[];
28
+ /** Per-channel credential presence (true = stored & set). */
29
+ credentials: Record<string, boolean>;
30
+ }
31
+ /** The service backing the RPC; supplied by the web-settings integration. */
32
+ export interface SettingsService {
33
+ get(): Promise<SettingsSnapshot>;
34
+ save(config: Record<string, unknown>): Promise<SettingsSnapshot>;
35
+ /** Persist channel secrets ({configKey: secret}) to the credential store. */
36
+ saveCredentials?(channel: string, values: Record<string, string>): Promise<SettingsSnapshot>;
37
+ status(): Promise<SettingsSnapshot>;
38
+ }
39
+ /** Build the channel handler for a settings service. */
40
+ export declare function createSettingsRpcHandler(service: SettingsService): (endpoint: string, payload: unknown, signal?: {
41
+ aborted?: boolean;
42
+ }) => Promise<{
43
+ ok: boolean;
44
+ value: SettingsSnapshot;
45
+ error?: undefined;
46
+ } | {
47
+ ok: boolean;
48
+ error: {
49
+ code: any;
50
+ message: any;
51
+ };
52
+ value?: undefined;
53
+ }>;
54
+ /**
55
+ * Register the settings RPC channel, mirroring dsh-im's `installUpdateRpc`.
56
+ * No-ops (returns a no-op disposer) when the host connection is unavailable,
57
+ * so the plugin stays safe to load in any context.
58
+ */
59
+ export declare function installSettingsRpc(ctx: unknown, options: {
60
+ service: SettingsService;
61
+ }): () => void;
62
+ //# sourceMappingURL=settings-rpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-rpc.d.ts","sourceRoot":"","sources":["../../src/settings/settings-rpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,2CAA2C;AAC3C,eAAO,MAAM,oBAAoB,iBAAiB,CAAC;AAEnD,6DAA6D;AAC7D,eAAO,MAAM,kBAAkB,mBAA0F,CAAC;AAU1H,sDAAsD;AACtD,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,2CAA2C;IAC3C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,GAAG,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjE,6EAA6E;IAC7E,eAAe,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC7F,MAAM,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACrC;AAeD,wDAAwD;AACxD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,eAAe,IACjD,UAAU,MAAM,EAAE,SAAS,OAAO,EAAE,SAAS;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE;;;;;;;;;;;GAoBjF;AAaD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE;IAAE,OAAO,EAAE,eAAe,CAAA;CAAE,cAKrF"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Host-side RPC facade for the dsh-connect web settings pane.
3
+ *
4
+ * Mirrors dsh-im's host RPC pattern: a plugin registers a single channel on
5
+ * `ctx.connection.rpc.handle(...)` and a handler dispatches dotted endpoints,
6
+ * returning `{ ok: true, value }` on success or `{ ok: false, error }` on
7
+ * failure (see dsh-im `plugin-src/host/update-rpc.mjs`).
8
+ *
9
+ * Endpoints:
10
+ * - `settings.get` — current non-secret config + enabled channels + credential presence.
11
+ * - `settings.save` — persist non-secret config (payload must be non-empty).
12
+ * - `credentials.save` — persist secrets to the DSH credential store (payload
13
+ * `{ channel, values }`, values are {configKey: secret}).
14
+ * - `settings.status` — fresh status snapshot.
15
+ *
16
+ * @module dsh-connect/settings/settings-rpc
17
+ */
18
+ /** RPC channel the settings pane calls. */
19
+ export const SETTINGS_RPC_CHANNEL = "/dsh-connect";
20
+ /** Endpoints the settings pane can invoke on the channel. */
21
+ export const SETTINGS_ENDPOINTS = Object.freeze(["settings.get", "settings.save", "credentials.save", "settings.status"]);
22
+ /** Error codes considered safe to surface verbatim to the browser. */
23
+ const PUBLIC_ERRORS = new Set([
24
+ "settings-failed", "bad-request", "cancelled", "invalid-payload", "unknown-profile",
25
+ "unsupported-runtime", "not-configured", "credential-missing", "credential-invalid",
26
+ "channel-disabled", "save-failed", "state-unavailable", "disposed", "interrupted",
27
+ "unsupported", "invalid-channel", "invalid-credentials",
28
+ ]);
29
+ function validPayload(endpoint, payload) {
30
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload))
31
+ return false;
32
+ const keys = Object.keys(payload);
33
+ if (endpoint === "settings.save")
34
+ return keys.length > 0;
35
+ if (endpoint === "credentials.save") {
36
+ return keys.length > 0 && typeof payload.channel === "string"
37
+ && payload.values !== null && typeof payload.values === "object"
38
+ && !Array.isArray(payload.values);
39
+ }
40
+ // The reads carry no payload.
41
+ return keys.length === 0;
42
+ }
43
+ /** Build the channel handler for a settings service. */
44
+ export function createSettingsRpcHandler(service) {
45
+ return async (endpoint, payload, signal) => {
46
+ if (!SETTINGS_ENDPOINTS.includes(endpoint) || !validPayload(endpoint, payload)) {
47
+ return { ok: false, error: { code: "bad-request", message: "Invalid settings request." } };
48
+ }
49
+ if (signal?.aborted)
50
+ return { ok: false, error: { code: "cancelled", message: "Request cancelled." } };
51
+ try {
52
+ const record = (payload ?? {});
53
+ const value = endpoint === "settings.get"
54
+ ? await service.get()
55
+ : endpoint === "settings.save"
56
+ ? await service.save(record)
57
+ : endpoint === "credentials.save"
58
+ ? await saveCredentialsP(service, record)
59
+ : await service.status();
60
+ return { ok: true, value };
61
+ }
62
+ catch (error) {
63
+ const code = PUBLIC_ERRORS.has(error?.code) ? error.code : "settings-failed";
64
+ return { ok: false, error: { code, message: code } };
65
+ }
66
+ };
67
+ }
68
+ async function saveCredentialsP(service, record) {
69
+ if (typeof service.saveCredentials !== "function") {
70
+ const err = new Error("unsupported");
71
+ err.code = "unsupported";
72
+ throw err;
73
+ }
74
+ const channel = record.channel;
75
+ const values = (record.values ?? {});
76
+ return service.saveCredentials(channel, values);
77
+ }
78
+ /**
79
+ * Register the settings RPC channel, mirroring dsh-im's `installUpdateRpc`.
80
+ * No-ops (returns a no-op disposer) when the host connection is unavailable,
81
+ * so the plugin stays safe to load in any context.
82
+ */
83
+ export function installSettingsRpc(ctx, options) {
84
+ const conn = ctx?.connection;
85
+ const handle = conn?.rpc?.handle;
86
+ if (typeof handle !== "function")
87
+ return () => { };
88
+ return handle(SETTINGS_RPC_CHANNEL, createSettingsRpcHandler(options.service), { authority: "loopback" });
89
+ }
90
+ //# sourceMappingURL=settings-rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-rpc.js","sourceRoot":"","sources":["../../src/settings/settings-rpc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { type ChannelName } from "./channels.js";
2
+ import type { SettingsService } from "./settings-rpc.js";
3
+ import { type CredentialStore } from "./credential-store.js";
4
+ export interface SettingsServiceOptions {
5
+ /** JSON file to persist non-secret settings (omit = in-memory only). */
6
+ statePath?: string;
7
+ /** Known channel names (default: built-in channels). */
8
+ channelNames?: readonly ChannelName[];
9
+ /** Report credential presence per channel (optional; default: all false). */
10
+ credentialStore?: CredentialStore;
11
+ /** Error sink (default: console.error). */
12
+ log?: (msg: string) => void;
13
+ /**
14
+ * Seed config used when no state file exists (or `statePath` is unset), so the
15
+ * pane reflects the plugin's live config rather than an empty default. The
16
+ * live config carries only the settings-shape keys (`channels`, `channelDefaults`,
17
+ * per-channel) that the pane edits.
18
+ */
19
+ initialConfig?: Record<string, unknown>;
20
+ }
21
+ /**
22
+ * Build a settings service backed by a JSON state file. `get`/`status` read the
23
+ * current state; `save` merges and persists. A missing/corrupt state file is
24
+ * treated as an empty config (never throws on read).
25
+ */
26
+ export declare function createSettingsService(options?: SettingsServiceOptions): SettingsService;
27
+ //# sourceMappingURL=settings-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-service.d.ts","sourceRoot":"","sources":["../../src/settings/settings-service.ts"],"names":[],"mappings":"AAaA,OAAO,EAAY,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAElF,MAAM,WAAW,sBAAsB;IACrC,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IACtC,6EAA6E;IAC7E,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,2CAA2C;IAC3C,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAMD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,sBAA2B,GAAG,eAAe,CAsE3F"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Persistence backend for the dsh-connect web settings pane.
3
+ *
4
+ * A host-side service that reads/writes the non-secret plugin settings (the
5
+ * `dsh-connect` config: `channels`, `channelDefaults`, per-channel fields)
6
+ * to a small JSON state file, and reports per-channel credential presence via
7
+ * an optional DSH credential store. Secrets (appSecret/botToken) live in the
8
+ * DSH credentials store, never in this file.
9
+ *
10
+ * @module dsh-connect/settings/settings-service
11
+ */
12
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
13
+ import { dirname } from "node:path";
14
+ import { CHANNELS } from "./channels.js";
15
+ import { CHANNEL_SECRET_KEYS } from "./credential-store.js";
16
+ function logError(msg) {
17
+ if (typeof console !== "undefined")
18
+ console.error?.("[dsh-connect/settings] " + msg);
19
+ }
20
+ /**
21
+ * Build a settings service backed by a JSON state file. `get`/`status` read the
22
+ * current state; `save` merges and persists. A missing/corrupt state file is
23
+ * treated as an empty config (never throws on read).
24
+ */
25
+ export function createSettingsService(options = {}) {
26
+ const channels = options.channelNames ?? CHANNELS;
27
+ const statePath = options.statePath;
28
+ const log = options.log ?? logError;
29
+ const credentialStore = options.credentialStore;
30
+ const initialConfig = options.initialConfig ?? {};
31
+ function readConfig() {
32
+ if (!statePath || !existsSync(statePath))
33
+ return { ...initialConfig };
34
+ try {
35
+ const value = JSON.parse(readFileSync(statePath, "utf8"));
36
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
37
+ }
38
+ catch (error) {
39
+ log(`failed to read settings state: ${String(error)}`);
40
+ return {};
41
+ }
42
+ }
43
+ function persist(config) {
44
+ if (!statePath)
45
+ return;
46
+ try {
47
+ mkdirSync(dirname(statePath), { recursive: true });
48
+ writeFileSync(statePath, JSON.stringify(config, null, 2) + "\n");
49
+ }
50
+ catch (error) {
51
+ log(`failed to write settings state: ${String(error)}`);
52
+ }
53
+ }
54
+ async function snapshot(config) {
55
+ const enabled = (Array.isArray(config.channels) ? config.channels : [...channels])
56
+ .filter((name) => channels.includes(name));
57
+ const credentials = {};
58
+ for (const name of channels) {
59
+ if (credentialStore) {
60
+ try {
61
+ credentials[name] = await credentialStore.configured(name);
62
+ }
63
+ catch {
64
+ credentials[name] = false;
65
+ }
66
+ }
67
+ else {
68
+ credentials[name] = false;
69
+ }
70
+ }
71
+ return { config, enabled, credentials };
72
+ }
73
+ return {
74
+ async get() { return snapshot(readConfig()); },
75
+ async status() { return snapshot(readConfig()); },
76
+ async saveCredentials(channel, values) {
77
+ if (!credentialStore) {
78
+ const err = new Error("not-configured");
79
+ err.code = "not-configured";
80
+ throw err;
81
+ }
82
+ const map = CHANNEL_SECRET_KEYS[channel] ?? {};
83
+ const refValues = {};
84
+ for (const [configKey, ref] of Object.entries(map)) {
85
+ if (values[configKey] !== undefined)
86
+ refValues[ref] = values[configKey];
87
+ }
88
+ if (Object.keys(refValues).length === 0) {
89
+ const err = new Error("invalid-credentials");
90
+ err.code = "invalid-credentials";
91
+ throw err;
92
+ }
93
+ await credentialStore.save(channel, refValues);
94
+ return snapshot(readConfig());
95
+ },
96
+ async save(config) {
97
+ const next = { ...readConfig(), ...config };
98
+ persist(next);
99
+ return snapshot(next);
100
+ },
101
+ };
102
+ }
103
+ //# sourceMappingURL=settings-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-service.js","sourceRoot":"","sources":["../../src/settings/settings-service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-connect",
3
- "version": "0.7.2",
4
- "description": "Channel-agnostic messaging bridge core for DeepSeek Harness (DSH): binds chat channels to DSH agents, streams replies, and pushes work summaries",
3
+ "version": "0.8.0",
4
+ "description": "All-in-one DeepSeek Harness (DSH) chat bridge: one plugin, one config block — Feishu/Lark, Telegram, DingTalk, and Web mirror adapters plus the web-settings pane, all behind a channels[] selector",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
@@ -13,10 +13,36 @@
13
13
  "./binding": {
14
14
  "types": "./lib/binding.d.ts",
15
15
  "default": "./lib/binding.js"
16
- }
16
+ },
17
+ "./feishu": {
18
+ "types": "./lib/channels/feishu/index.d.ts",
19
+ "default": "./lib/channels/feishu/index.js"
20
+ },
21
+ "./telegram": {
22
+ "types": "./lib/channels/telegram/index.d.ts",
23
+ "default": "./lib/channels/telegram/index.js"
24
+ },
25
+ "./dingtalk": {
26
+ "types": "./lib/channels/dingtalk/index.d.ts",
27
+ "default": "./lib/channels/dingtalk/index.js"
28
+ },
29
+ "./web": {
30
+ "types": "./lib/channels/web/index.d.ts",
31
+ "default": "./lib/channels/web/index.js"
32
+ },
33
+ "./settings": {
34
+ "types": "./lib/settings/index.d.ts",
35
+ "default": "./lib/settings/index.js"
36
+ },
37
+ "./client": {
38
+ "default": "./client/client.js"
39
+ },
40
+ "./package.json": "./package.json"
17
41
  },
18
42
  "files": [
19
43
  "lib",
44
+ "client",
45
+ "examples",
20
46
  "README.md",
21
47
  "README.zh.md",
22
48
  "README.i18n.yaml",
@@ -25,6 +51,16 @@
25
51
  "dsh": {
26
52
  "bundle": {
27
53
  "patch": "./cordis.patch.yml"
54
+ },
55
+ "client": {
56
+ "platform": "web",
57
+ "inject": [
58
+ "@deepseek-ai/dsh-client-runtime",
59
+ "@deepseek-ai/dsh-client-ui-settings",
60
+ "@deepseek-ai/dsh-client-locale",
61
+ "@deepseek-ai/dsh-client-connection",
62
+ "@deepseek-ai/dsh-api-remotes"
63
+ ]
28
64
  }
29
65
  },
30
66
  "keywords": [
@@ -33,6 +69,8 @@
33
69
  "feishu",
34
70
  "lark",
35
71
  "dingtalk",
72
+ "telegram",
73
+ "all-in-one",
36
74
  "ai-agent",
37
75
  "chatbot",
38
76
  "cordis",
@@ -49,11 +87,14 @@
49
87
  "url": "https://github.com/IvanWu2015/dsh-connect/issues"
50
88
  },
51
89
  "scripts": {
52
- "build": "tsc -p tsconfig.json",
53
- "typecheck": "tsc -p tsconfig.json --noEmit"
90
+ "build": "tsc -p tsconfig.json && node scripts/build-client.mjs",
91
+ "typecheck": "tsc -p tsconfig.json --noEmit",
92
+ "test": "node test/run-all.mjs",
93
+ "prepack": "tsc -p tsconfig.json && node scripts/build-client.mjs"
54
94
  },
55
95
  "dependencies": {
56
- "@deepseek-ai/schemastery": "^3.18.1"
96
+ "@deepseek-ai/schemastery": "^3.18.1",
97
+ "@larksuiteoapi/node-sdk": "^1.73.0"
57
98
  },
58
99
  "peerDependencies": {
59
100
  "@deepseek-ai/cordis": "^4.0.1",
@@ -67,6 +108,7 @@
67
108
  "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
68
109
  "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
69
110
  "@types/node": "^22.15.0",
111
+ "esbuild": "^0.28.2",
70
112
  "typescript": "^5.6.3"
71
113
  }
72
114
  }