@desplega.ai/agent-fs 0.1.4 → 0.2.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/README.md +102 -0
- package/dist/__tests__/api-client.test.d.ts +2 -0
- package/dist/__tests__/api-client.test.d.ts.map +1 -0
- package/dist/__tests__/api-client.test.js +86 -0
- package/dist/__tests__/api-client.test.js.map +1 -0
- package/dist/__tests__/param-mapping.test.d.ts +2 -0
- package/dist/__tests__/param-mapping.test.d.ts.map +1 -0
- package/dist/__tests__/param-mapping.test.js +53 -0
- package/dist/__tests__/param-mapping.test.js.map +1 -0
- package/dist/api-client.d.ts +17 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +59 -0
- package/dist/api-client.js.map +1 -0
- package/dist/cli.js +191 -32
- package/dist/commands/auth.d.ts +4 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +81 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/comment.d.ts +4 -0
- package/dist/commands/comment.d.ts.map +1 -0
- package/dist/commands/comment.js +165 -0
- package/dist/commands/comment.js.map +1 -0
- package/dist/commands/config-cmd.d.ts +3 -0
- package/dist/commands/config-cmd.d.ts.map +1 -0
- package/dist/commands/config-cmd.js +147 -0
- package/dist/commands/config-cmd.js.map +1 -0
- package/dist/commands/daemon.d.ts +3 -0
- package/dist/commands/daemon.d.ts.map +1 -0
- package/dist/commands/daemon.js +33 -0
- package/dist/commands/daemon.js.map +1 -0
- package/dist/commands/docs.d.ts +3 -0
- package/dist/commands/docs.d.ts.map +1 -0
- package/dist/commands/docs.js +13 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/drive.d.ts +4 -0
- package/dist/commands/drive.d.ts.map +1 -0
- package/dist/commands/drive.js +86 -0
- package/dist/commands/drive.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +20 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/onboard.d.ts +3 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +229 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/ops.d.ts +4 -0
- package/dist/commands/ops.d.ts.map +1 -0
- package/dist/commands/ops.js +100 -0
- package/dist/commands/ops.js.map +1 -0
- package/dist/formatters.d.ts +11 -0
- package/dist/formatters.d.ts.map +1 -0
- package/dist/formatters.js +257 -0
- package/dist/formatters.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/{src/index.ts → dist/index.js} +33 -46
- package/dist/index.js.map +1 -0
- package/package.json +21 -10
package/README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://github.com/desplega-ai/agent-fs/stargazers"><img src="https://img.shields.io/github/stars/desplega-ai/agent-fs?style=flat-square&color=yellow" alt="GitHub Stars"></a>
|
|
3
|
+
<a href="https://github.com/desplega-ai/agent-fs/blob/main/LICENSE"><img src="https://img.shields.io/github/license/desplega-ai/agent-fs?style=flat-square" alt="MIT License"></a>
|
|
4
|
+
<a href="https://github.com/desplega-ai/agent-fs/pulls"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen?style=flat-square" alt="PRs Welcome"></a>
|
|
5
|
+
<a href="https://discord.gg/KZgfyyDVZa"><img src="https://img.shields.io/badge/Discord-Join%20us-5865F2?style=flat-square&logo=discord&logoColor=white" alt="Discord"></a>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<b>A persistent, searchable filesystem for AI agents.</b><br/>
|
|
10
|
+
<sub>Built by <a href="https://desplega.sh">desplega.sh</a> — by builders, for builders.</sub>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
Agent FS gives AI agents a structured filesystem with built-in semantic search, versioning, and identity management. It runs as a CLI and an HTTP server with integrated MCP support — so any AI coding assistant can use it as a long-term memory and file store.
|
|
16
|
+
|
|
17
|
+
## Key Features
|
|
18
|
+
|
|
19
|
+
- **Semantic search** — Index and search files using vector embeddings (OpenAI, Google GenAI, or local llama.cpp)
|
|
20
|
+
- **Structured storage** — SQLite-backed file operations with metadata and versioning
|
|
21
|
+
- **S3-compatible sync** — Sync agent workspaces to any S3-compatible object store
|
|
22
|
+
- **Identity management** — Persistent agent identity files that evolve over time
|
|
23
|
+
- **MCP integration** — Expose filesystem operations as MCP tools for Claude Code, Codex, and other assistants
|
|
24
|
+
- **HTTP API** — RESTful server powered by Hono for programmatic access
|
|
25
|
+
- **CLI** — Single binary (`agent-fs`) for local use and scripting
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
### Install
|
|
30
|
+
|
|
31
|
+
Requires [Bun](https://bun.sh) >= 1.2.0.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
bun add -g @desplega.ai/agent-fs
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or build from source:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
git clone https://github.com/desplega-ai/agent-fs.git
|
|
41
|
+
cd agent-fs
|
|
42
|
+
bun install
|
|
43
|
+
bun run build
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Usage
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Show available commands
|
|
50
|
+
agent-fs --help
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Architecture
|
|
54
|
+
|
|
55
|
+
Agent FS is a Bun monorepo with four packages:
|
|
56
|
+
|
|
57
|
+
| Package | Description |
|
|
58
|
+
|---------|-------------|
|
|
59
|
+
| `@desplega.ai/agent-fs-core` | Core library — storage engine, semantic search, identity, S3 sync |
|
|
60
|
+
| `@desplega.ai/agent-fs` | CLI binary (`agent-fs`) |
|
|
61
|
+
| `@desplega.ai/agent-fs-mcp` | MCP stdio proxy + tool registration for the HTTP server |
|
|
62
|
+
| `@desplega.ai/agent-fs-server` | HTTP server — RESTful API powered by Hono |
|
|
63
|
+
|
|
64
|
+
## Documentation
|
|
65
|
+
|
|
66
|
+
- [MCP Setup Guide](./docs/mcp-setup.md) — Connect agent-fs to Claude Code, Cursor, or any MCP client
|
|
67
|
+
- [Deployment Guide](./docs/deployment.md) — Local, remote S3, team, and multi-agent deployments
|
|
68
|
+
- [API Reference](./docs/api-reference.md) — HTTP API and OpenAPI spec
|
|
69
|
+
|
|
70
|
+
## Development
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
bun install # Install dependencies
|
|
74
|
+
bun run typecheck # Type checking
|
|
75
|
+
bun run test # Run tests
|
|
76
|
+
bun run build # Bundle CLI for npm
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full development guide.
|
|
80
|
+
|
|
81
|
+
## Releasing
|
|
82
|
+
|
|
83
|
+
1. Update `version` in root `package.json`
|
|
84
|
+
2. Commit the version bump
|
|
85
|
+
3. Run `./scripts/release.sh`
|
|
86
|
+
|
|
87
|
+
This creates a git tag and pushes it, triggering the release workflow which publishes to npm and creates a GitHub Release.
|
|
88
|
+
|
|
89
|
+
## Contributing
|
|
90
|
+
|
|
91
|
+
We welcome contributions! Whether it's bug reports, feature requests, docs improvements, or code — all are welcome.
|
|
92
|
+
|
|
93
|
+
1. Fork the repo
|
|
94
|
+
2. Create a branch (`git checkout -b my-feature`)
|
|
95
|
+
3. Make your changes
|
|
96
|
+
4. Open a PR
|
|
97
|
+
|
|
98
|
+
Join our [Discord](https://discord.gg/KZgfyyDVZa) if you have questions or want to discuss ideas.
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
[MIT](./LICENSE) — 2025-2026 [desplega.ai](https://desplega.ai)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/api-client.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, test, expect, beforeAll, afterAll } from "bun:test";
|
|
2
|
+
import { createTestDb, MockS3Client } from "../../../core/src/test-utils.js";
|
|
3
|
+
import { createApp } from "../../../server/src/app.js";
|
|
4
|
+
// We test ApiClient by pointing it at a real in-memory Hono server.
|
|
5
|
+
let server;
|
|
6
|
+
let port = 0;
|
|
7
|
+
let apiKey;
|
|
8
|
+
let orgId;
|
|
9
|
+
beforeAll(async () => {
|
|
10
|
+
const db = createTestDb();
|
|
11
|
+
const s3 = new MockS3Client();
|
|
12
|
+
const app = createApp(db, s3);
|
|
13
|
+
// Start on a random port
|
|
14
|
+
server = Bun.serve({
|
|
15
|
+
port: 0,
|
|
16
|
+
fetch: app.fetch,
|
|
17
|
+
});
|
|
18
|
+
port = server.port;
|
|
19
|
+
// Register a user to get an API key
|
|
20
|
+
const res = await fetch(`http://localhost:${port}/auth/register`, {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: { "Content-Type": "application/json" },
|
|
23
|
+
body: JSON.stringify({ email: "cli-test@example.com" }),
|
|
24
|
+
});
|
|
25
|
+
const body = await res.json();
|
|
26
|
+
apiKey = body.apiKey;
|
|
27
|
+
orgId = body.orgId;
|
|
28
|
+
// Set env vars so ApiClient picks them up
|
|
29
|
+
process.env.AGENT_FS_API_URL = `http://localhost:${port}`;
|
|
30
|
+
process.env.AGENT_FS_API_KEY = apiKey;
|
|
31
|
+
});
|
|
32
|
+
afterAll(() => {
|
|
33
|
+
server?.stop();
|
|
34
|
+
delete process.env.AGENT_FS_API_URL;
|
|
35
|
+
delete process.env.AGENT_FS_API_KEY;
|
|
36
|
+
});
|
|
37
|
+
describe("ApiClient", () => {
|
|
38
|
+
// Dynamic import so env vars are set before constructor runs
|
|
39
|
+
async function makeClient() {
|
|
40
|
+
const { ApiClient } = await import("../api-client.js");
|
|
41
|
+
return new ApiClient();
|
|
42
|
+
}
|
|
43
|
+
test("get() fetches data", async () => {
|
|
44
|
+
const client = await makeClient();
|
|
45
|
+
const result = await client.get("/orgs");
|
|
46
|
+
expect(result.orgs).toBeDefined();
|
|
47
|
+
expect(result.orgs.length).toBeGreaterThan(0);
|
|
48
|
+
});
|
|
49
|
+
test("post() sends data", async () => {
|
|
50
|
+
const client = await makeClient();
|
|
51
|
+
const result = await client.post("/orgs", { name: "cli-test-org" });
|
|
52
|
+
expect(result.name).toBe("cli-test-org");
|
|
53
|
+
});
|
|
54
|
+
test("callOp() dispatches operation", async () => {
|
|
55
|
+
const client = await makeClient();
|
|
56
|
+
// Write a file
|
|
57
|
+
const writeResult = await client.callOp(orgId, "write", {
|
|
58
|
+
path: "/cli-test.txt",
|
|
59
|
+
content: "Hello from CLI",
|
|
60
|
+
});
|
|
61
|
+
expect(writeResult.version).toBe(1);
|
|
62
|
+
// Read it back
|
|
63
|
+
const catResult = await client.callOp(orgId, "cat", {
|
|
64
|
+
path: "/cli-test.txt",
|
|
65
|
+
});
|
|
66
|
+
expect(catResult.content).toBe("Hello from CLI");
|
|
67
|
+
});
|
|
68
|
+
test("setApiKey() changes auth", async () => {
|
|
69
|
+
const client = await makeClient();
|
|
70
|
+
client.setApiKey("af_invalid_key");
|
|
71
|
+
// Should fail with auth error
|
|
72
|
+
await expect(client.get("/orgs")).rejects.toThrow();
|
|
73
|
+
});
|
|
74
|
+
test("connection error gives helpful message", async () => {
|
|
75
|
+
process.env.AGENT_FS_API_URL = "http://localhost:1"; // Nothing running
|
|
76
|
+
const client = await makeClient();
|
|
77
|
+
await expect(client.get("/health")).rejects.toThrow(/Cannot connect/);
|
|
78
|
+
// Restore
|
|
79
|
+
process.env.AGENT_FS_API_URL = `http://localhost:${port}`;
|
|
80
|
+
});
|
|
81
|
+
test("server error includes message from response", async () => {
|
|
82
|
+
const client = await makeClient();
|
|
83
|
+
await expect(client.callOp(orgId, "cat", { path: "/nonexistent.txt" })).rejects.toThrow(/not found|NoSuchKey/i);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=api-client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.test.js","sourceRoot":"","sources":["../../src/__tests__/api-client.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"param-mapping.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/param-mapping.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, test, expect } from "bun:test";
|
|
2
|
+
/**
|
|
3
|
+
* Tests for CLI flag → Zod schema param mapping.
|
|
4
|
+
* The CLI uses --old/--new flags but the edit Zod schema expects old_string/new_string.
|
|
5
|
+
* The CLI uses --expected-version but the write Zod schema expects expectedVersion.
|
|
6
|
+
*/
|
|
7
|
+
function applyParamMapping(params) {
|
|
8
|
+
const mapped = { ...params };
|
|
9
|
+
// These mappings mirror packages/cli/src/commands/ops.ts
|
|
10
|
+
if (mapped["expected-version"] !== undefined) {
|
|
11
|
+
mapped.expectedVersion = mapped["expected-version"];
|
|
12
|
+
delete mapped["expected-version"];
|
|
13
|
+
}
|
|
14
|
+
if (mapped["old"] !== undefined) {
|
|
15
|
+
mapped.old_string = mapped["old"];
|
|
16
|
+
delete mapped["old"];
|
|
17
|
+
}
|
|
18
|
+
if (mapped["new"] !== undefined) {
|
|
19
|
+
mapped.new_string = mapped["new"];
|
|
20
|
+
delete mapped["new"];
|
|
21
|
+
}
|
|
22
|
+
return mapped;
|
|
23
|
+
}
|
|
24
|
+
describe("CLI param mapping", () => {
|
|
25
|
+
test("maps --old to old_string and --new to new_string", () => {
|
|
26
|
+
const input = { path: "/test.md", old: "hello", new: "world" };
|
|
27
|
+
const result = applyParamMapping(input);
|
|
28
|
+
expect(result.old_string).toBe("hello");
|
|
29
|
+
expect(result.new_string).toBe("world");
|
|
30
|
+
expect(result.old).toBeUndefined();
|
|
31
|
+
expect(result.new).toBeUndefined();
|
|
32
|
+
expect(result.path).toBe("/test.md");
|
|
33
|
+
});
|
|
34
|
+
test("maps --expected-version to expectedVersion", () => {
|
|
35
|
+
const input = { path: "/test.md", "expected-version": "3" };
|
|
36
|
+
const result = applyParamMapping(input);
|
|
37
|
+
expect(result.expectedVersion).toBe("3");
|
|
38
|
+
expect(result["expected-version"]).toBeUndefined();
|
|
39
|
+
});
|
|
40
|
+
test("does not affect params without CLI flag names", () => {
|
|
41
|
+
const input = { path: "/test.md", content: "hello", message: "update" };
|
|
42
|
+
const result = applyParamMapping(input);
|
|
43
|
+
expect(result).toEqual(input);
|
|
44
|
+
});
|
|
45
|
+
test("handles missing optional params gracefully", () => {
|
|
46
|
+
const input = { path: "/test.md", old: "hello" };
|
|
47
|
+
const result = applyParamMapping(input);
|
|
48
|
+
expect(result.old_string).toBe("hello");
|
|
49
|
+
expect(result.new_string).toBeUndefined();
|
|
50
|
+
expect(result.old).toBeUndefined();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=param-mapping.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"param-mapping.test.js","sourceRoot":"","sources":["../../src/__tests__/param-mapping.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class ApiClient {
|
|
2
|
+
private baseUrl;
|
|
3
|
+
private apiKey;
|
|
4
|
+
constructor();
|
|
5
|
+
private request;
|
|
6
|
+
get(path: string): Promise<any>;
|
|
7
|
+
post(path: string, body: any): Promise<any>;
|
|
8
|
+
callOp(orgId: string, op: string, params: Record<string, any>): Promise<any>;
|
|
9
|
+
getMe(): Promise<{
|
|
10
|
+
userId: string;
|
|
11
|
+
email: string;
|
|
12
|
+
defaultOrgId: string | null;
|
|
13
|
+
defaultDriveId: string | null;
|
|
14
|
+
}>;
|
|
15
|
+
setApiKey(key: string): void;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAEA,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;;YAUT,OAAO;IA+Bf,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAI/B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAO3C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAI5E,KAAK,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAIrH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAG7B"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getConfig } from "@/core";
|
|
2
|
+
export class ApiClient {
|
|
3
|
+
baseUrl;
|
|
4
|
+
apiKey;
|
|
5
|
+
constructor() {
|
|
6
|
+
const config = getConfig();
|
|
7
|
+
this.baseUrl =
|
|
8
|
+
process.env.AGENT_FS_API_URL ??
|
|
9
|
+
`http://${config.server.host}:${config.server.port}`;
|
|
10
|
+
this.apiKey = process.env.AGENT_FS_API_KEY ?? config.auth.apiKey;
|
|
11
|
+
}
|
|
12
|
+
async request(path, opts) {
|
|
13
|
+
const headers = new Headers(opts?.headers);
|
|
14
|
+
if (this.apiKey) {
|
|
15
|
+
headers.set("Authorization", `Bearer ${this.apiKey}`);
|
|
16
|
+
}
|
|
17
|
+
headers.set("Content-Type", "application/json");
|
|
18
|
+
let res;
|
|
19
|
+
try {
|
|
20
|
+
res = await fetch(`${this.baseUrl}${path}`, { ...opts, headers });
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
throw new Error(`Cannot connect to agent-fs daemon at ${this.baseUrl}. Is it running? Start with: agent-fs daemon start`);
|
|
24
|
+
}
|
|
25
|
+
let body;
|
|
26
|
+
try {
|
|
27
|
+
body = await res.json();
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
const text = await res.text().catch(() => "");
|
|
31
|
+
throw new Error(`Unexpected response from daemon (${res.status}): ${text || "empty"}`);
|
|
32
|
+
}
|
|
33
|
+
if (!res.ok) {
|
|
34
|
+
const msg = body.message ?? body.error ?? "Request failed";
|
|
35
|
+
const suggestion = body.suggestion ? `\n Suggestion: ${body.suggestion}` : "";
|
|
36
|
+
throw new Error(`${msg}${suggestion}`);
|
|
37
|
+
}
|
|
38
|
+
return body;
|
|
39
|
+
}
|
|
40
|
+
async get(path) {
|
|
41
|
+
return this.request(path);
|
|
42
|
+
}
|
|
43
|
+
async post(path, body) {
|
|
44
|
+
return this.request(path, {
|
|
45
|
+
method: "POST",
|
|
46
|
+
body: JSON.stringify(body),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async callOp(orgId, op, params) {
|
|
50
|
+
return this.post(`/orgs/${orgId}/ops`, { op, ...params });
|
|
51
|
+
}
|
|
52
|
+
async getMe() {
|
|
53
|
+
return this.get("/auth/me");
|
|
54
|
+
}
|
|
55
|
+
setApiKey(key) {
|
|
56
|
+
this.apiKey = key;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
|