dsh-one-click-polish 1.2.1 → 1.2.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/client.js +83 -5
- package/index.js +64 -1
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -41,6 +41,7 @@ window.__ModuleLoader__.load({
|
|
|
41
41
|
const PROGRESS = ENDPOINT.replace(/\/polish$/, '/progress')
|
|
42
42
|
const PILOT = ENDPOINT.replace(/\/polish$/, '/autopilot')
|
|
43
43
|
const RUNS = ENDPOINT.replace(/\/polish$/, '/runs')
|
|
44
|
+
const VERSION = ENDPOINT.replace(/\/polish$/, '/version')
|
|
44
45
|
|
|
45
46
|
/** The in-flight request, so the panel can cancel it. */
|
|
46
47
|
let activeAbort = null
|
|
@@ -253,8 +254,8 @@ window.__ModuleLoader__.load({
|
|
|
253
254
|
'auto.warn.body': '启动后 AI 会自动往这个会话里发送消息:读对话 → 写下一步提示词 → 发给助手,一轮接一轮。它会消耗模型额度,也可能做出你没想到的改动。随时可以中断或结束循环。',
|
|
254
255
|
'auto.warn.cancel': '再想想',
|
|
255
256
|
'auto.warn.confirm': '确认启动',
|
|
256
|
-
'auto.interrupt': '跳过这一轮',
|
|
257
|
-
'auto.interrupt.hint': '取消助手正在做的这一轮,循环继续,它会重新判断下一步。',
|
|
257
|
+
'auto.interrupt': '跳过这一轮',
|
|
258
|
+
'auto.interrupt.hint': '取消助手正在做的这一轮,循环继续,它会重新判断下一步。',
|
|
258
259
|
'auto.stop.hint': '整个自动驾驶停下。之后可以从这里继续。',
|
|
259
260
|
'auto.stop': '停止自动',
|
|
260
261
|
'auto.running': '运行中',
|
|
@@ -281,6 +282,13 @@ window.__ModuleLoader__.load({
|
|
|
281
282
|
'settings.idleWait': '等待助手完成上一轮的上限',
|
|
282
283
|
'settings.idleWait.hint': '自动驾驶要发下一条时,如果助手还在处理,它会等。超过这个上限就先停下,点「继续」可以接着来。长会话需要更长的时间。',
|
|
283
284
|
'settings.idleWait.unit': '分钟',
|
|
285
|
+
'version.current': '当前版本',
|
|
286
|
+
'version.latest': '已是最新',
|
|
287
|
+
'version.newest': 'npm 上有',
|
|
288
|
+
'version.checking': '检查更新中…',
|
|
289
|
+
'version.unknown': '查不到最新版本',
|
|
290
|
+
'version.how': '怎么更新',
|
|
291
|
+
'version.recheck': '重新检查',
|
|
284
292
|
'settings.explore': '检索预算',
|
|
285
293
|
'settings.explore.hint': '标准/深度润色时会先查资料。这是查资料总共能用多久、最多查几轮。查完后再改写,两者互不占用。',
|
|
286
294
|
'settings.explore.unit': '秒',
|
|
@@ -412,8 +420,8 @@ window.__ModuleLoader__.load({
|
|
|
412
420
|
'auto.warn.body': 'The AI will send messages into this conversation by itself: read the history, write the next prompt, send it, round after round. It spends model quota and may change things you did not expect. You can interrupt or end the loop at any time.',
|
|
413
421
|
'auto.warn.cancel': 'Not now',
|
|
414
422
|
'auto.warn.confirm': 'Start',
|
|
415
|
-
'auto.interrupt': 'Skip this round',
|
|
416
|
-
'auto.interrupt.hint': 'Cancel the turn the assistant is running. The loop stays alive and re-plans the next step.',
|
|
423
|
+
'auto.interrupt': 'Skip this round',
|
|
424
|
+
'auto.interrupt.hint': 'Cancel the turn the assistant is running. The loop stays alive and re-plans the next step.',
|
|
417
425
|
'auto.stop.hint': 'End the autopilot. You can continue from here afterwards.',
|
|
418
426
|
'auto.stop': 'Stop autopilot',
|
|
419
427
|
'auto.running': 'Running',
|
|
@@ -440,6 +448,13 @@ window.__ModuleLoader__.load({
|
|
|
440
448
|
'settings.idleWait': 'How long to wait for the assistant',
|
|
441
449
|
'settings.idleWait.hint': 'When the loop is ready to send but the assistant is still working, it waits. Past this limit it parks, and Continue picks it up again. Long conversations need more time.',
|
|
442
450
|
'settings.idleWait.unit': 'minutes',
|
|
451
|
+
'version.current': 'Version',
|
|
452
|
+
'version.latest': 'Up to date',
|
|
453
|
+
'version.newest': 'npm has',
|
|
454
|
+
'version.checking': 'Checking for updates…',
|
|
455
|
+
'version.unknown': 'Cannot reach npm',
|
|
456
|
+
'version.how': 'How to update',
|
|
457
|
+
'version.recheck': 'Check again',
|
|
443
458
|
'settings.explore': 'Lookup budget',
|
|
444
459
|
'settings.explore.hint': 'A standard or deep polish looks things up first. This is how long that may take in total, and how many rounds it may spend. The rewrite runs separately with its own budget.',
|
|
445
460
|
'settings.explore.unit': 's',
|
|
@@ -564,6 +579,21 @@ window.__ModuleLoader__.load({
|
|
|
564
579
|
.dsh-op-head{margin-bottom:18px}
|
|
565
580
|
.dsh-op-h2{margin:0 0 4px;font-size:17px;font-weight:600;line-height:26px;letter-spacing:-.01em}
|
|
566
581
|
.dsh-op-sub{margin:0;color:var(--dsw-alias-label-secondary);font-size:12.5px;line-height:20px}
|
|
582
|
+
/* Version line: this plugin's own update affordance. dsh's plugin page only
|
|
583
|
+
computes installTarget for bundles in its official catalogue, so a third-party
|
|
584
|
+
plugin has no update button there. */
|
|
585
|
+
.dsh-op-version{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:9px;
|
|
586
|
+
font-size:11.5px;line-height:17px;color:var(--dsw-alias-label-secondary)}
|
|
587
|
+
.dsh-op-versionNow{font-variant-numeric:tabular-nums;
|
|
588
|
+
font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;
|
|
589
|
+
background:var(--dsw-alias-bg-base);border-radius:999px;padding:1px 8px;
|
|
590
|
+
color:var(--dsw-alias-label-primary)}
|
|
591
|
+
.dsh-op-versionNew{display:flex;flex-wrap:wrap;align-items:center;gap:8px;
|
|
592
|
+
font-size:11.5px;color:var(--dsw-alias-state-warn-primary)}
|
|
593
|
+
.dsh-op-versionBad{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-secondary));opacity:.8}
|
|
594
|
+
/* The busy-wait line: a live counter, so it is monospaced and does not reflow as
|
|
595
|
+
the seconds tick, and it holds a fixed height so the panel does not jump. */
|
|
596
|
+
.dsh-op-waiting{font-variant-numeric:tabular-nums;min-height:17px}
|
|
567
597
|
.dsh-op-card{display:flex;flex-direction:column;gap:2px;padding:2px 16px;
|
|
568
598
|
background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);
|
|
569
599
|
border-radius:14px}
|
|
@@ -2266,6 +2296,8 @@ window.__ModuleLoader__.load({
|
|
|
2266
2296
|
const [form, setForm] = useState(null) // what the user is editing
|
|
2267
2297
|
const [efforts, setEfforts] = useState({ state: 'idle', list: [], defaultEffort: null })
|
|
2268
2298
|
const [saveState, setSaveState] = useState({ state: 'idle', message: '' })
|
|
2299
|
+
// null while the first lookup is in flight; afterwards { current, latest, error }
|
|
2300
|
+
const [version, setVersion] = useState(null)
|
|
2269
2301
|
const [runs, setRuns] = useState([])
|
|
2270
2302
|
const [runsPick, setRunsPick] = useState(null)
|
|
2271
2303
|
const [runEntries, setRunEntries] = useState([])
|
|
@@ -2317,6 +2349,24 @@ window.__ModuleLoader__.load({
|
|
|
2317
2349
|
|
|
2318
2350
|
useEffect(() => { load() }, [load])
|
|
2319
2351
|
|
|
2352
|
+
/** Read this plugin's version against npm. Cached on the Host for 10 minutes. */
|
|
2353
|
+
const checkVersion = useCallback(async (force) => {
|
|
2354
|
+
try {
|
|
2355
|
+
const response = await fetch(force === true ? `${VERSION}?refresh=1` : VERSION)
|
|
2356
|
+
const payload = await response.json()
|
|
2357
|
+
if (payload?.ok !== true) throw new Error(payload?.error ?? 'HTTP error')
|
|
2358
|
+
setVersion({
|
|
2359
|
+
current: typeof payload.current === 'string' ? payload.current : '',
|
|
2360
|
+
latest: typeof payload.latest === 'string' ? payload.latest : null,
|
|
2361
|
+
error: typeof payload.error === 'string' ? payload.error : null,
|
|
2362
|
+
})
|
|
2363
|
+
} catch (failure) {
|
|
2364
|
+
setVersion({ current: '', latest: null, error: String(failure?.message ?? failure) })
|
|
2365
|
+
}
|
|
2366
|
+
}, [])
|
|
2367
|
+
|
|
2368
|
+
useEffect(() => { void checkVersion(false) }, [checkVersion])
|
|
2369
|
+
|
|
2320
2370
|
/** Sessions that have an archived run, newest first. */
|
|
2321
2371
|
const loadRuns = useCallback(async () => {
|
|
2322
2372
|
try {
|
|
@@ -2462,7 +2512,35 @@ window.__ModuleLoader__.load({
|
|
|
2462
2512
|
const pageBody = h('div', { className: 'dsh-op-page' },
|
|
2463
2513
|
h('div', { className: 'dsh-op-head' },
|
|
2464
2514
|
h('h2', { className: 'dsh-op-h2' }, t('settings.title')),
|
|
2465
|
-
h('p', { className: 'dsh-op-sub' }, t('settings.sub'))
|
|
2515
|
+
h('p', { className: 'dsh-op-sub' }, t('settings.sub')),
|
|
2516
|
+
// dsh's own plugin page can only offer 更新 for bundles in its official
|
|
2517
|
+
// catalogue, so a third-party plugin gets no update affordance there.
|
|
2518
|
+
// The version line puts that question here instead.
|
|
2519
|
+
h('div', { className: 'dsh-op-version' },
|
|
2520
|
+
h('span', { className: 'dsh-op-versionNow' },
|
|
2521
|
+
`${t('version.current')} ${version.current === '' ? '?' : version.current}`),
|
|
2522
|
+
version === null
|
|
2523
|
+
? h('span', { className: 'dsh-op-hint dsh-op-hint--inline' }, t('version.checking'))
|
|
2524
|
+
: version.error !== null && version.error !== ''
|
|
2525
|
+
? h('span', { className: 'dsh-op-versionBad' },
|
|
2526
|
+
`${t('version.unknown')} · ${version.error}`)
|
|
2527
|
+
: version.latest === null
|
|
2528
|
+
? h('span', { className: 'dsh-op-hint dsh-op-hint--inline' }, t('version.unknown'))
|
|
2529
|
+
: version.latest !== version.current
|
|
2530
|
+
? h('div', { className: 'dsh-op-versionNew' },
|
|
2531
|
+
h('span', null, `${t('version.newest')} ${version.latest}`),
|
|
2532
|
+
h('a', {
|
|
2533
|
+
className: 'dsh-op-link',
|
|
2534
|
+
href: 'https://www.npmjs.com/package/dsh-one-click-polish',
|
|
2535
|
+
target: '_blank',
|
|
2536
|
+
rel: 'noreferrer',
|
|
2537
|
+
}, t('version.how')),
|
|
2538
|
+
h('button', {
|
|
2539
|
+
type: 'button',
|
|
2540
|
+
className: 'dsh-op-link',
|
|
2541
|
+
onClick: () => { void checkVersion(true) },
|
|
2542
|
+
}, t('version.recheck')))
|
|
2543
|
+
: h('span', { className: 'dsh-op-hint dsh-op-hint--inline' }, t('version.latest')))),
|
|
2466
2544
|
h('div', { className: 'dsh-op-card' },
|
|
2467
2545
|
h('div', { className: 'dsh-op-cardTitle' }, t('settings.group.model')),
|
|
2468
2546
|
h('div', { className: 'dsh-op-field' },
|
package/index.js
CHANGED
|
@@ -23,7 +23,8 @@ export const name = 'one-click-polish'
|
|
|
23
23
|
export const inject = ['llm', 'agents', 'webServer']
|
|
24
24
|
|
|
25
25
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
|
26
|
-
import { join } from 'node:path'
|
|
26
|
+
import { dirname, join } from 'node:path'
|
|
27
|
+
import { fileURLToPath } from 'node:url'
|
|
27
28
|
|
|
28
29
|
const PREFIX = '/plugins/dsh-one-click-polish'
|
|
29
30
|
const DEFAULT_MAX_INPUT_CHARS = 12000
|
|
@@ -466,6 +467,61 @@ async function produceRewrite(ctx, settings, mode, strength, research, input, ag
|
|
|
466
467
|
return text
|
|
467
468
|
}
|
|
468
469
|
|
|
470
|
+
/**
|
|
471
|
+
* This plugin's own version, and the newest one on npm.
|
|
472
|
+
*
|
|
473
|
+
* dsh's plugin page only offers an update button for bundles in its official
|
|
474
|
+
* catalogue, because `installTarget` is computed from that catalogue. A third-party
|
|
475
|
+
* plugin therefore has no update affordance there at all, so the question "is there
|
|
476
|
+
* a newer version?" is answered here instead, on the plugin's own settings page.
|
|
477
|
+
*/
|
|
478
|
+
const VERSION_TTL_MS = 10 * 60 * 1000
|
|
479
|
+
let versionCache = { at: 0, latest: null, error: null }
|
|
480
|
+
|
|
481
|
+
async function versionInfo() {
|
|
482
|
+
let current = ''
|
|
483
|
+
try {
|
|
484
|
+
// Resolve from this module rather than the process cwd: the Host may run with
|
|
485
|
+
// any working directory, and this file sits next to its own manifest.
|
|
486
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
487
|
+
const manifest = JSON.parse(readFileSync(join(here, 'package.json'), 'utf8'))
|
|
488
|
+
current = typeof manifest.version === 'string' ? manifest.version : ''
|
|
489
|
+
} catch { /* a missing manifest just means no version to report */ }
|
|
490
|
+
|
|
491
|
+
if (versionCache.latest !== null && Date.now() - versionCache.at < VERSION_TTL_MS) {
|
|
492
|
+
return { current, latest: versionCache.latest, error: null, checked: versionCache.at }
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// The registry is the only source of truth for "what is published"; a failed
|
|
496
|
+
// lookup must not look like "you are up to date".
|
|
497
|
+
let latest = null
|
|
498
|
+
let error = null
|
|
499
|
+
try {
|
|
500
|
+
const controller = new AbortController()
|
|
501
|
+
const timer = setTimeout(() => controller.abort(), 8000)
|
|
502
|
+
const response = await fetch('https://registry.npmjs.org/dsh-one-click-polish/latest', {
|
|
503
|
+
signal: controller.signal,
|
|
504
|
+
headers: { accept: 'application/json' },
|
|
505
|
+
})
|
|
506
|
+
clearTimeout(timer)
|
|
507
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`)
|
|
508
|
+
const payload = await response.json()
|
|
509
|
+
latest = typeof payload?.version === 'string' ? payload.version : null
|
|
510
|
+
} catch (failure) {
|
|
511
|
+
error = textOf(failure)
|
|
512
|
+
}
|
|
513
|
+
versionCache = { at: Date.now(), latest, error }
|
|
514
|
+
return { current, latest, error, checked: Date.now() }
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
async function versionRoute(req, res) {
|
|
518
|
+
// `refresh=1` drops the TTL cache: the panel offers a recheck, and a button that
|
|
519
|
+
// silently answers from cache would look broken.
|
|
520
|
+
const url = new URL(req.url ?? '/', 'http://localhost')
|
|
521
|
+
if (url.searchParams.get('refresh') === '1') versionCache.at = 0
|
|
522
|
+
sendJson(res, 200, { ok: true, ...(await versionInfo()) })
|
|
523
|
+
}
|
|
524
|
+
|
|
469
525
|
async function statusRoute(ctx, req, res) {
|
|
470
526
|
const url = new URL(req.url ?? '/', 'http://localhost')
|
|
471
527
|
const sessionId = url.searchParams.get('sessionId') ?? undefined
|
|
@@ -2466,6 +2522,13 @@ export function apply(ctx, config) {
|
|
|
2466
2522
|
})
|
|
2467
2523
|
|
|
2468
2524
|
|
|
2525
|
+
ctx.effect(() => server.register({
|
|
2526
|
+
kind: 'exact',
|
|
2527
|
+
path: `${PREFIX}/version`,
|
|
2528
|
+
handler: (req, res) => versionRoute(req, res)
|
|
2529
|
+
.catch(error => sendJson(res, 500, { ok: false, error: textOf(error) })),
|
|
2530
|
+
}), 'one-click-polish: version route')
|
|
2531
|
+
|
|
2469
2532
|
ctx.effect(() => server.register({
|
|
2470
2533
|
kind: 'exact',
|
|
2471
2534
|
path: `${PREFIX}/status`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-one-click-polish",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "One-click polish, expand and autopilot for the DeepSeek Harness composer: rewrite the draft with the model the session is switched to, expand a one-line wish into a task brief, or let an AI drive a goal round after round.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|