@cognipeer/agent-sdk 0.10.1 → 0.10.2
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/index.cjs +193 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.mjs +193 -71
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4601,18 +4601,60 @@ function createToolsNode(initialTools, opts) {
|
|
|
4601
4601
|
toolStateRef.__currentToolCallId = toolCallId;
|
|
4602
4602
|
delete toolStateRef.__awaitingApproval;
|
|
4603
4603
|
}
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4604
|
+
const stableJson = (value) => {
|
|
4605
|
+
try {
|
|
4606
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
4607
|
+
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
4608
|
+
const keys = Object.keys(value).sort();
|
|
4609
|
+
return `{${keys.map((k) => JSON.stringify(k) + ":" + stableJson(value[k])).join(",")}}`;
|
|
4610
|
+
} catch {
|
|
4611
|
+
return String(value);
|
|
4612
|
+
}
|
|
4613
|
+
};
|
|
4614
|
+
const rejectByPolicy = (gateReason, gatedArgs) => {
|
|
4615
|
+
const reason = gateReason || `Tool call blocked by policy: ${toolName}`;
|
|
4616
|
+
push({ role: "tool", content: reason, tool_call_id: toolCallId, name: tc.name });
|
|
4617
|
+
toolHistory.push({
|
|
4618
|
+
executionId: nanoid.nanoid(),
|
|
4619
|
+
toolName,
|
|
4620
|
+
args: gatedArgs,
|
|
4621
|
+
output: reason,
|
|
4622
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4623
|
+
tool_call_id: toolCallId,
|
|
4624
|
+
status: "rejected"
|
|
4625
|
+
});
|
|
4626
|
+
onEvent?.({ type: "tool_call", phase: "skipped", name: toolName, id: tc.id, args: gatedArgs, error: { message: reason } });
|
|
4627
|
+
recordTraceEvent(traceSession, {
|
|
4628
|
+
type: "tool_call",
|
|
4629
|
+
label: `Tool Denied - ${toolName}`,
|
|
4630
|
+
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
4631
|
+
status: "skipped",
|
|
4632
|
+
toolDetails,
|
|
4633
|
+
toolExecutionId: toolCallId,
|
|
4634
|
+
sections: buildToolTraceSections({
|
|
4635
|
+
args: gatedArgs,
|
|
4636
|
+
executionId: toolCallId,
|
|
4637
|
+
output: reason,
|
|
4638
|
+
status: "skipped",
|
|
4639
|
+
summary: reason,
|
|
4640
|
+
toolDetails,
|
|
4641
|
+
toolName
|
|
4642
|
+
})
|
|
4643
|
+
});
|
|
4644
|
+
toolCount += 1;
|
|
4645
|
+
return { status: "error" };
|
|
4646
|
+
};
|
|
4647
|
+
const applyPreToolUseGate = async (candidate) => {
|
|
4648
|
+
if (!host?.has("preToolUse")) return { ok: true, args: candidate, ask: false };
|
|
4608
4649
|
const gate = await host.runGate("preToolUse", {
|
|
4609
4650
|
toolName,
|
|
4610
4651
|
toolCallId,
|
|
4611
|
-
args,
|
|
4652
|
+
args: candidate,
|
|
4612
4653
|
tool,
|
|
4613
4654
|
executionCount: countSuccessfulToolExecutions(toolHistory, toolName)
|
|
4614
4655
|
});
|
|
4615
|
-
|
|
4656
|
+
let next = candidate;
|
|
4657
|
+
if (gate.input.args !== candidate) {
|
|
4616
4658
|
const revalidated = validateToolArgs(tool, gate.input.args);
|
|
4617
4659
|
if (!revalidated.ok && resolved.toolResponses.schemaValidation === "strict") {
|
|
4618
4660
|
const message = `Tool argument validation failed after a plugin rewrite for ${toolName}: ${revalidated.message}`;
|
|
@@ -4620,48 +4662,31 @@ function createToolsNode(initialTools, opts) {
|
|
|
4620
4662
|
markToolFailure(message, toolName, toolCallId);
|
|
4621
4663
|
onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args: gate.input.args, error: { message } });
|
|
4622
4664
|
toolCount += 1;
|
|
4623
|
-
return { status: "error" };
|
|
4665
|
+
return { ok: false, outcome: { status: "error" } };
|
|
4624
4666
|
}
|
|
4625
|
-
|
|
4667
|
+
next = revalidated.ok ? revalidated.value : gate.input.args;
|
|
4626
4668
|
}
|
|
4627
4669
|
if (gate.decision === "deny") {
|
|
4628
|
-
|
|
4629
|
-
push({ role: "tool", content: reason, tool_call_id: toolCallId, name: tc.name });
|
|
4630
|
-
toolHistory.push({
|
|
4631
|
-
executionId: nanoid.nanoid(),
|
|
4632
|
-
toolName,
|
|
4633
|
-
args,
|
|
4634
|
-
output: reason,
|
|
4635
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4636
|
-
tool_call_id: toolCallId,
|
|
4637
|
-
status: "rejected"
|
|
4638
|
-
});
|
|
4639
|
-
onEvent?.({ type: "tool_call", phase: "skipped", name: toolName, id: tc.id, args, error: { message: reason } });
|
|
4640
|
-
recordTraceEvent(traceSession, {
|
|
4641
|
-
type: "tool_call",
|
|
4642
|
-
label: `Tool Denied - ${toolName}`,
|
|
4643
|
-
actor: { scope: "tool", name: toolName, role: "tool" },
|
|
4644
|
-
status: "skipped",
|
|
4645
|
-
toolDetails,
|
|
4646
|
-
toolExecutionId: toolCallId,
|
|
4647
|
-
sections: buildToolTraceSections({
|
|
4648
|
-
args,
|
|
4649
|
-
executionId: toolCallId,
|
|
4650
|
-
output: reason,
|
|
4651
|
-
status: "skipped",
|
|
4652
|
-
summary: reason,
|
|
4653
|
-
toolDetails,
|
|
4654
|
-
toolName
|
|
4655
|
-
})
|
|
4656
|
-
});
|
|
4657
|
-
toolCount += 1;
|
|
4658
|
-
return { status: "error" };
|
|
4659
|
-
}
|
|
4660
|
-
if (gate.decision === "ask") {
|
|
4661
|
-
hookAskedForApproval = true;
|
|
4662
|
-
hookApprovalPrompt = gate.approvalPrompt;
|
|
4670
|
+
return { ok: false, outcome: rejectByPolicy(gate.reason, next) };
|
|
4663
4671
|
}
|
|
4664
|
-
|
|
4672
|
+
return {
|
|
4673
|
+
ok: true,
|
|
4674
|
+
args: next,
|
|
4675
|
+
ask: gate.decision === "ask",
|
|
4676
|
+
approvalPrompt: gate.approvalPrompt,
|
|
4677
|
+
result: gate.shortCircuit
|
|
4678
|
+
};
|
|
4679
|
+
};
|
|
4680
|
+
let hookAskedForApproval = false;
|
|
4681
|
+
let hookApprovalPrompt;
|
|
4682
|
+
let hookResult;
|
|
4683
|
+
{
|
|
4684
|
+
const gated = await applyPreToolUseGate(args);
|
|
4685
|
+
if (!gated.ok) return gated.outcome;
|
|
4686
|
+
args = gated.args;
|
|
4687
|
+
hookAskedForApproval = gated.ask;
|
|
4688
|
+
hookApprovalPrompt = gated.approvalPrompt;
|
|
4689
|
+
if (gated.result !== void 0) hookResult = gated.result;
|
|
4665
4690
|
}
|
|
4666
4691
|
const maxExecutionsPerRun = normalizeMaxExecutionsPerRun(tool.maxExecutionsPerRun);
|
|
4667
4692
|
if (maxExecutionsPerRun !== null) {
|
|
@@ -4746,7 +4771,34 @@ function createToolsNode(initialTools, opts) {
|
|
|
4746
4771
|
return { status: "rejected", approval: approvalEntry };
|
|
4747
4772
|
}
|
|
4748
4773
|
if (approvalEntry.status === "approved" && approvalEntry.approvedArgs !== void 0) {
|
|
4749
|
-
|
|
4774
|
+
const approvedArgs = approvalEntry.approvedArgs;
|
|
4775
|
+
if (stableJson(approvedArgs) !== stableJson(args)) {
|
|
4776
|
+
const settleRefused = (resolution) => {
|
|
4777
|
+
approvalEntry.metadata = { ...approvalEntry.metadata || {}, resolution };
|
|
4778
|
+
approvalEntry.status = "executed";
|
|
4779
|
+
approvalEntry.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4780
|
+
pendingByCallId.set(toolCallId, approvalEntry);
|
|
4781
|
+
};
|
|
4782
|
+
const revalidated = validateToolArgs(tool, approvedArgs);
|
|
4783
|
+
if (!revalidated.ok && resolved.toolResponses.schemaValidation === "strict") {
|
|
4784
|
+
const message = `Tool argument validation failed for reviewer-edited arguments of ${toolName}: ${revalidated.message}`;
|
|
4785
|
+
push({ role: "tool", content: message, tool_call_id: toolCallId, name: tc.name });
|
|
4786
|
+
markToolFailure(message, toolName, toolCallId);
|
|
4787
|
+
settleRefused("invalid_args");
|
|
4788
|
+
onEvent?.({ type: "tool_call", phase: "error", name: toolName, id: tc.id, args: approvedArgs, error: { message } });
|
|
4789
|
+
toolCount += 1;
|
|
4790
|
+
return { status: "error", approval: approvalEntry };
|
|
4791
|
+
}
|
|
4792
|
+
const gated = await applyPreToolUseGate(revalidated.ok ? revalidated.value : approvedArgs);
|
|
4793
|
+
if (!gated.ok) {
|
|
4794
|
+
settleRefused("policy_denied");
|
|
4795
|
+
return { ...gated.outcome, approval: approvalEntry };
|
|
4796
|
+
}
|
|
4797
|
+
args = gated.args;
|
|
4798
|
+
if (gated.result !== void 0 && hookResult === void 0) hookResult = gated.result;
|
|
4799
|
+
} else {
|
|
4800
|
+
args = approvedArgs;
|
|
4801
|
+
}
|
|
4750
4802
|
onEvent?.({ type: "tool_approval", status: "approved", id: approvalEntry.id, toolName: approvalEntry.toolName, toolCallId: approvalEntry.toolCallId, decidedBy: approvalEntry.decidedBy, comment: approvalEntry.comment });
|
|
4751
4803
|
}
|
|
4752
4804
|
}
|
|
@@ -4756,16 +4808,6 @@ function createToolsNode(initialTools, opts) {
|
|
|
4756
4808
|
const cacheCfg = tool.cache;
|
|
4757
4809
|
const cacheEnabled = cacheCfg === true || cacheCfg && typeof cacheCfg === "object";
|
|
4758
4810
|
const cacheKeyFn = cacheEnabled && typeof cacheCfg === "object" ? cacheCfg.keyFn : void 0;
|
|
4759
|
-
const stableJson = (value) => {
|
|
4760
|
-
try {
|
|
4761
|
-
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
4762
|
-
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
4763
|
-
const keys = Object.keys(value).sort();
|
|
4764
|
-
return `{${keys.map((k) => JSON.stringify(k) + ":" + stableJson(value[k])).join(",")}}`;
|
|
4765
|
-
} catch {
|
|
4766
|
-
return String(value);
|
|
4767
|
-
}
|
|
4768
|
-
};
|
|
4769
4811
|
const cacheKey = cacheEnabled ? `${toolName}|${cacheKeyFn ? cacheKeyFn(args) : stableJson(args)}` : void 0;
|
|
4770
4812
|
const toolCache = state.toolCache = state.toolCache || {};
|
|
4771
4813
|
let cachedHit = void 0;
|
|
@@ -4813,6 +4855,22 @@ function createToolsNode(initialTools, opts) {
|
|
|
4813
4855
|
try {
|
|
4814
4856
|
if (cachedHit !== void 0) {
|
|
4815
4857
|
const executionId2 = nanoid.nanoid();
|
|
4858
|
+
if (host?.has("postToolUse")) {
|
|
4859
|
+
const shortGate = await host.runGate("postToolUse", {
|
|
4860
|
+
toolName,
|
|
4861
|
+
toolCallId,
|
|
4862
|
+
args,
|
|
4863
|
+
output: cachedHit,
|
|
4864
|
+
durationMs: 0,
|
|
4865
|
+
executionId: executionId2,
|
|
4866
|
+
source: shortCircuitSource === "plugin" ? "hook" : "cache"
|
|
4867
|
+
});
|
|
4868
|
+
if (shortGate.decision === "deny") {
|
|
4869
|
+
cachedHit = shortGate.reason || `Tool output withheld by policy: ${toolName}`;
|
|
4870
|
+
} else if (shortGate.input.output !== cachedHit) {
|
|
4871
|
+
cachedHit = shortGate.input.output;
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4816
4874
|
const { output: compressedCachedHit, stats: cachedContextPilotStats } = maybeCompressToolOutput(toolName, cachedHit, executionId2);
|
|
4817
4875
|
const responsePolicy2 = applyToolResponseHardCap(toolName, compressedCachedHit, executionId2, resolved);
|
|
4818
4876
|
toolHistory.push({
|
|
@@ -4979,7 +5037,8 @@ function createToolsNode(initialTools, opts) {
|
|
|
4979
5037
|
args,
|
|
4980
5038
|
output,
|
|
4981
5039
|
durationMs,
|
|
4982
|
-
executionId
|
|
5040
|
+
executionId,
|
|
5041
|
+
source: "tool"
|
|
4983
5042
|
});
|
|
4984
5043
|
if (postGate.decision === "deny") {
|
|
4985
5044
|
output = postGate.reason || `Tool output withheld by policy: ${toolName}`;
|
|
@@ -5074,7 +5133,8 @@ function createToolsNode(initialTools, opts) {
|
|
|
5074
5133
|
output: message,
|
|
5075
5134
|
error: error instanceof Error ? error : new Error(message),
|
|
5076
5135
|
durationMs,
|
|
5077
|
-
executionId
|
|
5136
|
+
executionId,
|
|
5137
|
+
source: "tool"
|
|
5078
5138
|
});
|
|
5079
5139
|
if (errorGate.decision === "deny") {
|
|
5080
5140
|
message = errorGate.reason || `Tool error withheld by policy: ${toolName}`;
|
|
@@ -5750,7 +5810,14 @@ var DISALLOWED_CTX_KEYS = /* @__PURE__ */ new Set([
|
|
|
5750
5810
|
// Session bookkeeping: a resumed run must open its OWN session, so these
|
|
5751
5811
|
// must not travel in a snapshot.
|
|
5752
5812
|
"__pluginRunStarted",
|
|
5753
|
-
"__pluginRunEnded"
|
|
5813
|
+
"__pluginRunEnded",
|
|
5814
|
+
// Set by restoreSnapshot on the way OUT, consumed by the next invoke. Never
|
|
5815
|
+
// persisted: a snapshot of a restored run would otherwise mark every later
|
|
5816
|
+
// restore as "resumed" forever.
|
|
5817
|
+
"__restoredFromSnapshot",
|
|
5818
|
+
// A per-turn verdict. It describes the run that produced the snapshot, not
|
|
5819
|
+
// the run that will resume from it.
|
|
5820
|
+
"__guardrailBlocked"
|
|
5754
5821
|
]);
|
|
5755
5822
|
var clone = (value) => {
|
|
5756
5823
|
if (typeof globalThis.structuredClone === "function") {
|
|
@@ -6374,6 +6441,7 @@ var SLOT_NAMES = [
|
|
|
6374
6441
|
"contextBuilder"
|
|
6375
6442
|
];
|
|
6376
6443
|
var DECISION_RANK = { allow: 0, ask: 1, deny: 2 };
|
|
6444
|
+
var isHookDecision = (value) => typeof value === "string" && Object.prototype.hasOwnProperty.call(DECISION_RANK, value);
|
|
6377
6445
|
function escalate(current, next) {
|
|
6378
6446
|
return DECISION_RANK[next] > DECISION_RANK[current] ? next : current;
|
|
6379
6447
|
}
|
|
@@ -6383,6 +6451,15 @@ var HookTimeoutError = class extends Error {
|
|
|
6383
6451
|
this.name = "HookTimeoutError";
|
|
6384
6452
|
}
|
|
6385
6453
|
};
|
|
6454
|
+
var InvalidHookDecisionError = class extends Error {
|
|
6455
|
+
constructor(plugin, hook, value) {
|
|
6456
|
+
const shown = typeof value === "string" ? JSON.stringify(value) : String(value);
|
|
6457
|
+
super(
|
|
6458
|
+
`plugin "${plugin}" hook "${hook}" returned an unknown decision ${shown}; expected "allow", "ask" or "deny"`
|
|
6459
|
+
);
|
|
6460
|
+
this.name = "InvalidHookDecisionError";
|
|
6461
|
+
}
|
|
6462
|
+
};
|
|
6386
6463
|
function withTimeout(value, ms, label) {
|
|
6387
6464
|
if (!ms || !Number.isFinite(ms) || ms <= 0) return Promise.resolve(value);
|
|
6388
6465
|
return new Promise((resolve, reject) => {
|
|
@@ -6672,10 +6749,18 @@ function createPluginHost(plugins = [], options = {}) {
|
|
|
6672
6749
|
`plugin "${entry.plugin}" hook "${hook}"`
|
|
6673
6750
|
);
|
|
6674
6751
|
output = raw ?? void 0;
|
|
6752
|
+
if (output && typeof output === "object" && output.decision !== void 0 && !isHookDecision(output.decision)) {
|
|
6753
|
+
throw new InvalidHookDecisionError(entry.plugin, hook, output.decision);
|
|
6754
|
+
}
|
|
6675
6755
|
} catch (err) {
|
|
6676
6756
|
const message = err instanceof Error ? err.message : String(err);
|
|
6677
6757
|
const timedOut = err instanceof HookTimeoutError;
|
|
6678
|
-
|
|
6758
|
+
const badDecision = err instanceof InvalidHookDecisionError;
|
|
6759
|
+
if (badDecision) {
|
|
6760
|
+
logger.error(`plugin "${entry.plugin}" hook "${hook}" returned an invalid decision:`, message);
|
|
6761
|
+
} else {
|
|
6762
|
+
logger.warn(`plugin "${entry.plugin}" hook "${hook}" failed:`, message);
|
|
6763
|
+
}
|
|
6679
6764
|
emitPluginEvent(entry, hook, {
|
|
6680
6765
|
phase: timedOut ? "timeout" : "error",
|
|
6681
6766
|
error: { message },
|
|
@@ -6687,8 +6772,9 @@ function createPluginHost(plugins = [], options = {}) {
|
|
|
6687
6772
|
durationMs: performanceNow() - startedAt
|
|
6688
6773
|
});
|
|
6689
6774
|
if (entry.failureMode === "closed") {
|
|
6775
|
+
const cause = timedOut ? "timed out" : badDecision ? "invalid decision" : "hook error";
|
|
6690
6776
|
result.decision = "deny";
|
|
6691
|
-
result.reason = `${entry.plugin}: ${
|
|
6777
|
+
result.reason = `${entry.plugin}: ${cause} (fail-closed) \u2014 ${message}`;
|
|
6692
6778
|
result.deniedBy = entry.plugin;
|
|
6693
6779
|
result.input = current;
|
|
6694
6780
|
return result;
|
|
@@ -6746,11 +6832,19 @@ function createPluginHost(plugins = [], options = {}) {
|
|
|
6746
6832
|
if (output.metadata && typeof output.metadata === "object") {
|
|
6747
6833
|
result.metadata = { ...result.metadata ?? {}, ...output.metadata };
|
|
6748
6834
|
}
|
|
6749
|
-
|
|
6835
|
+
let decision = output.decision;
|
|
6836
|
+
if (decision === "ask" && hook !== "preToolUse") {
|
|
6837
|
+
logger.warn(
|
|
6838
|
+
`plugin "${entry.plugin}" returned "ask" from "${hook}", which cannot pause for approval; treating it as "deny".`
|
|
6839
|
+
);
|
|
6840
|
+
decision = "deny";
|
|
6841
|
+
}
|
|
6750
6842
|
const escalated = decision ? escalate(result.decision, decision) : result.decision;
|
|
6751
6843
|
const escalatesHere = escalated !== result.decision;
|
|
6752
6844
|
result.decision = escalated;
|
|
6753
|
-
if (
|
|
6845
|
+
if (escalatesHere) {
|
|
6846
|
+
result.reason = typeof output.reason === "string" ? `${entry.plugin}: ${output.reason}` : void 0;
|
|
6847
|
+
} else if (typeof output.reason === "string" && !result.reason) {
|
|
6754
6848
|
result.reason = `${entry.plugin}: ${output.reason}`;
|
|
6755
6849
|
}
|
|
6756
6850
|
if (mutatedHere) {
|
|
@@ -6844,7 +6938,7 @@ async function openPluginSession(runHost, params) {
|
|
|
6844
6938
|
const appended = startGate.collected.systemPromptAppend ?? [];
|
|
6845
6939
|
const systemPromptAppend = appended.length > 0 ? appended.join("\n\n") : void 0;
|
|
6846
6940
|
const last = messages[messages.length - 1];
|
|
6847
|
-
if (params.
|
|
6941
|
+
if (params.pausedMidRun || last?.role !== "user" || !runHost.has("userPromptSubmit")) {
|
|
6848
6942
|
return { messages, systemPromptAppend };
|
|
6849
6943
|
}
|
|
6850
6944
|
const content = last.content;
|
|
@@ -7089,6 +7183,11 @@ function createAgent(opts) {
|
|
|
7089
7183
|
delete nextCtx.__paused;
|
|
7090
7184
|
state = { ...state, ctx: Object.keys(nextCtx).length > 0 ? nextCtx : void 0 };
|
|
7091
7185
|
}
|
|
7186
|
+
if (state.ctx?.__restoredFromSnapshot) {
|
|
7187
|
+
const nextCtx = { ...state.ctx };
|
|
7188
|
+
delete nextCtx.__restoredFromSnapshot;
|
|
7189
|
+
state = { ...state, ctx: Object.keys(nextCtx).length > 0 ? nextCtx : void 0 };
|
|
7190
|
+
}
|
|
7092
7191
|
let resumeStage = null;
|
|
7093
7192
|
if (state.ctx?.__resumeStage) {
|
|
7094
7193
|
const nextCtx = { ...state.ctx };
|
|
@@ -7363,7 +7462,7 @@ function createAgent(opts) {
|
|
|
7363
7462
|
continue;
|
|
7364
7463
|
}
|
|
7365
7464
|
if (toolCalls.length === 0) {
|
|
7366
|
-
if (soManager && !state.ctx?.__finalizedDueToStructuredOutput && !state.ctx?.__structuredOutputForceFinalize) {
|
|
7465
|
+
if (soManager && !state.ctx?.__finalizedDueToStructuredOutput && !state.ctx?.__structuredOutputForceFinalize && !state.ctx?.__guardrailBlocked) {
|
|
7367
7466
|
if (soManager.strategy.kind === "native") {
|
|
7368
7467
|
const assistantText = extractMessageText2(lastMsg);
|
|
7369
7468
|
if (assistantText) {
|
|
@@ -7532,6 +7631,7 @@ function createAgent(opts) {
|
|
|
7532
7631
|
delete ctx.__plugins;
|
|
7533
7632
|
delete ctx.__applySystemPromptContribution;
|
|
7534
7633
|
delete ctx.__pluginState;
|
|
7634
|
+
delete ctx.__guardrailBlocked;
|
|
7535
7635
|
const inheritedSession = config?.__pluginSession;
|
|
7536
7636
|
ctx.__runId = inheritedSession?.runId ?? traceSession?.sessionId ?? `run_${nanoid.nanoid(10)}`;
|
|
7537
7637
|
const stateHolder = inheritedSession?.stateHolder ?? { value: void 0 };
|
|
@@ -7581,9 +7681,11 @@ function createAgent(opts) {
|
|
|
7581
7681
|
usage: input.usage || { perRequest: [], totals: {} }
|
|
7582
7682
|
};
|
|
7583
7683
|
stateHolder.value = initial;
|
|
7584
|
-
const
|
|
7585
|
-
input.ctx?.
|
|
7684
|
+
const pausedMidRun = Boolean(
|
|
7685
|
+
input.ctx?.__paused || input.ctx?.__resumeStage || input.ctx?.__awaitingApproval || input.ctx?.__awaitingUserQuestion
|
|
7586
7686
|
);
|
|
7687
|
+
const resumed = Boolean(input.ctx?.__restoredFromSnapshot || pausedMidRun);
|
|
7688
|
+
delete ctx.__restoredFromSnapshot;
|
|
7587
7689
|
const startedAt = Date.now();
|
|
7588
7690
|
let sessionEnded = false;
|
|
7589
7691
|
const endSession = async (status, payload) => {
|
|
@@ -7609,6 +7711,7 @@ function createAgent(opts) {
|
|
|
7609
7711
|
const opened = await openPluginSession(runHost, {
|
|
7610
7712
|
messages: initial.messages,
|
|
7611
7713
|
resumed,
|
|
7714
|
+
pausedMidRun,
|
|
7612
7715
|
config
|
|
7613
7716
|
});
|
|
7614
7717
|
if (opened.messages !== initial.messages) {
|
|
@@ -10265,6 +10368,11 @@ ${pluginAppend}`;
|
|
|
10265
10368
|
const instance = {
|
|
10266
10369
|
invoke: async (input, config) => {
|
|
10267
10370
|
await ensurePluginSetup();
|
|
10371
|
+
if (input?.ctx?.__guardrailBlocked !== void 0) {
|
|
10372
|
+
const clearedCtx = { ...input.ctx };
|
|
10373
|
+
delete clearedCtx.__guardrailBlocked;
|
|
10374
|
+
input = { ...input, ctx: clearedCtx };
|
|
10375
|
+
}
|
|
10268
10376
|
const sessionHolder = { value: input };
|
|
10269
10377
|
const emitSessionEvent = (event) => {
|
|
10270
10378
|
try {
|
|
@@ -10315,12 +10423,20 @@ ${pluginAppend}`;
|
|
|
10315
10423
|
stateHolder: sessionHolder
|
|
10316
10424
|
}
|
|
10317
10425
|
};
|
|
10318
|
-
const
|
|
10319
|
-
input.ctx?.
|
|
10426
|
+
const pausedMidRun = Boolean(
|
|
10427
|
+
input.ctx?.__paused || input.ctx?.__resumeStage || input.ctx?.__awaitingApproval || input.ctx?.__awaitingUserQuestion
|
|
10320
10428
|
);
|
|
10429
|
+
const resumed = Boolean(input.ctx?.__restoredFromSnapshot || pausedMidRun);
|
|
10430
|
+
if (input.ctx?.__restoredFromSnapshot) {
|
|
10431
|
+
const consumedCtx = { ...input.ctx };
|
|
10432
|
+
delete consumedCtx.__restoredFromSnapshot;
|
|
10433
|
+
input = { ...input, ctx: consumedCtx };
|
|
10434
|
+
sessionHolder.value = input;
|
|
10435
|
+
}
|
|
10321
10436
|
const opened = await openPluginSession(runHost, {
|
|
10322
10437
|
messages: input.messages || [],
|
|
10323
10438
|
resumed,
|
|
10439
|
+
pausedMidRun,
|
|
10324
10440
|
config
|
|
10325
10441
|
});
|
|
10326
10442
|
if (opened.denied) {
|
|
@@ -11110,7 +11226,7 @@ var HOOKS = {
|
|
|
11110
11226
|
sessionStart: { implemented: true },
|
|
11111
11227
|
userPromptSubmit: {
|
|
11112
11228
|
implemented: true,
|
|
11113
|
-
notes: "Fires once per run
|
|
11229
|
+
notes: "Fires once per run whenever the transcript tail is a NEW user turn \u2014 including a turn appended to a state that was restored from a snapshot. Skipped on a genuine resume, where the tail is a tool result rather than a user message."
|
|
11114
11230
|
},
|
|
11115
11231
|
preModelCall: {
|
|
11116
11232
|
implemented: true,
|
|
@@ -11123,7 +11239,7 @@ var HOOKS = {
|
|
|
11123
11239
|
},
|
|
11124
11240
|
postToolUse: {
|
|
11125
11241
|
implemented: true,
|
|
11126
|
-
notes: "Raw output, before compression and the hard cap. Also fires on a tool ERROR. Does NOT fire for a call that parks the run."
|
|
11242
|
+
notes: "Raw output, before compression and the hard cap. Also fires on a tool ERROR, on a preToolUse `result` short-circuit and on a tool-cache hit (`input.source` says which). Does NOT fire for a call that parks the run."
|
|
11127
11243
|
},
|
|
11128
11244
|
preCompact: { implemented: true },
|
|
11129
11245
|
postCompact: { implemented: true },
|
|
@@ -12107,6 +12223,12 @@ function auditLog(config = {}) {
|
|
|
12107
12223
|
return "[unserializable]";
|
|
12108
12224
|
}
|
|
12109
12225
|
};
|
|
12226
|
+
const renderDetail = (detail) => {
|
|
12227
|
+
if (!detail || typeof detail !== "object" || Array.isArray(detail) || !("args" in detail)) return detail;
|
|
12228
|
+
const { args, ...rest } = detail;
|
|
12229
|
+
const rendered = renderArgs(args);
|
|
12230
|
+
return rendered === void 0 ? rest : { ...rest, args: rendered };
|
|
12231
|
+
};
|
|
12110
12232
|
return {
|
|
12111
12233
|
name: config.name ?? "audit-log",
|
|
12112
12234
|
// Lowest number: runs first, so denials by later plugins are still recorded
|
|
@@ -12135,7 +12257,7 @@ function auditLog(config = {}) {
|
|
|
12135
12257
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12136
12258
|
kind: "notification",
|
|
12137
12259
|
status: kind,
|
|
12138
|
-
detail
|
|
12260
|
+
detail: renderDetail(detail)
|
|
12139
12261
|
});
|
|
12140
12262
|
},
|
|
12141
12263
|
sessionEnd: async ({ status }, ctx) => {
|