@tineira/apc-conformance 0.0.0-stage → 0.7.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.
@@ -0,0 +1,95 @@
1
+ /**
2
+ * A Cloudflare Durable Object on Node, for the conformance suite and other local tests (no network,
3
+ * no workerd): the object's own code on Node's SQLite, with a stand-in for what Cloudflare gives it.
4
+ * The person's pages are fake WebSockets that record what the object sends them.
5
+ *
6
+ * Call `installWorkersStandIn()` before importing a module that imports "cloudflare:workers".
7
+ */
8
+ import { registerHooks } from "node:module";
9
+ import { DatabaseSync } from "node:sqlite";
10
+ let installed = false;
11
+ /** Lets "cloudflare:workers" resolve on Node, to a DurableObject base class that keeps ctx and env. */
12
+ export function installWorkersStandIn() {
13
+ if (installed)
14
+ return;
15
+ installed = true;
16
+ registerHooks({
17
+ resolve(specifier, context, next) {
18
+ if (specifier === "cloudflare:workers")
19
+ return { url: "data:text/javascript,export class DurableObject { constructor(ctx, env) { this.ctx = ctx; this.env = env; } }", shortCircuit: true };
20
+ return next(specifier, context);
21
+ },
22
+ });
23
+ const g = globalThis;
24
+ g.WebSocketRequestResponsePair ??= class {
25
+ };
26
+ }
27
+ export function durableObjectRoom() {
28
+ const db = new DatabaseSync(":memory:");
29
+ const sql = {
30
+ exec(query, ...params) {
31
+ if (query.trim().replace(/;\s*$/, "").includes(";")) {
32
+ db.exec(query);
33
+ return { toArray: () => [] };
34
+ }
35
+ const statement = db.prepare(query);
36
+ const rows = statement.columns().length ? statement.all(...params) : (statement.run(...params), []);
37
+ return { toArray: () => rows };
38
+ },
39
+ };
40
+ const tables = () => db.prepare("select name from sqlite_master where type = 'table' and name not like 'sqlite_%'").all().map((t) => String(t.name));
41
+ const OPEN = 1;
42
+ const room = {
43
+ db,
44
+ alarm: null,
45
+ pages: [],
46
+ ctx: {
47
+ storage: {
48
+ sql,
49
+ setAlarm: async (at) => void (room.alarm = at),
50
+ deleteAll: async () => {
51
+ for (const table of tables())
52
+ db.exec(`drop table ${table}`);
53
+ },
54
+ },
55
+ setWebSocketAutoResponse: () => { },
56
+ blockConcurrencyWhile: (work) => work(),
57
+ acceptWebSocket: () => { },
58
+ getWebSockets: () => room.pages.filter((p) => p.readyState === OPEN),
59
+ // Every open page answered its heartbeat just now.
60
+ getWebSocketAutoResponseTimestamp: () => new Date(),
61
+ },
62
+ openPage() {
63
+ let attachment = { accepted_at: Date.now() };
64
+ const page = {
65
+ readyState: OPEN,
66
+ sent: [],
67
+ send: (text) => void page.sent.push(text),
68
+ close: () => void (page.readyState = 3),
69
+ serializeAttachment: (value) => void (attachment = value),
70
+ deserializeAttachment: () => attachment,
71
+ };
72
+ room.pages.push(page);
73
+ return page;
74
+ },
75
+ closePages() {
76
+ for (const page of room.pages)
77
+ page.close();
78
+ },
79
+ takeMessages() {
80
+ const out = [];
81
+ for (const page of room.pages) {
82
+ for (const text of page.sent.splice(0)) {
83
+ try {
84
+ out.push(JSON.parse(text));
85
+ }
86
+ catch {
87
+ // not JSON
88
+ }
89
+ }
90
+ }
91
+ return out;
92
+ },
93
+ };
94
+ return room;
95
+ }
package/package.json CHANGED
@@ -1,6 +1,55 @@
1
1
  {
2
2
  "name": "@tineira/apc-conformance",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.7.0",
4
+ "description": "Agent Pointed Context (APC) conformance: checks an app against the standard, in process with an adapter, or live over HTTP with the apc-conformance command.",
5
+ "keywords": [
6
+ "apc",
7
+ "agent-pointed-context",
8
+ "mcp",
9
+ "model-context-protocol",
10
+ "ai-agents",
11
+ "conformance",
12
+ "testing"
13
+ ],
14
+ "homepage": "https://apc.tineira.com/docs",
15
+ "bugs": {
16
+ "url": "https://github.com/tineira/agent-pointed-context/issues"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/tineira/agent-pointed-context",
21
+ "directory": "packages/conformance"
22
+ },
23
+ "license": "MIT",
24
+ "type": "module",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.js"
29
+ },
30
+ "./workers": {
31
+ "types": "./dist/workers.d.ts",
32
+ "import": "./dist/workers.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "README.md",
38
+ "LICENSE"
39
+ ],
40
+ "sideEffects": false,
41
+ "engines": {
42
+ "node": ">=22.15"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "dependencies": {
48
+ "@tineira/apc-protocol": "^0.7.0"
49
+ },
50
+ "scripts": {},
51
+ "types": "./dist/index.d.ts",
52
+ "bin": {
53
+ "apc-conformance": "./dist/cli.js"
54
+ }
6
55
  }