@ran-sh/dsh-crew 1.2.0-rc.4 → 1.2.0-rc.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/.claude-plugin/plugin.json +1 -1
- package/lib/client.js +5436 -5434
- package/official-web-bridge/lib/client.js +567 -567
- package/package.json +1 -1
- package/src/client/index.tsx +5 -5
- package/src/client/task-telemetry.mjs +11 -4
- package/src/runtime-identity.mjs +1 -1
- package/windows/start-dsh-crew.ps1 +22 -9
package/package.json
CHANGED
package/src/client/index.tsx
CHANGED
|
@@ -163,8 +163,8 @@ const COPY = {
|
|
|
163
163
|
save: '保存', saved: '已保存', jobs: 'Worker 任务', empty: '当前没有 Worker / Reviewer 任务。',
|
|
164
164
|
adaptiveTitle: '自适应模型路由(实验)', adaptiveHint: '默认关闭;只重排系统自动候选,手动模型优先级始终保持原序。健康信号仅来自本进程已观察到的成功、失败、超时与粗粒度延迟,重启后清空。',
|
|
165
165
|
adaptiveEnabled: '启用自适应路由', adaptiveWindow: '健康窗口', adaptiveSamples: '最少样本', adaptiveBoundary: '下一个工作流生效',
|
|
166
|
-
modelActivity: '
|
|
167
|
-
calls: '
|
|
166
|
+
modelActivity: '模型活动概览', modelActivityHint: '聚合本 Hub 内存中最近 500 个含真实调用证据的任务;每个模型按任务计数(不是推测底层轮次),最多显示 50 个模型。不保存提示词、结果或凭据。', noModelActivity: '还没有真实模型活动。',
|
|
167
|
+
calls: '任务数', invocationSource: '任务来源', routingSource: '路由来源', lastCalled: '最近调用', role: '角色', model: '模型', never: '—',
|
|
168
168
|
col: { id: '任务', role: '角色', source: '来源', model: '模型', tier: '档位', status: '状态', progress: '进度', tokens: 'tokens ⇅', task: '内容' },
|
|
169
169
|
working: '处理中…',
|
|
170
170
|
tips: {
|
|
@@ -305,8 +305,8 @@ const COPY = {
|
|
|
305
305
|
save: 'Save', saved: 'Saved', jobs: 'Worker jobs', empty: 'No Worker / Reviewer jobs yet.',
|
|
306
306
|
adaptiveTitle: 'Adaptive model routing (experimental)', adaptiveHint: 'Off by default. Only system-derived candidates may be reordered; explicit model priorities always keep their order. Health uses only process-local success, failure, timeout, and coarse latency observations and resets on restart.',
|
|
307
307
|
adaptiveEnabled: 'Enable adaptive routing', adaptiveWindow: 'Health window', adaptiveSamples: 'Minimum samples', adaptiveBoundary: 'Effective for the next workflow',
|
|
308
|
-
modelActivity: 'Model
|
|
309
|
-
calls: '
|
|
308
|
+
modelActivity: 'Model activity overview', modelActivityHint: 'Aggregates the latest 500 in-memory Hub jobs with real model-activity evidence; each model is counted once per qualifying job (not an inferred turn count). Shows at most 50 models; prompts, results, and credentials are never stored here.', noModelActivity: 'No real model activity yet.',
|
|
309
|
+
calls: 'Jobs', invocationSource: 'Task source', routingSource: 'Routing source', lastCalled: 'Last called', role: 'Role', model: 'Model', never: '—',
|
|
310
310
|
col: { id: 'job', role: 'role', source: 'source', model: 'model', tier: 'tier', status: 'status', progress: 'progress', tokens: 'tokens ⇅', task: 'task' },
|
|
311
311
|
working: 'Working…',
|
|
312
312
|
tips: {
|
|
@@ -1838,7 +1838,7 @@ function WorkersPanel({ ctx }: { ctx: any }) {
|
|
|
1838
1838
|
<div role="row" key={`${entry.provider}/${entry.model}`} style={{ display: 'grid', gridTemplateColumns: 'minmax(190px, 1.35fr) 72px minmax(170px, 1fr) 125px', gap: 10, alignItems: 'center', padding: '7px 6px', borderTop: '1px solid rgba(128,128,128,0.16)' }}>
|
|
1839
1839
|
<span role="cell" style={{ minWidth: 0 }}><strong style={{ display: 'block', fontSize: 12 }}>{entry.model}</strong><span style={{ ...S.mono, opacity: 0.55 }}>{entry.provider}</span></span>
|
|
1840
1840
|
<span role="cell" style={{ ...S.mono, fontSize: 15, fontWeight: 650 }}>{entry.count}</span>
|
|
1841
|
-
<span role="cell" style={{ minWidth: 0, fontSize: 11.5 }}><span style={{ display: 'block' }}>{entry.task_sources.map(sourceLabel).join(' · ')}</span><span style={{ display: 'block', opacity: 0.55 }}>{entry.selection_sources.join(' · ')} · {entry.roles.join(' / ')}</span></span>
|
|
1841
|
+
<span role="cell" style={{ minWidth: 0, fontSize: 11.5 }}><span style={{ display: 'block' }}>{entry.task_sources.map(sourceLabel).join(' · ')}</span><span style={{ display: 'block', opacity: 0.55 }}>{entry.selection_sources.join(' · ')} · {entry.roles.length > 0 ? entry.roles.join(' / ') : copy.never}</span></span>
|
|
1842
1842
|
<span role="cell" style={{ ...S.mono, fontSize: 10.5 }}>{formatTimestamp(entry.last_called_at, locale)}</span>
|
|
1843
1843
|
</div>
|
|
1844
1844
|
))}
|
|
@@ -21,9 +21,11 @@ function hasInvocationEvidence(job) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* Build a bounded, presentation-only model activity summary from
|
|
25
|
-
* Hub already exposes.
|
|
26
|
-
*
|
|
24
|
+
* Build a bounded, presentation-only, job-level model activity summary from
|
|
25
|
+
* the jobs the Hub already exposes. Each qualifying job contributes one row
|
|
26
|
+
* count for its selected provider/model; the count is not an inferred number
|
|
27
|
+
* of underlying model turns. No prompts, results, credentials, or new
|
|
28
|
+
* persistence are introduced here.
|
|
27
29
|
*/
|
|
28
30
|
export function aggregateModelInvocations(jobs = []) {
|
|
29
31
|
const groups = new Map();
|
|
@@ -45,7 +47,12 @@ export function aggregateModelInvocations(jobs = []) {
|
|
|
45
47
|
current.count += 1;
|
|
46
48
|
current.taskSources.add(clean(job?.source, 'api'));
|
|
47
49
|
current.selectionSources.add(clean(job?.selection_source, 'unknown'));
|
|
48
|
-
|
|
50
|
+
// Do not infer a role from malformed, missing, or future role values. The
|
|
51
|
+
// summary is presentation evidence and must never assert a role the job
|
|
52
|
+
// did not provide.
|
|
53
|
+
if (job?.role === 'worker' || job?.role === 'reviewer') {
|
|
54
|
+
current.roles.add(job.role);
|
|
55
|
+
}
|
|
49
56
|
const calledAt = validTimestamp(job?.startedAt);
|
|
50
57
|
if (calledAt && (!current.lastCalledAt || Date.parse(calledAt) > Date.parse(current.lastCalledAt))) {
|
|
51
58
|
current.lastCalledAt = calledAt;
|
package/src/runtime-identity.mjs
CHANGED
|
@@ -36,7 +36,7 @@ export {
|
|
|
36
36
|
// included in the identity contract.
|
|
37
37
|
const RUNTIME_ID = randomUUID();
|
|
38
38
|
|
|
39
|
-
export const RUNTIME_VERSION = '1.2.0-rc.
|
|
39
|
+
export const RUNTIME_VERSION = '1.2.0-rc.6';
|
|
40
40
|
export const HUB_PROTOCOL_VERSION = 1;
|
|
41
41
|
|
|
42
42
|
export const HUB_CAPABILITIES = Object.freeze([
|
|
@@ -82,15 +82,28 @@ function Test-OfficialWebReady {
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
function Get-OfficialFrontendOverlay {
|
|
86
|
-
$frontendRoot = Join-Path $env:USERPROFILE '.config\dsh-crew\frontend'
|
|
87
|
-
$path = Join-Path $frontendRoot 'official-web.patch.json'
|
|
88
|
-
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) { throw 'Crew frontend overlay is missing. Run dsh-crew update with the current GitHub candidate.' }
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
85
|
+
function Get-OfficialFrontendOverlay {
|
|
86
|
+
$frontendRoot = Join-Path $env:USERPROFILE '.config\dsh-crew\frontend'
|
|
87
|
+
$path = Join-Path $frontendRoot 'official-web.patch.json'
|
|
88
|
+
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) { throw 'Crew frontend overlay is missing. Run dsh-crew update with the current GitHub candidate.' }
|
|
89
|
+
# Windows PowerShell 5.1 keeps a JSON root array as one pipeline object;
|
|
90
|
+
# direct `$patch[0].insert[0]` therefore resolves `insert` as IList.Insert
|
|
91
|
+
# instead of indexing the JSON property. Flatten both PowerShell generations
|
|
92
|
+
# explicitly and read properties through PSObject so StrictMode reports a
|
|
93
|
+
# useful validation error instead of "property id cannot be found".
|
|
94
|
+
$parsed = Get-Content -LiteralPath $path -Raw | ConvertFrom-Json
|
|
95
|
+
$patch = @($parsed | ForEach-Object { $_ })
|
|
96
|
+
$root = if ($patch.Count -eq 1) { $patch[0] } else { $null }
|
|
97
|
+
$insertProperty = if ($null -ne $root) { $root.PSObject.Properties['insert'] } else { $null }
|
|
98
|
+
$insertValue = if ($null -ne $insertProperty) { $insertProperty.Value } else { $null }
|
|
99
|
+
$inserts = @($insertValue | ForEach-Object { $_ })
|
|
100
|
+
$bridge = if ($inserts.Count -eq 1) { $inserts[0] } else { $null }
|
|
101
|
+
$idProperty = if ($null -ne $bridge) { $bridge.PSObject.Properties['id'] } else { $null }
|
|
102
|
+
$nameProperty = if ($null -ne $bridge) { $bridge.PSObject.Properties['name'] } else { $null }
|
|
103
|
+
if ($patch.Count -ne 1 -or $inserts.Count -ne 1 -or $null -eq $idProperty -or [string] $idProperty.Value -ne 'dsh-crew-official-web-bridge' -or $null -eq $nameProperty) {
|
|
104
|
+
throw 'Crew frontend overlay has an unexpected structure.'
|
|
105
|
+
}
|
|
106
|
+
$uri = [Uri] ([string] $nameProperty.Value)
|
|
94
107
|
if (-not $uri.IsFile) { throw 'Crew frontend must load from its local snapshot.' }
|
|
95
108
|
$entry = [IO.Path]::GetFullPath($uri.LocalPath)
|
|
96
109
|
$prefix = [IO.Path]::GetFullPath((Join-Path $frontendRoot 'revisions')) + [IO.Path]::DirectorySeparatorChar
|