@ran-sh/dsh-crew 1.0.1 → 1.0.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 +24 -20
- package/README.zh.md +21 -18
- package/lib/client.js +156 -13
- package/official-web-bridge/lib/client.js +156 -13
- package/package.json +166 -166
- package/src/client/index.tsx +765 -716
- package/src/hub/index.mjs +418 -62
- package/src/install/install-legacy.mjs +184 -185
- package/src/policy-legacy.mjs +2 -2
- package/src/provider-delete-adapters.mjs +1786 -451
- package/src/provider-inventory.mjs +170 -132
- package/src/provider-lifecycle-state.mjs +100 -95
- package/src/provider-lifecycle.mjs +252 -214
- package/src/provider-profile-store.mjs +189 -171
- package/src/provider-settings-store.mjs +215 -0
- package/src/runtime-identity.mjs +72 -72
package/README.md
CHANGED
|
@@ -17,9 +17,13 @@ dsh-crew integrate
|
|
|
17
17
|
dsh-crew status
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Open <http://127.0.0.1:3080> for the daily console. On Windows, installation
|
|
21
|
-
also registers login startup for the 3080 console; its official bridge starts
|
|
22
|
-
and owns the isolated 3210 Harness backend.
|
|
20
|
+
Open <http://127.0.0.1:3080> for the daily console. On Windows, installation
|
|
21
|
+
also registers login startup for the 3080 console; its official bridge starts
|
|
22
|
+
and owns the isolated 3210 Harness backend.
|
|
23
|
+
|
|
24
|
+
Fresh installs contain only the built-in DeepSeek route. Add your own provider
|
|
25
|
+
credentials, model priorities, and optional integrations in the local Settings;
|
|
26
|
+
they are never bundled into this package.
|
|
23
27
|
|
|
24
28
|
| Surface | Purpose |
|
|
25
29
|
| --- | --- |
|
|
@@ -42,26 +46,26 @@ silently falling back.
|
|
|
42
46
|
## Useful commands
|
|
43
47
|
|
|
44
48
|
```bash
|
|
45
|
-
dsh-crew inspect # live capabilities and readiness
|
|
46
|
-
dsh-crew jobs list # jobs and Result Contracts
|
|
47
|
-
dsh-crew providers list # 3210 Harness provider inventory (secret-free)
|
|
48
|
-
dsh-crew providers probe <provider-id>
|
|
49
|
-
curl http://127.0.0.1:3210/_dsh/dsh-crew/credential-references # references/orphans only
|
|
50
|
-
dsh-crew credentials list # secret-free reference inventory
|
|
51
|
-
dsh-crew credentials purge-plan env:NAME
|
|
52
|
-
dsh-crew credentials purge env:NAME --plan <plan-id> --expected-revision <sha256> --confirm
|
|
53
|
-
dsh-crew providers delete-plan <provider-id> --replacement-default <provider-id>
|
|
54
|
-
dsh-crew providers delete <provider-id> --plan <plan-id> --expected-revision <sha256> --confirm
|
|
55
|
-
dsh-crew releases list # retained validated payloads
|
|
56
|
-
dsh-crew rollback <version> # switch payload and verify the 3210 runtime
|
|
57
|
-
dsh-crew update # update and repair enabled integrations
|
|
49
|
+
dsh-crew inspect # live capabilities and readiness
|
|
50
|
+
dsh-crew jobs list # jobs and Result Contracts
|
|
51
|
+
dsh-crew providers list # 3210 Harness provider inventory (secret-free)
|
|
52
|
+
dsh-crew providers probe <provider-id>
|
|
53
|
+
curl http://127.0.0.1:3210/_dsh/dsh-crew/credential-references # references/orphans only
|
|
54
|
+
dsh-crew credentials list # secret-free reference inventory
|
|
55
|
+
dsh-crew credentials purge-plan env:NAME
|
|
56
|
+
dsh-crew credentials purge env:NAME --plan <plan-id> --expected-revision <sha256> --confirm
|
|
57
|
+
dsh-crew providers delete-plan <provider-id> --replacement-default <provider-id>
|
|
58
|
+
dsh-crew providers delete <provider-id> --plan <plan-id> --expected-revision <sha256> --confirm
|
|
59
|
+
dsh-crew releases list # retained validated payloads
|
|
60
|
+
dsh-crew rollback <version> # switch payload and verify the 3210 runtime
|
|
61
|
+
dsh-crew update # update and repair enabled integrations
|
|
58
62
|
dsh-crew uninstall # remove managed files, keep backups/config
|
|
59
63
|
```
|
|
60
64
|
|
|
61
|
-
The runtime is isolated under `~/.config/dsh-crew/harness` with `profile: dsh-crew`;
|
|
62
|
-
the official `web` profile receives only the 3080 bridge.
|
|
63
|
-
All production Worker/Reviewer model calls are executed by the isolated 3210
|
|
64
|
-
Crew Harness; 3080 is a control-plane bridge only.
|
|
65
|
+
The runtime is isolated under `~/.config/dsh-crew/harness` with `profile: dsh-crew`;
|
|
66
|
+
the official `web` profile receives only the 3080 bridge.
|
|
67
|
+
All production Worker/Reviewer model calls are executed by the isolated 3210
|
|
68
|
+
Crew Harness; 3080 is a control-plane bridge only.
|
|
65
69
|
|
|
66
70
|
## Legacy launcher migration
|
|
67
71
|
|
package/README.zh.md
CHANGED
|
@@ -16,8 +16,11 @@ dsh-crew integrate
|
|
|
16
16
|
dsh-crew status
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
打开 <http://127.0.0.1:3080> 进入日常控制台。Windows 安装会注册当前用户的
|
|
20
|
-
登录启动项,先启动 3080 控制台,再由官方桥接启动并监管隔离的 3210 Harness。
|
|
19
|
+
打开 <http://127.0.0.1:3080> 进入日常控制台。Windows 安装会注册当前用户的
|
|
20
|
+
登录启动项,先启动 3080 控制台,再由官方桥接启动并监管隔离的 3210 Harness。
|
|
21
|
+
|
|
22
|
+
全新安装只包含内置 DeepSeek 路由。其他 Provider 凭据、模型优先级和可选集成需要
|
|
23
|
+
在本机设置中自行配置,绝不会打包进发布版本。
|
|
21
24
|
|
|
22
25
|
| 界面 | 用途 |
|
|
23
26
|
| --- | --- |
|
|
@@ -38,25 +41,25 @@ dsh-crew status
|
|
|
38
41
|
## 常用命令
|
|
39
42
|
|
|
40
43
|
```bash
|
|
41
|
-
dsh-crew inspect # 实时能力与就绪度
|
|
42
|
-
dsh-crew jobs list # 任务与 Result Contract
|
|
43
|
-
dsh-crew providers list # 3210 Harness Provider 清单(不含密钥)
|
|
44
|
-
dsh-crew providers probe <provider-id>
|
|
45
|
-
curl http://127.0.0.1:3210/_dsh/dsh-crew/credential-references # 仅查看引用/孤儿报告
|
|
46
|
-
dsh-crew credentials list # 不含密钥值的引用清单
|
|
47
|
-
dsh-crew credentials purge-plan env:NAME
|
|
48
|
-
dsh-crew credentials purge env:NAME --plan <plan-id> --expected-revision <sha256> --confirm
|
|
49
|
-
dsh-crew providers delete-plan <provider-id> --replacement-default <provider-id>
|
|
50
|
-
dsh-crew providers delete <provider-id> --plan <plan-id> --expected-revision <sha256> --confirm
|
|
51
|
-
dsh-crew releases list # 查看保留且已验证的版本
|
|
52
|
-
dsh-crew rollback <version> # 切换版本并验证 3210 runtime
|
|
53
|
-
dsh-crew update # 更新并修复已启用集成
|
|
44
|
+
dsh-crew inspect # 实时能力与就绪度
|
|
45
|
+
dsh-crew jobs list # 任务与 Result Contract
|
|
46
|
+
dsh-crew providers list # 3210 Harness Provider 清单(不含密钥)
|
|
47
|
+
dsh-crew providers probe <provider-id>
|
|
48
|
+
curl http://127.0.0.1:3210/_dsh/dsh-crew/credential-references # 仅查看引用/孤儿报告
|
|
49
|
+
dsh-crew credentials list # 不含密钥值的引用清单
|
|
50
|
+
dsh-crew credentials purge-plan env:NAME
|
|
51
|
+
dsh-crew credentials purge env:NAME --plan <plan-id> --expected-revision <sha256> --confirm
|
|
52
|
+
dsh-crew providers delete-plan <provider-id> --replacement-default <provider-id>
|
|
53
|
+
dsh-crew providers delete <provider-id> --plan <plan-id> --expected-revision <sha256> --confirm
|
|
54
|
+
dsh-crew releases list # 查看保留且已验证的版本
|
|
55
|
+
dsh-crew rollback <version> # 切换版本并验证 3210 runtime
|
|
56
|
+
dsh-crew update # 更新并修复已启用集成
|
|
54
57
|
dsh-crew uninstall # 移除受管文件,保留配置/备份
|
|
55
58
|
```
|
|
56
59
|
|
|
57
|
-
运行时隔离在 `~/.config/dsh-crew/harness`,使用 `profile: dsh-crew`;官方 `web` profile
|
|
58
|
-
只接收 3080 轻量桥接。
|
|
59
|
-
生产 Worker/Reviewer 的模型调用全部由隔离的 3210 Crew Harness 执行,3080 仅作为控制面桥接。
|
|
60
|
+
运行时隔离在 `~/.config/dsh-crew/harness`,使用 `profile: dsh-crew`;官方 `web` profile
|
|
61
|
+
只接收 3080 轻量桥接。
|
|
62
|
+
生产 Worker/Reviewer 的模型调用全部由隔离的 3210 Crew Harness 执行,3080 仅作为控制面桥接。
|
|
60
63
|
|
|
61
64
|
## 旧启动器迁移
|
|
62
65
|
|
package/lib/client.js
CHANGED
|
@@ -509,6 +509,8 @@ const COPY = {
|
|
|
509
509
|
providerState: (state) => `状态:${state}`,
|
|
510
510
|
providerModels: (count) => `${count} 个模型`,
|
|
511
511
|
providerJobs: (count) => `${count} 个运行任务`,
|
|
512
|
+
providerOfficialBuiltin: "· 官方内置(不可删除)",
|
|
513
|
+
providerSourceUnresolved: "· 来源未解析(安全锁定)",
|
|
512
514
|
providerDeletePlan: "生成删除计划",
|
|
513
515
|
providerDelete: "确认删除",
|
|
514
516
|
providerPlanReady: "计划已生成;再次确认后才会修改 3210 配置。",
|
|
@@ -519,6 +521,12 @@ const COPY = {
|
|
|
519
521
|
providerDeleteConfirm: "确认按计划删除这个 Harness Provider?会清理路由引用并重启 3210。",
|
|
520
522
|
providerDeleteBlocked: "当前 Provider 不能删除(内置、在用、已删除或缺少可用替换)。",
|
|
521
523
|
providerLifecycleError: "Provider 生命周期操作失败",
|
|
524
|
+
providerDeletePending: "配置可能已变更,事务仍待重启/验证;请刷新状态后选择回滚。",
|
|
525
|
+
providerRollbackContinue: "继续回滚验证",
|
|
526
|
+
recoveryUnresolved: "发现不可自动恢复的事务",
|
|
527
|
+
recoveryStorage: "存储项",
|
|
528
|
+
recoveryQuarantine: "隔离",
|
|
529
|
+
recoveryQuarantineConfirm: "该事务清单无法安全恢复。将其移入隔离区并阻止自动使用,继续?",
|
|
522
530
|
providerNoInventory: "暂时无法读取 3210 Provider inventory。",
|
|
523
531
|
credentialReferences: "Credential 引用",
|
|
524
532
|
credentialReferenceHint: "仅显示引用名、归属和孤儿状态;不会读取或删除密钥。",
|
|
@@ -832,6 +840,8 @@ const COPY = {
|
|
|
832
840
|
providerState: (state) => `State: ${state}`,
|
|
833
841
|
providerModels: (count) => `${count} models`,
|
|
834
842
|
providerJobs: (count) => `${count} running jobs`,
|
|
843
|
+
providerOfficialBuiltin: "· official built-in (immutable)",
|
|
844
|
+
providerSourceUnresolved: "· source unresolved (locked)",
|
|
835
845
|
providerDeletePlan: "Plan deletion",
|
|
836
846
|
providerDelete: "Confirm delete",
|
|
837
847
|
providerPlanReady: "Plan ready; a second confirmation is required before changing 3210 config.",
|
|
@@ -842,6 +852,12 @@ const COPY = {
|
|
|
842
852
|
providerDeleteConfirm: "Delete this Harness Provider per the plan? Routing refs will be scrubbed and 3210 restarted.",
|
|
843
853
|
providerDeleteBlocked: "This Provider cannot be deleted (built-in, in use, already absent, or missing a valid replacement).",
|
|
844
854
|
providerLifecycleError: "Provider lifecycle operation failed",
|
|
855
|
+
providerDeletePending: "Configuration may already be changed; the transaction still needs restart/verification. Refresh status and use rollback if needed.",
|
|
856
|
+
providerRollbackContinue: "Continue rollback verification",
|
|
857
|
+
recoveryUnresolved: "An unrecoverable recovery transaction is blocking deletion",
|
|
858
|
+
recoveryStorage: "storage entry",
|
|
859
|
+
recoveryQuarantine: "Quarantine",
|
|
860
|
+
recoveryQuarantineConfirm: "This recovery manifest cannot be safely reopened. Move it into the quarantine area and keep it out of automatic recovery?",
|
|
845
861
|
providerNoInventory: "3210 Provider inventory is temporarily unavailable.",
|
|
846
862
|
credentialReferences: "Credential references",
|
|
847
863
|
credentialReferenceHint: "Names, ownership, and orphan status only; values are never read or deleted.",
|
|
@@ -1959,13 +1975,13 @@ function WorkersPanel({ ctx }) {
|
|
|
1959
1975
|
applyPatch(patch);
|
|
1960
1976
|
};
|
|
1961
1977
|
const deleteHarnessProvider = async (record) => {
|
|
1962
|
-
if (!record || record.
|
|
1978
|
+
if (!record || record.delete_capability !== "supported" || record.desired_state === "absent" || Number(record.references?.active_jobs ?? 0) > 0) {
|
|
1963
1979
|
setNotice(copy.providerDeleteBlocked);
|
|
1964
1980
|
return;
|
|
1965
1981
|
}
|
|
1966
1982
|
let replacementDefault;
|
|
1967
1983
|
if (record.references?.harness_default === true) {
|
|
1968
|
-
const candidate = (providerInventory?.records ?? []).find((item) => item.id !== record.id && item.desired_state !== "absent" && item.
|
|
1984
|
+
const candidate = (providerInventory?.records ?? []).find((item) => item.id === "deepseek-official" && item.id !== record.id && item.desired_state !== "absent" && (item.models?.length ?? 0) > 0)?.id ?? (providerInventory?.records ?? []).find((item) => item.id !== record.id && item.desired_state !== "absent" && item.delete_capability !== "source-unresolved" && (item.models?.length ?? 0) > 0)?.id ?? "";
|
|
1969
1985
|
const entered = window.prompt(copy.providerReplacement, candidate);
|
|
1970
1986
|
if (!entered?.trim()) return;
|
|
1971
1987
|
replacementDefault = entered.trim();
|
|
@@ -2006,13 +2022,29 @@ function WorkersPanel({ ctx }) {
|
|
|
2006
2022
|
setNotice(copy.saved);
|
|
2007
2023
|
await refreshProviderInventory();
|
|
2008
2024
|
} catch (error) {
|
|
2009
|
-
|
|
2025
|
+
try {
|
|
2026
|
+
await refreshProviderInventory();
|
|
2027
|
+
} catch {}
|
|
2028
|
+
setNotice(`${String(error?.message ?? error)} · ${copy.providerDeletePending}`);
|
|
2010
2029
|
} finally {
|
|
2011
2030
|
setProviderLifecycleBusy(null);
|
|
2012
2031
|
}
|
|
2013
2032
|
};
|
|
2014
|
-
const rollbackHarnessProvider = async (record, transactionId) => {
|
|
2015
|
-
|
|
2033
|
+
const rollbackHarnessProvider = async (record, transactionId, transactionState = "VERIFIED") => {
|
|
2034
|
+
const continuing = ["ROLLBACK_PENDING", "ROLLBACK_RESTART_PENDING"].includes(transactionState);
|
|
2035
|
+
const recoverable = [
|
|
2036
|
+
"PLANNED",
|
|
2037
|
+
"TOMBSTONE_APPLYING",
|
|
2038
|
+
"TOMBSTONE_APPLIED",
|
|
2039
|
+
"REFERENCES_APPLYING",
|
|
2040
|
+
"REFERENCES_APPLIED",
|
|
2041
|
+
"DECLARATIONS_APPLYING",
|
|
2042
|
+
"DECLARATIONS_APPLIED",
|
|
2043
|
+
"DELETE_RESTART_PENDING",
|
|
2044
|
+
"ROLLBACK_APPLYING",
|
|
2045
|
+
"ROLLBACK_RESTORED"
|
|
2046
|
+
].includes(transactionState);
|
|
2047
|
+
if (!record || !transactionId || !continuing && !recoverable && record.desired_state !== "absent") {
|
|
2016
2048
|
setNotice(copy.providerRollbackUnavailable);
|
|
2017
2049
|
return;
|
|
2018
2050
|
}
|
|
@@ -2021,7 +2053,11 @@ function WorkersPanel({ ctx }) {
|
|
|
2021
2053
|
setNotice(copy.working);
|
|
2022
2054
|
try {
|
|
2023
2055
|
const encoded = encodeURIComponent(record.id);
|
|
2024
|
-
const result =
|
|
2056
|
+
const result = continuing ? {
|
|
2057
|
+
ok: true,
|
|
2058
|
+
restart_required: true,
|
|
2059
|
+
state: "ROLLBACK_PENDING"
|
|
2060
|
+
} : await post(`/providers/${encoded}/rollback`, {
|
|
2025
2061
|
transaction_id: transactionId,
|
|
2026
2062
|
confirm: true
|
|
2027
2063
|
});
|
|
@@ -2043,6 +2079,32 @@ function WorkersPanel({ ctx }) {
|
|
|
2043
2079
|
setNotice(copy.saved);
|
|
2044
2080
|
await refreshProviderInventory();
|
|
2045
2081
|
} catch (error) {
|
|
2082
|
+
try {
|
|
2083
|
+
await refreshProviderInventory();
|
|
2084
|
+
} catch {}
|
|
2085
|
+
setNotice(`${String(error?.message ?? error)} · ${copy.providerDeletePending}`);
|
|
2086
|
+
} finally {
|
|
2087
|
+
setProviderLifecycleBusy(null);
|
|
2088
|
+
}
|
|
2089
|
+
};
|
|
2090
|
+
const quarantineRecoveryTransaction = async (entry) => {
|
|
2091
|
+
const actionId = typeof entry?.action_id === "string" ? entry.action_id : "";
|
|
2092
|
+
if (!actionId || entry?.recoverable === true) return;
|
|
2093
|
+
if (!window.confirm(copy.recoveryQuarantineConfirm)) return;
|
|
2094
|
+
setProviderLifecycleBusy(`quarantine:${actionId}`);
|
|
2095
|
+
setNotice(copy.working);
|
|
2096
|
+
try {
|
|
2097
|
+
const result = await post("/providers/_recovery/quarantine", {
|
|
2098
|
+
action_id: actionId,
|
|
2099
|
+
confirm: true
|
|
2100
|
+
});
|
|
2101
|
+
if (!result.ok) throw new Error(result.code ?? result.error ?? copy.providerLifecycleError);
|
|
2102
|
+
setNotice(copy.saved);
|
|
2103
|
+
await refreshProviderInventory();
|
|
2104
|
+
} catch (error) {
|
|
2105
|
+
try {
|
|
2106
|
+
await refreshProviderInventory();
|
|
2107
|
+
} catch {}
|
|
2046
2108
|
setNotice(String(error?.message ?? error));
|
|
2047
2109
|
} finally {
|
|
2048
2110
|
setProviderLifecycleBusy(null);
|
|
@@ -3040,7 +3102,7 @@ function WorkersPanel({ ctx }) {
|
|
|
3040
3102
|
style: S.fieldLabel,
|
|
3041
3103
|
children: copy.workerProvider
|
|
3042
3104
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomSelect, {
|
|
3043
|
-
value: config.worker_provider_mode ?? "
|
|
3105
|
+
value: config.worker_provider_mode ?? "deepseek-official",
|
|
3044
3106
|
onChange: (v) => field("worker_provider_mode", v),
|
|
3045
3107
|
options: ["follow-dsh", "deepseek-official"].map((m) => ({
|
|
3046
3108
|
value: m,
|
|
@@ -3588,9 +3650,31 @@ function WorkersPanel({ ctx }) {
|
|
|
3588
3650
|
children: copy.providerNoInventory
|
|
3589
3651
|
}),
|
|
3590
3652
|
(providerInventory?.records ?? []).map((record) => {
|
|
3591
|
-
const
|
|
3653
|
+
const immutable = record.delete_capability === "immutable-builtin";
|
|
3654
|
+
const unresolved = record.delete_capability === "source-unresolved";
|
|
3655
|
+
const blocked = immutable || unresolved || record.desired_state === "absent" || Number(record.references?.active_jobs ?? 0) > 0;
|
|
3592
3656
|
const lifecycle = record.desired_state === "absent" ? "absent" : record.lifecycle?.enabled === false ? "disabled" : record.lifecycle?.catalogued ? "catalogued" : "configured";
|
|
3593
|
-
const
|
|
3657
|
+
const lifecycleTransactions = providerInventory?.lifecycle_transactions ?? [];
|
|
3658
|
+
const recoveryTransactions = (providerInventory?.recovery_transactions ?? []).map((entry) => ({
|
|
3659
|
+
...entry,
|
|
3660
|
+
state: entry.phase
|
|
3661
|
+
}));
|
|
3662
|
+
const rollbackTransaction = [...lifecycleTransactions, ...recoveryTransactions].filter((entry) => entry.provider_id === record.id && [
|
|
3663
|
+
"VERIFIED",
|
|
3664
|
+
"RESTART_PENDING",
|
|
3665
|
+
"ROLLBACK_PENDING",
|
|
3666
|
+
"PLANNED",
|
|
3667
|
+
"TOMBSTONE_APPLYING",
|
|
3668
|
+
"TOMBSTONE_APPLIED",
|
|
3669
|
+
"REFERENCES_APPLYING",
|
|
3670
|
+
"REFERENCES_APPLIED",
|
|
3671
|
+
"DECLARATIONS_APPLYING",
|
|
3672
|
+
"DECLARATIONS_APPLIED",
|
|
3673
|
+
"DELETE_RESTART_PENDING",
|
|
3674
|
+
"ROLLBACK_RESTART_PENDING",
|
|
3675
|
+
"ROLLBACK_RESTORED",
|
|
3676
|
+
"ROLLBACK_APPLYING"
|
|
3677
|
+
].includes(entry.state)).sort((a, b) => String(a.updated_at ?? "").localeCompare(String(b.updated_at ?? ""))).at(-1);
|
|
3594
3678
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3595
3679
|
style: {
|
|
3596
3680
|
display: "flex",
|
|
@@ -3619,12 +3703,20 @@ function WorkersPanel({ ctx }) {
|
|
|
3619
3703
|
style: { opacity: .65 },
|
|
3620
3704
|
children: copy.providerModels(record.models?.length ?? 0)
|
|
3621
3705
|
}),
|
|
3706
|
+
immutable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3707
|
+
style: { opacity: .65 },
|
|
3708
|
+
children: copy.providerOfficialBuiltin
|
|
3709
|
+
}),
|
|
3710
|
+
unresolved && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3711
|
+
style: { color: "#c98735" },
|
|
3712
|
+
children: copy.providerSourceUnresolved
|
|
3713
|
+
}),
|
|
3622
3714
|
Number(record.references?.active_jobs ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3623
3715
|
style: { color: "#c98735" },
|
|
3624
3716
|
children: copy.providerJobs(record.references.active_jobs)
|
|
3625
3717
|
}),
|
|
3626
3718
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { flex: 1 } }),
|
|
3627
|
-
record.
|
|
3719
|
+
record.delete_capability === "supported" && record.desired_state !== "absent" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3628
3720
|
type: "button",
|
|
3629
3721
|
style: {
|
|
3630
3722
|
...S.btn,
|
|
@@ -3636,7 +3728,20 @@ function WorkersPanel({ ctx }) {
|
|
|
3636
3728
|
},
|
|
3637
3729
|
children: providerLifecycleBusy === record.id ? copy.working : copy.providerDeletePlan
|
|
3638
3730
|
}),
|
|
3639
|
-
record.desired_state === "absent"
|
|
3731
|
+
(record.desired_state === "absent" || [
|
|
3732
|
+
"PLANNED",
|
|
3733
|
+
"TOMBSTONE_APPLYING",
|
|
3734
|
+
"TOMBSTONE_APPLIED",
|
|
3735
|
+
"REFERENCES_APPLYING",
|
|
3736
|
+
"REFERENCES_APPLIED",
|
|
3737
|
+
"DECLARATIONS_APPLYING",
|
|
3738
|
+
"DECLARATIONS_APPLIED",
|
|
3739
|
+
"DELETE_RESTART_PENDING",
|
|
3740
|
+
"ROLLBACK_PENDING",
|
|
3741
|
+
"ROLLBACK_RESTART_PENDING",
|
|
3742
|
+
"ROLLBACK_RESTORED",
|
|
3743
|
+
"ROLLBACK_APPLYING"
|
|
3744
|
+
].includes(rollbackTransaction?.state)) && rollbackTransaction && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3640
3745
|
type: "button",
|
|
3641
3746
|
style: {
|
|
3642
3747
|
...S.btn,
|
|
@@ -3644,13 +3749,51 @@ function WorkersPanel({ ctx }) {
|
|
|
3644
3749
|
},
|
|
3645
3750
|
disabled: providerLifecycleBusy !== null,
|
|
3646
3751
|
onClick: () => {
|
|
3647
|
-
rollbackHarnessProvider(record, rollbackTransaction.transaction_id);
|
|
3752
|
+
rollbackHarnessProvider(record, rollbackTransaction.transaction_id, rollbackTransaction.state);
|
|
3648
3753
|
},
|
|
3649
|
-
children: providerLifecycleBusy === `rollback:${record.id}` ? copy.working : copy.providerRollback
|
|
3754
|
+
children: providerLifecycleBusy === `rollback:${record.id}` ? copy.working : rollbackTransaction.state === "ROLLBACK_PENDING" ? copy.providerRollbackContinue : copy.providerRollback
|
|
3650
3755
|
})
|
|
3651
3756
|
]
|
|
3652
3757
|
}, record.id);
|
|
3653
3758
|
}),
|
|
3759
|
+
(providerInventory?.recovery_transactions ?? []).filter((entry) => entry?.unresolved === true || !entry?.provider_id).map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3760
|
+
style: {
|
|
3761
|
+
display: "flex",
|
|
3762
|
+
alignItems: "center",
|
|
3763
|
+
gap: 8,
|
|
3764
|
+
fontSize: 12,
|
|
3765
|
+
flexWrap: "wrap",
|
|
3766
|
+
color: "#c98735",
|
|
3767
|
+
marginTop: 6
|
|
3768
|
+
},
|
|
3769
|
+
children: [
|
|
3770
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3771
|
+
style: { fontWeight: 600 },
|
|
3772
|
+
children: copy.recoveryUnresolved
|
|
3773
|
+
}),
|
|
3774
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3775
|
+
style: S.mono,
|
|
3776
|
+
children: entry.storage_id ?? entry.transaction_id ?? "unknown"
|
|
3777
|
+
}),
|
|
3778
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3779
|
+
style: { opacity: .7 },
|
|
3780
|
+
children: entry.phase
|
|
3781
|
+
}),
|
|
3782
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: { flex: 1 } }),
|
|
3783
|
+
entry.action_id && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3784
|
+
type: "button",
|
|
3785
|
+
style: {
|
|
3786
|
+
...S.btn,
|
|
3787
|
+
padding: "2px 8px"
|
|
3788
|
+
},
|
|
3789
|
+
disabled: providerLifecycleBusy !== null,
|
|
3790
|
+
onClick: () => {
|
|
3791
|
+
quarantineRecoveryTransaction(entry);
|
|
3792
|
+
},
|
|
3793
|
+
children: providerLifecycleBusy === `quarantine:${entry.action_id}` ? copy.working : copy.recoveryQuarantine
|
|
3794
|
+
})
|
|
3795
|
+
]
|
|
3796
|
+
}, `recovery:${entry.storage_id ?? entry.transaction_id ?? "unknown"}`)),
|
|
3654
3797
|
(credentialRefs.length > 0 || credentialUnverified.length > 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3655
3798
|
style: {
|
|
3656
3799
|
marginTop: 10,
|