@sweny-ai/core 0.1.125 → 0.1.126
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/dist/agent-env.d.ts +37 -0
- package/dist/agent-env.js +125 -0
- package/dist/claude.d.ts +2 -3
- package/dist/claude.js +4 -9
- package/package.json +1 -1
package/dist/agent-env.d.ts
CHANGED
|
@@ -58,11 +58,48 @@ export interface BuildAgentEnvOpts {
|
|
|
58
58
|
export declare function resolveEnvScope(env: Record<string, string | undefined>, explicit?: boolean, logger?: Pick<Logger, "warn">): boolean;
|
|
59
59
|
/** Max names listed in the withheld-vars warning before "and N more". */
|
|
60
60
|
export declare const WITHHELD_WARNING_CAP = 30;
|
|
61
|
+
/**
|
|
62
|
+
* Runner baseline: exact names set by common CI images (GitHub-hosted runner
|
|
63
|
+
* image, Actions runner context, Debian-based containers). They are present on
|
|
64
|
+
* every run, so listing them as "withheld" is noise. Names only; none of these
|
|
65
|
+
* is a credential the operator supplied. Secrets such as `GITHUB_TOKEN`,
|
|
66
|
+
* `NPM_TOKEN`, or `AWS_*` are deliberately absent, so withholding them still
|
|
67
|
+
* warns.
|
|
68
|
+
*/
|
|
69
|
+
export declare const RUNNER_BASELINE_VARS: ReadonlySet<string>;
|
|
70
|
+
/**
|
|
71
|
+
* Runner baseline: name patterns for families the CI images set in bulk
|
|
72
|
+
* (Actions runner internals, Android/Java/.NET/Go/Python toolchains, browsers
|
|
73
|
+
* and webdrivers, Azure CLI, vcpkg, ghcup, ...). `AWS_*`, `NPM_*` and
|
|
74
|
+
* `GITHUB_TOKEN`-style names are intentionally not matched.
|
|
75
|
+
*/
|
|
76
|
+
export declare const RUNNER_BASELINE_PATTERNS: readonly RegExp[];
|
|
77
|
+
/** True when `name` is set by the CI image itself, not by the workflow author. */
|
|
78
|
+
export declare function isRunnerBaselineVar(name: string): boolean;
|
|
79
|
+
/** Split withheld names into the runner baseline and everything else. */
|
|
80
|
+
export declare function classifyWithheld(withheld: readonly string[]): {
|
|
81
|
+
baseline: string[];
|
|
82
|
+
other: string[];
|
|
83
|
+
};
|
|
61
84
|
/**
|
|
62
85
|
* One-line warning naming the withheld variables. Names only, never values;
|
|
63
86
|
* sorted; capped at {@link WITHHELD_WARNING_CAP}.
|
|
64
87
|
*/
|
|
65
88
|
export declare function formatWithheldWarning(withheld: readonly string[]): string;
|
|
89
|
+
/** Plain-log summary: counts only, no names. */
|
|
90
|
+
export declare function formatScopeSummary(total: number, baseline: number): string;
|
|
91
|
+
/** Test seam: forget that the withheld notice was already emitted. */
|
|
92
|
+
export declare function resetWithheldReport(): void;
|
|
93
|
+
/**
|
|
94
|
+
* Report withheld env names, once per process (not per node or per client).
|
|
95
|
+
*
|
|
96
|
+
* - always: one plain `info` line with counts (not a `::warning::` annotation);
|
|
97
|
+
* - only when non-baseline names were withheld: a `warn` listing just those
|
|
98
|
+
* (capped), as a `::warning title=SWEny agent env::` annotation under GitHub
|
|
99
|
+
* Actions;
|
|
100
|
+
* - `debug` (shown with `--verbose`): every withheld name.
|
|
101
|
+
*/
|
|
102
|
+
export declare function reportWithheldEnv(withheld: readonly string[], logger: Pick<Logger, "info" | "warn" | "debug">, env?: Record<string, string | undefined>): void;
|
|
66
103
|
/**
|
|
67
104
|
* Scope the agent env and report which variable names were withheld.
|
|
68
105
|
* `withheld` holds names only; values never leave `source`.
|
package/dist/agent-env.js
CHANGED
|
@@ -159,6 +159,100 @@ export function resolveEnvScope(env, explicit, logger) {
|
|
|
159
159
|
}
|
|
160
160
|
/** Max names listed in the withheld-vars warning before "and N more". */
|
|
161
161
|
export const WITHHELD_WARNING_CAP = 30;
|
|
162
|
+
/**
|
|
163
|
+
* Runner baseline: exact names set by common CI images (GitHub-hosted runner
|
|
164
|
+
* image, Actions runner context, Debian-based containers). They are present on
|
|
165
|
+
* every run, so listing them as "withheld" is noise. Names only; none of these
|
|
166
|
+
* is a credential the operator supplied. Secrets such as `GITHUB_TOKEN`,
|
|
167
|
+
* `NPM_TOKEN`, or `AWS_*` are deliberately absent, so withholding them still
|
|
168
|
+
* warns.
|
|
169
|
+
*/
|
|
170
|
+
export const RUNNER_BASELINE_VARS = new Set([
|
|
171
|
+
// image / OS
|
|
172
|
+
"ImageOS",
|
|
173
|
+
"ImageVersion",
|
|
174
|
+
"ACCEPT_EULA",
|
|
175
|
+
"DEBIAN_FRONTEND",
|
|
176
|
+
"AGENT_TOOLSDIRECTORY",
|
|
177
|
+
"CONDA",
|
|
178
|
+
"SWIFT_PATH",
|
|
179
|
+
"LEIN_HOME",
|
|
180
|
+
"LEIN_JAR",
|
|
181
|
+
"ANT_HOME",
|
|
182
|
+
"GRADLE_HOME",
|
|
183
|
+
"M2_HOME",
|
|
184
|
+
"SELENIUM_JAR_PATH",
|
|
185
|
+
"ENABLE_RUNNER_TRACING",
|
|
186
|
+
"INVOCATION_ID",
|
|
187
|
+
"JOURNAL_STREAM",
|
|
188
|
+
"SYSTEMD_EXEC_PID",
|
|
189
|
+
"MANAGERPID",
|
|
190
|
+
"OLDPWD",
|
|
191
|
+
"PWD",
|
|
192
|
+
"SHLVL",
|
|
193
|
+
"_",
|
|
194
|
+
// GitHub Actions context (never GITHUB_TOKEN)
|
|
195
|
+
"GITHUB_ACTION",
|
|
196
|
+
"GITHUB_ACTION_PATH",
|
|
197
|
+
"GITHUB_ACTION_REF",
|
|
198
|
+
"GITHUB_ACTION_REPOSITORY",
|
|
199
|
+
"GITHUB_ACTOR",
|
|
200
|
+
"GITHUB_ACTOR_ID",
|
|
201
|
+
"GITHUB_ENV",
|
|
202
|
+
"GITHUB_EVENT_PATH",
|
|
203
|
+
"GITHUB_GRAPHQL_URL",
|
|
204
|
+
"GITHUB_JOB",
|
|
205
|
+
"GITHUB_OUTPUT",
|
|
206
|
+
"GITHUB_PATH",
|
|
207
|
+
"GITHUB_REF_PROTECTED",
|
|
208
|
+
"GITHUB_REF_TYPE",
|
|
209
|
+
"GITHUB_REPOSITORY_ID",
|
|
210
|
+
"GITHUB_REPOSITORY_OWNER_ID",
|
|
211
|
+
"GITHUB_RETENTION_DAYS",
|
|
212
|
+
"GITHUB_RUN_ATTEMPT",
|
|
213
|
+
"GITHUB_STATE",
|
|
214
|
+
"GITHUB_STEP_SUMMARY",
|
|
215
|
+
"GITHUB_TRIGGERING_ACTOR",
|
|
216
|
+
"GITHUB_WORKFLOW",
|
|
217
|
+
"GITHUB_WORKFLOW_REF",
|
|
218
|
+
"GITHUB_WORKFLOW_SHA",
|
|
219
|
+
]);
|
|
220
|
+
/**
|
|
221
|
+
* Runner baseline: name patterns for families the CI images set in bulk
|
|
222
|
+
* (Actions runner internals, Android/Java/.NET/Go/Python toolchains, browsers
|
|
223
|
+
* and webdrivers, Azure CLI, vcpkg, ghcup, ...). `AWS_*`, `NPM_*` and
|
|
224
|
+
* `GITHUB_TOKEN`-style names are intentionally not matched.
|
|
225
|
+
*/
|
|
226
|
+
export const RUNNER_BASELINE_PATTERNS = [
|
|
227
|
+
/^ACTIONS_/,
|
|
228
|
+
/^RUNNER_/,
|
|
229
|
+
/^ANDROID_/,
|
|
230
|
+
/^JAVA_HOME(_|$)/,
|
|
231
|
+
/^CHROME/,
|
|
232
|
+
/WEBDRIVER$/,
|
|
233
|
+
/^DOTNET_/,
|
|
234
|
+
/^GOROOT(_|$)/,
|
|
235
|
+
/^PIPX_/,
|
|
236
|
+
/^POWERSHELL_/,
|
|
237
|
+
/^VCPKG_/,
|
|
238
|
+
/^GHCUP_/,
|
|
239
|
+
/^BOOTSTRAP_HASKELL_/,
|
|
240
|
+
/^AZURE_(EXTENSION_DIR|HTTP_USER_AGENT|CONFIG_DIR)$/,
|
|
241
|
+
/^HOMEBREW_/,
|
|
242
|
+
/^STATS_/,
|
|
243
|
+
];
|
|
244
|
+
/** True when `name` is set by the CI image itself, not by the workflow author. */
|
|
245
|
+
export function isRunnerBaselineVar(name) {
|
|
246
|
+
return RUNNER_BASELINE_VARS.has(name) || RUNNER_BASELINE_PATTERNS.some((re) => re.test(name));
|
|
247
|
+
}
|
|
248
|
+
/** Split withheld names into the runner baseline and everything else. */
|
|
249
|
+
export function classifyWithheld(withheld) {
|
|
250
|
+
const baseline = [];
|
|
251
|
+
const other = [];
|
|
252
|
+
for (const n of withheld)
|
|
253
|
+
(isRunnerBaselineVar(n) ? baseline : other).push(n);
|
|
254
|
+
return { baseline: baseline.sort(), other: other.sort() };
|
|
255
|
+
}
|
|
162
256
|
/**
|
|
163
257
|
* One-line warning naming the withheld variables. Names only, never values;
|
|
164
258
|
* sorted; capped at {@link WITHHELD_WARNING_CAP}.
|
|
@@ -171,6 +265,37 @@ export function formatWithheldWarning(withheld) {
|
|
|
171
265
|
`If a node's commands need any of them, add the names to env-passthrough ` +
|
|
172
266
|
`(SWENY_ENV_PASSTHROUGH), or set env-scope: off (SWENY_ENV_SCOPE=off).`);
|
|
173
267
|
}
|
|
268
|
+
/** Plain-log summary: counts only, no names. */
|
|
269
|
+
export function formatScopeSummary(total, baseline) {
|
|
270
|
+
return (`sweny: agent env scoped (${total} withheld, ${baseline} from the CI image). ` +
|
|
271
|
+
`Add names to env-passthrough if a node needs them; --verbose lists them.`);
|
|
272
|
+
}
|
|
273
|
+
let withheldReported = false;
|
|
274
|
+
/** Test seam: forget that the withheld notice was already emitted. */
|
|
275
|
+
export function resetWithheldReport() {
|
|
276
|
+
withheldReported = false;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Report withheld env names, once per process (not per node or per client).
|
|
280
|
+
*
|
|
281
|
+
* - always: one plain `info` line with counts (not a `::warning::` annotation);
|
|
282
|
+
* - only when non-baseline names were withheld: a `warn` listing just those
|
|
283
|
+
* (capped), as a `::warning title=SWEny agent env::` annotation under GitHub
|
|
284
|
+
* Actions;
|
|
285
|
+
* - `debug` (shown with `--verbose`): every withheld name.
|
|
286
|
+
*/
|
|
287
|
+
export function reportWithheldEnv(withheld, logger, env = process.env) {
|
|
288
|
+
if (withheld.length === 0 || withheldReported)
|
|
289
|
+
return;
|
|
290
|
+
withheldReported = true;
|
|
291
|
+
const { baseline, other } = classifyWithheld(withheld);
|
|
292
|
+
logger.info(formatScopeSummary(withheld.length, baseline.length));
|
|
293
|
+
if (other.length > 0) {
|
|
294
|
+
const prefix = env.GITHUB_ACTIONS === "true" ? "::warning title=SWEny agent env::" : "";
|
|
295
|
+
logger.warn(`${prefix}${formatWithheldWarning(other)}`);
|
|
296
|
+
}
|
|
297
|
+
logger.debug(`sweny: agent env withheld: ${[...withheld].sort().join(", ")}`);
|
|
298
|
+
}
|
|
174
299
|
/**
|
|
175
300
|
* Scope the agent env and report which variable names were withheld.
|
|
176
301
|
* `withheld` holds names only; values never leave `source`.
|
package/dist/claude.d.ts
CHANGED
|
@@ -129,7 +129,6 @@ export declare class ClaudeClient implements Claude {
|
|
|
129
129
|
private sandboxProbe;
|
|
130
130
|
private sandboxWarned;
|
|
131
131
|
private envScope;
|
|
132
|
-
private envWarned;
|
|
133
132
|
constructor(opts?: ClaudeClientOptions);
|
|
134
133
|
/**
|
|
135
134
|
* Build env for the Claude Code subprocess (#360). Applies auth precedence
|
|
@@ -137,8 +136,8 @@ export declare class ClaudeClient implements Claude {
|
|
|
137
136
|
* `SWENY_AUTH`). When env scoping is on (default in CI, see
|
|
138
137
|
* {@link resolveEnvScope}) the result is narrowed to the allowlist plus
|
|
139
138
|
* `extraVars` (the node's declared skill env vars) and the operator
|
|
140
|
-
* passthrough list, and the withheld names (never values) are
|
|
141
|
-
* per
|
|
139
|
+
* passthrough list, and the withheld names (never values) are reported once
|
|
140
|
+
* per process ({@link reportWithheldEnv}). When off, the full env passes through as before.
|
|
142
141
|
*/
|
|
143
142
|
private buildEnv;
|
|
144
143
|
run(opts: {
|
package/dist/claude.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import { query, createSdkMcpServer, tool as sdkTool } from "@anthropic-ai/claude-agent-sdk";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
import { consoleLogger } from "./types.js";
|
|
14
|
-
import {
|
|
14
|
+
import { reportWithheldEnv, parseList, resolveEnvScope, scopeAgentEnv, resolveAgentSandbox, } from "./agent-env.js";
|
|
15
15
|
import { fenceUntrustedJson } from "./untrusted.js";
|
|
16
16
|
const SYSTEM_PROMPT = `You are a step in an automated workflow. Execute the instruction precisely using the tools available to you. Be thorough but concise. When you're done, summarize your findings and results.`;
|
|
17
17
|
/**
|
|
@@ -217,7 +217,6 @@ export class ClaudeClient {
|
|
|
217
217
|
sandboxProbe;
|
|
218
218
|
sandboxWarned = false;
|
|
219
219
|
envScope;
|
|
220
|
-
envWarned = false;
|
|
221
220
|
constructor(opts = {}) {
|
|
222
221
|
this.model = opts.model;
|
|
223
222
|
this.maxTurns = opts.maxTurns ?? 20;
|
|
@@ -237,8 +236,8 @@ export class ClaudeClient {
|
|
|
237
236
|
* `SWENY_AUTH`). When env scoping is on (default in CI, see
|
|
238
237
|
* {@link resolveEnvScope}) the result is narrowed to the allowlist plus
|
|
239
238
|
* `extraVars` (the node's declared skill env vars) and the operator
|
|
240
|
-
* passthrough list, and the withheld names (never values) are
|
|
241
|
-
* per
|
|
239
|
+
* passthrough list, and the withheld names (never values) are reported once
|
|
240
|
+
* per process ({@link reportWithheldEnv}). When off, the full env passes through as before.
|
|
242
241
|
*/
|
|
243
242
|
buildEnv(extraVars = []) {
|
|
244
243
|
const full = Object.fromEntries(Object.entries(process.env).filter((e) => e[1] != null));
|
|
@@ -250,11 +249,7 @@ export class ClaudeClient {
|
|
|
250
249
|
passthrough: this.envPassthrough ?? parseList(process.env.SWENY_ENV_PASSTHROUGH),
|
|
251
250
|
logger: this.logger,
|
|
252
251
|
});
|
|
253
|
-
|
|
254
|
-
this.envWarned = true;
|
|
255
|
-
const prefix = process.env.GITHUB_ACTIONS === "true" ? "::warning title=SWEny agent env::" : "";
|
|
256
|
-
this.logger.warn(`${prefix}${formatWithheldWarning(withheld)}`);
|
|
257
|
-
}
|
|
252
|
+
reportWithheldEnv(withheld, this.logger);
|
|
258
253
|
return env;
|
|
259
254
|
}
|
|
260
255
|
async run(opts) {
|