@sleep2agi/agent-network 2.3.0-preview.9 → 2.3.0-preview.91
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 +35 -324
- package/dist/bin/anet.cjs +101 -0
- package/dist/bin/cli.d.ts +1 -0
- package/dist/bin/cli.js +20 -1
- package/dist/bin/goal-wake-log-render.d.ts +31 -0
- package/dist/src/active-network-task.d.ts +28 -0
- package/dist/src/batch-workdir.d.ts +9 -0
- package/dist/src/bootstrap-password-db.d.ts +13 -0
- package/dist/src/channel-attachments.d.ts +29 -0
- package/dist/src/channel-meta.d.ts +10 -0
- package/dist/src/channel-task-trace.d.ts +14 -0
- package/dist/src/claude-vendor-env.d.ts +28 -0
- package/dist/src/cli-args.d.ts +8 -0
- package/dist/src/cli-version-display.d.ts +16 -0
- package/dist/src/client-task-trace.d.ts +9 -0
- package/dist/src/client.js +1 -1
- package/dist/src/codex-copresence-preflight.d.ts +65 -0
- package/dist/src/codex-copresence-profile.d.ts +125 -0
- package/dist/src/codex-copresence-recovery.d.ts +43 -0
- package/dist/src/codex-copresence-thread.d.ts +13 -0
- package/dist/src/codex-lifecycle-account.d.ts +104 -0
- package/dist/src/codex-lifecycle-canary.d.ts +20 -0
- package/dist/src/codex-lifecycle-facts.d.ts +53 -0
- package/dist/src/codex-lifecycle-fork.d.ts +53 -0
- package/dist/src/codex-lifecycle-preflight.d.ts +77 -0
- package/dist/src/codex-lifecycle-receipt.d.ts +44 -0
- package/dist/src/codex-lifecycle-restart.d.ts +86 -0
- package/dist/src/codex-model-default.d.ts +6 -0
- package/dist/src/codex-tui-client-health.d.ts +17 -0
- package/dist/src/commhub-response.d.ts +1 -0
- package/dist/src/controlled-upload.d.ts +83 -0
- package/dist/src/copresence-deps.d.ts +22 -0
- package/dist/src/copresence-identity.d.ts +353 -0
- package/dist/src/copresence-startup-diagnosis.d.ts +17 -0
- package/dist/src/daemon-capability-display.d.ts +110 -0
- package/dist/src/daemon-capability-display.js +21 -0
- package/dist/src/daemon-runtime-path-preflight.d.ts +22 -0
- package/dist/src/daemon-runtime-staleness.d.ts +13 -0
- package/dist/src/dashboard-managed-process.d.ts +35 -0
- package/dist/src/display-width.d.ts +27 -0
- package/dist/src/doctor-node-count.d.ts +28 -0
- package/dist/src/environ-alias.d.ts +14 -0
- package/dist/src/grok-attach-client.d.ts +129 -0
- package/dist/src/grok-build-drift.d.ts +15 -0
- package/dist/src/grok-copresence-disclosure.d.ts +11 -0
- package/dist/src/grok-copresence-orchestration.d.ts +75 -0
- package/dist/src/grok-copresence-profile.d.ts +65 -0
- package/dist/src/host-telemetry.d.ts +14 -0
- package/dist/src/hub-time-display.d.ts +20 -0
- package/dist/src/hub-version-skew.d.ts +19 -0
- package/dist/src/im/correlation-store.d.ts +34 -0
- package/dist/src/im/feishu/adapter.d.ts +80 -0
- package/dist/src/im/feishu/bridge.d.ts +85 -14
- package/dist/src/im/feishu/config.d.ts +31 -0
- package/dist/src/im/feishu/hub-upload.d.ts +88 -0
- package/dist/src/im/feishu/outbound-marker.d.ts +24 -19
- package/dist/src/im/feishu/outbound-paths.d.ts +50 -0
- package/dist/src/im/feishu/outbound-route.d.ts +62 -0
- package/dist/src/im/feishu/worker-lifecycle.d.ts +13 -0
- package/dist/src/im/feishu/worker.js +187 -144
- package/dist/src/im/types.d.ts +38 -1
- package/dist/src/local-process-state.d.ts +12 -0
- package/dist/src/locale-diagnostic.d.ts +12 -0
- package/dist/src/ls-columns.d.ts +15 -0
- package/dist/src/mock-llm.d.ts +12 -0
- package/dist/src/node-activity-log.d.ts +4 -0
- package/dist/src/node-not-found.d.ts +1 -0
- package/dist/src/node-running-guard.d.ts +9 -0
- package/dist/src/node-server-payload.d.ts +66 -0
- package/dist/src/node-server.js +7 -1
- package/dist/src/normalize-runtime.d.ts +29 -2
- package/dist/src/offline-age.d.ts +29 -0
- package/dist/src/one-line-cell.d.ts +20 -0
- package/dist/src/opencode-agent-node-pair.d.ts +25 -0
- package/dist/src/opencode-auth-login.d.ts +43 -0
- package/dist/src/opencode-launch-env.d.ts +13 -0
- package/dist/src/opencode-owner-mode.d.ts +6 -0
- package/dist/src/opencode-package-binary.d.ts +26 -0
- package/dist/src/opencode-pin.d.ts +44 -0
- package/dist/src/opencode-preset.d.ts +73 -0
- package/dist/src/opencode-runtime-binding.d.ts +30 -0
- package/dist/src/opencode-safe-root.d.ts +36 -0
- package/dist/src/opencode-smoke-env.d.ts +1 -0
- package/dist/src/outbound-attachments.d.ts +60 -0
- package/dist/src/outbound-tool-names.d.ts +1 -0
- package/dist/src/owned-roots.d.ts +58 -0
- package/dist/src/owner-env-file.d.ts +2 -0
- package/dist/src/package-mode-preflight.d.ts +41 -0
- package/dist/src/posix-codex-copresence.d.ts +8 -0
- package/dist/src/posix-modes.d.ts +36 -0
- package/dist/src/primary-network.d.ts +23 -0
- package/dist/src/private-state.d.ts +10 -0
- package/dist/src/process-telemetry.d.ts +12 -0
- package/dist/src/profile-serialize.d.ts +1 -0
- package/dist/src/project-key.d.ts +1 -0
- package/dist/src/reply-local-links.d.ts +47 -0
- package/dist/src/reply-originator.d.ts +20 -0
- package/dist/src/resume-runtime-infer.d.ts +18 -0
- package/dist/src/secret-shell-guidance.d.ts +3 -0
- package/dist/src/session-status-class.d.ts +48 -0
- package/dist/src/sibling-agent-node.d.ts +23 -0
- package/dist/src/stale-socket.d.ts +118 -0
- package/dist/src/subcommand-redirect.d.ts +26 -0
- package/dist/src/task-trace.d.ts +33 -0
- package/dist/src/tmux-attach.d.ts +8 -0
- package/dist/src/tmux-capability.d.ts +58 -0
- package/dist/src/tmux-exact-target.d.ts +34 -0
- package/dist/src/tmux-pane-prompt.d.ts +22 -0
- package/dist/src/token-cli.d.ts +13 -0
- package/dist/src/tool-allowlist.d.ts +28 -0
- package/dist/src/unsafe-package-path-reason.d.ts +17 -0
- package/dist/src/win-launcher.d.ts +20 -0
- package/dist/src/windows-codex-copresence.d.ts +60 -0
- package/package.json +10 -5
|
@@ -1,9 +1,36 @@
|
|
|
1
|
-
export type RuntimeName = "claude-code-cli" | "codex-sdk" | "claude-agent-sdk" | "grok-build-acp";
|
|
2
|
-
/**
|
|
1
|
+
export type RuntimeName = "claude-code-cli" | "codex-sdk" | "claude-agent-sdk" | "grok-build-acp" | "grok-build-cli" | "opencode-cli" | "codex-app-server";
|
|
2
|
+
/** 一个 runtime 复用的是哪种**外部登录态**,而不是 API key。 */
|
|
3
|
+
export type ReusedLogin = "claude" | "codex" | "grok";
|
|
4
|
+
/**
|
|
5
|
+
* runtime → 它复用的外部登录。**只有一处定义**,VENDORS 的 `requiresAuth`
|
|
6
|
+
* 与登录态探测都引用这里。
|
|
7
|
+
*
|
|
8
|
+
* 不在表里 = 该 runtime 走 API key,不复用任何登录:
|
|
9
|
+
* · `claude-agent-sdk` —— 走 ANTHROPIC_AUTH_TOKEN / ANTHROPIC_API_KEY
|
|
10
|
+
* · `opencode-cli` —— 走 ANTHROPIC_API_KEY / OPENAI_API_KEY(vendor preset 从 env 读,不 prompt)
|
|
11
|
+
* 这条区分是有意写下来的:Vincent 那句「复用会员登录状态、不用自己输 key 和 url」
|
|
12
|
+
* 点名的是 Claude Code / Codex / Grok 三家,opencode 不在其中,别顺手加进来。
|
|
13
|
+
*/
|
|
14
|
+
export declare const RUNTIME_REUSED_LOGIN: Readonly<Partial<Record<RuntimeName, ReusedLogin>>>;
|
|
15
|
+
/** 该 runtime 复用哪种登录;返回 undefined 表示它用 API key。 */
|
|
16
|
+
export declare function reusedLoginFor(runtime: RuntimeName): ReusedLogin | undefined;
|
|
17
|
+
/** Operator-facing default for a runtime slot that is empty or missing. */
|
|
3
18
|
export declare const DEFAULT_RUNTIME: RuntimeName;
|
|
19
|
+
export declare const SUPPORTED_RUNTIME_NAMES: readonly RuntimeName[];
|
|
4
20
|
type ProfileLike = {
|
|
5
21
|
runtime?: string;
|
|
6
22
|
codexRuntime?: string;
|
|
7
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Legacy normalization used by display and migration code. Missing, empty,
|
|
26
|
+
* and unknown values all use the safe default for backward compatibility.
|
|
27
|
+
* Security-sensitive create/start paths must call `normalizeRuntimeStrict`.
|
|
28
|
+
*/
|
|
8
29
|
export declare function normalizeRuntime(profileOrRuntime?: ProfileLike | string): RuntimeName;
|
|
30
|
+
/**
|
|
31
|
+
* Canonicalize a runtime at an execution boundary. Missing/empty still means
|
|
32
|
+
* the documented default, but any non-empty unknown value is rejected so a
|
|
33
|
+
* typo or future runtime cannot silently execute as Claude.
|
|
34
|
+
*/
|
|
35
|
+
export declare function normalizeRuntimeStrict(profileOrRuntime?: ProfileLike | string): RuntimeName;
|
|
9
36
|
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #1648 — 名册上「刚停的节点」和「掉了三天没人发现的节点」渲染成同一个数字。
|
|
3
|
+
*
|
|
4
|
+
* `anet status` 原先只印 `N offline`。实测(2026-08-31,84 台 TM 相关节点):
|
|
5
|
+
* 45 台 offline 里 27 台 >3 天、18 台 1–3 天、**近 6 小时内 0 台** ——
|
|
6
|
+
* 「当前没有活故障」和「有 45 台掉了」是完全不同的两个结论,而屏幕上只有后者。
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* 🔴 hub 存的 `last_seen_at` 是 **UTC**,但字符串里**没有时区标记**
|
|
10
|
+
* (形如 `2026-08-30 21:11:24`)。直接 `new Date(raw)` 会被当成**本地时间**:
|
|
11
|
+
* 在 UTC+8 上就是整整 8 小时的偏差,而且它**不会报错** —— 只会把「4 分钟前」
|
|
12
|
+
* 读成「8 小时前」。这个错本人在 2026-08-31 亲自犯过一次,差点把
|
|
13
|
+
* 「舰队心跳陈旧」报出去。
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseHubTimestamp(raw: unknown): number | null;
|
|
16
|
+
export type OfflineAges = {
|
|
17
|
+
under1h: number;
|
|
18
|
+
h1to24: number;
|
|
19
|
+
d1to3: number;
|
|
20
|
+
over3d: number;
|
|
21
|
+
/** 🔴 没有可用时间戳的那些必须单独一格,不能并进任何一档 —— 见下 */
|
|
22
|
+
unknown: number;
|
|
23
|
+
total: number;
|
|
24
|
+
};
|
|
25
|
+
export declare function summarizeOfflineAges(offline: ReadonlyArray<{
|
|
26
|
+
last_seen_at?: unknown;
|
|
27
|
+
}>, nowMs: number): OfflineAges;
|
|
28
|
+
/** 返回空串表示「没有值得多说一句的东西」,调用方据此决定印不印。 */
|
|
29
|
+
export declare function formatOfflineAges(a: OfflineAges): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI 里那几张对齐表(`anet status` 的 needs-attention / working,以及 Recent Tasks
|
|
3
|
+
* 和 `anet tasks`)把**用户提供的文本**直接 `slice(0, N)` 塞进一行。
|
|
4
|
+
*
|
|
5
|
+
* 🔴 任务正文里有换行时,截出来的那段会**把整张表打断**。实测(2026-08-31,
|
|
6
|
+
* 真跑 `anet status` 才看见,读代码看不出来):
|
|
7
|
+
*
|
|
8
|
+
* grok-v1 blocked 【把你自己的名册状态修正过来 —— 两步,别做别的】
|
|
9
|
+
*
|
|
10
|
+
* 你今天两次在 22 秒内答了我的探测(G
|
|
11
|
+
*
|
|
12
|
+
* 第二行完全脱离了对齐,而且读起来像另一个节点的输出。
|
|
13
|
+
*
|
|
14
|
+
* 这里把所有空白(含 \n \r \t 和连续空格)折成单个空格再截。
|
|
15
|
+
*
|
|
16
|
+
* 🔴 **有意不加省略号**:加了会改变列宽,而列宽是这几张表现有的对齐依据。
|
|
17
|
+
* 「截断了却看不出来」是另一个问题(先存在于这里,本次不动),
|
|
18
|
+
* 不要顺手在一个修显示错位的改动里改掉它。
|
|
19
|
+
*/
|
|
20
|
+
export declare function oneLineCell(text: unknown, max: number): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const PAIRED_AGENT_NETWORK_VERSION = "2.3.0-preview.91";
|
|
2
|
+
export declare const PAIRED_AGENT_NODE_VERSION = "2.5.0-preview.69";
|
|
3
|
+
export declare const PAIRED_AGENT_NODE_SPEC = "@sleep2agi/agent-node@2.5.0-preview.69";
|
|
4
|
+
export declare const OPENCODE_AGENT_NETWORK_VERSION = "2.3.0-preview.91";
|
|
5
|
+
export declare const OPENCODE_AGENT_NODE_VERSION = "2.5.0-preview.69";
|
|
6
|
+
export declare const OPENCODE_AGENT_NODE_SPEC = "@sleep2agi/agent-node@2.5.0-preview.69";
|
|
7
|
+
export type PairedAgentNodeResolution = {
|
|
8
|
+
spec: string;
|
|
9
|
+
args: string[];
|
|
10
|
+
allowPathGlobal: false;
|
|
11
|
+
};
|
|
12
|
+
/** The codex bridge must resolve the immutable release pair, independent of PATH. */
|
|
13
|
+
export declare function pairedAgentNodeResolution(): PairedAgentNodeResolution;
|
|
14
|
+
export declare function agentNodeHelpSupportsCodexAppServer(help: string): boolean;
|
|
15
|
+
export declare function opencodeExactPairInstallCommand(): string;
|
|
16
|
+
/** Runtime capability advertised by agent-node's operator-facing help. */
|
|
17
|
+
export declare function agentNodeHelpSupportsOpencode(help: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a package-owned agent-node entrypoint and verify its immutable
|
|
20
|
+
* release identity before it can receive `opencode-cli`. Capability text is
|
|
21
|
+
* not a security boundary: an older preview already advertised the runtime.
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateAgentNodePackageEntrypoint(rawEntrypoint: string, packageSpec: string, expectedVersion?: string, forbiddenRoots?: readonly string[]): string;
|
|
24
|
+
/** Skip invalid/local PATH shims and return the first exact trusted package. */
|
|
25
|
+
export declare function resolveAgentNodePackageEntrypointFromPath(searchPath: string, packageSpec: string, expectedVersion: string, forbiddenRoots?: readonly string[]): string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { OpencodePresetId } from "./opencode-preset";
|
|
2
|
+
export declare const OPENCODE_AUTH_LOGIN_ROOT_PREFIX = "opencode-auth-login-";
|
|
3
|
+
export declare const OPENCODE_AUTH_LOGIN_OWNER_FILE = ".owner.json";
|
|
4
|
+
export declare const OPENCODE_AUTH_LOGIN_CLEANUP_PREFIX = ".anet-opencode-auth-cleanup-";
|
|
5
|
+
export interface OpencodeAuthLoginSandbox {
|
|
6
|
+
readonly nodeWorkDir: string;
|
|
7
|
+
readonly provider: OpencodePresetId;
|
|
8
|
+
readonly root: string;
|
|
9
|
+
readonly cwd: string;
|
|
10
|
+
readonly authPath: string;
|
|
11
|
+
readonly env: Readonly<NodeJS.ProcessEnv>;
|
|
12
|
+
}
|
|
13
|
+
export interface CreateOpencodeAuthLoginSandboxOptions {
|
|
14
|
+
nodeWorkDir: string;
|
|
15
|
+
provider: OpencodePresetId | string;
|
|
16
|
+
parentEnv?: NodeJS.ProcessEnv;
|
|
17
|
+
/** Internal/test-only trusted external base override. */
|
|
18
|
+
launchBase?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface OpencodeAuthLoginCredential {
|
|
21
|
+
provider: OpencodePresetId;
|
|
22
|
+
type: "api";
|
|
23
|
+
key: string;
|
|
24
|
+
}
|
|
25
|
+
/** Deterministic exact-1.18.1 login argv for the selected API-key flow. */
|
|
26
|
+
export declare function buildOpencodeAuthLoginArgs(provider: OpencodePresetId | string): string[];
|
|
27
|
+
/** Prepare a fresh, node-scoped environment for one interactive login. */
|
|
28
|
+
export declare function createOpencodeAuthLoginSandbox(options: CreateOpencodeAuthLoginSandboxOptions): OpencodeAuthLoginSandbox;
|
|
29
|
+
/** Repeat external-root ancestor and inode validation immediately before the
|
|
30
|
+
* vetted upstream binary is spawned. */
|
|
31
|
+
export declare function revalidateOpencodeAuthLoginSandbox(sandbox: OpencodeAuthLoginSandbox): void;
|
|
32
|
+
/**
|
|
33
|
+
* Read only the selected provider's exact API-key shape from the fresh root.
|
|
34
|
+
* OAuth/browser-login records and mixed/multi-provider documents are refused.
|
|
35
|
+
*/
|
|
36
|
+
export declare function readOpencodeAuthLoginCredential(sandbox: OpencodeAuthLoginSandbox): OpencodeAuthLoginCredential;
|
|
37
|
+
/** Safely remove a sandbox created by this process. Idempotent after removal. */
|
|
38
|
+
export declare function cleanupOpencodeAuthLoginSandbox(sandbox: OpencodeAuthLoginSandbox): void;
|
|
39
|
+
/**
|
|
40
|
+
* Lifecycle helper for CLI integration. Spawn/wait/read the credential inside
|
|
41
|
+
* `action`; the fresh tree is cleaned on success, child failure, or throw.
|
|
42
|
+
*/
|
|
43
|
+
export declare function withOpencodeAuthLoginSandbox<T>(options: CreateOpencodeAuthLoginSandboxOptions, action: (sandbox: OpencodeAuthLoginSandbox) => T | Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-loader hooks that must never cross the opencode-cli launcher
|
|
3
|
+
* boundary. The exact agent-node package/entrypoint check happens before the
|
|
4
|
+
* node profile env is merged; allowing that profile to supply one of these
|
|
5
|
+
* variables would let code run before the verified entrypoint's first line.
|
|
6
|
+
*/
|
|
7
|
+
export declare const OPENCODE_AGENT_NODE_LOADER_ENV_KEYS: readonly ["NODE_OPTIONS", "NODE_PATH", "NODE_V8_COVERAGE", "NODE_REDIRECT_WARNINGS", "NODE_COMPILE_CACHE", "BUN_OPTIONS", "BUN_PRELOAD", "LD_PRELOAD", "LD_LIBRARY_PATH", "LD_AUDIT", "LD_DEBUG_OUTPUT", "DYLD_INSERT_LIBRARIES", "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH", "DYLD_FALLBACK_LIBRARY_PATH", "OPENSSL_CONF", "OPENSSL_ENGINES", "OPENSSL_MODULES"];
|
|
8
|
+
/**
|
|
9
|
+
* Return a child env that preserves the launcher's original executable search
|
|
10
|
+
* path and removes pre-entrypoint loader/write hooks. Other operator settings
|
|
11
|
+
* (locale, proxy, custom CA, channel integration) remain backward-compatible.
|
|
12
|
+
*/
|
|
13
|
+
export declare function hardenOpencodeAgentNodeEnv(source: NodeJS.ProcessEnv, launcherPath: string | undefined): NodeJS.ProcessEnv;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Linux user-private-group compatibility for ordinary umask 0002 installs. */
|
|
2
|
+
export declare function opencodeOwnedPathModeIsSafe(stat: {
|
|
3
|
+
uid: number;
|
|
4
|
+
gid: number;
|
|
5
|
+
mode: number | bigint;
|
|
6
|
+
}, runtimeUid?: number | undefined, runtimeGid?: number | undefined): boolean;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface ValidateOpencodePackageBinaryOptions {
|
|
2
|
+
expectedVersion: string;
|
|
3
|
+
/** A package payload may not be inside, or contain, the current project or
|
|
4
|
+
* node state tree. This rejects project-local same-version impersonators. */
|
|
5
|
+
forbiddenRoots?: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
/** Current cwd plus every enclosing source-workspace boundary. This catches a
|
|
8
|
+
* monorepo root's node_modules when anet is invoked from packages/app. */
|
|
9
|
+
export declare function discoverOpencodeForbiddenRoots(cwd?: string): string[];
|
|
10
|
+
/**
|
|
11
|
+
* Bind an executable to the exact npm `opencode-ai` payload identity.
|
|
12
|
+
*
|
|
13
|
+
* `--version` output alone is not an identity boundary: a checkout can put a
|
|
14
|
+
* same-version credential-stealing shim first on PATH. Only the canonical
|
|
15
|
+
* package entrypoint with matching package metadata and trusted path modes is
|
|
16
|
+
* admitted. The returned path is the one callers must spawn verbatim.
|
|
17
|
+
*/
|
|
18
|
+
export declare function validateOpencodePackageBinary(rawBinary: string, options: ValidateOpencodePackageBinaryOptions): string;
|
|
19
|
+
/** Resolve the first *valid package-owned* OpenCode entry on PATH. Invalid
|
|
20
|
+
* project-local shims are skipped so a later trusted global install can win. */
|
|
21
|
+
/** #1845 层① —— 包身份校验只依赖 POSIX 的 lstat/uid/mode 语义,darwin 与 linux 等价
|
|
22
|
+
* (2026-09-07 Mac mini 真跑:home 前缀 npm 安装 → VALIDATE_OK;/tmp 下祖先 1777 仍被拒)。
|
|
23
|
+
* win32 没有 uid、也没有 0o111 可执行位,继续拦。平台可注入,便于在 Linux CI 上测三种分支。 */
|
|
24
|
+
export declare const OPENCODE_VERIFIER_PLATFORMS: ReadonlySet<NodeJS.Platform>;
|
|
25
|
+
export declare function opencodeVerifierSupportsPlatform(platform?: NodeJS.Platform): boolean;
|
|
26
|
+
export declare function resolveOpencodePackageBinaryFromPath(searchPath: string, options: ValidateOpencodePackageBinaryOptions, platform?: NodeJS.Platform): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version this branch was validated against by the maintainers.
|
|
3
|
+
* Bumped when a new opencode-ai release passes the full Docker/E2E gate.
|
|
4
|
+
*/
|
|
5
|
+
export declare const OPENCODE_BUILTIN_PIN = "1.18.1";
|
|
6
|
+
/** Exact upstream remediation shared by every CLI failure path. */
|
|
7
|
+
export declare function opencodeExactInstallCommand(version?: string): string;
|
|
8
|
+
/** Preserve package-identity diagnostics while always leaving a missing or
|
|
9
|
+
* untrusted install with an actionable exact-pin command. */
|
|
10
|
+
export declare function formatOpencodePackageIdentityFailure(expectedVersion: string, detail: string): string;
|
|
11
|
+
/** Where the per-machine override lives. Kept under `~/.anet/` so
|
|
12
|
+
* it sits next to the other anet-local state. */
|
|
13
|
+
export declare function opencodePinFilePath(homeDirOverride?: string): string;
|
|
14
|
+
/** Shape of the override file written by `upgrade-pin`. */
|
|
15
|
+
export interface OpencodePinOverride {
|
|
16
|
+
version: string;
|
|
17
|
+
/** ISO timestamp when the smoke test passed. Presence of this
|
|
18
|
+
* field is REQUIRED for `readEffectivePin()` to trust the file —
|
|
19
|
+
* a hand-edited version without a smoke marker is refused. */
|
|
20
|
+
smokePassedAt: string;
|
|
21
|
+
/** Free-form note about what the smoke checked (initialize +
|
|
22
|
+
* session/new by default). Kept so a future review can tell what
|
|
23
|
+
* bar the pin actually cleared. */
|
|
24
|
+
smokeNote?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface EffectivePin {
|
|
27
|
+
version: string;
|
|
28
|
+
source: "override-file" | "builtin";
|
|
29
|
+
smokePassedAt?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Recognize a validated override only when it records the exact built-in
|
|
33
|
+
* release pin. A different locally-smoked version is deliberately ignored:
|
|
34
|
+
* the lightweight ACP smoke does not replace the maintainer's full security
|
|
35
|
+
* and reply-path gate. Malformed/stale files also fall back to the built-in.
|
|
36
|
+
*/
|
|
37
|
+
export declare function readEffectivePin(homeDirOverride?: string): EffectivePin;
|
|
38
|
+
/**
|
|
39
|
+
* Write the override — SHOULD ONLY be called after the smoke test
|
|
40
|
+
* has actually passed. The command layer in `bin/cli.ts` is
|
|
41
|
+
* responsible for gating this; this function does no
|
|
42
|
+
* verification of its own beyond shape.
|
|
43
|
+
*/
|
|
44
|
+
export declare function writePinOverride(version: string, smokePassedAt: string, smokeNote?: string, homeDirOverride?: string): void;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export type OpencodePresetId = "anthropic" | "openai";
|
|
2
|
+
export interface OpencodePreset {
|
|
3
|
+
id: OpencodePresetId;
|
|
4
|
+
displayName: string;
|
|
5
|
+
envKey: string;
|
|
6
|
+
signupUrl: string;
|
|
7
|
+
/** How opencode's provider config identifies this vendor in the
|
|
8
|
+
* `provider.<id>.options.baseUrl` config. Left null when we don't
|
|
9
|
+
* need to override the built-in default. */
|
|
10
|
+
configProviderId: "anthropic" | "openai";
|
|
11
|
+
}
|
|
12
|
+
export declare const OPENCODE_PRESETS: OpencodePreset[];
|
|
13
|
+
/**
|
|
14
|
+
* OpenCode tools disabled for the default `opencode-cli` profile.
|
|
15
|
+
*
|
|
16
|
+
* This policy reduces the model's ambient filesystem/shell surface. It is
|
|
17
|
+
* deliberately represented in the generated opencode.json so operators can
|
|
18
|
+
* inspect the default, but it is not an OS security boundary: a same-uid
|
|
19
|
+
* OpenCode process can still read files allowed by normal filesystem ACLs.
|
|
20
|
+
*/
|
|
21
|
+
export declare const OPENCODE_DEFAULT_DISABLED_TOOLS: readonly ["bash", "read", "glob", "grep", "edit", "write", "list", "task", "skill", "webfetch", "websearch", "question"];
|
|
22
|
+
export declare function buildOpencodeDefaultToolsPolicy(): Record<string, false>;
|
|
23
|
+
export declare function buildOpencodeDefaultPermissionPolicy(): Record<string, "deny">;
|
|
24
|
+
export declare function findOpencodePreset(id: string): OpencodePreset | null;
|
|
25
|
+
/**
|
|
26
|
+
* Look up the API key for a preset from the current process env.
|
|
27
|
+
* Callers MUST handle the `null` case (per RFC v0.3 D3 + 通信龙 PR③
|
|
28
|
+
* flag: "从 env 读, 别 prompt"). Returns null so the wizard can
|
|
29
|
+
* emit a clear message telling the operator to export the env var
|
|
30
|
+
* and re-run — rather than silently continuing without a key.
|
|
31
|
+
*/
|
|
32
|
+
export declare function readPresetKeyFromEnv(preset: OpencodePreset, env?: NodeJS.ProcessEnv): string | null;
|
|
33
|
+
/**
|
|
34
|
+
* opencode.ai's auth.json shape:
|
|
35
|
+
* { "<providerId>": { "type": "api", "key": "..." } }
|
|
36
|
+
* Same shape verified against the release pin opencode-ai@1.18.1.
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildAuthJsonBody(preset: OpencodePreset, apiKey: string): string;
|
|
39
|
+
export type OpencodePrivateProfileFilename = "config.json" | ".env";
|
|
40
|
+
/**
|
|
41
|
+
* Establish the boundary before saveProfile/rewritePlainSecrets writes the
|
|
42
|
+
* node token or dotenv key. The expected shape is exactly
|
|
43
|
+
* `<project>/.anet/nodes/<node>`. Every existing path is inspected with
|
|
44
|
+
* lstat + O_NOFOLLOW and inode checks; absent private directories are created
|
|
45
|
+
* one component at a time. A pre-planted node-root/config/.env symlink is a
|
|
46
|
+
* hard error before any secret-bearing write.
|
|
47
|
+
*/
|
|
48
|
+
export declare function prepareOpencodeNodeForProfileWrite(nodeWorkDir: string): string;
|
|
49
|
+
export declare function readOpencodePrivateProfileFile(nodeWorkDir: string, filename: OpencodePrivateProfileFilename): string | undefined;
|
|
50
|
+
export declare function writeOpencodePrivateProfileFile(nodeWorkDir: string, filename: OpencodePrivateProfileFilename, body: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Write auth.json into the opencode config root that lives under
|
|
53
|
+
* `nodeWorkDir` (the per-node OpenCode data root). mode 0o600 limits
|
|
54
|
+
* filesystem access to the owning OS account; it does not prevent a
|
|
55
|
+
* same-uid OpenCode child from opening the file directly. Directory is
|
|
56
|
+
* created if missing.
|
|
57
|
+
*
|
|
58
|
+
* Returns the absolute path we wrote for logging.
|
|
59
|
+
*/
|
|
60
|
+
export declare function writeOpencodeAuthJson(nodeWorkDir: string, preset: OpencodePreset, apiKey: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* New keyless nodes must not inherit a private-but-preplanted credential.
|
|
63
|
+
* Keep the file present as an explicit empty object so the creation log's
|
|
64
|
+
* "auth not configured" statement matches the state OpenCode will consume.
|
|
65
|
+
*/
|
|
66
|
+
export declare function clearOpencodeAuthJson(nodeWorkDir: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* Companion opencode.json: records only the selected blessed provider
|
|
69
|
+
* identity and safe-by-default tool policy. Pre-existing model routing and
|
|
70
|
+
* arbitrary OpenCode integrations are stripped; operators may explicitly set
|
|
71
|
+
* a model after creation, which the runtime's separate safe renderer retains.
|
|
72
|
+
*/
|
|
73
|
+
export declare function writeOpencodeConfigJson(nodeWorkDir: string, preset: OpencodePreset): string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare const OPENCODE_RUNTIME_BINDING_SCHEMA_VERSION: 1;
|
|
2
|
+
export declare const OPENCODE_RUNTIME_BINDING_RUNTIME: "opencode-cli";
|
|
3
|
+
export declare const OPENCODE_RUNTIME_BINDINGS_DIRECTORY = "opencode-runtime-bindings";
|
|
4
|
+
export interface OpencodeRuntimeBinding {
|
|
5
|
+
schemaVersion: typeof OPENCODE_RUNTIME_BINDING_SCHEMA_VERSION;
|
|
6
|
+
runtime: typeof OPENCODE_RUNTIME_BINDING_RUNTIME;
|
|
7
|
+
projectRoot: string;
|
|
8
|
+
nodeId: string;
|
|
9
|
+
}
|
|
10
|
+
/** Windows reports synthetic POSIX permission bits; retain all other checks there. */
|
|
11
|
+
export declare function isOpencodeRuntimeBindingModeSecure(mode: number, exactMode?: number, platform?: NodeJS.Platform): boolean;
|
|
12
|
+
/** Resolve the deterministic binding path without creating HOME state. */
|
|
13
|
+
export declare function opencodeRuntimeBindingPath(nodeWorkDir: string, homeDirectory?: string): string;
|
|
14
|
+
/** Persist an external, immutable-by-config record that this node was created as OpenCode. */
|
|
15
|
+
export declare function writeOpencodeRuntimeBinding(nodeWorkDir: string, homeDirectory?: string): string;
|
|
16
|
+
/** Read and validate a binding. Missing bindings return undefined; unsafe or tampered state throws. */
|
|
17
|
+
export declare function readOpencodeRuntimeBinding(nodeWorkDir: string, homeDirectory?: string): OpencodeRuntimeBinding | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Remove only the exact, validated binding for this node. Missing exact state is
|
|
20
|
+
* idempotent; malformed, replaced, or unsafe state always fails closed.
|
|
21
|
+
*/
|
|
22
|
+
export declare function removeOpencodeRuntimeBinding(nodeWorkDir: string, homeDirectory?: string): boolean;
|
|
23
|
+
/** Assert that the external record exists and exactly identifies this node as opencode-cli. */
|
|
24
|
+
export declare function assertExactOpencodeRuntimeBinding(nodeWorkDir: string, homeDirectory?: string): OpencodeRuntimeBinding;
|
|
25
|
+
/**
|
|
26
|
+
* Refuse OpenCode node state committed to a surrounding Git index. A normal
|
|
27
|
+
* non-Git project is allowed. Git is always invoked directly with argv and a
|
|
28
|
+
* literal pathspec; no shell or command interpolation is used.
|
|
29
|
+
*/
|
|
30
|
+
export declare function assertOpencodeNodeStateUntracked(nodeWorkDir: string): void;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Exact 1.18.1 project/instruction discovery surface plus project-root
|
|
2
|
+
* redirects. Any existing entry, including a broken symlink, is a refusal. */
|
|
3
|
+
export declare const OPENCODE_SAFE_ANCESTOR_CANDIDATES: readonly ["opencode.jsonc", "opencode.json", ".opencode", "AGENTS.md", "CLAUDE.md", "CONTEXT.md", ".claude", ".agents", ".git"];
|
|
4
|
+
interface PathIdentity {
|
|
5
|
+
path: string;
|
|
6
|
+
dev: number | bigint;
|
|
7
|
+
ino: number | bigint;
|
|
8
|
+
}
|
|
9
|
+
export interface OpencodeSafeExternalRoot {
|
|
10
|
+
readonly base: string;
|
|
11
|
+
readonly root: string;
|
|
12
|
+
readonly cwd: string;
|
|
13
|
+
readonly dev: number | bigint;
|
|
14
|
+
readonly ino: number | bigint;
|
|
15
|
+
readonly baseDev: number | bigint;
|
|
16
|
+
readonly baseIno: number | bigint;
|
|
17
|
+
readonly ancestors: readonly PathIdentity[];
|
|
18
|
+
}
|
|
19
|
+
/** #1845 层② —— 运行时隔离 base 的平台策略。规则(祖先不可符号链接、非 root 只能是本 uid、无 0o022 写位、
|
|
20
|
+
* base 本身 uid-owned 0700)三平台一样;不同的只有**默认 base 在哪**:
|
|
21
|
+
* linux → /run/user/<uid>(systemd 的每用户 0700 运行目录;缺失时仅 root 可建)
|
|
22
|
+
* darwin → realpath($TMPDIR)(macOS 每用户 0700 的 /private/var/folders/xx/<hash>/T;2026-09-07 Mac mini 量过
|
|
23
|
+
* 全链:T 700 uid、<hash> 755 uid、其余 755 root,满足同一套祖先规则)
|
|
24
|
+
* 其它 → 拦(win32 没有 uid 语义)
|
|
25
|
+
* 显式 base(参数或 ANET_OPENCODE_SAFE_BASE)三平台通用。platform / env 可注入,便于在 Linux CI 上测 darwin 分支。 */
|
|
26
|
+
export declare const OPENCODE_SAFE_ROOT_PLATFORMS: ReadonlySet<NodeJS.Platform>;
|
|
27
|
+
export declare function defaultOpencodeRuntimeBase(uid: number, platform: NodeJS.Platform, env: NodeJS.ProcessEnv): string;
|
|
28
|
+
export declare function resolveOpencodeTrustedRuntimeBase(explicit?: string, platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): PathIdentity;
|
|
29
|
+
export declare function createOpencodeSafeExternalRoot(options: {
|
|
30
|
+
prefix: string;
|
|
31
|
+
boundaries?: readonly string[];
|
|
32
|
+
base?: string;
|
|
33
|
+
}): OpencodeSafeExternalRoot;
|
|
34
|
+
export declare function revalidateOpencodeSafeExternalRoot(context: OpencodeSafeExternalRoot): void;
|
|
35
|
+
export declare function cleanupOpencodeSafeExternalRoot(context: OpencodeSafeExternalRoot): void;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function buildOpencodeSmokeEnv(parentEnv: NodeJS.ProcessEnv, smokeRoot: string, cwd?: string): NodeJS.ProcessEnv;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** One attachment as the Hub stores it. `file_id` comes from commhub_upload_file. */
|
|
2
|
+
export interface OutboundAttachment {
|
|
3
|
+
type: "file";
|
|
4
|
+
file_id: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
mime?: string;
|
|
7
|
+
size?: number;
|
|
8
|
+
}
|
|
9
|
+
export type NormalizeResult = {
|
|
10
|
+
ok: true;
|
|
11
|
+
attachments: OutboundAttachment[];
|
|
12
|
+
} | {
|
|
13
|
+
ok: false;
|
|
14
|
+
error: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Normalize caller-supplied attachments into what the Hub expects.
|
|
18
|
+
*
|
|
19
|
+
* Absent input is not an error and yields no `attachments` key at all — a call
|
|
20
|
+
* without attachments must produce a byte-identical request to before this
|
|
21
|
+
* existed, or every existing reply changes behaviour the day this ships.
|
|
22
|
+
*/
|
|
23
|
+
/** 2026-09-15 —— LLM 常把数组参数当成 JSON 字符串传(TM汇报马 真机:attachments 是 "[{...}]" 字符串,回复 ok:true 但 hub 里没有附件)。
|
|
24
|
+
* 字符串先 parse;parse 不出来是错误,不是「没有附件」。 */
|
|
25
|
+
export declare function coerceAttachmentsArg(input: unknown): unknown;
|
|
26
|
+
export declare function normalizeOutboundAttachments(input: unknown): NormalizeResult;
|
|
27
|
+
/**
|
|
28
|
+
* Spread into a Hub request body. Empty → `{}`, so a call with no attachments
|
|
29
|
+
* is unchanged from before this module existed.
|
|
30
|
+
*/
|
|
31
|
+
export declare function attachmentsField(attachments: readonly OutboundAttachment[]): Record<string, unknown>;
|
|
32
|
+
/** `send_task` carries them under `meta`, not at the top level. */
|
|
33
|
+
export declare function attachmentsMeta(attachments: readonly OutboundAttachment[], existingMeta?: unknown): Record<string, unknown>;
|
|
34
|
+
/** Shared wording for the two tool schemas, so they cannot drift apart. */
|
|
35
|
+
export declare const ATTACHMENTS_SCHEMA: {
|
|
36
|
+
type: "array";
|
|
37
|
+
description: string;
|
|
38
|
+
items: {
|
|
39
|
+
type: "object";
|
|
40
|
+
properties: {
|
|
41
|
+
file_id: {
|
|
42
|
+
type: string;
|
|
43
|
+
description: string;
|
|
44
|
+
};
|
|
45
|
+
name: {
|
|
46
|
+
type: string;
|
|
47
|
+
description: string;
|
|
48
|
+
};
|
|
49
|
+
mime: {
|
|
50
|
+
type: string;
|
|
51
|
+
description: string;
|
|
52
|
+
};
|
|
53
|
+
size: {
|
|
54
|
+
type: string;
|
|
55
|
+
description: string;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
required: string[];
|
|
59
|
+
};
|
|
60
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const OUTBOUND_TOOL_NAMES: Set<string>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export type OwnedRootRole = "agent";
|
|
2
|
+
export interface OwnedRoot {
|
|
3
|
+
pid: number;
|
|
4
|
+
birth: string;
|
|
5
|
+
role: OwnedRootRole;
|
|
6
|
+
}
|
|
7
|
+
/** 🔴 #1438 — 发现阶段(`ps`)与后续 `/proc/<pid>/stat` 读之间,pid 可能被回收。
|
|
8
|
+
* 为让 resolveOwnedRoots 能识别「pid 相同、进程不同」,发现阶段必须在
|
|
9
|
+
* **同一次 `ps` 快照**里同时取 pid 与一个稳定的启动时刻签名(lstart),
|
|
10
|
+
* 并把这个签名一路带进来做比对。同一次 ps 内的 pid 与 lstart 无 TOCTOU。 */
|
|
11
|
+
export interface OwnedRootCandidate {
|
|
12
|
+
pid: number;
|
|
13
|
+
/** 发现时刻的 `ps -o lstart=` 字符串(24 字符定宽),用于识别 pid 回收。 */
|
|
14
|
+
discoveredBirth: string;
|
|
15
|
+
}
|
|
16
|
+
export interface OwnedRootProbes {
|
|
17
|
+
/** 进程这一代的出生时刻(以「存储格式」返回,通常是 /proc/stat starttime jiffies);
|
|
18
|
+
* 读不到返回 null(可能已退出,也可能无权限)。用于写进 lifecycle 记录。 */
|
|
19
|
+
birth(pid: number): string | null;
|
|
20
|
+
/** 🔴 只有**确证**进程不存在时返回 true。无权限等一律视为存在。 */
|
|
21
|
+
vanished(pid: number): boolean;
|
|
22
|
+
/** 🔴 #1438 — 返回**当前**pid 的 lstart 签名,和发现阶段同格式。
|
|
23
|
+
* 用来识别 pid 回收:发现时是 A、现在读回来是 B ⇒ pid 已被复用。
|
|
24
|
+
* 读不到返回 null(进程已退出,或读 ps 失败)。 */
|
|
25
|
+
currentBirthSignature(pid: number): string | null;
|
|
26
|
+
}
|
|
27
|
+
/** 把 `ps` 发现的 (pid, birth) 候选冻结成 owned roots。
|
|
28
|
+
*
|
|
29
|
+
* · currentBirthSignature 与 discoveredBirth **相等** ⇒ 同一代,收下
|
|
30
|
+
* · currentBirthSignature 与 discoveredBirth **不等** ⇒ 🔴 #1438 pid 已被复用,
|
|
31
|
+
* 现在这个 pid 属于另一个进程 B。**跳过**(而不是收下 B 当我们的节点):
|
|
32
|
+
* stop 的目的是让 A 没了;B 是无关进程,不能因为它恰好占了 A 的 pid 就被杀。
|
|
33
|
+
* · currentBirthSignature 为 null、**确证已消失** ⇒ 跳过(stop 想要的结果)
|
|
34
|
+
* · currentBirthSignature 为 null、进程仍在 ⇒ throw(权限等真问题)
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveOwnedRoots(candidates: OwnedRootCandidate[], probes: OwnedRootProbes): OwnedRoot[];
|
|
37
|
+
/** 🔴 正向判定「进程确实没了」,而不是「读失败就假设没了」。
|
|
38
|
+
*
|
|
39
|
+
* `kill(pid, 0)` 不送信号,只做存在性与权限探测:
|
|
40
|
+
* · ESRCH ⇒ 确证不存在
|
|
41
|
+
* · EPERM ⇒ 存在,只是不属于本用户
|
|
42
|
+
* · 其他 ⇒ 保守当作存在(判据只在**确证**时放行)
|
|
43
|
+
*/
|
|
44
|
+
export declare function processVanished(pid: number, kill?: (p: number, s: number) => void): boolean;
|
|
45
|
+
/** 🔴 #1458 — kill 前的 pid 回收保护:发现阶段捕获的 discoveredBirth 与
|
|
46
|
+
* **当前**probeCurrentSignature(pid) 相等 ⇒ 同一代,可以信号。
|
|
47
|
+
*
|
|
48
|
+
* · currentSig === discoveredBirth ⇒ true(同代,可 kill)
|
|
49
|
+
* · currentSig !== discoveredBirth ⇒ false(pid 被回收,现在这个 pid 是另一
|
|
50
|
+
* 个进程 B。**不要 kill** —— B 与我们要 stop 的 agent 无关)
|
|
51
|
+
* · currentSig === null ⇒ false(pid 已消失或读不到;caller 判
|
|
52
|
+
* 是消失就该 skip,权限问题应额外处理但不该 kill 未知对象)
|
|
53
|
+
*
|
|
54
|
+
* 与 resolveOwnedRoots 内嵌的同款比较**在语义上一致**,但在**时间点上不同**:
|
|
55
|
+
* resolveOwnedRoots 用于「冻结」时刻(装进 lifecycle owner)
|
|
56
|
+
* isSameIncarnation 用于「发信号」前那一瞬(rename 的 kill 循环)
|
|
57
|
+
* 两个时刻中间可能又有窗口,所以这个检查要**离 process.kill 越近越好**。 */
|
|
58
|
+
export declare function isSameIncarnation(pid: number, discoveredBirth: string, probeCurrentSignature: (pid: number) => string | null): boolean;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface UmaskVerdict {
|
|
2
|
+
/** Will a freshly npm-extracted payload fail the (mode & 0o022) === 0 check? */
|
|
3
|
+
willProduceUnsafeModes: boolean;
|
|
4
|
+
/** Octal umask string as an operator would type it. */
|
|
5
|
+
umaskOctal: string;
|
|
6
|
+
/** Which write bits this umask fails to mask off. */
|
|
7
|
+
leaks: Array<"group" | "other">;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Read a umask value the way the package check will experience it.
|
|
11
|
+
*
|
|
12
|
+
* A umask bit SET means "withhold this permission". So group-write is withheld
|
|
13
|
+
* only when 0o020 is set in the umask; umask 0002 withholds other-write and
|
|
14
|
+
* nothing else, which is exactly the failing case.
|
|
15
|
+
*/
|
|
16
|
+
export declare function judgeUmask(umask: number): UmaskVerdict;
|
|
17
|
+
/**
|
|
18
|
+
* One line for `anet doctor`, or null when there is nothing to say.
|
|
19
|
+
*
|
|
20
|
+
* 🔴 Windows gets a different sentence, not the same one. There, umask is always
|
|
21
|
+
* 0000 and this fires on every machine, while both remedies it names —
|
|
22
|
+
* `umask 0022` and `chmod -R` — do not exist. The conclusion is still true
|
|
23
|
+
* (opencode-cli will refuse), but for another reason entirely: its check is
|
|
24
|
+
* `if (runtimeUid === undefined) return false`, and Windows has no getuid.
|
|
25
|
+
* An always-on warning whose fix cannot be typed teaches people to ignore
|
|
26
|
+
* the warnings that can be.
|
|
27
|
+
*/
|
|
28
|
+
export declare function describeUmaskRisk(verdict: UmaskVerdict, platform?: NodeJS.Platform): string | null;
|
|
29
|
+
export interface ExtractedPayload {
|
|
30
|
+
path: string;
|
|
31
|
+
uid: number;
|
|
32
|
+
mode: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Which already-extracted payloads would be rejected right now.
|
|
36
|
+
*
|
|
37
|
+
* Reports facts about copies that exist on disk; it never fetches. An empty
|
|
38
|
+
* result means "nothing extracted yet", which is not the same as "safe" — the
|
|
39
|
+
* umask verdict is what speaks to the next fetch.
|
|
40
|
+
*/
|
|
41
|
+
export declare function rejectedPayloads(payloads: ExtractedPayload[], processUid: number): ExtractedPayload[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type ProcRow = {
|
|
2
|
+
pid: number;
|
|
3
|
+
ppid: number;
|
|
4
|
+
start: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function ownedConnectionFromSnapshot(rootPid: number, beforeStart: string | null, afterStart: string | null, rows: ProcRow[], socketOwners: ReadonlyMap<number, ReadonlySet<string>>, establishedInodes: ReadonlySet<string>, unread?: boolean): boolean;
|
|
7
|
+
/** Fail-closed attribution of an exact loopback connection to a managed POSIX TUI tree. */
|
|
8
|
+
export declare function probePosixOwnedLoopbackConnection(rootPid: number, port: number, platform?: NodeJS.Platform): boolean;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare function posixFileModes(platform?: NodeJS.Platform): boolean;
|
|
2
|
+
/** chmod where the platform has modes; a no-op where it does not. */
|
|
3
|
+
export declare function chmodIfPosix(path: string, mode: number): void;
|
|
4
|
+
/** fchmod where the platform has modes; a no-op where it does not. */
|
|
5
|
+
export declare function fchmodIfPosix(fd: number, mode: number): void;
|
|
6
|
+
/**
|
|
7
|
+
* Whether a stat's mode may be judged at all.
|
|
8
|
+
*
|
|
9
|
+
* Windows synthesises mode bits, so `(mode & 0o022) !== 0` is true for ordinary
|
|
10
|
+
* files there and every POSIX-shaped safety check reads as "unsafe". A check
|
|
11
|
+
* that can only ever return one answer is not a check.
|
|
12
|
+
*/
|
|
13
|
+
export declare function modeIsJudgeable(platform?: NodeJS.Platform): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* fsync a DIRECTORY handle, where the platform supports it.
|
|
16
|
+
*
|
|
17
|
+
* The durability barrier after an atomic rename: on POSIX, fsyncing the parent
|
|
18
|
+
* makes the rename itself survive a crash, not just the file's bytes. Windows
|
|
19
|
+
* has no equivalent — FlushFileBuffers works on files, and on a directory
|
|
20
|
+
* handle it fails:
|
|
21
|
+
*
|
|
22
|
+
* [anet] FATAL: Error: EPERM: operation not permitted, fsync
|
|
23
|
+
* at fsyncSync (node:fs:1285:11)
|
|
24
|
+
*
|
|
25
|
+
* which is `anet start <node>` dying on its first private-state write. Reported
|
|
26
|
+
* from the Windows box while it was running the previous fix, i.e. this is the
|
|
27
|
+
* next call in the same family, not a regression of that one.
|
|
28
|
+
*
|
|
29
|
+
* 🔴 Note what is NOT skipped: the fsync of the temp FILE before the rename.
|
|
30
|
+
* That one works on Windows and carries the bytes. What is skipped is only
|
|
31
|
+
* the parent-directory barrier, which the platform does not offer at all —
|
|
32
|
+
* NTFS journals the rename's metadata itself. Skipping an operation the OS
|
|
33
|
+
* cannot perform is not a weakened guarantee; crashing instead of writing
|
|
34
|
+
* the file is a much larger one.
|
|
35
|
+
*/
|
|
36
|
+
export declare function fsyncDirectoryIfSupported(fd: number): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface PrimaryNetworkResponse {
|
|
2
|
+
ok?: boolean;
|
|
3
|
+
current_network?: unknown;
|
|
4
|
+
networks?: unknown;
|
|
5
|
+
}
|
|
6
|
+
export type PrimaryNetworkFetch = (input: string, init: {
|
|
7
|
+
headers: Record<string, string>;
|
|
8
|
+
}) => Promise<{
|
|
9
|
+
ok: boolean;
|
|
10
|
+
status: number;
|
|
11
|
+
json: () => Promise<PrimaryNetworkResponse>;
|
|
12
|
+
}>;
|
|
13
|
+
export declare class PrimaryNetworkResolutionError extends Error {
|
|
14
|
+
constructor(message: string, options?: ErrorOptions);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the authenticated user's active network from the server's explicit
|
|
18
|
+
* `/api/auth/me.current_network` field.
|
|
19
|
+
*
|
|
20
|
+
* Do not fall back to a network name or list position: both are presentation
|
|
21
|
+
* details, and guessing either can silently run a command in the wrong network.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolvePrimaryNetwork(hub: string, headers: Record<string, string>, fetchImpl?: PrimaryNetworkFetch): Promise<string>;
|