dsh-reference-anything 0.4.0 → 0.4.2
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 +6 -6
- package/lib/client.js +91 -13
- package/lib/contract.js +2 -2
- package/lib/sources/local-agent/adapters/pi.js +5 -3
- package/lib/sources/local-agent/index.js +3 -1
- package/lib/sources/local-agent/scan.d.ts +9 -0
- package/lib/sources/local-agent/scan.js +72 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -70,18 +70,18 @@ Type `@`, search across enabled sources, and insert the selected reference into
|
|
|
70
70
|
|
|
71
71
|
**The External conversations group** — and only that group — uses OpenCLI to reach AI chat sessions you are already logged into. By default it stores conversation titles locally and the agent fetches remote content on demand; an optional offline-mirror mode stores the latest complete bodies locally instead. **Local agent conversations need none of that**: those transcripts are already files on your own disk, so that group reads them directly, with no browser, no OpenCLI, and nothing mirrored.
|
|
72
72
|
|
|
73
|
-
> [!IMPORTANT]
|
|
74
|
-
> v0.4.0 targets DSH `>=0.1.2-rc.1` and uses the RC1 Skills Remote, Session snapshot API, native `@` trigger menu, official file/session Remotes, and native Composer reference rendering. It is incompatible with DSH versions older than `0.1.2-rc.1`.
|
|
75
|
-
> The `0.3.x` line remains on the current stable DSH SDK (`0.1.0-rc.8 ~ 0.1.1-rc.2`). Due to breaking changes, starting with version `v0.4.0`, development releases will target DSH `v0.1.2-rc.1` or newer, use the npm `alpha` tag, and no longer support older DSH releases.
|
|
76
|
-
|
|
77
73
|
> [!NOTE]
|
|
78
74
|
> DSH is currently in Beta, so its underlying capabilities and interfaces may change as it evolves. This plugin will adapt alongside those changes. Because of some current DSH limitations, parts of the implementation may not yet be ideal; we will continue to follow DSH updates and improve the plugin over time. See the relevant sections below for specific limitations and usage notes.
|
|
79
75
|
|
|
80
76
|
## 📰 News
|
|
81
77
|
|
|
78
|
+
- **2026-09-28 · v0.4.2 — Important update** — Fixed a fatal plugin compatibility error with the current DSH interface. During plugin loading, DSH now requires every strict `agentSearch` registration codec to provide a `create()` validator factory; v0.4.1 supplied only validation rules, so DSH rejected the plugin before search could run. This release adds the required factory and fixes command icon sizing plus bilingual command labels in the native picker.
|
|
79
|
+
|
|
80
|
+
- **2026-09-25 · v0.4.1** — We're back!!🎉🎉 Improved local-agent session titles by reading Codex's own `session_index.jsonl` and added Pi/Codex title support. Restored the native DSH handling for `@` menu group headings to avoid translucent overlap and unnecessary custom blur rendering; bounded index reads to 16 MiB for predictable resource use.
|
|
81
|
+
|
|
82
82
|
- **2026-09-03 · v0.4.0** — **Compatibility: DSH `>=0.1.2-rc.1`.** Migrated Skills discovery to the DSH RC1 Skills Remote, restored historical reference grants through the RC1 Session snapshot API, and verified the plugin against DSH `0.1.2-rc.1`.
|
|
83
83
|
|
|
84
|
-
- **2026-08-28 · v0.3.3** — Improved dark-theme backgrounds for the reference menu and settings panels, added project screenshot metadata, and refreshed the documentation. This
|
|
84
|
+
- **2026-08-28 · v0.3.3** — Improved dark-theme backgrounds for the reference menu and settings panels, added project screenshot metadata, and refreshed the documentation. This was the final release line targeting the current stable DeepSeek Harness SDK; `v0.4.0` migrated to DeepSeek Harness `v0.1.2-rc.1` under the npm `alpha` tag and does not support older DSH releases.
|
|
85
85
|
- **2026-08-25 · v0.3.2** — Added local-agent conversation references, with detected session counts and custom-folder support. Web AI sync can be age-limited; cloud drives now support folder browsing and quick download-folder access. Settings include update notes, and local-agent tool details stay concise unless expanded.
|
|
86
86
|
- **2026-08-20 · v0.3.0** — Completed the native DSH `@` integration: five independently configurable sources, official file/session Remotes, native Composer references with source logos, in-place expand/collapse and sync actions, and a one-click switch between Reference Anything and the official DSH `@` list. The legacy `dsh-file:` protocol and custom Composer interaction layer were removed.
|
|
87
87
|
|
|
@@ -110,7 +110,7 @@ Install the stable `0.3.x` line for the current stable DSH SDK:
|
|
|
110
110
|
dsh plugin --profile web add dsh-reference-anything@latest
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
Install `v0.4.
|
|
113
|
+
Install `v0.4.2` on DSH `>=0.1.2-rc.1`:
|
|
114
114
|
|
|
115
115
|
```powershell
|
|
116
116
|
dsh plugin --profile web add dsh-reference-anything@alpha
|
package/lib/client.js
CHANGED
|
@@ -14989,7 +14989,7 @@ var agentLookup = {
|
|
|
14989
14989
|
wire: "agentId",
|
|
14990
14990
|
source: "lookup",
|
|
14991
14991
|
lookup: "agent",
|
|
14992
|
-
codec: { mode: "strict", typeSymbol: "@deepseek-ai/dsh-session/types#SessionId", schema: external_exports.string().min(1) }
|
|
14992
|
+
codec: { mode: "strict", typeSymbol: "@deepseek-ai/dsh-session/types#SessionId", schema: external_exports.string().min(1), create: () => external_exports.string().min(1) }
|
|
14993
14993
|
};
|
|
14994
14994
|
var searchInputSchema = external_exports.object({
|
|
14995
14995
|
query: external_exports.string(),
|
|
@@ -15198,7 +15198,7 @@ var REFERENCE_ANYTHING_INVOCATIONS = [
|
|
|
15198
15198
|
descriptor("openListReindex", [{ name: "input", wire: "input", source: "json", codec: strict("OpenListMountInput", openListMountInputSchema) }], strict("OpenListReindex", external_exports.object({ supported: external_exports.boolean(), reason: external_exports.string().optional() }).readonly()), true)
|
|
15199
15199
|
];
|
|
15200
15200
|
function strict(type, schema) {
|
|
15201
|
-
return { mode: "strict", typeSymbol: `dsh-reference-anything#${type}`, schema };
|
|
15201
|
+
return { mode: "strict", typeSymbol: `dsh-reference-anything#${type}`, schema, create: () => schema };
|
|
15202
15202
|
}
|
|
15203
15203
|
function descriptor(method, parameters, result, cancelled = false) {
|
|
15204
15204
|
return {
|
|
@@ -16883,7 +16883,13 @@ var PICKER_ICON_MARKER = {
|
|
|
16883
16883
|
font: "\uE114",
|
|
16884
16884
|
refresh: "\uE115",
|
|
16885
16885
|
agent: "\uE116",
|
|
16886
|
-
drive: "\uE117"
|
|
16886
|
+
drive: "\uE117",
|
|
16887
|
+
goal: "\uE125",
|
|
16888
|
+
plan: "\uE126",
|
|
16889
|
+
feedback: "\uE127",
|
|
16890
|
+
compact: "\uE128",
|
|
16891
|
+
permission: "\uE129",
|
|
16892
|
+
export: "\uE12A"
|
|
16887
16893
|
};
|
|
16888
16894
|
var SESSION_ICON_MARKER = PICKER_ICON_MARKER.session;
|
|
16889
16895
|
var SKILL_ICON_MARKER = PICKER_ICON_MARKER.skill;
|
|
@@ -16937,6 +16943,25 @@ var PICKER_ICON_NODES = {
|
|
|
16937
16943
|
{ tag: "path", attrs: { d: "M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" } },
|
|
16938
16944
|
{ tag: "path", attrs: { d: "M16 16h5v5" } }
|
|
16939
16945
|
],
|
|
16946
|
+
goal: [
|
|
16947
|
+
{ tag: "path", attrs: { d: "M14.5001 8C14.5 9.28552 14.1188 10.5422 13.4045 11.611C12.6903 12.6799 11.6752 13.5129 10.4875 14.0049C9.29982 14.4968 7.99295 14.6255 6.73212 14.3747C5.4713 14.124 4.31314 13.505 3.4041 12.596C2.49514 11.687 1.87614 10.5288 1.62537 9.26798C1.37459 8.00716 1.50331 6.70028 1.99525 5.51261C2.48719 4.32494 3.32025 3.30981 4.3891 2.59557C5.45795 1.88134 6.71458 1.50008 8.0001 1.5" } },
|
|
16948
|
+
{ tag: "path", attrs: { d: "M11.5 8C11.5001 8.69227 11.2948 9.36901 10.9102 9.94463C10.5257 10.5202 9.97901 10.9689 9.33944 11.2338C8.69986 11.4987 7.99609 11.5681 7.31712 11.433C6.63816 11.2979 6.01449 10.9645 5.52501 10.475C5.03548 9.98552 4.70209 9.36185 4.56702 8.68289C4.43195 8.00392 4.50127 7.30015 4.76619 6.66057C5.03112 6.021 5.47976 5.47436 6.05538 5.08978C6.631 4.70519 7.30774 4.49995 8.00001 4.5" } },
|
|
16949
|
+
{ tag: "path", attrs: { d: "M8.00024 7.99976L11.2 4.80005" } }
|
|
16950
|
+
],
|
|
16951
|
+
feedback: [{ tag: "path", attrs: { d: "M4.74024 9.11029L1.82882 7.79865L12.9665 2.60943L12.3914 13.1388L6.12677 9.83657M8.44336 11.0825L6.2832 13.2843V9.86772L12.972 2.78748" } }],
|
|
16952
|
+
plan: [
|
|
16953
|
+
{ tag: "path", attrs: { d: "M4.9375 5.90295H11.0625" } },
|
|
16954
|
+
{ tag: "path", attrs: { d: "M4.9375 9.02991H8.27841" } },
|
|
16955
|
+
{ tag: "path", attrs: { d: "M12.5 1.32617C13.3039 1.32617 14 1.95171 14 2.77637V7.61328L13 8.68164V2.77637C13 2.55186 12.8007 2.32617 12.5 2.32617H3.5C3.1993 2.32617 3 2.55186 3 2.77637V13.2246C3.00044 13.4489 3.19963 13.6738 3.5 13.6738H8.32812L7.39258 14.6738H3.5C2.69637 14.6738 2.00042 14.0489 2 13.2246V2.77637C2 1.95171 2.69613 1.32617 3.5 1.32617H12.5Z" } },
|
|
16956
|
+
{ tag: "path", attrs: { d: "M8.97212 14.3693C9.17511 14.5723 9.37811 14.7753 9.5811 14.9783C9.67012 14.8953 9.75914 14.8123 9.84815 14.7293C11.4505 13.2352 13.0528 11.7411 14.6551 10.247C14.7441 10.164 14.8331 10.081 14.9221 9.99803C14.5989 9.6748 14.2756 9.35157 13.9524 9.02834C13.8694 9.11736 13.7864 9.20637 13.7034 9.29539C12.2093 10.8977 10.7152 12.5 9.22113 14.1023C9.13813 14.1913 9.05513 14.2803 8.97212 14.3693Z" } }
|
|
16957
|
+
],
|
|
16958
|
+
permission: [
|
|
16959
|
+
{ tag: "path", attrs: { d: "M6.59624 2.14853C7.50155 1.80917 8.49914 1.80919 9.40444 2.14859L13.9245 3.84317V7.11961C13.9245 11.6089 10.5565 13.5975 8.00035 14.5779C5.44423 13.5975 2.07544 11.6089 2.07544 7.11961V3.84317L6.59624 2.14853Z" } },
|
|
16960
|
+
{ tag: "path", attrs: { d: "M8 4.39209V9.89209" } },
|
|
16961
|
+
{ tag: "path", attrs: { d: "M8 10.8081V11.8081" } }
|
|
16962
|
+
],
|
|
16963
|
+
compact: [{ tag: "circle", attrs: { cx: "8", cy: "8", r: "6.5" } }, { tag: "path", attrs: { d: "M8 1.5A6.5 6.5 0 0 1 14.5 8" } }],
|
|
16964
|
+
export: [{ tag: "path", attrs: { d: "M8 1.95317V10.0469M4.25 6.29688L8 10.0469L11.75 6.29688M1.5 10.0469V13.158C1.5 13.3937 1.60536 13.6198 1.79289 13.7865C1.98043 13.9532 2.23478 14.0469 2.5 14.0469H13.5C13.7652 14.0469 14.0198 13.9532 14.2071 13.7865C14.3946 13.6198 14.5 13.3937 14.5 13.158V10.0469" } }],
|
|
16940
16965
|
// FolderClosed
|
|
16941
16966
|
folder: [
|
|
16942
16967
|
{ tag: "path", attrs: { d: "M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" } },
|
|
@@ -17667,6 +17692,48 @@ function decodeDriveReference(value) {
|
|
|
17667
17692
|
function formatDriveMention(reference) {
|
|
17668
17693
|
return `@[${escapeLabel(reference.label)}](${driveReferenceUri(reference.id)})`;
|
|
17669
17694
|
}
|
|
17695
|
+
var COMMAND_ICON_KIND = {
|
|
17696
|
+
goal: "goal",
|
|
17697
|
+
plan: "plan",
|
|
17698
|
+
feedback: "feedback",
|
|
17699
|
+
compact: "compact",
|
|
17700
|
+
permission: "permission",
|
|
17701
|
+
export: "export"
|
|
17702
|
+
};
|
|
17703
|
+
var COMMAND_DESCRIPTION_EN = {
|
|
17704
|
+
goal: "Set or view the goal for a long-running task",
|
|
17705
|
+
plan: "Enter or leave plan mode",
|
|
17706
|
+
feedback: "Record feedback about this session",
|
|
17707
|
+
compact: "Compact older conversation history",
|
|
17708
|
+
permission: "Switch the permission preset (sandbox mode + approval policy)",
|
|
17709
|
+
export: "Download this Session log as a ZIP archive"
|
|
17710
|
+
};
|
|
17711
|
+
var COMMAND_DESCRIPTION_ZH = {
|
|
17712
|
+
goal: "\u8BBE\u7F6E\u6216\u67E5\u770B\u957F\u671F\u4EFB\u52A1\u76EE\u6807",
|
|
17713
|
+
plan: "\u8FDB\u5165\u6216\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F",
|
|
17714
|
+
feedback: "\u53D1\u9001\u5173\u4E8E\u5F53\u524D\u4F1A\u8BDD\u7684\u53CD\u9988",
|
|
17715
|
+
compact: "\u538B\u7F29\u4EE5\u4E0A\u5BF9\u8BDD\u5185\u5BB9",
|
|
17716
|
+
permission: "\u5207\u6362\u6743\u9650\u9884\u8BBE\uFF08\u6C99\u7BB1\u6A21\u5F0F\u4E0E\u5BA1\u6279\u7B56\u7565\uFF09",
|
|
17717
|
+
export: "\u5C06\u5F53\u524D\u4F1A\u8BDD\u5185\u5BB9\u5BFC\u51FA\u4E3A ZIP"
|
|
17718
|
+
};
|
|
17719
|
+
var COMMAND_LABEL_EN = {
|
|
17720
|
+
goal: "Goal",
|
|
17721
|
+
plan: "Plan",
|
|
17722
|
+
feedback: "Feedback",
|
|
17723
|
+
compact: "Compact",
|
|
17724
|
+
permission: "Permission",
|
|
17725
|
+
export: "Export",
|
|
17726
|
+
model: "Model"
|
|
17727
|
+
};
|
|
17728
|
+
var COMMAND_LABEL_ZH = {
|
|
17729
|
+
goal: "\u76EE\u6807",
|
|
17730
|
+
plan: "\u8BA1\u5212",
|
|
17731
|
+
feedback: "\u53CD\u9988",
|
|
17732
|
+
compact: "\u538B\u7F29",
|
|
17733
|
+
permission: "\u6743\u9650",
|
|
17734
|
+
export: "\u4E0B\u8F7D\u65E5\u5FD7",
|
|
17735
|
+
model: "\u6A21\u578B"
|
|
17736
|
+
};
|
|
17670
17737
|
function createCommandSource(load, t = fallback, options = { ...DEFAULT_SOURCE_OPTIONS, order: 0 }) {
|
|
17671
17738
|
const source = {
|
|
17672
17739
|
trigger: "@",
|
|
@@ -17676,13 +17743,19 @@ function createCommandSource(load, t = fallback, options = { ...DEFAULT_SOURCE_O
|
|
|
17676
17743
|
const scoped = scopedQuery(query, "commands");
|
|
17677
17744
|
if (scoped === void 0) return [];
|
|
17678
17745
|
const needle = scoped.toLocaleLowerCase();
|
|
17679
|
-
return (await load(session.sessionId, signal)).filter((row) => row.name.toLocaleLowerCase().includes(needle)).map((row) =>
|
|
17680
|
-
|
|
17681
|
-
|
|
17682
|
-
|
|
17683
|
-
|
|
17684
|
-
|
|
17685
|
-
|
|
17746
|
+
return (await load(session.sessionId, signal)).filter((row) => row.name.toLocaleLowerCase().includes(needle)).map((row) => {
|
|
17747
|
+
return {
|
|
17748
|
+
name: (() => {
|
|
17749
|
+
const key = row.name.toLocaleLowerCase();
|
|
17750
|
+
const zh2 = navigator.language.toLowerCase().startsWith("zh");
|
|
17751
|
+
return zh2 ? `${COMMAND_LABEL_ZH[key] ?? row.name} ${row.name}` : COMMAND_LABEL_EN[key] ?? row.name;
|
|
17752
|
+
})(),
|
|
17753
|
+
description: (navigator.language.toLowerCase().startsWith("zh") ? COMMAND_DESCRIPTION_ZH[row.name.toLocaleLowerCase()] : COMMAND_DESCRIPTION_EN[row.name.toLocaleLowerCase()]) ?? row.description,
|
|
17754
|
+
hint: row.input?.hint,
|
|
17755
|
+
icon: PICKER_ICON_MARKER[COMMAND_ICON_KIND[row.name.toLocaleLowerCase()] ?? "command"],
|
|
17756
|
+
value: encodeCandidate({ kind: "command", name: row.name })
|
|
17757
|
+
};
|
|
17758
|
+
});
|
|
17686
17759
|
},
|
|
17687
17760
|
onPick({ candidate }) {
|
|
17688
17761
|
const value = decodeCandidate(candidate.value);
|
|
@@ -29617,16 +29690,17 @@ var css = `
|
|
|
29617
29690
|
caret, selection, wrapping, and message geometry. */
|
|
29618
29691
|
[data-composer-card] [role="listbox"]:has([role="presentation"][data-source]){box-sizing:border-box!important;width:100%!important;min-width:0!important;max-width:100%!important}
|
|
29619
29692
|
[data-trigger-menu]:has(> [role="listbox"] [role="presentation"][data-source]){border-radius:22px}
|
|
29620
|
-
[data-composer-card] [role="listbox"] [role="presentation"][data-source]{position:sticky;top:0;z-index:2;box-sizing:border-box;padding-top:6px!important;background:var(--dsw-specific-menu,var(--dsw-alias-background-primary,var(--dsw-alias-bg-layer-1,#fff)))}
|
|
29621
|
-
[data-composer-card] [role="listbox"] [role="presentation"][data-source]:not(:first-child){margin-top:8px}
|
|
29622
29693
|
[data-composer-card] [role="listbox"] [role="option"]{scroll-margin-block-start:30px;scroll-margin-block-end:4px}
|
|
29623
29694
|
[data-composer-card] [role="listbox"]>[data-dsh-ref-menu-settling]{overflow-anchor:none!important}
|
|
29624
29695
|
[data-composer-card] [role="listbox"]>[data-dsh-ref-menu-settling] [role="option"][aria-selected="false"]:hover{background:transparent!important}
|
|
29625
29696
|
[data-composer-card] [role="listbox"] [role="option"][data-dsh-ref-menu-action]{color:var(--dsw-alias-label-tertiary,#737780)!important}
|
|
29626
29697
|
[data-composer-card] [role="listbox"] [role="option"][data-dsh-ref-menu-action]>span:last-child:not(:first-child){display:none!important}
|
|
29627
29698
|
[data-composer-card] [role="listbox"] .dsh_ref_projected_icon,[data-composer-card] [role="listbox"] .dsh_ref_picker_icon{display:inline-flex!important;align-items:center!important;justify-content:center!important;flex:none;width:16px!important;height:16px!important;line-height:1!important;color:var(--dsw-alias-label-secondary,#5f636b)}
|
|
29699
|
+
[data-composer-card] [role="listbox"] .dsh_ref_command_icon{width:18px!important;height:18px!important}
|
|
29700
|
+
[data-composer-card] [role="listbox"] .dsh_ref_command_icon>svg{width:18px!important;height:18px!important}
|
|
29628
29701
|
[data-composer-card] [role="listbox"] .dsh_ref_dual_icon{width:36px!important;gap:4px}
|
|
29629
29702
|
[data-composer-card] [role="listbox"] :is(.dsh_ref_projected_icon,.dsh_ref_picker_icon)>svg{display:block;width:16px;height:16px;overflow:visible}
|
|
29703
|
+
[data-composer-card] [role="listbox"] .dsh_ref_command_icon,[data-composer-card] [role="listbox"] .dsh_ref_command_icon>svg{width:18px!important;height:18px!important}
|
|
29630
29704
|
[data-composer-card] [data-decoration="chip"][data-dsh-ref-chip-icon]>:first-child>svg{visibility:hidden!important}
|
|
29631
29705
|
[data-composer-card] [data-decoration="chip"][data-dsh-ref-chip-icon]>:first-child:after{content:"";position:absolute;top:50%;left:50%;display:block;width:16px;height:16px;transform:translate(-50%,-50%);background:currentColor;-webkit-mask:var(--dsh-ref-chip-icon-mask) center/contain no-repeat;mask:var(--dsh-ref-chip-icon-mask) center/contain no-repeat;pointer-events:none}
|
|
29632
29706
|
[data-composer-card] [data-composer-chip][data-dsh-ref-chip-icon]>:first-child>svg{background:currentColor;-webkit-mask:var(--dsh-ref-chip-icon-mask) center/contain no-repeat;mask:var(--dsh-ref-chip-icon-mask) center/contain no-repeat}
|
|
@@ -29971,6 +30045,7 @@ function adoptReferenceIconProjection() {
|
|
|
29971
30045
|
node2.replaceChildren(createPickerIcon(kind), ...secondary === void 0 ? [] : [createPickerIcon(secondary)]);
|
|
29972
30046
|
node2.classList.remove("dsh_ref_projected_icon");
|
|
29973
30047
|
node2.classList.add("dsh_ref_picker_icon");
|
|
30048
|
+
node2.classList.toggle("dsh_ref_command_icon", ["goal", "plan", "feedback", "compact", "permission", "export"].includes(kind));
|
|
29974
30049
|
node2.classList.toggle("dsh_ref_dual_icon", secondary !== void 0);
|
|
29975
30050
|
node2.dataset.dshRefMenuIcon = kind;
|
|
29976
30051
|
};
|
|
@@ -29996,7 +30071,10 @@ function adoptReferenceIconProjection() {
|
|
|
29996
30071
|
const source = heading2?.getAttribute("data-source");
|
|
29997
30072
|
const name2 = option.children.item(1)?.textContent?.trim() ?? "";
|
|
29998
30073
|
const description = option.children.item(2)?.textContent?.trim() ?? "";
|
|
29999
|
-
if (source === "Commands")
|
|
30074
|
+
if (source === "Commands") {
|
|
30075
|
+
const commandIcons = { goal: "goal", plan: "plan", feedback: "feedback", compact: "compact", permission: "permission", export: "export" };
|
|
30076
|
+
return paintPicker(icon, commandIcons[name2.toLocaleLowerCase()] ?? "command");
|
|
30077
|
+
}
|
|
30000
30078
|
if (source === "Skills") return paintPicker(icon, "skill");
|
|
30001
30079
|
if (source === "Files and folders") return paintPicker(icon, workspacePathIconKind(name2, name2.endsWith("/") ? "directory" : "file"));
|
|
30002
30080
|
if (source === "DSH sessions") return paintPicker(icon, "session");
|
package/lib/contract.js
CHANGED
|
@@ -25,7 +25,7 @@ export const driveCandidateSchema = z.object({
|
|
|
25
25
|
* lookup back to DSH's native Remotes and removed its last other caller.
|
|
26
26
|
*/
|
|
27
27
|
const agentLookup = { name: 'agent', wire: 'agentId', source: 'lookup', lookup: 'agent',
|
|
28
|
-
codec: { mode: 'strict', typeSymbol: '@deepseek-ai/dsh-session/types#SessionId', schema: z.string().min(1) } };
|
|
28
|
+
codec: { mode: 'strict', typeSymbol: '@deepseek-ai/dsh-session/types#SessionId', schema: z.string().min(1), create: () => z.string().min(1) } };
|
|
29
29
|
export const searchInputSchema = z.object({
|
|
30
30
|
query: z.string(), provider: providerSchema.optional(), limit: z.number().int().min(1).max(100),
|
|
31
31
|
}).readonly();
|
|
@@ -159,7 +159,7 @@ export const REFERENCE_ANYTHING_INVOCATIONS = [
|
|
|
159
159
|
descriptor('openListReindex', [{ name: 'input', wire: 'input', source: 'json', codec: strict('OpenListMountInput', openListMountInputSchema) }], strict('OpenListReindex', z.object({ supported: z.boolean(), reason: z.string().optional() }).readonly()), true),
|
|
160
160
|
];
|
|
161
161
|
function strict(type, schema) {
|
|
162
|
-
return { mode: 'strict', typeSymbol: `dsh-reference-anything#${type}`, schema };
|
|
162
|
+
return { mode: 'strict', typeSymbol: `dsh-reference-anything#${type}`, schema, create: () => schema };
|
|
163
163
|
}
|
|
164
164
|
function descriptor(method, parameters, result, cancelled = false) {
|
|
165
165
|
return {
|
|
@@ -82,9 +82,11 @@ export const piAdapter = {
|
|
|
82
82
|
createdAt ??= parseTimestamp(record['timestamp']);
|
|
83
83
|
continue;
|
|
84
84
|
}
|
|
85
|
-
// A rename writes another `session_info`, so the newest one wins.
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
// A rename writes another `session_info`, so the newest one wins. Some
|
|
86
|
+
// Pi-compatible writers call the same field `title`.
|
|
87
|
+
if (record['type'] === 'session_info') {
|
|
88
|
+
named = stringField(record, 'name') ?? stringField(record, 'title') ?? named;
|
|
89
|
+
}
|
|
88
90
|
}
|
|
89
91
|
for (const line of headLines) {
|
|
90
92
|
const record = parseRecord(line);
|
|
@@ -643,7 +643,9 @@ function foldsToNothing(adapter, lines, options) {
|
|
|
643
643
|
return adapter.flush(state, options).length === 0;
|
|
644
644
|
}
|
|
645
645
|
function labelFor(descriptor, bookmark) {
|
|
646
|
-
|
|
646
|
+
// Some file-backed agents expose a title index beside the transcript. It is
|
|
647
|
+
// fresher than a persisted first-prompt bookmark and must win when present.
|
|
648
|
+
const title = descriptor.title?.trim() || bookmark?.title.trim() || '';
|
|
647
649
|
return title === '' ? basename(descriptor.relPath) : title;
|
|
648
650
|
}
|
|
649
651
|
/** The schema's own defaults, as a plain object. */
|
|
@@ -40,6 +40,15 @@ export interface TranscriptDescriptor {
|
|
|
40
40
|
readonly relPath: string;
|
|
41
41
|
readonly mtimeMs: number;
|
|
42
42
|
readonly size: number;
|
|
43
|
+
/**
|
|
44
|
+
* A title supplied by an index beside a file-backed transcript.
|
|
45
|
+
*
|
|
46
|
+
* Codex keeps its user-facing session title in `~/.codex/session_index.jsonl`,
|
|
47
|
+
* while the rollout itself only contains the opening prompt. This value is
|
|
48
|
+
* kept on the descriptor so a fresh index title can override an older
|
|
49
|
+
* first-prompt bookmark without changing the transcript adapter contract.
|
|
50
|
+
*/
|
|
51
|
+
readonly title?: string;
|
|
43
52
|
/**
|
|
44
53
|
* The session row, for a database-backed format only.
|
|
45
54
|
*
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
* @module dsh-reference-anything/local-agent/scan
|
|
18
18
|
*/
|
|
19
19
|
import { createReadStream } from 'node:fs';
|
|
20
|
-
import { open, readdir, stat } from 'node:fs/promises';
|
|
21
|
-
import { join, relative } from 'node:path';
|
|
20
|
+
import { open, readdir, readFile, stat } from 'node:fs/promises';
|
|
21
|
+
import { basename, join, relative, resolve } from 'node:path';
|
|
22
22
|
import { ReferenceAnythingError } from "../../errors.js";
|
|
23
23
|
import { withDatabase } from "./sqlite.js";
|
|
24
24
|
import { isQueryAdapter } from "./types.js";
|
|
@@ -26,6 +26,7 @@ import { isQueryAdapter } from "./types.js";
|
|
|
26
26
|
export const SESSION_SEPARATOR = '#';
|
|
27
27
|
/** Directory depth walked below each root. */
|
|
28
28
|
const MAX_DEPTH = 6;
|
|
29
|
+
const MAX_CODEX_TITLE_INDEX_BYTES = 16 * 1024 * 1024;
|
|
29
30
|
/** Probe windows, in bytes, tried in order until enough lines are recovered. */
|
|
30
31
|
const PROBE_STEPS = [32 * 1024, 256 * 1024, 2 * 1024 * 1024];
|
|
31
32
|
/** Chunk size for walking a large transcript backwards from its end. */
|
|
@@ -48,12 +49,15 @@ export async function listTranscripts(roots, adapters, maxTranscripts, signal) {
|
|
|
48
49
|
const adapter = adapters.get(root.kind);
|
|
49
50
|
if (adapter === undefined)
|
|
50
51
|
continue;
|
|
51
|
-
|
|
52
|
+
const titles = root.kind === 'codex' && !isQueryAdapter(adapter)
|
|
53
|
+
? await readCodexTitleIndex(root.path)
|
|
54
|
+
: undefined;
|
|
55
|
+
await walk(root, root.path, 0, adapter, found, signal, maxTranscripts, titles);
|
|
52
56
|
}
|
|
53
57
|
found.sort((left, right) => right.mtimeMs - left.mtimeMs);
|
|
54
58
|
return found.slice(0, maxTranscripts);
|
|
55
59
|
}
|
|
56
|
-
async function walk(root, dir, depth, adapter, found, signal, maxSessions = 200) {
|
|
60
|
+
async function walk(root, dir, depth, adapter, found, signal, maxSessions = 200, titles) {
|
|
57
61
|
signal?.throwIfAborted();
|
|
58
62
|
if (depth > MAX_DEPTH)
|
|
59
63
|
return;
|
|
@@ -63,7 +67,7 @@ async function walk(root, dir, depth, adapter, found, signal, maxSessions = 200)
|
|
|
63
67
|
for (const entry of entries) {
|
|
64
68
|
const path = join(dir, entry.name);
|
|
65
69
|
if (entry.isDirectory()) {
|
|
66
|
-
await walk(root, path, depth + 1, adapter, found, signal, maxSessions);
|
|
70
|
+
await walk(root, path, depth + 1, adapter, found, signal, maxSessions, titles);
|
|
67
71
|
continue;
|
|
68
72
|
}
|
|
69
73
|
if (!entry.isFile())
|
|
@@ -78,9 +82,71 @@ async function walk(root, dir, depth, adapter, found, signal, maxSessions = 200)
|
|
|
78
82
|
found.push(...await expandSessions(root.kind, path, relPath, stats.mtimeMs, stats.size, adapter, maxSessions));
|
|
79
83
|
continue;
|
|
80
84
|
}
|
|
81
|
-
found.push({
|
|
85
|
+
found.push({
|
|
86
|
+
kind: root.kind,
|
|
87
|
+
path,
|
|
88
|
+
relPath,
|
|
89
|
+
mtimeMs: stats.mtimeMs,
|
|
90
|
+
size: stats.size,
|
|
91
|
+
...titles === undefined ? {} : titleForCodexPath(path, titles),
|
|
92
|
+
});
|
|
82
93
|
}
|
|
83
94
|
}
|
|
95
|
+
/** Read the Codex title index once per configured sessions root. */
|
|
96
|
+
async function readCodexTitleIndex(sessionsRoot) {
|
|
97
|
+
const indexPath = resolve(sessionsRoot, '..', 'session_index.jsonl');
|
|
98
|
+
const indexStats = await stat(indexPath).catch(() => undefined);
|
|
99
|
+
// Keep discovery bounded; an unexpectedly large index must not turn a
|
|
100
|
+
// keystroke-triggered scan into an unbounded allocation.
|
|
101
|
+
if (indexStats === undefined || indexStats.size > MAX_CODEX_TITLE_INDEX_BYTES)
|
|
102
|
+
return undefined;
|
|
103
|
+
const raw = await readFile(indexPath, 'utf8').catch(() => undefined);
|
|
104
|
+
if (raw === undefined)
|
|
105
|
+
return undefined;
|
|
106
|
+
const byPath = new Map();
|
|
107
|
+
const bySessionId = new Map();
|
|
108
|
+
for (const line of raw.split(/\r?\n/u)) {
|
|
109
|
+
if (line.trim() === '')
|
|
110
|
+
continue;
|
|
111
|
+
let record;
|
|
112
|
+
try {
|
|
113
|
+
record = JSON.parse(line);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (typeof record !== 'object' || record === null)
|
|
119
|
+
continue;
|
|
120
|
+
const row = record;
|
|
121
|
+
const title = typeof row['thread_name'] === 'string' ? row['thread_name'].trim() : '';
|
|
122
|
+
if (title === '')
|
|
123
|
+
continue;
|
|
124
|
+
const id = typeof row['id'] === 'string' ? row['id'].trim() : '';
|
|
125
|
+
if (id !== '')
|
|
126
|
+
bySessionId.set(id, title);
|
|
127
|
+
const rolloutPath = typeof row['rollout_path'] === 'string' ? row['rollout_path'].trim() : '';
|
|
128
|
+
if (rolloutPath !== '')
|
|
129
|
+
byPath.set(normalizeIndexedPath(rolloutPath), title);
|
|
130
|
+
}
|
|
131
|
+
return { byPath, bySessionId };
|
|
132
|
+
}
|
|
133
|
+
function titleForCodexPath(path, index) {
|
|
134
|
+
const direct = index.byPath.get(normalizeIndexedPath(path));
|
|
135
|
+
if (direct !== undefined)
|
|
136
|
+
return { title: direct };
|
|
137
|
+
const match = basename(path).match(/-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:_[^.]*)?\.jsonl$/iu);
|
|
138
|
+
const sessionId = match?.[1];
|
|
139
|
+
const title = sessionId === undefined ? undefined : index.bySessionId.get(sessionId);
|
|
140
|
+
return title === undefined ? {} : { title };
|
|
141
|
+
}
|
|
142
|
+
/** Normalize Windows paths from the index and from the active filesystem. */
|
|
143
|
+
function normalizeIndexedPath(path) {
|
|
144
|
+
return path
|
|
145
|
+
.replace(/^\\\\\?\\/u, '')
|
|
146
|
+
.replace(/[\\/]+/gu, '\\')
|
|
147
|
+
.replace(/\\$/u, '')
|
|
148
|
+
.toLocaleLowerCase();
|
|
149
|
+
}
|
|
84
150
|
/**
|
|
85
151
|
* Turn one database into a descriptor per conversation inside it.
|
|
86
152
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-reference-anything",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Reference commands, skills, workspace files, DSH sessions, local agent transcripts, cloud-drive files, and mirrored web-chat conversations from one DeepSeek Harness @ menu",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|