@atbash/atbash-langgraph 0.0.11 → 0.0.13

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 CHANGED
@@ -30,6 +30,25 @@ interface AtbashSafetyOptions {
30
30
  endpoint?: string;
31
31
  toolsNode?: string;
32
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;
33
52
  }
34
53
  declare function addAtbashSafety(builder: StateGraph<AtbashState>, opts: AtbashSafetyOptions): StateGraph<_langchain_langgraph.StateType<{
35
54
  atbashVerdict: _langchain_langgraph.BaseChannel<string | null, string | _langchain_langgraph.OverwriteValue<string | null> | null, unknown>;
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@ var AtbashStateAnnotation = Annotation.Root({
21
21
  });
22
22
 
23
23
  // src/nodes/guardNode.ts
24
+ import { MemoryIntegrityError } from "@atbash/sdk";
24
25
  import { ToolMessage } from "@langchain/core/messages";
25
26
  import { isGraphBubbleUp } from "@langchain/langgraph";
26
27
  function createGuardNode(opts) {
@@ -33,6 +34,7 @@ function createGuardNode(opts) {
33
34
  atbashReason: "No tool calls detected"
34
35
  };
35
36
  }
37
+ const memoryHandledIds = /* @__PURE__ */ new Set();
36
38
  if (opts.guardManager) {
37
39
  for (const tc of toolCalls) {
38
40
  let memDecision;
@@ -43,6 +45,7 @@ function createGuardNode(opts) {
43
45
  );
44
46
  } catch (err) {
45
47
  const reason = err instanceof Error ? err.message : String(err);
48
+ const verdict = err instanceof MemoryIntegrityError ? "BLOCK" : "ERROR";
46
49
  return {
47
50
  messages: toolCalls.map(
48
51
  (toolCall) => new ToolMessage({
@@ -50,33 +53,45 @@ function createGuardNode(opts) {
50
53
  content: toolCall.id === tc.id ? `Memory guard error: ${reason}` : "Blocked \u2014 memory safety check failed for another tool call"
51
54
  })
52
55
  ),
53
- atbashVerdict: "BLOCK",
56
+ atbashVerdict: verdict,
54
57
  atbashReason: `Memory guard error: ${reason}`,
55
58
  atbashToolCallId: null,
56
59
  atbashConfidence: null
57
60
  };
58
61
  }
59
- if (memDecision !== null && memDecision.block) {
60
- return {
61
- messages: toolCalls.map(
62
- (toolCall) => new ToolMessage({
63
- tool_call_id: toolCall.id,
64
- content: toolCall.id === tc.id ? `Memory write blocked by Atbash: ${memDecision.blockReason ?? ""}` : "Blocked \u2014 another tool call was blocked by memory safety"
65
- })
66
- ),
67
- atbashVerdict: "BLOCK",
68
- atbashReason: memDecision.blockReason ?? "memory write blocked",
69
- atbashToolCallId: null,
70
- atbashConfidence: null
71
- };
62
+ if (memDecision !== null) {
63
+ if (memDecision.block) {
64
+ return {
65
+ messages: toolCalls.map(
66
+ (toolCall) => new ToolMessage({
67
+ tool_call_id: toolCall.id,
68
+ content: toolCall.id === tc.id ? `Memory write blocked by Atbash: ${memDecision.blockReason ?? ""}` : "Blocked \u2014 another tool call was blocked by memory safety"
69
+ })
70
+ ),
71
+ atbashVerdict: "BLOCK",
72
+ atbashReason: memDecision.blockReason ?? "memory write blocked",
73
+ atbashToolCallId: null,
74
+ atbashConfidence: null
75
+ };
76
+ }
77
+ memoryHandledIds.add(tc.id);
72
78
  }
73
79
  }
74
80
  }
75
- const actionText = toolCalls.map((toolCall) => `${toolCall.name}(${JSON.stringify(toolCall.args)})`).join("; ");
81
+ const auditCalls = toolCalls.filter((tc) => !memoryHandledIds.has(tc.id));
82
+ if (auditCalls.length === 0) {
83
+ return {
84
+ atbashVerdict: "ALLOW",
85
+ atbashReason: "Memory operations validated by guard",
86
+ atbashToolCallId: null,
87
+ atbashConfidence: null
88
+ };
89
+ }
90
+ const actionText = auditCalls.map((toolCall) => `${toolCall.name}(${JSON.stringify(toolCall.args)})`).join("; ");
76
91
  try {
77
92
  const decision = await opts.client.auditToolCall({
78
- toolName: toolCalls.map((t) => t.name).join(",") || "langgraph_batch",
79
- args: toolCalls,
93
+ toolName: auditCalls.map((t) => t.name).join(",") || "langgraph_batch",
94
+ args: auditCalls,
80
95
  context: `LangGraph agent attempting: ${actionText}`
81
96
  });
82
97
  if (decision.verdict === "BLOCK" || decision.verdict === "ERROR") {
@@ -165,9 +180,14 @@ function createAuditNode(opts) {
165
180
  // src/builder.ts
166
181
  import {
167
182
  Atbash,
183
+ createMemoryGuardManager,
168
184
  setupTelemetry,
169
185
  shutdownTelemetry
170
186
  } from "@atbash/sdk";
187
+ import { homedir } from "os";
188
+ function expandHome(p) {
189
+ return p.replace(/^~(?=\/|$)/, homedir());
190
+ }
171
191
  function addAtbashSafety(builder, opts) {
172
192
  setupTelemetry({ enabled: true, source: "plugin:langgraph" });
173
193
  process.once("beforeExit", () => shutdownTelemetry());
@@ -177,10 +197,26 @@ function addAtbashSafety(builder, opts) {
177
197
  const clientOpts = {};
178
198
  if (opts.endpoint) clientOpts.endpoint = opts.endpoint;
179
199
  const client = new Atbash(privkey, clientOpts);
200
+ const guard = createMemoryGuardManager({
201
+ auth: client.auth,
202
+ workspaceDir: opts.workspaceDir ? expandHome(opts.workspaceDir) : process.cwd(),
203
+ ...opts.memoryFilePath ? { memoryFilePath: expandHome(opts.memoryFilePath) } : {},
204
+ ...opts.memorySyncTTLMs !== void 0 ? { ttlMs: opts.memorySyncTTLMs } : {},
205
+ ...opts.memoryRollbackMinScore !== void 0 ? { rollbackMinScore: opts.memoryRollbackMinScore } : {},
206
+ ...opts.memoryPathPatterns ? { memoryPathPatterns: opts.memoryPathPatterns } : {},
207
+ ...opts.judgeEndpoint ? { judgeEndpoint: opts.judgeEndpoint } : {},
208
+ ...opts.judgeVerifyPubKey ? { judgeVerifyPubKey: opts.judgeVerifyPubKey } : {},
209
+ ...opts.orgName ? { orgName: opts.orgName } : {},
210
+ enforce: opts.enforce ?? true,
211
+ debug: opts.debug ?? false
212
+ });
213
+ guard.runBootProbe().catch((err) => {
214
+ console.warn("[atbash] boot probe failed:", err instanceof Error ? err.message : String(err));
215
+ });
180
216
  const graph = builder;
181
217
  const toolsNode = opts.toolsNode ?? "tools";
182
218
  const agentNode = opts.agentNode ?? "agent";
183
- graph.addNode("atbash_guard", createGuardNode({ client }));
219
+ graph.addNode("atbash_guard", createGuardNode({ client, guardManager: guard }));
184
220
  graph.addNode("atbash_audit", createAuditNode({ client }));
185
221
  graph.addConditionalEdges("atbash_guard", (state) => {
186
222
  return state.atbashVerdict === "ALLOW" ? toolsNode : agentNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atbash/atbash-langgraph",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
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.6.1",
40
+ "@atbash/sdk": "^0.7.0",
41
41
  "zod": "^3.25.76"
42
42
  },
43
43
  "peerDependencies": {