@isoplan/protocol 0.0.0-stage → 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/LICENSE +21 -0
- package/dist/facts.d.ts +383 -0
- package/dist/facts.js +129 -0
- package/dist/facts.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/messages.d.ts +975 -0
- package/dist/messages.js +263 -0
- package/dist/messages.js.map +1 -0
- package/dist/project-id.d.ts +12 -0
- package/dist/project-id.js +37 -0
- package/dist/project-id.js.map +1 -0
- package/package.json +31 -4
- package/README.md +0 -3
package/dist/messages.js
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { FactRemoveSchema, FactsSchema, FactUpsertSchema, SourceSchema } from "./facts.js";
|
|
3
|
+
/**
|
|
4
|
+
* The protocol version every message carries as `v`. Adding optional fields doesn't change it;
|
|
5
|
+
* changing what a field means, or removing one, does.
|
|
6
|
+
*/
|
|
7
|
+
export const PROTOCOL_VERSION = 1;
|
|
8
|
+
const Version = z.literal(PROTOCOL_VERSION);
|
|
9
|
+
const Seq = z.number().int().nonnegative();
|
|
10
|
+
export const ProjectSchema = z.object({
|
|
11
|
+
id: z.string().min(1),
|
|
12
|
+
name: z.string().min(1),
|
|
13
|
+
});
|
|
14
|
+
const Account = z.object({ id: z.string().min(1), name: z.string() });
|
|
15
|
+
const Machine = z.object({ name: z.string().min(1) });
|
|
16
|
+
/** Matches a request with its reply or refusal. */
|
|
17
|
+
const RequestId = z.string().min(1);
|
|
18
|
+
/** A handoff's id. It names the handoff's branch, `isoplan/handoff/<id>`, so it keeps to safe characters. */
|
|
19
|
+
const HandoffId = z
|
|
20
|
+
.string()
|
|
21
|
+
.max(64)
|
|
22
|
+
.regex(/^[a-z0-9][a-z0-9-]*$/, "lowercase letters, digits and dashes");
|
|
23
|
+
/**
|
|
24
|
+
* One repo a handoff pushed: its path in the session's folder (`.` for the folder itself), remote,
|
|
25
|
+
* branch and commit. A handoff drives git on the receiver's machine, so the path stays inside the
|
|
26
|
+
* folder and the remote can't name a transport helper such as `ext::`, which runs a command.
|
|
27
|
+
*/
|
|
28
|
+
export const HandoffRepoSchema = z.object({
|
|
29
|
+
path: z
|
|
30
|
+
.string()
|
|
31
|
+
.min(1)
|
|
32
|
+
.refine((path) => !/^([\\/]|[A-Za-z]:)/.test(path), "a path relative to the session's folder")
|
|
33
|
+
.refine((path) => !path.split(/[\\/]/).includes(".."), "a path inside the session's folder, with no `..`")
|
|
34
|
+
.refine((path) => !path.startsWith("-"), "a path that doesn't start with `-`, which git would read as an option"),
|
|
35
|
+
remote: z
|
|
36
|
+
.string()
|
|
37
|
+
.min(1)
|
|
38
|
+
.refine((remote) => !/^[A-Za-z0-9+.-]+::/.test(remote), "a remote with no transport helper (`<transport>::`)")
|
|
39
|
+
.refine((remote) => !remote.startsWith("-"), "a remote that doesn't start with `-`, which git would read as an option"),
|
|
40
|
+
branch: z.string().min(1),
|
|
41
|
+
commit: z.string().regex(/^([0-9a-f]{40}|[0-9a-f]{64})$/, "a full commit hash"),
|
|
42
|
+
});
|
|
43
|
+
/** What the receiver gets: the brief, and every repo pushed for it, each on the handoff's own branch. */
|
|
44
|
+
export const HandoffSchema = z
|
|
45
|
+
.object({
|
|
46
|
+
id: HandoffId,
|
|
47
|
+
brief: z.string().min(1),
|
|
48
|
+
repos: z.array(HandoffRepoSchema).min(1),
|
|
49
|
+
})
|
|
50
|
+
.superRefine((handoff, context) => {
|
|
51
|
+
handoff.repos.forEach((repo, i) => {
|
|
52
|
+
if (repo.branch !== `isoplan/handoff/${handoff.id}`) {
|
|
53
|
+
context.addIssue({ code: "custom", path: ["repos", i, "branch"], message: `the handoff's branch, isoplan/handoff/${handoff.id}` });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
// Data layer → office server.
|
|
58
|
+
/** The first message on a connection: who is reporting, from where, about which session. */
|
|
59
|
+
export const HelloMessageSchema = z.object({
|
|
60
|
+
type: z.literal("hello"),
|
|
61
|
+
v: Version,
|
|
62
|
+
source: SourceSchema,
|
|
63
|
+
account: Account,
|
|
64
|
+
machine: Machine,
|
|
65
|
+
session: z.string().min(1),
|
|
66
|
+
project: ProjectSchema,
|
|
67
|
+
});
|
|
68
|
+
/** The first message on a runner's link: the one link per machine that answers requests for its rooms. */
|
|
69
|
+
export const RunnerHelloMessageSchema = z.object({
|
|
70
|
+
type: z.literal("runner"),
|
|
71
|
+
v: Version,
|
|
72
|
+
account: Account,
|
|
73
|
+
machine: Machine,
|
|
74
|
+
});
|
|
75
|
+
/** All of the session's facts. Sent on connect and on repair. */
|
|
76
|
+
export const FullMessageSchema = z.object({
|
|
77
|
+
type: z.literal("full"),
|
|
78
|
+
v: Version,
|
|
79
|
+
seq: Seq,
|
|
80
|
+
facts: FactsSchema,
|
|
81
|
+
});
|
|
82
|
+
/** What changed since the last message. `seq` goes up by one per message, so a gap shows. */
|
|
83
|
+
export const ChangesMessageSchema = z.object({
|
|
84
|
+
type: z.literal("changes"),
|
|
85
|
+
v: Version,
|
|
86
|
+
seq: Seq,
|
|
87
|
+
upsert: FactUpsertSchema,
|
|
88
|
+
remove: FactRemoveSchema,
|
|
89
|
+
});
|
|
90
|
+
/** The answer to a request, carrying the request's id and kind. */
|
|
91
|
+
export const ReplyMessageSchema = z.discriminatedUnion("kind", [
|
|
92
|
+
z.object({ type: z.literal("reply"), v: Version, id: RequestId, kind: z.literal("answer-question"), answer: z.string().min(1) }),
|
|
93
|
+
z.object({ type: z.literal("reply"), v: Version, id: RequestId, kind: z.literal("write-brief"), handoff: HandoffSchema }),
|
|
94
|
+
// The owner's answer reached the question that was waiting for it.
|
|
95
|
+
z.object({ type: z.literal("reply"), v: Version, id: RequestId, kind: z.literal("owner-answer") }),
|
|
96
|
+
]);
|
|
97
|
+
/**
|
|
98
|
+
* A request the machine won't answer, sent in place of its reply. `over-cap` names the cap it would
|
|
99
|
+
* go over. `withheld` means the secret scan matched; the reply follows if the owner releases it.
|
|
100
|
+
* `unavailable` is anything else that stops the room answering now, such as its checkout being gone,
|
|
101
|
+
* its lead being mid-turn or a push being rejected.
|
|
102
|
+
*/
|
|
103
|
+
export const RefusalMessageSchema = z.discriminatedUnion("reason", [
|
|
104
|
+
z.object({
|
|
105
|
+
type: z.literal("refusal"),
|
|
106
|
+
v: Version,
|
|
107
|
+
id: RequestId,
|
|
108
|
+
reason: z.literal("over-cap"),
|
|
109
|
+
cap: z.enum(["room-hour", "owner-day", "owner-tokens"]),
|
|
110
|
+
}),
|
|
111
|
+
z.object({ type: z.literal("refusal"), v: Version, id: RequestId, reason: z.literal("withheld") }),
|
|
112
|
+
z.object({ type: z.literal("refusal"), v: Version, id: RequestId, reason: z.literal("unavailable"), detail: z.string().min(1) }),
|
|
113
|
+
]);
|
|
114
|
+
/**
|
|
115
|
+
* The sender's session handed its room over with the command: its agent wrote the brief and pushed.
|
|
116
|
+
* `to` is the receiver as the sender named them, for the server to find in the office.
|
|
117
|
+
*/
|
|
118
|
+
export const HandOverMessageSchema = z.object({
|
|
119
|
+
type: z.literal("hand-over"),
|
|
120
|
+
v: Version,
|
|
121
|
+
to: z.string().min(1),
|
|
122
|
+
handoff: HandoffSchema,
|
|
123
|
+
});
|
|
124
|
+
/** The receiver's session asks for the handoff a take code stands for. */
|
|
125
|
+
export const TakeMessageSchema = z.object({
|
|
126
|
+
type: z.literal("take"),
|
|
127
|
+
v: Version,
|
|
128
|
+
code: z.string().min(1),
|
|
129
|
+
});
|
|
130
|
+
/**
|
|
131
|
+
* The receiver took the handoff and joins its room. Each step that failed is listed with the repo it
|
|
132
|
+
* was for and the end of its output; the session opens anyway.
|
|
133
|
+
*/
|
|
134
|
+
export const TakenMessageSchema = z.object({
|
|
135
|
+
type: z.literal("taken"),
|
|
136
|
+
v: Version,
|
|
137
|
+
handoff: HandoffId,
|
|
138
|
+
failures: z.array(z.object({
|
|
139
|
+
step: z.enum(["worktree", "setup", "checkout", "open"]),
|
|
140
|
+
repo: z.string().min(1).optional(),
|
|
141
|
+
output: z.string(),
|
|
142
|
+
})),
|
|
143
|
+
});
|
|
144
|
+
export const DataLayerMessageSchema = z.discriminatedUnion("type", [
|
|
145
|
+
HelloMessageSchema,
|
|
146
|
+
RunnerHelloMessageSchema,
|
|
147
|
+
FullMessageSchema,
|
|
148
|
+
ChangesMessageSchema,
|
|
149
|
+
ReplyMessageSchema,
|
|
150
|
+
RefusalMessageSchema,
|
|
151
|
+
HandOverMessageSchema,
|
|
152
|
+
TakeMessageSchema,
|
|
153
|
+
TakenMessageSchema,
|
|
154
|
+
]);
|
|
155
|
+
// Office server → data layer.
|
|
156
|
+
/** Asks the data layer to send its facts in full. */
|
|
157
|
+
export const RepairMessageSchema = z.object({
|
|
158
|
+
type: z.literal("repair"),
|
|
159
|
+
v: Version,
|
|
160
|
+
reason: z.string().optional(),
|
|
161
|
+
});
|
|
162
|
+
/** A note for the later editor of `file`, which the data layer adds to `agent`'s next tool result. */
|
|
163
|
+
export const ConflictMessageSchema = z.object({
|
|
164
|
+
type: z.literal("conflict"),
|
|
165
|
+
v: Version,
|
|
166
|
+
agent: z.string().min(1),
|
|
167
|
+
file: z.string().min(1),
|
|
168
|
+
text: z.string().min(1),
|
|
169
|
+
});
|
|
170
|
+
/** Something the data layer should show. */
|
|
171
|
+
export const ErrorMessageSchema = z.object({
|
|
172
|
+
type: z.literal("error"),
|
|
173
|
+
v: Version,
|
|
174
|
+
code: z.string().min(1),
|
|
175
|
+
message: z.string(),
|
|
176
|
+
});
|
|
177
|
+
/**
|
|
178
|
+
* Something for the machine to answer, with a reply or a refusal carrying the same id. `session` is
|
|
179
|
+
* the session it concerns: the lead whose fork answers or writes the brief, or the session whose
|
|
180
|
+
* agent asked its owner. `room` is the room the caps count against.
|
|
181
|
+
*/
|
|
182
|
+
export const RequestMessageSchema = z.discriminatedUnion("kind", [
|
|
183
|
+
// Someone the room was handed to asks it a question.
|
|
184
|
+
z.object({
|
|
185
|
+
type: z.literal("request"),
|
|
186
|
+
v: Version,
|
|
187
|
+
id: RequestId,
|
|
188
|
+
kind: z.literal("answer-question"),
|
|
189
|
+
session: z.string().min(1),
|
|
190
|
+
room: z.string().min(1),
|
|
191
|
+
from: Account,
|
|
192
|
+
question: z.string().min(1),
|
|
193
|
+
}),
|
|
194
|
+
// The sender handed the room over from the floor: write the brief and push, for this handoff.
|
|
195
|
+
z.object({
|
|
196
|
+
type: z.literal("request"),
|
|
197
|
+
v: Version,
|
|
198
|
+
id: RequestId,
|
|
199
|
+
kind: z.literal("write-brief"),
|
|
200
|
+
session: z.string().min(1),
|
|
201
|
+
room: z.string().min(1),
|
|
202
|
+
handoff: HandoffId,
|
|
203
|
+
to: Account,
|
|
204
|
+
}),
|
|
205
|
+
// The owner answered their agent's question from the floor. `question` is the question fact's id,
|
|
206
|
+
// and `answers` maps each question's text to its answer.
|
|
207
|
+
z.object({
|
|
208
|
+
type: z.literal("request"),
|
|
209
|
+
v: Version,
|
|
210
|
+
id: RequestId,
|
|
211
|
+
kind: z.literal("owner-answer"),
|
|
212
|
+
session: z.string().min(1),
|
|
213
|
+
question: z.string().min(1),
|
|
214
|
+
answers: z.record(z.string(), z.string()),
|
|
215
|
+
}),
|
|
216
|
+
]);
|
|
217
|
+
/** The owner released a reply the secret scan withheld, so the machine sends it now. */
|
|
218
|
+
export const ReleaseMessageSchema = z.object({
|
|
219
|
+
type: z.literal("release"),
|
|
220
|
+
v: Version,
|
|
221
|
+
id: RequestId,
|
|
222
|
+
});
|
|
223
|
+
/**
|
|
224
|
+
* A handoff for the receiver to take: sent to their runner when they take it from the floor, or to
|
|
225
|
+
* their session in answer to a take code.
|
|
226
|
+
*/
|
|
227
|
+
export const HandoffMessageSchema = z.object({
|
|
228
|
+
type: z.literal("handoff"),
|
|
229
|
+
v: Version,
|
|
230
|
+
handoff: HandoffSchema,
|
|
231
|
+
});
|
|
232
|
+
export const OfficeServerMessageSchema = z.discriminatedUnion("type", [
|
|
233
|
+
RepairMessageSchema,
|
|
234
|
+
ConflictMessageSchema,
|
|
235
|
+
ErrorMessageSchema,
|
|
236
|
+
RequestMessageSchema,
|
|
237
|
+
ReleaseMessageSchema,
|
|
238
|
+
HandoffMessageSchema,
|
|
239
|
+
]);
|
|
240
|
+
/** Validates a message an office server received from a data layer. */
|
|
241
|
+
export function parseDataLayerMessage(value) {
|
|
242
|
+
return parse(DataLayerMessageSchema, value);
|
|
243
|
+
}
|
|
244
|
+
/** Validates a message a data layer received from an office server. */
|
|
245
|
+
export function parseOfficeServerMessage(value) {
|
|
246
|
+
return parse(OfficeServerMessageSchema, value);
|
|
247
|
+
}
|
|
248
|
+
function parse(schema, value) {
|
|
249
|
+
// The version is checked first, so a newer peer is told so rather than given a field-by-field
|
|
250
|
+
// list of what changed.
|
|
251
|
+
if (typeof value === "object" && value !== null && "v" in value && typeof value.v === "number" && value.v !== PROTOCOL_VERSION) {
|
|
252
|
+
return {
|
|
253
|
+
ok: false,
|
|
254
|
+
kind: "unsupported-version",
|
|
255
|
+
error: `protocol version ${JSON.stringify(value.v)} is not supported; this side speaks version ${PROTOCOL_VERSION}`,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
const result = schema.safeParse(value);
|
|
259
|
+
if (result.success)
|
|
260
|
+
return { ok: true, message: result.data };
|
|
261
|
+
return { ok: false, kind: "invalid", error: z.prettifyError(result.error) };
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Project } from "./messages.js";
|
|
2
|
+
/**
|
|
3
|
+
* A project's id and name. With a git remote the id is `host/owner/repo` (any deeper path kept, as
|
|
4
|
+
* for GitLab subgroups), the same whichever form or letter case the remote is written in, so a
|
|
5
|
+
* repository cloned on several machines is one project. A repo with no remote, a remote that is a
|
|
6
|
+
* local path, or one that can't be read is `local:<machine>/<root>`, its working tree's root path.
|
|
7
|
+
* Never throws, so a remote's credentials never reach an error message.
|
|
8
|
+
*/
|
|
9
|
+
export declare function projectId(remoteUrl: string | null, local: {
|
|
10
|
+
machine: string;
|
|
11
|
+
root: string;
|
|
12
|
+
}): Project;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A project's id and name. With a git remote the id is `host/owner/repo` (any deeper path kept, as
|
|
3
|
+
* for GitLab subgroups), the same whichever form or letter case the remote is written in, so a
|
|
4
|
+
* repository cloned on several machines is one project. A repo with no remote, a remote that is a
|
|
5
|
+
* local path, or one that can't be read is `local:<machine>/<root>`, its working tree's root path.
|
|
6
|
+
* Never throws, so a remote's credentials never reach an error message.
|
|
7
|
+
*/
|
|
8
|
+
export function projectId(remoteUrl, local) {
|
|
9
|
+
const remote = remoteUrl === null || isLocalPath(remoteUrl.trim()) ? null : splitRemote(remoteUrl.trim());
|
|
10
|
+
const segments = remote?.path
|
|
11
|
+
.replace(/\/+$/, "")
|
|
12
|
+
.replace(/\.git$/, "")
|
|
13
|
+
.split("/")
|
|
14
|
+
.filter(Boolean);
|
|
15
|
+
if (!remote || !segments || segments.length === 0) {
|
|
16
|
+
const root = local.root.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
17
|
+
return { id: `local:${local.machine}/${root}`, name: root.split("/").pop() || root };
|
|
18
|
+
}
|
|
19
|
+
// Hosts and the big forges treat owner and repo names case-insensitively.
|
|
20
|
+
return { id: [remote.host, ...segments].join("/").toLowerCase(), name: segments[segments.length - 1] };
|
|
21
|
+
}
|
|
22
|
+
// An empty remote, a path (`/srv/x.git`, `./x`, `~/x`, `C:\x`, `\\server\x`) or a `file:` URL.
|
|
23
|
+
function isLocalPath(remote) {
|
|
24
|
+
return remote === "" || /^(?:[/.~\\]|[A-Za-z]:[\\/]|file:)/.test(remote);
|
|
25
|
+
}
|
|
26
|
+
// `scheme://[user[:password]@]host[:port]/path`, or scp-like `[user@]host:path`; null when neither.
|
|
27
|
+
function splitRemote(remote) {
|
|
28
|
+
if (remote.includes("://")) {
|
|
29
|
+
if (!URL.canParse(remote))
|
|
30
|
+
return null;
|
|
31
|
+
const url = new URL(remote);
|
|
32
|
+
return url.hostname ? { host: url.hostname, path: url.pathname } : null;
|
|
33
|
+
}
|
|
34
|
+
const scp = /^(?:[^@/]+@)?([^:/]+):(.+)$/.exec(remote);
|
|
35
|
+
return scp ? { host: scp[1], path: scp[2] } : null;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=project-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-id.js","sourceRoot":"","sources":["../src/project-id.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,SAAwB,EAAE,KAAwC;IAC1F,MAAM,MAAM,GAAG,SAAS,KAAK,IAAI,IAAI,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1G,MAAM,QAAQ,GAAG,MAAM,EAAE,IAAI;SAC1B,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;SACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAChE,OAAO,EAAE,EAAE,EAAE,SAAS,KAAK,CAAC,OAAO,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,EAAE,CAAC;IACvF,CAAC;IACD,0EAA0E;IAC1E,OAAO,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAE,EAAE,CAAC;AAC1G,CAAC;AAED,+FAA+F;AAC/F,SAAS,WAAW,CAAC,MAAc;IACjC,OAAO,MAAM,KAAK,EAAE,IAAI,mCAAmC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED,oGAAoG;AACpG,SAAS,WAAW,CAAC,MAAc;IACjC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;QACvC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5B,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,CAAC;IACD,MAAM,GAAG,GAAG,6BAA6B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvD,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@isoplan/protocol",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "The wire protocol between Isoplan's Claude Code plugin and an office server: message and fact types, with zod parsers.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/adamlinscott/isoplan-plugin.git",
|
|
9
|
+
"directory": "packages/protocol"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -p tsconfig.build.json",
|
|
26
|
+
"typecheck": "tsc --noEmit",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"prepublishOnly": "tsc -p tsconfig.build.json"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"zod": "^4.6.7"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/README.md
DELETED