@anynotate/protocol 0.2.0 → 0.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/PROTOCOL.md +20 -3
- package/dist/fixtures.d.ts +3 -1
- package/dist/fixtures.js +2 -2
- package/dist/index.d.ts +17 -5
- package/dist/index.js +5 -3
- package/package.json +1 -1
- package/src/fixtures.ts +2 -2
- package/src/index.ts +8 -3
package/PROTOCOL.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
# Anynotate protocol
|
|
1
|
+
# Anynotate protocol v2
|
|
2
2
|
|
|
3
3
|
The bridge is an HTTP server on `127.0.0.1`, port `47291` by default (`ANYNOTATE_PORT`). Clients send annotation **bundles**; the bridge stores each one as a folder and delivers it to an AI agent session. Constants and schemas live in `@anynotate/protocol`; request/response examples for the extension-facing endpoints live in `@anynotate/protocol/fixtures` (`conformance`).
|
|
4
4
|
|
|
5
5
|
## Handshake
|
|
6
6
|
|
|
7
|
-
`POST /health` (or `GET`) → `{ "ok": true, "bridgeVersion": "0.
|
|
7
|
+
`POST /health` (or `GET`) → `{ "ok": true, "bridgeVersion": "0.3.0", "protocol": { "version": 2, "min": 1 } }`.
|
|
8
8
|
|
|
9
|
-
A client supports a range of protocol versions (the extension: `min
|
|
9
|
+
A client supports a range of protocol versions (the extension: `min 2, max 2`) and calls `compatibility(clientRange, response.protocol)`:
|
|
10
10
|
|
|
11
11
|
- `ok` — the ranges overlap; proceed.
|
|
12
12
|
- `bridge-too-old` — ask the user to update the bridge; don't send.
|
|
@@ -66,12 +66,29 @@ Each bundle is written to `$ANYNOTATE_HOME/inbox/<id>/` (default `~/.anynotate`)
|
|
|
66
66
|
|
|
67
67
|
`$ANYNOTATE_HOME/inbox/latest` points at the newest bundle.
|
|
68
68
|
|
|
69
|
+
## Intents
|
|
70
|
+
|
|
71
|
+
Each annotation may carry an `intent` telling the agent what the user wants. `INTENTS` lists the current ones; `README.md` puts a directive line under the note's heading instead of naming the intent:
|
|
72
|
+
|
|
73
|
+
| `intent` | Directive in `README.md` |
|
|
74
|
+
|---|---|
|
|
75
|
+
| `explain` | `**Explain** this.` |
|
|
76
|
+
| `change` | `**Change requested.**` |
|
|
77
|
+
| `approve` | `**Approved** — no change needed.` |
|
|
78
|
+
|
|
79
|
+
The v1 values `question`, `bug` and `note` are still accepted and appear in the heading as before, with no directive line. `change` was also a v1 value; it keeps its name and now gets the directive line. No `intent` means no directive either.
|
|
80
|
+
|
|
69
81
|
## Evolution
|
|
70
82
|
|
|
71
83
|
- Additive changes — optional fields, new endpoints — keep `PROTOCOL_VERSION`. Both sides ignore fields they don't know.
|
|
72
84
|
- Removing, renaming or changing the meaning of anything bumps `PROTOCOL_VERSION`; the bridge keeps accepting the previous version (`PROTOCOL_MIN`) for at least one release.
|
|
73
85
|
- The bundle format has its own `v` (currently `1`); the agent-facing `README.md` stays human-readable.
|
|
74
86
|
|
|
87
|
+
### Version history
|
|
88
|
+
|
|
89
|
+
- **v1** — handshake, token-only access, native-host token delivery.
|
|
90
|
+
- **v2** — intents `explain`, `change`, `approve` (legacy `question`, `bug`, `note` still accepted). `PROTOCOL_MIN` stays `1`: a v2 bridge accepts v1 clients.
|
|
91
|
+
|
|
75
92
|
## Threat model
|
|
76
93
|
|
|
77
94
|
- **Web pages** can reach `127.0.0.1` from the user's browser. They are refused by `Origin` (including preflights), and DNS-rebinding pages by `Host`; a web request without an `Origin` (such as an `<img>` GET) fails the token check.
|
package/dist/fixtures.d.ts
CHANGED
|
@@ -67,8 +67,10 @@ export declare const responseSchemas: {
|
|
|
67
67
|
}>;
|
|
68
68
|
comment: z.ZodString;
|
|
69
69
|
intent: z.ZodOptional<z.ZodEnum<{
|
|
70
|
-
|
|
70
|
+
explain: "explain";
|
|
71
71
|
change: "change";
|
|
72
|
+
approve: "approve";
|
|
73
|
+
question: "question";
|
|
72
74
|
bug: "bug";
|
|
73
75
|
note: "note";
|
|
74
76
|
}>>;
|
package/dist/fixtures.js
CHANGED
|
@@ -11,7 +11,7 @@ export const exampleBundleInput = {
|
|
|
11
11
|
target: { agent: "claude", sessionId: "s-1", cwd: "/tmp/repo" },
|
|
12
12
|
overall: "can we make this vegan?",
|
|
13
13
|
annotations: [{
|
|
14
|
-
id: "A1", kind: "text", comment: "is there a substitute for cream?", intent: "
|
|
14
|
+
id: "A1", kind: "text", comment: "is there a substitute for cream?", intent: "explain",
|
|
15
15
|
anchor: {
|
|
16
16
|
quote: { exact: "200 ml cream", prefix: "stir in ", suffix: " before serving" },
|
|
17
17
|
css: "section#ingredients > li:nth-child(3)", path: ["main", "section#ingredients", "ul"], near: "Ingredients",
|
|
@@ -25,7 +25,7 @@ export const examplePage = "# Tomato soup\n\nstir in ⟦A1⟧200 ml cream before
|
|
|
25
25
|
export const responseSchemas = {
|
|
26
26
|
HealthResponse, SessionsResponse, SendResponse, BundleStatusResponse, OkResponse, ErrorResponse,
|
|
27
27
|
};
|
|
28
|
-
const health = { ok: true, bridgeVersion: "0.
|
|
28
|
+
const health = { ok: true, bridgeVersion: "0.3.0", protocol: { version: 2, min: 1 } };
|
|
29
29
|
const queued = { state: "queued", at: "2026-09-24T15:32:01.000Z" };
|
|
30
30
|
const exampleBundle = { ...exampleBundleInput, id: EXAMPLE_BUNDLE_ID, files: { page: "page.md", screenshot: "screenshot.png" } };
|
|
31
31
|
export const conformance = [
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,10 @@ import { z } from "zod";
|
|
|
2
2
|
export declare const AGENT_NAME: RegExp;
|
|
3
3
|
export declare const Agent: z.ZodString;
|
|
4
4
|
export type Agent = z.infer<typeof Agent>;
|
|
5
|
+
export declare const INTENTS: readonly ["explain", "change", "approve"];
|
|
6
|
+
export declare const LEGACY_INTENTS: readonly ["question", "bug", "note"];
|
|
7
|
+
/** The intent clients should send; parsed annotations may also hold a LEGACY_INTENTS value. */
|
|
8
|
+
export type Intent = (typeof INTENTS)[number];
|
|
5
9
|
export declare const Annotation: z.ZodObject<{
|
|
6
10
|
id: z.ZodString;
|
|
7
11
|
kind: z.ZodEnum<{
|
|
@@ -10,8 +14,10 @@ export declare const Annotation: z.ZodObject<{
|
|
|
10
14
|
}>;
|
|
11
15
|
comment: z.ZodString;
|
|
12
16
|
intent: z.ZodOptional<z.ZodEnum<{
|
|
13
|
-
|
|
17
|
+
explain: "explain";
|
|
14
18
|
change: "change";
|
|
19
|
+
approve: "approve";
|
|
20
|
+
question: "question";
|
|
15
21
|
bug: "bug";
|
|
16
22
|
note: "note";
|
|
17
23
|
}>>;
|
|
@@ -80,8 +86,10 @@ export declare const BundleInput: z.ZodObject<{
|
|
|
80
86
|
}>;
|
|
81
87
|
comment: z.ZodString;
|
|
82
88
|
intent: z.ZodOptional<z.ZodEnum<{
|
|
83
|
-
|
|
89
|
+
explain: "explain";
|
|
84
90
|
change: "change";
|
|
91
|
+
approve: "approve";
|
|
92
|
+
question: "question";
|
|
85
93
|
bug: "bug";
|
|
86
94
|
note: "note";
|
|
87
95
|
}>>;
|
|
@@ -145,8 +153,10 @@ export declare const Bundle: z.ZodObject<{
|
|
|
145
153
|
}>;
|
|
146
154
|
comment: z.ZodString;
|
|
147
155
|
intent: z.ZodOptional<z.ZodEnum<{
|
|
148
|
-
|
|
156
|
+
explain: "explain";
|
|
149
157
|
change: "change";
|
|
158
|
+
approve: "approve";
|
|
159
|
+
question: "question";
|
|
150
160
|
bug: "bug";
|
|
151
161
|
note: "note";
|
|
152
162
|
}>>;
|
|
@@ -234,7 +244,7 @@ export declare const Session: z.ZodObject<{
|
|
|
234
244
|
sessionIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
235
245
|
}, z.core.$strip>;
|
|
236
246
|
export type Session = z.infer<typeof Session>;
|
|
237
|
-
export declare const PROTOCOL_VERSION =
|
|
247
|
+
export declare const PROTOCOL_VERSION = 2;
|
|
238
248
|
export declare const PROTOCOL_MIN = 1;
|
|
239
249
|
export declare const HealthResponse: z.ZodObject<{
|
|
240
250
|
ok: z.ZodLiteral<true>;
|
|
@@ -301,8 +311,10 @@ export declare const BundleStatusResponse: z.ZodObject<{
|
|
|
301
311
|
}>;
|
|
302
312
|
comment: z.ZodString;
|
|
303
313
|
intent: z.ZodOptional<z.ZodEnum<{
|
|
304
|
-
|
|
314
|
+
explain: "explain";
|
|
305
315
|
change: "change";
|
|
316
|
+
approve: "approve";
|
|
317
|
+
question: "question";
|
|
306
318
|
bug: "bug";
|
|
307
319
|
note: "note";
|
|
308
320
|
}>>;
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export const AGENT_NAME = /^[a-z][a-z0-9_-]{0,31}$/;
|
|
3
3
|
export const Agent = z.string().regex(AGENT_NAME);
|
|
4
|
+
export const INTENTS = ["explain", "change", "approve"];
|
|
5
|
+
export const LEGACY_INTENTS = ["question", "bug", "note"];
|
|
4
6
|
const Box = z.object({ x: z.number(), y: z.number(), w: z.number(), h: z.number() });
|
|
5
7
|
export const Annotation = z.object({
|
|
6
8
|
id: z.string().regex(/^A\d+$/),
|
|
7
9
|
// v1 kinds only; "region" | "draw" are reserved for later tools.
|
|
8
10
|
kind: z.enum(["text", "element"]),
|
|
9
11
|
comment: z.string(),
|
|
10
|
-
intent: z.enum([
|
|
12
|
+
intent: z.enum([...INTENTS, ...LEGACY_INTENTS]).optional(),
|
|
11
13
|
anchor: z.object({
|
|
12
14
|
quote: z.object({ exact: z.string(), prefix: z.string(), suffix: z.string() }).optional(),
|
|
13
15
|
position: z.object({ start: z.number().int(), end: z.number().int() }).optional(),
|
|
@@ -68,9 +70,9 @@ export const Session = z.object({
|
|
|
68
70
|
pane: z.string().optional(),
|
|
69
71
|
sessionIds: z.array(z.string()).optional(),
|
|
70
72
|
});
|
|
71
|
-
// Protocol
|
|
73
|
+
// Protocol v2. Additive changes (optional fields, new endpoints) keep the version; removals, renames and
|
|
72
74
|
// semantic changes bump PROTOCOL_VERSION, and the bridge keeps accepting the previous version for a release.
|
|
73
|
-
export const PROTOCOL_VERSION =
|
|
75
|
+
export const PROTOCOL_VERSION = 2;
|
|
74
76
|
export const PROTOCOL_MIN = 1;
|
|
75
77
|
export const HealthResponse = z.object({
|
|
76
78
|
ok: z.literal(true),
|
package/package.json
CHANGED
package/src/fixtures.ts
CHANGED
|
@@ -16,7 +16,7 @@ export const exampleBundleInput: BundleInput = {
|
|
|
16
16
|
target: { agent: "claude", sessionId: "s-1", cwd: "/tmp/repo" },
|
|
17
17
|
overall: "can we make this vegan?",
|
|
18
18
|
annotations: [{
|
|
19
|
-
id: "A1", kind: "text", comment: "is there a substitute for cream?", intent: "
|
|
19
|
+
id: "A1", kind: "text", comment: "is there a substitute for cream?", intent: "explain",
|
|
20
20
|
anchor: {
|
|
21
21
|
quote: { exact: "200 ml cream", prefix: "stir in ", suffix: " before serving" },
|
|
22
22
|
css: "section#ingredients > li:nth-child(3)", path: ["main", "section#ingredients", "ul"], near: "Ingredients",
|
|
@@ -49,7 +49,7 @@ export type Exchange = {
|
|
|
49
49
|
response: { schema: SchemaName; example: unknown };
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
const health = { ok: true, bridgeVersion: "0.
|
|
52
|
+
const health = { ok: true, bridgeVersion: "0.3.0", protocol: { version: 2, min: 1 } };
|
|
53
53
|
const queued = { state: "queued", at: "2026-09-24T15:32:01.000Z" };
|
|
54
54
|
const exampleBundle = { ...exampleBundleInput, id: EXAMPLE_BUNDLE_ID, files: { page: "page.md", screenshot: "screenshot.png" } };
|
|
55
55
|
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,11 @@ export const AGENT_NAME = /^[a-z][a-z0-9_-]{0,31}$/;
|
|
|
4
4
|
export const Agent = z.string().regex(AGENT_NAME);
|
|
5
5
|
export type Agent = z.infer<typeof Agent>;
|
|
6
6
|
|
|
7
|
+
export const INTENTS = ["explain", "change", "approve"] as const;
|
|
8
|
+
export const LEGACY_INTENTS = ["question", "bug", "note"] as const;
|
|
9
|
+
/** The intent clients should send; parsed annotations may also hold a LEGACY_INTENTS value. */
|
|
10
|
+
export type Intent = (typeof INTENTS)[number];
|
|
11
|
+
|
|
7
12
|
const Box = z.object({ x: z.number(), y: z.number(), w: z.number(), h: z.number() });
|
|
8
13
|
|
|
9
14
|
export const Annotation = z.object({
|
|
@@ -11,7 +16,7 @@ export const Annotation = z.object({
|
|
|
11
16
|
// v1 kinds only; "region" | "draw" are reserved for later tools.
|
|
12
17
|
kind: z.enum(["text", "element"]),
|
|
13
18
|
comment: z.string(),
|
|
14
|
-
intent: z.enum([
|
|
19
|
+
intent: z.enum([...INTENTS, ...LEGACY_INTENTS]).optional(),
|
|
15
20
|
anchor: z.object({
|
|
16
21
|
quote: z.object({ exact: z.string(), prefix: z.string(), suffix: z.string() }).optional(),
|
|
17
22
|
position: z.object({ start: z.number().int(), end: z.number().int() }).optional(),
|
|
@@ -87,9 +92,9 @@ export const Session = z.object({
|
|
|
87
92
|
});
|
|
88
93
|
export type Session = z.infer<typeof Session>;
|
|
89
94
|
|
|
90
|
-
// Protocol
|
|
95
|
+
// Protocol v2. Additive changes (optional fields, new endpoints) keep the version; removals, renames and
|
|
91
96
|
// semantic changes bump PROTOCOL_VERSION, and the bridge keeps accepting the previous version for a release.
|
|
92
|
-
export const PROTOCOL_VERSION =
|
|
97
|
+
export const PROTOCOL_VERSION = 2;
|
|
93
98
|
export const PROTOCOL_MIN = 1;
|
|
94
99
|
|
|
95
100
|
export const HealthResponse = z.object({
|