@oxagen/cli 2.1.4-619 → 2.1.4-627
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/oxagen.mjs +254 -33
- package/package.json +1 -1
package/oxagen.mjs
CHANGED
|
@@ -5028,6 +5028,12 @@ var init_envelope = __esm({
|
|
|
5028
5028
|
* beside it for readers of the joined form.
|
|
5029
5029
|
*/
|
|
5030
5030
|
policy_rules: external_exports.array(short).max(64).optional(),
|
|
5031
|
+
/**
|
|
5032
|
+
* The taint sources the decision read (#4666): each third-party read the
|
|
5033
|
+
* run made before the call, by tool, or `web` for a web fetch or search.
|
|
5034
|
+
* Absent when the run was untainted or no Cedar decision read it.
|
|
5035
|
+
*/
|
|
5036
|
+
policy_taint: external_exports.array(short).max(32).optional(),
|
|
5031
5037
|
policy_source: external_exports.enum(POLICY_SOURCES).optional(),
|
|
5032
5038
|
policy_reason_code: short.optional(),
|
|
5033
5039
|
policy_reason_digest: digest.optional(),
|
|
@@ -7180,6 +7186,70 @@ var init_builtins = __esm({
|
|
|
7180
7186
|
}
|
|
7181
7187
|
});
|
|
7182
7188
|
|
|
7189
|
+
// ../../packages/tacho/src/policy/run-facts.ts
|
|
7190
|
+
function taintSourceOf(action, tool) {
|
|
7191
|
+
if (tool.side_effect !== "read" || tool.egress !== "third_party") return null;
|
|
7192
|
+
return WEB_ACTIONS.has(action) ? WEB_TAINT_SOURCE : action;
|
|
7193
|
+
}
|
|
7194
|
+
function emptyRunCallLog() {
|
|
7195
|
+
return { calls: [], reads: [], taint: [] };
|
|
7196
|
+
}
|
|
7197
|
+
function add(list, value, max2) {
|
|
7198
|
+
if (list.length >= max2 || list.includes(value)) return;
|
|
7199
|
+
list.push(value);
|
|
7200
|
+
}
|
|
7201
|
+
function noteRunCall(log, action, tool, targets = []) {
|
|
7202
|
+
if (action === "") return;
|
|
7203
|
+
add(log.calls, action, RUN_CALLS_MAX);
|
|
7204
|
+
if (tool === null) return;
|
|
7205
|
+
const source = taintSourceOf(action, tool);
|
|
7206
|
+
if (source !== null) add(log.taint, source, RUN_TAINT_MAX);
|
|
7207
|
+
if (tool.side_effect !== "read") return;
|
|
7208
|
+
for (const target2 of targets) {
|
|
7209
|
+
if (target2 === "" || target2.length > RUN_READ_MAX_CHARS) continue;
|
|
7210
|
+
add(log.reads, target2, RUN_READS_MAX);
|
|
7211
|
+
}
|
|
7212
|
+
}
|
|
7213
|
+
function runFactsOf(log) {
|
|
7214
|
+
const sources = [...log.taint].sort();
|
|
7215
|
+
return {
|
|
7216
|
+
taint: { tainted: sources.length > 0, sources },
|
|
7217
|
+
run: {
|
|
7218
|
+
prior_calls: [...log.calls].sort(),
|
|
7219
|
+
prior_reads: [...log.reads].sort()
|
|
7220
|
+
}
|
|
7221
|
+
};
|
|
7222
|
+
}
|
|
7223
|
+
function targetsOfArgs(args) {
|
|
7224
|
+
const targets = [];
|
|
7225
|
+
for (const value of Object.values(args ?? {})) {
|
|
7226
|
+
if (typeof value === "string") {
|
|
7227
|
+
if (value !== "" && !targets.includes(value)) targets.push(value);
|
|
7228
|
+
} else if (Array.isArray(value)) {
|
|
7229
|
+
for (const item of value) {
|
|
7230
|
+
if (typeof item === "string" && item !== "" && !targets.includes(item))
|
|
7231
|
+
targets.push(item);
|
|
7232
|
+
}
|
|
7233
|
+
}
|
|
7234
|
+
}
|
|
7235
|
+
return targets;
|
|
7236
|
+
}
|
|
7237
|
+
var WEB_TAINT_SOURCE, WEB_ACTIONS, RUN_TAINT_MAX, RUN_CALLS_MAX, RUN_READS_MAX, RUN_READ_MAX_CHARS;
|
|
7238
|
+
var init_run_facts = __esm({
|
|
7239
|
+
"../../packages/tacho/src/policy/run-facts.ts"() {
|
|
7240
|
+
"use strict";
|
|
7241
|
+
WEB_TAINT_SOURCE = "web";
|
|
7242
|
+
WEB_ACTIONS = /* @__PURE__ */ new Set([
|
|
7243
|
+
"builtin__web_fetch",
|
|
7244
|
+
"builtin__web_search"
|
|
7245
|
+
]);
|
|
7246
|
+
RUN_TAINT_MAX = 32;
|
|
7247
|
+
RUN_CALLS_MAX = 256;
|
|
7248
|
+
RUN_READS_MAX = 256;
|
|
7249
|
+
RUN_READ_MAX_CHARS = 512;
|
|
7250
|
+
}
|
|
7251
|
+
});
|
|
7252
|
+
|
|
7183
7253
|
// ../../packages/tacho/src/policy/decision.ts
|
|
7184
7254
|
function readCedarDecision(answer, approvalIds) {
|
|
7185
7255
|
if (answer.type === "failure") {
|
|
@@ -7299,12 +7369,12 @@ function importedToolRequest(action, tool, input) {
|
|
|
7299
7369
|
const { args: _types, ...classification } = tool;
|
|
7300
7370
|
return { action, tool: classification, argSets: [args], errors };
|
|
7301
7371
|
}
|
|
7302
|
-
function hookRequest(call) {
|
|
7372
|
+
function hookRequest(call, tools) {
|
|
7303
7373
|
const mcpAction = call.action === void 0 ? mcpActionFor(call.toolName) : void 0;
|
|
7304
|
-
if (mcpAction !== void 0 && Object.hasOwn(
|
|
7374
|
+
if (mcpAction !== void 0 && Object.hasOwn(tools, mcpAction)) {
|
|
7305
7375
|
return importedToolRequest(
|
|
7306
7376
|
mcpAction,
|
|
7307
|
-
|
|
7377
|
+
tools[mcpAction],
|
|
7308
7378
|
call.toolInput
|
|
7309
7379
|
);
|
|
7310
7380
|
}
|
|
@@ -7316,9 +7386,20 @@ function hookRequest(call) {
|
|
|
7316
7386
|
errors: []
|
|
7317
7387
|
};
|
|
7318
7388
|
}
|
|
7389
|
+
function hookCallClass(call, tools) {
|
|
7390
|
+
if (isOxagenTool(call.toolName)) return null;
|
|
7391
|
+
const request3 = hookRequest(call, tools);
|
|
7392
|
+
const targets = [];
|
|
7393
|
+
for (const args of request3.argSets) {
|
|
7394
|
+
for (const target2 of targetsOfArgs(args)) {
|
|
7395
|
+
if (!targets.includes(target2)) targets.push(target2);
|
|
7396
|
+
}
|
|
7397
|
+
}
|
|
7398
|
+
return { action: request3.action, tool: request3.tool, targets };
|
|
7399
|
+
}
|
|
7319
7400
|
function evaluateHookCall(call) {
|
|
7320
7401
|
if (isOxagenTool(call.toolName)) return null;
|
|
7321
|
-
const request3 = hookRequest(call);
|
|
7402
|
+
const request3 = hookRequest(call, call.cedar.tools);
|
|
7322
7403
|
const { action } = request3;
|
|
7323
7404
|
const principals = principalsFor(call.cedar, call.harness, call.agent);
|
|
7324
7405
|
if (principals.length === 0) {
|
|
@@ -7350,7 +7431,12 @@ function evaluateHookCall(call) {
|
|
|
7350
7431
|
args,
|
|
7351
7432
|
now: call.now,
|
|
7352
7433
|
tier: "harness",
|
|
7434
|
+
...call.facts !== void 0 ? { taint: call.facts.taint, run: call.facts.run } : {},
|
|
7353
7435
|
...principal.operator_role !== void 0 ? { operator_role: principal.operator_role } : {},
|
|
7436
|
+
// The agent's budget from its row in Oxagen, which the bundle
|
|
7437
|
+
// carries on the principal. The hook runs on the machine and cannot
|
|
7438
|
+
// read the run's metered spend, so it does not subtract it: the
|
|
7439
|
+
// gateway's decision of a served call does (#4666).
|
|
7354
7440
|
...principal.budget_remaining_cents !== void 0 ? { budget_remaining_cents: principal.budget_remaining_cents } : {},
|
|
7355
7441
|
harness_tool: call.harnessTool ?? call.toolName,
|
|
7356
7442
|
...skill !== void 0 ? { skill } : {}
|
|
@@ -7377,6 +7463,7 @@ var init_hook = __esm({
|
|
|
7377
7463
|
"use strict";
|
|
7378
7464
|
init_builtins();
|
|
7379
7465
|
init_context();
|
|
7466
|
+
init_run_facts();
|
|
7380
7467
|
init_decision();
|
|
7381
7468
|
CALL_RESOURCE = { type: "Target", id: "call" };
|
|
7382
7469
|
MCP_PREFIX = "mcp__";
|
|
@@ -7870,6 +7957,7 @@ function evaluatePreToolUse(input) {
|
|
|
7870
7957
|
rules: [ask],
|
|
7871
7958
|
reason_code: "rule_ask",
|
|
7872
7959
|
reason: `Oxagen policy rule ${ask} requires a permission decision.`,
|
|
7960
|
+
...taintOf(cedar),
|
|
7873
7961
|
...base2,
|
|
7874
7962
|
stale
|
|
7875
7963
|
};
|
|
@@ -7890,6 +7978,7 @@ function evaluatePreToolUse(input) {
|
|
|
7890
7978
|
rules: allowed,
|
|
7891
7979
|
reason_code: "rule_allow",
|
|
7892
7980
|
reason: `Allowed by Oxagen policy rule ${rule}.`,
|
|
7981
|
+
...taintOf(cedar),
|
|
7893
7982
|
...base2,
|
|
7894
7983
|
stale
|
|
7895
7984
|
};
|
|
@@ -7901,6 +7990,7 @@ function evaluatePreToolUse(input) {
|
|
|
7901
7990
|
source: "bundle",
|
|
7902
7991
|
reason_code: cedar.reason_code,
|
|
7903
7992
|
reason: cedar.reason,
|
|
7993
|
+
...taintOf(cedar),
|
|
7904
7994
|
...base2,
|
|
7905
7995
|
stale
|
|
7906
7996
|
};
|
|
@@ -7915,6 +8005,9 @@ function evaluatePreToolUse(input) {
|
|
|
7915
8005
|
stale
|
|
7916
8006
|
};
|
|
7917
8007
|
}
|
|
8008
|
+
function taintOf(cedar) {
|
|
8009
|
+
return cedar?.taint === void 0 ? {} : { taint: cedar.taint };
|
|
8010
|
+
}
|
|
7918
8011
|
function ruleNames(reasons) {
|
|
7919
8012
|
return reasons.length > 0 ? { rule: reasons.join(" and "), rules: reasons } : {};
|
|
7920
8013
|
}
|
|
@@ -7930,7 +8023,7 @@ function decideWithCedar(input) {
|
|
|
7930
8023
|
const cedarBundle = input.bundle.cedar;
|
|
7931
8024
|
if (cedarBundle === void 0 || input.cedar === void 0) return void 0;
|
|
7932
8025
|
if (isOxagenTool(input.toolName)) return void 0;
|
|
7933
|
-
const { runtime, harness, agent, skill, action, harness_tool } = input.cedar;
|
|
8026
|
+
const { runtime, harness, agent, skill, action, harness_tool, facts } = input.cedar;
|
|
7934
8027
|
const readOnly = cedarReadOnly(cedarBundle, input.toolName, harness, action);
|
|
7935
8028
|
if (runtime === null) {
|
|
7936
8029
|
if (readOnly) return void 0;
|
|
@@ -7966,6 +8059,7 @@ function decideWithCedar(input) {
|
|
|
7966
8059
|
...harness_tool !== void 0 ? { harnessTool: harness_tool } : {},
|
|
7967
8060
|
...action !== void 0 ? { action } : {},
|
|
7968
8061
|
...skill !== void 0 ? { skill } : {},
|
|
8062
|
+
...facts !== void 0 ? { facts } : {},
|
|
7969
8063
|
now: input.now
|
|
7970
8064
|
});
|
|
7971
8065
|
} catch (error) {
|
|
@@ -7976,10 +8070,12 @@ function decideWithCedar(input) {
|
|
|
7976
8070
|
};
|
|
7977
8071
|
}
|
|
7978
8072
|
if (verdict === null) return void 0;
|
|
8073
|
+
const taint = facts !== void 0 ? { taint: facts.taint.sources } : {};
|
|
7979
8074
|
if (verdict.errors.length > 0) {
|
|
7980
8075
|
return {
|
|
7981
8076
|
evaluated: "deny",
|
|
7982
8077
|
...ruleNames(verdict.reasons),
|
|
8078
|
+
...taint,
|
|
7983
8079
|
reason_code: "cedar_error",
|
|
7984
8080
|
reason: `Cedar could not decide ${verdict.action}: ${verdict.errors[0]}`
|
|
7985
8081
|
};
|
|
@@ -7997,6 +8093,7 @@ function decideWithCedar(input) {
|
|
|
7997
8093
|
return {
|
|
7998
8094
|
evaluated: "allow",
|
|
7999
8095
|
...ruleNames(verdict.reasons),
|
|
8096
|
+
...taint,
|
|
8000
8097
|
reason_code: "cedar_allow",
|
|
8001
8098
|
reason: `The steering record's Cedar policy ${names} permits this tool, so the harness's own permission flow decides.`
|
|
8002
8099
|
};
|
|
@@ -8004,6 +8101,7 @@ function decideWithCedar(input) {
|
|
|
8004
8101
|
return {
|
|
8005
8102
|
evaluated: "ask",
|
|
8006
8103
|
...ruleNames(verdict.reasons),
|
|
8104
|
+
...taint,
|
|
8007
8105
|
reason_code: "cedar_require_approval",
|
|
8008
8106
|
reason: `The steering record's Cedar policy ${names} requires a person's approval.`
|
|
8009
8107
|
};
|
|
@@ -8011,6 +8109,7 @@ function decideWithCedar(input) {
|
|
|
8011
8109
|
return {
|
|
8012
8110
|
evaluated: "deny",
|
|
8013
8111
|
...ruleNames(verdict.reasons),
|
|
8112
|
+
...taint,
|
|
8014
8113
|
reason_code: "cedar_deny",
|
|
8015
8114
|
reason: verdict.reasons.length > 0 ? `Denied by the steering record's Cedar policy ${names}.` : `No Cedar policy in the steering record permits ${verdict.action} for this agent.`
|
|
8016
8115
|
};
|
|
@@ -20235,7 +20334,7 @@ async function isDirectory(path2) {
|
|
|
20235
20334
|
async function subagentFiles(sessionDir, tally2) {
|
|
20236
20335
|
const dir = join11(sessionDir, "subagents");
|
|
20237
20336
|
const out = [];
|
|
20238
|
-
const
|
|
20337
|
+
const add2 = async (folder, name) => {
|
|
20239
20338
|
const match = /^agent-(.+)\.jsonl$/.exec(name);
|
|
20240
20339
|
if (match === null) return;
|
|
20241
20340
|
const agentId = match[1];
|
|
@@ -20245,7 +20344,7 @@ async function subagentFiles(sessionDir, tally2) {
|
|
|
20245
20344
|
meta: await readMeta(join11(folder, `agent-${agentId}.meta.json`))
|
|
20246
20345
|
});
|
|
20247
20346
|
};
|
|
20248
|
-
for (const name of (await listDir(dir)).sort()) await
|
|
20347
|
+
for (const name of (await listDir(dir)).sort()) await add2(dir, name);
|
|
20249
20348
|
const workflows = join11(dir, "workflows");
|
|
20250
20349
|
for (const workflow of (await listDir(workflows)).sort()) {
|
|
20251
20350
|
const folder = join11(workflows, workflow);
|
|
@@ -20254,7 +20353,7 @@ async function subagentFiles(sessionDir, tally2) {
|
|
|
20254
20353
|
tally2.recordsIgnored["workflow-journal"] = (tally2.recordsIgnored["workflow-journal"] ?? 0) + 1;
|
|
20255
20354
|
continue;
|
|
20256
20355
|
}
|
|
20257
|
-
await
|
|
20356
|
+
await add2(folder, name);
|
|
20258
20357
|
}
|
|
20259
20358
|
}
|
|
20260
20359
|
return out;
|
|
@@ -23365,7 +23464,13 @@ var init_credential_store = __esm({
|
|
|
23365
23464
|
/** `OPENAI_API_KEY` in Codex's `auth.json`. */
|
|
23366
23465
|
"codex:auth.json",
|
|
23367
23466
|
/** `TACHO_BROKER_<PROVIDER>_API_KEY` in the enrolling shell. */
|
|
23368
|
-
"enroll:env"
|
|
23467
|
+
"enroll:env",
|
|
23468
|
+
/**
|
|
23469
|
+
* The run token in an Oxagen Agent Runners sandbox's `launch` message. It
|
|
23470
|
+
* is spent at the cloud gateway, which attaches the operator's model
|
|
23471
|
+
* credential. It is not a model credential itself.
|
|
23472
|
+
*/
|
|
23473
|
+
"sandbox:launch"
|
|
23369
23474
|
];
|
|
23370
23475
|
CREDENTIAL_KINDS = ["api_key", "bearer"];
|
|
23371
23476
|
sealedSchema = external_exports.object({
|
|
@@ -23976,7 +24081,7 @@ import { readFileSync as readFileSync11 } from "node:fs";
|
|
|
23976
24081
|
import { dirname as dirname9, resolve as resolve3 } from "node:path";
|
|
23977
24082
|
import { fileURLToPath } from "node:url";
|
|
23978
24083
|
function readVersion() {
|
|
23979
|
-
if (true) return "2.1.4-
|
|
24084
|
+
if (true) return "2.1.4-627";
|
|
23980
24085
|
try {
|
|
23981
24086
|
const here = dirname9(fileURLToPath(import.meta.url));
|
|
23982
24087
|
const pkg = JSON.parse(
|
|
@@ -35821,8 +35926,18 @@ function refusalMarkOf(result2) {
|
|
|
35821
35926
|
return void 0;
|
|
35822
35927
|
const mark = _meta[REFUSAL_META_KEY];
|
|
35823
35928
|
if (mark === null || typeof mark !== "object") return void 0;
|
|
35824
|
-
const { ruleIds } = mark;
|
|
35825
|
-
return {
|
|
35929
|
+
const { ruleIds, taint } = mark;
|
|
35930
|
+
return {
|
|
35931
|
+
ruleIds: Array.isArray(ruleIds) ? ruleIds : [],
|
|
35932
|
+
...Array.isArray(taint) ? { taint } : {}
|
|
35933
|
+
};
|
|
35934
|
+
}
|
|
35935
|
+
function refusalTaintOf(rpc) {
|
|
35936
|
+
if (rpc?.error !== void 0) return void 0;
|
|
35937
|
+
const listed = refusalMarkOf(rpc?.result)?.taint;
|
|
35938
|
+
if (listed === void 0) return void 0;
|
|
35939
|
+
const taint = listed.filter((source) => typeof source === "string").filter((source) => source !== "").slice(0, REFUSAL_TAINT_MAX).map((source) => source.slice(0, REFUSAL_RULE_MAX));
|
|
35940
|
+
return taint;
|
|
35826
35941
|
}
|
|
35827
35942
|
function toolErrorTextOf(result2) {
|
|
35828
35943
|
if (result2 === null || typeof result2 !== "object") return void 0;
|
|
@@ -36067,6 +36182,7 @@ function createMcpGateway(deps) {
|
|
|
36067
36182
|
const isCall = request3.method === "tools/call";
|
|
36068
36183
|
if (!isCall && status2 !== "rejected") return;
|
|
36069
36184
|
const ruleIds = status2 === "rejected" ? refusalRulesOf(rpc) : void 0;
|
|
36185
|
+
const taint = status2 === "rejected" ? refusalTaintOf(rpc) : void 0;
|
|
36070
36186
|
const toolUseId = isCall ? toolUseIdOf(request3.params) : void 0;
|
|
36071
36187
|
deps.record({
|
|
36072
36188
|
sessionId: context.sessionId,
|
|
@@ -36077,6 +36193,7 @@ function createMcpGateway(deps) {
|
|
|
36077
36193
|
durationMs,
|
|
36078
36194
|
...refusedReason === void 0 ? {} : { refusedReason },
|
|
36079
36195
|
...ruleIds === void 0 ? {} : { ruleIds },
|
|
36196
|
+
...taint === void 0 ? {} : { taint },
|
|
36080
36197
|
...exchangeOf(request3, rpc, log)
|
|
36081
36198
|
});
|
|
36082
36199
|
}
|
|
@@ -36140,7 +36257,7 @@ function toolNameOf(params) {
|
|
|
36140
36257
|
const name = params?.["name"];
|
|
36141
36258
|
return typeof name === "string" && name.length > 0 ? name : "unknown";
|
|
36142
36259
|
}
|
|
36143
|
-
var RPC_INVALID_REQUEST, RPC_INTERNAL_ERROR, RPC_REFUSED, CLAUDE_CODE_TOOL_USE_ID_META, MAX_TOOL_USE_ID_LENGTH, DEFAULT_TIMEOUT_MS3, UPSTREAM_EXCERPT_MAX, KERNEL_REFUSAL_PREFIXES, REFUSAL_RULES_MAX, REFUSAL_RULE_MAX;
|
|
36260
|
+
var RPC_INVALID_REQUEST, RPC_INTERNAL_ERROR, RPC_REFUSED, CLAUDE_CODE_TOOL_USE_ID_META, MAX_TOOL_USE_ID_LENGTH, DEFAULT_TIMEOUT_MS3, UPSTREAM_EXCERPT_MAX, KERNEL_REFUSAL_PREFIXES, REFUSAL_TAINT_MAX, REFUSAL_RULES_MAX, REFUSAL_RULE_MAX;
|
|
36144
36261
|
var init_mcp_gateway = __esm({
|
|
36145
36262
|
"../../packages/tacho/src/collector/mcp-gateway.ts"() {
|
|
36146
36263
|
"use strict";
|
|
@@ -36159,6 +36276,7 @@ var init_mcp_gateway = __esm({
|
|
|
36159
36276
|
'IAM denied "',
|
|
36160
36277
|
'IAM requires approval for "'
|
|
36161
36278
|
];
|
|
36279
|
+
REFUSAL_TAINT_MAX = 32;
|
|
36162
36280
|
REFUSAL_RULES_MAX = 64;
|
|
36163
36281
|
REFUSAL_RULE_MAX = 512;
|
|
36164
36282
|
}
|
|
@@ -40489,6 +40607,34 @@ var init_recall_hints = __esm({
|
|
|
40489
40607
|
}
|
|
40490
40608
|
});
|
|
40491
40609
|
|
|
40610
|
+
// ../../packages/tacho/src/collector/policy-run.ts
|
|
40611
|
+
function notePolicyRunCall(record, call) {
|
|
40612
|
+
const counted = hookCallClass(
|
|
40613
|
+
{
|
|
40614
|
+
harness: call.harness,
|
|
40615
|
+
toolName: call.toolName,
|
|
40616
|
+
...call.toolInput !== void 0 ? { toolInput: call.toolInput } : {}
|
|
40617
|
+
},
|
|
40618
|
+
call.cedar.tools
|
|
40619
|
+
);
|
|
40620
|
+
if (counted === null) return;
|
|
40621
|
+
record.policyRun ??= emptyRunCallLog();
|
|
40622
|
+
noteRunCall(record.policyRun, counted.action, counted.tool, counted.targets);
|
|
40623
|
+
}
|
|
40624
|
+
function policyRunFacts(record) {
|
|
40625
|
+
return runFactsOf(record.policyRun ?? emptyRunCallLog());
|
|
40626
|
+
}
|
|
40627
|
+
function forgetPolicyRun(record) {
|
|
40628
|
+
delete record.policyRun;
|
|
40629
|
+
}
|
|
40630
|
+
var init_policy_run = __esm({
|
|
40631
|
+
"../../packages/tacho/src/collector/policy-run.ts"() {
|
|
40632
|
+
"use strict";
|
|
40633
|
+
init_hook();
|
|
40634
|
+
init_run_facts();
|
|
40635
|
+
}
|
|
40636
|
+
});
|
|
40637
|
+
|
|
40492
40638
|
// ../../packages/tacho/src/collector/hook-handler.ts
|
|
40493
40639
|
import { homedir as homedir4 } from "node:os";
|
|
40494
40640
|
import { dirname as dirname17, isAbsolute as isAbsolute6 } from "node:path";
|
|
@@ -40517,6 +40663,10 @@ function policyFacts2(evaluation, view) {
|
|
|
40517
40663
|
// The list is what the Run page's Policy tab prints (#3971); the joined
|
|
40518
40664
|
// `policy_rule` stays for older readers and `tacho.session_commands`.
|
|
40519
40665
|
...evaluation.rules !== void 0 && evaluation.rules.length > 0 ? { policy_rules: evaluation.rules.slice(0, 64) } : {},
|
|
40666
|
+
// The taint sources Cedar decided the call with (#4666). An empty list
|
|
40667
|
+
// says the session was assessed and clean; no member says it was not
|
|
40668
|
+
// assessed (ADR-201).
|
|
40669
|
+
...evaluation.taint !== void 0 ? { policy_taint: evaluation.taint.slice(0, 32) } : {},
|
|
40520
40670
|
...evaluation.capability_id !== void 0 ? { capability_id: evaluation.capability_id } : {}
|
|
40521
40671
|
};
|
|
40522
40672
|
}
|
|
@@ -40746,6 +40896,7 @@ async function handleHookEvent(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
40746
40896
|
async function cedarCallFor(view, record, input, deps, action) {
|
|
40747
40897
|
if (view.bundle.cedar === void 0) return void 0;
|
|
40748
40898
|
const custom2 = record.customAgent;
|
|
40899
|
+
const facts = policyRunFacts(record);
|
|
40749
40900
|
return {
|
|
40750
40901
|
// No loader means no evaluator: a mutating tool is refused rather than
|
|
40751
40902
|
// decided without the bundle's policies.
|
|
@@ -40755,7 +40906,9 @@ async function cedarCallFor(view, record, input, deps, action) {
|
|
|
40755
40906
|
...input.agent_type !== void 0 ? { skill: input.agent_type } : {},
|
|
40756
40907
|
...action !== void 0 ? { action } : {},
|
|
40757
40908
|
// Cursor's adapter renames `Shell` to `Bash` and keeps Cursor's own name here.
|
|
40758
|
-
...typeof input["cursor_tool_name"] === "string" ? { harness_tool: input["cursor_tool_name"] } : {}
|
|
40909
|
+
...typeof input["cursor_tool_name"] === "string" ? { harness_tool: input["cursor_tool_name"] } : {},
|
|
40910
|
+
// The taint and prior calls of the calls that ran in the session (#4666).
|
|
40911
|
+
facts
|
|
40759
40912
|
};
|
|
40760
40913
|
}
|
|
40761
40914
|
function evaluationRequestFor(view, toolName3, toolInput, record, deps, input, cedar) {
|
|
@@ -41316,6 +41469,13 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
41316
41469
|
case "PostToolUse":
|
|
41317
41470
|
case "PostToolUseFailure": {
|
|
41318
41471
|
events.push(...record.recorder.ingestHook(payload, env, at, withReplay));
|
|
41472
|
+
if (view.bundle.cedar !== void 0 && input.tool_name !== void 0)
|
|
41473
|
+
notePolicyRunCall(record, {
|
|
41474
|
+
cedar: view.bundle.cedar,
|
|
41475
|
+
harness: record.customAgent !== void 0 ? "custom" : record.harness ?? "claude-code",
|
|
41476
|
+
toolName: input.tool_name,
|
|
41477
|
+
...input.tool_input !== void 0 ? { toolInput: input.tool_input } : {}
|
|
41478
|
+
});
|
|
41319
41479
|
if (input.hook_event_name === "PostToolUseFailure")
|
|
41320
41480
|
noteToolFailure(record, input.tool_name);
|
|
41321
41481
|
else if (deps.noteMemoryReads !== void 0 && (record.harness ?? "claude-code") === "claude-code")
|
|
@@ -41380,6 +41540,7 @@ async function routeHook(raw, env, deps, replay, harness, agent, hookId) {
|
|
|
41380
41540
|
events.push(...record.recorder.ingestHook(payload, env, at, withReplay));
|
|
41381
41541
|
deps.registry.seal(record);
|
|
41382
41542
|
forgetRecallHints(record);
|
|
41543
|
+
forgetPolicyRun(record);
|
|
41383
41544
|
const harness2 = skillsHarness(record);
|
|
41384
41545
|
if (deps.skills !== void 0 && harness2 !== void 0)
|
|
41385
41546
|
await deps.skills.remove(harness2, record.harnessSessionId, env);
|
|
@@ -41455,6 +41616,7 @@ var init_hook_handler = __esm({
|
|
|
41455
41616
|
init_reflection_ask();
|
|
41456
41617
|
init_interjection2();
|
|
41457
41618
|
init_recall_hints();
|
|
41619
|
+
init_policy_run();
|
|
41458
41620
|
CONTAINMENT_REQUIRED_REASON = "This agent's mandate requires the contained tier. Start it with `oxagen agent run --contained`.";
|
|
41459
41621
|
MESSAGE_BOUNDARIES = /* @__PURE__ */ new Set([
|
|
41460
41622
|
"SessionStart",
|
|
@@ -41999,7 +42161,8 @@ function gatewayFrameBody(call) {
|
|
|
41999
42161
|
policy_source: "kernel",
|
|
42000
42162
|
policy_reason_code: "mcp_refused",
|
|
42001
42163
|
policy_reason_digest: digestText(call.refusedReason ?? "refused"),
|
|
42002
|
-
...call.ruleIds === void 0 || call.ruleIds.length === 0 ? {} : { policy_rules: call.ruleIds }
|
|
42164
|
+
...call.ruleIds === void 0 || call.ruleIds.length === 0 ? {} : { policy_rules: call.ruleIds },
|
|
42165
|
+
...call.taint === void 0 ? {} : { policy_taint: call.taint }
|
|
42003
42166
|
} : {}
|
|
42004
42167
|
}
|
|
42005
42168
|
};
|
|
@@ -49842,6 +50005,33 @@ import { readdir as readdir3, readFile as readFile3, stat as stat2 } from "node:
|
|
|
49842
50005
|
import { homedir as homedir7, hostname as osHostname2 } from "node:os";
|
|
49843
50006
|
import { dirname as dirname21, join as join39 } from "node:path";
|
|
49844
50007
|
import { execFile as execFile4, spawnSync as spawnSync7 } from "node:child_process";
|
|
50008
|
+
function cloudGatewayUpstreams(origin = CLOUD_GATEWAY_ORIGIN) {
|
|
50009
|
+
const base2 = new URL(origin).origin;
|
|
50010
|
+
const openai = `${base2}${CLOUD_GATEWAY_BASE_PATH}/openai/v1`;
|
|
50011
|
+
return {
|
|
50012
|
+
anthropic: `${base2}${CLOUD_GATEWAY_BASE_PATH}/anthropic`,
|
|
50013
|
+
openai,
|
|
50014
|
+
chatgpt: openai
|
|
50015
|
+
};
|
|
50016
|
+
}
|
|
50017
|
+
function cloudGatewayCredentialStore(disk, runToken) {
|
|
50018
|
+
const held = (provider) => ({
|
|
50019
|
+
kind: provider === "anthropic" ? "api_key" : "bearer",
|
|
50020
|
+
secret: runToken
|
|
50021
|
+
});
|
|
50022
|
+
return {
|
|
50023
|
+
...disk,
|
|
50024
|
+
has: () => true,
|
|
50025
|
+
read: (provider) => held(provider),
|
|
50026
|
+
take: () => {
|
|
50027
|
+
throw new Error(
|
|
50028
|
+
"A sandbox's local gateway holds no model credential. The cloud gateway attaches the operator's key."
|
|
50029
|
+
);
|
|
50030
|
+
},
|
|
50031
|
+
release: () => void 0,
|
|
50032
|
+
status: () => []
|
|
50033
|
+
};
|
|
50034
|
+
}
|
|
49845
50035
|
function defaultExec(command2, args) {
|
|
49846
50036
|
const result2 = spawnSync7(command2, args, {
|
|
49847
50037
|
encoding: "utf8",
|
|
@@ -50137,10 +50327,14 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
50137
50327
|
const bootId = `tachod-${ulid(now())}`;
|
|
50138
50328
|
const hostRecord = registry2.ensure(bootId, { pid: process.pid }).record;
|
|
50139
50329
|
const hostRecorder = hostRecord.recorder;
|
|
50140
|
-
const
|
|
50330
|
+
const diskCredentialStore = openCredentialStore({
|
|
50141
50331
|
file: paths.credentials,
|
|
50142
50332
|
key: paths.credentialsKey
|
|
50143
50333
|
});
|
|
50334
|
+
const credentialStore = options.cloudGateway !== void 0 ? cloudGatewayCredentialStore(
|
|
50335
|
+
diskCredentialStore,
|
|
50336
|
+
options.cloudGateway.runToken
|
|
50337
|
+
) : diskCredentialStore;
|
|
50144
50338
|
const runTokenKey = () => readRunTokenKey(paths.runTokenKey) ?? loadOrCreateRunTokenKey(paths.runTokenKey).key;
|
|
50145
50339
|
runTokenKey();
|
|
50146
50340
|
function inCustody(provider) {
|
|
@@ -51788,11 +51982,11 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
51788
51982
|
bundle: host.bundle,
|
|
51789
51983
|
hostStatus: hostStatusInForce(host, bundleVerified)
|
|
51790
51984
|
}),
|
|
51791
|
-
upstreams: () => ({
|
|
51985
|
+
upstreams: () => options.cloudGateway !== void 0 ? cloudGatewayUpstreams(options.cloudGateway.origin) : {
|
|
51792
51986
|
...DEFAULT_MODEL_UPSTREAMS,
|
|
51793
51987
|
...displacedUpstreams,
|
|
51794
51988
|
...options.modelUpstreams
|
|
51795
|
-
}
|
|
51989
|
+
},
|
|
51796
51990
|
// A restart must not hand the agent's day back either (ADR-160). The day
|
|
51797
51991
|
// counter asks this once per process (`createDaySpend`), so the figure
|
|
51798
51992
|
// read at startup is used once. A first call on a later day than
|
|
@@ -51971,6 +52165,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
51971
52165
|
}
|
|
51972
52166
|
const api = {
|
|
51973
52167
|
runContained: contained.run,
|
|
52168
|
+
runSandbox: contained.runSandbox,
|
|
51974
52169
|
githubLease: (input) => githubProxy.issue(input),
|
|
51975
52170
|
githubProxy: (req, res) => githubProxy.handle(req, res),
|
|
51976
52171
|
localToken: host.local_token,
|
|
@@ -52375,6 +52570,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
52375
52570
|
}
|
|
52376
52571
|
registry2.settleSwept(candidate);
|
|
52377
52572
|
forgetRecallHints(candidate.record);
|
|
52573
|
+
forgetPolicyRun(candidate.record);
|
|
52378
52574
|
closed2.push(candidate);
|
|
52379
52575
|
}
|
|
52380
52576
|
if (!queues.hostBusy()) {
|
|
@@ -52631,7 +52827,7 @@ async function initializeDaemon(options, server, port, ready) {
|
|
|
52631
52827
|
}
|
|
52632
52828
|
};
|
|
52633
52829
|
}
|
|
52634
|
-
var DEFAULT_TIMERS, STATIC_TOKEN_RENEWAL_CHECK_MS, MEMORY_SCAN_MS, QUEUED_PROMPT_CLASS, RECORDER_EVENTS_KEPT, STOPPING, STOPPED_EXEC, STATE_WRITE_DEFER_MS;
|
|
52830
|
+
var DEFAULT_TIMERS, STATIC_TOKEN_RENEWAL_CHECK_MS, MEMORY_SCAN_MS, CLOUD_GATEWAY_ORIGIN, CLOUD_GATEWAY_BASE_PATH, QUEUED_PROMPT_CLASS, RECORDER_EVENTS_KEPT, STOPPING, STOPPED_EXEC, STATE_WRITE_DEFER_MS;
|
|
52635
52831
|
var init_daemon = __esm({
|
|
52636
52832
|
"../../packages/tacho/src/collector/daemon.ts"() {
|
|
52637
52833
|
"use strict";
|
|
@@ -52686,6 +52882,7 @@ var init_daemon = __esm({
|
|
|
52686
52882
|
init_machine();
|
|
52687
52883
|
init_push_basis();
|
|
52688
52884
|
init_recall_hints();
|
|
52885
|
+
init_policy_run();
|
|
52689
52886
|
init_session_skills();
|
|
52690
52887
|
init_credential_issuer();
|
|
52691
52888
|
init_day_spend();
|
|
@@ -52720,6 +52917,8 @@ var init_daemon = __esm({
|
|
|
52720
52917
|
};
|
|
52721
52918
|
STATIC_TOKEN_RENEWAL_CHECK_MS = 60 * 6e4;
|
|
52722
52919
|
MEMORY_SCAN_MS = 5 * 6e4;
|
|
52920
|
+
CLOUD_GATEWAY_ORIGIN = "https://api.oxagen.sh";
|
|
52921
|
+
CLOUD_GATEWAY_BASE_PATH = "/v1/gateway";
|
|
52723
52922
|
QUEUED_PROMPT_CLASS = RETENTION_CLASS_BY_KIND["oxagen:message"] ?? "model_call";
|
|
52724
52923
|
RECORDER_EVENTS_KEPT = 64;
|
|
52725
52924
|
STOPPING = "tachod is stopping; tacho-hook spools this hook for the next start";
|
|
@@ -52868,7 +53067,7 @@ async function stopAll(daemons) {
|
|
|
52868
53067
|
const failed3 = results.find((result2) => result2.status === "rejected");
|
|
52869
53068
|
if (failed3 !== void 0) throw failed3.reason;
|
|
52870
53069
|
}
|
|
52871
|
-
async function runDaemonProcess() {
|
|
53070
|
+
async function runDaemonProcess(options = {}) {
|
|
52872
53071
|
const paths = tachoHome(process.env);
|
|
52873
53072
|
const daemons = [];
|
|
52874
53073
|
let stopping;
|
|
@@ -52912,6 +53111,18 @@ async function runDaemonProcess() {
|
|
|
52912
53111
|
process.on("SIGHUP", () => {
|
|
52913
53112
|
for (const daemon of daemons) daemon.refreshBundle().catch(() => void 0);
|
|
52914
53113
|
});
|
|
53114
|
+
if (options.started !== void 0) {
|
|
53115
|
+
try {
|
|
53116
|
+
await options.started(daemons);
|
|
53117
|
+
} catch (error) {
|
|
53118
|
+
log(
|
|
53119
|
+
`tachod: ${error instanceof Error ? error.message : String(error)}, stopping
|
|
53120
|
+
`
|
|
53121
|
+
);
|
|
53122
|
+
stopWithin(stopOnce, STOP_GRACE_MS, () => exit(1), log);
|
|
53123
|
+
return;
|
|
53124
|
+
}
|
|
53125
|
+
}
|
|
52915
53126
|
await new Promise(() => void 0);
|
|
52916
53127
|
}
|
|
52917
53128
|
var STOP_GRACE_MS;
|
|
@@ -54940,7 +55151,7 @@ var init_package = __esm({
|
|
|
54940
55151
|
"package.json"() {
|
|
54941
55152
|
package_default = {
|
|
54942
55153
|
name: "@oxagen/cli",
|
|
54943
|
-
version: "2.1.4-
|
|
55154
|
+
version: "2.1.4-627",
|
|
54944
55155
|
description: "Oxagen governance CLI \u2014 spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
|
|
54945
55156
|
type: "module",
|
|
54946
55157
|
main: "./dist/index.js",
|
|
@@ -64051,7 +64262,7 @@ var require_YAMLMap = __commonJS({
|
|
|
64051
64262
|
static from(schema, obj2, ctx) {
|
|
64052
64263
|
const { keepUndefined, replacer } = ctx;
|
|
64053
64264
|
const map = new this(schema);
|
|
64054
|
-
const
|
|
64265
|
+
const add2 = (key, value) => {
|
|
64055
64266
|
if (typeof replacer === "function")
|
|
64056
64267
|
value = replacer.call(obj2, key, value);
|
|
64057
64268
|
else if (Array.isArray(replacer) && !replacer.includes(key))
|
|
@@ -64061,10 +64272,10 @@ var require_YAMLMap = __commonJS({
|
|
|
64061
64272
|
};
|
|
64062
64273
|
if (obj2 instanceof Map) {
|
|
64063
64274
|
for (const [key, value] of obj2)
|
|
64064
|
-
|
|
64275
|
+
add2(key, value);
|
|
64065
64276
|
} else if (obj2 && typeof obj2 === "object") {
|
|
64066
64277
|
for (const key of Object.keys(obj2))
|
|
64067
|
-
|
|
64278
|
+
add2(key, obj2[key]);
|
|
64068
64279
|
}
|
|
64069
64280
|
if (typeof schema.sortMapEntries === "function") {
|
|
64070
64281
|
map.items.sort(schema.sortMapEntries);
|
|
@@ -78587,10 +78798,10 @@ var init_esm2 = __esm({
|
|
|
78587
78798
|
lpos = pos, lm = null;
|
|
78588
78799
|
break;
|
|
78589
78800
|
} else {
|
|
78590
|
-
var
|
|
78801
|
+
var add2 = sym - 254;
|
|
78591
78802
|
if (sym > 264) {
|
|
78592
78803
|
var i2 = sym - 257, b5 = fleb[i2];
|
|
78593
|
-
|
|
78804
|
+
add2 = bits(dat, pos, (1 << b5) - 1) + fl[i2];
|
|
78594
78805
|
pos += b5;
|
|
78595
78806
|
}
|
|
78596
78807
|
var d = dm[bits16(dat, pos) & dms], dsym = d >> 4;
|
|
@@ -78609,7 +78820,7 @@ var init_esm2 = __esm({
|
|
|
78609
78820
|
}
|
|
78610
78821
|
if (resize)
|
|
78611
78822
|
cbuf(bt + 131072);
|
|
78612
|
-
var end = bt +
|
|
78823
|
+
var end = bt + add2;
|
|
78613
78824
|
if (bt < dt) {
|
|
78614
78825
|
var shift = dl - dt, dend = Math.min(dt, end);
|
|
78615
78826
|
if (shift + bt < 0)
|
|
@@ -90587,7 +90798,7 @@ var require_umd = __commonJS({
|
|
|
90587
90798
|
return this.not().add(ONE);
|
|
90588
90799
|
};
|
|
90589
90800
|
LongPrototype.neg = LongPrototype.negate;
|
|
90590
|
-
LongPrototype.add = function
|
|
90801
|
+
LongPrototype.add = function add2(addend) {
|
|
90591
90802
|
if (!isLong3(addend)) addend = fromValue(addend);
|
|
90592
90803
|
var a48 = this.high >>> 16;
|
|
90593
90804
|
var a32 = this.high & 65535;
|
|
@@ -92076,7 +92287,7 @@ var require_namespace = __commonJS({
|
|
|
92076
92287
|
return this.nested[name].values;
|
|
92077
92288
|
throw Error("no such enum: " + name);
|
|
92078
92289
|
};
|
|
92079
|
-
Namespace.prototype.add = function
|
|
92290
|
+
Namespace.prototype.add = function add2(object) {
|
|
92080
92291
|
if (!(object instanceof Field && object.extend !== void 0 || object instanceof Type || object instanceof OneOf || object instanceof Enum || object instanceof Service || object instanceof Namespace))
|
|
92081
92292
|
throw TypeError("object must be a valid nested object");
|
|
92082
92293
|
if (object.name === "__proto__")
|
|
@@ -92460,7 +92671,7 @@ var require_service2 = __commonJS({
|
|
|
92460
92671
|
});
|
|
92461
92672
|
return this;
|
|
92462
92673
|
};
|
|
92463
|
-
Service.prototype.add = function
|
|
92674
|
+
Service.prototype.add = function add2(object) {
|
|
92464
92675
|
if (this.get(object.name))
|
|
92465
92676
|
throw Error("duplicate name '" + object.name + "' in " + this);
|
|
92466
92677
|
if (object instanceof Method) {
|
|
@@ -93187,7 +93398,7 @@ var require_type = __commonJS({
|
|
|
93187
93398
|
return this.nested[name];
|
|
93188
93399
|
return null;
|
|
93189
93400
|
};
|
|
93190
|
-
Type.prototype.add = function
|
|
93401
|
+
Type.prototype.add = function add2(object) {
|
|
93191
93402
|
if (this.get(object.name))
|
|
93192
93403
|
throw Error("duplicate name '" + object.name + "' in " + this);
|
|
93193
93404
|
if (object instanceof Field && object.extend === void 0) {
|
|
@@ -94114,7 +94325,7 @@ var require_oneof = __commonJS({
|
|
|
94114
94325
|
oneof.parent.add(oneof.fieldsArray[i2]);
|
|
94115
94326
|
}
|
|
94116
94327
|
}
|
|
94117
|
-
OneOf.prototype.add = function
|
|
94328
|
+
OneOf.prototype.add = function add2(field) {
|
|
94118
94329
|
if (!(field instanceof Field))
|
|
94119
94330
|
throw TypeError("field must be a Field");
|
|
94120
94331
|
if (field.parent && field.parent !== this.parent)
|
|
@@ -94446,7 +94657,7 @@ var require_enum = __commonJS({
|
|
|
94446
94657
|
keepComments ? this.comments : void 0
|
|
94447
94658
|
]);
|
|
94448
94659
|
};
|
|
94449
|
-
Enum.prototype.add = function
|
|
94660
|
+
Enum.prototype.add = function add2(name, id, comment, options) {
|
|
94450
94661
|
if (!util2.isString(name))
|
|
94451
94662
|
throw TypeError("name must be a string");
|
|
94452
94663
|
if (!util2.isInteger(id))
|
|
@@ -122693,6 +122904,7 @@ var init_policy2 = __esm({
|
|
|
122693
122904
|
init_decision();
|
|
122694
122905
|
init_hook();
|
|
122695
122906
|
init_runtime();
|
|
122907
|
+
init_run_facts();
|
|
122696
122908
|
}
|
|
122697
122909
|
});
|
|
122698
122910
|
|
|
@@ -123498,6 +123710,14 @@ var init_decision_rules = __esm({
|
|
|
123498
123710
|
}
|
|
123499
123711
|
});
|
|
123500
123712
|
|
|
123713
|
+
// ../../packages/policy/src/run-facts.ts
|
|
123714
|
+
var init_run_facts2 = __esm({
|
|
123715
|
+
"../../packages/policy/src/run-facts.ts"() {
|
|
123716
|
+
"use strict";
|
|
123717
|
+
init_policy2();
|
|
123718
|
+
}
|
|
123719
|
+
});
|
|
123720
|
+
|
|
123501
123721
|
// ../../packages/policy/src/visibility.ts
|
|
123502
123722
|
var init_visibility = __esm({
|
|
123503
123723
|
"../../packages/policy/src/visibility.ts"() {
|
|
@@ -123515,6 +123735,7 @@ var init_src7 = __esm({
|
|
|
123515
123735
|
init_compile3();
|
|
123516
123736
|
init_decision_rules();
|
|
123517
123737
|
init_evaluate();
|
|
123738
|
+
init_run_facts2();
|
|
123518
123739
|
init_schema4();
|
|
123519
123740
|
init_tests();
|
|
123520
123741
|
init_visibility();
|
package/package.json
CHANGED