@loopbacktools/protocol 0.0.0-stage → 0.4.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/README.md +14 -2
- package/dist/openapi/openapi.1.json +1903 -0
- package/dist/src/briefing.d.ts +80 -0
- package/dist/src/briefing.js +219 -0
- package/dist/src/generated/document.gen.d.ts +3256 -0
- package/dist/src/generated/document.gen.js +25 -0
- package/dist/src/generated/requests.gen.d.ts +480 -0
- package/dist/src/generated/requests.gen.js +1 -0
- package/dist/src/generated/schemas.gen.d.ts +5 -0
- package/dist/src/generated/schemas.gen.js +6 -0
- package/dist/src/generated/schemas.r1.gen.d.ts +5433 -0
- package/dist/src/generated/schemas.r1.gen.js +58 -0
- package/dist/src/generated/vocabularies.gen.d.ts +11 -0
- package/dist/src/generated/vocabularies.gen.js +13 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +4 -0
- package/dist/src/schema.d.ts +9 -0
- package/dist/src/schema.js +8 -0
- package/dist/src/unknown.d.ts +94 -0
- package/dist/src/unknown.js +59 -0
- package/dist/src/versions.d.ts +11 -0
- package/dist/src/versions.js +11 -0
- package/openapi/openapi.1.json +1903 -0
- package/package.json +61 -3
- package/spec/main.tsp +660 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// GENERATED by scripts/schemas.ts from openapi/openapi.1.json. DO NOT EDIT.
|
|
2
|
+
// Regenerate with: pnpm generate
|
|
3
|
+
import * as Schema from "effect/Schema";
|
|
4
|
+
import { unknownAsk, unknownBlock, unknownEvent, unknownReply, } from "../unknown.js";
|
|
5
|
+
export const Actor = Schema.Struct({ "id": Schema.String.annotate({ "description": "Stable within the deployment, as its gate names them." }), "name": Schema.optionalKey(Schema.String.annotate({ "description": "How to show them, when the gate knows." })) }).annotate({ "description": "Someone a deployment's gate recognised: a person, or the agent they authorised.", "identifier": "Actor" });
|
|
6
|
+
export const MarkdownBlock = Schema.Struct({ "type": Schema.Literal("markdown"), "text": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) }).annotate({ "description": "Prose, copy or a plan, as GitHub-flavoured markdown.", "identifier": "MarkdownBlock" });
|
|
7
|
+
export const CodeBlock = Schema.Struct({ "type": Schema.Literal("code"), "code": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "language": Schema.optionalKey(Schema.String.annotate({ "description": "A language name the highlighter knows, such as `ts` or `python`." })), "filename": Schema.optionalKey(Schema.String) }).annotate({ "description": "Source code, shown highlighted.", "identifier": "CodeBlock" });
|
|
8
|
+
export const DiffBlock = Schema.Struct({ "type": Schema.Literal("diff"), "diff": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "filename": Schema.optionalKey(Schema.String) }).annotate({ "description": "A unified diff, as `git diff` prints it.", "identifier": "DiffBlock" });
|
|
9
|
+
export const ImageBlock = Schema.Struct({ "type": Schema.Literal("image"), "uploadId": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "caption": Schema.optionalKey(Schema.String) }).annotate({ "description": "An image uploaded beforehand through an upload ticket.", "identifier": "ImageBlock" });
|
|
10
|
+
export const Answered = Schema.Struct({ "outcome": Schema.Literal("answered"), "selected": Schema.Array(Schema.String), "text": Schema.optionalKey(Schema.String) }).annotate({ "description": "An answer to a question: the choices picked, words of their own, or both.", "identifier": "Answered" });
|
|
11
|
+
export const Approved = Schema.Struct({ "outcome": Schema.Literal("approved"), "note": Schema.optionalKey(Schema.String) }).annotate({ "description": "A review approved, with an optional note.", "identifier": "Approved" });
|
|
12
|
+
export const Choice = Schema.Struct({ "label": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxCodePoints(80).annotate({ "expected": "a string with at most 80 code points" })), "description": Schema.optionalKey(Schema.String) }).annotate({ "description": "A choice offered with a question.", "identifier": "Choice" });
|
|
13
|
+
export const AskStatus = Schema.Literals(["awaiting_human", "awaiting_agent", "closed"]).annotate({ "description": "Where an ask stands. While it is open, it is either the person's move or the agent's.", "identifier": "AskStatus" });
|
|
14
|
+
export const ChangesRequested = Schema.Struct({ "outcome": Schema.Literal("changes_requested"), "feedback": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) }).annotate({ "description": "A review sent back with feedback.", "identifier": "ChangesRequested" });
|
|
15
|
+
export const FollowUp = Schema.Struct({ "outcome": Schema.Literal("follow_up"), "question": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) }).annotate({ "description": "A question asked back before deciding. The ask stays open until the agent answers.", "identifier": "FollowUp" });
|
|
16
|
+
export const Dismissed = Schema.Struct({ "outcome": Schema.Literal("dismissed") }).annotate({ "description": "Declined without an answer.", "identifier": "Dismissed" });
|
|
17
|
+
export const PointReply = Schema.Struct({ "point": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "text": Schema.optionalKey(Schema.String.annotate({ "description": "What they said: a question, a push-back or a comment." })), "resolved": Schema.optionalKey(Schema.Boolean.annotate({ "description": "Whether they are done with the point, and everything beneath it." })) }).annotate({ "description": "The person on one point of a briefing: words, resolved, or both.", "identifier": "PointReply" });
|
|
18
|
+
export const AskKind = Schema.Literals(["question", "review", "briefing"]).annotate({ "description": "What an agent is asking for: an answer to a question, a verdict on something it produced, or the\nperson's word on each point of something it explained.", "identifier": "AskKind" });
|
|
19
|
+
export const EventTicket = Schema.Struct({ "ticket": Schema.String, "expiresAt": Schema.String.annotate({ "format": "date-time" }) }).annotate({ "description": "A one-time pass onto the event socket, for a client that cannot send headers there, as a browser\ncannot. Offer it as the subprotocol `loopback.ticket.<ticket>` alongside `loopback.v1`. It works\nonce, within a minute, so a copy that turns up in a log is of no use to anyone.", "identifier": "EventTicket" });
|
|
20
|
+
export const ImageType = Schema.Literals(["image/png", "image/jpeg", "image/webp", "image/gif"]).annotate({ "description": "Image formats an agent may upload for a review.", "identifier": "ImageType" });
|
|
21
|
+
export const InboxLink = Schema.Struct({ "url": Schema.String }).annotate({ "description": "Where the person reads and answers everything agents ask.", "identifier": "InboxLink" });
|
|
22
|
+
export const InboxRequest = Schema.Struct({ "askId": Schema.optionalKey(Schema.String.annotate({ "description": "An ask to open directly. Leave it out for the inbox itself." })) }).annotate({ "description": "A request for the address of the person's inbox.", "identifier": "InboxRequest" });
|
|
23
|
+
export const Problem = Schema.Struct({ "code": Schema.String.annotate({ "description": "A stable, machine-readable reason, such as `ask.closed`." }), "message": Schema.String }).annotate({ "description": "Why a request was refused.", "identifier": "Problem" });
|
|
24
|
+
export const Revisions = Schema.Literal("1").annotate({ "description": "The contract's revisions, oldest first. Change the shape of any message and declare it here as a\nnew revision, marking what changed with `@added`, `@removed`, `@renamedFrom` or `@typeChangedFrom`:\nevery part of a deployment names the revision it writes, and newer code upgrades older messages.\nNever edit a revision that has shipped; `revisions/` holds each one frozen, and a test fails when\nthe contract no longer emits it unchanged. See docs/design/versioned-messages.md.", "identifier": "Revisions" });
|
|
25
|
+
export const UploadTicket = Schema.Struct({ "uploadId": Schema.String, "uploadUrl": Schema.String.annotate({ "description": "Send the image here with `PUT` and its `Content-Type`. No credentials needed." }), "expiresAt": Schema.String.annotate({ "format": "date-time" }), "maxBytes": Schema.Number.annotate({ "format": "int32" }).check(Schema.isInt().annotate({ "expected": "an integer" })), "command": Schema.String.annotate({ "description": "A ready-to-run command that performs the upload; replace `FILE` with the image's path." }) }).annotate({ "description": "Where to upload an image, once, before it expires.", "identifier": "UploadTicket" });
|
|
26
|
+
export const Whoami = Schema.Struct({ "space": Schema.String, "actor": Actor }).annotate({ "description": "Who the caller is.", "identifier": "Whoami" });
|
|
27
|
+
export const Block = Schema.Union([MarkdownBlock, CodeBlock, DiffBlock, ImageBlock, unknownBlock]).annotate({ "description": "One piece of what is shown to the person.", "identifier": "Block" });
|
|
28
|
+
export const QuestionPrompt = Schema.Struct({ "question": Schema.String, "options": Schema.Array(Choice), "multiple": Schema.Boolean, "context": Schema.optionalKey(Schema.String) }).annotate({ "description": "A question as it is shown to the person.", "identifier": "QuestionPrompt" });
|
|
29
|
+
export const QuestionInput = Schema.Struct({ "question": Schema.String.annotate({ "description": "The question, as markdown." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "options": Schema.optionalKey(Schema.Array(Choice).annotate({ "description": "Between two and six choices, offered as buttons." }).check(Schema.isMinLength(2).annotate({ "expected": "a value with a length of at least 2" })).check(Schema.isMaxLength(6).annotate({ "expected": "a value with a length of at most 6" }))), "multiple": Schema.optionalKey(Schema.Boolean.annotate({ "description": "Whether the person may pick more than one choice." })), "context": Schema.optionalKey(Schema.String.annotate({ "description": "Background the person needs to answer, as markdown." })), "project": Schema.String.annotate({ "description": "The project you are working in: the name of the folder at the root of its repository (the\nlast part of `git rev-parse --show-toplevel`), or of the working directory outside one. The\nperson works on many projects at once from one inbox; this is how they know who is asking." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) }).annotate({ "description": "A question for the person, with optional choices. They may always answer in their own words. All\nof it together may be at most 256 KiB.", "identifier": "QuestionInput" });
|
|
30
|
+
export const Responded = Schema.Struct({ "outcome": Schema.Literal("responded"), "points": Schema.Array(PointReply).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) }).annotate({ "description": "Replies on the points of a briefing. The agent answers every point written on and left unresolved;\nthe briefing closes once every point is resolved.", "identifier": "Responded" });
|
|
31
|
+
export const UploadReceipt = Schema.Struct({ "uploadId": Schema.String, "contentType": ImageType, "size": Schema.Number.annotate({ "format": "int32" }).check(Schema.isInt().annotate({ "expected": "an integer" })) }).annotate({ "description": "A stored upload.", "identifier": "UploadReceipt" });
|
|
32
|
+
export const UploadRequest = Schema.Struct({ "contentType": ImageType }).annotate({ "description": "A request for somewhere to upload an image.", "identifier": "UploadRequest" });
|
|
33
|
+
export const Point = Schema.Struct({ "id": Schema.String.annotate({ "description": "`3` for the third point of the briefing, `3.1` for the first beneath it." }), "title": Schema.String.annotate({ "description": "The point in one line, shown while it is folded." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxCodePoints(200).annotate({ "expected": "a string with at most 200 code points" })), "detail": Schema.optionalKey(Schema.String.annotate({ "description": "The point explained, as markdown, shown when the person opens it." })), "content": Schema.optionalKey(Schema.Array(Block).annotate({ "description": "Anything to look at with it: code, a diff or an image." })) }).annotate({ "description": "A point of a briefing as it is shown, with the id replies name it by.", "identifier": "Point" });
|
|
34
|
+
export const ReviewPrompt = Schema.Struct({ "title": Schema.String, "content": Schema.Array(Block), "summary": Schema.optionalKey(Schema.String) }).annotate({ "description": "A review as it is shown to the person.", "identifier": "ReviewPrompt" });
|
|
35
|
+
export const BriefingPoint = Schema.Struct({ "title": Schema.String.annotate({ "description": "The point in one line, shown while it is folded." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxCodePoints(200).annotate({ "expected": "a string with at most 200 code points" })), "detail": Schema.optionalKey(Schema.String.annotate({ "description": "The point explained, as markdown, shown when the person opens it." })), "content": Schema.optionalKey(Schema.Array(Block).annotate({ "description": "Anything to look at with it: code, a diff or an image." })) }).annotate({ "description": "One point of a briefing: a line the person sees folded, and what opens beneath it.", "identifier": "BriefingPoint" });
|
|
36
|
+
export const FollowUpInput = Schema.Struct({ "askId": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "answer": Schema.String.annotate({ "description": "The answer, as markdown." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "content": Schema.optionalKey(Schema.Array(Block).annotate({ "description": "Anything new to look at alongside the answer." })) }).annotate({ "description": "The agent's answer to a question the person asked back, with its content at most 256 KiB.", "identifier": "FollowUpInput" });
|
|
37
|
+
export const ReviewInput = Schema.Struct({ "title": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxCodePoints(200).annotate({ "expected": "a string with at most 200 code points" })), "content": Schema.Array(Block).annotate({ "description": "What is being reviewed, in order." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "summary": Schema.optionalKey(Schema.String.annotate({ "description": "What changed, or what to look at." })), "revises": Schema.optionalKey(Schema.String.annotate({ "description": "The id of the review this one revises, after changes were requested." })), "project": Schema.String.annotate({ "description": "The project you are working in: the name of the folder at the root of its repository (the\nlast part of `git rev-parse --show-toplevel`), or of the working directory outside one. The\nperson works on many projects at once from one inbox; this is how they know who is asking." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) }).annotate({ "description": "Work put in front of the person for approval or feedback. All of it together may be at most\n256 KiB: show the part that matters, or split it into several reviews.", "identifier": "ReviewInput" });
|
|
38
|
+
export const Reply = Schema.Union([Answered, Approved, ChangesRequested, FollowUp, Dismissed, Responded, unknownReply]).annotate({ "description": "What a person replies. A `follow_up` hands the move to the agent; so does a `responded` that\nleaves any point unresolved. Every other reply closes the ask.", "identifier": "Reply" });
|
|
39
|
+
export const AgentEntry = Schema.Struct({ "author": Schema.Literal("agent"), "answer": Schema.String, "content": Schema.optionalKey(Schema.Array(Block)), "point": Schema.optionalKey(Schema.String.annotate({ "description": "The briefing point this answers." })), "points": Schema.optionalKey(Schema.Array(Point).annotate({ "description": "Sub-points the answer broke the point into, with their ids." })), "at": Schema.String.annotate({ "format": "date-time" }) }).annotate({ "description": "An answer the agent gave: to a question asked back, or on one point of a briefing.", "identifier": "AgentEntry" });
|
|
40
|
+
export const BriefingPromptSection = Schema.Struct({ "title": Schema.optionalKey(Schema.String), "points": Schema.Array(Point) }).annotate({ "description": "A list of a briefing's points as it is shown.", "identifier": "BriefingPromptSection" });
|
|
41
|
+
export const PointAnswer = Schema.Struct({ "point": Schema.String.annotate({ "description": "The point's id, such as `3` or `3.1`." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "answer": Schema.String.annotate({ "description": "The answer, as markdown." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "content": Schema.optionalKey(Schema.Array(Block).annotate({ "description": "Anything new to look at alongside the answer." })), "points": Schema.optionalKey(Schema.Array(BriefingPoint).annotate({ "description": "Sub-points this point breaks into, numbered beneath it (`3.1`, `3.2`, …), each of which the\nperson can reply on in turn. Points go at most three levels deep." })) }).annotate({ "description": "Your answer on one point of a briefing.", "identifier": "PointAnswer" });
|
|
42
|
+
export const BriefingSection = Schema.Struct({ "title": Schema.optionalKey(Schema.String), "points": Schema.Array(BriefingPoint).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) }).annotate({ "description": "A list of points under an optional heading.", "identifier": "BriefingSection" });
|
|
43
|
+
export const HumanEntry = Schema.Struct({ "author": Schema.Literal("human"), "reply": Reply, "by": Schema.optionalKey(Schema.suspend(() => Actor).annotate({ "description": "Who replied, when the deployment knows." })), "at": Schema.String.annotate({ "format": "date-time" }) }).annotate({ "description": "A reply the person gave.", "identifier": "HumanEntry" });
|
|
44
|
+
export const ToolReply = Schema.Struct({ "askId": Schema.String, "reply": Reply }).annotate({ "description": "What a blocking MCP tool returns: the reply that ended its wait.", "identifier": "ToolReply" });
|
|
45
|
+
export const BriefingPrompt = Schema.Struct({ "title": Schema.String, "summary": Schema.optionalKey(Schema.String), "sections": Schema.Array(BriefingPromptSection) }).annotate({ "description": "A briefing as it is shown to the person, before any sub-points the agent adds while answering.", "identifier": "BriefingPrompt" });
|
|
46
|
+
export const BriefingAnswerInput = Schema.Struct({ "askId": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "answers": Schema.Array(PointAnswer).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) }).annotate({ "description": "Your answers on a briefing, one per point: every point the person wrote on without resolving it,\nand any other open point you have more to say on. All of it together may be at most 256 KiB.", "identifier": "BriefingAnswerInput" });
|
|
47
|
+
export const BriefingInput = Schema.Struct({ "title": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxCodePoints(200).annotate({ "expected": "a string with at most 200 code points" })), "summary": Schema.optionalKey(Schema.String.annotate({ "description": "What this explains, and why, as markdown." })), "sections": Schema.Array(BriefingSection).annotate({ "description": "The points, in lists under optional headings." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "project": Schema.String.annotate({ "description": "The project you are working in: the name of the folder at the root of its repository (the\nlast part of `git rev-parse --show-toplevel`), or of the working directory outside one. The\nperson works on many projects at once from one inbox; this is how they know who is asking." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })) }).annotate({ "description": "Something explained as points the person can reply on one at a time: findings, options, steps, a\nlist of changes. They may write on any point, or mark it resolved, and you answer on each point\nthey wrote on until every point is resolved. Points are numbered for you, straight through every\nsection: at most fifty. All of it together may be at most 256 KiB.", "identifier": "BriefingInput" });
|
|
48
|
+
export const Entry = Schema.Union([HumanEntry, AgentEntry]).annotate({ "description": "One turn in an ask's thread after it was opened.", "identifier": "Entry" });
|
|
49
|
+
export const QuestionAsk = Schema.Struct({ "kind": Schema.Literal("question"), "prompt": QuestionPrompt, "id": Schema.String, "status": AskStatus, "waiting": Schema.Boolean.annotate({ "description": "Whether an agent is following this ask right now: waiting on its call, or polling it as a background task." }), "project": Schema.optionalKey(Schema.String), "client": Schema.optionalKey(Schema.String.annotate({ "description": "The MCP client that asked, such as `claude-code 2.1.0`." })), "raisedBy": Schema.optionalKey(Schema.suspend(() => Actor).annotate({ "description": "Whose agent asked: the person its credential belongs to, when the deployment knows." })), "thread": Schema.Array(Entry).annotate({ "description": "Every turn after the ask was opened, oldest first." }), "createdAt": Schema.String.annotate({ "format": "date-time" }), "updatedAt": Schema.String.annotate({ "format": "date-time" }), "closedAt": Schema.optionalKey(Schema.String.annotate({ "format": "date-time" })) }).annotate({ "description": "A question an agent asked.", "identifier": "QuestionAsk" });
|
|
50
|
+
export const ReviewAsk = Schema.Struct({ "kind": Schema.Literal("review"), "prompt": ReviewPrompt, "revises": Schema.optionalKey(Schema.String.annotate({ "description": "The id of the review this one revises." })), "id": Schema.String, "status": AskStatus, "waiting": Schema.Boolean.annotate({ "description": "Whether an agent is following this ask right now: waiting on its call, or polling it as a background task." }), "project": Schema.optionalKey(Schema.String), "client": Schema.optionalKey(Schema.String.annotate({ "description": "The MCP client that asked, such as `claude-code 2.1.0`." })), "raisedBy": Schema.optionalKey(Schema.suspend(() => Actor).annotate({ "description": "Whose agent asked: the person its credential belongs to, when the deployment knows." })), "thread": Schema.Array(Entry).annotate({ "description": "Every turn after the ask was opened, oldest first." }), "createdAt": Schema.String.annotate({ "format": "date-time" }), "updatedAt": Schema.String.annotate({ "format": "date-time" }), "closedAt": Schema.optionalKey(Schema.String.annotate({ "format": "date-time" })) }).annotate({ "description": "Work an agent put up for review.", "identifier": "ReviewAsk" });
|
|
51
|
+
export const BriefingAsk = Schema.Struct({ "kind": Schema.Literal("briefing"), "prompt": BriefingPrompt, "id": Schema.String, "status": AskStatus, "waiting": Schema.Boolean.annotate({ "description": "Whether an agent is following this ask right now: waiting on its call, or polling it as a background task." }), "project": Schema.optionalKey(Schema.String), "client": Schema.optionalKey(Schema.String.annotate({ "description": "The MCP client that asked, such as `claude-code 2.1.0`." })), "raisedBy": Schema.optionalKey(Schema.suspend(() => Actor).annotate({ "description": "Whose agent asked: the person its credential belongs to, when the deployment knows." })), "thread": Schema.Array(Entry).annotate({ "description": "Every turn after the ask was opened, oldest first." }), "createdAt": Schema.String.annotate({ "format": "date-time" }), "updatedAt": Schema.String.annotate({ "format": "date-time" }), "closedAt": Schema.optionalKey(Schema.String.annotate({ "format": "date-time" })) }).annotate({ "description": "Points an agent explained, for the person to reply on one at a time.", "identifier": "BriefingAsk" });
|
|
52
|
+
export const AskCommon = Schema.Struct({ "id": Schema.String, "status": AskStatus, "waiting": Schema.Boolean.annotate({ "description": "Whether an agent is following this ask right now: waiting on its call, or polling it as a background task." }), "project": Schema.optionalKey(Schema.String), "client": Schema.optionalKey(Schema.String.annotate({ "description": "The MCP client that asked, such as `claude-code 2.1.0`." })), "raisedBy": Schema.optionalKey(Schema.suspend(() => Actor).annotate({ "description": "Whose agent asked: the person its credential belongs to, when the deployment knows." })), "thread": Schema.Array(Entry).annotate({ "description": "Every turn after the ask was opened, oldest first." }), "createdAt": Schema.String.annotate({ "format": "date-time" }), "updatedAt": Schema.String.annotate({ "format": "date-time" }), "closedAt": Schema.optionalKey(Schema.String.annotate({ "format": "date-time" })) }).annotate({ "description": "What every ask carries, whatever its kind.", "identifier": "AskCommon" });
|
|
53
|
+
export const Ask = Schema.Union([QuestionAsk, ReviewAsk, BriefingAsk, unknownAsk(AskStatus)]).annotate({ "description": "Something an agent needs from a person: a short thread that ends with a reply.", "identifier": "Ask" });
|
|
54
|
+
export const AskEvent = Schema.Struct({ "type": Schema.Literals(["ask.opened", "ask.updated"]), "ask": Ask }).annotate({ "description": "An ask was opened, or changed: a new turn, a close, or an agent starting or stopping following it.", "identifier": "AskEvent" });
|
|
55
|
+
export const AskPage = Schema.Struct({ "items": Schema.Array(Ask), "nextBefore": Schema.optionalKey(Schema.String.annotate({ "description": "Pass as `before` for the next page. Absent on the last page.", "format": "date-time" })) }).annotate({ "description": "A page of closed asks, newest first.", "identifier": "AskPage" });
|
|
56
|
+
export const Snapshot = Schema.Struct({ "open": Schema.Array(Ask), "recent": Schema.Array(Ask) }).annotate({ "description": "Open asks, newest first, and the most recently closed.", "identifier": "Snapshot" });
|
|
57
|
+
export const SnapshotEvent = Schema.Struct({ "type": Schema.Literal("snapshot"), "snapshot": Snapshot }).annotate({ "description": "The first frame on the event socket, and the state to start from.", "identifier": "SnapshotEvent" });
|
|
58
|
+
export const ServerEvent = Schema.Union([SnapshotEvent, AskEvent, unknownEvent]).annotate({ "description": "A frame on the event socket.", "identifier": "ServerEvent" });
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The spec's vocabularies - every enum the surface reaches, and what each one contains.
|
|
3
|
+
*
|
|
4
|
+
* `as const` so each is a readonly tuple of literals - the type every consumer derives with
|
|
5
|
+
* `(typeof X)[number]` keeps working unchanged.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SPEC_VOCABULARIES: {
|
|
8
|
+
readonly AskKind: readonly ["question", "review", "briefing"];
|
|
9
|
+
readonly AskStatus: readonly ["awaiting_human", "awaiting_agent", "closed"];
|
|
10
|
+
readonly Revisions: readonly ["1"];
|
|
11
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// GENERATED by typespec-http-zod from the TypeSpec service definition. DO NOT EDIT.
|
|
2
|
+
// Regenerate with: pnpm generate
|
|
3
|
+
/**
|
|
4
|
+
* The spec's vocabularies - every enum the surface reaches, and what each one contains.
|
|
5
|
+
*
|
|
6
|
+
* `as const` so each is a readonly tuple of literals - the type every consumer derives with
|
|
7
|
+
* `(typeof X)[number]` keeps working unchanged.
|
|
8
|
+
*/
|
|
9
|
+
export const SPEC_VOCABULARIES = {
|
|
10
|
+
AskKind: ["question", "review", "briefing"],
|
|
11
|
+
AskStatus: ["awaiting_human", "awaiting_agent", "closed"],
|
|
12
|
+
Revisions: ["1"],
|
|
13
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract as a reader decodes it: Effect schemas for every message at the latest revision,
|
|
3
|
+
* generated from the spec. Each union a release can grow (kinds of ask, blocks of content, reply
|
|
4
|
+
* outcomes, socket frames) has an `unknown` member, so a reader that meets a message from a newer
|
|
5
|
+
* revision keeps what it can show instead of failing. Decode what you receive with these; never cast
|
|
6
|
+
* it. See docs/design/versioned-messages.md.
|
|
7
|
+
*/
|
|
8
|
+
export * from "./generated/schemas.gen.ts";
|
|
9
|
+
export type { UnknownAsk, UnknownBlock, UnknownEvent, UnknownReply } from "./unknown.ts";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract as a reader decodes it: Effect schemas for every message at the latest revision,
|
|
3
|
+
* generated from the spec. Each union a release can grow (kinds of ask, blocks of content, reply
|
|
4
|
+
* outcomes, socket frames) has an `unknown` member, so a reader that meets a message from a newer
|
|
5
|
+
* revision keeps what it can show instead of failing. Decode what you receive with these; never cast
|
|
6
|
+
* it. See docs/design/versioned-messages.md.
|
|
7
|
+
*/
|
|
8
|
+
export * from "./generated/schemas.gen.js";
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/**
|
|
3
|
+
* What a reader makes of a message it can't read: one of a kind, outcome or type it doesn't know, as
|
|
4
|
+
* it meets one from a newer revision of the contract. It keeps what it can still show and what the
|
|
5
|
+
* message said it was, so that one message is drawn as "can't be shown" instead of failing
|
|
6
|
+
* everything around it. The generated schemas end each union a release can grow with one of these
|
|
7
|
+
* (`scripts/schemas.ts`). See docs/design/versioned-messages.md.
|
|
8
|
+
*/
|
|
9
|
+
/** Who an unknown ask was raised by, read as leniently as the rest of it. */
|
|
10
|
+
interface UnknownActor {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly name?: string;
|
|
13
|
+
}
|
|
14
|
+
/** An ask of a kind this reader doesn't know, or that it can't otherwise read. */
|
|
15
|
+
export interface UnknownAsk<Status extends string = string> {
|
|
16
|
+
readonly kind: "unknown";
|
|
17
|
+
/** The kind it said it was. */
|
|
18
|
+
readonly was: string;
|
|
19
|
+
readonly id: string;
|
|
20
|
+
/** Its status, or `closed` when that is unknown too, so it never asks for attention it can't get. */
|
|
21
|
+
readonly status: Status;
|
|
22
|
+
readonly waiting: boolean;
|
|
23
|
+
readonly project?: string;
|
|
24
|
+
readonly client?: string;
|
|
25
|
+
readonly raisedBy?: UnknownActor;
|
|
26
|
+
readonly createdAt: string;
|
|
27
|
+
readonly updatedAt: string;
|
|
28
|
+
readonly closedAt?: string;
|
|
29
|
+
}
|
|
30
|
+
/** The union member for an ask this reader can't read, given the statuses it knows. */
|
|
31
|
+
export declare const unknownAsk: <Status extends string>(statuses: Schema.Codec<Status>) => Schema.decodeTo<Schema.Struct<{
|
|
32
|
+
readonly kind: Schema.Literal<"unknown">;
|
|
33
|
+
readonly was: Schema.String;
|
|
34
|
+
readonly id: Schema.String;
|
|
35
|
+
readonly status: Schema.Codec<Status, Status, never, never>;
|
|
36
|
+
readonly waiting: Schema.Boolean;
|
|
37
|
+
readonly project: Schema.optionalKey<Schema.String>;
|
|
38
|
+
readonly client: Schema.optionalKey<Schema.String>;
|
|
39
|
+
readonly raisedBy: Schema.optionalKey<Schema.Struct<{
|
|
40
|
+
readonly id: Schema.String;
|
|
41
|
+
readonly name: Schema.optionalKey<Schema.String>;
|
|
42
|
+
}>>;
|
|
43
|
+
readonly createdAt: Schema.String;
|
|
44
|
+
readonly updatedAt: Schema.String;
|
|
45
|
+
readonly closedAt: Schema.optionalKey<Schema.String>;
|
|
46
|
+
}>, Schema.Struct<{
|
|
47
|
+
readonly kind: Schema.String;
|
|
48
|
+
readonly id: Schema.String;
|
|
49
|
+
readonly status: Schema.String;
|
|
50
|
+
readonly waiting: Schema.optionalKey<Schema.Boolean>;
|
|
51
|
+
readonly project: Schema.optionalKey<Schema.String>;
|
|
52
|
+
readonly client: Schema.optionalKey<Schema.String>;
|
|
53
|
+
readonly raisedBy: Schema.optionalKey<Schema.Struct<{
|
|
54
|
+
readonly id: Schema.String;
|
|
55
|
+
readonly name: Schema.optionalKey<Schema.String>;
|
|
56
|
+
}>>;
|
|
57
|
+
readonly createdAt: Schema.String;
|
|
58
|
+
readonly updatedAt: Schema.String;
|
|
59
|
+
readonly closedAt: Schema.optionalKey<Schema.String>;
|
|
60
|
+
}>, never, never>;
|
|
61
|
+
/** A block of content of a type this reader doesn't know. */
|
|
62
|
+
export interface UnknownBlock {
|
|
63
|
+
readonly type: "unknown";
|
|
64
|
+
readonly was: string;
|
|
65
|
+
}
|
|
66
|
+
export declare const unknownBlock: Schema.decodeTo<Schema.Struct<{
|
|
67
|
+
readonly type: Schema.Literal<"unknown">;
|
|
68
|
+
readonly was: Schema.String;
|
|
69
|
+
}>, Schema.Struct<{
|
|
70
|
+
readonly type: Schema.String;
|
|
71
|
+
}>, never, never>;
|
|
72
|
+
/** A frame on the event socket of a type this reader doesn't know. Readers skip it. */
|
|
73
|
+
export interface UnknownEvent {
|
|
74
|
+
readonly type: "unknown";
|
|
75
|
+
readonly was: string;
|
|
76
|
+
}
|
|
77
|
+
export declare const unknownEvent: Schema.decodeTo<Schema.Struct<{
|
|
78
|
+
readonly type: Schema.Literal<"unknown">;
|
|
79
|
+
readonly was: Schema.String;
|
|
80
|
+
}>, Schema.Struct<{
|
|
81
|
+
readonly type: Schema.String;
|
|
82
|
+
}>, never, never>;
|
|
83
|
+
/** A reply with an outcome this reader doesn't know. */
|
|
84
|
+
export interface UnknownReply {
|
|
85
|
+
readonly outcome: "unknown";
|
|
86
|
+
readonly was: string;
|
|
87
|
+
}
|
|
88
|
+
export declare const unknownReply: Schema.decodeTo<Schema.Struct<{
|
|
89
|
+
readonly outcome: Schema.Literal<"unknown">;
|
|
90
|
+
readonly was: Schema.String;
|
|
91
|
+
}>, Schema.Struct<{
|
|
92
|
+
readonly outcome: Schema.String;
|
|
93
|
+
}>, never, never>;
|
|
94
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Schema, SchemaGetter } from "effect";
|
|
2
|
+
const Actor = Schema.Struct({ id: Schema.String, name: Schema.optionalKey(Schema.String) });
|
|
3
|
+
/**
|
|
4
|
+
* What an unknown ask is read for: what every ask has had in every revision, which a list of asks
|
|
5
|
+
* shows and sorts by. Only the identity, status and times are required, so an ask from a newer
|
|
6
|
+
* revision that has dropped anything else still reads as one.
|
|
7
|
+
*/
|
|
8
|
+
const AskFields = Schema.Struct({
|
|
9
|
+
kind: Schema.String,
|
|
10
|
+
id: Schema.String,
|
|
11
|
+
status: Schema.String,
|
|
12
|
+
waiting: Schema.optionalKey(Schema.Boolean),
|
|
13
|
+
project: Schema.optionalKey(Schema.String),
|
|
14
|
+
client: Schema.optionalKey(Schema.String),
|
|
15
|
+
raisedBy: Schema.optionalKey(Actor),
|
|
16
|
+
createdAt: Schema.String,
|
|
17
|
+
updatedAt: Schema.String,
|
|
18
|
+
closedAt: Schema.optionalKey(Schema.String),
|
|
19
|
+
});
|
|
20
|
+
/** The union member for an ask this reader can't read, given the statuses it knows. */
|
|
21
|
+
export const unknownAsk = (statuses) => {
|
|
22
|
+
const known = Schema.is(statuses);
|
|
23
|
+
return AskFields.pipe(Schema.decodeTo(Schema.Struct({
|
|
24
|
+
kind: Schema.Literal("unknown"),
|
|
25
|
+
was: Schema.String,
|
|
26
|
+
id: Schema.String,
|
|
27
|
+
status: statuses,
|
|
28
|
+
waiting: Schema.Boolean,
|
|
29
|
+
project: Schema.optionalKey(Schema.String),
|
|
30
|
+
client: Schema.optionalKey(Schema.String),
|
|
31
|
+
raisedBy: Schema.optionalKey(Actor),
|
|
32
|
+
createdAt: Schema.String,
|
|
33
|
+
updatedAt: Schema.String,
|
|
34
|
+
closedAt: Schema.optionalKey(Schema.String),
|
|
35
|
+
}), {
|
|
36
|
+
decode: SchemaGetter.transform(({ kind, status, waiting, ...rest }) => ({
|
|
37
|
+
...rest,
|
|
38
|
+
kind: "unknown",
|
|
39
|
+
was: kind,
|
|
40
|
+
status: known(status) ? status : "closed",
|
|
41
|
+
waiting: waiting ?? false,
|
|
42
|
+
})),
|
|
43
|
+
encode: SchemaGetter.transform(({ was, ...rest }) => ({ ...rest, kind: was })),
|
|
44
|
+
}));
|
|
45
|
+
};
|
|
46
|
+
/** A message whose `type` this reader doesn't know: the type `unknown`, and what it was. */
|
|
47
|
+
const unknownType = Schema.Struct({ type: Schema.String }).pipe(Schema.decodeTo(Schema.Struct({ type: Schema.Literal("unknown"), was: Schema.String }), {
|
|
48
|
+
decode: SchemaGetter.transform(({ type }) => ({ type: "unknown", was: type })),
|
|
49
|
+
encode: SchemaGetter.transform(({ was }) => ({ type: was })),
|
|
50
|
+
}));
|
|
51
|
+
export const unknownBlock = unknownType;
|
|
52
|
+
export const unknownEvent = unknownType;
|
|
53
|
+
export const unknownReply = Schema.Struct({ outcome: Schema.String }).pipe(Schema.decodeTo(Schema.Struct({ outcome: Schema.Literal("unknown"), was: Schema.String }), {
|
|
54
|
+
decode: SchemaGetter.transform(({ outcome }) => ({
|
|
55
|
+
outcome: "unknown",
|
|
56
|
+
was: outcome,
|
|
57
|
+
})),
|
|
58
|
+
encode: SchemaGetter.transform(({ was }) => ({ outcome: was })),
|
|
59
|
+
}));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the parts of a deployment name the code they run, over HTTP. Every API response names the
|
|
3
|
+
* revision of the contract its server writes, and the build of the deploy it is from. A client names
|
|
4
|
+
* the revision it writes on every request; one naming a later revision than the server's, as a page
|
|
5
|
+
* from newer code does after a rollback, is refused with `409` and the problem code `reload`. See
|
|
6
|
+
* docs/design/versioned-messages.md.
|
|
7
|
+
*/
|
|
8
|
+
export declare const REVISION_HEADER = "Loopback-Revision";
|
|
9
|
+
export declare const BUILD_HEADER = "Loopback-Build";
|
|
10
|
+
/** The problem code a request from newer code than the server's is refused with: reload onto it. */
|
|
11
|
+
export declare const RELOAD_CODE = "reload";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the parts of a deployment name the code they run, over HTTP. Every API response names the
|
|
3
|
+
* revision of the contract its server writes, and the build of the deploy it is from. A client names
|
|
4
|
+
* the revision it writes on every request; one naming a later revision than the server's, as a page
|
|
5
|
+
* from newer code does after a rollback, is refused with `409` and the problem code `reload`. See
|
|
6
|
+
* docs/design/versioned-messages.md.
|
|
7
|
+
*/
|
|
8
|
+
export const REVISION_HEADER = "Loopback-Revision";
|
|
9
|
+
export const BUILD_HEADER = "Loopback-Build";
|
|
10
|
+
/** The problem code a request from newer code than the server's is refused with: reload onto it. */
|
|
11
|
+
export const RELOAD_CODE = "reload";
|