dsh-tiddlywiki 0.16.21 → 0.16.23
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 +311 -271
- package/docs/seed-initialization.md +47 -22
- package/lib/client.bundle.js +26 -26
- package/lib/client.js +26 -26
- package/lib/index.js +395 -17
- package/lib/index.js.map +1 -1
- package/package.json +86 -86
- package/src/client/better-sidebar-tab.ts +136 -0
- package/src/client/index.ts +30 -0
- package/src/client/panel.ts +5 -4
- package/src/client/rightbar-tab.ts +20 -299
- package/src/client/settings-page.ts +1 -0
- package/src/client/tw-frame.ts +334 -0
- package/src/client/ui-config.ts +5 -2
- package/src/host/config.ts +8 -0
- package/src/host/routes.ts +2 -0
- package/src/host/seed-home.ts +96 -92
- package/src/host/seed-notes.ts +8 -1
- package/src/host/seed-starter-docs.ts +251 -0
- package/src/host/seed-ui-styles.ts +74 -0
- package/src/host/seeds.ts +71 -25
- package/src/index.ts +7 -4
package/package.json
CHANGED
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dsh-tiddlywiki",
|
|
3
|
-
"description": "TiddlyWiki 5 as the DSH persistent knowledge base: tiddlywiki_* agent tools (search with filters/recent/tags/batch/rename + git sync & conflict resolve), a full TiddlyWiki editor embedded in the GUI center column (same-origin proxy, works over Tailscale/LAN/domain), a quick-note card with draft auto-save & recent-notes picker behind a single knowledge FAB, and git-based sync with auto-commit. Mounts via the official dsh plugin system — no DSH source changes.",
|
|
4
|
-
"version": "0.16.
|
|
5
|
-
"type": "module",
|
|
6
|
-
"keywords": [
|
|
7
|
-
"dsh",
|
|
8
|
-
"dsh-plugin",
|
|
9
|
-
"tiddlywiki",
|
|
10
|
-
"knowledge-base",
|
|
11
|
-
"note-taking",
|
|
12
|
-
"notes",
|
|
13
|
-
"wiki",
|
|
14
|
-
"git-sync",
|
|
15
|
-
"agent-tools",
|
|
16
|
-
"plugin"
|
|
17
|
-
],
|
|
18
|
-
"author": {
|
|
19
|
-
"name": "bbqisbbq",
|
|
20
|
-
"url": "https://github.com/bbqisbbq"
|
|
21
|
-
},
|
|
22
|
-
"main": "lib/index.js",
|
|
23
|
-
"exports": {
|
|
24
|
-
".": "./lib/index.js",
|
|
25
|
-
"./client": "./lib/client.js",
|
|
26
|
-
"./package.json": "./package.json"
|
|
27
|
-
},
|
|
28
|
-
"dsh": {
|
|
29
|
-
"bundle": {
|
|
30
|
-
"patch": "./cordis.patch.yml"
|
|
31
|
-
},
|
|
32
|
-
"client": {
|
|
33
|
-
"inject": [
|
|
34
|
-
"slots"
|
|
35
|
-
],
|
|
36
|
-
"platform": "web"
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
"files": [
|
|
40
|
-
"lib/**/*.js",
|
|
41
|
-
"lib/**/*.js.map",
|
|
42
|
-
"src",
|
|
43
|
-
"docs",
|
|
44
|
-
"cordis.patch.yml",
|
|
45
|
-
"LICENSE",
|
|
46
|
-
"README.md"
|
|
47
|
-
],
|
|
48
|
-
"license": "MIT",
|
|
49
|
-
"homepage": "https://github.com/bbqisbbq/dsh-tiddlywiki#readme",
|
|
50
|
-
"repository": {
|
|
51
|
-
"type": "git",
|
|
52
|
-
"url": "git+https://github.com/bbqisbbq/dsh-tiddlywiki.git"
|
|
53
|
-
},
|
|
54
|
-
"bugs": {
|
|
55
|
-
"url": "https://github.com/bbqisbbq/dsh-tiddlywiki/issues"
|
|
56
|
-
},
|
|
57
|
-
"engines": {
|
|
58
|
-
"node": ">=22"
|
|
59
|
-
},
|
|
60
|
-
"dependencies": {
|
|
61
|
-
"tiddlywiki": "^5.4.1"
|
|
62
|
-
},
|
|
63
|
-
"devDependencies": {
|
|
64
|
-
"@codemirror/commands": "^6.11.0",
|
|
65
|
-
"@codemirror/lang-markdown": "^6.5.2",
|
|
66
|
-
"@codemirror/language": "^6.12.4",
|
|
67
|
-
"@codemirror/state": "^6.7.2",
|
|
68
|
-
"@codemirror/view": "^6.43.10",
|
|
69
|
-
"@lezer/highlight": "^1.2.3",
|
|
70
|
-
"@types/node": "^22.20.1",
|
|
71
|
-
"@types/react": "^19.1.0",
|
|
72
|
-
"react": "^19.1.0",
|
|
73
|
-
"tsdown": "0.22.2",
|
|
74
|
-
"tsx": "^4.19.2",
|
|
75
|
-
"typescript": "~5.7.2",
|
|
76
|
-
"unrun": "*"
|
|
77
|
-
},
|
|
78
|
-
"scripts": {
|
|
79
|
-
"build": "node scripts/clean-lib.mjs && npm run build:host && npm run build:client",
|
|
80
|
-
"build:host": "tsdown -c tsdown.host.config.ts",
|
|
81
|
-
"build:client": "tsdown -c tsdown.client.config.ts && node scripts/wrap-client.mjs",
|
|
82
|
-
"watch": "tsdown -c tsdown.host.config.ts --watch",
|
|
83
|
-
"typecheck": "tsc --noEmit",
|
|
84
|
-
"selftest": "node scripts/selftest.mjs"
|
|
85
|
-
}
|
|
86
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-tiddlywiki",
|
|
3
|
+
"description": "TiddlyWiki 5 as the DSH persistent knowledge base: tiddlywiki_* agent tools (search with filters/recent/tags/batch/rename + git sync & conflict resolve), a full TiddlyWiki editor embedded in the GUI center column (same-origin proxy, works over Tailscale/LAN/domain), a quick-note card with draft auto-save & recent-notes picker behind a single knowledge FAB, and git-based sync with auto-commit. Mounts via the official dsh plugin system — no DSH source changes.",
|
|
4
|
+
"version": "0.16.23",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"dsh",
|
|
8
|
+
"dsh-plugin",
|
|
9
|
+
"tiddlywiki",
|
|
10
|
+
"knowledge-base",
|
|
11
|
+
"note-taking",
|
|
12
|
+
"notes",
|
|
13
|
+
"wiki",
|
|
14
|
+
"git-sync",
|
|
15
|
+
"agent-tools",
|
|
16
|
+
"plugin"
|
|
17
|
+
],
|
|
18
|
+
"author": {
|
|
19
|
+
"name": "bbqisbbq",
|
|
20
|
+
"url": "https://github.com/bbqisbbq"
|
|
21
|
+
},
|
|
22
|
+
"main": "lib/index.js",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": "./lib/index.js",
|
|
25
|
+
"./client": "./lib/client.js",
|
|
26
|
+
"./package.json": "./package.json"
|
|
27
|
+
},
|
|
28
|
+
"dsh": {
|
|
29
|
+
"bundle": {
|
|
30
|
+
"patch": "./cordis.patch.yml"
|
|
31
|
+
},
|
|
32
|
+
"client": {
|
|
33
|
+
"inject": [
|
|
34
|
+
"slots"
|
|
35
|
+
],
|
|
36
|
+
"platform": "web"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"lib/**/*.js",
|
|
41
|
+
"lib/**/*.js.map",
|
|
42
|
+
"src",
|
|
43
|
+
"docs",
|
|
44
|
+
"cordis.patch.yml",
|
|
45
|
+
"LICENSE",
|
|
46
|
+
"README.md"
|
|
47
|
+
],
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"homepage": "https://github.com/bbqisbbq/dsh-tiddlywiki#readme",
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/bbqisbbq/dsh-tiddlywiki.git"
|
|
53
|
+
},
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/bbqisbbq/dsh-tiddlywiki/issues"
|
|
56
|
+
},
|
|
57
|
+
"engines": {
|
|
58
|
+
"node": ">=22"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"tiddlywiki": "^5.4.1"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@codemirror/commands": "^6.11.0",
|
|
65
|
+
"@codemirror/lang-markdown": "^6.5.2",
|
|
66
|
+
"@codemirror/language": "^6.12.4",
|
|
67
|
+
"@codemirror/state": "^6.7.2",
|
|
68
|
+
"@codemirror/view": "^6.43.10",
|
|
69
|
+
"@lezer/highlight": "^1.2.3",
|
|
70
|
+
"@types/node": "^22.20.1",
|
|
71
|
+
"@types/react": "^19.1.0",
|
|
72
|
+
"react": "^19.1.0",
|
|
73
|
+
"tsdown": "0.22.2",
|
|
74
|
+
"tsx": "^4.19.2",
|
|
75
|
+
"typescript": "~5.7.2",
|
|
76
|
+
"unrun": "*"
|
|
77
|
+
},
|
|
78
|
+
"scripts": {
|
|
79
|
+
"build": "node scripts/clean-lib.mjs && npm run build:host && npm run build:client",
|
|
80
|
+
"build:host": "tsdown -c tsdown.host.config.ts",
|
|
81
|
+
"build:client": "tsdown -c tsdown.client.config.ts && node scripts/wrap-client.mjs",
|
|
82
|
+
"watch": "tsdown -c tsdown.host.config.ts --watch",
|
|
83
|
+
"typecheck": "tsc --noEmit",
|
|
84
|
+
"selftest": "node scripts/selftest.mjs"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DSH Better Sidebar (dsh-better-sidebar) TiddlyWiki tab type (v0.16.23).
|
|
3
|
+
*
|
|
4
|
+
* dsh-better-sidebar exposes a client-side registry service on the cordis
|
|
5
|
+
* context as `ctx.betterSidebar` (registerTab / registerFileViewer / openTab /
|
|
6
|
+
* closeTab …). This module registers a TW tab type there: the sidebar's + menu
|
|
7
|
+
* (and any caller of `openTab({ type: 'dsh-tiddlywiki' })`) opens the
|
|
8
|
+
* SAME-ORIGIN TW proxy iframe — the same shared machinery the center panel and
|
|
9
|
+
* the native rightbar tab use (tw-frame.ts).
|
|
10
|
+
*
|
|
11
|
+
* Mutual exclusion (one TW client at a time) rides the shared
|
|
12
|
+
* `dsh-panel-activate` protocol: when this tab becomes visible the center
|
|
13
|
+
* overlay / rightbar tab close; when another TW surface activates, this tab
|
|
14
|
+
* closes itself through the service (closeTab). Wiki links in the reply
|
|
15
|
+
* stream route here while the tab is visible (tw-frame.ts' live-frame
|
|
16
|
+
* registry → panel.ts).
|
|
17
|
+
*
|
|
18
|
+
* The integration is optional: the caller reads `ctx.get('betterSidebar')`
|
|
19
|
+
* and skips silently when the plugin is not installed (older DSH / other web
|
|
20
|
+
* profiles). Registering a tab also gives every better-sidebar user an
|
|
21
|
+
* enable/disable switch for it in the Side card settings page — that gate is
|
|
22
|
+
* the plugin's own, independent of our `ui.showBetterSidebarTab` config.
|
|
23
|
+
*
|
|
24
|
+
* @module dsh-tiddlywiki/client/better-sidebar-tab
|
|
25
|
+
*/
|
|
26
|
+
import * as React from 'react'
|
|
27
|
+
import {
|
|
28
|
+
ACTIVATE_EVENT,
|
|
29
|
+
createTwFrameController,
|
|
30
|
+
getTabLabel,
|
|
31
|
+
TwTabIcon,
|
|
32
|
+
type TwFrameController,
|
|
33
|
+
warmTabLabel,
|
|
34
|
+
} from './tw-frame.ts'
|
|
35
|
+
|
|
36
|
+
/** The tab type this package owns in the better-sidebar registry. */
|
|
37
|
+
export const TW_BETTER_SIDEBAR_ID = 'dsh-tiddlywiki'
|
|
38
|
+
/** Activation-event name for THIS surface (distinct from center 'dsh-tiddlywiki' / rightbar). */
|
|
39
|
+
const BETTER_SIDEBAR_PANEL_NAME = 'dsh-tiddlywiki/bettersidebar'
|
|
40
|
+
|
|
41
|
+
/** Structural faces over the better-sidebar contract (no @deepseek-ai imports). */
|
|
42
|
+
|
|
43
|
+
export interface BetterSidebarTabProps {
|
|
44
|
+
ctx: { get?(name: string): unknown }
|
|
45
|
+
scope: { sessionId?: string; cwd?: string }
|
|
46
|
+
tab: { id: string; type: string }
|
|
47
|
+
/** Whether this tab is the active one AND the panel is open (live views pause otherwise). */
|
|
48
|
+
visible: boolean
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Structural face over the better-sidebar registry service (no @deepseek-ai imports). */
|
|
52
|
+
export interface BetterSidebarFace {
|
|
53
|
+
registerTab(descriptor: {
|
|
54
|
+
id: string
|
|
55
|
+
title: string | (() => string)
|
|
56
|
+
icon?: unknown
|
|
57
|
+
single?: boolean
|
|
58
|
+
component: (props: BetterSidebarTabProps) => unknown
|
|
59
|
+
}): () => void
|
|
60
|
+
closeTab(tabId: string, scope?: unknown): void
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The tab body: a thin React wrapper that mounts the TW iframe into a
|
|
65
|
+
* plain-DOM host, like the rightbar tab body. `visible` pauses/resumes the
|
|
66
|
+
* frame (lazy-loads on the first show); the `dsh-panel-activate` protocol
|
|
67
|
+
* keeps exactly one TW client on screen.
|
|
68
|
+
*/
|
|
69
|
+
export function TwBetterSidebarTabBody(props: BetterSidebarTabProps): React.ReactElement {
|
|
70
|
+
const { ctx, scope, tab } = props
|
|
71
|
+
// 老版本 better-sidebar 可能不传 visible(缺失按「已可见」处理——tab 渲染在其
|
|
72
|
+
// 面板内即视为在屏)。
|
|
73
|
+
const visible = props.visible !== false
|
|
74
|
+
const hostRef = React.useRef<HTMLDivElement | null>(null)
|
|
75
|
+
const controllerRef = React.useRef<TwFrameController | null>(null)
|
|
76
|
+
|
|
77
|
+
React.useEffect(() => {
|
|
78
|
+
const host = hostRef.current
|
|
79
|
+
if (host === null) return
|
|
80
|
+
const ac = new AbortController()
|
|
81
|
+
const controller = createTwFrameController(host, ac.signal)
|
|
82
|
+
controllerRef.current = controller
|
|
83
|
+
return () => {
|
|
84
|
+
controller.dispose()
|
|
85
|
+
ac.abort()
|
|
86
|
+
controllerRef.current = null
|
|
87
|
+
}
|
|
88
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- one controller per tab (id stable; single-instance type).
|
|
89
|
+
}, [tab.id])
|
|
90
|
+
|
|
91
|
+
React.useEffect(() => {
|
|
92
|
+
controllerRef.current?.setVisible(visible)
|
|
93
|
+
}, [visible])
|
|
94
|
+
|
|
95
|
+
// When this tab becomes visible, close the center overlay / rightbar tab.
|
|
96
|
+
// When any OTHER TW surface activates, close this tab (one TW client).
|
|
97
|
+
React.useEffect(() => {
|
|
98
|
+
if (!visible) return
|
|
99
|
+
document.dispatchEvent(new CustomEvent(ACTIVATE_EVENT, { detail: BETTER_SIDEBAR_PANEL_NAME }))
|
|
100
|
+
const onActivate = (event: Event): void => {
|
|
101
|
+
const detail = (event as CustomEvent).detail
|
|
102
|
+
if (detail !== BETTER_SIDEBAR_PANEL_NAME) {
|
|
103
|
+
const service = ctx.get?.('betterSidebar') as BetterSidebarFace | undefined
|
|
104
|
+
service?.closeTab(tab.id, scope)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
document.addEventListener(ACTIVATE_EVENT, onActivate)
|
|
108
|
+
return () => document.removeEventListener(ACTIVATE_EVENT, onActivate)
|
|
109
|
+
}, [visible, tab.id, scope, ctx])
|
|
110
|
+
|
|
111
|
+
return React.createElement('div', { ref: hostRef, className: 'dsh-tw-rightbar-tab', 'data-dsh-tw-bettersidebar': '' })
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Register the TW tab type in a live better-sidebar service for the caller's
|
|
116
|
+
* lifetime; the returned disposer unregisters it. Call only when
|
|
117
|
+
* `ctx.get('betterSidebar')` actually returned a service.
|
|
118
|
+
*/
|
|
119
|
+
export function mountBetterSidebarTab(service: BetterSidebarFace): (() => void) | undefined {
|
|
120
|
+
try {
|
|
121
|
+
const remove = service.registerTab({
|
|
122
|
+
id: TW_BETTER_SIDEBAR_ID,
|
|
123
|
+
title: (): string => getTabLabel(),
|
|
124
|
+
icon: (size: number) => TwTabIcon({ size }),
|
|
125
|
+
// Single instance: opening the tab focuses the existing one.
|
|
126
|
+
single: true,
|
|
127
|
+
component: (props: BetterSidebarTabProps) => TwBetterSidebarTabBody(props),
|
|
128
|
+
})
|
|
129
|
+
// Warm the + menu label from the live config (ui.tabLabel).
|
|
130
|
+
warmTabLabel()
|
|
131
|
+
return remove
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error('[dsh-tiddlywiki] better-sidebar tab mount failed:', error)
|
|
134
|
+
return undefined
|
|
135
|
+
}
|
|
136
|
+
}
|
package/src/client/index.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { disposeEditorPopup } from './editor-popup.ts'
|
|
|
25
25
|
import { SettingsSection } from './settings-page.ts'
|
|
26
26
|
import { registerToolViews, installWikiLinkInterceptor } from './tool-views.ts'
|
|
27
27
|
import { mountRightbarTab, type RightbarSlotsFace } from './rightbar-tab.ts'
|
|
28
|
+
import { mountBetterSidebarTab, type BetterSidebarFace } from './better-sidebar-tab.ts'
|
|
28
29
|
|
|
29
30
|
/** Client plugin name. */
|
|
30
31
|
export const name = 'dsh-tiddlywiki/client'
|
|
@@ -127,6 +128,35 @@ export function apply(ctx: ClientContextFace): void {
|
|
|
127
128
|
// 右侧栏集成失败只影响该功能本身,绝不让整个插件挂掉。
|
|
128
129
|
console.error('[dsh-tiddlywiki] rightbar mount failed:', error)
|
|
129
130
|
}
|
|
131
|
+
try {
|
|
132
|
+
// DSH Better Sidebar(dsh-better-sidebar 插件)集成:可选挂载——仅当该
|
|
133
|
+
// 插件的 client 半部提供了 betterSidebar 服务时才启用(未安装 / 老版本
|
|
134
|
+
// DSH 静默跳过,插件其余功能不受影响)。注册 TW tab 类型(+ 菜单可开);
|
|
135
|
+
// 由 ui.showBetterSidebarTab 控制(默认开)。better-sidebar 的 Side
|
|
136
|
+
// 设置页也会为已注册 tab 自动提供它自己的启用开关。
|
|
137
|
+
let bsRetryTimer: number | undefined
|
|
138
|
+
const tryMountBetterSidebar = (attempt: number): void => {
|
|
139
|
+
const service = ctx.get?.('betterSidebar') as BetterSidebarFace | undefined
|
|
140
|
+
if (service === undefined) {
|
|
141
|
+
// better-sidebar 插件可能在本次 apply 之后才就绪:有限重试几次即可。
|
|
142
|
+
if (attempt < 6 && !clientDisposed) {
|
|
143
|
+
bsRetryTimer = window.setTimeout(() => tryMountBetterSidebar(attempt + 1), 500 * (attempt + 1))
|
|
144
|
+
}
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
void fetchUiConfig().then((cfg) => {
|
|
148
|
+
if (clientDisposed) return
|
|
149
|
+
if (!cfg.showBetterSidebarTab) return
|
|
150
|
+
const removeBs = mountBetterSidebarTab(service)
|
|
151
|
+
if (removeBs !== undefined) disposers.push(removeBs)
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
tryMountBetterSidebar(0)
|
|
155
|
+
disposers.push(() => { if (bsRetryTimer !== undefined) window.clearTimeout(bsRetryTimer) })
|
|
156
|
+
} catch (error) {
|
|
157
|
+
// Better Sidebar 集成失败只影响该功能本身,绝不让整个插件挂掉。
|
|
158
|
+
console.error('[dsh-tiddlywiki] better-sidebar mount failed:', error)
|
|
159
|
+
}
|
|
130
160
|
try {
|
|
131
161
|
// Reply-stream native tool cards: keyed `tool.call.toolview` slots for
|
|
132
162
|
// every tiddlywiki_* tool (additive — our keys are unclaimed).
|
package/src/client/panel.ts
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
import type { PanelState } from './state.ts'
|
|
24
24
|
import { ENTRY_SELECTOR } from './sidebar-entry.ts'
|
|
25
25
|
import { attachThemeSync, setThemeSyncConfig } from './theme-sync.ts'
|
|
26
|
-
import {
|
|
26
|
+
import { openTiddlerInLiveTab } from './tw-frame.ts'
|
|
27
27
|
|
|
28
28
|
export const PANEL_RELOAD_EVENT = 'dsh-tw-panel-reload'
|
|
29
29
|
|
|
@@ -317,9 +317,10 @@ export function mountPanel(state: PanelState): () => void {
|
|
|
317
317
|
const detail = (event as CustomEvent).detail as { title?: unknown } | undefined
|
|
318
318
|
const title = typeof detail?.title === 'string' && detail.title.length > 0 ? detail.title : ''
|
|
319
319
|
if (title.length === 0) return
|
|
320
|
-
//
|
|
321
|
-
//
|
|
322
|
-
|
|
320
|
+
// 侧边栏(rightbar / better-sidebar)的 TW tab 可见时,链接直接在那里
|
|
321
|
+
// 打开(与聊天并排);否则退回中央面板。互斥由 tw-frame.ts 共享的
|
|
322
|
+
// dsh-panel-activate 协议保证。
|
|
323
|
+
if (openTiddlerInLiveTab(title)) return
|
|
323
324
|
pendingHash = `#${encodeURIComponent(title)}`
|
|
324
325
|
state.openPanel()
|
|
325
326
|
applyPendingHash()
|