bazis 0.99.1 → 0.99.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/core/agent/AgentToolExecutor.ts +37 -32
- package/core/agent/README.md +8 -0
- package/core/agent/errors.ts +15 -2
- package/core/agent/index.ts +1 -0
- package/core/agent/internal/AgentExecutionDriver.ts +13 -1
- package/core/infra/connectors/codex/CodexAppServerClient.ts +1 -1
- package/core/infra/connectors/llm.ts +3 -1
- package/index.ts +1 -0
- package/package.json +1 -1
|
@@ -7,7 +7,8 @@ import { assertAgentToolHookIdV1, getAgentModuleContributionsV1, type AgentModul
|
|
|
7
7
|
import type { AgentToolBeforeEffectEventV1, AgentToolEnforcementDecisionV1, AgentToolHookContextV1, AgentToolRequiredHookRefV1, AgentToolAuditHookProjectionV1, AgentToolSettlementEventV1 } from "./AgentToolHooks";
|
|
8
8
|
import { agentModelJson } from "./internal/AgentModelBinding";
|
|
9
9
|
import { redactSensitive, type SensitiveRedactionOptions } from "../../library/redaction";
|
|
10
|
-
import { AgentSetupError, AgentToolExecutionError, AgentToolPreCommitError } from "./errors";
|
|
10
|
+
import { AgentSetupError, AgentToolExecutionError, AgentToolPreCommitError, ToolError } from "./errors";
|
|
11
|
+
import type { Logger } from "../kernel/logging/Logger";
|
|
11
12
|
import type { AgentRegistry, ToolDefinition } from "./AgentRegistry";
|
|
12
13
|
import type { JsonObject, JsonValue, AgentToolCall, AgentToolResult } from "./semantic";
|
|
13
14
|
import { agentToolCall, agentToolResult, normalizeJsonValue } from "./semantic";
|
|
@@ -430,6 +431,8 @@ export class AgentToolExecutor {
|
|
|
430
431
|
private readonly services: ServiceProvider,
|
|
431
432
|
private readonly registry: AgentRegistry,
|
|
432
433
|
options: AgentToolExecutorOptions = {},
|
|
434
|
+
/** Where unexpected tool failures go with their stack; the model sees a generic message. */
|
|
435
|
+
private readonly logger?: Logger,
|
|
433
436
|
) {
|
|
434
437
|
assertNonNegativeInteger(options.defaultTimeoutMs, "AgentToolExecutor.defaultTimeoutMs");
|
|
435
438
|
assertPositiveInteger(options.scopeDisposeTimeoutMs, "AgentToolExecutor.scopeDisposeTimeoutMs");
|
|
@@ -1530,15 +1533,12 @@ export class AgentToolExecutor {
|
|
|
1530
1533
|
);
|
|
1531
1534
|
});
|
|
1532
1535
|
const code = this.interruptionCode(error, tool, executionState);
|
|
1536
|
+
if (code.endsWith("_OUTCOME_UNKNOWN")) {
|
|
1537
|
+
this.logger?.error("Agent tool outcome unknown", { agent: agentName ?? null, tool: call.name, callId: call.id, code, phase: executionState.phase });
|
|
1538
|
+
}
|
|
1533
1539
|
return this.errorResult(call, code, executionState.timedOut ? "Tool execution timed out." : errorMessageOf(error), this.attemptMetadata(metadata, attempt), startedAt, { phase: executionState.phase });
|
|
1534
1540
|
}
|
|
1535
|
-
result = this.
|
|
1536
|
-
call,
|
|
1537
|
-
"TOOL_EXECUTION_FAILED",
|
|
1538
|
-
errorMessageOf(error),
|
|
1539
|
-
this.attemptMetadata(metadata, attempt),
|
|
1540
|
-
startedAt,
|
|
1541
|
-
);
|
|
1541
|
+
result = this.failedResult(call, agentName, "TOOL_EXECUTION_FAILED", error, "Tool execution failed.", this.attemptMetadata(metadata, attempt), startedAt);
|
|
1542
1542
|
} finally {
|
|
1543
1543
|
detach?.();
|
|
1544
1544
|
}
|
|
@@ -1582,13 +1582,7 @@ export class AgentToolExecutor {
|
|
|
1582
1582
|
? await contributed[0]!.activation.activateAsync(scope)
|
|
1583
1583
|
: await scope.resolveAsync(tool.target);
|
|
1584
1584
|
} catch (error) {
|
|
1585
|
-
return this.
|
|
1586
|
-
call,
|
|
1587
|
-
"TOOL_RESOLVE_FAILED",
|
|
1588
|
-
`Tool resolve failed: ${errorMessageOf(error)}`,
|
|
1589
|
-
this.attemptMetadata(metadata, attempt),
|
|
1590
|
-
startedAt,
|
|
1591
|
-
);
|
|
1585
|
+
return this.failedResult(call, agentName, "TOOL_RESOLVE_FAILED", error, "Tool could not be created.", this.attemptMetadata(metadata, attempt), startedAt);
|
|
1592
1586
|
}
|
|
1593
1587
|
|
|
1594
1588
|
if (signal.aborted) {
|
|
@@ -1638,12 +1632,14 @@ export class AgentToolExecutor {
|
|
|
1638
1632
|
const explicitlyPreCommit = error instanceof AgentToolPreCommitError;
|
|
1639
1633
|
const outcomeUnknown = !explicitlyPreCommit
|
|
1640
1634
|
&& (tool.metadata.sideEffect === "write" || tool.metadata.sideEffect === "external");
|
|
1641
|
-
return this.
|
|
1635
|
+
return this.failedResult(
|
|
1642
1636
|
call,
|
|
1637
|
+
agentName,
|
|
1643
1638
|
outcomeUnknown ? "TOOL_EXECUTION_FAILED_OUTCOME_UNKNOWN" : "TOOL_EXECUTION_FAILED",
|
|
1639
|
+
error,
|
|
1644
1640
|
outcomeUnknown
|
|
1645
|
-
? `Tool "${tool.metadata.name}" threw after side-effect execution started; retry safety is unknown
|
|
1646
|
-
:
|
|
1641
|
+
? `Tool "${tool.metadata.name}" threw after side-effect execution started; retry safety is unknown.`
|
|
1642
|
+
: "Tool execution failed.",
|
|
1647
1643
|
this.attemptMetadata(metadata, attempt),
|
|
1648
1644
|
startedAt,
|
|
1649
1645
|
outcomeUnknown ? { sideEffect: tool.metadata.sideEffect, phase: "execute" } : undefined,
|
|
@@ -1664,13 +1660,7 @@ export class AgentToolExecutor {
|
|
|
1664
1660
|
return this.postExecutionOutcome(
|
|
1665
1661
|
call,
|
|
1666
1662
|
tool,
|
|
1667
|
-
this.
|
|
1668
|
-
call,
|
|
1669
|
-
"TOOL_OUTPUT_INVALID",
|
|
1670
|
-
`Tool output processing failed: ${errorMessageOf(error)}`,
|
|
1671
|
-
this.attemptMetadata(metadata, attempt),
|
|
1672
|
-
startedAt,
|
|
1673
|
-
),
|
|
1663
|
+
this.failedResult(call, agentName, "TOOL_OUTPUT_INVALID", error, "Tool output processing failed.", this.attemptMetadata(metadata, attempt), startedAt),
|
|
1674
1664
|
metadata,
|
|
1675
1665
|
startedAt,
|
|
1676
1666
|
attempt,
|
|
@@ -1692,13 +1682,7 @@ export class AgentToolExecutor {
|
|
|
1692
1682
|
return this.postExecutionOutcome(
|
|
1693
1683
|
call,
|
|
1694
1684
|
tool,
|
|
1695
|
-
this.
|
|
1696
|
-
call,
|
|
1697
|
-
"TOOL_RESULT_INVALID",
|
|
1698
|
-
errorMessageOf(error),
|
|
1699
|
-
this.attemptMetadata(metadata, attempt),
|
|
1700
|
-
startedAt,
|
|
1701
|
-
),
|
|
1685
|
+
this.failedResult(call, agentName, "TOOL_RESULT_INVALID", error, "Tool result is invalid.", this.attemptMetadata(metadata, attempt), startedAt),
|
|
1702
1686
|
metadata,
|
|
1703
1687
|
startedAt,
|
|
1704
1688
|
attempt,
|
|
@@ -2056,6 +2040,27 @@ export class AgentToolExecutor {
|
|
|
2056
2040
|
}
|
|
2057
2041
|
|
|
2058
2042
|
|
|
2043
|
+
/**
|
|
2044
|
+
* A tool's own failure: a ToolError message reaches the model as written;
|
|
2045
|
+
* anything else is replaced by `fallback` and logged with its stack.
|
|
2046
|
+
*/
|
|
2047
|
+
private failedResult(
|
|
2048
|
+
call: AgentToolCall,
|
|
2049
|
+
agentName: string | undefined,
|
|
2050
|
+
code: string,
|
|
2051
|
+
error: unknown,
|
|
2052
|
+
fallback: string,
|
|
2053
|
+
metadata: JsonObject,
|
|
2054
|
+
startedAt: number,
|
|
2055
|
+
details?: JsonObject,
|
|
2056
|
+
): AgentToolResult {
|
|
2057
|
+
if (error instanceof ToolError) {
|
|
2058
|
+
return this.errorResult(call, code, error.message, metadata, startedAt, details);
|
|
2059
|
+
}
|
|
2060
|
+
this.logger?.error("Agent tool failed", { agent: agentName ?? null, tool: call.name, callId: call.id, code, error: redactSensitive(error) });
|
|
2061
|
+
return this.errorResult(call, code, fallback, metadata, startedAt, details);
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2059
2064
|
private errorResult(
|
|
2060
2065
|
call: AgentToolCall,
|
|
2061
2066
|
code: string,
|
package/core/agent/README.md
CHANGED
|
@@ -100,6 +100,14 @@ Tool input and output are validated by the model validator
|
|
|
100
100
|
otherwise. Audit entries redact `input`, `result` and execution `metadata`
|
|
101
101
|
by default using `bazis/library/redaction`.
|
|
102
102
|
|
|
103
|
+
A tool reports a failure to the model with `throw new ToolError("Product
|
|
104
|
+
kiwi is no longer sold")`: the message reaches the model as written. Any other
|
|
105
|
+
exception from `execute` reaches the model as `Tool execution failed.` — internal
|
|
106
|
+
details stay out of the LLM — and goes to the application log with its stack
|
|
107
|
+
(`Agent tool failed`). Failures of the model itself are logged as `Agent model
|
|
108
|
+
call failed`. The LLM connectors pass the application logger; a runtime created
|
|
109
|
+
by hand takes `options.logger`.
|
|
110
|
+
|
|
103
111
|
Retries are opt-in. `write` and `external` tools need an idempotency key before
|
|
104
112
|
the executor repeats them. Runtime-generated keys include both the invocation id
|
|
105
113
|
and the unique model call id; `toolExecution.idempotencyKeyForCall` gives a
|
package/core/agent/errors.ts
CHANGED
|
@@ -22,12 +22,25 @@ export class AgentToolExecutionError extends Error {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* A failure a tool reports to the model on purpose: the message reaches the
|
|
27
|
+
* model as written, so the model can explain it or try another way. Any other
|
|
28
|
+
* exception from `execute` reaches the model as "Tool execution failed." and
|
|
29
|
+
* goes to the application log with its stack.
|
|
30
|
+
*/
|
|
31
|
+
export class ToolError extends Error {
|
|
32
|
+
constructor(message: string) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = "ToolError";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
25
38
|
/**
|
|
26
39
|
* Explicit assertion by a tool that execution failed before any side effect
|
|
27
40
|
* could commit. Only this typed error keeps write/external failures eligible
|
|
28
|
-
* for an idempotency-gated retry.
|
|
41
|
+
* for an idempotency-gated retry. Its message reaches the model like a ToolError.
|
|
29
42
|
*/
|
|
30
|
-
export class AgentToolPreCommitError extends
|
|
43
|
+
export class AgentToolPreCommitError extends ToolError {
|
|
31
44
|
constructor(message: string) {
|
|
32
45
|
super(message);
|
|
33
46
|
this.name = "AgentToolPreCommitError";
|
package/core/agent/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { describeTool } from "../Tool.contract";
|
|
|
3
3
|
import type { ServiceProvider } from "../../di";
|
|
4
4
|
import { getGeneratedOpenApiMetadata } from "../../http/OpenApi/generatedOpenApiRegistry";
|
|
5
5
|
import { redactSensitive, redactSensitiveText } from "../../../library/redaction";
|
|
6
|
+
import type { Logger } from "../../kernel/logging/Logger";
|
|
6
7
|
import { AgentRuntimeError } from "../errors";
|
|
7
8
|
import { validateAgentJsonSchema } from "./AgentJsonSchema";
|
|
8
9
|
import type { AgentDefinition, AgentRegistry } from "../AgentRegistry";
|
|
@@ -80,6 +81,11 @@ export interface AgentRuntimeOptions {
|
|
|
80
81
|
readonly contextBuilder?: AgentContextBuilder;
|
|
81
82
|
readonly contextLimits?: AgentContextLimits;
|
|
82
83
|
readonly toolExecutorOptions?: AgentToolExecutorOptions;
|
|
84
|
+
/**
|
|
85
|
+
* Where failures of the model and unexpected tool failures go, with their
|
|
86
|
+
* stack. The LLM connectors pass the application logger.
|
|
87
|
+
*/
|
|
88
|
+
readonly logger?: Logger;
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
export interface AgentRuntimeInvokeOptions {
|
|
@@ -503,6 +509,7 @@ export class AgentExecutionDriver {
|
|
|
503
509
|
readonly defaultTimeoutMs?: number;
|
|
504
510
|
private readonly defaultContextLimits?: AgentContextLimits;
|
|
505
511
|
private readonly contextBuilder: AgentContextBuilder;
|
|
512
|
+
private readonly logger?: Logger;
|
|
506
513
|
|
|
507
514
|
constructor(
|
|
508
515
|
services: ServiceProvider,
|
|
@@ -521,7 +528,8 @@ export class AgentExecutionDriver {
|
|
|
521
528
|
: options.timeoutMs ?? DEFAULT_MODEL_TIMEOUT_MS;
|
|
522
529
|
this.defaultContextLimits = normalizeAgentContextLimits(options.contextLimits, "AgentRuntime.contextLimits");
|
|
523
530
|
this.contextBuilder = options.contextBuilder ?? new DefaultAgentContextBuilder();
|
|
524
|
-
this.
|
|
531
|
+
this.logger = options.logger;
|
|
532
|
+
this.toolExecutor = new AgentToolExecutor(services, registry, options.toolExecutorOptions, options.logger);
|
|
525
533
|
}
|
|
526
534
|
|
|
527
535
|
async invoke(agentName: string, options: AgentRuntimeInvokeOptions = {}): Promise<AgentRuntimeResult> {
|
|
@@ -1122,6 +1130,7 @@ export class AgentExecutionDriver {
|
|
|
1122
1130
|
try {
|
|
1123
1131
|
return { ok: true, value: normalizeProviderResponse(rawResponse) };
|
|
1124
1132
|
} catch (error) {
|
|
1133
|
+
this.logger?.error("Agent model call failed", { agent: agentName, invocationId: request.invocationId, code: "AGENT_PROVIDER_RESPONSE_INVALID", error: redactSensitive(error) });
|
|
1125
1134
|
return {
|
|
1126
1135
|
ok: false,
|
|
1127
1136
|
error: runtimeError("AGENT_PROVIDER_RESPONSE_INVALID", `Model provider returned an invalid response: ${errorMessageOf(error)}`),
|
|
@@ -1133,6 +1142,9 @@ export class AgentExecutionDriver {
|
|
|
1133
1142
|
: error instanceof AgentRuntimeAbortError
|
|
1134
1143
|
? "AGENT_ABORTED"
|
|
1135
1144
|
: "AGENT_PROVIDER_FAILED";
|
|
1145
|
+
if (code !== "AGENT_ABORTED") {
|
|
1146
|
+
this.logger?.error("Agent model call failed", { agent: agentName, invocationId: request.invocationId, code, error: redactSensitive(error) });
|
|
1147
|
+
}
|
|
1136
1148
|
return { ok: false, error: runtimeError(code, errorMessageOf(error)) };
|
|
1137
1149
|
} finally {
|
|
1138
1150
|
acceptingText = false;
|
|
@@ -232,7 +232,7 @@ export class CodexAppServerClient implements CodexClient {
|
|
|
232
232
|
if (method === "account/updated") this.modelCache = undefined;
|
|
233
233
|
}, () => { this.clearLogin(); this.modelCache = undefined; });
|
|
234
234
|
const initialized = await client.request("initialize", {
|
|
235
|
-
clientInfo: { name: "bazis", title: "Bazis", version: "0.99.
|
|
235
|
+
clientInfo: { name: "bazis", title: "Bazis", version: "0.99.2" }, capabilities: { experimentalApi: true },
|
|
236
236
|
}, 15_000, signal);
|
|
237
237
|
if (resolve(text(initialized.codexHome, 4096)) !== this.paths.home) throw new CodexError("PROTOCOL_ERROR");
|
|
238
238
|
client.notify("initialized");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AppConfig, ConfigRegistry, Secret } from "../../kernel";
|
|
2
2
|
import { AGENT_MODEL_PROVIDER, AGENT_RUNTIME_OPTIONS, AgentRuntime, type AgentModelProvider } from "../../agent";
|
|
3
3
|
import { DI, SERVICE_PROVIDER, type ProviderDefinition } from "../../di";
|
|
4
|
+
import { LOGGER } from "../../kernel/logging/Logger";
|
|
4
5
|
import { reader, requireValue } from "../connectorConfig";
|
|
5
6
|
import { InfraError, type InfraConnector } from "../InfraConnector";
|
|
6
7
|
import { identifyConnector } from "../connectorIdentity";
|
|
@@ -62,7 +63,8 @@ export function resolveLlmConnectionOptions<T extends LlmConfigShape>(
|
|
|
62
63
|
export const agentRuntimeProviders: readonly ProviderDefinition[] = Object.freeze([
|
|
63
64
|
DI.singleton(DI.factoryProviderWithResolver(AgentRuntime, [AGENT_MODEL_PROVIDER], (resolver, model: AgentModelProvider) => {
|
|
64
65
|
const services = resolver.resolve(SERVICE_PROVIDER);
|
|
65
|
-
|
|
66
|
+
const options = services.has(AGENT_RUNTIME_OPTIONS) ? services.resolve(AGENT_RUNTIME_OPTIONS) : {};
|
|
67
|
+
return new AgentRuntime(services, model, { ...options, logger: options.logger ?? services.tryResolve(LOGGER) });
|
|
66
68
|
})),
|
|
67
69
|
]);
|
|
68
70
|
|
package/index.ts
CHANGED
package/package.json
CHANGED