nexus-ai-pro 2.2.0 → 2.3.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/API_STABILITY.md +39 -0
- package/CHANGELOG.md +142 -1
- package/README.md +10 -5
- package/dist/agent/capabilities.d.ts +39 -0
- package/dist/agent/capabilities.js +36 -0
- package/dist/agent/create-agent.d.ts +61 -11
- package/dist/agent/create-agent.js +136 -22
- package/dist/agent/index.d.ts +3 -2
- package/dist/agent/index.js +1 -1
- package/dist/agent/middleware/approval.d.ts +26 -0
- package/dist/agent/middleware/approval.js +23 -0
- package/dist/agent/{middleware.d.ts → middleware/basic.d.ts} +5 -4
- package/dist/agent/{middleware.js → middleware/basic.js} +3 -5
- package/dist/agent/middleware/context-editor.d.ts +52 -0
- package/dist/agent/middleware/context-editor.js +66 -0
- package/dist/agent/middleware/filesystem.d.ts +44 -0
- package/dist/agent/middleware/filesystem.js +83 -0
- package/dist/agent/middleware/index.d.ts +19 -0
- package/dist/agent/middleware/index.js +9 -0
- package/dist/agent/middleware/limits.d.ts +42 -0
- package/dist/agent/middleware/limits.js +52 -0
- package/dist/agent/middleware/models.d.ts +48 -0
- package/dist/agent/middleware/models.js +44 -0
- package/dist/agent/middleware/pii.d.ts +67 -0
- package/dist/agent/middleware/pii.js +173 -0
- package/dist/agent/middleware/retry.d.ts +66 -0
- package/dist/agent/middleware/retry.js +59 -0
- package/dist/agent/middleware/shared.d.ts +41 -0
- package/dist/agent/middleware/shared.js +73 -0
- package/dist/agent/middleware/tool-selector.d.ts +64 -0
- package/dist/agent/middleware/tool-selector.js +106 -0
- package/dist/agent/permissions.d.ts +113 -0
- package/dist/agent/permissions.js +180 -0
- package/dist/agent/sandbox.d.ts +151 -0
- package/dist/agent/sandbox.js +257 -0
- package/dist/agent/tool.d.ts +8 -3
- package/dist/agent/tool.js +14 -3
- package/dist/deep-agent/index.d.ts +109 -0
- package/dist/deep-agent/index.js +216 -0
- package/dist/graph/functional.d.ts +9 -0
- package/dist/graph/functional.js +20 -3
- package/dist/graph/graph.js +25 -4
- package/dist/graph/lint.d.ts +4 -1
- package/dist/graph/lint.js +35 -0
- package/dist/postgres/fulltext.d.ts +67 -0
- package/dist/postgres/fulltext.js +91 -0
- package/dist/rag/elasticsearch.d.ts +71 -0
- package/dist/rag/elasticsearch.js +130 -0
- package/dist/rag/pipeline.d.ts +140 -0
- package/dist/rag/pipeline.js +187 -0
- package/dist/rag/rerankers.d.ts +92 -0
- package/dist/rag/rerankers.js +97 -0
- package/dist/rag/retrievers.d.ts +12 -1
- package/dist/server/assistant.d.ts +5 -1
- package/dist/server/assistant.js +4 -2
- package/dist/server/auth.d.ts +250 -0
- package/dist/server/auth.js +392 -0
- package/dist/store/memory.d.ts +10 -0
- package/dist/store/memory.js +10 -0
- package/dist/types/graph.d.ts +38 -0
- package/dist/types/messages.d.ts +36 -2
- package/dist/types/principal.d.ts +21 -0
- package/dist/types/principal.js +1 -0
- package/dist/types/server.d.ts +2 -9
- package/dist/utils/tenant.d.ts +11 -0
- package/dist/utils/tenant.js +14 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist-cjs/agent/capabilities.d.ts +39 -0
- package/dist-cjs/agent/capabilities.js +41 -0
- package/dist-cjs/agent/create-agent.d.ts +61 -11
- package/dist-cjs/agent/create-agent.js +136 -22
- package/dist-cjs/agent/index.d.ts +3 -2
- package/dist-cjs/agent/index.js +4 -4
- package/dist-cjs/agent/middleware/approval.d.ts +26 -0
- package/dist-cjs/agent/middleware/approval.js +26 -0
- package/dist-cjs/agent/{middleware.d.ts → middleware/basic.d.ts} +5 -4
- package/dist-cjs/agent/{middleware.js → middleware/basic.js} +3 -5
- package/dist-cjs/agent/middleware/context-editor.d.ts +52 -0
- package/dist-cjs/agent/middleware/context-editor.js +70 -0
- package/dist-cjs/agent/middleware/filesystem.d.ts +44 -0
- package/dist-cjs/agent/middleware/filesystem.js +86 -0
- package/dist-cjs/agent/middleware/index.d.ts +19 -0
- package/dist-cjs/agent/middleware/index.js +28 -0
- package/dist-cjs/agent/middleware/limits.d.ts +42 -0
- package/dist-cjs/agent/middleware/limits.js +57 -0
- package/dist-cjs/agent/middleware/models.d.ts +48 -0
- package/dist-cjs/agent/middleware/models.js +48 -0
- package/dist-cjs/agent/middleware/pii.d.ts +67 -0
- package/dist-cjs/agent/middleware/pii.js +178 -0
- package/dist-cjs/agent/middleware/retry.d.ts +66 -0
- package/dist-cjs/agent/middleware/retry.js +63 -0
- package/dist-cjs/agent/middleware/shared.d.ts +41 -0
- package/dist-cjs/agent/middleware/shared.js +83 -0
- package/dist-cjs/agent/middleware/tool-selector.d.ts +64 -0
- package/dist-cjs/agent/middleware/tool-selector.js +109 -0
- package/dist-cjs/agent/permissions.d.ts +113 -0
- package/dist-cjs/agent/permissions.js +189 -0
- package/dist-cjs/agent/sandbox.d.ts +151 -0
- package/dist-cjs/agent/sandbox.js +297 -0
- package/dist-cjs/agent/tool.d.ts +8 -3
- package/dist-cjs/agent/tool.js +14 -3
- package/dist-cjs/deep-agent/index.d.ts +109 -0
- package/dist-cjs/deep-agent/index.js +219 -0
- package/dist-cjs/graph/functional.d.ts +9 -0
- package/dist-cjs/graph/functional.js +20 -3
- package/dist-cjs/graph/graph.js +25 -4
- package/dist-cjs/graph/lint.d.ts +4 -1
- package/dist-cjs/graph/lint.js +35 -0
- package/dist-cjs/postgres/fulltext.d.ts +67 -0
- package/dist-cjs/postgres/fulltext.js +129 -0
- package/dist-cjs/rag/elasticsearch.d.ts +71 -0
- package/dist-cjs/rag/elasticsearch.js +135 -0
- package/dist-cjs/rag/pipeline.d.ts +140 -0
- package/dist-cjs/rag/pipeline.js +191 -0
- package/dist-cjs/rag/rerankers.d.ts +92 -0
- package/dist-cjs/rag/rerankers.js +107 -0
- package/dist-cjs/rag/retrievers.d.ts +12 -1
- package/dist-cjs/server/assistant.d.ts +5 -1
- package/dist-cjs/server/assistant.js +4 -2
- package/dist-cjs/server/auth.d.ts +250 -0
- package/dist-cjs/server/auth.js +402 -0
- package/dist-cjs/store/memory.d.ts +10 -0
- package/dist-cjs/store/memory.js +10 -0
- package/dist-cjs/types/graph.d.ts +38 -0
- package/dist-cjs/types/messages.d.ts +36 -2
- package/dist-cjs/types/principal.d.ts +21 -0
- package/dist-cjs/types/principal.js +2 -0
- package/dist-cjs/types/server.d.ts +2 -9
- package/dist-cjs/utils/tenant.d.ts +11 -0
- package/dist-cjs/utils/tenant.js +15 -0
- package/dist-cjs/version.d.ts +1 -1
- package/dist-cjs/version.js +1 -1
- package/llms.txt +4 -3
- package/package.json +118 -1
package/dist/store/memory.js
CHANGED
|
@@ -4,6 +4,8 @@ export class MemoryStore {
|
|
|
4
4
|
options;
|
|
5
5
|
items = new Map();
|
|
6
6
|
maxItems;
|
|
7
|
+
expiring = false;
|
|
8
|
+
sweptAt = Number.NEGATIVE_INFINITY;
|
|
7
9
|
now;
|
|
8
10
|
constructor(options = {}) {
|
|
9
11
|
this.options = options;
|
|
@@ -18,6 +20,8 @@ export class MemoryStore {
|
|
|
18
20
|
const timestamp = this.now().toISOString();
|
|
19
21
|
const existing = this.items.get(id);
|
|
20
22
|
const vector = await this.embed(value, options.index);
|
|
23
|
+
if (options.ttlMs !== undefined)
|
|
24
|
+
this.expiring = true;
|
|
21
25
|
this.items.delete(id);
|
|
22
26
|
this.items.set(id, {
|
|
23
27
|
namespace: [...namespace],
|
|
@@ -99,6 +103,12 @@ export class MemoryStore {
|
|
|
99
103
|
return item.expiresAt !== undefined && Date.parse(item.expiresAt) <= this.now().getTime();
|
|
100
104
|
}
|
|
101
105
|
sweep() {
|
|
106
|
+
if (!this.expiring)
|
|
107
|
+
return;
|
|
108
|
+
const now = this.now().getTime();
|
|
109
|
+
if (now - this.sweptAt < 1_000 && this.items.size <= this.maxItems)
|
|
110
|
+
return;
|
|
111
|
+
this.sweptAt = now;
|
|
102
112
|
for (const [id, item] of this.items)
|
|
103
113
|
if (this.expired(item))
|
|
104
114
|
this.items.delete(id);
|
package/dist/types/graph.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { OperationLifecycleLike } from './lifecycle.js';
|
|
|
8
8
|
* is, so a different process can pick it up.
|
|
9
9
|
*/
|
|
10
10
|
import type { CacheAdapter } from '../cache/adapters.js';
|
|
11
|
+
import type { Principal } from './principal.js';
|
|
11
12
|
import type { Store } from './store.js';
|
|
12
13
|
/** Entry sentinel. An edge from `START` names the first node. */
|
|
13
14
|
export declare const START = "__start__";
|
|
@@ -243,6 +244,14 @@ export interface NodeOptions<S extends ChannelSchema = ChannelSchema> {
|
|
|
243
244
|
* that are not.
|
|
244
245
|
*/
|
|
245
246
|
idempotent?: boolean;
|
|
247
|
+
/**
|
|
248
|
+
* What the node does to the world, as capabilities: `payments:charge`, `network:api.stripe.com`,
|
|
249
|
+
* `filesystem:write`. Declared for the linter, which reports a node with effects that also
|
|
250
|
+
* interrupts, since the node runs again from the top when the answer comes.
|
|
251
|
+
*/
|
|
252
|
+
effects?: readonly string[];
|
|
253
|
+
/** True when the node may call `context.interrupt()`. Declared for the linter. */
|
|
254
|
+
interrupts?: boolean;
|
|
246
255
|
/**
|
|
247
256
|
* Nodes this one may reach through `Send` or a `Command`. Declaring them keeps compile-time
|
|
248
257
|
* reachability checks and diagrams exact, so a node reached only that way is not reported as
|
|
@@ -374,6 +383,8 @@ export interface NodeContext<S extends ChannelSchema> {
|
|
|
374
383
|
readonly threadId: string;
|
|
375
384
|
/** The tenant the run is for, when it has one. */
|
|
376
385
|
readonly tenantId?: string;
|
|
386
|
+
/** Who the run is for, when it was started with a principal: the caller the server authenticated. */
|
|
387
|
+
readonly principal?: Readonly<Principal>;
|
|
377
388
|
/** Identifies this task. Equal to `node` unless the task came from a `Send`. */
|
|
378
389
|
readonly taskId: string;
|
|
379
390
|
/** Input carried by a `Send`. Undefined for a node reached through an ordinary edge. */
|
|
@@ -577,6 +588,14 @@ export interface GraphRunOptions {
|
|
|
577
588
|
* `tenantId` is refused before anything runs. A run without one carries on the thread's tenant.
|
|
578
589
|
*/
|
|
579
590
|
tenantId?: string;
|
|
591
|
+
/**
|
|
592
|
+
* Who the run is for, such as the caller the server authenticated. Nodes read it as
|
|
593
|
+
* `context.principal`, and an agent hands it to every tool and middleware. Its `tenantId` is the
|
|
594
|
+
* run's tenant when `tenantId` is not given, and a run whose two tenants differ is refused. Its
|
|
595
|
+
* `userId` is recorded on every checkpoint as `metadata.userId`; the rest is never stored, so a
|
|
596
|
+
* resumed run carries the principal of whoever resumed it.
|
|
597
|
+
*/
|
|
598
|
+
principal?: Principal;
|
|
580
599
|
/** Overrides the compiled `maxConcurrency` for this run. */
|
|
581
600
|
maxConcurrency?: number;
|
|
582
601
|
/** Breakpoints for this run only, replacing the compiled ones. */
|
|
@@ -853,6 +872,10 @@ export interface GraphDescription {
|
|
|
853
872
|
idempotent?: boolean;
|
|
854
873
|
/** True when the node reuses results through `cache`. */
|
|
855
874
|
cache?: boolean;
|
|
875
|
+
/** The capabilities its work uses, when it declares them. */
|
|
876
|
+
effects?: string[];
|
|
877
|
+
/** True when it declares that it may interrupt. */
|
|
878
|
+
interrupts?: boolean;
|
|
856
879
|
/** The graph this node runs, when it is a compiled graph used through `asNode()`. */
|
|
857
880
|
subgraph?: GraphDescription;
|
|
858
881
|
}>;
|
|
@@ -876,6 +899,19 @@ export interface GraphDescription {
|
|
|
876
899
|
checkpointer?: 'memory' | 'custom' | 'none';
|
|
877
900
|
/** Tasks a superstep runs at once. */
|
|
878
901
|
maxConcurrency?: number;
|
|
902
|
+
/** The tools the graph's nodes call, when it was compiled with them, as an agent is. */
|
|
903
|
+
tools?: GraphToolDescription[];
|
|
904
|
+
}
|
|
905
|
+
/** A tool a graph calls, as the linter reads it. */
|
|
906
|
+
export interface GraphToolDescription {
|
|
907
|
+
/** The tool's name. */
|
|
908
|
+
name: string;
|
|
909
|
+
/** Its capabilities, when it declares a fixed list. */
|
|
910
|
+
capabilities?: string[];
|
|
911
|
+
/** True when it computes its capabilities from each call's arguments. */
|
|
912
|
+
dynamic?: boolean;
|
|
913
|
+
/** How its calls are approved: an interrupt for each, a permission policy, or not at all. */
|
|
914
|
+
approval: 'interrupt' | 'policy' | 'none';
|
|
879
915
|
}
|
|
880
916
|
/**
|
|
881
917
|
* Options applied when a graph is compiled: stores, breakpoints, concurrency, retries, and failure
|
|
@@ -898,6 +934,8 @@ export interface CompileOptions {
|
|
|
898
934
|
maxConcurrency?: number;
|
|
899
935
|
/** Default retry policy for every node. A node's own policy wins. */
|
|
900
936
|
retry?: RetryPolicy;
|
|
937
|
+
/** The tools the graph's nodes call, for `describe()` and the linter. `createAgent()` fills it. */
|
|
938
|
+
tools?: GraphToolDescription[];
|
|
901
939
|
/**
|
|
902
940
|
* Defaults for every node: a retry policy, timeouts, and an `onError`. A node's own options win,
|
|
903
941
|
* field by field. `retry` here is the same as `compile({ retry })`, and wins over it.
|
package/dist/types/messages.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { CacheTtl, ReasoningEffort } from './providers.js';
|
|
2
2
|
import type { AssetInput } from './images.js';
|
|
3
|
+
import type { Principal } from './principal.js';
|
|
4
|
+
import type { Store } from './store.js';
|
|
3
5
|
declare global {
|
|
4
6
|
namespace NodeJS {
|
|
5
7
|
/**
|
|
@@ -128,8 +130,19 @@ export interface ToolDefinition {
|
|
|
128
130
|
description: string;
|
|
129
131
|
/** JSON Schema for the arguments. */
|
|
130
132
|
parameters: Record<string, unknown>;
|
|
131
|
-
/**
|
|
132
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Runs the tool, for the agent loop and executors that call tools automatically. An agent passes
|
|
135
|
+
* a `ToolContext` too: who the run is for, its thread and tenant, its signal, and its store.
|
|
136
|
+
*/
|
|
137
|
+
execute?: (args: Record<string, unknown>, context?: ToolContext) => Promise<unknown>;
|
|
138
|
+
/**
|
|
139
|
+
* What the tool does to the world, as capabilities a permission policy decides on:
|
|
140
|
+
* `filesystem:read` or `filesystem:write` with an optional path, `network` with an optional host,
|
|
141
|
+
* `shell` with an optional command, `code`, or a name of the application's own such as `payments`.
|
|
142
|
+
* A function computes them from each call's arguments, so a policy sees the path, host, or command
|
|
143
|
+
* the call actually uses. Never sent to a model.
|
|
144
|
+
*/
|
|
145
|
+
capabilities?: readonly string[] | ((args: Record<string, unknown>) => readonly string[]);
|
|
133
146
|
/**
|
|
134
147
|
* Ends a cacheable prefix after this tool. Only honored when the request sets
|
|
135
148
|
* `cache.mode: 'explicit'` and the provider accepts caller-placed breakpoints.
|
|
@@ -145,6 +158,27 @@ export interface ToolDefinition {
|
|
|
145
158
|
export type ToolChoice = 'auto' | 'none' | 'required' | {
|
|
146
159
|
name: string;
|
|
147
160
|
};
|
|
161
|
+
/**
|
|
162
|
+
* What a tool receives besides its arguments when an agent runs it. Every field is optional: a tool
|
|
163
|
+
* run outside an agent, or by an executor given nothing, sees none of them.
|
|
164
|
+
*/
|
|
165
|
+
export interface ToolContext {
|
|
166
|
+
/** The model's id for this call. */
|
|
167
|
+
toolCallId?: string;
|
|
168
|
+
/** The thread the run belongs to. */
|
|
169
|
+
threadId?: string;
|
|
170
|
+
/** The tenant the run is for. */
|
|
171
|
+
tenantId?: string;
|
|
172
|
+
/**
|
|
173
|
+
* Who the run is for: the caller the server authenticated, with their roles and scopes, so a
|
|
174
|
+
* tool can act as that user and nobody else.
|
|
175
|
+
*/
|
|
176
|
+
principal?: Readonly<Principal>;
|
|
177
|
+
/** Aborted when the run is cancelled or the step times out. A tool that waits should stop with it. */
|
|
178
|
+
signal?: AbortSignal;
|
|
179
|
+
/** Long-term memory. In a tenant's run, the tenant's view of it. */
|
|
180
|
+
store?: Store;
|
|
181
|
+
}
|
|
148
182
|
/** What a tool returned, correlated with the call that asked for it. */
|
|
149
183
|
export interface ToolCallResult {
|
|
150
184
|
/** The id of the call this answers. */
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who a request, a run, or a tool call is for.
|
|
3
|
+
*
|
|
4
|
+
* One shape everywhere: the server's authentication hook returns it, a run carries it, graph nodes
|
|
5
|
+
* and workflow steps read it, tools and middleware receive it, and a permission policy can decide on
|
|
6
|
+
* it. Its tenant scopes threads, runs, budgets, and the store.
|
|
7
|
+
*/
|
|
8
|
+
export interface Principal {
|
|
9
|
+
/** Isolates threads, runs, and cron jobs. Requests only ever see their own tenant's resources. */
|
|
10
|
+
tenantId?: string;
|
|
11
|
+
/** Who the caller is: a token's subject, a key's owner. Recorded on what they create. */
|
|
12
|
+
userId?: string;
|
|
13
|
+
/** What the caller may do. A route that names a scope refuses a principal without it. */
|
|
14
|
+
scopes?: readonly string[];
|
|
15
|
+
/** The caller's roles, for policies and tools that decide by role rather than by scope. */
|
|
16
|
+
roles?: readonly string[];
|
|
17
|
+
/** How the caller was authenticated: `jwt`, `api-key`, `proxy`, or a name of your own. */
|
|
18
|
+
method?: string;
|
|
19
|
+
/** The verified claims or attributes the principal was built from, for anything the fields above leave out. */
|
|
20
|
+
claims?: Readonly<Record<string, unknown>>;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/types/server.d.ts
CHANGED
|
@@ -6,15 +6,8 @@
|
|
|
6
6
|
* graph thread, so state, interrupts, and history come from the checkpointer; and an assistant is
|
|
7
7
|
* anything that can stream events for an input, which a compiled graph already does.
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
|
-
export
|
|
11
|
-
/** Isolates threads, runs, and cron jobs. Requests only ever see their own tenant's resources. */
|
|
12
|
-
tenantId?: string;
|
|
13
|
-
/** Who the caller is, recorded on what they create. */
|
|
14
|
-
userId?: string;
|
|
15
|
-
/** What the caller may do. A route that names a scope refuses a principal without it. */
|
|
16
|
-
scopes?: readonly string[];
|
|
17
|
-
}
|
|
9
|
+
import type { Principal } from './principal.js';
|
|
10
|
+
export type { Principal };
|
|
18
11
|
/** Where a run stands, as the server reports it. */
|
|
19
12
|
export type RunStatus = 'queued' | 'running' | 'awaiting_input' | 'succeeded' | 'failed' | 'cancelled' | 'expired';
|
|
20
13
|
/** What happens when a run is requested for a thread that is already running one. */
|
package/dist/utils/tenant.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Principal } from '../types/principal.js';
|
|
1
2
|
/**
|
|
2
3
|
* The tenant id rule every scope shares. An id is letters, digits, `_`, and `-`, so it can never hold
|
|
3
4
|
* the `/` a scoped name or key is built with: no tenant's prefix is a prefix of another's.
|
|
@@ -12,3 +13,13 @@ export declare class TenantIdError extends RangeError {
|
|
|
12
13
|
export declare function assertTenantId(tenantId: string): string;
|
|
13
14
|
/** @internal The prefix a tenant's names and keys carry in a shared store. */
|
|
14
15
|
export declare function tenantPrefix(tenantId: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Run options with the principal's tenant applied: the principal's `tenantId` becomes the run's when
|
|
18
|
+
* it has none, a run whose two tenants differ is refused, and the principal's `userId` is recorded
|
|
19
|
+
* in the run's metadata.
|
|
20
|
+
*/
|
|
21
|
+
export declare function withPrincipal<O extends {
|
|
22
|
+
tenantId?: string;
|
|
23
|
+
principal?: Principal;
|
|
24
|
+
metadata?: Record<string, unknown>;
|
|
25
|
+
}>(runOptions: O): O;
|
package/dist/utils/tenant.js
CHANGED
|
@@ -14,3 +14,17 @@ export function assertTenantId(tenantId) {
|
|
|
14
14
|
export function tenantPrefix(tenantId) {
|
|
15
15
|
return `tenant/${assertTenantId(tenantId)}/`;
|
|
16
16
|
}
|
|
17
|
+
export function withPrincipal(runOptions) {
|
|
18
|
+
const principal = runOptions.principal;
|
|
19
|
+
if (!principal)
|
|
20
|
+
return runOptions;
|
|
21
|
+
const tenantId = principal.tenantId;
|
|
22
|
+
if (tenantId !== undefined && runOptions.tenantId !== undefined && tenantId !== runOptions.tenantId) {
|
|
23
|
+
throw new TypeError("The run's tenantId and its principal's tenant differ");
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
...runOptions,
|
|
27
|
+
...(tenantId !== undefined && runOptions.tenantId === undefined ? { tenantId } : {}),
|
|
28
|
+
...(principal.userId !== undefined ? { metadata: { ...runOptions.metadata, userId: principal.userId } } : {}),
|
|
29
|
+
};
|
|
30
|
+
}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const NEXUS_VERSION = '2.
|
|
1
|
+
export const NEXUS_VERSION = '2.3.0';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ToolDefinition } from '../types/messages.js';
|
|
2
|
+
/**
|
|
3
|
+
* Capabilities: what a tool does to the world, written as strings a policy can decide on.
|
|
4
|
+
*
|
|
5
|
+
* | Capability | Means |
|
|
6
|
+
* | --- | --- |
|
|
7
|
+
* | `filesystem:read`, `filesystem:read:<path>` | Reads files, or one path |
|
|
8
|
+
* | `filesystem:write`, `filesystem:write:<path>` | Writes, creates, or deletes files |
|
|
9
|
+
* | `network`, `network:<host or URL>` | Opens a network connection, to a host when given |
|
|
10
|
+
* | `shell`, `shell:<command line>` | Runs a shell command |
|
|
11
|
+
* | `code` | Runs code it was given, as an interpreter does |
|
|
12
|
+
* | `<name>`, `<name>:<detail>` | Anything the application names, such as `payments:refund` |
|
|
13
|
+
*
|
|
14
|
+
* A tool that declares `capabilities: []` does nothing to the world; one that declares none at all
|
|
15
|
+
* is undeclared, and a policy decides on it as such.
|
|
16
|
+
*/
|
|
17
|
+
/** One capability, split into its parts. */
|
|
18
|
+
export interface ParsedCapability {
|
|
19
|
+
/** `filesystem`, `network`, `shell`, `code`, or the application's own name. */
|
|
20
|
+
kind: string;
|
|
21
|
+
/** `read` or `write`, for the filesystem. */
|
|
22
|
+
access?: 'read' | 'write';
|
|
23
|
+
/** The path, host, command, or detail, when the capability names one. */
|
|
24
|
+
target?: string;
|
|
25
|
+
}
|
|
26
|
+
/** Splits a capability string into its kind, access, and target. */
|
|
27
|
+
export declare function parseCapability(capability: string): ParsedCapability;
|
|
28
|
+
/**
|
|
29
|
+
* The capabilities one call of a tool declares: its static list, or what its function computes from
|
|
30
|
+
* the call's arguments. `undefined` means undeclared — no list, or a function that threw — which is
|
|
31
|
+
* not the same as `[]`, a tool that declares it does nothing to the world.
|
|
32
|
+
*/
|
|
33
|
+
export declare function capabilitiesOf(tool: Pick<ToolDefinition, 'capabilities'> | undefined, args: Record<string, unknown>): string[] | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Whether a capability is sensitive: anything but reading files. A pure tool declares
|
|
36
|
+
* `capabilities: []`; whatever it does declare, a write, a command, code, the network, or an
|
|
37
|
+
* effect of the application's own such as `payments`, changes the world or leaves the process.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isSensitiveCapability(capability: string): boolean;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseCapability = parseCapability;
|
|
4
|
+
exports.capabilitiesOf = capabilitiesOf;
|
|
5
|
+
exports.isSensitiveCapability = isSensitiveCapability;
|
|
6
|
+
function parseCapability(capability) {
|
|
7
|
+
const text = capability.trim();
|
|
8
|
+
const colon = text.indexOf(':');
|
|
9
|
+
const kind = (colon < 0 ? text : text.slice(0, colon)).toLowerCase();
|
|
10
|
+
const rest = colon < 0 ? undefined : text.slice(colon + 1);
|
|
11
|
+
if (kind === 'filesystem') {
|
|
12
|
+
if (!rest)
|
|
13
|
+
return { kind };
|
|
14
|
+
const [access, ...path] = rest.split(':');
|
|
15
|
+
const parsed = { kind };
|
|
16
|
+
if (access === 'read' || access === 'write')
|
|
17
|
+
parsed.access = access;
|
|
18
|
+
const target = parsed.access ? path.join(':') : rest;
|
|
19
|
+
if (target)
|
|
20
|
+
parsed.target = target;
|
|
21
|
+
return parsed;
|
|
22
|
+
}
|
|
23
|
+
return rest === undefined || rest === '' ? { kind } : { kind, target: rest };
|
|
24
|
+
}
|
|
25
|
+
function capabilitiesOf(tool, args) {
|
|
26
|
+
const declared = tool?.capabilities;
|
|
27
|
+
if (!declared)
|
|
28
|
+
return undefined;
|
|
29
|
+
if (typeof declared !== 'function')
|
|
30
|
+
return [...declared];
|
|
31
|
+
try {
|
|
32
|
+
return [...declared(args)];
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function isSensitiveCapability(capability) {
|
|
39
|
+
const parsed = parseCapability(capability);
|
|
40
|
+
return !(parsed.kind === 'filesystem' && parsed.access === 'read');
|
|
41
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { OperationLifecycleLike } from '../types/lifecycle.js';
|
|
2
2
|
import { type CompiledGraph } from '../graph/graph.js';
|
|
3
|
-
import type { GraphCheckpointer, NodeContext } from '../types/graph.js';
|
|
3
|
+
import type { GraphCheckpointer, InterruptRequest, NodeContext } from '../types/graph.js';
|
|
4
4
|
import type { CompletionRequest, Message, ToolDefinition } from '../types/messages.js';
|
|
5
5
|
import type { NexusResponse, StreamChunk } from '../types/response.js';
|
|
6
|
+
import type { Principal } from '../types/principal.js';
|
|
6
7
|
import type { Store } from '../types/store.js';
|
|
8
|
+
import type { PermissionPolicyLike } from './permissions.js';
|
|
7
9
|
/**
|
|
8
10
|
* An agent as a graph.
|
|
9
11
|
*
|
|
@@ -28,6 +30,10 @@ export interface AgentToolCall {
|
|
|
28
30
|
name: string;
|
|
29
31
|
/** Arguments, parsed from the model's JSON. */
|
|
30
32
|
args: Record<string, unknown>;
|
|
33
|
+
/** What the call declares it does, when the tool declares capabilities. */
|
|
34
|
+
capabilities?: readonly string[];
|
|
35
|
+
/** Why the permission policy asked for approval, when it did. */
|
|
36
|
+
permission?: string;
|
|
31
37
|
}
|
|
32
38
|
/** What an approver may answer: allow, refuse with a reason, or allow with corrected arguments. */
|
|
33
39
|
export type AgentApproval = boolean | {
|
|
@@ -42,24 +48,58 @@ export interface AgentApprovalPolicy {
|
|
|
42
48
|
/** The question an operator sees. Defaults to naming the tool and its arguments. */
|
|
43
49
|
reason?: (call: AgentToolCall) => string;
|
|
44
50
|
}
|
|
51
|
+
/** What every middleware hook can read about the step it runs in. */
|
|
52
|
+
export interface AgentMiddlewareContext {
|
|
53
|
+
/** The agent's state at this step: the whole transcript, tool calls and results included. */
|
|
54
|
+
state: AgentState;
|
|
55
|
+
/** Long-term memory, when the agent has a store. */
|
|
56
|
+
store?: Store;
|
|
57
|
+
/** The thread the run belongs to. */
|
|
58
|
+
threadId: string;
|
|
59
|
+
/** The tenant the run is for, when it has one. */
|
|
60
|
+
tenantId?: string;
|
|
61
|
+
/** Who the run is for, when it has a principal: the caller the server authenticated. */
|
|
62
|
+
principal?: Readonly<Principal>;
|
|
63
|
+
/** Aborted when the run is cancelled or the step times out. A hook that waits should stop with it. */
|
|
64
|
+
signal: AbortSignal;
|
|
65
|
+
/**
|
|
66
|
+
* Suspends the run until a person answers, as `interruptOn` does. When the run resumes, the step
|
|
67
|
+
* runs again and this returns the answer instead of suspending.
|
|
68
|
+
*/
|
|
69
|
+
interrupt<T = unknown>(request: InterruptRequest): T;
|
|
70
|
+
}
|
|
71
|
+
/** What `wrapModelCall` can read, and how it ends the run without calling the model. */
|
|
72
|
+
export interface AgentModelCallContext extends AgentMiddlewareContext {
|
|
73
|
+
/**
|
|
74
|
+
* Ends the run with this answer and `stopReason: 'stopped'`, without another model call. Return
|
|
75
|
+
* what it returns: `return context.stop('The model call limit was reached.')`.
|
|
76
|
+
*/
|
|
77
|
+
stop(answer: string): NexusResponse;
|
|
78
|
+
}
|
|
45
79
|
/** Hooks around the agent's model calls and tool calls. Each hook is optional. */
|
|
46
80
|
export interface AgentMiddleware {
|
|
47
81
|
/** Names the middleware in traces and errors. */
|
|
48
82
|
name?: string;
|
|
49
83
|
/** Adjusts the request before it is sent: trim history, add context, swap the model. */
|
|
50
|
-
beforeModel?(context: {
|
|
84
|
+
beforeModel?(context: AgentMiddlewareContext & {
|
|
51
85
|
request: CompletionRequest;
|
|
52
|
-
state: AgentState;
|
|
53
|
-
store?: Store;
|
|
54
86
|
}): CompletionRequest | void | Promise<CompletionRequest | void>;
|
|
55
87
|
/** Inspects or replaces the response: redact, validate, count. */
|
|
56
|
-
afterModel?(context: {
|
|
88
|
+
afterModel?(context: AgentMiddlewareContext & {
|
|
57
89
|
response: NexusResponse;
|
|
58
|
-
state: AgentState;
|
|
59
|
-
store?: Store;
|
|
60
90
|
}): NexusResponse | void | Promise<NexusResponse | void>;
|
|
61
|
-
/**
|
|
62
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Wraps the model call itself, after every `beforeModel` and before every `afterModel`. `next`
|
|
93
|
+
* sends a request and may be called again, with the same request or a changed one, to retry or to
|
|
94
|
+
* fall back to another model. The first middleware is the outermost.
|
|
95
|
+
*/
|
|
96
|
+
wrapModelCall?(request: CompletionRequest, next: (request: CompletionRequest) => Promise<NexusResponse>, context: AgentModelCallContext): Promise<NexusResponse> | NexusResponse;
|
|
97
|
+
/**
|
|
98
|
+
* Wraps a tool call, so a policy can log it, time it, retry it, or refuse it. `next` runs the
|
|
99
|
+
* rest of the chain and may be called again; given a call, it runs that call's arguments instead,
|
|
100
|
+
* and the permission policy decides them again first. The first middleware is the outermost.
|
|
101
|
+
*/
|
|
102
|
+
wrapToolCall?(call: AgentToolCall, next: (call?: AgentToolCall) => Promise<AgentToolResult>, context: AgentMiddlewareContext): Promise<AgentToolResult> | AgentToolResult;
|
|
63
103
|
}
|
|
64
104
|
/** What a tool call produced. */
|
|
65
105
|
export interface AgentToolResult {
|
|
@@ -88,6 +128,13 @@ export interface CreateAgentOptions {
|
|
|
88
128
|
interruptOn?: Record<string, AgentApprovalPolicy | true>;
|
|
89
129
|
/** Hooks around model and tool calls, applied in order. */
|
|
90
130
|
middleware?: AgentMiddleware[];
|
|
131
|
+
/**
|
|
132
|
+
* Decides every tool call from the capabilities it declares, before it runs: allow it, deny it,
|
|
133
|
+
* or interrupt for a person's approval, as `interruptOn` does. A denied call reaches the model as a
|
|
134
|
+
* failed tool result naming the reason, and never runs. See `permissionPolicy()` in
|
|
135
|
+
* `nexus-ai-pro/agent/permissions`.
|
|
136
|
+
*/
|
|
137
|
+
permissions?: PermissionPolicyLike;
|
|
91
138
|
/** Long-term memory, available to tools and middleware as `store`. */
|
|
92
139
|
store?: Store;
|
|
93
140
|
/**
|
|
@@ -136,8 +183,11 @@ export type AgentState = {
|
|
|
136
183
|
/** Why the agent stopped. */
|
|
137
184
|
stopReason?: AgentStopReason;
|
|
138
185
|
};
|
|
139
|
-
/**
|
|
140
|
-
|
|
186
|
+
/**
|
|
187
|
+
* `completed` when the model answered, `max_iterations` when it ran out of model calls, `stopped`
|
|
188
|
+
* when a middleware ended the run through `context.stop()`.
|
|
189
|
+
*/
|
|
190
|
+
export type AgentStopReason = 'completed' | 'max_iterations' | 'stopped';
|
|
141
191
|
/** An agent: a compiled graph over the agent's channels. */
|
|
142
192
|
export type AgentGraph = CompiledGraph<AgentChannels>;
|
|
143
193
|
/** Wraps a question into the state an agent starts from. */
|