dsh-as-aistudio 0.4.4 → 0.4.6
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/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/src/client.js +5 -32
- package/src/components.js +1 -1
- package/src/vendor/host/dsh-edit-turn.js +24 -13
- package/src/vendor/host/dsh-edit-turn.patch.js +1 -1
- package/src/vendor/versions.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,22 @@
|
|
|
4
4
|
|
|
5
5
|
## 中文
|
|
6
6
|
|
|
7
|
+
**0.4.6** —— 复制已修好,临时诊断撤掉;`/state` 再快一档。
|
|
8
|
+
|
|
9
|
+
- **组件跟进**:`dsh-edit-turn` **0.5.12**、`dsh-rerun-turn` 0.2.6、`dsh-delete-turn` 0.1.15、`dsh-markdown-bubble` 0.1.5。
|
|
10
|
+
|
|
11
|
+
- **复制修好了**:根因是 `/state` 太大太慢(25 MB / 13 秒),那段时间里浏览器半部没有任何编辑条目,按下复制不会被插件接管 —— 瘦身之后复制拿到的是改写后的文本。0.4.4 加的自报诊断按计划撤掉。
|
|
12
|
+
|
|
13
|
+
- **再提速**:`rollbackLedger` 原本自己又折了一遍表面(`/state` 已经折过),31k 事件等于走两遍;现在折一次、四个遍历共用同一份索引。
|
|
14
|
+
|
|
15
|
+
- `dsh-edit-turn` 同时把工具链依赖的 `dsh-session-format-catalog` 写进了 devDependencies(之前只在 node_modules 里,重装就丢)。
|
|
16
|
+
|
|
17
|
+
**0.4.5** —— `/state` 再提速(跟进 `dsh-edit-turn` 0.5.11)。
|
|
18
|
+
|
|
19
|
+
- **组件跟进**:`dsh-edit-turn` **0.5.11**、`dsh-rerun-turn` 0.2.6、`dsh-delete-turn` 0.1.15、`dsh-markdown-bubble` 0.1.5。
|
|
20
|
+
|
|
21
|
+
- 回复列表不再构建分块:同一个会话 **2,227 ms → 29 ms**(中间数据 22.4 MB → 1.1 MB)。编辑笔的出现不再等这一下。
|
|
22
|
+
|
|
7
23
|
**0.4.4** —— 复制失败的诊断(跟进 `dsh-edit-turn` 0.5.10)。
|
|
8
24
|
|
|
9
25
|
- **组件跟进**:`dsh-edit-turn` **0.5.10**(另三个不变:`dsh-rerun-turn` 0.2.6、`dsh-delete-turn` 0.1.15、`dsh-markdown-bubble` 0.1.5)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-as-aistudio",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"description": "Google-AI-Studio-style turn controls for DeepSeek Harness, in one install: edit a prompt and re-run it, re-run a reply in place, delete a turn from the model context, and render sent prompts as Markdown. Self-contained: the plugin list shows this one row, and the four components are vendored inside it - installing the studio installs nothing else.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
package/src/client.js
CHANGED
|
@@ -43,7 +43,7 @@ window.__ModuleLoader__.load({
|
|
|
43
43
|
const RERUN_PREFIX = '/dsh-rerun-turn'
|
|
44
44
|
|
|
45
45
|
/** Keep in sync with package.json and lib/index.js. */
|
|
46
|
-
const PLUGIN_VERSION = '0.5.
|
|
46
|
+
const PLUGIN_VERSION = '0.5.12'
|
|
47
47
|
|
|
48
48
|
// --- copy -----------------------------------------------------------------
|
|
49
49
|
|
|
@@ -1999,24 +1999,6 @@ window.__ModuleLoader__.load({
|
|
|
1999
1999
|
})()
|
|
2000
2000
|
const rowCopyText = copyRegistry.text
|
|
2001
2001
|
|
|
2002
|
-
// TEMP DIAG (删除时机:复制修好后). 复制按下没被接管时,把原因写进标签页标题:
|
|
2003
|
-
// 不污染剪贴板、不改页面内容,用户念一眼标题即可;成功接管时自动恢复原标题。
|
|
2004
|
-
const copyDiag = (page) => {
|
|
2005
|
-
try {
|
|
2006
|
-
if (page.__dshetTitle === undefined) page.__dshetTitle = document.title
|
|
2007
|
-
const base = String(page.__dshetTitle ?? '')
|
|
2008
|
-
const show = (reason) => {
|
|
2009
|
-
document.title = `[复制诊断] ${reason}${base === '' ? '' : ' · ' + base}`
|
|
2010
|
-
}
|
|
2011
|
-
const clear = () => {
|
|
2012
|
-
if (String(document.title).startsWith('[复制诊断]')) document.title = base
|
|
2013
|
-
}
|
|
2014
|
-
return { show, clear }
|
|
2015
|
-
} catch {
|
|
2016
|
-
return { show: () => {}, clear: () => {} }
|
|
2017
|
-
}
|
|
2018
|
-
}
|
|
2019
|
-
const titleDiag = typeof globalThis !== 'undefined' ? copyDiag(globalThis) : { show: () => {}, clear: () => {} }
|
|
2020
2002
|
const rowHostText = copyRegistry.host
|
|
2021
2003
|
|
|
2022
2004
|
/**
|
|
@@ -2148,11 +2130,6 @@ window.__ModuleLoader__.load({
|
|
|
2148
2130
|
const native = clipboard.writeText.bind(clipboard)
|
|
2149
2131
|
const wrapped = (value) => {
|
|
2150
2132
|
const rewritten = rewriteCopiedText(String(value ?? ''))
|
|
2151
|
-
if (rewritten === null && rowCopyText.size > 0) {
|
|
2152
|
-
titleDiag.show(`写入没匹配上(登记 ${rowCopyText.size} 行,长度 ${String(value ?? '').length})`)
|
|
2153
|
-
} else if (rewritten !== null) {
|
|
2154
|
-
titleDiag.clear()
|
|
2155
|
-
}
|
|
2156
2133
|
return rewritten === null ? native(value) : native(rewritten)
|
|
2157
2134
|
}
|
|
2158
2135
|
wrapped[CLIPBOARD_WRAPPED] = true
|
|
@@ -4993,15 +4970,11 @@ window.__ModuleLoader__.load({
|
|
|
4993
4970
|
// Our own buttons sit in the same bar: theirs is not this press.
|
|
4994
4971
|
if (pluginOwned(button)) return
|
|
4995
4972
|
const row = button.closest('[data-chat-flow-key]')
|
|
4996
|
-
if (row === null)
|
|
4973
|
+
if (row === null) return
|
|
4997
4974
|
const key = row.getAttribute('data-chat-flow-key')
|
|
4998
|
-
if (typeof key !== 'string' || key === '')
|
|
4975
|
+
if (typeof key !== 'string' || key === '') return
|
|
4999
4976
|
const text = rowCopyText.get(key)
|
|
5000
|
-
if (typeof text !== 'string')
|
|
5001
|
-
titleDiag.show(`这一行没登记文本(登记 ${rowCopyText.size} 行)`)
|
|
5002
|
-
return
|
|
5003
|
-
}
|
|
5004
|
-
titleDiag.clear()
|
|
4977
|
+
if (typeof text !== 'string') return
|
|
5005
4978
|
const write = primitives !== null && primitives !== undefined && typeof primitives.writeClipboard === 'function'
|
|
5006
4979
|
? primitives.writeClipboard
|
|
5007
4980
|
: null
|
|
@@ -9224,7 +9197,7 @@ window.__ModuleLoader__.load({
|
|
|
9224
9197
|
const NS = 'dsh-as-aistudio'
|
|
9225
9198
|
|
|
9226
9199
|
/** Keep in sync with package.json and src/components.js. */
|
|
9227
|
-
const PLUGIN_VERSION = '0.4.
|
|
9200
|
+
const PLUGIN_VERSION = '0.4.6'
|
|
9228
9201
|
|
|
9229
9202
|
/** Presence marker the live verifier reads. */
|
|
9230
9203
|
const DEBUG_KEY = '__DSH_AS_AISTUDIO__'
|
package/src/components.js
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
export const STUDIO_ID = 'dsh-as-aistudio'
|
|
27
27
|
|
|
28
28
|
/** Keep in sync with package.json and src/client.js. */
|
|
29
|
-
export const STUDIO_VERSION = '0.4.
|
|
29
|
+
export const STUDIO_VERSION = '0.4.6'
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* The AI Studio action strip this studio composes, in the order the user meets
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// dsh-edit-turn host half (dsh-edit-turn.js), VENDORED by tools/vendor.mjs - DO NOT EDIT.
|
|
2
2
|
//
|
|
3
|
-
// Source: ../dsh-edit-turn/lib/index.js (v0.5.
|
|
3
|
+
// Source: ../dsh-edit-turn/lib/index.js (v0.5.12, sha256 6adfd5b9699657d5)
|
|
4
4
|
// Regenerate with `npm run vendor`; test/sync.test.js fails when this is stale.
|
|
5
5
|
//
|
|
6
6
|
// src/shell.js imports the copy named after the component, which is why the
|
|
@@ -85,7 +85,7 @@ export const PLUGIN_ID = 'dsh-edit-turn'
|
|
|
85
85
|
export const name = PLUGIN_ID
|
|
86
86
|
|
|
87
87
|
/** Keep in sync with package.json and lib/client.js. */
|
|
88
|
-
export const PLUGIN_VERSION = '0.5.
|
|
88
|
+
export const PLUGIN_VERSION = '0.5.12'
|
|
89
89
|
|
|
90
90
|
// A ring of the last few requests, answering "did the browser half even ask, and
|
|
91
91
|
// what did it get?" without needing its console. Read-only diagnostics: the
|
|
@@ -706,10 +706,13 @@ function copyBlock(block) {
|
|
|
706
706
|
* @returns `{ hidden, edits }`: one hidden entry per shadowed seq, and one
|
|
707
707
|
* record per landed rollback.
|
|
708
708
|
*/
|
|
709
|
-
export function rollbackLedger(events) {
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
709
|
+
export function rollbackLedger(events, options = {}) {
|
|
710
|
+
// A caller that already folded the surface (the state route does) hands it in:
|
|
711
|
+
// folding twice over a long session is the single most expensive thing this
|
|
712
|
+
// route did - 31k events, and every fold walks all of them.
|
|
713
|
+
const folded = options.folded ?? foldSurface(events)
|
|
714
|
+
const bySeq = options.bySeq ?? new Map(events.map((event) => [event.seq, event]))
|
|
715
|
+
const turnOf = options.turnOf ?? turnIndex(events)
|
|
713
716
|
const hidden = []
|
|
714
717
|
const edits = []
|
|
715
718
|
for (const replacement of folded.replacements) {
|
|
@@ -1251,8 +1254,8 @@ export function buildReplayWrites(events, plan, baseTurn, replayId, startSeq, pr
|
|
|
1251
1254
|
* @returns one entry per editable prompt, in conversation order.
|
|
1252
1255
|
*/
|
|
1253
1256
|
export function editableTurns(events, surfaceNodes, options = {}) {
|
|
1254
|
-
const eventBySeq = new Map(events.map((event) => [event.seq, event]))
|
|
1255
|
-
const turnOf = turnIndex(events)
|
|
1257
|
+
const eventBySeq = options.bySeq ?? new Map(events.map((event) => [event.seq, event]))
|
|
1258
|
+
const turnOf = options.turnOf ?? turnIndex(events)
|
|
1256
1259
|
const head = surfaceNodes[0]
|
|
1257
1260
|
const out = []
|
|
1258
1261
|
// Surface order, not log order: a prompt rewritten in place travels as a
|
|
@@ -1308,10 +1311,15 @@ export function editableTurns(events, surfaceNodes, options = {}) {
|
|
|
1308
1311
|
*/
|
|
1309
1312
|
export function editableReplies(events, surfaceNodes, options = {}) {
|
|
1310
1313
|
const nodeIndex = new Map(surfaceNodes.map((seq, index) => [seq, index]))
|
|
1311
|
-
const turnOf = turnIndex(events)
|
|
1314
|
+
const turnOf = options.turnOf ?? turnIndex(events)
|
|
1312
1315
|
const head = surfaceNodes[0]
|
|
1313
1316
|
const patches = options.patches instanceof Map ? options.patches : new Map()
|
|
1314
1317
|
const patch = options.patch === true
|
|
1318
|
+
// `/state` publishes identities only, so the blocks never leave this function.
|
|
1319
|
+
// Skipping them also skips the per-turn widening below, which walks every reply
|
|
1320
|
+
// of the same turn for every reply: that widening is what made one refresh of a
|
|
1321
|
+
// long session take seconds.
|
|
1322
|
+
const light = options.light === true
|
|
1315
1323
|
const out = []
|
|
1316
1324
|
for (const event of events) {
|
|
1317
1325
|
if (!isAssistantReply(event)) continue
|
|
@@ -1331,7 +1339,7 @@ export function editableReplies(events, surfaceNodes, options = {}) {
|
|
|
1331
1339
|
// text of that turn is offered, each annotated with the seq it lives in.
|
|
1332
1340
|
let listed = blocks.map((block) => ({ ...block, seq: event.seq }))
|
|
1333
1341
|
const carriesAnswer = blocks.some((block) => block.kind === 'text' && block.text.trim() !== '')
|
|
1334
|
-
if (patch && carriesAnswer && typeof turn === 'number') {
|
|
1342
|
+
if (!light && patch && carriesAnswer && typeof turn === 'number') {
|
|
1335
1343
|
const acrossTurn = []
|
|
1336
1344
|
for (const other of events) {
|
|
1337
1345
|
if (!isAssistantReply(other) || turnOf.get(other.seq) !== turn) continue
|
|
@@ -1345,6 +1353,7 @@ export function editableReplies(events, surfaceNodes, options = {}) {
|
|
|
1345
1353
|
if (acrossTurn.length > listed.length) listed = acrossTurn
|
|
1346
1354
|
}
|
|
1347
1355
|
out.push({
|
|
1356
|
+
...(light ? {} : { blocks: listed }),
|
|
1348
1357
|
seq: event.seq,
|
|
1349
1358
|
turn: typeof turn === 'number' ? turn : null,
|
|
1350
1359
|
messageId: messageIdOf(event) ?? null,
|
|
@@ -1770,7 +1779,9 @@ async function stateOf(ctx, sessionId, config) {
|
|
|
1770
1779
|
}
|
|
1771
1780
|
}
|
|
1772
1781
|
const folded = foldSurface(events)
|
|
1773
|
-
const
|
|
1782
|
+
const bySeq = new Map(events.map((event) => [event.seq, event]))
|
|
1783
|
+
const turnOf = turnIndex(events)
|
|
1784
|
+
const ledger = rollbackLedger(events, { folded, bySeq, turnOf })
|
|
1774
1785
|
const patches = patchesOf(events)
|
|
1775
1786
|
// A patch whose target has been retired (a later rerun shadowed it) is inert:
|
|
1776
1787
|
// the projection skips it and no row can show it. Reporting it in /state made
|
|
@@ -1784,8 +1795,8 @@ async function stateOf(ctx, sessionId, config) {
|
|
|
1784
1795
|
// now, so a store that is unmounted (or not yet mounted) cannot leave the
|
|
1785
1796
|
// editor promising to keep blocks the host would have to drop.
|
|
1786
1797
|
const store = resolveAttachmentStore(ctx)
|
|
1787
|
-
const turns = editableTurns(events, folded.nodes, { preview: canPreviewAttachments(store) })
|
|
1788
|
-
const replies = editableReplies(events, folded.nodes, { patches, patch: config.patch === true }).map(lightReply)
|
|
1798
|
+
const turns = editableTurns(events, folded.nodes, { preview: canPreviewAttachments(store), bySeq, turnOf })
|
|
1799
|
+
const replies = editableReplies(events, folded.nodes, { patches, patch: config.patch === true, light: true, bySeq, turnOf }).map(lightReply)
|
|
1789
1800
|
noteRequest({
|
|
1790
1801
|
kind: 'state',
|
|
1791
1802
|
sessionId,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// dsh-edit-turn host half (dsh-edit-turn.patch.js), VENDORED by tools/vendor.mjs - DO NOT EDIT.
|
|
2
2
|
//
|
|
3
|
-
// Source: ../dsh-edit-turn/lib/patch.js (v0.5.
|
|
3
|
+
// Source: ../dsh-edit-turn/lib/patch.js (v0.5.12, sha256 5e1e8cce1d168f6c)
|
|
4
4
|
// Regenerate with `npm run vendor`; test/sync.test.js fails when this is stale.
|
|
5
5
|
//
|
|
6
6
|
// src/shell.js imports the copy named after the component, which is why the
|
package/src/vendor/versions.json
CHANGED