@socketsecurity/lib 6.0.7 → 6.0.8
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/CHANGELOG.md +20 -0
- package/README.md +1 -1
- package/dist/ai/agent-context.d.mts +103 -0
- package/dist/ai/agent-context.js +157 -0
- package/dist/ai/backends.d.mts +83 -0
- package/dist/ai/backends.js +173 -0
- package/dist/ai/credentials.d.mts +49 -0
- package/dist/ai/credentials.js +82 -0
- package/dist/ai/discover.d.mts +4 -0
- package/dist/ai/discover.js +1 -1
- package/dist/ai/exec.d.mts +52 -0
- package/dist/ai/exec.js +92 -0
- package/dist/ai/http.d.mts +132 -0
- package/dist/ai/http.js +130 -0
- package/dist/ai/profiles.d.mts +41 -6
- package/dist/ai/profiles.js +52 -10
- package/dist/ai/route.d.mts +69 -0
- package/dist/ai/route.js +156 -0
- package/dist/ai/spawn.d.mts +10 -2
- package/dist/ai/spawn.js +55 -31
- package/dist/ai/subagent-status.d.mts +48 -0
- package/dist/ai/subagent-status.js +57 -0
- package/dist/ai/tier.d.mts +60 -0
- package/dist/ai/tier.js +53 -0
- package/dist/ai/types.d.mts +15 -2
- package/dist/ai/worktree.js +4 -0
- package/dist/archives/tar.js +1 -1
- package/dist/archives/zip.js +2 -2
- package/dist/argv/parse.d.ts +19 -2
- package/dist/argv/parse.js +1 -1
- package/dist/arrays/join.js +4 -0
- package/dist/bin/find.js +4 -4
- package/dist/bin/prim.cjs +3915 -3781
- package/dist/bin/resolve.js +1 -1
- package/dist/cache/ttl/store.js +1 -1
- package/dist/cli/check-primordials.d.ts +8 -3
- package/dist/cli/check-primordials.js +4 -4
- package/dist/compression/_internal.js +1 -1
- package/dist/compression/brotli.d.ts +1 -2
- package/dist/compression/brotli.js +6 -2
- package/dist/compression/gzip.js +6 -2
- package/dist/constants/packages.d.ts +3 -0
- package/dist/constants/packages.js +2 -1
- package/dist/constants/socket.d.ts +2 -6
- package/dist/constants/socket.js +12 -14
- package/dist/cover/code.js +2 -2
- package/dist/crypto/hash.d.ts +4 -1
- package/dist/crypto/hash.js +4 -1
- package/dist/debug/caller-info.js +1 -1
- package/dist/dlx/arborist.js +13 -3
- package/dist/dlx/binary-cache.js +1 -1
- package/dist/dlx/binary-resolution.js +1 -1
- package/dist/dlx/detect.d.ts +8 -0
- package/dist/dlx/firewall.d.ts +8 -0
- package/dist/dlx/firewall.js +1 -1
- package/dist/dlx/lockfile.js +4 -1
- package/dist/dlx/manifest.js +1 -1
- package/dist/dlx/package.js +4 -0
- package/dist/eco/cargo/parse-lockfile.d.ts +1 -2
- package/dist/eco/cargo/parse-lockfile.js +3 -3
- package/dist/eco/manifest/detect-format.js +1 -1
- package/dist/eco/npm/npm/parse-lockfile.d.ts +3 -4
- package/dist/eco/npm/npm/parse-lockfile.js +2 -2
- package/dist/eco/npm/parse-package-json.d.ts +11 -0
- package/dist/eco/npm/parse-package-json.js +1 -1
- package/dist/eco/npm/pnpm/parse-lockfile.d.ts +5 -3
- package/dist/eco/npm/pnpm/parse-lockfile.js +3 -3
- package/dist/eco/npm/yarnpkg/yarn/exec.js +1 -1
- package/dist/eco/npm/yarnpkg/yarn/parse-lockfile.d.ts +1 -2
- package/dist/eco/npm/yarnpkg/yarn/parse-lockfile.js +1 -1
- package/dist/env/proxy.js +1 -1
- package/dist/env/rewire.d.ts +1 -0
- package/dist/env/rewire.js +1 -1
- package/dist/env/socket.d.ts +7 -0
- package/dist/env/socket.js +10 -0
- package/dist/errors/predicates.js +1 -1
- package/dist/external/@npmcli/promise-spawn.js +3 -1
- package/dist/external/pico-pack.js +4 -2
- package/dist/external/which.js +3 -1
- package/dist/external-tools/bazel/asset-names.d.ts +1 -1
- package/dist/external-tools/bazel/asset-names.js +5 -2
- package/dist/external-tools/bazel/from-download.d.ts +1 -1
- package/dist/external-tools/bazel/from-download.js +5 -2
- package/dist/external-tools/bazel/resolve-bazel-version.js +4 -0
- package/dist/external-tools/bazel/resolve.d.ts +3 -3
- package/dist/external-tools/bazel/resolve.js +16 -8
- package/dist/external-tools/cdxgen/asset-names.d.ts +1 -1
- package/dist/external-tools/cdxgen/asset-names.js +5 -2
- package/dist/external-tools/cdxgen/from-download.d.ts +1 -1
- package/dist/external-tools/cdxgen/from-download.js +7 -4
- package/dist/external-tools/cdxgen/resolve.d.ts +3 -3
- package/dist/external-tools/cdxgen/resolve.js +16 -8
- package/dist/external-tools/from-download.d.ts +2 -2
- package/dist/external-tools/from-download.js +11 -5
- package/dist/external-tools/from-pip-venv.d.ts +1 -1
- package/dist/external-tools/from-pip-venv.js +12 -5
- package/dist/external-tools/janus/asset-names.d.ts +1 -1
- package/dist/external-tools/janus/asset-names.js +5 -2
- package/dist/external-tools/janus/from-download.d.ts +1 -1
- package/dist/external-tools/janus/from-download.js +5 -2
- package/dist/external-tools/janus/resolve.d.ts +3 -3
- package/dist/external-tools/janus/resolve.js +16 -8
- package/dist/external-tools/jre/asset-names.d.ts +1 -1
- package/dist/external-tools/jre/asset-names.js +5 -2
- package/dist/external-tools/jre/from-download.d.ts +1 -1
- package/dist/external-tools/jre/from-download.js +7 -4
- package/dist/external-tools/jre/from-java-home.js +2 -2
- package/dist/external-tools/jre/from-vfs.js +2 -2
- package/dist/external-tools/jre/resolve.d.ts +3 -3
- package/dist/external-tools/jre/resolve.js +16 -8
- package/dist/external-tools/manifest.d.ts +18 -0
- package/dist/external-tools/manifest.js +1 -1
- package/dist/external-tools/opengrep/asset-names.d.ts +1 -1
- package/dist/external-tools/opengrep/asset-names.js +5 -2
- package/dist/external-tools/opengrep/from-download.d.ts +1 -1
- package/dist/external-tools/opengrep/from-download.js +5 -2
- package/dist/external-tools/opengrep/resolve.d.ts +3 -3
- package/dist/external-tools/opengrep/resolve.js +16 -8
- package/dist/external-tools/python/asset-names.d.ts +1 -1
- package/dist/external-tools/python/asset-names.js +10 -3
- package/dist/external-tools/python/dlx.d.ts +3 -3
- package/dist/external-tools/python/dlx.js +20 -9
- package/dist/external-tools/python/from-download.d.ts +1 -1
- package/dist/external-tools/python/from-download.js +12 -5
- package/dist/external-tools/python/pin.js +6 -3
- package/dist/external-tools/python/pip-install.js +6 -3
- package/dist/external-tools/python/resolve.d.ts +3 -3
- package/dist/external-tools/python/resolve.js +19 -11
- package/dist/external-tools/sbt/asset-names.d.ts +1 -1
- package/dist/external-tools/sbt/asset-names.js +5 -2
- package/dist/external-tools/sbt/from-download.d.ts +1 -1
- package/dist/external-tools/sbt/from-download.js +5 -2
- package/dist/external-tools/sbt/resolve.d.ts +3 -3
- package/dist/external-tools/sbt/resolve.js +16 -8
- package/dist/external-tools/skillspector/from-dlx.d.ts +1 -1
- package/dist/external-tools/skillspector/from-dlx.js +10 -3
- package/dist/external-tools/skillspector/resolve.d.ts +2 -2
- package/dist/external-tools/skillspector/resolve.js +14 -6
- package/dist/external-tools/synp/asset-names.d.ts +1 -1
- package/dist/external-tools/synp/asset-names.js +6 -2
- package/dist/external-tools/synp/from-download.d.ts +1 -1
- package/dist/external-tools/synp/from-download.js +5 -2
- package/dist/external-tools/synp/resolve.d.ts +3 -3
- package/dist/external-tools/synp/resolve.js +16 -8
- package/dist/external-tools/trivy/asset-names.d.ts +1 -1
- package/dist/external-tools/trivy/asset-names.js +5 -2
- package/dist/external-tools/trivy/from-download.d.ts +1 -1
- package/dist/external-tools/trivy/from-download.js +7 -4
- package/dist/external-tools/trivy/resolve.d.ts +3 -3
- package/dist/external-tools/trivy/resolve.js +16 -8
- package/dist/external-tools/trufflehog/asset-names.d.ts +1 -1
- package/dist/external-tools/trufflehog/asset-names.js +5 -2
- package/dist/external-tools/trufflehog/from-download.d.ts +1 -1
- package/dist/external-tools/trufflehog/from-download.js +7 -4
- package/dist/external-tools/trufflehog/resolve.d.ts +3 -3
- package/dist/external-tools/trufflehog/resolve.js +16 -8
- package/dist/fs/allowed-dirs-cache.d.ts +27 -1
- package/dist/fs/allowed-dirs-cache.js +38 -3
- package/dist/fs/find.js +1 -1
- package/dist/fs/read-json-cache.d.ts +7 -0
- package/dist/fs/resolve-module.js +6 -2
- package/dist/fs/safe.js +1 -1
- package/dist/git/_internal.js +2 -2
- package/dist/git/repo.js +2 -4
- package/dist/git/staged.js +8 -0
- package/dist/git/tracked.d.ts +84 -0
- package/dist/git/tracked.js +163 -0
- package/dist/git/unstaged.js +8 -0
- package/dist/github/refs-graphql.js +4 -0
- package/dist/github/refs-rest.js +4 -0
- package/dist/github/refs.js +15 -10
- package/dist/globs/_internal.js +1 -1
- package/dist/globs/match.js +9 -1
- package/dist/globs/matcher.js +5 -1
- package/dist/http-request/browser.js +6 -2
- package/dist/http-request/{browser-fetch.d.ts → fetch/browser.d.ts} +2 -2
- package/dist/http-request/{browser-fetch.js → fetch/browser.js} +4 -4
- package/dist/http-request/headers.js +1 -1
- package/dist/http-request/request-attempt.js +2 -2
- package/dist/http-request/user-agent.js +1 -1
- package/dist/integrity.d.ts +10 -4
- package/dist/integrity.js +10 -4
- package/dist/json/edit.js +38 -30
- package/dist/json/format.js +1 -1
- package/dist/native-messaging/install.d.ts +1 -1
- package/dist/native-messaging/install.js +7 -4
- package/dist/native-messaging/rate-limit.d.ts +7 -0
- package/dist/native-messaging/rate-limit.js +4 -0
- package/dist/node/async-hooks.js +1 -1
- package/dist/node/child-process.js +1 -1
- package/dist/node/crypto.js +1 -1
- package/dist/node/events.js +1 -1
- package/dist/node/fs-promises.js +1 -1
- package/dist/node/fs.d.ts +22 -6
- package/dist/node/fs.js +16 -3
- package/dist/node/http.js +1 -1
- package/dist/node/https.js +1 -1
- package/dist/node/module.js +1 -1
- package/dist/node/os.d.ts +10 -2
- package/dist/node/os.js +11 -4
- package/dist/node/path.d.ts +11 -2
- package/dist/node/path.js +17 -4
- package/dist/node/timers-promises.js +1 -1
- package/dist/node/url.js +1 -1
- package/dist/node/util.js +1 -1
- package/dist/objects/getters.js +1 -1
- package/dist/objects/mutate.js +2 -2
- package/dist/objects/predicates.js +1 -1
- package/dist/packages/edit-class.d.ts +2 -3
- package/dist/packages/edit-class.js +41 -35
- package/dist/packages/exports.js +4 -4
- package/dist/packages/fetch.js +1 -1
- package/dist/packages/isolation.js +1 -1
- package/dist/packages/licenses.js +2 -2
- package/dist/packages/manifest.js +4 -4
- package/dist/packages/normalize.js +1 -1
- package/dist/packages/provenance.js +2 -2
- package/dist/packages/specs.js +1 -1
- package/dist/packages/tarball.js +4 -2
- package/dist/packages/types.d.ts +1 -2
- package/dist/paths/dirnames.d.ts +1 -0
- package/dist/paths/dirnames.js +2 -0
- package/dist/paths/resolve.js +14 -19
- package/dist/paths/rewire.d.ts +5 -0
- package/dist/paths/socket.d.ts +74 -111
- package/dist/paths/socket.js +99 -132
- package/dist/primordials/process.d.ts +88 -0
- package/dist/primordials/process.js +132 -0
- package/dist/primordials/uncurry.d.ts +1 -2
- package/dist/process/spawn/child.js +8 -2
- package/dist/process/spawn/errors.js +1 -1
- package/dist/regexps/spec.js +1 -1
- package/dist/releases/github-archives.js +1 -1
- package/dist/releases/github-listing.d.ts +1 -2
- package/dist/schema/types.d.ts +3 -4
- package/dist/schema/validate.js +1 -1
- package/dist/secrets/find.d.ts +2 -2
- package/dist/secrets/find.js +10 -4
- package/dist/secrets/keychain.d.ts +1 -1
- package/dist/secrets/linux.js +32 -44
- package/dist/secrets/macos.d.ts +1 -2
- package/dist/secrets/macos.js +20 -29
- package/dist/secrets/rc.d.ts +2 -2
- package/dist/secrets/rc.js +21 -13
- package/dist/secrets/socket-api-token.js +8 -0
- package/dist/secrets/windows.js +27 -33
- package/dist/shell/parse.d.ts +32 -0
- package/dist/shell/parse.js +60 -0
- package/dist/spinner/create-spinner-class.js +2 -2
- package/dist/spinner/spinner-internals.d.ts +1 -1
- package/dist/spinner/spinner-internals.js +9 -5
- package/dist/spinner/spinner.d.ts +4 -0
- package/dist/spinner/spinner.js +1 -1
- package/dist/stdio/progress.js +5 -1
- package/dist/stdio/prompts.d.ts +2 -2
- package/dist/stdio/prompts.js +1 -1
- package/dist/temporal/instant.js +2 -2
- package/dist/url/assert-safe.d.ts +29 -0
- package/dist/url/assert-safe.js +54 -0
- package/dist/url/predicates.d.ts +31 -1
- package/dist/url/predicates.js +42 -1
- package/dist/url/types.d.ts +4 -0
- package/package.json +177 -115
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Socket Lib - Built with rolldown */
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
const require_secrets_find = require('../secrets/find.js');
|
|
5
|
+
|
|
6
|
+
//#region src/ai/credentials.mts
|
|
7
|
+
/**
|
|
8
|
+
* @file Layered provider-credential resolver for AI backends. One call site,
|
|
9
|
+
* dev and CI: a provider token resolves from an explicit override, then the
|
|
10
|
+
* provider's env var, then the OS keychain — mirroring the
|
|
11
|
+
* `readSocketApiToken` env → keychain precedence
|
|
12
|
+
* (`secrets/socket-api-token.ts`). Why a single resolver: `ai/http.mts` read
|
|
13
|
+
* `process.env[tokenEnv]` inline, so every consumer hard-coded the env-only
|
|
14
|
+
* path and none could reach the keychain. Routing skills also need a uniform
|
|
15
|
+
* way to ask "do I have a credential for provider X?" without knowing its
|
|
16
|
+
* env-var name. This centralizes the provider → { tokenEnv, keychainService }
|
|
17
|
+
* map (the HTTP providers reuse `AI_HTTP_PROVIDERS` so the env var isn't
|
|
18
|
+
* duplicated) and the precedence. CI vs dev: pass `allowEnvOnly: true` (the
|
|
19
|
+
* resolver's existing escape) in headless contexts so a missing token returns
|
|
20
|
+
* `undefined` immediately instead of triggering a keychain auth prompt. CI
|
|
21
|
+
* sets the token as a GH-secret env var (e.g. `ANTHROPIC_API_KEY`); the same
|
|
22
|
+
* `resolveProviderCredential` call reads it there with no keychain. proteus
|
|
23
|
+
* hook-point: the forthcoming biometric credential daemon
|
|
24
|
+
* (`.claude/plans/proteus-credential-broker.md`) slots in as a layer between
|
|
25
|
+
* the env check and the keychain read inside `resolve()`'s implementation —
|
|
26
|
+
* call sites here do not change when it lands (resolver decision #4 in that
|
|
27
|
+
* plan). This module is the stable seam.
|
|
28
|
+
*/
|
|
29
|
+
const PROVIDER_CREDENTIALS = {
|
|
30
|
+
__proto__: null,
|
|
31
|
+
anthropic: {
|
|
32
|
+
keychainService: "socketsecurity",
|
|
33
|
+
tokenEnv: "ANTHROPIC_API_KEY"
|
|
34
|
+
},
|
|
35
|
+
fireworks: {
|
|
36
|
+
keychainService: "socketsecurity",
|
|
37
|
+
tokenEnv: "FIREWORKS_API_KEY"
|
|
38
|
+
},
|
|
39
|
+
openai: {
|
|
40
|
+
keychainService: "socketsecurity",
|
|
41
|
+
tokenEnv: "OPENAI_API_KEY"
|
|
42
|
+
},
|
|
43
|
+
synthetic: {
|
|
44
|
+
keychainService: "socketsecurity",
|
|
45
|
+
tokenEnv: "SYNTHETIC_API_KEY"
|
|
46
|
+
},
|
|
47
|
+
xai: {
|
|
48
|
+
keychainService: "socketsecurity",
|
|
49
|
+
tokenEnv: "XAI_API_KEY"
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* True when `value` names a provider with a resolvable credential.
|
|
54
|
+
*/
|
|
55
|
+
function isCredentialProvider(value) {
|
|
56
|
+
return value in PROVIDER_CREDENTIALS;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolve a provider's bearer token: explicit override → env var → keychain →
|
|
60
|
+
* undefined. The token never appears inline or in logs — callers pass the
|
|
61
|
+
* result straight to an `Authorization` header. Returns `undefined` when no
|
|
62
|
+
* source has it (the caller decides whether that's fatal).
|
|
63
|
+
*/
|
|
64
|
+
async function resolveProviderCredential(options) {
|
|
65
|
+
const opts = {
|
|
66
|
+
__proto__: null,
|
|
67
|
+
...options
|
|
68
|
+
};
|
|
69
|
+
if (opts.explicit) return opts.explicit;
|
|
70
|
+
const spec = PROVIDER_CREDENTIALS[opts.provider];
|
|
71
|
+
if (!spec) return;
|
|
72
|
+
return (await require_secrets_find.resolve({
|
|
73
|
+
accounts: [spec.tokenEnv],
|
|
74
|
+
allowEnvOnly: opts.allowEnvOnly,
|
|
75
|
+
service: spec.keychainService
|
|
76
|
+
}))?.value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
//#endregion
|
|
80
|
+
exports.PROVIDER_CREDENTIALS = PROVIDER_CREDENTIALS;
|
|
81
|
+
exports.isCredentialProvider = isCredentialProvider;
|
|
82
|
+
exports.resolveProviderCredential = resolveProviderCredential;
|
package/dist/ai/discover.d.mts
CHANGED
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
* cold-start cost.
|
|
15
15
|
*/
|
|
16
16
|
import type { DiscoveredAgents } from './types.mts';
|
|
17
|
+
export interface OnDiskCache {
|
|
18
|
+
readonly agents: DiscoveredAgents;
|
|
19
|
+
readonly writtenAt: number;
|
|
20
|
+
}
|
|
17
21
|
export declare function cachePathFor(repoRoot: string): string;
|
|
18
22
|
/**
|
|
19
23
|
* Discover which AI agent CLIs are installed.
|
package/dist/ai/discover.js
CHANGED
|
@@ -8,9 +8,9 @@ const require_bin_which = require('../bin/which.js');
|
|
|
8
8
|
const require_errors_message = require('../errors/message.js');
|
|
9
9
|
const require_logger_default = require('../logger/default.js');
|
|
10
10
|
let node_fs = require("node:fs");
|
|
11
|
-
let node_fs_promises = require("node:fs/promises");
|
|
12
11
|
let node_path = require("node:path");
|
|
13
12
|
node_path = require_runtime.__toESM(node_path, 1);
|
|
13
|
+
let node_fs_promises = require("node:fs/promises");
|
|
14
14
|
|
|
15
15
|
//#region src/ai/discover.mts
|
|
16
16
|
/**
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Exec-backend seam: WHERE a shell command runs, a separate axis from
|
|
3
|
+
* WHICH model produced it (`ai/backends`). The lib owns the INTERFACE plus
|
|
4
|
+
* the cheap built-in `real` runner (the host shell via lib `spawn`); a
|
|
5
|
+
* SANDBOXED runner is INJECTED by the caller, never imported here. That keeps
|
|
6
|
+
* the small-dist lib free of a heavy sandbox dependency — the fleet's sandbox
|
|
7
|
+
* of choice (`just-bash`, ~40MB incl. WASM) is owned by the wheelhouse hook /
|
|
8
|
+
* CI tooling and passed in, so a lib consumer that never sandboxes pays
|
|
9
|
+
* nothing. Layering: ExecRunner.run() — the injectable primitive (real |
|
|
10
|
+
* sandboxed) composed into ExecContext — { runners: { real, sandboxed? },
|
|
11
|
+
* resolve(trust) } used by runShell(script, { context, trust }) — the
|
|
12
|
+
* ergonomic entry point Pick a runner by TRUST LEVEL, never by model.
|
|
13
|
+
* `untrusted` resolves to the sandboxed runner — which a caller that hasn't
|
|
14
|
+
* injected one cannot run, so `resolve` throws a clear "provide a sandboxed
|
|
15
|
+
* runner" error rather than silently falling back to the host shell. Both
|
|
16
|
+
* runners normalize to one `ExecResult` so callers swap trust levels without
|
|
17
|
+
* reshaping result handling.
|
|
18
|
+
*/
|
|
19
|
+
export type ExecBackend = 'real' | 'sandboxed';
|
|
20
|
+
export type ExecTrust = 'trusted' | 'untrusted';
|
|
21
|
+
export interface ExecResult {
|
|
22
|
+
readonly stdout: string;
|
|
23
|
+
readonly stderr: string;
|
|
24
|
+
readonly exitCode: number;
|
|
25
|
+
}
|
|
26
|
+
export interface ExecRunOptions {
|
|
27
|
+
readonly cwd?: string | undefined;
|
|
28
|
+
readonly env?: Record<string, string> | undefined;
|
|
29
|
+
readonly files?: Record<string, string> | undefined;
|
|
30
|
+
readonly signal?: AbortSignal | undefined;
|
|
31
|
+
readonly stdin?: string | undefined;
|
|
32
|
+
}
|
|
33
|
+
export interface ExecRunner {
|
|
34
|
+
run(script: string, options?: ExecRunOptions | undefined): Promise<ExecResult>;
|
|
35
|
+
}
|
|
36
|
+
export interface ExecContext {
|
|
37
|
+
readonly runners: {
|
|
38
|
+
readonly real: ExecRunner;
|
|
39
|
+
readonly sandboxed?: ExecRunner | undefined;
|
|
40
|
+
};
|
|
41
|
+
resolve(trust: ExecTrust): ExecRunner;
|
|
42
|
+
}
|
|
43
|
+
export declare const realRunner: ExecRunner;
|
|
44
|
+
export declare function backendForTrust(trust: ExecTrust): ExecBackend;
|
|
45
|
+
export declare function createExecContext(options?: {
|
|
46
|
+
real?: ExecRunner | undefined;
|
|
47
|
+
sandboxed?: ExecRunner | undefined;
|
|
48
|
+
} | undefined): ExecContext;
|
|
49
|
+
export declare function runShell(script: string, options?: (ExecRunOptions & {
|
|
50
|
+
context?: ExecContext | undefined;
|
|
51
|
+
trust?: ExecTrust | undefined;
|
|
52
|
+
}) | undefined): Promise<ExecResult>;
|
package/dist/ai/exec.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Socket Lib - Built with rolldown */
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
const require_process_spawn_errors = require('../process/spawn/errors.js');
|
|
5
|
+
const require_process_spawn_child = require('../process/spawn/child.js');
|
|
6
|
+
|
|
7
|
+
//#region src/ai/exec.mts
|
|
8
|
+
/**
|
|
9
|
+
* @file Exec-backend seam: WHERE a shell command runs, a separate axis from
|
|
10
|
+
* WHICH model produced it (`ai/backends`). The lib owns the INTERFACE plus
|
|
11
|
+
* the cheap built-in `real` runner (the host shell via lib `spawn`); a
|
|
12
|
+
* SANDBOXED runner is INJECTED by the caller, never imported here. That keeps
|
|
13
|
+
* the small-dist lib free of a heavy sandbox dependency — the fleet's sandbox
|
|
14
|
+
* of choice (`just-bash`, ~40MB incl. WASM) is owned by the wheelhouse hook /
|
|
15
|
+
* CI tooling and passed in, so a lib consumer that never sandboxes pays
|
|
16
|
+
* nothing. Layering: ExecRunner.run() — the injectable primitive (real |
|
|
17
|
+
* sandboxed) composed into ExecContext — { runners: { real, sandboxed? },
|
|
18
|
+
* resolve(trust) } used by runShell(script, { context, trust }) — the
|
|
19
|
+
* ergonomic entry point Pick a runner by TRUST LEVEL, never by model.
|
|
20
|
+
* `untrusted` resolves to the sandboxed runner — which a caller that hasn't
|
|
21
|
+
* injected one cannot run, so `resolve` throws a clear "provide a sandboxed
|
|
22
|
+
* runner" error rather than silently falling back to the host shell. Both
|
|
23
|
+
* runners normalize to one `ExecResult` so callers swap trust levels without
|
|
24
|
+
* reshaping result handling.
|
|
25
|
+
*/
|
|
26
|
+
const realRunner = { async run(script, options) {
|
|
27
|
+
const { cwd, env, signal } = {
|
|
28
|
+
__proto__: null,
|
|
29
|
+
...options
|
|
30
|
+
};
|
|
31
|
+
const spawnOptions = {
|
|
32
|
+
...cwd ? { cwd } : {},
|
|
33
|
+
...env ? { env } : {},
|
|
34
|
+
...signal ? { signal } : {},
|
|
35
|
+
stdioString: true
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
const result = await require_process_spawn_child.spawn("bash", ["-c", script], spawnOptions);
|
|
39
|
+
return {
|
|
40
|
+
stdout: String(result.stdout ?? ""),
|
|
41
|
+
stderr: String(result.stderr ?? ""),
|
|
42
|
+
exitCode: typeof result.code === "number" ? result.code : 0
|
|
43
|
+
};
|
|
44
|
+
} catch (e) {
|
|
45
|
+
if (!require_process_spawn_errors.isSpawnError(e)) throw e;
|
|
46
|
+
return {
|
|
47
|
+
stdout: String(e.stdout ?? ""),
|
|
48
|
+
stderr: String(e.stderr ?? ""),
|
|
49
|
+
exitCode: typeof e.code === "number" ? e.code : 1
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
} };
|
|
53
|
+
function backendForTrust(trust) {
|
|
54
|
+
return trust === "trusted" ? "real" : "sandboxed";
|
|
55
|
+
}
|
|
56
|
+
function createExecContext(options) {
|
|
57
|
+
const { real = realRunner, sandboxed } = {
|
|
58
|
+
__proto__: null,
|
|
59
|
+
...options
|
|
60
|
+
};
|
|
61
|
+
const runners = {
|
|
62
|
+
real,
|
|
63
|
+
sandboxed
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
runners,
|
|
67
|
+
resolve(trust) {
|
|
68
|
+
if (backendForTrust(trust) === "real") return runners.real;
|
|
69
|
+
if (!runners.sandboxed) throw new Error("No sandboxed exec runner provided.\n→ An `untrusted` script must run in a sandbox, not the host shell.\n→ Fix: pass a `sandboxed` runner to createExecContext() (e.g. the wheelhouse just-bash runner), or mark the script `trusted` if it is.");
|
|
70
|
+
return runners.sandboxed;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
async function runShell(script, options) {
|
|
75
|
+
const { context, cwd, env, files, signal, stdin, trust = "untrusted" } = {
|
|
76
|
+
__proto__: null,
|
|
77
|
+
...options
|
|
78
|
+
};
|
|
79
|
+
return await (context ?? createExecContext()).resolve(trust).run(script, {
|
|
80
|
+
cwd,
|
|
81
|
+
env,
|
|
82
|
+
files,
|
|
83
|
+
signal,
|
|
84
|
+
stdin
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
//#endregion
|
|
89
|
+
exports.backendForTrust = backendForTrust;
|
|
90
|
+
exports.createExecContext = createExecContext;
|
|
91
|
+
exports.realRunner = realRunner;
|
|
92
|
+
exports.runShell = runShell;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file OpenAI-compatible HTTP backends for AI providers that expose a
|
|
3
|
+
* chat-completions endpoint rather than a CLI — Fireworks
|
|
4
|
+
* (`api.fireworks.ai`) and Synthetic (`api.synthetic.new`). The CLI path
|
|
5
|
+
* (`spawn.mts`) drives an interactive agent binary; this path is for a
|
|
6
|
+
* script/hook that needs a single completion from a model without an agent
|
|
7
|
+
* harness (the way the local OpenCode setup reaches GLM-5.1 / Kimi-K2.5). Why
|
|
8
|
+
* a separate module from `spawn.mts`: those are different surfaces. A CLI
|
|
9
|
+
* agent gets tools + a permission mode + a working dir; an HTTP completion
|
|
10
|
+
* gets a prompt + a model + (optionally) a reasoning effort and returns text.
|
|
11
|
+
* Conflating them would force every HTTP call to carry meaningless CLI
|
|
12
|
+
* lockdown fields. Lockdown equivalent: these calls send NO tools /
|
|
13
|
+
* function-calling surface — they're plain completions, so there's no agentic
|
|
14
|
+
* capability to constrain. The token is read from the env var the provider
|
|
15
|
+
* config names (`FIREWORKS_API_KEY` / `SYNTHETIC_API_KEY`), NEVER passed
|
|
16
|
+
* inline, and never logged — same token-hygiene rule as the rest of the
|
|
17
|
+
* fleet. A missing token throws with the exact env var to set. Wire format is
|
|
18
|
+
* the OpenAI Chat Completions API (`POST {baseUrl}/chat/completions`), which
|
|
19
|
+
* both providers implement.
|
|
20
|
+
*/
|
|
21
|
+
import type { AiEffort } from './types.mts';
|
|
22
|
+
/**
|
|
23
|
+
* An OpenAI-compatible HTTP provider. `id` is the slug prefix used in
|
|
24
|
+
* `provider/model` references; `baseUrl` is the chat-completions API root;
|
|
25
|
+
* `tokenEnv` names the env var holding the bearer token.
|
|
26
|
+
*/
|
|
27
|
+
export interface AiHttpProvider {
|
|
28
|
+
readonly id: string;
|
|
29
|
+
readonly baseUrl: string;
|
|
30
|
+
readonly tokenEnv: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Built-in OpenAI-compatible providers. Add an entry to support a new one — no
|
|
34
|
+
* other call site changes. Base URLs are the documented chat-completions
|
|
35
|
+
* roots.
|
|
36
|
+
*/
|
|
37
|
+
export declare const AI_HTTP_PROVIDERS: Readonly<Record<string, AiHttpProvider>>;
|
|
38
|
+
/**
|
|
39
|
+
* Inputs to a single completion call.
|
|
40
|
+
*
|
|
41
|
+
* Required: `provider`, `model`, `prompt`. `effort` maps to the OpenAI
|
|
42
|
+
* `reasoning_effort` field for models that support it (left off otherwise).
|
|
43
|
+
*/
|
|
44
|
+
export interface AiHttpCallOptions {
|
|
45
|
+
/**
|
|
46
|
+
* Provider id (a key of AI_HTTP_PROVIDERS) or a full AiHttpProvider.
|
|
47
|
+
*/
|
|
48
|
+
readonly provider: string | AiHttpProvider;
|
|
49
|
+
/**
|
|
50
|
+
* The provider's model id (e.g. `accounts/fireworks/models/glm-5p1`,
|
|
51
|
+
* `hf:moonshotai/Kimi-K2.5`).
|
|
52
|
+
*/
|
|
53
|
+
readonly model: string;
|
|
54
|
+
/**
|
|
55
|
+
* The user prompt.
|
|
56
|
+
*/
|
|
57
|
+
readonly prompt: string;
|
|
58
|
+
/**
|
|
59
|
+
* Optional system prompt prepended as the `system` role message.
|
|
60
|
+
*/
|
|
61
|
+
readonly system?: string | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Reasoning effort (`reasoning_effort` field); omitted when absent. Only set
|
|
64
|
+
* for a model that supports it — providers ignore or reject it otherwise.
|
|
65
|
+
*/
|
|
66
|
+
readonly effort?: AiEffort | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Sampling temperature; provider default when absent.
|
|
69
|
+
*/
|
|
70
|
+
readonly temperature?: number | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Per-call timeout (ms).
|
|
73
|
+
*/
|
|
74
|
+
readonly timeoutMs?: number | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* An explicit bearer token that wins over env + keychain. When absent the
|
|
77
|
+
* token resolves via `resolveProviderCredential` (env → keychain).
|
|
78
|
+
*/
|
|
79
|
+
readonly token?: string | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Skip the keychain fallback when resolving the token — env var only. Set in
|
|
82
|
+
* headless contexts (CI, hooks) where a keychain auth prompt is
|
|
83
|
+
* unacceptable.
|
|
84
|
+
*/
|
|
85
|
+
readonly allowEnvOnly?: boolean | undefined;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Result of a completion: the assistant text plus the raw provider response for
|
|
89
|
+
* callers that need usage / finish-reason detail.
|
|
90
|
+
*/
|
|
91
|
+
export interface AiHttpResult {
|
|
92
|
+
readonly text: string;
|
|
93
|
+
readonly raw: OpenAiChatResponse;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The slice of the OpenAI chat-completions response we read.
|
|
97
|
+
*/
|
|
98
|
+
export interface OpenAiChatResponse {
|
|
99
|
+
readonly choices?: ReadonlyArray<{
|
|
100
|
+
message?: {
|
|
101
|
+
content?: string | undefined;
|
|
102
|
+
} | undefined;
|
|
103
|
+
}> | undefined;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Build the chat-completions request body. Kept pure for testing — the effort →
|
|
107
|
+
* `reasoning_effort` mapping + system-message prepend are the parts worth
|
|
108
|
+
* asserting without a network call.
|
|
109
|
+
*/
|
|
110
|
+
export declare function buildChatRequestBody(options: AiHttpCallOptions): string;
|
|
111
|
+
/**
|
|
112
|
+
* Call an OpenAI-compatible chat-completions endpoint and return the assistant
|
|
113
|
+
* text. The bearer token is read from the provider's `tokenEnv` env var — never
|
|
114
|
+
* accepted as a parameter, never logged. Throws when the token env var is unset
|
|
115
|
+
* (naming the var to set) or when the response carries no message text.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ;```ts
|
|
119
|
+
* const { text } = await callAiHttpModel({
|
|
120
|
+
* provider: 'fireworks',
|
|
121
|
+
* model: 'accounts/fireworks/models/glm-5p1',
|
|
122
|
+
* prompt: 'Summarize this diff: …',
|
|
123
|
+
* effort: 'high',
|
|
124
|
+
* })
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export declare function callAiHttpModel(options: AiHttpCallOptions): Promise<AiHttpResult>;
|
|
128
|
+
/**
|
|
129
|
+
* Resolve a provider id / object to an AiHttpProvider. Throws with the known
|
|
130
|
+
* provider set when an unknown id is passed.
|
|
131
|
+
*/
|
|
132
|
+
export declare function resolveAiHttpProvider(provider: string | AiHttpProvider): AiHttpProvider;
|
package/dist/ai/http.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Socket Lib - Built with rolldown */
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
const require_primordials_error = require('../primordials/error.js');
|
|
5
|
+
const require_ai_credentials = require('./credentials.js');
|
|
6
|
+
const require_http_request_node = require('../http-request/node.js');
|
|
7
|
+
|
|
8
|
+
//#region src/ai/http.mts
|
|
9
|
+
/**
|
|
10
|
+
* @file OpenAI-compatible HTTP backends for AI providers that expose a
|
|
11
|
+
* chat-completions endpoint rather than a CLI — Fireworks
|
|
12
|
+
* (`api.fireworks.ai`) and Synthetic (`api.synthetic.new`). The CLI path
|
|
13
|
+
* (`spawn.mts`) drives an interactive agent binary; this path is for a
|
|
14
|
+
* script/hook that needs a single completion from a model without an agent
|
|
15
|
+
* harness (the way the local OpenCode setup reaches GLM-5.1 / Kimi-K2.5). Why
|
|
16
|
+
* a separate module from `spawn.mts`: those are different surfaces. A CLI
|
|
17
|
+
* agent gets tools + a permission mode + a working dir; an HTTP completion
|
|
18
|
+
* gets a prompt + a model + (optionally) a reasoning effort and returns text.
|
|
19
|
+
* Conflating them would force every HTTP call to carry meaningless CLI
|
|
20
|
+
* lockdown fields. Lockdown equivalent: these calls send NO tools /
|
|
21
|
+
* function-calling surface — they're plain completions, so there's no agentic
|
|
22
|
+
* capability to constrain. The token is read from the env var the provider
|
|
23
|
+
* config names (`FIREWORKS_API_KEY` / `SYNTHETIC_API_KEY`), NEVER passed
|
|
24
|
+
* inline, and never logged — same token-hygiene rule as the rest of the
|
|
25
|
+
* fleet. A missing token throws with the exact env var to set. Wire format is
|
|
26
|
+
* the OpenAI Chat Completions API (`POST {baseUrl}/chat/completions`), which
|
|
27
|
+
* both providers implement.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Built-in OpenAI-compatible providers. Add an entry to support a new one — no
|
|
31
|
+
* other call site changes. Base URLs are the documented chat-completions
|
|
32
|
+
* roots.
|
|
33
|
+
*/
|
|
34
|
+
const AI_HTTP_PROVIDERS = {
|
|
35
|
+
__proto__: null,
|
|
36
|
+
fireworks: {
|
|
37
|
+
id: "fireworks",
|
|
38
|
+
baseUrl: "https://api.fireworks.ai/inference/v1",
|
|
39
|
+
tokenEnv: "FIREWORKS_API_KEY"
|
|
40
|
+
},
|
|
41
|
+
synthetic: {
|
|
42
|
+
id: "synthetic",
|
|
43
|
+
baseUrl: "https://api.synthetic.new/openai/v1",
|
|
44
|
+
tokenEnv: "SYNTHETIC_API_KEY"
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Build the chat-completions request body. Kept pure for testing — the effort →
|
|
49
|
+
* `reasoning_effort` mapping + system-message prepend are the parts worth
|
|
50
|
+
* asserting without a network call.
|
|
51
|
+
*/
|
|
52
|
+
function buildChatRequestBody(options) {
|
|
53
|
+
options = {
|
|
54
|
+
__proto__: null,
|
|
55
|
+
...options
|
|
56
|
+
};
|
|
57
|
+
const messages = [];
|
|
58
|
+
if (options.system) messages.push({
|
|
59
|
+
content: options.system,
|
|
60
|
+
role: "system"
|
|
61
|
+
});
|
|
62
|
+
messages.push({
|
|
63
|
+
content: options.prompt,
|
|
64
|
+
role: "user"
|
|
65
|
+
});
|
|
66
|
+
const body = {
|
|
67
|
+
messages,
|
|
68
|
+
model: options.model
|
|
69
|
+
};
|
|
70
|
+
if (options.effort) body["reasoning_effort"] = options.effort;
|
|
71
|
+
if (typeof options.temperature === "number") body["temperature"] = options.temperature;
|
|
72
|
+
return JSON.stringify(body);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Call an OpenAI-compatible chat-completions endpoint and return the assistant
|
|
76
|
+
* text. The bearer token is read from the provider's `tokenEnv` env var — never
|
|
77
|
+
* accepted as a parameter, never logged. Throws when the token env var is unset
|
|
78
|
+
* (naming the var to set) or when the response carries no message text.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ;```ts
|
|
82
|
+
* const { text } = await callAiHttpModel({
|
|
83
|
+
* provider: 'fireworks',
|
|
84
|
+
* model: 'accounts/fireworks/models/glm-5p1',
|
|
85
|
+
* prompt: 'Summarize this diff: …',
|
|
86
|
+
* effort: 'high',
|
|
87
|
+
* })
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
async function callAiHttpModel(options) {
|
|
91
|
+
options = {
|
|
92
|
+
__proto__: null,
|
|
93
|
+
...options
|
|
94
|
+
};
|
|
95
|
+
const provider = resolveAiHttpProvider(options.provider);
|
|
96
|
+
const token = require_ai_credentials.isCredentialProvider(provider.id) ? await require_ai_credentials.resolveProviderCredential({
|
|
97
|
+
allowEnvOnly: options.allowEnvOnly,
|
|
98
|
+
explicit: options.token,
|
|
99
|
+
provider: provider.id
|
|
100
|
+
}) : options.token ?? process.env[provider.tokenEnv];
|
|
101
|
+
if (!token) throw new require_primordials_error.ErrorCtor(`Missing API token for AI HTTP provider "${provider.id}". Set the ${provider.tokenEnv} environment variable (a bearer token) or store it in the keychain — never pass it inline.`);
|
|
102
|
+
const raw = await require_http_request_node.httpJson(`${provider.baseUrl}/chat/completions`, {
|
|
103
|
+
body: buildChatRequestBody(options),
|
|
104
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
105
|
+
method: "POST",
|
|
106
|
+
...options.timeoutMs === void 0 ? {} : { timeout: options.timeoutMs }
|
|
107
|
+
});
|
|
108
|
+
const text = raw.choices?.[0]?.message?.content;
|
|
109
|
+
if (typeof text !== "string") throw new require_primordials_error.ErrorCtor(`AI HTTP provider "${provider.id}" returned no message text for model "${options.model}". The response had no choices[0].message.content — check the model id and the provider's status.`);
|
|
110
|
+
return {
|
|
111
|
+
raw,
|
|
112
|
+
text
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Resolve a provider id / object to an AiHttpProvider. Throws with the known
|
|
117
|
+
* provider set when an unknown id is passed.
|
|
118
|
+
*/
|
|
119
|
+
function resolveAiHttpProvider(provider) {
|
|
120
|
+
if (typeof provider !== "string") return provider;
|
|
121
|
+
const found = AI_HTTP_PROVIDERS[provider];
|
|
122
|
+
if (!found) throw new require_primordials_error.ErrorCtor(`Unknown AI HTTP provider "${provider}". Known providers: ${Object.keys(AI_HTTP_PROVIDERS).join(", ")}. Pass a known id or a full AiHttpProvider { id, baseUrl, tokenEnv }.`);
|
|
123
|
+
return found;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
//#endregion
|
|
127
|
+
exports.AI_HTTP_PROVIDERS = AI_HTTP_PROVIDERS;
|
|
128
|
+
exports.buildChatRequestBody = buildChatRequestBody;
|
|
129
|
+
exports.callAiHttpModel = callAiHttpModel;
|
|
130
|
+
exports.resolveAiHttpProvider = resolveAiHttpProvider;
|
package/dist/ai/profiles.d.mts
CHANGED
|
@@ -16,11 +16,20 @@
|
|
|
16
16
|
* - `AI_PROFILE.create` — edit AND create files. Adds MultiEdit + Write on top
|
|
17
17
|
* of `.edit`. Still no Bash. Codegen, adding a test, refactors that split
|
|
18
18
|
* modules.
|
|
19
|
-
* - `AI_PROFILE.
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
19
|
+
* - `AI_PROFILE.verify` — `.create` plus a READ-ONLY Bash allowlist (node /
|
|
20
|
+
* pnpm test+run / git status·diff·log). Lets an agent author files AND run
|
|
21
|
+
* the verifier (its own tests, a check script) — but it CANNOT mutate the
|
|
22
|
+
* repo: no `git add`, no `git commit`, no install. For codegen that must
|
|
23
|
+
* self-verify without being trusted to land.
|
|
24
|
+
* - `AI_PROFILE.full` — `.verify` plus the mutating git commands (`git add` /
|
|
25
|
+
* `git commit`) and `pnpm exec`. Skills that commit, run tests, install
|
|
26
|
+
* deps. No "wide open" tier exists by design — letting an agent run
|
|
27
|
+
* arbitrary tools is the lockdown rule's exact failure mode. The ladder is
|
|
28
|
+
* read ⊂ edit ⊂ create ⊂ verify ⊂ full: each tier's tool set is a superset
|
|
29
|
+
* of the one above. Bash allowlists are composed from the `BASH_ALLOW`
|
|
30
|
+
* building blocks below so a caller can assemble a custom tier
|
|
31
|
+
* (`[...BASH_ALLOW.git, ...BASH_ALLOW.test]`) without forking a profile
|
|
32
|
+
* literal.
|
|
24
33
|
*/
|
|
25
34
|
import type { PermissionMode } from './types.mts';
|
|
26
35
|
export interface AiProfile {
|
|
@@ -29,6 +38,26 @@ export interface AiProfile {
|
|
|
29
38
|
readonly permissionMode: PermissionMode;
|
|
30
39
|
readonly tools: readonly string[];
|
|
31
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Composable Bash-allowlist building blocks. Each group is a frozen list of
|
|
43
|
+
* `Bash(<cmd>:*)` glob entries; the profiles below compose tiers from them, and
|
|
44
|
+
* callers can mix their own (`allow: [...BASH_ALLOW.test, 'Bash(make:*)']`)
|
|
45
|
+
* without rewriting a whole tier's literal.
|
|
46
|
+
*
|
|
47
|
+
* - `gitRead` — non-mutating inspection (`status` / `diff` / `log`).
|
|
48
|
+
* - `gitWrite` — mutating (`add` / `commit`). The bright line between `verify`
|
|
49
|
+
* (may NOT land) and `full` (may land).
|
|
50
|
+
* - `node` — run a `.mts` / `.js` directly (tests, check scripts, codegen).
|
|
51
|
+
* - `test` — `pnpm test` / `pnpm run <script>` (the verify surface).
|
|
52
|
+
* - `pkgExec` — `pnpm exec` (run a workspace bin); broader, full-tier only.
|
|
53
|
+
*/
|
|
54
|
+
export declare const BASH_ALLOW: {
|
|
55
|
+
readonly gitRead: readonly ["Bash(git status:*)", "Bash(git diff:*)", "Bash(git log:*)"];
|
|
56
|
+
readonly gitWrite: readonly ["Bash(git add:*)", "Bash(git commit:*)"];
|
|
57
|
+
readonly node: readonly ["Bash(node:*)"];
|
|
58
|
+
readonly pkgExec: readonly ["Bash(pnpm exec:*)"];
|
|
59
|
+
readonly test: readonly ["Bash(pnpm run:*)", "Bash(pnpm test:*)"];
|
|
60
|
+
};
|
|
32
61
|
/**
|
|
33
62
|
* Capability ladder of lockdown profiles, ordered least → most capable. Key
|
|
34
63
|
* order documents the ladder; each tier is a strict superset of the previous
|
|
@@ -53,8 +82,14 @@ export declare const AI_PROFILE: {
|
|
|
53
82
|
readonly permissionMode: 'acceptEdits';
|
|
54
83
|
readonly tools: readonly ["Edit", "Glob", "Grep", "MultiEdit", "Read", "Write"];
|
|
55
84
|
};
|
|
85
|
+
readonly verify: {
|
|
86
|
+
readonly allow: readonly ["Bash(git status:*)", "Bash(git diff:*)", "Bash(git log:*)", "Bash(node:*)", "Bash(pnpm run:*)", "Bash(pnpm test:*)"];
|
|
87
|
+
readonly disallow: readonly ["Agent", "WebFetch", "WebSearch"];
|
|
88
|
+
readonly permissionMode: 'acceptEdits';
|
|
89
|
+
readonly tools: readonly ["Bash", "Edit", "Glob", "Grep", "MultiEdit", "Read", "Write"];
|
|
90
|
+
};
|
|
56
91
|
readonly full: {
|
|
57
|
-
readonly allow: readonly ["Bash(git status:*)", "Bash(git diff:*)", "Bash(git log:*)", "Bash(
|
|
92
|
+
readonly allow: readonly ["Bash(git status:*)", "Bash(git diff:*)", "Bash(git log:*)", "Bash(node:*)", "Bash(pnpm run:*)", "Bash(pnpm test:*)", "Bash(git add:*)", "Bash(git commit:*)", "Bash(pnpm exec:*)"];
|
|
58
93
|
readonly disallow: readonly ["Agent", "WebFetch", "WebSearch"];
|
|
59
94
|
readonly permissionMode: 'acceptEdits';
|
|
60
95
|
readonly tools: readonly ["Bash", "Edit", "Glob", "Grep", "MultiEdit", "Read", "Write"];
|
package/dist/ai/profiles.js
CHANGED
|
@@ -4,6 +4,35 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
4
4
|
|
|
5
5
|
//#region src/ai/profiles.mts
|
|
6
6
|
/**
|
|
7
|
+
* Composable Bash-allowlist building blocks. Each group is a frozen list of
|
|
8
|
+
* `Bash(<cmd>:*)` glob entries; the profiles below compose tiers from them, and
|
|
9
|
+
* callers can mix their own (`allow: [...BASH_ALLOW.test, 'Bash(make:*)']`)
|
|
10
|
+
* without rewriting a whole tier's literal.
|
|
11
|
+
*
|
|
12
|
+
* - `gitRead` — non-mutating inspection (`status` / `diff` / `log`).
|
|
13
|
+
* - `gitWrite` — mutating (`add` / `commit`). The bright line between `verify`
|
|
14
|
+
* (may NOT land) and `full` (may land).
|
|
15
|
+
* - `node` — run a `.mts` / `.js` directly (tests, check scripts, codegen).
|
|
16
|
+
* - `test` — `pnpm test` / `pnpm run <script>` (the verify surface).
|
|
17
|
+
* - `pkgExec` — `pnpm exec` (run a workspace bin); broader, full-tier only.
|
|
18
|
+
*/
|
|
19
|
+
const BASH_ALLOW = {
|
|
20
|
+
gitRead: [
|
|
21
|
+
"Bash(git status:*)",
|
|
22
|
+
"Bash(git diff:*)",
|
|
23
|
+
"Bash(git log:*)"
|
|
24
|
+
],
|
|
25
|
+
gitWrite: ["Bash(git add:*)", "Bash(git commit:*)"],
|
|
26
|
+
node: ["Bash(node:*)"],
|
|
27
|
+
pkgExec: ["Bash(pnpm exec:*)"],
|
|
28
|
+
test: ["Bash(pnpm run:*)", "Bash(pnpm test:*)"]
|
|
29
|
+
};
|
|
30
|
+
const VERIFY_BASH_ALLOW = [
|
|
31
|
+
...BASH_ALLOW.gitRead,
|
|
32
|
+
...BASH_ALLOW.node,
|
|
33
|
+
...BASH_ALLOW.test
|
|
34
|
+
];
|
|
35
|
+
/**
|
|
7
36
|
* Capability ladder of lockdown profiles, ordered least → most capable. Key
|
|
8
37
|
* order documents the ladder; each tier is a strict superset of the previous
|
|
9
38
|
* tier's tool surface.
|
|
@@ -63,17 +92,29 @@ const AI_PROFILE = {
|
|
|
63
92
|
"Write"
|
|
64
93
|
]
|
|
65
94
|
},
|
|
95
|
+
verify: {
|
|
96
|
+
allow: [...VERIFY_BASH_ALLOW],
|
|
97
|
+
disallow: [
|
|
98
|
+
"Agent",
|
|
99
|
+
"WebFetch",
|
|
100
|
+
"WebSearch"
|
|
101
|
+
],
|
|
102
|
+
permissionMode: "acceptEdits",
|
|
103
|
+
tools: [
|
|
104
|
+
"Bash",
|
|
105
|
+
"Edit",
|
|
106
|
+
"Glob",
|
|
107
|
+
"Grep",
|
|
108
|
+
"MultiEdit",
|
|
109
|
+
"Read",
|
|
110
|
+
"Write"
|
|
111
|
+
]
|
|
112
|
+
},
|
|
66
113
|
full: {
|
|
67
114
|
allow: [
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"Bash(git add:*)",
|
|
72
|
-
"Bash(git commit:*)",
|
|
73
|
-
"Bash(node:*)",
|
|
74
|
-
"Bash(pnpm exec:*)",
|
|
75
|
-
"Bash(pnpm run:*)",
|
|
76
|
-
"Bash(pnpm test:*)"
|
|
115
|
+
...VERIFY_BASH_ALLOW,
|
|
116
|
+
...BASH_ALLOW.gitWrite,
|
|
117
|
+
...BASH_ALLOW.pkgExec
|
|
77
118
|
],
|
|
78
119
|
disallow: [
|
|
79
120
|
"Agent",
|
|
@@ -94,4 +135,5 @@ const AI_PROFILE = {
|
|
|
94
135
|
};
|
|
95
136
|
|
|
96
137
|
//#endregion
|
|
97
|
-
exports.AI_PROFILE = AI_PROFILE;
|
|
138
|
+
exports.AI_PROFILE = AI_PROFILE;
|
|
139
|
+
exports.BASH_ALLOW = BASH_ALLOW;
|