@flue/client 0.0.21 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -69,10 +69,23 @@ const summary = await flue.prompt('Summarize these test failures: ...', {
69
69
 
70
70
  Options: `result`, `model`
71
71
 
72
- ### Properties
72
+ ## Proxies (Sandbox Mode)
73
73
 
74
- | Property | Type | Description |
75
- | -------------- | ------------------------- | --------------------------------------- |
76
- | `flue.args` | `Record<string, unknown>` | Workflow arguments passed by the runner |
77
- | `flue.secrets` | `Record<string, string>` | Scoped secrets passed by the runner |
78
- | `flue.branch` | `string` | Working branch for commits |
74
+ In sandbox mode, the AI agent runs inside a sandbox container with no access to sensitive host credentials. Proxies let the sandbox talk to external services without leaking any actual credentials into the sandbox.
75
+
76
+ Flue ships with built-in presets for popular services. Every proxy supports an access control policy (`policy`) option for advanced control over what the sandbox has access to do. Built-in levels like `'allow-read'` and `'allow-all'` cover common service-specific policy rules, and you can extend them with explicit allow/deny rules for fine-grained control:
77
+
78
+ ```ts
79
+ import { anthropic, github } from '@flue/client/proxies';
80
+
81
+ export const proxies = [
82
+ anthropic(),
83
+ github({
84
+ token: process.env.GH_TOKEN!,
85
+ policy: {
86
+ base: 'allow-read',
87
+ allow: [{ method: 'POST', path: '/repos/withastro/astro/issues/*/comments', limit: 1 }],
88
+ },
89
+ }),
90
+ ];
91
+ ```
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as ProxyService, n as ProxyPolicy, r as ProxyPresetResult, t as PolicyRule } from "./types-Ch4cwdD8.mjs";
1
+ import { i as ProxyService, n as ProxyPolicy, r as ProxyPresetResult, t as PolicyRule } from "./types-37Tgp-H9.mjs";
2
2
  import * as v from "valibot";
3
3
 
4
4
  //#region src/errors.d.ts
@@ -1,4 +1,4 @@
1
- import { i as ProxyService, n as ProxyPolicy, r as ProxyPresetResult, t as PolicyRule } from "../types-Ch4cwdD8.mjs";
1
+ import { i as ProxyService, n as ProxyPolicy, r as ProxyPresetResult, t as PolicyRule } from "../types-37Tgp-H9.mjs";
2
2
 
3
3
  //#region src/proxies/anthropic.d.ts
4
4
  /**
@@ -10,6 +10,7 @@ import { i as ProxyService, n as ProxyPolicy, r as ProxyPresetResult, t as Polic
10
10
  */
11
11
  declare function anthropic(opts?: {
12
12
  apiKey?: string;
13
+ policy?: string | ProxyPolicy;
13
14
  }): ProxyService;
14
15
  //#endregion
15
16
  //#region src/proxies/github.d.ts
@@ -26,7 +26,7 @@ function anthropic(opts) {
26
26
  filtered["x-api-key"] = apiKey;
27
27
  return { headers: filtered };
28
28
  },
29
- policy: "allow-all",
29
+ policy: opts?.policy ?? "allow-all",
30
30
  isModelProvider: true,
31
31
  providerConfig: {
32
32
  providerKey: "anthropic",
@@ -49,7 +49,7 @@ function anthropic(opts) {
49
49
  * Both share the same token and policy.
50
50
  */
51
51
  function github(opts) {
52
- const resolvedPolicy = resolveGitHubPolicy(opts.policy ?? "read-only");
52
+ const resolvedPolicy = resolveGitHubPolicy(opts.policy);
53
53
  const denyResponse = ({ method, path, reason }) => ({
54
54
  status: 403,
55
55
  headers: { "Content-Type": "application/json" },
@@ -85,29 +85,46 @@ function github(opts) {
85
85
  }];
86
86
  }
87
87
  /**
88
- * Resolve GitHub-specific policy level names to concrete ProxyPolicy rules.
88
+ * Resolve a GitHub policy into a concrete ProxyPolicy.
89
89
  *
90
- * Levels:
91
- * - 'read-only': GET/HEAD only (default)
92
- * - 'read-only+clone': GET/HEAD + git smart HTTP fetch (clone/pull)
93
- * - 'allow-all': everything allowed
90
+ * Accepts a core policy level string ('allow-read', 'allow-all', 'deny-all')
91
+ * or a ProxyPolicy object. Defaults to 'allow-read' if omitted.
92
+ *
93
+ * When the base is 'allow-read', GitHub-specific allow rules are prepended
94
+ * so that the gh CLI (GraphQL queries) and git clone/fetch work out of the box.
95
+ * Other base levels are used as-is.
94
96
  */
95
97
  function resolveGitHubPolicy(policy) {
96
- if (typeof policy !== "string") return policy;
97
- switch (policy) {
98
- case "read-only": return { default: "deny-non-safe" };
99
- case "read-only+clone": return {
100
- default: "deny-non-safe",
101
- allow: [{
102
- method: "POST",
103
- path: "/*/git-upload-pack"
104
- }, {
105
- method: "GET",
106
- path: "/*/info/refs"
107
- }]
98
+ const base = typeof policy === "string" ? policy : policy?.base ?? "allow-read";
99
+ const userAllow = typeof policy === "object" ? policy.allow ?? [] : [];
100
+ const userDeny = typeof policy === "object" ? policy.deny ?? [] : [];
101
+ switch (base) {
102
+ case "allow-all":
103
+ case "deny-all": return {
104
+ base,
105
+ allow: userAllow,
106
+ deny: userDeny
107
+ };
108
+ default: return {
109
+ base: "allow-read",
110
+ allow: [
111
+ {
112
+ method: "POST",
113
+ path: "/graphql",
114
+ body: githubBody.graphql()
115
+ },
116
+ {
117
+ method: "POST",
118
+ path: "/*/git-upload-pack"
119
+ },
120
+ {
121
+ method: "GET",
122
+ path: "/*/info/refs"
123
+ },
124
+ ...userAllow
125
+ ],
126
+ deny: userDeny
108
127
  };
109
- case "allow-all": return { default: "allow-all" };
110
- default: throw new Error(`Unknown github() policy level: '${policy}'`);
111
128
  }
112
129
  }
113
130
  /**
@@ -63,14 +63,14 @@ interface ProxyService {
63
63
  /**
64
64
  * Access control policy for this proxy.
65
65
  *
66
- * String shorthand: a named policy level defined by the preset.
67
- * Object form: full control with default level + allow/deny rules.
66
+ * String shorthand: a core policy level ('allow-read', 'allow-all', 'deny-all').
67
+ * Object form: full control with base level + allow/deny rules.
68
68
  *
69
- * When a string is provided, it is equivalent to { default: theString }.
69
+ * When a string is provided, it is equivalent to { base: theString }.
70
70
  *
71
- * If omitted, defaults to 'read-only' (GET/HEAD only).
72
- * Each preset defines what its policy levels mean see the preset
73
- * documentation for available levels.
71
+ * If omitted, defaults to 'allow-read' (GET/HEAD/OPTIONS only).
72
+ * Presets may extend the base level with additional allow rules
73
+ * appropriate for their service.
74
74
  */
75
75
  policy?: string | ProxyPolicy;
76
76
  /**
@@ -108,16 +108,22 @@ interface ProxyService {
108
108
  }
109
109
  interface ProxyPolicy {
110
110
  /**
111
- * The base policy level. Preset-defined string that maps to a set of rules.
112
- * Common levels: 'read-only', 'allow-all', 'deny-all'.
113
- * Presets may define additional levels (e.g., 'read-only+clone' for GitHub).
111
+ * The base policy level that applies when no allow/deny rule matches.
112
+ *
113
+ * - `'allow-read'`: allow GET/HEAD/OPTIONS, deny everything else
114
+ * - `'allow-all'`: allow everything
115
+ * - `'deny-all'`: deny everything
116
+ *
117
+ * Presets may extend the base level with additional allow rules
118
+ * (e.g., the GitHub preset adds GraphQL query and git clone support
119
+ * on top of `'allow-read'`).
114
120
  */
115
- default: string;
121
+ base: string;
116
122
  /**
117
123
  * Explicit allow rules. Evaluated after deny rules.
118
124
  * A request matching an allow rule is permitted (subject to rate limits).
119
125
  * If a request matches method + path but fails body validation, the rule
120
- * does not match and evaluation continues to the next rule or default.
126
+ * does not match and evaluation continues to the next rule or base level.
121
127
  */
122
128
  allow?: PolicyRule[];
123
129
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flue/client",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "exports": {