@intx/agent 0.3.0 → 0.4.0
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.js +5 -0
- package/dist/credential-resolver.d.ts +16 -0
- package/dist/credential-resolver.js +33 -0
- package/dist/env.d.ts +26 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/internal-fixtures/mail.js +1 -1
- package/dist/internal-fixtures/planner.js +1 -1
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +1 -0
- package/dist/testing/reactor-waiters.d.ts +13 -0
- package/dist/testing/reactor-waiters.js +23 -0
- package/package.json +6 -6
package/dist/agent.js
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
// contract; the caller owns the lifetime of what it puts in env.
|
|
43
43
|
import { createReactorAssembly, } from "@intx/inference";
|
|
44
44
|
import { createDefaultDependencies } from "@intx/inference/providers";
|
|
45
|
+
import { createUnconfiguredCredentialResolver } from "./credential-resolver.js";
|
|
45
46
|
import { getLogger } from "@intx/log";
|
|
46
47
|
import { createInboundMessage } from "@intx/mime";
|
|
47
48
|
import { validateDirectorConfig } from "./director.js";
|
|
@@ -489,6 +490,7 @@ export async function createAgent(def, env) {
|
|
|
489
490
|
source: sourceRegistry.active,
|
|
490
491
|
failOverToNextSource: () => sourceRegistry.failOverToNextSource(),
|
|
491
492
|
resetToPreferredSource: () => sourceRegistry.resetToPreferredSource(),
|
|
493
|
+
readMaterial: env.readCurrentMaterial ?? createUnconfiguredCredentialResolver(),
|
|
492
494
|
toolRunner: resolvedTools.runner,
|
|
493
495
|
contextStore,
|
|
494
496
|
onEvent: handleEvent,
|
|
@@ -507,6 +509,9 @@ export async function createAgent(def, env) {
|
|
|
507
509
|
...(env.sizeCapMaxChars !== undefined
|
|
508
510
|
? { sizeCapMaxChars: env.sizeCapMaxChars }
|
|
509
511
|
: {}),
|
|
512
|
+
...(env.doomLoopThreshold !== undefined
|
|
513
|
+
? { doomLoopThreshold: env.doomLoopThreshold }
|
|
514
|
+
: {}),
|
|
510
515
|
deps,
|
|
511
516
|
...(env.compactors !== undefined ? { compactors: env.compactors } : {}),
|
|
512
517
|
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CredentialMaterialResolver } from "@intx/types";
|
|
2
|
+
/**
|
|
3
|
+
* A resolver that fails closed on every call. `createAgent` installs this when
|
|
4
|
+
* the env supplies no `readCurrentMaterial`, so an agent whose inference never
|
|
5
|
+
* resolves a credential (a mock adapter emitting no credential sentinel) needs
|
|
6
|
+
* no resolver, while one that DOES reach a credential surfaces a clear error
|
|
7
|
+
* rather than a confusing `undefined`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createUnconfiguredCredentialResolver(): CredentialMaterialResolver;
|
|
10
|
+
/**
|
|
11
|
+
* A resolver over a fixed `credentialId -> secret` map. For callers that hold
|
|
12
|
+
* their secrets in memory rather than a live cell -- examples, tests, and any
|
|
13
|
+
* single-process agent. Fails closed when a source references a credential the
|
|
14
|
+
* map does not carry, mirroring the cell reader's revoked/absent behavior.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createStaticCredentialResolver(materials: Record<string, string>): CredentialMaterialResolver;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Helpers for the inference credential-material resolver seam
|
|
2
|
+
// (`CredentialMaterialResolver` in `@intx/types`). An inference call resolves
|
|
3
|
+
// its source's secret by `credentialId` through this seam instead of reading an
|
|
4
|
+
// inline `apiKey`, so the source config carries no secret. The sidecar backs it
|
|
5
|
+
// with the run's live credential cell; the helpers here cover the two simpler
|
|
6
|
+
// cases.
|
|
7
|
+
/**
|
|
8
|
+
* A resolver that fails closed on every call. `createAgent` installs this when
|
|
9
|
+
* the env supplies no `readCurrentMaterial`, so an agent whose inference never
|
|
10
|
+
* resolves a credential (a mock adapter emitting no credential sentinel) needs
|
|
11
|
+
* no resolver, while one that DOES reach a credential surfaces a clear error
|
|
12
|
+
* rather than a confusing `undefined`.
|
|
13
|
+
*/
|
|
14
|
+
export function createUnconfiguredCredentialResolver() {
|
|
15
|
+
return (credentialId) => {
|
|
16
|
+
throw new Error(`no credential resolver configured for this agent, but an inference call needs the secret for credential ${credentialId}; supply env.readCurrentMaterial`);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A resolver over a fixed `credentialId -> secret` map. For callers that hold
|
|
21
|
+
* their secrets in memory rather than a live cell -- examples, tests, and any
|
|
22
|
+
* single-process agent. Fails closed when a source references a credential the
|
|
23
|
+
* map does not carry, mirroring the cell reader's revoked/absent behavior.
|
|
24
|
+
*/
|
|
25
|
+
export function createStaticCredentialResolver(materials) {
|
|
26
|
+
return (credentialId) => {
|
|
27
|
+
const secret = materials[credentialId];
|
|
28
|
+
if (secret === undefined) {
|
|
29
|
+
throw new Error(`no credential material for ${credentialId} in the static resolver`);
|
|
30
|
+
}
|
|
31
|
+
return { secret };
|
|
32
|
+
};
|
|
33
|
+
}
|
package/dist/env.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AuthzCallResult, Dependencies } from "@intx/inference";
|
|
2
|
+
import type { CredentialMaterialResolver } from "@intx/types";
|
|
2
3
|
import type { AuditStore, Compactor, ContextStore, InferenceSource } from "@intx/types/runtime";
|
|
3
4
|
import type { DirectorRegistry } from "./director-types.js";
|
|
4
5
|
export type { Dependencies };
|
|
@@ -50,6 +51,12 @@ export interface BaseEnv {
|
|
|
50
51
|
* `workdir` values pointing at the same on-disk storage directory
|
|
51
52
|
* will silently corrupt each other -- the invariant is the caller's
|
|
52
53
|
* to maintain.
|
|
54
|
+
*
|
|
55
|
+
* This is the lock and storage boundary, not the working tree the
|
|
56
|
+
* filesystem tools operate on. A tool that needs a working directory
|
|
57
|
+
* (e.g. `@intx/tools-posix`) reads that from its own env-DI key
|
|
58
|
+
* declared through `defineTool({ requires })`, which the caller may
|
|
59
|
+
* point at a directory distinct from `workdir`.
|
|
53
60
|
*/
|
|
54
61
|
workdir: string;
|
|
55
62
|
/** Audit sink. Required; no read-site fallback. */
|
|
@@ -90,6 +97,18 @@ export interface BaseEnv {
|
|
|
90
97
|
* Optional; do not require this field on the production path.
|
|
91
98
|
*/
|
|
92
99
|
deps?: Dependencies;
|
|
100
|
+
/**
|
|
101
|
+
* Resolves an inference source's credential secret by `credentialId` from the
|
|
102
|
+
* run's credential-material cell at send time -- the same cell tool
|
|
103
|
+
* credentials resolve from, so the source config carries no inline secret.
|
|
104
|
+
*
|
|
105
|
+
* Optional at this boundary only to spare callers whose inference never
|
|
106
|
+
* resolves a credential (a mock adapter that emits no credential sentinel).
|
|
107
|
+
* `createAgent` fills a fail-closed default that throws if an inference call
|
|
108
|
+
* actually needs a secret; a caller that does real credentialed inference (the
|
|
109
|
+
* sidecar step env, an example, a test with a real adapter) MUST supply one.
|
|
110
|
+
*/
|
|
111
|
+
readCurrentMaterial?: CredentialMaterialResolver;
|
|
93
112
|
/**
|
|
94
113
|
* Optional deterministic session id. Production callers omit and let
|
|
95
114
|
* the agent generate a fresh UUID; tests that assert on audit-record
|
|
@@ -101,6 +120,13 @@ export interface BaseEnv {
|
|
|
101
120
|
* Forwarded to the reactor assembly's size-cap transform.
|
|
102
121
|
*/
|
|
103
122
|
sizeCapMaxChars?: number;
|
|
123
|
+
/**
|
|
124
|
+
* Override for the default doom-loop detection threshold: the number of
|
|
125
|
+
* identical consecutive tool-call turns that ends the run (default 3).
|
|
126
|
+
* Forwarded to the reactor. Must be a positive integer, or `false` to
|
|
127
|
+
* disable doom-loop detection entirely.
|
|
128
|
+
*/
|
|
129
|
+
doomLoopThreshold?: number | false;
|
|
104
130
|
/**
|
|
105
131
|
* Maximum number of pending sends (active + queued). Beyond this,
|
|
106
132
|
* `send()` rejects with `SendQueueFullError`. Defaults to 16.
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { AgentContextLockError } from "./lock.js";
|
|
|
2
2
|
export { type AgentTool, type AgentToolRunner, type AnnotatedPluginFactory, type AnnotatedPluginMeta, type AnnotatedToolFactory, type PluginFactory, type StringToolHandler, type ToolBundle, type ToolDeclaration, type ToolFactory, type ToolFactoryMeta, type ToolHandler, DuplicateToolError, PLUGIN_MARKER, TOOL_PLUGIN_KIND, type ToolPluginKind, createToolRunner, defineTool, definePlugin, fromToolRunner, isAnnotatedPluginFactory, isToolPluginInstance, stringTool, tool, toolApprovalEffect, } from "./tool.js";
|
|
3
3
|
export { type AuthorizeFn, type BaseEnv, type Dependencies, AgentEnvError, } from "./env.js";
|
|
4
4
|
export { type AnnotatedDirectorFactory, type DirectorAgentContext, type DirectorConfigSchema, type DirectorFactory, type DirectorFactoryMeta, type DirectorRef, type DirectorRegistry, } from "./director-types.js";
|
|
5
|
+
export { createStaticCredentialResolver, createUnconfiguredCredentialResolver, } from "./credential-resolver.js";
|
|
5
6
|
export { validateNamespacedId } from "./namespace.js";
|
|
6
7
|
export { CanonicalizationError, canonicalizeForHash } from "./canonicalize.js";
|
|
7
8
|
export { type DefinedDirector, defineDirector, isAnnotatedDirectorFactory, } from "./director.js";
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export { AgentContextLockError } from "./lock.js";
|
|
|
10
10
|
export { DuplicateToolError, PLUGIN_MARKER, TOOL_PLUGIN_KIND, createToolRunner, defineTool, definePlugin, fromToolRunner, isAnnotatedPluginFactory, isToolPluginInstance, stringTool, tool, toolApprovalEffect, } from "./tool.js";
|
|
11
11
|
export { AgentEnvError, } from "./env.js";
|
|
12
12
|
export {} from "./director-types.js";
|
|
13
|
+
export { createStaticCredentialResolver, createUnconfiguredCredentialResolver, } from "./credential-resolver.js";
|
|
13
14
|
export { validateNamespacedId } from "./namespace.js";
|
|
14
15
|
export { CanonicalizationError, canonicalizeForHash } from "./canonicalize.js";
|
|
15
16
|
export { defineDirector, isAnnotatedDirectorFactory, } from "./director.js";
|
|
@@ -20,7 +20,7 @@ export const MAIL_SOURCE = {
|
|
|
20
20
|
id: "anthropic:claude-opus-4-6",
|
|
21
21
|
provider: "anthropic",
|
|
22
22
|
baseURL: "https://api.anthropic.com",
|
|
23
|
-
|
|
23
|
+
credentialId: "sk-test-mail",
|
|
24
24
|
model: "claude-opus-4-6",
|
|
25
25
|
};
|
|
26
26
|
export const MAIL_ADDRESS = "support@fixture.local";
|
package/dist/testing/index.d.ts
CHANGED
package/dist/testing/index.js
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve once the stream emits `reactor.done`.
|
|
3
|
+
*
|
|
4
|
+
* Throws if the stream ends without it: returning would resolve as though the
|
|
5
|
+
* run had completed, and the caller would then fail on a later assertion
|
|
6
|
+
* instead of on the real cause.
|
|
7
|
+
*
|
|
8
|
+
* Typed structurally so a caller need not import the reactor's event union to
|
|
9
|
+
* await its terminal event.
|
|
10
|
+
*/
|
|
11
|
+
export declare function waitForReactorDone(stream: AsyncIterable<{
|
|
12
|
+
type: string;
|
|
13
|
+
}>): Promise<void>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Waiter over a reactor's emitted-event stream.
|
|
2
|
+
//
|
|
3
|
+
// A reactor run ends with a `reactor.done` event, including on the fatal
|
|
4
|
+
// error path, so a test that needs the run finished waits for that event
|
|
5
|
+
// rather than for an interval. CONVENTIONS.md names this shape as the one to
|
|
6
|
+
// copy; it lives here so it is imported rather than copied again.
|
|
7
|
+
/**
|
|
8
|
+
* Resolve once the stream emits `reactor.done`.
|
|
9
|
+
*
|
|
10
|
+
* Throws if the stream ends without it: returning would resolve as though the
|
|
11
|
+
* run had completed, and the caller would then fail on a later assertion
|
|
12
|
+
* instead of on the real cause.
|
|
13
|
+
*
|
|
14
|
+
* Typed structurally so a caller need not import the reactor's event union to
|
|
15
|
+
* await its terminal event.
|
|
16
|
+
*/
|
|
17
|
+
export async function waitForReactorDone(stream) {
|
|
18
|
+
for await (const event of stream) {
|
|
19
|
+
if (event.type === "reactor.done")
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
throw new Error("reactor event stream ended before reactor.done");
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intx/agent",
|
|
3
3
|
"description": "In-process agent runtime: construct an agent, send it a message, get a reply",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"license": "LGPL-2.1-only",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@intx/inference": "0.
|
|
21
|
-
"@intx/log": "0.
|
|
22
|
-
"@intx/mime": "0.
|
|
23
|
-
"@intx/types": "0.
|
|
20
|
+
"@intx/inference": "0.4.0",
|
|
21
|
+
"@intx/log": "0.4.0",
|
|
22
|
+
"@intx/mime": "0.4.0",
|
|
23
|
+
"@intx/types": "0.4.0",
|
|
24
24
|
"arktype": "^2.1.29"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@intx/storage-isogit": "0.
|
|
27
|
+
"@intx/storage-isogit": "0.4.0"
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
30
30
|
"dist",
|