@garuda-agent/garuda 0.0.1 → 0.14.1

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 (61) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +4 -0
  4. package/README.md +1040 -0
  5. package/SECURITY.md +32 -0
  6. package/dist/anthropic-NQDBCHJU.js +327 -0
  7. package/dist/chunk-35GMLLJW.js +157 -0
  8. package/dist/chunk-36GQIVGT.js +526 -0
  9. package/dist/chunk-3CEPHS4C.js +231 -0
  10. package/dist/chunk-3NJNVZTK.js +123 -0
  11. package/dist/chunk-42DSA4EA.js +116 -0
  12. package/dist/chunk-4P26OKTP.js +100 -0
  13. package/dist/chunk-5DEWP3YX.js +139 -0
  14. package/dist/chunk-6TWBYMY7.js +9 -0
  15. package/dist/chunk-A2QAIRQL.js +45 -0
  16. package/dist/chunk-ATW7BNIG.js +31 -0
  17. package/dist/chunk-D5O5CIWK.js +1339 -0
  18. package/dist/chunk-EU7PA45O.js +324 -0
  19. package/dist/chunk-FARS4R67.js +206 -0
  20. package/dist/chunk-G2AX7MGS.js +36 -0
  21. package/dist/chunk-HUIK3WXO.js +234 -0
  22. package/dist/chunk-ITITLNAR.js +9341 -0
  23. package/dist/chunk-KKB5W47S.js +231 -0
  24. package/dist/chunk-KWRJREUH.js +283 -0
  25. package/dist/chunk-N4I6YS3E.js +73 -0
  26. package/dist/chunk-OUCV3FCT.js +205 -0
  27. package/dist/chunk-PZS3V6P3.js +46 -0
  28. package/dist/chunk-QOW5TK4L.js +320 -0
  29. package/dist/chunk-U4OQVT2T.js +73 -0
  30. package/dist/chunk-V7WPGQLB.js +207 -0
  31. package/dist/chunk-W7BPYQMW.js +173 -0
  32. package/dist/chunk-WMOLXTBU.js +61 -0
  33. package/dist/chunk-YIZWYUBG.js +138 -0
  34. package/dist/chunk-YM6T4J5V.js +1350 -0
  35. package/dist/chunk-YQTGMCU6.js +111 -0
  36. package/dist/chunk-ZAE25JM2.js +158 -0
  37. package/dist/chunk-ZGZ2ZADL.js +49 -0
  38. package/dist/cli/index.js +1191 -0
  39. package/dist/create-Y5SXJUXO.js +223 -0
  40. package/dist/deadline-F5RJJ2QW.js +86 -0
  41. package/dist/detect-LARDSLLZ.js +10 -0
  42. package/dist/evalCommand-5TG2CKZY.js +2795 -0
  43. package/dist/export-HN3CT7AV.js +158 -0
  44. package/dist/inkChat-3J26R24L.js +1190 -0
  45. package/dist/install-XWLU22OH.js +17 -0
  46. package/dist/job-3NYDMP2M.js +31 -0
  47. package/dist/jobCommand-IYWZWTSI.js +30 -0
  48. package/dist/launchd-2FL5UN2U.js +40 -0
  49. package/dist/lspCommand-TJEZBV2E.js +99 -0
  50. package/dist/manager-4PMSXT47.js +14 -0
  51. package/dist/manager-EBTYO2GR.js +847 -0
  52. package/dist/nightCommand-DUNWJASI.js +247 -0
  53. package/dist/oauth-W6OK6XXO.js +23 -0
  54. package/dist/openaiCompatible-CJWVJP5M.js +501 -0
  55. package/dist/policy-EJPLEEXP.js +31 -0
  56. package/dist/proxy-XJAHCZB2.js +192 -0
  57. package/dist/remove-AENULZZE.js +59 -0
  58. package/dist/run-66Y6R2KU.js +886 -0
  59. package/dist/servers-6YDGWOZ6.js +24 -0
  60. package/dist/text-J2GD647J.js +11 -0
  61. package/package.json +83 -3
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ commandMatches,
4
+ commandParts,
5
+ hostMatches,
6
+ pathMatches
7
+ } from "./chunk-3NJNVZTK.js";
8
+
9
+ // src/permissions/policy.ts
10
+ import { existsSync } from "fs";
11
+ import { readFile } from "fs/promises";
12
+ import { homedir } from "os";
13
+ import { join } from "path";
14
+ import { z } from "zod";
15
+ var POLICY_FILE = join(".garuda", "policy.json");
16
+ function managedPolicyPath(platform = process.platform) {
17
+ if (platform === "darwin") return "/Library/Application Support/Garuda/policy.json";
18
+ if (platform === "linux") return "/etc/garuda/policy.json";
19
+ return void 0;
20
+ }
21
+ function ignoredProjectPolicy(root) {
22
+ const file = join(root, POLICY_FILE);
23
+ return existsSync(file) ? file : void 0;
24
+ }
25
+ var policySchema = z.strictObject({
26
+ disallowedCommands: z.array(z.string()).optional(),
27
+ requireSandbox: z.boolean().optional(),
28
+ denyPaths: z.array(z.string()).optional(),
29
+ allowedModels: z.array(z.string()).optional(),
30
+ network: z.strictObject({
31
+ blockedHosts: z.array(z.string()).optional(),
32
+ strictAllowlist: z.boolean().optional()
33
+ }).optional(),
34
+ limits: z.strictObject({
35
+ maxSteps: z.number().int().positive().optional(),
36
+ tokenBudget: z.number().int().positive().optional()
37
+ }).optional(),
38
+ audit: z.strictObject({
39
+ enabled: z.boolean().optional(),
40
+ level: z.enum(["all", "mutations", "denials"]).optional()
41
+ }).optional()
42
+ });
43
+ function parsePolicy(json) {
44
+ const result = policySchema.safeParse(json);
45
+ if (!result.success) {
46
+ throw new Error(`Invalid policy schema: ${z.prettifyError(result.error)}`);
47
+ }
48
+ const data = result.data;
49
+ return {
50
+ ...data.disallowedCommands === void 0 ? {} : { disallowedCommands: data.disallowedCommands },
51
+ ...data.requireSandbox === void 0 ? {} : { requireSandbox: data.requireSandbox },
52
+ ...data.denyPaths === void 0 ? {} : { denyPaths: data.denyPaths },
53
+ ...data.allowedModels === void 0 ? {} : { allowedModels: data.allowedModels },
54
+ ...data.network === void 0 ? {} : {
55
+ network: {
56
+ ...data.network.blockedHosts === void 0 ? {} : { blockedHosts: data.network.blockedHosts },
57
+ ...data.network.strictAllowlist === void 0 ? {} : { strictAllowlist: data.network.strictAllowlist }
58
+ }
59
+ },
60
+ ...data.limits === void 0 ? {} : {
61
+ limits: {
62
+ ...data.limits.maxSteps === void 0 ? {} : { maxSteps: data.limits.maxSteps },
63
+ ...data.limits.tokenBudget === void 0 ? {} : { tokenBudget: data.limits.tokenBudget }
64
+ }
65
+ },
66
+ ...data.audit === void 0 ? {} : {
67
+ audit: {
68
+ ...data.audit.enabled === void 0 ? {} : { enabled: data.audit.enabled },
69
+ ...data.audit.level === void 0 ? {} : { level: data.audit.level }
70
+ }
71
+ }
72
+ };
73
+ }
74
+ async function readPolicyFile(file) {
75
+ let text;
76
+ try {
77
+ text = await readFile(file, "utf8");
78
+ } catch (error) {
79
+ if (error.code === "ENOENT") return void 0;
80
+ throw new Error(`${file}: ${error.message}`);
81
+ }
82
+ let json;
83
+ try {
84
+ json = JSON.parse(text);
85
+ } catch (error) {
86
+ throw new Error(`${file}: invalid JSON: ${error.message}`);
87
+ }
88
+ try {
89
+ return parsePolicy(json);
90
+ } catch (error) {
91
+ throw new Error(`${file}: ${error.message}`);
92
+ }
93
+ }
94
+ function mergePolicies(user, managed) {
95
+ if (user === void 0) return managed;
96
+ if (managed === void 0) return user;
97
+ const union = (a, b) => a === void 0 && b === void 0 ? void 0 : [.../* @__PURE__ */ new Set([...a ?? [], ...b ?? []])];
98
+ const either = (a, b) => a === void 0 && b === void 0 ? void 0 : a === true || b === true;
99
+ const lower = (a, b) => a === void 0 ? b : b === void 0 ? a : Math.min(a, b);
100
+ const disallowedCommands = union(user.disallowedCommands, managed.disallowedCommands);
101
+ const denyPaths = union(user.denyPaths, managed.denyPaths);
102
+ const requireSandbox = either(user.requireSandbox, managed.requireSandbox);
103
+ const allowedModels = managed.allowedModels ?? user.allowedModels;
104
+ const blockedHosts = union(user.network?.blockedHosts, managed.network?.blockedHosts);
105
+ const strictAllowlist = either(user.network?.strictAllowlist, managed.network?.strictAllowlist);
106
+ const maxSteps = lower(user.limits?.maxSteps, managed.limits?.maxSteps);
107
+ const tokenBudget = lower(user.limits?.tokenBudget, managed.limits?.tokenBudget);
108
+ const audit = managed.audit ?? user.audit;
109
+ return {
110
+ ...disallowedCommands === void 0 ? {} : { disallowedCommands },
111
+ ...requireSandbox === void 0 ? {} : { requireSandbox },
112
+ ...denyPaths === void 0 ? {} : { denyPaths },
113
+ ...allowedModels === void 0 ? {} : { allowedModels },
114
+ ...blockedHosts === void 0 && strictAllowlist === void 0 ? {} : {
115
+ network: {
116
+ ...blockedHosts === void 0 ? {} : { blockedHosts },
117
+ ...strictAllowlist === void 0 ? {} : { strictAllowlist }
118
+ }
119
+ },
120
+ ...maxSteps === void 0 && tokenBudget === void 0 ? {} : {
121
+ limits: {
122
+ ...maxSteps === void 0 ? {} : { maxSteps },
123
+ ...tokenBudget === void 0 ? {} : { tokenBudget }
124
+ }
125
+ },
126
+ ...audit === void 0 ? {} : { audit }
127
+ };
128
+ }
129
+ async function loadTeamPolicy(options = {}) {
130
+ const userFile = join(options.home ?? homedir(), POLICY_FILE);
131
+ const managedFile = "managed" in options ? options.managed : managedPolicyPath();
132
+ const user = await readPolicyFile(userFile);
133
+ const managed = managedFile === void 0 ? void 0 : await readPolicyFile(managedFile);
134
+ const policy = mergePolicies(user, managed);
135
+ if (policy === void 0) return void 0;
136
+ const sources = [
137
+ ...managed === void 0 || managedFile === void 0 ? [] : [managedFile],
138
+ ...user === void 0 ? [] : [userFile]
139
+ ];
140
+ return { policy, sources };
141
+ }
142
+ function isCommandDisallowedByPolicy(policy, command) {
143
+ if (!policy.disallowedCommands || policy.disallowedCommands.length === 0) {
144
+ return { disallowed: false };
145
+ }
146
+ const parts = commandParts(command);
147
+ for (const pattern of policy.disallowedCommands) {
148
+ const hit = (part) => commandMatches(pattern, part);
149
+ if (parts.some(hit) || hit(command)) {
150
+ return {
151
+ disallowed: true,
152
+ pattern,
153
+ reason: `Command is disallowed by team policy: pattern "${pattern}".`
154
+ };
155
+ }
156
+ }
157
+ return { disallowed: false };
158
+ }
159
+ function isSandboxRequiredByPolicy(policy, outsideSandbox) {
160
+ if (policy.requireSandbox === true && outsideSandbox) {
161
+ return {
162
+ disallowed: true,
163
+ reason: "The team policy requires the OS sandbox: this command would run outside it (outside_sandbox, or no sandbox on this machine)."
164
+ };
165
+ }
166
+ return { disallowed: false };
167
+ }
168
+ function isPathDeniedByPolicy(policy, path) {
169
+ if (!policy.denyPaths || policy.denyPaths.length === 0) {
170
+ return { denied: false };
171
+ }
172
+ for (const pattern of policy.denyPaths) {
173
+ if (pathMatches(pattern, path)) {
174
+ return {
175
+ denied: true,
176
+ pattern,
177
+ reason: `Access to path "${path}" is disallowed by team policy: pattern "${pattern}".`
178
+ };
179
+ }
180
+ }
181
+ return { denied: false };
182
+ }
183
+ function isModelAllowedByPolicy(policy, modelId) {
184
+ if (!policy.allowedModels || policy.allowedModels.length === 0) {
185
+ return { allowed: true };
186
+ }
187
+ const allowed = policy.allowedModels.some((pattern) => commandMatches(pattern, modelId));
188
+ if (!allowed) {
189
+ return {
190
+ allowed: false,
191
+ reason: `Model "${modelId}" is not permitted by team policy. Allowed: ${policy.allowedModels.join(", ")}.`
192
+ };
193
+ }
194
+ return { allowed: true };
195
+ }
196
+ function assertModelAllowedByPolicy(policy, modelId) {
197
+ if (policy === void 0) return;
198
+ const decision = isModelAllowedByPolicy(policy, modelId);
199
+ if (!decision.allowed) {
200
+ throw new Error(decision.reason ?? `Model "${modelId}" is not permitted by team policy.`);
201
+ }
202
+ }
203
+ function isHostBlockedByPolicy(policy, host) {
204
+ if (!policy.network?.blockedHosts || policy.network.blockedHosts.length === 0) {
205
+ return { blocked: false };
206
+ }
207
+ const name = host.replace(/^\[|\]$/g, "").replace(/\.$/, "");
208
+ for (const pattern of policy.network.blockedHosts) {
209
+ if (hostMatches(pattern, name)) {
210
+ return {
211
+ blocked: true,
212
+ pattern,
213
+ reason: `Network access to host "${host}" is blocked by team policy: pattern "${pattern}".`
214
+ };
215
+ }
216
+ }
217
+ return { blocked: false };
218
+ }
219
+
220
+ export {
221
+ POLICY_FILE,
222
+ managedPolicyPath,
223
+ ignoredProjectPolicy,
224
+ parsePolicy,
225
+ mergePolicies,
226
+ loadTeamPolicy,
227
+ isCommandDisallowedByPolicy,
228
+ isSandboxRequiredByPolicy,
229
+ isPathDeniedByPolicy,
230
+ isModelAllowedByPolicy,
231
+ assertModelAllowedByPolicy,
232
+ isHostBlockedByPolicy
233
+ };
234
+ //# sourceMappingURL=chunk-HUIK3WXO.js.map