@cubeai/dsh-feishu-channels 0.0.0-stage → 0.2.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 (65) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +15 -0
  3. package/README.md +56 -2
  4. package/client.js +4189 -0
  5. package/cordis.patch.yml +4 -0
  6. package/docs/coexistence.md +112 -0
  7. package/docs/dsh-feishu-channels-plan.md +1406 -0
  8. package/docs/ui-revamp-plan.md +263 -0
  9. package/docs/verification.md +120 -0
  10. package/icon.svg +17 -0
  11. package/locale/en.json +6 -0
  12. package/locale/zh.json +6 -0
  13. package/package.json +76 -4
  14. package/src/channels/connection-state.js +12 -0
  15. package/src/channels/diagnostics.js +77 -0
  16. package/src/channels/factory.js +20 -0
  17. package/src/channels/feishu-app.js +267 -0
  18. package/src/channels/feishu.js +399 -0
  19. package/src/channels/media.js +9 -0
  20. package/src/channels/meta.js +24 -0
  21. package/src/channels/qr/feishu.js +84 -0
  22. package/src/channels/qr/hub.js +229 -0
  23. package/src/channels/qr/render.js +8 -0
  24. package/src/channels/qr/shared.js +50 -0
  25. package/src/engine/abort.js +35 -0
  26. package/src/engine/access.js +23 -0
  27. package/src/engine/agent-options.js +19 -0
  28. package/src/engine/approval.js +70 -0
  29. package/src/engine/assistant-settings.js +38 -0
  30. package/src/engine/assistant-text.js +11 -0
  31. package/src/engine/atomic-file.js +45 -0
  32. package/src/engine/chat-commands.js +752 -0
  33. package/src/engine/choice-delivery.js +20 -0
  34. package/src/engine/choices.js +103 -0
  35. package/src/engine/command-locale.js +70 -0
  36. package/src/engine/command-messages.js +434 -0
  37. package/src/engine/command-permissions.js +38 -0
  38. package/src/engine/command-replies.js +59 -0
  39. package/src/engine/credentials.js +54 -0
  40. package/src/engine/deferred-delivery.js +260 -0
  41. package/src/engine/delivery-history.js +39 -0
  42. package/src/engine/file-delivery.js +215 -0
  43. package/src/engine/file-input.js +52 -0
  44. package/src/engine/file-log.js +25 -0
  45. package/src/engine/gateway.js +1337 -0
  46. package/src/engine/image-input.js +31 -0
  47. package/src/engine/json-state.js +25 -0
  48. package/src/engine/keyed-queue.js +20 -0
  49. package/src/engine/merge.js +56 -0
  50. package/src/engine/message-progress.js +274 -0
  51. package/src/engine/question.js +201 -0
  52. package/src/engine/quiet-logger.js +25 -0
  53. package/src/engine/reply-stream.js +86 -0
  54. package/src/engine/router.js +713 -0
  55. package/src/engine/secure-file.js +8 -0
  56. package/src/engine/seen-store.js +43 -0
  57. package/src/engine/session-export.js +64 -0
  58. package/src/engine/session-history.js +30 -0
  59. package/src/engine/session-id.js +62 -0
  60. package/src/engine/session-store.js +109 -0
  61. package/src/engine/session-title.js +29 -0
  62. package/src/engine/split.js +291 -0
  63. package/src/engine/workspace-path.js +9 -0
  64. package/src/index.js +62 -0
  65. package/src/manager.js +1325 -0
@@ -0,0 +1,4 @@
1
+ # DSH飞书频道:把飞书机器人接入本机 DeepSeek Harness。
2
+ - insert:
3
+ - id: feishu-channel
4
+ name: '@cubeai/dsh-feishu-channels'
@@ -0,0 +1,112 @@
1
+ # Sidebar coexistence with dsh-im-connect
2
+
3
+ This document is the maintenance contract for the shared "任务 | 频道 | 飞书频道" tab bar.
4
+
5
+ ## Why a contract is needed
6
+
7
+ DSH has no official sidebar-tab slot. `sidebar.workspaces` is a single slot owned by
8
+ `@deepseek-ai/dsh-client-ui-workspace`. `dsh-im-connect` wraps that component and
9
+ attaches a private **Registry v1** (`component.__dshNativeTabs`). Other plugins can insert
10
+ tabs into that registry without modifying `dsh-im-connect`.
11
+
12
+ `@cubeai/dsh-feishu-channels` implements the same registry contract. Either plugin may be
13
+ the wrapper ("host"); the other one inserts its tab.
14
+
15
+ ## Registry v1
16
+
17
+ ```ts
18
+ interface SidebarTabRegistryV1 {
19
+ version: 1
20
+ officialTree: React.ComponentType<any>
21
+ sessionFilters: Array<(sessionId: string) => boolean>
22
+ sessionOpeners: Array<{ id: string, order?: number, matchSession(id: string): boolean, open(id: string, hostOpen?: (id: string) => void): void }>
23
+ getTabs(): Tab[]
24
+ getRevision(): number
25
+ subscribe(listener: () => void): () => void
26
+ insert(tab: Tab): () => void
27
+ addSessionFilter(filter: (id: string) => boolean): () => void
28
+ addSessionOpener(opener: SessionOpener): () => void
29
+ }
30
+ ```
31
+
32
+ Discovery rules (compatible with `dsh-im-connect@1.0.12`):
33
+
34
+ 1. Read `sidebar.workspaces` occupants.
35
+ 2. If `occupant.component.__dshNativeTabs` is a valid v1 registry, insert a tab; do not wrap.
36
+ 3. Else if the component is already wrapped by an unknown host, leave it untouched.
37
+ 4. Else wrap the official component and attach a registry to the wrapper function.
38
+
39
+ Wrapper markers:
40
+
41
+ - `__dshNativeTabHost = true`
42
+ - `__dshNativeTabWrapped = true`
43
+ - `__dshNativeTabOriginal = originalComponent`
44
+ - `__dshNativeTabOwner = 'im-connect' | 'feishu-channel'`
45
+ - `__dfcTabHost = true` (new plugin only)
46
+
47
+ Coordination event: `window.dispatchEvent(new Event('dsh-native-sidebar-change'))`.
48
+
49
+ ## Tabs
50
+
51
+ | Plugin | id | order | Label |
52
+ |---|---|---:|---|
53
+ | dsh-im-connect | `channels` | 20 | 频道 / Channels |
54
+ | dsh-feishu-channels | `feishu` | 30 | 飞书频道 / Feishu |
55
+
56
+ Tasks is the fixed first tab. Sorted result:
57
+
58
+ ```text
59
+ 任务 | 频道 | 飞书频道
60
+ ```
61
+
62
+ When only one plugin is installed, the other tab is absent.
63
+
64
+ ## Session visibility
65
+
66
+ - Feishu sessions use `dfc:`; im-connect sessions use `im:`.
67
+ - Each plugin adds a session filter to the shared registry so its own sessions do not appear
68
+ in the Tasks tree.
69
+ - A session id never matches both prefixes.
70
+ - Do not share `sessions.json`, `channels.json`, credentials, or state directories.
71
+
72
+ ## Lifecycle
73
+
74
+ | Event | Behavior |
75
+ |---|---|
76
+ | New plugin loads after im-connect | Insert `feishu` into im-connect's registry |
77
+ | im-connect loads after new plugin | im-connect detects the new registry and inserts `channels` |
78
+ | New plugin unloads, im-connect remains | Remove own tab/filter; if own wrapper, restore official component and dispatch change event; im-connect re-wraps |
79
+ | im-connect unloads, new plugin remains | im-connect removes its tab/restores; new plugin re-wraps on change event |
80
+ | Both disabled | Official sidebar |
81
+ | Page refresh | Deterministic re-evaluation from the bundle order |
82
+
83
+ All disposers must be idempotent and remove only their own tab/filter/opener.
84
+
85
+ ## Known limitations
86
+
87
+ - Registry v1 is a private convention, not a DSH public API. A future im-connect release may
88
+ change it; the new plugin degrades to the official sidebar rather than fighting it.
89
+ - Codex UI sidebars (`sidebar.channels`) are not wrapped by v1.
90
+ - Two plugins must not use the same Feishu App ID at the same time; Feishu long-connection
91
+ events are delivered to one connection.
92
+ - **Uninstall order:** because both plugins share the single `sidebar.workspaces` slot and
93
+ one wraps the other, uninstalling `dsh-im-connect` while the new plugin is active can be
94
+ rejected by DSH's `bundle-in-use` guard. Disable `@cubeai/dsh-feishu-channels` first, then
95
+ uninstall `dsh-im-connect`; the new plugin can be re-enabled afterwards (it falls back to
96
+ the official sidebar and shows `任务 | 飞书频道`). This is a UI-wrapper/runtime coupling,
97
+ not an npm dependency: neither package imports the other, and their Host state, APIs,
98
+ credentials, and sessions are separate.
99
+
100
+ ## Verification matrix
101
+
102
+ | Scenario | Expected |
103
+ |---|---|
104
+ | new plugin only | 任务 \| 飞书频道 |
105
+ | im-connect only | 任务 \| 频道 |
106
+ | im-connect first, new plugin second | 任务 \| 频道 \| 飞书频道 |
107
+ | new plugin first, im-connect second | 任务 \| 频道 \| 飞书频道 |
108
+ | disable new plugin | 任务 \| 频道 |
109
+ | disable im-connect | 任务 \| 飞书频道 |
110
+ | uninstall either | Disable the other plugin first if DSH reports `bundle-in-use`; then uninstall, then re-enable |
111
+ | refresh | Same as before refresh |
112
+ | reload client | No duplicate tabs |