@atbash/atbash-langgraph 0.0.5-dev.2 → 0.0.5-dev.4
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.d.ts +23 -5
- package/dist/index.js +95 -24
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _langchain_core_messages from '@langchain/core/messages';
|
|
2
2
|
import * as _langchain_langgraph from '@langchain/langgraph';
|
|
3
3
|
import { StateGraph } from '@langchain/langgraph';
|
|
4
|
-
import { Atbash,
|
|
4
|
+
import { Atbash, MemoryGuardManager } from '@atbash/sdk';
|
|
5
5
|
import * as _langchain_core_tools from '@langchain/core/tools';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
|
|
@@ -16,21 +16,39 @@ type AtbashState = typeof AtbashStateAnnotation.State;
|
|
|
16
16
|
|
|
17
17
|
interface GuardNodeOptions {
|
|
18
18
|
client: Atbash;
|
|
19
|
+
guardManager?: MemoryGuardManager;
|
|
19
20
|
}
|
|
20
21
|
declare function createGuardNode(opts: GuardNodeOptions): (state: AtbashState) => Promise<Partial<AtbashState>>;
|
|
21
22
|
|
|
22
23
|
interface AuditNodeOptions {
|
|
23
|
-
|
|
24
|
-
clientOpts?: AtbashOptions;
|
|
24
|
+
client: Atbash;
|
|
25
25
|
}
|
|
26
26
|
declare function createAuditNode(opts: AuditNodeOptions): (state: AtbashState) => Promise<Partial<AtbashState>>;
|
|
27
27
|
|
|
28
28
|
interface AtbashSafetyOptions {
|
|
29
|
-
agent?: AgentAuth;
|
|
30
29
|
privkey?: string;
|
|
31
30
|
endpoint?: string;
|
|
32
31
|
toolsNode?: string;
|
|
33
32
|
agentNode?: string;
|
|
33
|
+
/** Agent workspace directory — `~` is expanded. Defaults to `process.cwd()`. */
|
|
34
|
+
workspaceDir?: string;
|
|
35
|
+
/** Explicit MEMORY.md path. Overrides `workspaceDir/MEMORY.md`. */
|
|
36
|
+
memoryFilePath?: string;
|
|
37
|
+
/** How long (ms) to trust the local pointer between chain checks. Default 30000. */
|
|
38
|
+
memorySyncTTLMs?: number;
|
|
39
|
+
/** Block memory reads when a rolled-back version scores below this (1–10). Default 1 = warn only. */
|
|
40
|
+
memoryRollbackMinScore?: number;
|
|
41
|
+
/** Custom memory path patterns. Defaults to SDK built-ins. */
|
|
42
|
+
memoryPathPatterns?: string[];
|
|
43
|
+
/** Optional judge endpoint override. */
|
|
44
|
+
judgeEndpoint?: string;
|
|
45
|
+
/** Self-hosted judge response-signing pubkey (required when judgeEndpoint uses "self-hosted" policy). */
|
|
46
|
+
judgeVerifyPubKey?: string;
|
|
47
|
+
/** Organization name for chain resolution (public vs private chain). */
|
|
48
|
+
orgName?: string;
|
|
49
|
+
/** false = monitor mode: log but never block. Default true. */
|
|
50
|
+
enforce?: boolean;
|
|
51
|
+
debug?: boolean;
|
|
34
52
|
}
|
|
35
53
|
declare function addAtbashSafety(builder: StateGraph<AtbashState>, opts: AtbashSafetyOptions): StateGraph<_langchain_langgraph.StateType<{
|
|
36
54
|
atbashVerdict: _langchain_langgraph.BaseChannel<string | null, string | _langchain_langgraph.OverwriteValue<string | null> | null, unknown>;
|
|
@@ -52,7 +70,7 @@ declare function addAtbashSafety(builder: StateGraph<AtbashState>, opts: AtbashS
|
|
|
52
70
|
messages: _langchain_langgraph.BaseChannel<_langchain_core_messages.BaseMessage<_langchain_core_messages.MessageStructure<_langchain_core_messages.MessageToolSet>, _langchain_core_messages.MessageType>[], _langchain_langgraph.OverwriteValue<_langchain_core_messages.BaseMessage<_langchain_core_messages.MessageStructure<_langchain_core_messages.MessageToolSet>, _langchain_core_messages.MessageType>[]> | _langchain_langgraph.Messages, unknown>;
|
|
53
71
|
}>>, "__start__", _langchain_langgraph.StateDefinition, _langchain_langgraph.StateDefinition, _langchain_langgraph.StateDefinition, unknown, unknown, unknown>;
|
|
54
72
|
|
|
55
|
-
declare function createJudgeTool(
|
|
73
|
+
declare function createJudgeTool(client: Atbash): _langchain_core_tools.DynamicStructuredTool<z.ZodObject<{
|
|
56
74
|
action: z.ZodString;
|
|
57
75
|
context: z.ZodString;
|
|
58
76
|
}, "strip", z.ZodTypeAny, {
|
package/dist/index.js
CHANGED
|
@@ -33,11 +33,63 @@ function createGuardNode(opts) {
|
|
|
33
33
|
atbashReason: "No tool calls detected"
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
|
-
const
|
|
36
|
+
const memoryHandledIds = /* @__PURE__ */ new Set();
|
|
37
|
+
if (opts.guardManager) {
|
|
38
|
+
for (const tc of toolCalls) {
|
|
39
|
+
let memDecision;
|
|
40
|
+
try {
|
|
41
|
+
memDecision = await opts.guardManager.handleBeforeToolCall(
|
|
42
|
+
{ toolName: tc.name, args: tc.args },
|
|
43
|
+
{}
|
|
44
|
+
);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
47
|
+
return {
|
|
48
|
+
messages: toolCalls.map(
|
|
49
|
+
(toolCall) => new ToolMessage({
|
|
50
|
+
tool_call_id: toolCall.id,
|
|
51
|
+
content: toolCall.id === tc.id ? `Memory guard error: ${reason}` : "Blocked \u2014 memory safety check failed for another tool call"
|
|
52
|
+
})
|
|
53
|
+
),
|
|
54
|
+
atbashVerdict: "BLOCK",
|
|
55
|
+
atbashReason: `Memory guard error: ${reason}`,
|
|
56
|
+
atbashToolCallId: null,
|
|
57
|
+
atbashConfidence: null
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (memDecision !== null) {
|
|
61
|
+
if (memDecision.block) {
|
|
62
|
+
return {
|
|
63
|
+
messages: toolCalls.map(
|
|
64
|
+
(toolCall) => new ToolMessage({
|
|
65
|
+
tool_call_id: toolCall.id,
|
|
66
|
+
content: toolCall.id === tc.id ? `Memory write blocked by Atbash: ${memDecision.blockReason ?? ""}` : "Blocked \u2014 another tool call was blocked by memory safety"
|
|
67
|
+
})
|
|
68
|
+
),
|
|
69
|
+
atbashVerdict: "BLOCK",
|
|
70
|
+
atbashReason: memDecision.blockReason ?? "memory write blocked",
|
|
71
|
+
atbashToolCallId: null,
|
|
72
|
+
atbashConfidence: null
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
memoryHandledIds.add(tc.id);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const auditCalls = toolCalls.filter((tc) => !memoryHandledIds.has(tc.id));
|
|
80
|
+
if (auditCalls.length === 0) {
|
|
81
|
+
return {
|
|
82
|
+
atbashVerdict: "ALLOW",
|
|
83
|
+
atbashReason: "Memory operations validated by guard",
|
|
84
|
+
atbashToolCallId: null,
|
|
85
|
+
atbashConfidence: null
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const actionText = auditCalls.map((toolCall) => `${toolCall.name}(${JSON.stringify(toolCall.args)})`).join("; ");
|
|
37
89
|
try {
|
|
38
90
|
const decision = await opts.client.auditToolCall({
|
|
39
|
-
toolName:
|
|
40
|
-
args:
|
|
91
|
+
toolName: auditCalls.map((t) => t.name).join(",") || "langgraph_batch",
|
|
92
|
+
args: auditCalls,
|
|
41
93
|
context: `LangGraph agent attempting: ${actionText}`
|
|
42
94
|
});
|
|
43
95
|
if (decision.verdict === "BLOCK" || decision.verdict === "ERROR") {
|
|
@@ -101,9 +153,6 @@ function createGuardNode(opts) {
|
|
|
101
153
|
};
|
|
102
154
|
}
|
|
103
155
|
|
|
104
|
-
// src/nodes/auditNode.ts
|
|
105
|
-
import { Atbash } from "@atbash/sdk";
|
|
106
|
-
|
|
107
156
|
// src/utils.ts
|
|
108
157
|
function truncateText(value, max = 500) {
|
|
109
158
|
return value.length <= max ? value : `${value.slice(0, max - 3)}...`;
|
|
@@ -111,12 +160,12 @@ function truncateText(value, max = 500) {
|
|
|
111
160
|
|
|
112
161
|
// src/nodes/auditNode.ts
|
|
113
162
|
function createAuditNode(opts) {
|
|
163
|
+
const { client } = opts;
|
|
114
164
|
return async (state) => {
|
|
115
165
|
const lastMessage = state.messages[state.messages.length - 1];
|
|
116
166
|
const content = typeof lastMessage?.content === "string" ? lastMessage.content : JSON.stringify(lastMessage?.content ?? "");
|
|
117
167
|
try {
|
|
118
|
-
|
|
119
|
-
await client.judgeAction(
|
|
168
|
+
await client.logToolCall(
|
|
120
169
|
truncateText(content, 500),
|
|
121
170
|
"LangGraph tool execution completed"
|
|
122
171
|
);
|
|
@@ -128,25 +177,45 @@ function createAuditNode(opts) {
|
|
|
128
177
|
|
|
129
178
|
// src/builder.ts
|
|
130
179
|
import {
|
|
131
|
-
Atbash
|
|
132
|
-
|
|
180
|
+
Atbash,
|
|
181
|
+
createMemoryGuardManager,
|
|
133
182
|
setupTelemetry,
|
|
134
183
|
shutdownTelemetry
|
|
135
184
|
} from "@atbash/sdk";
|
|
185
|
+
import { homedir } from "os";
|
|
186
|
+
function expandHome(p) {
|
|
187
|
+
return p.replace(/^~(?=\/|$)/, homedir());
|
|
188
|
+
}
|
|
136
189
|
function addAtbashSafety(builder, opts) {
|
|
137
190
|
setupTelemetry({ enabled: true, source: "plugin:langgraph" });
|
|
138
191
|
process.once("beforeExit", () => shutdownTelemetry());
|
|
139
192
|
process.once("SIGINT", () => shutdownTelemetry().finally(() => process.exit(0)));
|
|
140
193
|
process.once("SIGTERM", () => shutdownTelemetry().finally(() => process.exit(0)));
|
|
141
|
-
const privkey = opts.privkey ?? process.env.ATBASH_AGENT_PRIVKEY;
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
const client = new
|
|
194
|
+
const privkey = opts.privkey ?? process.env.ATBASH_AGENT_PRIVKEY ?? "";
|
|
195
|
+
const clientOpts = {};
|
|
196
|
+
if (opts.endpoint) clientOpts.endpoint = opts.endpoint;
|
|
197
|
+
const client = new Atbash(privkey, clientOpts);
|
|
198
|
+
const guard = createMemoryGuardManager({
|
|
199
|
+
auth: client.auth,
|
|
200
|
+
workspaceDir: opts.workspaceDir ? expandHome(opts.workspaceDir) : process.cwd(),
|
|
201
|
+
...opts.memoryFilePath ? { memoryFilePath: expandHome(opts.memoryFilePath) } : {},
|
|
202
|
+
...opts.memorySyncTTLMs !== void 0 ? { ttlMs: opts.memorySyncTTLMs } : {},
|
|
203
|
+
...opts.memoryRollbackMinScore !== void 0 ? { rollbackMinScore: opts.memoryRollbackMinScore } : {},
|
|
204
|
+
...opts.memoryPathPatterns ? { memoryPathPatterns: opts.memoryPathPatterns } : {},
|
|
205
|
+
...opts.judgeEndpoint ? { judgeEndpoint: opts.judgeEndpoint } : {},
|
|
206
|
+
...opts.judgeVerifyPubKey ? { judgeVerifyPubKey: opts.judgeVerifyPubKey } : {},
|
|
207
|
+
...opts.orgName ? { orgName: opts.orgName } : {},
|
|
208
|
+
enforce: opts.enforce ?? true,
|
|
209
|
+
debug: opts.debug ?? false
|
|
210
|
+
});
|
|
211
|
+
guard.runBootProbe().catch((err) => {
|
|
212
|
+
console.warn("[atbash] boot probe failed:", err instanceof Error ? err.message : String(err));
|
|
213
|
+
});
|
|
145
214
|
const graph = builder;
|
|
146
215
|
const toolsNode = opts.toolsNode ?? "tools";
|
|
147
216
|
const agentNode = opts.agentNode ?? "agent";
|
|
148
|
-
graph.addNode("atbash_guard", createGuardNode({ client }));
|
|
149
|
-
graph.addNode("atbash_audit", createAuditNode({
|
|
217
|
+
graph.addNode("atbash_guard", createGuardNode({ client, guardManager: guard }));
|
|
218
|
+
graph.addNode("atbash_audit", createAuditNode({ client }));
|
|
150
219
|
graph.addConditionalEdges("atbash_guard", (state) => {
|
|
151
220
|
return state.atbashVerdict === "ALLOW" ? toolsNode : agentNode;
|
|
152
221
|
});
|
|
@@ -156,19 +225,21 @@ function addAtbashSafety(builder, opts) {
|
|
|
156
225
|
}
|
|
157
226
|
|
|
158
227
|
// src/tools/judgeTool.ts
|
|
159
|
-
import { Atbash as Atbash3 } from "@atbash/sdk";
|
|
160
228
|
import { tool } from "@langchain/core/tools";
|
|
161
229
|
import { z } from "zod";
|
|
162
|
-
function createJudgeTool(
|
|
230
|
+
function createJudgeTool(client) {
|
|
163
231
|
return tool(
|
|
164
232
|
async ({ action, context }) => {
|
|
165
|
-
const
|
|
166
|
-
|
|
233
|
+
const decision = await client.auditToolCall({
|
|
234
|
+
toolName: "atbash_safety_check",
|
|
235
|
+
args: { action },
|
|
236
|
+
context
|
|
237
|
+
});
|
|
167
238
|
return JSON.stringify({
|
|
168
|
-
verdict:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
tool_call_id:
|
|
239
|
+
verdict: decision.verdict,
|
|
240
|
+
allow: decision.allow,
|
|
241
|
+
reason: decision.reason,
|
|
242
|
+
tool_call_id: decision.toolCallId
|
|
172
243
|
});
|
|
173
244
|
},
|
|
174
245
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atbash/atbash-langgraph",
|
|
3
|
-
"version": "0.0.5-dev.
|
|
3
|
+
"version": "0.0.5-dev.4",
|
|
4
4
|
"description": "Atbash safety guard and audit nodes for LangGraph workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"prepublishOnly": "npm run build"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@atbash/sdk": "0.5
|
|
40
|
+
"@atbash/sdk": "0.10.5-dev.0",
|
|
41
41
|
"zod": "^3.25.76"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|