@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.
Files changed (263) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -1
  3. package/dist/ai/agent-context.d.mts +103 -0
  4. package/dist/ai/agent-context.js +157 -0
  5. package/dist/ai/backends.d.mts +83 -0
  6. package/dist/ai/backends.js +173 -0
  7. package/dist/ai/credentials.d.mts +49 -0
  8. package/dist/ai/credentials.js +82 -0
  9. package/dist/ai/discover.d.mts +4 -0
  10. package/dist/ai/discover.js +1 -1
  11. package/dist/ai/exec.d.mts +52 -0
  12. package/dist/ai/exec.js +92 -0
  13. package/dist/ai/http.d.mts +132 -0
  14. package/dist/ai/http.js +130 -0
  15. package/dist/ai/profiles.d.mts +41 -6
  16. package/dist/ai/profiles.js +52 -10
  17. package/dist/ai/route.d.mts +69 -0
  18. package/dist/ai/route.js +156 -0
  19. package/dist/ai/spawn.d.mts +10 -2
  20. package/dist/ai/spawn.js +55 -31
  21. package/dist/ai/subagent-status.d.mts +48 -0
  22. package/dist/ai/subagent-status.js +57 -0
  23. package/dist/ai/tier.d.mts +60 -0
  24. package/dist/ai/tier.js +53 -0
  25. package/dist/ai/types.d.mts +15 -2
  26. package/dist/ai/worktree.js +4 -0
  27. package/dist/archives/tar.js +1 -1
  28. package/dist/archives/zip.js +2 -2
  29. package/dist/argv/parse.d.ts +19 -2
  30. package/dist/argv/parse.js +1 -1
  31. package/dist/arrays/join.js +4 -0
  32. package/dist/bin/find.js +4 -4
  33. package/dist/bin/prim.cjs +3915 -3781
  34. package/dist/bin/resolve.js +1 -1
  35. package/dist/cache/ttl/store.js +1 -1
  36. package/dist/cli/check-primordials.d.ts +8 -3
  37. package/dist/cli/check-primordials.js +4 -4
  38. package/dist/compression/_internal.js +1 -1
  39. package/dist/compression/brotli.d.ts +1 -2
  40. package/dist/compression/brotli.js +6 -2
  41. package/dist/compression/gzip.js +6 -2
  42. package/dist/constants/packages.d.ts +3 -0
  43. package/dist/constants/packages.js +2 -1
  44. package/dist/constants/socket.d.ts +2 -6
  45. package/dist/constants/socket.js +12 -14
  46. package/dist/cover/code.js +2 -2
  47. package/dist/crypto/hash.d.ts +4 -1
  48. package/dist/crypto/hash.js +4 -1
  49. package/dist/debug/caller-info.js +1 -1
  50. package/dist/dlx/arborist.js +13 -3
  51. package/dist/dlx/binary-cache.js +1 -1
  52. package/dist/dlx/binary-resolution.js +1 -1
  53. package/dist/dlx/detect.d.ts +8 -0
  54. package/dist/dlx/firewall.d.ts +8 -0
  55. package/dist/dlx/firewall.js +1 -1
  56. package/dist/dlx/lockfile.js +4 -1
  57. package/dist/dlx/manifest.js +1 -1
  58. package/dist/dlx/package.js +4 -0
  59. package/dist/eco/cargo/parse-lockfile.d.ts +1 -2
  60. package/dist/eco/cargo/parse-lockfile.js +3 -3
  61. package/dist/eco/manifest/detect-format.js +1 -1
  62. package/dist/eco/npm/npm/parse-lockfile.d.ts +3 -4
  63. package/dist/eco/npm/npm/parse-lockfile.js +2 -2
  64. package/dist/eco/npm/parse-package-json.d.ts +11 -0
  65. package/dist/eco/npm/parse-package-json.js +1 -1
  66. package/dist/eco/npm/pnpm/parse-lockfile.d.ts +5 -3
  67. package/dist/eco/npm/pnpm/parse-lockfile.js +3 -3
  68. package/dist/eco/npm/yarnpkg/yarn/exec.js +1 -1
  69. package/dist/eco/npm/yarnpkg/yarn/parse-lockfile.d.ts +1 -2
  70. package/dist/eco/npm/yarnpkg/yarn/parse-lockfile.js +1 -1
  71. package/dist/env/proxy.js +1 -1
  72. package/dist/env/rewire.d.ts +1 -0
  73. package/dist/env/rewire.js +1 -1
  74. package/dist/env/socket.d.ts +7 -0
  75. package/dist/env/socket.js +10 -0
  76. package/dist/errors/predicates.js +1 -1
  77. package/dist/external/@npmcli/promise-spawn.js +3 -1
  78. package/dist/external/pico-pack.js +4 -2
  79. package/dist/external/which.js +3 -1
  80. package/dist/external-tools/bazel/asset-names.d.ts +1 -1
  81. package/dist/external-tools/bazel/asset-names.js +5 -2
  82. package/dist/external-tools/bazel/from-download.d.ts +1 -1
  83. package/dist/external-tools/bazel/from-download.js +5 -2
  84. package/dist/external-tools/bazel/resolve-bazel-version.js +4 -0
  85. package/dist/external-tools/bazel/resolve.d.ts +3 -3
  86. package/dist/external-tools/bazel/resolve.js +16 -8
  87. package/dist/external-tools/cdxgen/asset-names.d.ts +1 -1
  88. package/dist/external-tools/cdxgen/asset-names.js +5 -2
  89. package/dist/external-tools/cdxgen/from-download.d.ts +1 -1
  90. package/dist/external-tools/cdxgen/from-download.js +7 -4
  91. package/dist/external-tools/cdxgen/resolve.d.ts +3 -3
  92. package/dist/external-tools/cdxgen/resolve.js +16 -8
  93. package/dist/external-tools/from-download.d.ts +2 -2
  94. package/dist/external-tools/from-download.js +11 -5
  95. package/dist/external-tools/from-pip-venv.d.ts +1 -1
  96. package/dist/external-tools/from-pip-venv.js +12 -5
  97. package/dist/external-tools/janus/asset-names.d.ts +1 -1
  98. package/dist/external-tools/janus/asset-names.js +5 -2
  99. package/dist/external-tools/janus/from-download.d.ts +1 -1
  100. package/dist/external-tools/janus/from-download.js +5 -2
  101. package/dist/external-tools/janus/resolve.d.ts +3 -3
  102. package/dist/external-tools/janus/resolve.js +16 -8
  103. package/dist/external-tools/jre/asset-names.d.ts +1 -1
  104. package/dist/external-tools/jre/asset-names.js +5 -2
  105. package/dist/external-tools/jre/from-download.d.ts +1 -1
  106. package/dist/external-tools/jre/from-download.js +7 -4
  107. package/dist/external-tools/jre/from-java-home.js +2 -2
  108. package/dist/external-tools/jre/from-vfs.js +2 -2
  109. package/dist/external-tools/jre/resolve.d.ts +3 -3
  110. package/dist/external-tools/jre/resolve.js +16 -8
  111. package/dist/external-tools/manifest.d.ts +18 -0
  112. package/dist/external-tools/manifest.js +1 -1
  113. package/dist/external-tools/opengrep/asset-names.d.ts +1 -1
  114. package/dist/external-tools/opengrep/asset-names.js +5 -2
  115. package/dist/external-tools/opengrep/from-download.d.ts +1 -1
  116. package/dist/external-tools/opengrep/from-download.js +5 -2
  117. package/dist/external-tools/opengrep/resolve.d.ts +3 -3
  118. package/dist/external-tools/opengrep/resolve.js +16 -8
  119. package/dist/external-tools/python/asset-names.d.ts +1 -1
  120. package/dist/external-tools/python/asset-names.js +10 -3
  121. package/dist/external-tools/python/dlx.d.ts +3 -3
  122. package/dist/external-tools/python/dlx.js +20 -9
  123. package/dist/external-tools/python/from-download.d.ts +1 -1
  124. package/dist/external-tools/python/from-download.js +12 -5
  125. package/dist/external-tools/python/pin.js +6 -3
  126. package/dist/external-tools/python/pip-install.js +6 -3
  127. package/dist/external-tools/python/resolve.d.ts +3 -3
  128. package/dist/external-tools/python/resolve.js +19 -11
  129. package/dist/external-tools/sbt/asset-names.d.ts +1 -1
  130. package/dist/external-tools/sbt/asset-names.js +5 -2
  131. package/dist/external-tools/sbt/from-download.d.ts +1 -1
  132. package/dist/external-tools/sbt/from-download.js +5 -2
  133. package/dist/external-tools/sbt/resolve.d.ts +3 -3
  134. package/dist/external-tools/sbt/resolve.js +16 -8
  135. package/dist/external-tools/skillspector/from-dlx.d.ts +1 -1
  136. package/dist/external-tools/skillspector/from-dlx.js +10 -3
  137. package/dist/external-tools/skillspector/resolve.d.ts +2 -2
  138. package/dist/external-tools/skillspector/resolve.js +14 -6
  139. package/dist/external-tools/synp/asset-names.d.ts +1 -1
  140. package/dist/external-tools/synp/asset-names.js +6 -2
  141. package/dist/external-tools/synp/from-download.d.ts +1 -1
  142. package/dist/external-tools/synp/from-download.js +5 -2
  143. package/dist/external-tools/synp/resolve.d.ts +3 -3
  144. package/dist/external-tools/synp/resolve.js +16 -8
  145. package/dist/external-tools/trivy/asset-names.d.ts +1 -1
  146. package/dist/external-tools/trivy/asset-names.js +5 -2
  147. package/dist/external-tools/trivy/from-download.d.ts +1 -1
  148. package/dist/external-tools/trivy/from-download.js +7 -4
  149. package/dist/external-tools/trivy/resolve.d.ts +3 -3
  150. package/dist/external-tools/trivy/resolve.js +16 -8
  151. package/dist/external-tools/trufflehog/asset-names.d.ts +1 -1
  152. package/dist/external-tools/trufflehog/asset-names.js +5 -2
  153. package/dist/external-tools/trufflehog/from-download.d.ts +1 -1
  154. package/dist/external-tools/trufflehog/from-download.js +7 -4
  155. package/dist/external-tools/trufflehog/resolve.d.ts +3 -3
  156. package/dist/external-tools/trufflehog/resolve.js +16 -8
  157. package/dist/fs/allowed-dirs-cache.d.ts +27 -1
  158. package/dist/fs/allowed-dirs-cache.js +38 -3
  159. package/dist/fs/find.js +1 -1
  160. package/dist/fs/read-json-cache.d.ts +7 -0
  161. package/dist/fs/resolve-module.js +6 -2
  162. package/dist/fs/safe.js +1 -1
  163. package/dist/git/_internal.js +2 -2
  164. package/dist/git/repo.js +2 -4
  165. package/dist/git/staged.js +8 -0
  166. package/dist/git/tracked.d.ts +84 -0
  167. package/dist/git/tracked.js +163 -0
  168. package/dist/git/unstaged.js +8 -0
  169. package/dist/github/refs-graphql.js +4 -0
  170. package/dist/github/refs-rest.js +4 -0
  171. package/dist/github/refs.js +15 -10
  172. package/dist/globs/_internal.js +1 -1
  173. package/dist/globs/match.js +9 -1
  174. package/dist/globs/matcher.js +5 -1
  175. package/dist/http-request/browser.js +6 -2
  176. package/dist/http-request/{browser-fetch.d.ts → fetch/browser.d.ts} +2 -2
  177. package/dist/http-request/{browser-fetch.js → fetch/browser.js} +4 -4
  178. package/dist/http-request/headers.js +1 -1
  179. package/dist/http-request/request-attempt.js +2 -2
  180. package/dist/http-request/user-agent.js +1 -1
  181. package/dist/integrity.d.ts +10 -4
  182. package/dist/integrity.js +10 -4
  183. package/dist/json/edit.js +38 -30
  184. package/dist/json/format.js +1 -1
  185. package/dist/native-messaging/install.d.ts +1 -1
  186. package/dist/native-messaging/install.js +7 -4
  187. package/dist/native-messaging/rate-limit.d.ts +7 -0
  188. package/dist/native-messaging/rate-limit.js +4 -0
  189. package/dist/node/async-hooks.js +1 -1
  190. package/dist/node/child-process.js +1 -1
  191. package/dist/node/crypto.js +1 -1
  192. package/dist/node/events.js +1 -1
  193. package/dist/node/fs-promises.js +1 -1
  194. package/dist/node/fs.d.ts +22 -6
  195. package/dist/node/fs.js +16 -3
  196. package/dist/node/http.js +1 -1
  197. package/dist/node/https.js +1 -1
  198. package/dist/node/module.js +1 -1
  199. package/dist/node/os.d.ts +10 -2
  200. package/dist/node/os.js +11 -4
  201. package/dist/node/path.d.ts +11 -2
  202. package/dist/node/path.js +17 -4
  203. package/dist/node/timers-promises.js +1 -1
  204. package/dist/node/url.js +1 -1
  205. package/dist/node/util.js +1 -1
  206. package/dist/objects/getters.js +1 -1
  207. package/dist/objects/mutate.js +2 -2
  208. package/dist/objects/predicates.js +1 -1
  209. package/dist/packages/edit-class.d.ts +2 -3
  210. package/dist/packages/edit-class.js +41 -35
  211. package/dist/packages/exports.js +4 -4
  212. package/dist/packages/fetch.js +1 -1
  213. package/dist/packages/isolation.js +1 -1
  214. package/dist/packages/licenses.js +2 -2
  215. package/dist/packages/manifest.js +4 -4
  216. package/dist/packages/normalize.js +1 -1
  217. package/dist/packages/provenance.js +2 -2
  218. package/dist/packages/specs.js +1 -1
  219. package/dist/packages/tarball.js +4 -2
  220. package/dist/packages/types.d.ts +1 -2
  221. package/dist/paths/dirnames.d.ts +1 -0
  222. package/dist/paths/dirnames.js +2 -0
  223. package/dist/paths/resolve.js +14 -19
  224. package/dist/paths/rewire.d.ts +5 -0
  225. package/dist/paths/socket.d.ts +74 -111
  226. package/dist/paths/socket.js +99 -132
  227. package/dist/primordials/process.d.ts +88 -0
  228. package/dist/primordials/process.js +132 -0
  229. package/dist/primordials/uncurry.d.ts +1 -2
  230. package/dist/process/spawn/child.js +8 -2
  231. package/dist/process/spawn/errors.js +1 -1
  232. package/dist/regexps/spec.js +1 -1
  233. package/dist/releases/github-archives.js +1 -1
  234. package/dist/releases/github-listing.d.ts +1 -2
  235. package/dist/schema/types.d.ts +3 -4
  236. package/dist/schema/validate.js +1 -1
  237. package/dist/secrets/find.d.ts +2 -2
  238. package/dist/secrets/find.js +10 -4
  239. package/dist/secrets/keychain.d.ts +1 -1
  240. package/dist/secrets/linux.js +32 -44
  241. package/dist/secrets/macos.d.ts +1 -2
  242. package/dist/secrets/macos.js +20 -29
  243. package/dist/secrets/rc.d.ts +2 -2
  244. package/dist/secrets/rc.js +21 -13
  245. package/dist/secrets/socket-api-token.js +8 -0
  246. package/dist/secrets/windows.js +27 -33
  247. package/dist/shell/parse.d.ts +32 -0
  248. package/dist/shell/parse.js +60 -0
  249. package/dist/spinner/create-spinner-class.js +2 -2
  250. package/dist/spinner/spinner-internals.d.ts +1 -1
  251. package/dist/spinner/spinner-internals.js +9 -5
  252. package/dist/spinner/spinner.d.ts +4 -0
  253. package/dist/spinner/spinner.js +1 -1
  254. package/dist/stdio/progress.js +5 -1
  255. package/dist/stdio/prompts.d.ts +2 -2
  256. package/dist/stdio/prompts.js +1 -1
  257. package/dist/temporal/instant.js +2 -2
  258. package/dist/url/assert-safe.d.ts +29 -0
  259. package/dist/url/assert-safe.js +54 -0
  260. package/dist/url/predicates.d.ts +31 -1
  261. package/dist/url/predicates.js +42 -1
  262. package/dist/url/types.d.ts +4 -0
  263. 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;
@@ -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.
@@ -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>;
@@ -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;
@@ -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;
@@ -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.full` — `.create` plus Bash, allowlisted to git / pnpm / node.
20
- * Skills that commit, run tests, install deps. No "wide open" tier exists
21
- * by design letting an agent run arbitrary tools is the lockdown rule's
22
- * exact failure mode. The ladder is read edit create full: each
23
- * tier's tool set is a superset of the one above.
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(git add:*)", "Bash(git commit:*)", "Bash(node:*)", "Bash(pnpm exec:*)", "Bash(pnpm run:*)", "Bash(pnpm test:*)"];
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"];
@@ -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
- "Bash(git status:*)",
69
- "Bash(git diff:*)",
70
- "Bash(git log:*)",
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;