dsh-cliworker-now 0.0.0-stage → 0.7.7
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/LICENSE +21 -0
- package/README.en.md +364 -0
- package/README.md +368 -2
- package/cordis.patch.yml +3 -0
- package/lib/account-models.mjs +262 -0
- package/lib/client.js +22139 -0
- package/lib/client.js.map +1 -0
- package/lib/grok-catalog.mjs +145 -0
- package/lib/hermes-native-entry.py +96 -0
- package/lib/hermes-nous-refresh.py +331 -0
- package/lib/index.js +14544 -0
- package/lib/index.js.map +1 -0
- package/lib/native-launch.mjs +234 -0
- package/lib/native-spawn.mjs +32 -0
- package/lib/own-account-lease.mjs +105 -0
- package/lib/pi-installation.mjs +87 -0
- package/lib/pi-login.mjs +80 -0
- package/lib/pi-native-catalog.mjs +417 -0
- package/lib/pi-omp-bridge.mjs +602 -0
- package/lib/pi-omp-environment.mjs +15 -0
- package/lib/pi-omp-refresh.mjs +324 -0
- package/lib/private-launch.mjs +23 -0
- package/lib/terminal-bridge.mjs +18 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +1430 -0
- package/lib/typert.remote-client.d.ts +72 -0
- package/lib/typert.remote-client.d.ts.map +1 -0
- package/lib/typert.remote-client.js +1256 -0
- package/lib/types/client/account-query-queue.d.ts +16 -0
- package/lib/types/client/account-query-queue.js +61 -0
- package/lib/types/client/account-query-queue.js.map +1 -0
- package/lib/types/client/account-terminal-css.d.ts +1 -0
- package/lib/types/client/account-terminal-css.js +3 -0
- package/lib/types/client/account-terminal-css.js.map +1 -0
- package/lib/types/client/account-terminal.d.ts +17 -0
- package/lib/types/client/account-terminal.js +525 -0
- package/lib/types/client/account-terminal.js.map +1 -0
- package/lib/types/client/assets/antigravity.png +0 -0
- package/lib/types/client/assets/claude-code.png +0 -0
- package/lib/types/client/assets/cliworker-now-logo.png +0 -0
- package/lib/types/client/assets/codex.png +0 -0
- package/lib/types/client/assets/grok.png +0 -0
- package/lib/types/client/assets/hermes.png +0 -0
- package/lib/types/client/assets/kimi-dark.png +0 -0
- package/lib/types/client/assets/kimi-light.png +0 -0
- package/lib/types/client/assets/mimo-code.png +0 -0
- package/lib/types/client/assets/omp.png +0 -0
- package/lib/types/client/assets/opencode.png +0 -0
- package/lib/types/client/assets/pi.png +0 -0
- package/lib/types/client/assets/zcode.png +0 -0
- package/lib/types/client/composer-keymap.d.ts +18 -0
- package/lib/types/client/composer-keymap.js +49 -0
- package/lib/types/client/composer-keymap.js.map +1 -0
- package/lib/types/client/conversation-timeline.d.ts +6 -0
- package/lib/types/client/conversation-timeline.js +65 -0
- package/lib/types/client/conversation-timeline.js.map +1 -0
- package/lib/types/client/copy-text.d.ts +5 -0
- package/lib/types/client/copy-text.js +45 -0
- package/lib/types/client/copy-text.js.map +1 -0
- package/lib/types/client/icons.d.ts +21 -0
- package/lib/types/client/icons.js +68 -0
- package/lib/types/client/icons.js.map +1 -0
- package/lib/types/client/index.d.ts +3 -0
- package/lib/types/client/index.js +124 -0
- package/lib/types/client/index.js.map +1 -0
- package/lib/types/client/management-styles.d.ts +1 -0
- package/lib/types/client/management-styles.js +17 -0
- package/lib/types/client/management-styles.js.map +1 -0
- package/lib/types/client/name-copy.d.ts +5 -0
- package/lib/types/client/name-copy.js +107 -0
- package/lib/types/client/name-copy.js.map +1 -0
- package/lib/types/client/native-job-overlay.d.ts +11 -0
- package/lib/types/client/native-job-overlay.js +129 -0
- package/lib/types/client/native-job-overlay.js.map +1 -0
- package/lib/types/client/operation-error.d.ts +2 -0
- package/lib/types/client/operation-error.js +12 -0
- package/lib/types/client/operation-error.js.map +1 -0
- package/lib/types/client/panel.d.ts +8 -0
- package/lib/types/client/panel.js +310 -0
- package/lib/types/client/panel.js.map +1 -0
- package/lib/types/client/rename-copy-styles.d.ts +1 -0
- package/lib/types/client/rename-copy-styles.js +21 -0
- package/lib/types/client/rename-copy-styles.js.map +1 -0
- package/lib/types/client/rename-worker.d.ts +9 -0
- package/lib/types/client/rename-worker.js +53 -0
- package/lib/types/client/rename-worker.js.map +1 -0
- package/lib/types/client/role-presets.d.ts +6 -0
- package/lib/types/client/role-presets.js +111 -0
- package/lib/types/client/role-presets.js.map +1 -0
- package/lib/types/client/settings-dialog.d.ts +13 -0
- package/lib/types/client/settings-dialog.js +442 -0
- package/lib/types/client/settings-dialog.js.map +1 -0
- package/lib/types/client/stat-popover.d.ts +10 -0
- package/lib/types/client/stat-popover.js +32 -0
- package/lib/types/client/stat-popover.js.map +1 -0
- package/lib/types/client/styles.d.ts +9 -0
- package/lib/types/client/styles.js +221 -0
- package/lib/types/client/styles.js.map +1 -0
- package/lib/types/client/telemetry.d.ts +11 -0
- package/lib/types/client/telemetry.js +24 -0
- package/lib/types/client/telemetry.js.map +1 -0
- package/lib/types/client/worker-card.d.ts +10 -0
- package/lib/types/client/worker-card.js +75 -0
- package/lib/types/client/worker-card.js.map +1 -0
- package/lib/types/client/worker-model-menu.d.ts +9 -0
- package/lib/types/client/worker-model-menu.js +136 -0
- package/lib/types/client/worker-model-menu.js.map +1 -0
- package/lib/types/client/workers.d.ts +21 -0
- package/lib/types/client/workers.js +59 -0
- package/lib/types/client/workers.js.map +1 -0
- package/lib/types/client/zcode-login-link-provider.d.ts +9 -0
- package/lib/types/client/zcode-login-link-provider.js +105 -0
- package/lib/types/client/zcode-login-link-provider.js.map +1 -0
- package/lib/types/client/zcode-login-link.d.ts +16 -0
- package/lib/types/client/zcode-login-link.js +194 -0
- package/lib/types/client/zcode-login-link.js.map +1 -0
- package/lib/types/host/account-identity.d.ts +16 -0
- package/lib/types/host/account-identity.js +126 -0
- package/lib/types/host/account-identity.js.map +1 -0
- package/lib/types/host/account-login.d.ts +10 -0
- package/lib/types/host/account-login.js +126 -0
- package/lib/types/host/account-login.js.map +1 -0
- package/lib/types/host/account-models.d.mts +21 -0
- package/lib/types/host/account-models.mjs +262 -0
- package/lib/types/host/accounts.d.ts +42 -0
- package/lib/types/host/accounts.js +945 -0
- package/lib/types/host/accounts.js.map +1 -0
- package/lib/types/host/adapters.d.ts +24 -0
- package/lib/types/host/adapters.js +380 -0
- package/lib/types/host/adapters.js.map +1 -0
- package/lib/types/host/agy-context.d.ts +8 -0
- package/lib/types/host/agy-context.js +122 -0
- package/lib/types/host/agy-context.js.map +1 -0
- package/lib/types/host/agy-models.d.ts +5 -0
- package/lib/types/host/agy-models.js +37 -0
- package/lib/types/host/agy-models.js.map +1 -0
- package/lib/types/host/agy-windows-account.d.ts +14 -0
- package/lib/types/host/agy-windows-account.js +104 -0
- package/lib/types/host/agy-windows-account.js.map +1 -0
- package/lib/types/host/authorized-catalog.d.ts +14 -0
- package/lib/types/host/authorized-catalog.js +35 -0
- package/lib/types/host/authorized-catalog.js.map +1 -0
- package/lib/types/host/bridge-protocol.d.ts +15 -0
- package/lib/types/host/bridge-protocol.js +80 -0
- package/lib/types/host/bridge-protocol.js.map +1 -0
- package/lib/types/host/claude-native-oauth.d.ts +17 -0
- package/lib/types/host/claude-native-oauth.js +272 -0
- package/lib/types/host/claude-native-oauth.js.map +1 -0
- package/lib/types/host/claude-own-route.d.ts +33 -0
- package/lib/types/host/claude-own-route.js +250 -0
- package/lib/types/host/claude-own-route.js.map +1 -0
- package/lib/types/host/cli-account-binding.d.ts +33 -0
- package/lib/types/host/cli-account-binding.js +540 -0
- package/lib/types/host/cli-account-binding.js.map +1 -0
- package/lib/types/host/cli-protocol.d.ts +27 -0
- package/lib/types/host/cli-protocol.js +212 -0
- package/lib/types/host/cli-protocol.js.map +1 -0
- package/lib/types/host/codex-account.d.ts +8 -0
- package/lib/types/host/codex-account.js +143 -0
- package/lib/types/host/codex-account.js.map +1 -0
- package/lib/types/host/codex-models.d.ts +6 -0
- package/lib/types/host/codex-models.js +169 -0
- package/lib/types/host/codex-models.js.map +1 -0
- package/lib/types/host/extended-adapters.d.ts +44 -0
- package/lib/types/host/extended-adapters.js +207 -0
- package/lib/types/host/extended-adapters.js.map +1 -0
- package/lib/types/host/first-party-account-context.d.ts +26 -0
- package/lib/types/host/first-party-account-context.js +55 -0
- package/lib/types/host/first-party-account-context.js.map +1 -0
- package/lib/types/host/first-party-models.d.ts +29 -0
- package/lib/types/host/first-party-models.js +459 -0
- package/lib/types/host/first-party-models.js.map +1 -0
- package/lib/types/host/grok-adapter.d.ts +44 -0
- package/lib/types/host/grok-adapter.js +293 -0
- package/lib/types/host/grok-adapter.js.map +1 -0
- package/lib/types/host/grok-models.d.ts +47 -0
- package/lib/types/host/grok-models.js +320 -0
- package/lib/types/host/grok-models.js.map +1 -0
- package/lib/types/host/harness-opencode-accounts.d.ts +17 -0
- package/lib/types/host/harness-opencode-accounts.js +80 -0
- package/lib/types/host/harness-opencode-accounts.js.map +1 -0
- package/lib/types/host/hermes-account-context.d.ts +8 -0
- package/lib/types/host/hermes-account-context.js +99 -0
- package/lib/types/host/hermes-account-context.js.map +1 -0
- package/lib/types/host/hermes-accounts.d.ts +19 -0
- package/lib/types/host/hermes-accounts.js +356 -0
- package/lib/types/host/hermes-accounts.js.map +1 -0
- package/lib/types/host/hermes-adapter.d.ts +93 -0
- package/lib/types/host/hermes-adapter.js +455 -0
- package/lib/types/host/hermes-adapter.js.map +1 -0
- package/lib/types/host/hermes-env.d.ts +4 -0
- package/lib/types/host/hermes-env.js +22 -0
- package/lib/types/host/hermes-env.js.map +1 -0
- package/lib/types/host/hermes-installation.d.ts +10 -0
- package/lib/types/host/hermes-installation.js +181 -0
- package/lib/types/host/hermes-installation.js.map +1 -0
- package/lib/types/host/hermes-models.d.ts +26 -0
- package/lib/types/host/hermes-models.js +328 -0
- package/lib/types/host/hermes-models.js.map +1 -0
- package/lib/types/host/hermes-native-entry.py +96 -0
- package/lib/types/host/hermes-nous-refresh.py +331 -0
- package/lib/types/host/hermes-nous.d.ts +53 -0
- package/lib/types/host/hermes-nous.js +343 -0
- package/lib/types/host/hermes-nous.js.map +1 -0
- package/lib/types/host/hermes-renewal.d.ts +27 -0
- package/lib/types/host/hermes-renewal.js +292 -0
- package/lib/types/host/hermes-renewal.js.map +1 -0
- package/lib/types/host/hermes-suppression.d.ts +7 -0
- package/lib/types/host/hermes-suppression.js +69 -0
- package/lib/types/host/hermes-suppression.js.map +1 -0
- package/lib/types/host/hermes-windows-installation.d.ts +5 -0
- package/lib/types/host/hermes-windows-installation.js +91 -0
- package/lib/types/host/hermes-windows-installation.js.map +1 -0
- package/lib/types/host/index.d.ts +140 -0
- package/lib/types/host/index.js +947 -0
- package/lib/types/host/index.js.map +1 -0
- package/lib/types/host/kimi-accounts.d.ts +17 -0
- package/lib/types/host/kimi-accounts.js +220 -0
- package/lib/types/host/kimi-accounts.js.map +1 -0
- package/lib/types/host/kimi-oauth-models.d.ts +14 -0
- package/lib/types/host/kimi-oauth-models.js +246 -0
- package/lib/types/host/kimi-oauth-models.js.map +1 -0
- package/lib/types/host/managed-agent.d.ts +4 -0
- package/lib/types/host/managed-agent.js +127 -0
- package/lib/types/host/managed-agent.js.map +1 -0
- package/lib/types/host/mimo-configuration.d.ts +22 -0
- package/lib/types/host/mimo-configuration.js +258 -0
- package/lib/types/host/mimo-configuration.js.map +1 -0
- package/lib/types/host/mimo-metadata-cache.d.ts +22 -0
- package/lib/types/host/mimo-metadata-cache.js +121 -0
- package/lib/types/host/mimo-metadata-cache.js.map +1 -0
- package/lib/types/host/native-capability-cache.d.ts +11 -0
- package/lib/types/host/native-capability-cache.js +94 -0
- package/lib/types/host/native-capability-cache.js.map +1 -0
- package/lib/types/host/native-launch.d.mts +2 -0
- package/lib/types/host/native-launch.mjs +234 -0
- package/lib/types/host/native-process.d.ts +5 -0
- package/lib/types/host/native-process.js +41 -0
- package/lib/types/host/native-process.js.map +1 -0
- package/lib/types/host/native-spawn.mjs +32 -0
- package/lib/types/host/opencode-adapter.d.ts +94 -0
- package/lib/types/host/opencode-adapter.js +507 -0
- package/lib/types/host/opencode-adapter.js.map +1 -0
- package/lib/types/host/opencode-native.d.ts +27 -0
- package/lib/types/host/opencode-native.js +403 -0
- package/lib/types/host/opencode-native.js.map +1 -0
- package/lib/types/host/own-account-lease.d.mts +5 -0
- package/lib/types/host/own-account-lease.mjs +105 -0
- package/lib/types/host/pi-installation.d.mts +7 -0
- package/lib/types/host/pi-installation.mjs +87 -0
- package/lib/types/host/pi-omp-accounts.d.ts +28 -0
- package/lib/types/host/pi-omp-accounts.js +175 -0
- package/lib/types/host/pi-omp-accounts.js.map +1 -0
- package/lib/types/host/pi-omp-adapter.d.ts +32 -0
- package/lib/types/host/pi-omp-adapter.js +190 -0
- package/lib/types/host/pi-omp-adapter.js.map +1 -0
- package/lib/types/host/pi-omp-environment.d.mts +1 -0
- package/lib/types/host/pi-omp-environment.mjs +15 -0
- package/lib/types/host/pi-omp-identity.d.ts +2 -0
- package/lib/types/host/pi-omp-identity.js +142 -0
- package/lib/types/host/pi-omp-identity.js.map +1 -0
- package/lib/types/host/pi-omp-logout.d.ts +3 -0
- package/lib/types/host/pi-omp-logout.js +152 -0
- package/lib/types/host/pi-omp-logout.js.map +1 -0
- package/lib/types/host/pi-omp-native.d.ts +71 -0
- package/lib/types/host/pi-omp-native.js +753 -0
- package/lib/types/host/pi-omp-native.js.map +1 -0
- package/lib/types/host/pi-omp-refresh.d.mts +7 -0
- package/lib/types/host/pi-omp-refresh.mjs +324 -0
- package/lib/types/host/private-launch.mjs +23 -0
- package/lib/types/host/process.d.ts +43 -0
- package/lib/types/host/process.js +134 -0
- package/lib/types/host/process.js.map +1 -0
- package/lib/types/host/protocol.d.ts +23 -0
- package/lib/types/host/protocol.js +112 -0
- package/lib/types/host/protocol.js.map +1 -0
- package/lib/types/host/roles.d.ts +34 -0
- package/lib/types/host/roles.js +80 -0
- package/lib/types/host/roles.js.map +1 -0
- package/lib/types/host/routing.d.ts +31 -0
- package/lib/types/host/routing.js +248 -0
- package/lib/types/host/routing.js.map +1 -0
- package/lib/types/host/runtime.d.ts +60 -0
- package/lib/types/host/runtime.js +598 -0
- package/lib/types/host/runtime.js.map +1 -0
- package/lib/types/host/storage.d.ts +48 -0
- package/lib/types/host/storage.js +449 -0
- package/lib/types/host/storage.js.map +1 -0
- package/lib/types/host/telemetry.d.ts +17 -0
- package/lib/types/host/telemetry.js +158 -0
- package/lib/types/host/telemetry.js.map +1 -0
- package/lib/types/host/windows-account-bootstrap.ps1 +44 -0
- package/lib/types/host/windows-account-launch.mjs +47 -0
- package/lib/types/host/windows-account-owner.ps1 +137 -0
- package/lib/types/host/windows-account-stdio.mjs +19 -0
- package/lib/types/host/windows-account-terminal.d.ts +17 -0
- package/lib/types/host/windows-account-terminal.js +208 -0
- package/lib/types/host/windows-account-terminal.js.map +1 -0
- package/lib/types/host/windows-agy-account.ps1 +81 -0
- package/lib/types/host/windows-cli-installation.d.ts +31 -0
- package/lib/types/host/windows-cli-installation.js +157 -0
- package/lib/types/host/windows-cli-installation.js.map +1 -0
- package/lib/types/host/windows-hidden-launch.mjs +49 -0
- package/lib/types/host/windows-hidden-process.d.ts +12 -0
- package/lib/types/host/windows-hidden-process.js +116 -0
- package/lib/types/host/windows-hidden-process.js.map +1 -0
- package/lib/types/host/zcode-account-models.d.ts +16 -0
- package/lib/types/host/zcode-account-models.js +114 -0
- package/lib/types/host/zcode-account-models.js.map +1 -0
- package/lib/types/host/zcode-adapter.d.ts +93 -0
- package/lib/types/host/zcode-adapter.js +808 -0
- package/lib/types/host/zcode-adapter.js.map +1 -0
- package/lib/types/host/zcode-grok-accounts.d.ts +30 -0
- package/lib/types/host/zcode-grok-accounts.js +408 -0
- package/lib/types/host/zcode-grok-accounts.js.map +1 -0
- package/lib/types/shared/accounts.d.ts +47 -0
- package/lib/types/shared/accounts.js +2 -0
- package/lib/types/shared/accounts.js.map +1 -0
- package/lib/types/shared/builtin-presets.d.ts +2 -0
- package/lib/types/shared/builtin-presets.js +231 -0
- package/lib/types/shared/builtin-presets.js.map +1 -0
- package/lib/types/shared/cli-settings.d.ts +5 -0
- package/lib/types/shared/cli-settings.js +2 -0
- package/lib/types/shared/cli-settings.js.map +1 -0
- package/lib/types/shared/model-presentation.d.ts +10 -0
- package/lib/types/shared/model-presentation.js +95 -0
- package/lib/types/shared/model-presentation.js.map +1 -0
- package/lib/types/shared/models.d.ts +7 -0
- package/lib/types/shared/models.js +35 -0
- package/lib/types/shared/models.js.map +1 -0
- package/lib/types/shared/telemetry.d.ts +18 -0
- package/lib/types/shared/telemetry.js +16 -0
- package/lib/types/shared/telemetry.js.map +1 -0
- package/lib/types/shared/types.d.ts +127 -0
- package/lib/types/shared/types.js +147 -0
- package/lib/types/shared/types.js.map +1 -0
- package/lib/windows-account-bootstrap.ps1 +44 -0
- package/lib/windows-account-launch.mjs +47 -0
- package/lib/windows-account-owner.ps1 +137 -0
- package/lib/windows-account-stdio.mjs +19 -0
- package/lib/windows-agy-account.ps1 +81 -0
- package/lib/windows-hidden-launch.mjs +49 -0
- package/lib/zcode-resume.mjs +423 -0
- package/package.json +109 -4
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { constants } from 'node:fs'
|
|
2
|
+
import { lstat, open, realpath, rename, rm, writeFile } from 'node:fs/promises'
|
|
3
|
+
import { createHash, randomUUID } from 'node:crypto'
|
|
4
|
+
import { createRequire } from 'node:module'
|
|
5
|
+
import { dirname, join } from 'node:path'
|
|
6
|
+
import { pathToFileURL } from 'node:url'
|
|
7
|
+
import { DatabaseSync } from 'node:sqlite'
|
|
8
|
+
import { inspectPiInstallation } from './pi-installation.mjs'
|
|
9
|
+
import { ownsOwnAccountLease, releaseOwnAccountLease } from './own-account-lease.mjs'
|
|
10
|
+
|
|
11
|
+
const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
12
|
+
const stable = (value) =>
|
|
13
|
+
JSON.stringify(
|
|
14
|
+
object(value)
|
|
15
|
+
? Object.fromEntries(
|
|
16
|
+
Object.keys(value)
|
|
17
|
+
.sort()
|
|
18
|
+
.map((key) => [key, JSON.parse(stable(value[key]))]),
|
|
19
|
+
)
|
|
20
|
+
: Array.isArray(value)
|
|
21
|
+
? value.map((entry) => JSON.parse(stable(entry)))
|
|
22
|
+
: (value ?? null),
|
|
23
|
+
)
|
|
24
|
+
export const refreshFingerprint = (value) => createHash('sha256').update(stable(value)).digest('hex')
|
|
25
|
+
const changed = () => new Error('账号配置已变化,请重新刷新模型')
|
|
26
|
+
const unsafe = () => new Error('无法安全保存账号续期,请重新登录')
|
|
27
|
+
function claims(value) {
|
|
28
|
+
try {
|
|
29
|
+
if (typeof value !== 'string' || value.length > 65536) return {}
|
|
30
|
+
const parsed = JSON.parse(Buffer.from(value.split('.')[1] ?? '', 'base64url').toString('utf8'))
|
|
31
|
+
return object(parsed) ? parsed : {}
|
|
32
|
+
} catch {
|
|
33
|
+
return {}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Identity comparison only, never a remote authentication assertion. */
|
|
37
|
+
export function refreshPrincipal(value) {
|
|
38
|
+
if (!object(value) || value.type !== 'oauth') return undefined
|
|
39
|
+
const identity = claims(value.id_token ?? value.idToken)
|
|
40
|
+
const token = claims(value.access ?? value.access_token)
|
|
41
|
+
const account =
|
|
42
|
+
value.accountId ?? value.account_id ?? token['https://api.openai.com/auth']?.chatgpt_account_id
|
|
43
|
+
const subject = identity.sub ?? token.sub ?? value.userId ?? value.user_id
|
|
44
|
+
const email = identity.email ?? value.email
|
|
45
|
+
const text = (item) => typeof item === 'string' && !!item
|
|
46
|
+
if (!text(account) && !text(subject) && !text(email)) return undefined
|
|
47
|
+
return refreshFingerprint({
|
|
48
|
+
...(text(account) ? { accountId: account } : {}),
|
|
49
|
+
...(text(subject) ? { subject } : text(email) ? { email: email.toLowerCase() } : {}),
|
|
50
|
+
...(text(identity.iss ?? token.iss) ? { issuer: identity.iss ?? token.iss } : {}),
|
|
51
|
+
...(text(value.organizationId ?? value.organization_id)
|
|
52
|
+
? { organization: value.organizationId ?? value.organization_id }
|
|
53
|
+
: {}),
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
export async function refreshJson(path, privateFile = true) {
|
|
57
|
+
let handle
|
|
58
|
+
let buffer
|
|
59
|
+
try {
|
|
60
|
+
if ((await realpath(dirname(path))) !== dirname(path)) throw unsafe()
|
|
61
|
+
const location = await lstat(path)
|
|
62
|
+
if (location.isSymbolicLink() || !location.isFile() || location.nlink !== 1) throw unsafe()
|
|
63
|
+
handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK)
|
|
64
|
+
const before = await handle.stat()
|
|
65
|
+
if (
|
|
66
|
+
!before.isFile() ||
|
|
67
|
+
before.dev !== location.dev || before.ino !== location.ino ||
|
|
68
|
+
before.nlink !== 1 ||
|
|
69
|
+
before.size > 16 * 1024 * 1024 ||
|
|
70
|
+
(privateFile && (process.platform !== 'win32' && (before.mode & 0o077)))
|
|
71
|
+
)
|
|
72
|
+
throw unsafe()
|
|
73
|
+
buffer = Buffer.alloc(before.size + 1)
|
|
74
|
+
let length = 0
|
|
75
|
+
while (length < buffer.length) {
|
|
76
|
+
const { bytesRead } = await handle.read(buffer, length, buffer.length - length, length)
|
|
77
|
+
if (!bytesRead) break
|
|
78
|
+
length += bytesRead
|
|
79
|
+
}
|
|
80
|
+
const after = await handle.stat()
|
|
81
|
+
const current = await lstat(path)
|
|
82
|
+
if (current.isSymbolicLink() || current.dev !== before.dev || current.ino !== before.ino) throw changed()
|
|
83
|
+
if (length !== before.size || after.mtimeMs !== before.mtimeMs || after.size !== before.size)
|
|
84
|
+
throw changed()
|
|
85
|
+
return JSON.parse(buffer.subarray(0, length).toString('utf8'))
|
|
86
|
+
} finally {
|
|
87
|
+
buffer?.fill(0)
|
|
88
|
+
await handle?.close()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export async function writeRefreshJson(path, value) {
|
|
92
|
+
const temporary = `${path}.${randomUUID()}.tmp`
|
|
93
|
+
try {
|
|
94
|
+
await writeFile(temporary, JSON.stringify(value), { flag: 'wx', mode: 0o600 })
|
|
95
|
+
await rename(temporary, path)
|
|
96
|
+
} finally {
|
|
97
|
+
await rm(temporary, { force: true })
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function validReceipt(value) {
|
|
101
|
+
if (
|
|
102
|
+
!object(value) ||
|
|
103
|
+
value.version !== 1 ||
|
|
104
|
+
!['pi', 'omp'].includes(value.cli) ||
|
|
105
|
+
!Array.isArray(value.entries)
|
|
106
|
+
)
|
|
107
|
+
throw unsafe()
|
|
108
|
+
for (const entry of value.entries)
|
|
109
|
+
if (
|
|
110
|
+
!object(entry) ||
|
|
111
|
+
typeof entry.provider !== 'string' ||
|
|
112
|
+
typeof entry.path !== 'string' ||
|
|
113
|
+
typeof entry.hash !== 'string'
|
|
114
|
+
)
|
|
115
|
+
throw unsafe()
|
|
116
|
+
return value
|
|
117
|
+
}
|
|
118
|
+
async function sourceIdentity(entry) {
|
|
119
|
+
if ((await realpath(dirname(entry.path))) !== dirname(entry.path)) throw changed()
|
|
120
|
+
const info = await lstat(entry.path)
|
|
121
|
+
if (
|
|
122
|
+
info.isSymbolicLink() ||
|
|
123
|
+
!info.isFile() ||
|
|
124
|
+
info.nlink !== 1 ||
|
|
125
|
+
info.dev !== entry.dev ||
|
|
126
|
+
info.ino !== entry.ino
|
|
127
|
+
)
|
|
128
|
+
throw changed()
|
|
129
|
+
}
|
|
130
|
+
function rowCredential(row) {
|
|
131
|
+
if (!row || row.credential_type !== 'oauth' || row.disabled_cause) return undefined
|
|
132
|
+
return { ...JSON.parse(row.data), type: 'oauth' }
|
|
133
|
+
}
|
|
134
|
+
export async function assertPiOmpRefreshSources(root, expected) {
|
|
135
|
+
const receipt = validReceipt(expected ?? (await refreshJson(join(root, 'receipt.json'))))
|
|
136
|
+
for (const entry of receipt.entries) {
|
|
137
|
+
await sourceIdentity(entry)
|
|
138
|
+
let current
|
|
139
|
+
if (receipt.cli === 'pi') current = (await refreshJson(entry.path, false))[entry.provider]
|
|
140
|
+
else {
|
|
141
|
+
const db = new DatabaseSync(entry.path, { readOnly: true })
|
|
142
|
+
try {
|
|
143
|
+
current = rowCredential(
|
|
144
|
+
db
|
|
145
|
+
.prepare(
|
|
146
|
+
'SELECT credential_type,data,disabled_cause FROM auth_credentials WHERE rowid=? AND provider=?',
|
|
147
|
+
)
|
|
148
|
+
.get(entry.rowId, entry.provider),
|
|
149
|
+
)
|
|
150
|
+
} finally {
|
|
151
|
+
db.close()
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (
|
|
155
|
+
!current ||
|
|
156
|
+
refreshFingerprint(current) !== entry.hash ||
|
|
157
|
+
refreshPrincipal(current) !== entry.principal
|
|
158
|
+
)
|
|
159
|
+
throw changed()
|
|
160
|
+
}
|
|
161
|
+
return receipt
|
|
162
|
+
}
|
|
163
|
+
export async function assertPiOmpRefreshCache(root, receipt) {
|
|
164
|
+
await refreshedEntries(root, validReceipt(receipt))
|
|
165
|
+
}
|
|
166
|
+
async function refreshedEntries(root, receipt) {
|
|
167
|
+
const result = []
|
|
168
|
+
if (receipt.cli === 'pi') {
|
|
169
|
+
const data = await refreshJson(join(root, 'agent/auth.json'))
|
|
170
|
+
const expected = [...receipt.entries, ...(receipt.fixed ?? [])].map((entry) => entry.provider).sort()
|
|
171
|
+
if (refreshFingerprint(Object.keys(data).sort()) !== refreshFingerprint(expected)) throw unsafe()
|
|
172
|
+
for (const entry of receipt.fixed ?? [])
|
|
173
|
+
if (refreshFingerprint(data[entry.provider]) !== entry.hash) throw unsafe()
|
|
174
|
+
for (const entry of receipt.entries) result.push([entry, data[entry.provider]])
|
|
175
|
+
} else {
|
|
176
|
+
const db = new DatabaseSync(join(root, 'agent/agent.db'), { readOnly: true })
|
|
177
|
+
try {
|
|
178
|
+
const rows = db
|
|
179
|
+
.prepare('SELECT rowid AS id,provider,credential_type,data,disabled_cause FROM auth_credentials')
|
|
180
|
+
.all()
|
|
181
|
+
if (rows.length !== receipt.entries.length + (receipt.fixed?.length ?? 0)) throw unsafe()
|
|
182
|
+
for (const entry of receipt.fixed ?? []) {
|
|
183
|
+
const row = rows.find((row) => row.id === entry.cacheRowId && row.provider === entry.provider)
|
|
184
|
+
if (
|
|
185
|
+
!row ||
|
|
186
|
+
refreshFingerprint({
|
|
187
|
+
...JSON.parse(row.data),
|
|
188
|
+
type: row.credential_type,
|
|
189
|
+
disabled_cause: row.disabled_cause,
|
|
190
|
+
}) !== entry.hash
|
|
191
|
+
)
|
|
192
|
+
throw unsafe()
|
|
193
|
+
}
|
|
194
|
+
for (const entry of receipt.entries)
|
|
195
|
+
result.push([
|
|
196
|
+
entry,
|
|
197
|
+
rowCredential(
|
|
198
|
+
db
|
|
199
|
+
.prepare(
|
|
200
|
+
'SELECT credential_type,data,disabled_cause FROM auth_credentials WHERE rowid=? AND provider=?',
|
|
201
|
+
)
|
|
202
|
+
.get(entry.cacheRowId, entry.provider),
|
|
203
|
+
),
|
|
204
|
+
])
|
|
205
|
+
} finally {
|
|
206
|
+
db.close()
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
for (const [entry, next] of result)
|
|
210
|
+
if (
|
|
211
|
+
!next ||
|
|
212
|
+
refreshPrincipal(next) !== entry.principal ||
|
|
213
|
+
typeof next.access !== 'string' ||
|
|
214
|
+
!next.access ||
|
|
215
|
+
typeof next.refresh !== 'string' ||
|
|
216
|
+
!next.refresh ||
|
|
217
|
+
!Number.isFinite(next.expires)
|
|
218
|
+
)
|
|
219
|
+
throw unsafe()
|
|
220
|
+
return result
|
|
221
|
+
}
|
|
222
|
+
/** Called only by Host after capture/process-scope cleanup confirmed exit. */
|
|
223
|
+
export async function finishPiOmpRefresh(root, nonce, executable, expectedReceipt) {
|
|
224
|
+
if (!(await ownsOwnAccountLease(root, nonce))) return
|
|
225
|
+
try {
|
|
226
|
+
// This snapshot is retained in the Host closure before launch. Never trust a
|
|
227
|
+
// runtime-writable receipt to select unsandboxed source write destinations.
|
|
228
|
+
const receipt = validReceipt(expectedReceipt)
|
|
229
|
+
const entries = await refreshedEntries(root, receipt)
|
|
230
|
+
for (const [entry, next] of entries) {
|
|
231
|
+
if (refreshFingerprint(next) === entry.hash) continue
|
|
232
|
+
await sourceIdentity(entry)
|
|
233
|
+
if (receipt.cli === 'pi') {
|
|
234
|
+
const { dist } = inspectPiInstallation(executable)
|
|
235
|
+
const require = createRequire(join(dist, 'core/auth-storage.js'))
|
|
236
|
+
const lockfile = require('proper-lockfile')
|
|
237
|
+
// Same canonical auth path and lock convention as Pi 1.0.4. Never call
|
|
238
|
+
// AuthStorage.create here: its initialization would recreate a logged-out file.
|
|
239
|
+
const unlock = await lockfile.lock(entry.path, { realpath: false, retries: 0, stale: 30000 })
|
|
240
|
+
try {
|
|
241
|
+
await sourceIdentity(entry)
|
|
242
|
+
const data = await refreshJson(entry.path, false)
|
|
243
|
+
if (
|
|
244
|
+
refreshFingerprint(data[entry.provider]) !== entry.hash ||
|
|
245
|
+
refreshPrincipal(data[entry.provider]) !== entry.principal
|
|
246
|
+
)
|
|
247
|
+
throw changed()
|
|
248
|
+
const handle = await open(
|
|
249
|
+
entry.path,
|
|
250
|
+
constants.O_WRONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK,
|
|
251
|
+
)
|
|
252
|
+
try {
|
|
253
|
+
const info = await handle.stat()
|
|
254
|
+
if (info.dev !== entry.dev || info.ino !== entry.ino || info.nlink !== 1) throw changed()
|
|
255
|
+
const bytes = Buffer.from(JSON.stringify({ ...data, [entry.provider]: next }, null, 2))
|
|
256
|
+
try {
|
|
257
|
+
let offset = 0
|
|
258
|
+
while (offset < bytes.length) {
|
|
259
|
+
const { bytesWritten } = await handle.write(bytes, offset, bytes.length - offset, offset)
|
|
260
|
+
if (!bytesWritten) throw unsafe()
|
|
261
|
+
offset += bytesWritten
|
|
262
|
+
}
|
|
263
|
+
await handle.truncate(bytes.length)
|
|
264
|
+
await handle.sync()
|
|
265
|
+
} finally {
|
|
266
|
+
bytes.fill(0)
|
|
267
|
+
}
|
|
268
|
+
} finally {
|
|
269
|
+
await handle.close()
|
|
270
|
+
}
|
|
271
|
+
} finally {
|
|
272
|
+
await unlock()
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
// SQLite URI mode=rw never recreates a source deleted after preflight.
|
|
276
|
+
const db = new DatabaseSync(`${pathToFileURL(entry.path).href}?mode=rw`)
|
|
277
|
+
try {
|
|
278
|
+
db.exec('PRAGMA busy_timeout=0; BEGIN IMMEDIATE')
|
|
279
|
+
const row = db
|
|
280
|
+
.prepare(
|
|
281
|
+
'SELECT credential_type,data,disabled_cause FROM auth_credentials WHERE rowid=? AND provider=?',
|
|
282
|
+
)
|
|
283
|
+
.get(entry.rowId, entry.provider)
|
|
284
|
+
const current = rowCredential(row)
|
|
285
|
+
if (
|
|
286
|
+
!current ||
|
|
287
|
+
refreshFingerprint(current) !== entry.hash ||
|
|
288
|
+
refreshPrincipal(current) !== entry.principal
|
|
289
|
+
)
|
|
290
|
+
throw changed()
|
|
291
|
+
const { type: _type, ...data } = next
|
|
292
|
+
const update = db
|
|
293
|
+
.prepare(
|
|
294
|
+
'UPDATE auth_credentials SET data=? WHERE rowid=? AND provider=? AND credential_type=? AND data=? AND disabled_cause IS NULL',
|
|
295
|
+
)
|
|
296
|
+
.run(JSON.stringify(data), entry.rowId, entry.provider, 'oauth', row.data)
|
|
297
|
+
if (Number(update.changes) !== 1) throw changed()
|
|
298
|
+
db.exec('COMMIT')
|
|
299
|
+
} catch (error) {
|
|
300
|
+
try {
|
|
301
|
+
db.exec('ROLLBACK')
|
|
302
|
+
} catch {}
|
|
303
|
+
throw error
|
|
304
|
+
} finally {
|
|
305
|
+
db.close()
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// Reuse the updated Host-held expectation in the next metadata phase and
|
|
309
|
+
// this same prepare's final worker request; don't reject our own refresh.
|
|
310
|
+
entry.hash = refreshFingerprint(next)
|
|
311
|
+
}
|
|
312
|
+
await writeRefreshJson(join(root, 'receipt.json'), receipt)
|
|
313
|
+
} catch (error) {
|
|
314
|
+
if (
|
|
315
|
+
error?.message === '账号配置已变化,请重新刷新模型' ||
|
|
316
|
+
error?.message === '无法安全保存账号续期,请重新登录'
|
|
317
|
+
)
|
|
318
|
+
throw error
|
|
319
|
+
throw unsafe()
|
|
320
|
+
} finally {
|
|
321
|
+
// A CAS conflict is a completed safe refusal, not an unconfirmed process exit.
|
|
322
|
+
await releaseOwnAccountLease(root, nonce)
|
|
323
|
+
}
|
|
324
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Set a private file-creation mask without mutating the shared Harness process.
|
|
2
|
+
import { forwardNativeStdio, spawnNativeProcess } from './native-spawn.mjs'
|
|
3
|
+
import { nativeLaunchArgv } from './native-launch.mjs'
|
|
4
|
+
process.umask(0o077)
|
|
5
|
+
const [executable, ...argv] = nativeLaunchArgv(process.argv.slice(2))
|
|
6
|
+
// This helper is also used under POSIX PTYs, whose original handles must stay.
|
|
7
|
+
// Windows ConPTY account launch unwraps it in windows-account-launch.mjs.
|
|
8
|
+
const backgroundPipes = process.platform === 'win32'
|
|
9
|
+
const child = spawnNativeProcess(executable, argv, { env: process.env, stdio: backgroundPipes ? ['pipe', 'pipe', 'pipe'] : 'inherit' })
|
|
10
|
+
if (backgroundPipes) forwardNativeStdio(child)
|
|
11
|
+
let stopped = false
|
|
12
|
+
for (const signal of ['SIGTERM', 'SIGINT'])
|
|
13
|
+
process.on(signal, () => {
|
|
14
|
+
stopped = true
|
|
15
|
+
child.kill(signal)
|
|
16
|
+
})
|
|
17
|
+
child.on('error', () => {
|
|
18
|
+
process.stderr.write('CLI launch failed\n')
|
|
19
|
+
process.exitCode = 1
|
|
20
|
+
})
|
|
21
|
+
child.on('close', (code, signal) => {
|
|
22
|
+
process.exitCode = stopped || signal ? 143 : (code ?? 1)
|
|
23
|
+
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// The native terminal owner tracks descendants across their own process groups.
|
|
2
|
+
// Keep this root alive until the Host acknowledges cleanup; never merge stderr
|
|
3
|
+
// into the CLI JSON protocol. Envelopes are transport only, not agent events.
|
|
4
|
+
import { spawnNativeProcess } from './native-spawn.mjs'
|
|
5
|
+
import { nativeLaunchArgv } from './native-launch.mjs'
|
|
6
|
+
const [executable, ...args] = nativeLaunchArgv(process.argv.slice(2))
|
|
7
|
+
const send = (channel, fields) => process.stdout.write(JSON.stringify({ channel, ...fields }) + '\n')
|
|
8
|
+
const keepAlive = setInterval(() => {}, 60000)
|
|
9
|
+
const child = spawnNativeProcess(executable, args, { stdio: ['ignore', 'pipe', 'pipe'] })
|
|
10
|
+
child.stdout.on('data', (bytes) => send('stdout', { bytes: bytes.toString('base64') }))
|
|
11
|
+
child.stderr.on('data', (bytes) => send('stderr', { bytes: bytes.toString('base64') }))
|
|
12
|
+
child.on('error', (error) => send('error', { message: error.message }))
|
|
13
|
+
child.on('close', (exitCode, signal) => send('exit', { exitCode, signal }))
|
|
14
|
+
// Native terminal teardown kills descendants first, then this root.
|
|
15
|
+
process.on('SIGTERM', () => {
|
|
16
|
+
clearInterval(keepAlive)
|
|
17
|
+
process.exit(0)
|
|
18
|
+
})
|