dsh-tiddlywiki 0.7.2 → 0.7.4
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 -0
- package/lib/index.js +70 -23
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/host/routes.ts +31 -5
- package/src/host/tools.ts +42 -13
- package/src/index.ts +8 -2
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/dsh-tiddlywiki)
|
|
6
6
|
[](https://github.com/bbqisbbq/dsh-tiddlywiki/blob/main/LICENSE)
|
|
7
7
|
[](https://github.com/bbqisbbq/dsh-tiddlywiki)
|
|
8
|
+
[](https://awesome-dsh-plugin.com)
|
|
8
9
|
|
|
9
10
|
等 Agent 干活的时候,人常是干坐着的——想随手写点什么,又不想切来切去。TiddlyWiki 单文件、纯文本、wiki 语法、自带 git 同步,天生适合**随手写点小东西**。于是把它做成 DSH 原生插件:不用离开当前界面,聊天区右下角就有快速笔记;要正经编辑,弹出 TW 原生编辑器;写下的内容自动进 git,既是知识库也是备份。
|
|
10
11
|
|
package/lib/index.js
CHANGED
|
@@ -949,10 +949,14 @@ function registerRoutes(ctx, deps) {
|
|
|
949
949
|
}
|
|
950
950
|
};
|
|
951
951
|
/**
|
|
952
|
-
* POST /dsh-tiddlywiki/agent/create — create (or adopt) one ordinary session
|
|
953
|
-
*
|
|
954
|
-
*
|
|
955
|
-
*
|
|
952
|
+
* POST /dsh-tiddlywiki/agent/create — create (or adopt) one ordinary session
|
|
953
|
+
* inside a real DSH workspace resolved from the requested path. The picker
|
|
954
|
+
* uses it for "new workspace / new session": the directory is materialised so
|
|
955
|
+
* a brand-new workspace actually exists on disk, the path is resolved to its
|
|
956
|
+
* (idempotent) Workspace, and the session is created with `workspaceId` so it
|
|
957
|
+
* lands under that workspace in the sidebar. Creating with bare `cwd` instead
|
|
958
|
+
* would leave the session in the ungrouped bucket even when its working
|
|
959
|
+
* directory matches an existing workspace path.
|
|
956
960
|
*/
|
|
957
961
|
const handleAgentCreate = async (req, res) => {
|
|
958
962
|
try {
|
|
@@ -984,10 +988,24 @@ function registerRoutes(ctx, deps) {
|
|
|
984
988
|
}, 503);
|
|
985
989
|
return;
|
|
986
990
|
}
|
|
991
|
+
const ws = deps.getWorkspaceRegistry();
|
|
987
992
|
if (cwd.length > 0) await mkdir(cwd, { recursive: true });
|
|
993
|
+
let created;
|
|
994
|
+
if (cwd.length > 0 && ws !== void 0) {
|
|
995
|
+
const workspace = await ws.create(cwd);
|
|
996
|
+
created = await sc.create({ workspaceId: workspace.id });
|
|
997
|
+
json$1(res, {
|
|
998
|
+
ok: true,
|
|
999
|
+
sessionId: created.sessionId,
|
|
1000
|
+
cwd,
|
|
1001
|
+
workspaceId: workspace.id
|
|
1002
|
+
});
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
created = await sc.create({ cwd: cwd.length > 0 ? cwd : void 0 });
|
|
988
1006
|
json$1(res, {
|
|
989
1007
|
ok: true,
|
|
990
|
-
sessionId:
|
|
1008
|
+
sessionId: created.sessionId,
|
|
991
1009
|
cwd: cwd || null
|
|
992
1010
|
});
|
|
993
1011
|
} catch (err) {
|
|
@@ -2327,6 +2345,12 @@ function defineTool(options) {
|
|
|
2327
2345
|
*
|
|
2328
2346
|
* @module dsh-tiddlywiki/host/tools
|
|
2329
2347
|
*/
|
|
2348
|
+
/**
|
|
2349
|
+
* 约定标签:标记「由 Agent 撰写」的笔记。
|
|
2350
|
+
* 新建(title 不存在)时由 tiddlywiki_put / tiddlywiki_batch_put 自动补打;
|
|
2351
|
+
* 首页据此把这类笔记单独列在「Agent 区块」并从主标签列表排除。
|
|
2352
|
+
*/
|
|
2353
|
+
const AGENT_WRITTEN_TAG = "agent-written";
|
|
2330
2354
|
function snippetOf(text, max = 160) {
|
|
2331
2355
|
const flat = text.replace(/\s+/g, " ").trim();
|
|
2332
2356
|
return flat.length <= max ? flat : `${flat.slice(0, max)}…`;
|
|
@@ -2376,6 +2400,20 @@ function rewriteRefs(text, oldTitle, newTitle) {
|
|
|
2376
2400
|
count
|
|
2377
2401
|
};
|
|
2378
2402
|
}
|
|
2403
|
+
/**
|
|
2404
|
+
* Compute the final tags for a write:
|
|
2405
|
+
* - NEW tiddler (created by this tool) → auto-append the agent-written tag,
|
|
2406
|
+
* unless it is a `$:/` system tiddler (config/language/theme internals).
|
|
2407
|
+
* - Existing tiddler → keep the caller's tags as-is (an agent maintaining a
|
|
2408
|
+
* human note must NOT silently claim authorship; an already agent-written
|
|
2409
|
+
* note keeps its tag because the caller provides the full tag list).
|
|
2410
|
+
*/
|
|
2411
|
+
function finalTagsForWrite(title, existing, tags) {
|
|
2412
|
+
if (existing !== void 0) return tags;
|
|
2413
|
+
if (title.startsWith("$:/")) return tags;
|
|
2414
|
+
if (tags.includes("agent-written")) return tags;
|
|
2415
|
+
return [...tags, AGENT_WRITTEN_TAG];
|
|
2416
|
+
}
|
|
2379
2417
|
function registerTiddlywikiTools(ctx, deps) {
|
|
2380
2418
|
const disposers = [];
|
|
2381
2419
|
const register = (tool) => {
|
|
@@ -2584,7 +2622,7 @@ function registerTiddlywikiTools(ctx, deps) {
|
|
|
2584
2622
|
}));
|
|
2585
2623
|
register(defineTool({
|
|
2586
2624
|
name: "tiddlywiki_put",
|
|
2587
|
-
description: "写入(新建或覆盖)一个 TiddlyWiki tiddler。同名覆盖;tags 为标签数组,fields 为附加自定义字段(json 对象,会写入 tiddler 字段)。写入后触发自动 commit
|
|
2625
|
+
description: "写入(新建或覆盖)一个 TiddlyWiki tiddler。同名覆盖;tags 为标签数组,fields 为附加自定义字段(json 对象,会写入 tiddler 字段)。写入后触发自动 commit。新建(title 不存在)时自动补打 agent-written 标签标记「由 Agent 撰写」,无需手动添加。",
|
|
2588
2626
|
parameters: {
|
|
2589
2627
|
title: {
|
|
2590
2628
|
type: "string",
|
|
@@ -2624,25 +2662,27 @@ function registerTiddlywikiTools(ctx, deps) {
|
|
|
2624
2662
|
execute: async (args) => {
|
|
2625
2663
|
const wiki = deps.wiki();
|
|
2626
2664
|
if (wiki === void 0) throw new Error("TiddlyWiki 服务未运行(tiddlywiki_status 可查)");
|
|
2665
|
+
const existing = await wiki.get(args.title).catch(() => void 0);
|
|
2666
|
+
const tags = finalTagsForWrite(args.title, existing, Array.isArray(args.tags) ? args.tags.filter((t) => typeof t === "string" && t.trim().length > 0) : []);
|
|
2627
2667
|
const tiddler = {
|
|
2628
2668
|
title: args.title,
|
|
2629
2669
|
text: args.text
|
|
2630
2670
|
};
|
|
2631
|
-
if (
|
|
2671
|
+
if (tags.length > 0) tiddler.tags = tags;
|
|
2632
2672
|
if (args.fields !== void 0 && typeof args.fields === "object" && args.fields !== null) Object.assign(tiddler, args.fields);
|
|
2633
2673
|
await wiki.put(tiddler);
|
|
2634
2674
|
deps.autoCommit();
|
|
2635
2675
|
return {
|
|
2636
2676
|
ok: true,
|
|
2637
2677
|
title: args.title,
|
|
2638
|
-
tags
|
|
2678
|
+
tags,
|
|
2639
2679
|
fields: args.fields ?? null
|
|
2640
2680
|
};
|
|
2641
2681
|
}
|
|
2642
2682
|
}));
|
|
2643
2683
|
register(defineTool({
|
|
2644
2684
|
name: "tiddlywiki_batch_put",
|
|
2645
|
-
description: "批量写入/覆盖多个 TiddlyWiki tiddler(一次工具调用)。overwrite=false 时跳过已存在的标题;返回逐条结果。写入后触发自动 commit
|
|
2685
|
+
description: "批量写入/覆盖多个 TiddlyWiki tiddler(一次工具调用)。overwrite=false 时跳过已存在的标题;返回逐条结果。写入后触发自动 commit。新建(title 不存在)的条目会自动补打 agent-written 标签,无需手动添加。",
|
|
2646
2686
|
parameters: {
|
|
2647
2687
|
items: {
|
|
2648
2688
|
type: "array",
|
|
@@ -2706,22 +2746,22 @@ function registerTiddlywikiTools(ctx, deps) {
|
|
|
2706
2746
|
for (const item of list) {
|
|
2707
2747
|
if (typeof item.title !== "string" || item.title.length === 0) throw new Error("batch_put: 每条 items 都需要非空 title");
|
|
2708
2748
|
if (typeof item.text !== "string") throw new Error(`batch_put: items「${item.title}」缺少 text`);
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
}
|
|
2749
|
+
const existing = await wiki.get(item.title).catch(() => void 0);
|
|
2750
|
+
if (!overwrite && existing !== void 0) {
|
|
2751
|
+
skipped++;
|
|
2752
|
+
results.push({
|
|
2753
|
+
title: item.title,
|
|
2754
|
+
written: false,
|
|
2755
|
+
skipped: true
|
|
2756
|
+
});
|
|
2757
|
+
continue;
|
|
2719
2758
|
}
|
|
2759
|
+
const tags = finalTagsForWrite(item.title, existing, Array.isArray(item.tags) ? item.tags.filter((t) => typeof t === "string" && t.trim().length > 0) : []);
|
|
2720
2760
|
const tiddler = {
|
|
2721
2761
|
title: item.title,
|
|
2722
2762
|
text: item.text
|
|
2723
2763
|
};
|
|
2724
|
-
if (
|
|
2764
|
+
if (tags.length > 0) tiddler.tags = tags;
|
|
2725
2765
|
if (item.fields !== void 0 && typeof item.fields === "object" && item.fields !== null) Object.assign(tiddler, item.fields);
|
|
2726
2766
|
await wiki.put(tiddler);
|
|
2727
2767
|
written++;
|
|
@@ -2806,7 +2846,10 @@ function registerTiddlywikiTools(ctx, deps) {
|
|
|
2806
2846
|
}
|
|
2807
2847
|
}
|
|
2808
2848
|
}
|
|
2809
|
-
await wiki.put(
|
|
2849
|
+
await wiki.put({
|
|
2850
|
+
...cleanTiddler(existing),
|
|
2851
|
+
title: newTitle
|
|
2852
|
+
});
|
|
2810
2853
|
await wiki.delete(oldTitle);
|
|
2811
2854
|
if (refsTiddlers === 0) warning = "未找到任何其他 tiddler 引用旧标题;如确实需要,可手动补充链接。";
|
|
2812
2855
|
deps.autoCommit();
|
|
@@ -3179,7 +3222,9 @@ pull 冲突后:先 \`tiddlywiki_git_resolve files=[冲突文件] strategy=keep
|
|
|
3179
3222
|
|
|
3180
3223
|
把 wiki 当作长期记忆与知识沉淀的地方:会议纪要、决策记录、调研笔记、随手的想法都可存成独立 tiddler(tag 建议用 inbox/meeting/decision 等便于检索)。
|
|
3181
3224
|
|
|
3182
|
-
用本插件自动创建笔记时,除了业务性 tag 外,请把「当前工作区(项目)的名字」也作为标签之一加上去(例如 \`tiddlywiki_put\` 的 tags 里带上当前 workspace
|
|
3225
|
+
用本插件自动创建笔记时,除了业务性 tag 外,请把「当前工作区(项目)的名字」也作为标签之一加上去(例如 \`tiddlywiki_put\` 的 tags 里带上当前 workspace 名),这样笔记能按项目归集、检索。
|
|
3226
|
+
|
|
3227
|
+
**Agent 笔记标签约定**:\`tiddlywiki_put\` / \`tiddlywiki_batch_put\` 新建笔记时,插件会自动补打 \`agent-written\` 标签(标记「由 Agent 撰写」),无需手动添加,也不要手动移除它(除非用户明确要求)。首页会把 Agent 笔记单独列在「Agent 区块」,主标签列表只统计人类笔记。若某篇 Agent 笔记后续被人类编辑过,请在该笔记上补打 \`human-edited\` 标签,首页会把它归入「Agent + 人工」档。覆盖写入已有的(人类)笔记时不会自动加 agent-written,请保持笔记原本的归属。`;
|
|
3183
3228
|
/**
|
|
3184
3229
|
* Mount the host half.
|
|
3185
3230
|
* @param ctx - the plugin context (tools + systemPrompt injected).
|
|
@@ -3332,6 +3377,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
3332
3377
|
ctx.inject(["webServer"], (webCtx) => {
|
|
3333
3378
|
const ws = webCtx.webServer;
|
|
3334
3379
|
const getSessionController = () => ctx.get("sessionController");
|
|
3380
|
+
const getWorkspaceRegistry = () => ctx.get("workspaceRegistry");
|
|
3335
3381
|
const disposeRoutes = registerRoutes({ webServer: ws }, {
|
|
3336
3382
|
server,
|
|
3337
3383
|
getClient: client,
|
|
@@ -3341,6 +3387,7 @@ function apply(ctx, rawConfig = {}) {
|
|
|
3341
3387
|
uiDefaults: () => effectiveUi(),
|
|
3342
3388
|
getWikiPath: () => wikiPath,
|
|
3343
3389
|
getSessionController,
|
|
3390
|
+
getWorkspaceRegistry,
|
|
3344
3391
|
sendToAgentEnabled: () => eff().ui?.sendToAgent?.enabled !== false,
|
|
3345
3392
|
sendToAgentToken: () => {
|
|
3346
3393
|
const token = eff().ui?.sendToAgent?.token;
|
|
@@ -3370,6 +3417,6 @@ function apply(ctx, rawConfig = {}) {
|
|
|
3370
3417
|
}, "dsh-tiddlywiki: host teardown");
|
|
3371
3418
|
}
|
|
3372
3419
|
//#endregion
|
|
3373
|
-
export { AutoCommitter, ConfigStore, DOC_NOTE_TAG, DOC_NOTE_TEXT, DOC_NOTE_TITLE, GitFace, PATH_PREFIX, TW_PROXY_PATH, TW_PROXY_PREFIX, TW_WEB_HOST_TIDDLER, TiddlyWebClient, WikiServer, apply, bundledCatalog, deepMerge, defineTool, dshHomePath, ensureLanguage, ensureTwWebHost, inject, name, normalizeThemes, openInTwEditor, readWikiInfo, registerAdminRoutes, registerRoutes, resolveTwRoot, seedDocNote, writeWikiInfo };
|
|
3420
|
+
export { AutoCommitter, ConfigStore, DOC_NOTE_TAG, DOC_NOTE_TEXT, DOC_NOTE_TITLE, GitFace, PATH_PREFIX, TW_PROXY_PATH, TW_PROXY_PREFIX, TW_WEB_HOST_TIDDLER, TiddlyWebClient, WikiServer, apply, bundledCatalog, deepMerge, defineTool, dshHomePath, ensureLanguage, ensureTwWebHost, inject, name, normalizeThemes, openInTwEditor, readWikiInfo, registerAdminRoutes, registerRoutes, registerTiddlywikiTools, resolveTwRoot, seedDocNote, writeWikiInfo };
|
|
3374
3421
|
|
|
3375
3422
|
//# sourceMappingURL=index.js.map
|