@brutal-ai/schema 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.
Files changed (4) hide show
  1. package/README.md +2 -2
  2. package/index.d.ts +202 -0
  3. package/index.js +80 -0
  4. package/package.json +24 -4
package/README.md CHANGED
@@ -1,3 +1,3 @@
1
- # Temporary Holding Version
1
+ # @brutal-ai/schema
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Brutal's report schema and report_feedback tool. See [Brutal](https://github.com/cldixon/brutal).
package/index.d.ts ADDED
@@ -0,0 +1,202 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * The report schema and the canonical tool definition. Every surface (HTTP API, MCP, a future
4
+ * SDK and CLI) validates against these, so an agent in any language can define the tool from
5
+ * `toolDefinition()` and POST to the API.
6
+ */
7
+ export declare const KINDS: readonly ["bug", "friction", "missing_capability", "confusing_output", "latency", "eval_candidate", "other"];
8
+ export declare const IMPACTS: readonly ["blocked", "worked_around", "minor"];
9
+ export declare const STATUSES: readonly ["new", "triaged", "linked", "fixed", "verified", "wont_fix"];
10
+ export type Kind = (typeof KINDS)[number];
11
+ export type Impact = (typeof IMPACTS)[number];
12
+ export type Status = (typeof STATUSES)[number];
13
+ /** What the agent supplies: its judgment. Kept small so models fill it reliably. */
14
+ export declare const agentInput: {
15
+ kind: z.ZodEnum<{
16
+ bug: "bug";
17
+ friction: "friction";
18
+ missing_capability: "missing_capability";
19
+ confusing_output: "confusing_output";
20
+ latency: "latency";
21
+ eval_candidate: "eval_candidate";
22
+ other: "other";
23
+ }>;
24
+ title: z.ZodString;
25
+ summary: z.ZodString;
26
+ details: z.ZodOptional<z.ZodString>;
27
+ tool_name: z.ZodOptional<z.ZodString>;
28
+ impact: z.ZodOptional<z.ZodEnum<{
29
+ blocked: "blocked";
30
+ worked_around: "worked_around";
31
+ minor: "minor";
32
+ }>>;
33
+ user_impact: z.ZodOptional<z.ZodString>;
34
+ };
35
+ export declare const AgentInput: z.ZodObject<{
36
+ kind: z.ZodEnum<{
37
+ bug: "bug";
38
+ friction: "friction";
39
+ missing_capability: "missing_capability";
40
+ confusing_output: "confusing_output";
41
+ latency: "latency";
42
+ eval_candidate: "eval_candidate";
43
+ other: "other";
44
+ }>;
45
+ title: z.ZodString;
46
+ summary: z.ZodString;
47
+ details: z.ZodOptional<z.ZodString>;
48
+ tool_name: z.ZodOptional<z.ZodString>;
49
+ impact: z.ZodOptional<z.ZodEnum<{
50
+ blocked: "blocked";
51
+ worked_around: "worked_around";
52
+ minor: "minor";
53
+ }>>;
54
+ user_impact: z.ZodOptional<z.ZodString>;
55
+ }, z.core.$strip>;
56
+ export type AgentInput = z.infer<typeof AgentInput>;
57
+ /** One recorded tool call, attached by the integration, never written by the agent. */
58
+ export declare const ToolCall: z.ZodObject<{
59
+ name: z.ZodString;
60
+ args: z.ZodOptional<z.ZodUnknown>;
61
+ status: z.ZodOptional<z.ZodEnum<{
62
+ error: "error";
63
+ ok: "ok";
64
+ }>>;
65
+ latency_ms: z.ZodOptional<z.ZodNumber>;
66
+ result: z.ZodOptional<z.ZodUnknown>;
67
+ error: z.ZodOptional<z.ZodString>;
68
+ at: z.ZodOptional<z.ZodString>;
69
+ }, z.core.$strip>;
70
+ export type ToolCall = z.infer<typeof ToolCall>;
71
+ /** What the integration supplies: context, never asked of the agent. */
72
+ export declare const Context: z.ZodObject<{
73
+ conversation_id: z.ZodOptional<z.ZodString>;
74
+ turn_id: z.ZodOptional<z.ZodString>;
75
+ app_version: z.ZodOptional<z.ZodString>;
76
+ branch: z.ZodOptional<z.ZodString>;
77
+ deploy_id: z.ZodOptional<z.ZodString>;
78
+ environment: z.ZodOptional<z.ZodString>;
79
+ model: z.ZodOptional<z.ZodString>;
80
+ agent_name: z.ZodOptional<z.ZodString>;
81
+ trace_id: z.ZodOptional<z.ZodString>;
82
+ user_id: z.ZodOptional<z.ZodString>;
83
+ sdk: z.ZodOptional<z.ZodString>;
84
+ sdk_version: z.ZodOptional<z.ZodString>;
85
+ recent_tool_calls: z.ZodOptional<z.ZodArray<z.ZodObject<{
86
+ name: z.ZodString;
87
+ args: z.ZodOptional<z.ZodUnknown>;
88
+ status: z.ZodOptional<z.ZodEnum<{
89
+ error: "error";
90
+ ok: "ok";
91
+ }>>;
92
+ latency_ms: z.ZodOptional<z.ZodNumber>;
93
+ result: z.ZodOptional<z.ZodUnknown>;
94
+ error: z.ZodOptional<z.ZodString>;
95
+ at: z.ZodOptional<z.ZodString>;
96
+ }, z.core.$strip>>>;
97
+ }, z.core.$strip>;
98
+ export type Context = z.infer<typeof Context>;
99
+ /** The body of `POST /v1/reports`: the agent's fields, plus the integration's `context`. */
100
+ export declare const ReportInput: z.ZodObject<{
101
+ kind: z.ZodEnum<{
102
+ bug: "bug";
103
+ friction: "friction";
104
+ missing_capability: "missing_capability";
105
+ confusing_output: "confusing_output";
106
+ latency: "latency";
107
+ eval_candidate: "eval_candidate";
108
+ other: "other";
109
+ }>;
110
+ title: z.ZodString;
111
+ summary: z.ZodString;
112
+ details: z.ZodOptional<z.ZodString>;
113
+ tool_name: z.ZodOptional<z.ZodString>;
114
+ impact: z.ZodOptional<z.ZodEnum<{
115
+ blocked: "blocked";
116
+ worked_around: "worked_around";
117
+ minor: "minor";
118
+ }>>;
119
+ user_impact: z.ZodOptional<z.ZodString>;
120
+ context: z.ZodOptional<z.ZodObject<{
121
+ conversation_id: z.ZodOptional<z.ZodString>;
122
+ turn_id: z.ZodOptional<z.ZodString>;
123
+ app_version: z.ZodOptional<z.ZodString>;
124
+ branch: z.ZodOptional<z.ZodString>;
125
+ deploy_id: z.ZodOptional<z.ZodString>;
126
+ environment: z.ZodOptional<z.ZodString>;
127
+ model: z.ZodOptional<z.ZodString>;
128
+ agent_name: z.ZodOptional<z.ZodString>;
129
+ trace_id: z.ZodOptional<z.ZodString>;
130
+ user_id: z.ZodOptional<z.ZodString>;
131
+ sdk: z.ZodOptional<z.ZodString>;
132
+ sdk_version: z.ZodOptional<z.ZodString>;
133
+ recent_tool_calls: z.ZodOptional<z.ZodArray<z.ZodObject<{
134
+ name: z.ZodString;
135
+ args: z.ZodOptional<z.ZodUnknown>;
136
+ status: z.ZodOptional<z.ZodEnum<{
137
+ error: "error";
138
+ ok: "ok";
139
+ }>>;
140
+ latency_ms: z.ZodOptional<z.ZodNumber>;
141
+ result: z.ZodOptional<z.ZodUnknown>;
142
+ error: z.ZodOptional<z.ZodString>;
143
+ at: z.ZodOptional<z.ZodString>;
144
+ }, z.core.$strip>>>;
145
+ }, z.core.$strip>>;
146
+ }, z.core.$strip>;
147
+ export type ReportInput = z.infer<typeof ReportInput>;
148
+ /** The body of `PATCH /v1/reports/:id`. */
149
+ export declare const ReportUpdate: z.ZodObject<{
150
+ status: z.ZodOptional<z.ZodEnum<{
151
+ new: "new";
152
+ triaged: "triaged";
153
+ linked: "linked";
154
+ fixed: "fixed";
155
+ verified: "verified";
156
+ wont_fix: "wont_fix";
157
+ }>>;
158
+ issue_url: z.ZodOptional<z.ZodNullable<z.ZodURL>>;
159
+ }, z.core.$strip>;
160
+ export type ReportUpdate = z.infer<typeof ReportUpdate>;
161
+ /** A stored report, as the read API returns it. */
162
+ export interface Report extends AgentInput {
163
+ id: string;
164
+ status: Status;
165
+ issue_url: string | null;
166
+ context: Context;
167
+ created_at: string;
168
+ updated_at: string;
169
+ }
170
+ export declare const TOOL_NAME = "report_feedback";
171
+ export declare const TOOL_VERSION = "2026-11-05";
172
+ /** The tool's wording is where most of the product's quality lives: version it with TOOL_VERSION. */
173
+ export declare const TOOL_DESCRIPTION: string;
174
+ /** What the tool answers. It never fails the agent's turn. */
175
+ export declare const TOOL_ACK = "Feedback recorded.";
176
+ /** The canonical tool definition, in the shape most model APIs take (name, description, JSON Schema). */
177
+ export declare function toolDefinition(): {
178
+ name: string;
179
+ version: string;
180
+ description: string;
181
+ input_schema: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
182
+ kind: z.ZodEnum<{
183
+ bug: "bug";
184
+ friction: "friction";
185
+ missing_capability: "missing_capability";
186
+ confusing_output: "confusing_output";
187
+ latency: "latency";
188
+ eval_candidate: "eval_candidate";
189
+ other: "other";
190
+ }>;
191
+ title: z.ZodString;
192
+ summary: z.ZodString;
193
+ details: z.ZodOptional<z.ZodString>;
194
+ tool_name: z.ZodOptional<z.ZodString>;
195
+ impact: z.ZodOptional<z.ZodEnum<{
196
+ blocked: "blocked";
197
+ worked_around: "worked_around";
198
+ minor: "minor";
199
+ }>>;
200
+ user_impact: z.ZodOptional<z.ZodString>;
201
+ }, z.core.$strip>>;
202
+ };
package/index.js ADDED
@@ -0,0 +1,80 @@
1
+ // packages/schema/src/index.ts
2
+ import { z } from "zod";
3
+ var KINDS = [
4
+ "bug",
5
+ "friction",
6
+ "missing_capability",
7
+ "confusing_output",
8
+ "latency",
9
+ "eval_candidate",
10
+ "other"
11
+ ];
12
+ var IMPACTS = ["blocked", "worked_around", "minor"];
13
+ var STATUSES = ["new", "triaged", "linked", "fixed", "verified", "wont_fix"];
14
+ var agentInput = {
15
+ kind: z.enum(KINDS).describe("What sort of report this is."),
16
+ title: z.string().min(1).max(100).describe("A short title, under 100 characters."),
17
+ summary: z.string().min(1).max(500).describe("What happened, in one or two sentences."),
18
+ details: z.string().max(1e4).optional().describe("What you tried, what you expected, what you got, and a suggested fix."),
19
+ tool_name: z.string().max(200).optional().describe("The tool the report is about, if any."),
20
+ impact: z.enum(IMPACTS).optional().describe("blocked: could not finish; worked_around: finished another way; minor."),
21
+ user_impact: z.string().max(1000).optional().describe("How the end user was affected, if at all.")
22
+ };
23
+ var AgentInput = z.object(agentInput);
24
+ var ToolCall = z.object({
25
+ name: z.string().max(200),
26
+ args: z.unknown().optional(),
27
+ status: z.enum(["ok", "error"]).optional(),
28
+ latency_ms: z.number().nonnegative().optional(),
29
+ result: z.unknown().optional(),
30
+ error: z.string().max(4000).optional(),
31
+ at: z.string().optional()
32
+ });
33
+ var Context = z.object({
34
+ conversation_id: z.string().max(200),
35
+ turn_id: z.string().max(200),
36
+ app_version: z.string().max(100),
37
+ branch: z.string().max(200),
38
+ deploy_id: z.string().max(200),
39
+ environment: z.string().max(100),
40
+ model: z.string().max(200),
41
+ agent_name: z.string().max(200),
42
+ trace_id: z.string().max(200),
43
+ user_id: z.string().max(200),
44
+ sdk: z.string().max(100),
45
+ sdk_version: z.string().max(100),
46
+ recent_tool_calls: z.array(ToolCall).max(50)
47
+ }).partial();
48
+ var ReportInput = AgentInput.extend({ context: Context.optional() });
49
+ var ReportUpdate = z.object({
50
+ status: z.enum(STATUSES),
51
+ issue_url: z.url({ protocol: /^https?$/ }).max(2000).nullable()
52
+ }).partial();
53
+ var TOOL_NAME = "report_feedback";
54
+ var TOOL_VERSION = "2026-11-05";
55
+ var TOOL_DESCRIPTION = "Use this to privately tell the developers of this application about problems or notable tasks. " + "The user does not see this call. Report when: a tool errors, rejects a reasonable input, " + "returns results that look wrong or suspiciously empty, cannot express what the user asked, " + "or is slow; the UI or input makes the task harder; or the task is unusually interesting or " + "hard and would make a good evaluation case (kind: eval_candidate). Be specific: name the " + "tool, what you tried, what you expected and what happened. Report once per distinct issue, " + "then continue helping the user. Never include secrets or personal data beyond what is " + "needed to reproduce.";
56
+ var TOOL_ACK = "Feedback recorded.";
57
+ function toolDefinition() {
58
+ return {
59
+ name: TOOL_NAME,
60
+ version: TOOL_VERSION,
61
+ description: TOOL_DESCRIPTION,
62
+ input_schema: z.toJSONSchema(AgentInput)
63
+ };
64
+ }
65
+ export {
66
+ AgentInput,
67
+ Context,
68
+ IMPACTS,
69
+ KINDS,
70
+ ReportInput,
71
+ ReportUpdate,
72
+ STATUSES,
73
+ TOOL_ACK,
74
+ TOOL_DESCRIPTION,
75
+ TOOL_NAME,
76
+ TOOL_VERSION,
77
+ ToolCall,
78
+ agentInput,
79
+ toolDefinition
80
+ };
package/package.json CHANGED
@@ -1,6 +1,26 @@
1
1
  {
2
+ "version": "0.2.0",
3
+ "license": "MIT",
2
4
  "name": "@brutal-ai/schema",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
5
+ "description": "Brutal's report schema and report_feedback tool",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/cldixon/brutal.git",
10
+ "directory": "packages/schema"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "types": "./index.d.ts",
15
+ "default": "./index.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "index.js",
20
+ "index.d.ts",
21
+ "README.md"
22
+ ],
23
+ "dependencies": {
24
+ "zod": "^4.1.0"
25
+ }
26
+ }