@bookedsolid/reagent 0.1.0 → 0.2.0

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 (107) hide show
  1. package/README.md +322 -50
  2. package/dist/cli/commands/check.d.ts +2 -0
  3. package/dist/cli/commands/check.d.ts.map +1 -0
  4. package/dist/cli/commands/check.js +87 -0
  5. package/dist/cli/commands/check.js.map +1 -0
  6. package/dist/cli/commands/freeze.d.ts +2 -0
  7. package/dist/cli/commands/freeze.d.ts.map +1 -0
  8. package/dist/cli/commands/freeze.js +24 -0
  9. package/dist/cli/commands/freeze.js.map +1 -0
  10. package/dist/cli/commands/init.d.ts +2 -0
  11. package/dist/cli/commands/init.d.ts.map +1 -0
  12. package/dist/cli/commands/init.js +487 -0
  13. package/dist/cli/commands/init.js.map +1 -0
  14. package/dist/cli/commands/serve.d.ts +2 -0
  15. package/dist/cli/commands/serve.d.ts.map +1 -0
  16. package/dist/cli/commands/serve.js +12 -0
  17. package/dist/cli/commands/serve.js.map +1 -0
  18. package/dist/cli/commands/unfreeze.d.ts +2 -0
  19. package/dist/cli/commands/unfreeze.d.ts.map +1 -0
  20. package/dist/cli/commands/unfreeze.js +14 -0
  21. package/dist/cli/commands/unfreeze.js.map +1 -0
  22. package/dist/cli/index.d.ts +3 -0
  23. package/dist/cli/index.d.ts.map +1 -0
  24. package/dist/cli/index.js +71 -0
  25. package/dist/cli/index.js.map +1 -0
  26. package/dist/cli/utils.d.ts +5 -0
  27. package/dist/cli/utils.d.ts.map +1 -0
  28. package/dist/cli/utils.js +34 -0
  29. package/dist/cli/utils.js.map +1 -0
  30. package/dist/config/gateway-config.d.ts +3 -0
  31. package/dist/config/gateway-config.d.ts.map +1 -0
  32. package/dist/config/gateway-config.js +60 -0
  33. package/dist/config/gateway-config.js.map +1 -0
  34. package/dist/config/policy-loader.d.ts +3 -0
  35. package/dist/config/policy-loader.d.ts.map +1 -0
  36. package/dist/config/policy-loader.js +38 -0
  37. package/dist/config/policy-loader.js.map +1 -0
  38. package/dist/config/tier-map.d.ts +12 -0
  39. package/dist/config/tier-map.d.ts.map +1 -0
  40. package/dist/config/tier-map.js +76 -0
  41. package/dist/config/tier-map.js.map +1 -0
  42. package/dist/gateway/client-manager.d.ts +26 -0
  43. package/dist/gateway/client-manager.d.ts.map +1 -0
  44. package/dist/gateway/client-manager.js +75 -0
  45. package/dist/gateway/client-manager.js.map +1 -0
  46. package/dist/gateway/middleware/audit.d.ts +12 -0
  47. package/dist/gateway/middleware/audit.d.ts.map +1 -0
  48. package/dist/gateway/middleware/audit.js +88 -0
  49. package/dist/gateway/middleware/audit.js.map +1 -0
  50. package/dist/gateway/middleware/chain.d.ts +27 -0
  51. package/dist/gateway/middleware/chain.d.ts.map +1 -0
  52. package/dist/gateway/middleware/chain.js +37 -0
  53. package/dist/gateway/middleware/chain.js.map +1 -0
  54. package/dist/gateway/middleware/kill-switch.d.ts +10 -0
  55. package/dist/gateway/middleware/kill-switch.d.ts.map +1 -0
  56. package/dist/gateway/middleware/kill-switch.js +61 -0
  57. package/dist/gateway/middleware/kill-switch.js.map +1 -0
  58. package/dist/gateway/middleware/policy.d.ts +10 -0
  59. package/dist/gateway/middleware/policy.d.ts.map +1 -0
  60. package/dist/gateway/middleware/policy.js +52 -0
  61. package/dist/gateway/middleware/policy.js.map +1 -0
  62. package/dist/gateway/middleware/redact.d.ts +17 -0
  63. package/dist/gateway/middleware/redact.d.ts.map +1 -0
  64. package/dist/gateway/middleware/redact.js +109 -0
  65. package/dist/gateway/middleware/redact.js.map +1 -0
  66. package/dist/gateway/middleware/session.d.ts +11 -0
  67. package/dist/gateway/middleware/session.d.ts.map +1 -0
  68. package/dist/gateway/middleware/session.js +19 -0
  69. package/dist/gateway/middleware/session.js.map +1 -0
  70. package/dist/gateway/middleware/tier.d.ts +7 -0
  71. package/dist/gateway/middleware/tier.d.ts.map +1 -0
  72. package/dist/gateway/middleware/tier.js +11 -0
  73. package/dist/gateway/middleware/tier.js.map +1 -0
  74. package/dist/gateway/server.d.ts +14 -0
  75. package/dist/gateway/server.d.ts.map +1 -0
  76. package/dist/gateway/server.js +79 -0
  77. package/dist/gateway/server.js.map +1 -0
  78. package/dist/gateway/tool-proxy.d.ts +21 -0
  79. package/dist/gateway/tool-proxy.d.ts.map +1 -0
  80. package/dist/gateway/tool-proxy.js +134 -0
  81. package/dist/gateway/tool-proxy.js.map +1 -0
  82. package/dist/types/audit.d.ts +16 -0
  83. package/dist/types/audit.d.ts.map +1 -0
  84. package/dist/types/audit.js +2 -0
  85. package/dist/types/audit.js.map +1 -0
  86. package/dist/types/enums.d.ts +21 -0
  87. package/dist/types/enums.d.ts.map +1 -0
  88. package/dist/types/enums.js +25 -0
  89. package/dist/types/enums.js.map +1 -0
  90. package/dist/types/gateway.d.ts +16 -0
  91. package/dist/types/gateway.d.ts.map +1 -0
  92. package/dist/types/gateway.js +2 -0
  93. package/dist/types/gateway.js.map +1 -0
  94. package/dist/types/index.d.ts +5 -0
  95. package/dist/types/index.d.ts.map +1 -0
  96. package/dist/types/index.js +2 -0
  97. package/dist/types/index.js.map +1 -0
  98. package/dist/types/policy.d.ts +14 -0
  99. package/dist/types/policy.d.ts.map +1 -0
  100. package/dist/types/policy.js +2 -0
  101. package/dist/types/policy.js.map +1 -0
  102. package/hooks/attribution-advisory.sh +78 -26
  103. package/husky/commit-msg.sh +102 -22
  104. package/package.json +24 -12
  105. package/profiles/bst-internal.json +2 -1
  106. package/profiles/client-engagement.json +2 -1
  107. package/bin/init.js +0 -818
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,MAAM,CAAC,EAAE,AAAD,EAAG,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;AAExC,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;IAC/D,SAAS,EAAE,CAAC;IACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,QAAQ,GAAG,EAAE,CAAC;IACZ,KAAK,MAAM;QACT,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,MAAM;IACR,KAAK,OAAO;QACV,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,MAAM;IACR,KAAK,QAAQ;QACX,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM;IACR,KAAK,UAAU;QACb,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,MAAM;IACR,KAAK,OAAO;QACV,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM;IACR;QACE,OAAO,CAAC,KAAK,CAAC,sBAAsB,GAAG,EAAE,CAAC,CAAC;QAC3C,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,SAAS;IAChB,MAAM,WAAW,GAAG,aAAa,EAAE,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC;wBACU,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgClC,CAAC,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const PKG_ROOT: string;
2
+ export declare function getPkgVersion(): string;
3
+ export declare function parseFlag(args: string[], flag: string): string | null;
4
+ export declare function gitignoreHasEntry(targetDir: string, entry: string): boolean;
5
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/cli/utils.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,QAAQ,QAAmC,CAAC;AAEzD,wBAAgB,aAAa,IAAI,MAAM,CAQtC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQrE;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAK3E"}
@@ -0,0 +1,34 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ const __filename = fileURLToPath(import.meta.url);
5
+ const __dirname = path.dirname(__filename);
6
+ export const PKG_ROOT = path.join(__dirname, '..', '..');
7
+ export function getPkgVersion() {
8
+ try {
9
+ const pkgPath = path.join(PKG_ROOT, 'package.json');
10
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
11
+ return pkg.version;
12
+ }
13
+ catch {
14
+ return '0.0.0';
15
+ }
16
+ }
17
+ export function parseFlag(args, flag) {
18
+ const eqForm = args.find((a) => a.startsWith(`${flag}=`));
19
+ if (eqForm)
20
+ return eqForm.split('=').slice(1).join('=');
21
+ const idx = args.indexOf(flag);
22
+ if (idx !== -1 && args[idx + 1] && !args[idx + 1].startsWith('--')) {
23
+ return args[idx + 1];
24
+ }
25
+ return null;
26
+ }
27
+ export function gitignoreHasEntry(targetDir, entry) {
28
+ const gitignorePath = path.join(targetDir, '.gitignore');
29
+ if (!fs.existsSync(gitignorePath))
30
+ return false;
31
+ const content = fs.readFileSync(gitignorePath, 'utf8');
32
+ return content.split('\n').some((line) => line.trim() === entry.trim());
33
+ }
34
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/cli/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEzD,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QACzD,OAAO,GAAG,CAAC,OAAO,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAc,EAAE,IAAY;IACpD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC;IAC1D,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACnE,OAAO,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAiB,EAAE,KAAa;IAChE,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACzD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,KAAK,CAAC;IAChD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACvD,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { GatewayConfig } from '../types/index.js';
2
+ export declare function loadGatewayConfig(baseDir: string): GatewayConfig;
3
+ //# sourceMappingURL=gateway-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-config.d.ts","sourceRoot":"","sources":["../../src/config/gateway-config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAgCvD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAmChE"}
@@ -0,0 +1,60 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { parse as parseYaml } from 'yaml';
4
+ import { z } from 'zod';
5
+ import { Tier } from '../types/index.js';
6
+ const ToolOverrideSchema = z.object({
7
+ tier: z.nativeEnum(Tier).optional(),
8
+ blocked: z.boolean().optional(),
9
+ });
10
+ const DownstreamServerSchema = z.object({
11
+ command: z.string(),
12
+ args: z.array(z.string()).default([]),
13
+ env: z.record(z.string()).optional(),
14
+ tool_overrides: z.record(ToolOverrideSchema).optional(),
15
+ });
16
+ const GatewayConfigSchema = z.object({
17
+ version: z.string(),
18
+ servers: z.record(DownstreamServerSchema),
19
+ });
20
+ /**
21
+ * Resolve `${ENV_VAR}` references in string values.
22
+ */
23
+ function resolveEnvVars(obj) {
24
+ const resolved = {};
25
+ for (const [key, value] of Object.entries(obj)) {
26
+ resolved[key] = value.replace(/\$\{([^}]+)\}/g, (_match, varName) => {
27
+ return process.env[varName] ?? '';
28
+ });
29
+ }
30
+ return resolved;
31
+ }
32
+ export function loadGatewayConfig(baseDir) {
33
+ const configPath = path.join(baseDir, '.reagent', 'gateway.yaml');
34
+ if (!fs.existsSync(configPath)) {
35
+ throw new Error(`Gateway config not found: ${configPath}`);
36
+ }
37
+ const raw = fs.readFileSync(configPath, 'utf8');
38
+ let parsed;
39
+ try {
40
+ parsed = parseYaml(raw);
41
+ }
42
+ catch (yamlErr) {
43
+ throw new Error(`Failed to parse gateway YAML at ${configPath}: ${yamlErr instanceof Error ? yamlErr.message : yamlErr}`);
44
+ }
45
+ let config;
46
+ try {
47
+ config = GatewayConfigSchema.parse(parsed);
48
+ }
49
+ catch (zodErr) {
50
+ throw new Error(`Invalid gateway config schema at ${configPath}: ${zodErr instanceof Error ? zodErr.message : zodErr}`);
51
+ }
52
+ // Resolve env vars in server env blocks
53
+ for (const server of Object.values(config.servers)) {
54
+ if (server.env) {
55
+ server.env = resolveEnvVars(server.env);
56
+ }
57
+ }
58
+ return config;
59
+ }
60
+ //# sourceMappingURL=gateway-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-config.js","sourceRoot":"","sources":["../../src/config/gateway-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Policy } from '../types/index.js';
2
+ export declare function loadPolicy(baseDir: string): Policy;
3
+ //# sourceMappingURL=policy-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-loader.d.ts","sourceRoot":"","sources":["../../src/config/policy-loader.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAehD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAyBlD"}
@@ -0,0 +1,38 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { parse as parseYaml } from 'yaml';
4
+ import { z } from 'zod';
5
+ import { AutonomyLevel } from '../types/index.js';
6
+ const PolicySchema = z.object({
7
+ version: z.string(),
8
+ profile: z.string(),
9
+ installed_by: z.string(),
10
+ installed_at: z.string(),
11
+ autonomy_level: z.nativeEnum(AutonomyLevel),
12
+ max_autonomy_level: z.nativeEnum(AutonomyLevel),
13
+ promotion_requires_human_approval: z.boolean(),
14
+ block_ai_attribution: z.boolean().default(false),
15
+ blocked_paths: z.array(z.string()),
16
+ notification_channel: z.string().default(''),
17
+ });
18
+ export function loadPolicy(baseDir) {
19
+ const policyPath = path.join(baseDir, '.reagent', 'policy.yaml');
20
+ if (!fs.existsSync(policyPath)) {
21
+ throw new Error(`Policy file not found: ${policyPath}`);
22
+ }
23
+ const raw = fs.readFileSync(policyPath, 'utf8');
24
+ let parsed;
25
+ try {
26
+ parsed = parseYaml(raw);
27
+ }
28
+ catch (yamlErr) {
29
+ throw new Error(`Failed to parse policy YAML at ${policyPath}: ${yamlErr instanceof Error ? yamlErr.message : yamlErr}`);
30
+ }
31
+ try {
32
+ return PolicySchema.parse(parsed);
33
+ }
34
+ catch (zodErr) {
35
+ throw new Error(`Invalid policy schema at ${policyPath}: ${zodErr instanceof Error ? zodErr.message : zodErr}`);
36
+ }
37
+ }
38
+ //# sourceMappingURL=policy-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-loader.js","sourceRoot":"","sources":["../../src/config/policy-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,cAAc,EAAE,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC;IAC3C,kBAAkB,EAAE,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC;IAC/C,iCAAiC,EAAE,CAAC,CAAC,OAAO,EAAE;IAC9C,oBAAoB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IAChD,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAClC,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CAC7C,CAAC,CAAC;AAEH,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IAEjE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,0BAA0B,UAAU,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAEhD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,OAAO,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,kCAAkC,UAAU,KAAK,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,CACxG,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,4BAA4B,UAAU,KAAK,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAC/F,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { Tier } from '../types/index.js';
2
+ import type { GatewayConfig } from '../types/index.js';
3
+ /**
4
+ * Classify a tool by its tier. Checks gateway config overrides first,
5
+ * then static map, then defaults to Write.
6
+ */
7
+ export declare function classifyTool(toolName: string, serverName: string, gatewayConfig?: GatewayConfig): Tier;
8
+ /**
9
+ * Check if a tool is explicitly blocked in gateway config.
10
+ */
11
+ export declare function isToolBlocked(toolName: string, serverName: string, gatewayConfig?: GatewayConfig): boolean;
12
+ //# sourceMappingURL=tier-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier-map.d.ts","sourceRoot":"","sources":["../../src/config/tier-map.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAwDvD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,aAAa,GAC5B,IAAI,CAYN;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAIT"}
@@ -0,0 +1,76 @@
1
+ import { Tier } from '../types/index.js';
2
+ /**
3
+ * Static tier classifications for known tool patterns.
4
+ * Tools not in this map default to Tier.Write (safe default).
5
+ */
6
+ const STATIC_TIER_MAP = {
7
+ // Read-tier tools (safe, no side effects)
8
+ get_messages: Tier.Read,
9
+ get_channel: Tier.Read,
10
+ get_guild: Tier.Read,
11
+ get_member: Tier.Read,
12
+ get_webhook: Tier.Read,
13
+ list_channels: Tier.Read,
14
+ list_guilds: Tier.Read,
15
+ list_members: Tier.Read,
16
+ list_roles: Tier.Read,
17
+ list_threads: Tier.Read,
18
+ list_webhooks: Tier.Read,
19
+ list_projects: Tier.Read,
20
+ search_messages: Tier.Read,
21
+ query_audit_log: Tier.Read,
22
+ health_check: Tier.Read,
23
+ // Write-tier tools (create or modify)
24
+ send_message: Tier.Write,
25
+ send_embed: Tier.Write,
26
+ edit_message: Tier.Write,
27
+ add_reaction: Tier.Write,
28
+ create_thread: Tier.Write,
29
+ create_channel: Tier.Write,
30
+ create_role: Tier.Write,
31
+ create_invite: Tier.Write,
32
+ create_webhook: Tier.Write,
33
+ execute_webhook: Tier.Write,
34
+ edit_channel: Tier.Write,
35
+ edit_role: Tier.Write,
36
+ edit_webhook: Tier.Write,
37
+ set_slowmode: Tier.Write,
38
+ set_permissions: Tier.Write,
39
+ assign_role: Tier.Write,
40
+ move_channel: Tier.Write,
41
+ archive_thread: Tier.Write,
42
+ timeout_member: Tier.Write,
43
+ // Destructive-tier tools (irreversible or high-impact)
44
+ delete_message: Tier.Destructive,
45
+ delete_channel: Tier.Destructive,
46
+ delete_role: Tier.Destructive,
47
+ delete_webhook: Tier.Destructive,
48
+ purge_messages: Tier.Destructive,
49
+ ban_member: Tier.Destructive,
50
+ unban_member: Tier.Destructive,
51
+ kick_member: Tier.Destructive,
52
+ };
53
+ /**
54
+ * Classify a tool by its tier. Checks gateway config overrides first,
55
+ * then static map, then defaults to Write.
56
+ */
57
+ export function classifyTool(toolName, serverName, gatewayConfig) {
58
+ // Check per-server overrides in gateway config
59
+ const serverConfig = gatewayConfig?.servers[serverName];
60
+ const override = serverConfig?.tool_overrides?.[toolName];
61
+ if (override?.tier) {
62
+ return override.tier;
63
+ }
64
+ // Strip server prefix for static lookup (e.g., "discord-ops__send_message" -> "send_message")
65
+ const baseName = toolName.includes('__') ? toolName.split('__').pop() : toolName;
66
+ return STATIC_TIER_MAP[baseName] ?? Tier.Write;
67
+ }
68
+ /**
69
+ * Check if a tool is explicitly blocked in gateway config.
70
+ */
71
+ export function isToolBlocked(toolName, serverName, gatewayConfig) {
72
+ const serverConfig = gatewayConfig?.servers[serverName];
73
+ const override = serverConfig?.tool_overrides?.[toolName];
74
+ return override?.blocked === true;
75
+ }
76
+ //# sourceMappingURL=tier-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier-map.js","sourceRoot":"","sources":["../../src/config/tier-map.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
3
+ import type { GatewayConfig, DownstreamServer } from '../types/index.js';
4
+ export interface ManagedClient {
5
+ name: string;
6
+ client: Client;
7
+ transport: StdioClientTransport;
8
+ config: DownstreamServer;
9
+ }
10
+ /**
11
+ * Manages lifecycle of downstream MCP server connections.
12
+ * Spawns each server as a child process via StdioClientTransport.
13
+ */
14
+ export declare class ClientManager {
15
+ private clients;
16
+ private connectTimeoutMs;
17
+ constructor(options?: {
18
+ connectTimeoutMs?: number;
19
+ });
20
+ connectAll(gatewayConfig: GatewayConfig): Promise<Map<string, ManagedClient>>;
21
+ private connect;
22
+ getClient(name: string): ManagedClient | undefined;
23
+ getAllClients(): Map<string, ManagedClient>;
24
+ disconnectAll(): Promise<void>;
25
+ }
26
+ //# sourceMappingURL=client-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-manager.d.ts","sourceRoot":"","sources":["../../src/gateway/client-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGzE,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,oBAAoB,CAAC;IAChC,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAcD;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,gBAAgB,CAAS;gBAErB,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE;IAI7C,UAAU,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YAmBrE,OAAO;IA2BrB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIlD,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC;IAIrC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAcrC"}
@@ -0,0 +1,75 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
3
+ import { getPkgVersion } from '../cli/utils.js';
4
+ /**
5
+ * Build a clean env record: merge process.env (filtering out undefined) with config env.
6
+ */
7
+ function buildEnv(configEnv) {
8
+ const base = {};
9
+ for (const [k, v] of Object.entries(process.env)) {
10
+ if (v !== undefined)
11
+ base[k] = v;
12
+ }
13
+ if (configEnv)
14
+ Object.assign(base, configEnv);
15
+ return base;
16
+ }
17
+ /**
18
+ * Manages lifecycle of downstream MCP server connections.
19
+ * Spawns each server as a child process via StdioClientTransport.
20
+ */
21
+ export class ClientManager {
22
+ clients = new Map();
23
+ connectTimeoutMs;
24
+ constructor(options) {
25
+ this.connectTimeoutMs = options?.connectTimeoutMs ?? 30_000;
26
+ }
27
+ async connectAll(gatewayConfig) {
28
+ const entries = Object.entries(gatewayConfig.servers);
29
+ for (const [name, serverConfig] of entries) {
30
+ try {
31
+ const managed = await this.connect(name, serverConfig);
32
+ this.clients.set(name, managed);
33
+ console.error(`[reagent] Connected to downstream: ${name}`);
34
+ }
35
+ catch (err) {
36
+ console.error(`[reagent] Failed to connect to downstream "${name}":`, err instanceof Error ? err.message : err);
37
+ }
38
+ }
39
+ return this.clients;
40
+ }
41
+ async connect(name, config) {
42
+ const transport = new StdioClientTransport({
43
+ command: config.command,
44
+ args: config.args,
45
+ env: buildEnv(config.env),
46
+ });
47
+ const client = new Client({ name: `reagent-proxy-${name}`, version: getPkgVersion() }, { capabilities: {} });
48
+ // H3: Timeout for downstream server connections
49
+ const connectPromise = client.connect(transport);
50
+ const timeoutPromise = new Promise((_, reject) => {
51
+ setTimeout(() => reject(new Error(`Connection to "${name}" timed out after ${this.connectTimeoutMs}ms`)), this.connectTimeoutMs);
52
+ });
53
+ await Promise.race([connectPromise, timeoutPromise]);
54
+ return { name, client, transport, config };
55
+ }
56
+ getClient(name) {
57
+ return this.clients.get(name);
58
+ }
59
+ getAllClients() {
60
+ return this.clients;
61
+ }
62
+ async disconnectAll() {
63
+ for (const [name, managed] of this.clients) {
64
+ try {
65
+ await managed.client.close();
66
+ console.error(`[reagent] Disconnected from: ${name}`);
67
+ }
68
+ catch (err) {
69
+ console.error(`[reagent] Error disconnecting "${name}":`, err instanceof Error ? err.message : err);
70
+ }
71
+ }
72
+ this.clients.clear();
73
+ }
74
+ }
75
+ //# sourceMappingURL=client-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-manager.js","sourceRoot":"","sources":["../../src/gateway/client-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { Middleware } from './chain.js';
2
+ /**
3
+ * Post-execution middleware: appends a hash-chained JSONL audit record.
4
+ *
5
+ * SECURITY: Each audit middleware instance maintains its own hash chain.
6
+ * SECURITY: Audit write failures are logged to stderr but do NOT crash the gateway.
7
+ * SECURITY: Wraps next() in try/finally to ensure audit runs even on middleware exceptions.
8
+ * SECURITY: Placed as outermost middleware so audit records ALL invocations, including denials.
9
+ * PERFORMANCE: All fs operations are async to avoid blocking the event loop.
10
+ */
11
+ export declare function createAuditMiddleware(baseDir: string): Middleware;
12
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/gateway/middleware/audit.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAO7C;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CA+EjE"}
@@ -0,0 +1,88 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import crypto from 'node:crypto';
4
+ import { Tier, InvocationStatus } from '../../types/index.js';
5
+ function computeHash(record) {
6
+ const payload = JSON.stringify(record);
7
+ return crypto.createHash('sha256').update(payload).digest('hex');
8
+ }
9
+ /**
10
+ * Post-execution middleware: appends a hash-chained JSONL audit record.
11
+ *
12
+ * SECURITY: Each audit middleware instance maintains its own hash chain.
13
+ * SECURITY: Audit write failures are logged to stderr but do NOT crash the gateway.
14
+ * SECURITY: Wraps next() in try/finally to ensure audit runs even on middleware exceptions.
15
+ * SECURITY: Placed as outermost middleware so audit records ALL invocations, including denials.
16
+ * PERFORMANCE: All fs operations are async to avoid blocking the event loop.
17
+ */
18
+ export function createAuditMiddleware(baseDir) {
19
+ const auditDir = path.join(baseDir, '.reagent', 'audit');
20
+ let prevHash = '0000000000000000000000000000000000000000000000000000000000000000';
21
+ let dirEnsured = false;
22
+ return async (ctx, next) => {
23
+ let nextError;
24
+ try {
25
+ await next();
26
+ }
27
+ catch (err) {
28
+ // Capture the error but still write the audit record
29
+ nextError = err instanceof Error ? err : new Error(String(err));
30
+ ctx.status = InvocationStatus.Error;
31
+ ctx.error = nextError.message;
32
+ }
33
+ // Build audit record — always runs, even after exceptions
34
+ try {
35
+ const duration_ms = Date.now() - ctx.start_time;
36
+ const now = new Date().toISOString();
37
+ const date = now.slice(0, 10); // YYYY-MM-DD
38
+ const recordBase = {
39
+ timestamp: now,
40
+ session_id: ctx.session_id,
41
+ tool_name: ctx.tool_name,
42
+ server_name: ctx.server_name,
43
+ tier: ctx.tier ?? Tier.Write,
44
+ status: ctx.status,
45
+ autonomy_level: ctx.metadata.autonomy_level ?? 'unknown',
46
+ duration_ms,
47
+ prev_hash: prevHash,
48
+ };
49
+ if (ctx.error) {
50
+ recordBase.error = ctx.error;
51
+ }
52
+ if (ctx.redacted_fields?.length) {
53
+ recordBase.redacted_fields = ctx.redacted_fields;
54
+ }
55
+ const hash = computeHash(recordBase);
56
+ const record = { ...recordBase, hash };
57
+ prevHash = hash;
58
+ const filePath = path.join(auditDir, `${date}.jsonl`);
59
+ const line = JSON.stringify(record) + '\n';
60
+ // Ensure audit dir exists (cached, with retry on failure)
61
+ if (!dirEnsured) {
62
+ await fs.mkdir(auditDir, { recursive: true });
63
+ dirEnsured = true;
64
+ }
65
+ try {
66
+ await fs.appendFile(filePath, line);
67
+ }
68
+ catch {
69
+ // Directory may have been deleted externally — retry once with mkdir
70
+ dirEnsured = false;
71
+ await fs.mkdir(auditDir, { recursive: true });
72
+ dirEnsured = true;
73
+ await fs.appendFile(filePath, line);
74
+ }
75
+ }
76
+ catch (auditErr) {
77
+ // SECURITY: Never crash the gateway on audit failure — log to stderr
78
+ // Reset dirEnsured in case the mkdir was the thing that failed
79
+ dirEnsured = false;
80
+ console.error('[reagent] AUDIT WRITE FAILED:', auditErr instanceof Error ? auditErr.message : auditErr);
81
+ }
82
+ // Re-throw the original error if next() failed
83
+ if (nextError) {
84
+ throw nextError;
85
+ }
86
+ };
87
+ }
88
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/gateway/middleware/audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { Tier } from '../../types/index.js';
2
+ import { InvocationStatus } from '../../types/index.js';
3
+ export interface InvocationContext {
4
+ tool_name: string;
5
+ server_name: string;
6
+ arguments: Record<string, unknown>;
7
+ session_id: string;
8
+ tier?: Tier;
9
+ status: InvocationStatus;
10
+ error?: string;
11
+ result?: unknown;
12
+ start_time: number;
13
+ redacted_fields?: string[];
14
+ metadata: Record<string, unknown>;
15
+ }
16
+ export type NextFn = () => Promise<void>;
17
+ export type Middleware = (ctx: InvocationContext, next: NextFn) => Promise<void>;
18
+ /**
19
+ * Execute a middleware chain in onion (koa-style) order.
20
+ * Each middleware calls `next()` to pass control to the next one.
21
+ * The innermost middleware is the actual tool execution.
22
+ *
23
+ * SECURITY: Once status is set to Denied, it is locked for the remainder
24
+ * of the chain. No middleware can revert a denial.
25
+ */
26
+ export declare function executeChain(middlewares: Middleware[], ctx: InvocationContext): Promise<void>;
27
+ //# sourceMappingURL=chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.d.ts","sourceRoot":"","sources":["../../../src/gateway/middleware/chain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEjF;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+B7F"}
@@ -0,0 +1,37 @@
1
+ import { InvocationStatus } from '../../types/index.js';
2
+ /**
3
+ * Execute a middleware chain in onion (koa-style) order.
4
+ * Each middleware calls `next()` to pass control to the next one.
5
+ * The innermost middleware is the actual tool execution.
6
+ *
7
+ * SECURITY: Once status is set to Denied, it is locked for the remainder
8
+ * of the chain. No middleware can revert a denial.
9
+ */
10
+ export function executeChain(middlewares, ctx) {
11
+ let index = -1;
12
+ let deniedOnce = false;
13
+ let savedError;
14
+ function dispatch(i) {
15
+ if (i <= index) {
16
+ return Promise.reject(new Error('next() called multiple times'));
17
+ }
18
+ index = i;
19
+ const mw = middlewares[i];
20
+ if (!mw) {
21
+ return Promise.resolve();
22
+ }
23
+ return Promise.resolve(mw(ctx, () => dispatch(i + 1))).then(() => {
24
+ // SECURITY: If any middleware ever set Denied, lock it permanently
25
+ if (ctx.status === InvocationStatus.Denied && !deniedOnce) {
26
+ deniedOnce = true;
27
+ savedError = ctx.error;
28
+ }
29
+ if (deniedOnce && ctx.status !== InvocationStatus.Denied) {
30
+ ctx.status = InvocationStatus.Denied;
31
+ ctx.error = savedError || 'Denial status was tampered with — re-locked';
32
+ }
33
+ });
34
+ }
35
+ return dispatch(0);
36
+ }
37
+ //# sourceMappingURL=chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.js","sourceRoot":"","sources":["../../../src/gateway/middleware/chain.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAmBxD;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,WAAyB,EAAE,GAAsB;IAC5E,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;IACf,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,UAA8B,CAAC;IAEnC,SAAS,QAAQ,CAAC,CAAS;QACzB,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;YACf,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,KAAK,GAAG,CAAC,CAAC;QAEV,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3B,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YAC/D,mEAAmE;YACnE,IAAI,GAAG,CAAC,MAAM,KAAK,gBAAgB,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;gBAC1D,UAAU,GAAG,IAAI,CAAC;gBAClB,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC;YACzB,CAAC;YAED,IAAI,UAAU,IAAI,GAAG,CAAC,MAAM,KAAK,gBAAgB,CAAC,MAAM,EAAE,CAAC;gBACzD,GAAG,CAAC,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;gBACrC,GAAG,CAAC,KAAK,GAAG,UAAU,IAAI,6CAA6C,CAAC;YAC1E,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;AACrB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Middleware } from './chain.js';
2
+ /**
3
+ * Checks for `.reagent/HALT` file. If present, denies the invocation.
4
+ *
5
+ * SECURITY: Validates HALT is a regular file (not directory/symlink to sensitive file).
6
+ * SECURITY: Caps read size to prevent oversized error strings.
7
+ * PERFORMANCE: All fs operations are async to avoid blocking the event loop.
8
+ */
9
+ export declare function createKillSwitchMiddleware(baseDir: string): Middleware;
10
+ //# sourceMappingURL=kill-switch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kill-switch.d.ts","sourceRoot":"","sources":["../../../src/gateway/middleware/kill-switch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAiDtE"}