@conciv/protocol 0.0.1
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 +5 -0
- package/dist/bundler-types.d.ts +37 -0
- package/dist/bundler-types.d.ts.map +1 -0
- package/dist/bundler-types.js +9 -0
- package/dist/bundler-types.js.map +1 -0
- package/dist/chat-types.d.ts +250 -0
- package/dist/chat-types.d.ts.map +1 -0
- package/dist/chat-types.js +127 -0
- package/dist/chat-types.js.map +1 -0
- package/dist/config-types.d.ts +44 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/config-types.js +8 -0
- package/dist/config-types.js.map +1 -0
- package/dist/done-types.d.ts +14 -0
- package/dist/done-types.d.ts.map +1 -0
- package/dist/done-types.js +13 -0
- package/dist/done-types.js.map +1 -0
- package/dist/editor-types.d.ts +11 -0
- package/dist/editor-types.d.ts.map +1 -0
- package/dist/editor-types.js +10 -0
- package/dist/editor-types.js.map +1 -0
- package/dist/harness-types.d.ts +138 -0
- package/dist/harness-types.d.ts.map +1 -0
- package/dist/harness-types.js +8 -0
- package/dist/harness-types.js.map +1 -0
- package/dist/page-introspect-types.d.ts +55 -0
- package/dist/page-introspect-types.d.ts.map +1 -0
- package/dist/page-introspect-types.js +1 -0
- package/dist/page-types.d.ts +222 -0
- package/dist/page-types.d.ts.map +1 -0
- package/dist/page-types.js +163 -0
- package/dist/page-types.js.map +1 -0
- package/dist/tool-timing.d.ts +14 -0
- package/dist/tool-timing.d.ts.map +1 -0
- package/dist/tool-timing.js +22 -0
- package/dist/tool-timing.js.map +1 -0
- package/dist/tool-view-types.d.ts +13794 -0
- package/dist/tool-view-types.d.ts.map +1 -0
- package/dist/tool-view-types.js +1 -0
- package/dist/ui-types.d.ts +118 -0
- package/dist/ui-types.d.ts.map +1 -0
- package/dist/ui-types.js +136 -0
- package/dist/ui-types.js.map +1 -0
- package/dist/usage-types.d.ts +24 -0
- package/dist/usage-types.d.ts.map +1 -0
- package/dist/usage-types.js +68 -0
- package/dist/usage-types.js.map +1 -0
- package/package.json +96 -0
package/dist/ui-types.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { EventType } from "@tanstack/ai";
|
|
3
|
+
//#region src/ui-types.ts
|
|
4
|
+
const renderId = z.string().min(1);
|
|
5
|
+
const UiFormFieldSchema = z.object({
|
|
6
|
+
name: z.string(),
|
|
7
|
+
label: z.string(),
|
|
8
|
+
type: z.enum(["text", "select"]),
|
|
9
|
+
options: z.array(z.string()).optional()
|
|
10
|
+
});
|
|
11
|
+
const UiChoicesSchema = z.object({
|
|
12
|
+
kind: z.literal("choices"),
|
|
13
|
+
renderId,
|
|
14
|
+
question: z.string(),
|
|
15
|
+
options: z.array(z.string()).min(1)
|
|
16
|
+
});
|
|
17
|
+
const UiConfirmSchema = z.object({
|
|
18
|
+
kind: z.literal("confirm"),
|
|
19
|
+
renderId,
|
|
20
|
+
question: z.string(),
|
|
21
|
+
detail: z.string().optional()
|
|
22
|
+
});
|
|
23
|
+
const UiDiffSchema = z.object({
|
|
24
|
+
kind: z.literal("diff"),
|
|
25
|
+
renderId,
|
|
26
|
+
file: z.string(),
|
|
27
|
+
before: z.string(),
|
|
28
|
+
after: z.string()
|
|
29
|
+
});
|
|
30
|
+
const UiFormSchema = z.object({
|
|
31
|
+
kind: z.literal("form"),
|
|
32
|
+
renderId,
|
|
33
|
+
title: z.string().optional(),
|
|
34
|
+
fields: z.array(UiFormFieldSchema).min(1)
|
|
35
|
+
});
|
|
36
|
+
const UiVitestSchema = z.object({
|
|
37
|
+
kind: z.literal("vitest"),
|
|
38
|
+
renderId
|
|
39
|
+
});
|
|
40
|
+
const UiSpecSchema = z.discriminatedUnion("kind", [
|
|
41
|
+
UiChoicesSchema,
|
|
42
|
+
UiConfirmSchema,
|
|
43
|
+
UiDiffSchema,
|
|
44
|
+
UiFormSchema,
|
|
45
|
+
UiVitestSchema
|
|
46
|
+
]);
|
|
47
|
+
const CONCIV_UI_EVENT = "conciv-ui";
|
|
48
|
+
function aguiCustomFor(spec) {
|
|
49
|
+
return {
|
|
50
|
+
type: EventType.CUSTOM,
|
|
51
|
+
name: CONCIV_UI_EVENT,
|
|
52
|
+
value: spec
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const APPROVAL_REQUESTED_EVENT = "approval-requested";
|
|
56
|
+
function aguiApprovalRequestedFor(req) {
|
|
57
|
+
return {
|
|
58
|
+
type: EventType.CUSTOM,
|
|
59
|
+
name: APPROVAL_REQUESTED_EVENT,
|
|
60
|
+
value: {
|
|
61
|
+
toolCallId: req.toolCallId,
|
|
62
|
+
toolName: req.toolName,
|
|
63
|
+
input: req.input,
|
|
64
|
+
approval: { id: req.approvalId }
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function parseUiSpec(input) {
|
|
69
|
+
const result = UiSpecSchema.safeParse(input);
|
|
70
|
+
return result.success ? result.data : null;
|
|
71
|
+
}
|
|
72
|
+
function parseField(raw) {
|
|
73
|
+
const [name, label, type, opts] = raw.split(":");
|
|
74
|
+
if (!name || !label) return null;
|
|
75
|
+
if (type !== "text" && type !== "select") return null;
|
|
76
|
+
if (type === "select") {
|
|
77
|
+
const options = (opts ?? "").split(",").filter(Boolean);
|
|
78
|
+
if (options.length === 0) return null;
|
|
79
|
+
return {
|
|
80
|
+
name,
|
|
81
|
+
label,
|
|
82
|
+
type,
|
|
83
|
+
options
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
name,
|
|
88
|
+
label,
|
|
89
|
+
type
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function buildUiSpec(input, id) {
|
|
93
|
+
if (input.kind === "choices") {
|
|
94
|
+
if (!input.question) throw new Error("choices needs a question");
|
|
95
|
+
if (!input.options?.length) throw new Error("choices needs at least one option");
|
|
96
|
+
return {
|
|
97
|
+
kind: "choices",
|
|
98
|
+
renderId: id,
|
|
99
|
+
question: input.question,
|
|
100
|
+
options: input.options
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (input.kind === "confirm") {
|
|
104
|
+
if (!input.question) throw new Error("confirm needs a question");
|
|
105
|
+
return {
|
|
106
|
+
kind: "confirm",
|
|
107
|
+
renderId: id,
|
|
108
|
+
question: input.question,
|
|
109
|
+
detail: input.detail
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (input.kind === "diff") {
|
|
113
|
+
if (input.file === void 0 || input.before === void 0 || input.after === void 0) throw new Error("diff needs file, before, and after");
|
|
114
|
+
return {
|
|
115
|
+
kind: "diff",
|
|
116
|
+
renderId: id,
|
|
117
|
+
file: input.file,
|
|
118
|
+
before: input.before,
|
|
119
|
+
after: input.after
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
if (input.kind === "form") {
|
|
123
|
+
if (!input.fields?.length) throw new Error("form needs at least one field");
|
|
124
|
+
return {
|
|
125
|
+
kind: "form",
|
|
126
|
+
renderId: id,
|
|
127
|
+
title: input.title,
|
|
128
|
+
fields: input.fields
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
throw new Error(`unknown ui kind: ${input.kind}`);
|
|
132
|
+
}
|
|
133
|
+
//#endregion
|
|
134
|
+
export { APPROVAL_REQUESTED_EVENT, CONCIV_UI_EVENT, UiChoicesSchema, UiConfirmSchema, UiDiffSchema, UiFormFieldSchema, UiFormSchema, UiSpecSchema, UiVitestSchema, aguiApprovalRequestedFor, aguiCustomFor, buildUiSpec, parseField, parseUiSpec };
|
|
135
|
+
|
|
136
|
+
//# sourceMappingURL=ui-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-types.js","names":[],"sources":["../src/ui-types.ts"],"sourcesContent":["import {z} from 'zod'\nimport {EventType, type StreamChunk} from '@tanstack/ai'\n\n// Generative-UI specs the chat agent emits via `conciv ui …`, rendered as components in the\n// chat thread and carried to the widget as an AG-UI CUSTOM event. The schemas are the contract;\n// types are inferred from them.\n\nconst renderId = z.string().min(1)\n\nexport const UiFormFieldSchema = z.object({\n name: z.string(),\n label: z.string(),\n type: z.enum(['text', 'select']),\n options: z.array(z.string()).optional(),\n})\n\nexport const UiChoicesSchema = z.object({\n kind: z.literal('choices'),\n renderId,\n question: z.string(),\n options: z.array(z.string()).min(1),\n})\nexport const UiConfirmSchema = z.object({\n kind: z.literal('confirm'),\n renderId,\n question: z.string(),\n detail: z.string().optional(),\n})\nexport const UiDiffSchema = z.object({\n kind: z.literal('diff'),\n renderId,\n file: z.string(),\n before: z.string(),\n after: z.string(),\n})\nexport const UiFormSchema = z.object({\n kind: z.literal('form'),\n renderId,\n title: z.string().optional(),\n fields: z.array(UiFormFieldSchema).min(1),\n})\n// Test-results card injected by the test route. (Kind stays 'vitest' until Plan 3.)\nexport const UiVitestSchema = z.object({kind: z.literal('vitest'), renderId})\n\nexport const UiSpecSchema = z.discriminatedUnion('kind', [\n UiChoicesSchema,\n UiConfirmSchema,\n UiDiffSchema,\n UiFormSchema,\n UiVitestSchema,\n])\n\nexport type UiFormField = z.infer<typeof UiFormFieldSchema>\nexport type UiFieldType = UiFormField['type']\nexport type UiSpec = z.infer<typeof UiSpecSchema>\nexport type UiChoices = z.infer<typeof UiChoicesSchema>\nexport type UiConfirm = z.infer<typeof UiConfirmSchema>\nexport type UiDiff = z.infer<typeof UiDiffSchema>\nexport type UiForm = z.infer<typeof UiFormSchema>\nexport type UiVitest = z.infer<typeof UiVitestSchema>\n\n// The CUSTOM event name the widget listens for via useChat({onCustomEvent}).\nexport const CONCIV_UI_EVENT = 'conciv-ui'\n\n// Wrap a spec as the AG-UI CUSTOM StreamChunk injected into the live chat stream.\nexport function aguiCustomFor(spec: UiSpec): StreamChunk {\n return {type: EventType.CUSTOM, name: CONCIV_UI_EVENT, value: spec}\n}\n\n// tanstack's StreamProcessor consumes this reserved CUSTOM event name to drive a tool-call part into\n// its NATIVE approval-requested state — it sets part.state='approval-requested' and part.approval\n// (see @tanstack/ai processor handleCustomEvent). The risky-Bash gate emits it so approval renders on\n// the tool card itself (no separate GenUi card). The decision returns out-of-band via\n// /api/chat/permission-decision: claude owns the loop and blocks on its PreToolUse hook, so the\n// decision cannot ride the one-way stream back (it would deadlock the live turn).\nexport const APPROVAL_REQUESTED_EVENT = 'approval-requested'\n\n// The value shape the StreamProcessor reads off the approval-requested CUSTOM event. toolCallId MUST\n// equal the streamed tool-call part id (= claude's tool_use_id) so the right part is targeted.\nexport type ApprovalRequest = {toolCallId: string; toolName: string; input: unknown; approvalId: string}\n\nexport function aguiApprovalRequestedFor(req: ApprovalRequest): StreamChunk {\n return {\n type: EventType.CUSTOM,\n name: APPROVAL_REQUESTED_EVENT,\n value: {toolCallId: req.toolCallId, toolName: req.toolName, input: req.input, approval: {id: req.approvalId}},\n }\n}\n\n// For non-h3 callers; route handlers use readValidatedBody(event, UiSpecSchema) directly.\nexport function parseUiSpec(input: unknown): UiSpec | null {\n const result = UiSpecSchema.safeParse(input)\n return result.success ? result.data : null\n}\n\n// Parse a CLI form-field spec `name:label:type[:opt1,opt2]` into a typed field. null if malformed.\nexport function parseField(raw: string): UiFormField | null {\n const [name, label, type, opts] = raw.split(':')\n if (!name || !label) return null\n if (type !== 'text' && type !== 'select') return null\n if (type === 'select') {\n const options = (opts ?? '').split(',').filter(Boolean)\n if (options.length === 0) return null\n return {name, label, type, options}\n }\n return {name, label, type}\n}\n\n// Normalized builder input — shared by the CLI (`conciv ui`) and the conciv_ui MCP tool. Both\n// normalize their own raw args to this shape, then call buildUiSpec.\nexport type UiBuildInput = {\n kind: string\n question?: string\n detail?: string\n options?: string[]\n file?: string\n before?: string\n after?: string\n title?: string\n fields?: UiFormField[]\n}\n\n// Pure: normalized input + a caller-supplied renderId → a typed UiSpec. Throws on invalid input.\nexport function buildUiSpec(input: UiBuildInput, id: string): UiSpec {\n if (input.kind === 'choices') {\n if (!input.question) throw new Error('choices needs a question')\n if (!input.options?.length) throw new Error('choices needs at least one option')\n return {kind: 'choices', renderId: id, question: input.question, options: input.options}\n }\n if (input.kind === 'confirm') {\n if (!input.question) throw new Error('confirm needs a question')\n return {kind: 'confirm', renderId: id, question: input.question, detail: input.detail}\n }\n if (input.kind === 'diff') {\n if (input.file === undefined || input.before === undefined || input.after === undefined) {\n throw new Error('diff needs file, before, and after')\n }\n return {kind: 'diff', renderId: id, file: input.file, before: input.before, after: input.after}\n }\n if (input.kind === 'form') {\n if (!input.fields?.length) throw new Error('form needs at least one field')\n return {kind: 'form', renderId: id, title: input.title, fields: input.fields}\n }\n throw new Error(`unknown ui kind: ${input.kind}`)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { StreamChunk, TokenUsage } from "@tanstack/ai";
|
|
3
|
+
|
|
4
|
+
//#region src/usage-types.d.ts
|
|
5
|
+
declare const UsageSnapshotSchema: z.ZodObject<{
|
|
6
|
+
modelId: z.ZodOptional<z.ZodString>;
|
|
7
|
+
contextWindow: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
inputTokens: z.ZodOptional<z.ZodNumber>;
|
|
9
|
+
outputTokens: z.ZodOptional<z.ZodNumber>;
|
|
10
|
+
cacheReadTokens: z.ZodOptional<z.ZodNumber>;
|
|
11
|
+
cacheWriteTokens: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
reasoningTokens: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
totalCostUsd: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
numTurns: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
type UsageSnapshot = z.infer<typeof UsageSnapshotSchema>;
|
|
17
|
+
declare function snapshotToTokenUsage(s: UsageSnapshot): TokenUsage;
|
|
18
|
+
declare function tokenUsageToSnapshot(u: TokenUsage): UsageSnapshot;
|
|
19
|
+
declare const CONCIV_USAGE_EVENT = "conciv-usage";
|
|
20
|
+
declare function aguiUsageFor(snapshot: UsageSnapshot): StreamChunk;
|
|
21
|
+
declare function contextUsedTokens(s: UsageSnapshot): number | undefined;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { CONCIV_USAGE_EVENT, UsageSnapshot, UsageSnapshotSchema, aguiUsageFor, contextUsedTokens, snapshotToTokenUsage, tokenUsageToSnapshot };
|
|
24
|
+
//# sourceMappingURL=usage-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-types.d.ts","names":[],"sources":["../src/usage-types.ts"],"mappings":";;;;cAIa,mBAAA,EAAmB,CAAA,CAAA,SAAA;;;;;;;;;;;KAWpB,aAAA,GAAgB,CAAA,CAAE,KAAK,QAAQ,mBAAA;AAAA,iBAW3B,oBAAA,CAAqB,CAAA,EAAG,aAAA,GAAgB,UAAU;AAAA,iBAkBlD,oBAAA,CAAqB,CAAA,EAAG,UAAA,GAAa,aAAa;AAAA,cAiBrD,kBAAA;AAAA,iBACG,YAAA,CAAa,QAAA,EAAU,aAAA,GAAgB,WAAW;AAAA,iBAKlD,iBAAA,CAAkB,CAAgB,EAAb,aAAa"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { EventType } from "@tanstack/ai";
|
|
3
|
+
//#region src/usage-types.ts
|
|
4
|
+
const UsageSnapshotSchema = z.object({
|
|
5
|
+
modelId: z.string().optional(),
|
|
6
|
+
contextWindow: z.number().int().nonnegative().optional(),
|
|
7
|
+
inputTokens: z.number().int().nonnegative().optional(),
|
|
8
|
+
outputTokens: z.number().int().nonnegative().optional(),
|
|
9
|
+
cacheReadTokens: z.number().int().nonnegative().optional(),
|
|
10
|
+
cacheWriteTokens: z.number().int().nonnegative().optional(),
|
|
11
|
+
reasoningTokens: z.number().int().nonnegative().optional(),
|
|
12
|
+
totalCostUsd: z.number().nonnegative().optional(),
|
|
13
|
+
numTurns: z.number().int().nonnegative().optional()
|
|
14
|
+
});
|
|
15
|
+
function snapshotToTokenUsage(s) {
|
|
16
|
+
const provider = {
|
|
17
|
+
modelId: s.modelId,
|
|
18
|
+
contextWindow: s.contextWindow,
|
|
19
|
+
totalCostUsd: s.totalCostUsd,
|
|
20
|
+
numTurns: s.numTurns
|
|
21
|
+
};
|
|
22
|
+
return {
|
|
23
|
+
promptTokens: s.inputTokens ?? 0,
|
|
24
|
+
completionTokens: s.outputTokens ?? 0,
|
|
25
|
+
totalTokens: (s.inputTokens ?? 0) + (s.outputTokens ?? 0),
|
|
26
|
+
promptTokensDetails: {
|
|
27
|
+
cachedTokens: s.cacheReadTokens,
|
|
28
|
+
cacheWriteTokens: s.cacheWriteTokens
|
|
29
|
+
},
|
|
30
|
+
completionTokensDetails: { reasoningTokens: s.reasoningTokens },
|
|
31
|
+
providerUsageDetails: provider
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function tokenUsageToSnapshot(u) {
|
|
35
|
+
const p = u.providerUsageDetails ?? {};
|
|
36
|
+
return {
|
|
37
|
+
modelId: p.modelId,
|
|
38
|
+
contextWindow: p.contextWindow,
|
|
39
|
+
inputTokens: u.promptTokens,
|
|
40
|
+
outputTokens: u.completionTokens,
|
|
41
|
+
cacheReadTokens: u.promptTokensDetails?.cachedTokens,
|
|
42
|
+
cacheWriteTokens: u.promptTokensDetails?.cacheWriteTokens,
|
|
43
|
+
reasoningTokens: u.completionTokensDetails?.reasoningTokens,
|
|
44
|
+
totalCostUsd: p.totalCostUsd,
|
|
45
|
+
numTurns: p.numTurns
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const CONCIV_USAGE_EVENT = "conciv-usage";
|
|
49
|
+
function aguiUsageFor(snapshot) {
|
|
50
|
+
return {
|
|
51
|
+
type: EventType.CUSTOM,
|
|
52
|
+
name: CONCIV_USAGE_EVENT,
|
|
53
|
+
value: snapshot
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function contextUsedTokens(s) {
|
|
57
|
+
const parts = [
|
|
58
|
+
s.inputTokens,
|
|
59
|
+
s.cacheReadTokens,
|
|
60
|
+
s.cacheWriteTokens
|
|
61
|
+
];
|
|
62
|
+
if (parts.every((p) => p === void 0)) return void 0;
|
|
63
|
+
return parts.reduce((sum, p) => sum + (p ?? 0), 0);
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
export { CONCIV_USAGE_EVENT, UsageSnapshotSchema, aguiUsageFor, contextUsedTokens, snapshotToTokenUsage, tokenUsageToSnapshot };
|
|
67
|
+
|
|
68
|
+
//# sourceMappingURL=usage-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-types.js","names":[],"sources":["../src/usage-types.ts"],"sourcesContent":["import {z} from 'zod'\nimport {EventType, type StreamChunk, type TokenUsage} from '@tanstack/ai'\n\n// Normalized per-session model usage; every field optional so a harness reports only what it has.\nexport const UsageSnapshotSchema = z.object({\n modelId: z.string().optional(),\n contextWindow: z.number().int().nonnegative().optional(),\n inputTokens: z.number().int().nonnegative().optional(),\n outputTokens: z.number().int().nonnegative().optional(),\n cacheReadTokens: z.number().int().nonnegative().optional(),\n cacheWriteTokens: z.number().int().nonnegative().optional(),\n reasoningTokens: z.number().int().nonnegative().optional(),\n totalCostUsd: z.number().nonnegative().optional(),\n numTurns: z.number().int().nonnegative().optional(),\n})\nexport type UsageSnapshot = z.infer<typeof UsageSnapshotSchema>\n\n// Fields with no standard TokenUsage slot ride providerUsageDetails (one type keeps the mappers in sync).\ntype ConcivProviderUsage = {\n modelId?: string\n contextWindow?: number\n totalCostUsd?: number\n numTurns?: number\n}\n\n// Snapshot → native TokenUsage on RUN_FINISHED (survives chat(); CUSTOM chunks do not).\nexport function snapshotToTokenUsage(s: UsageSnapshot): TokenUsage {\n const provider: ConcivProviderUsage = {\n modelId: s.modelId,\n contextWindow: s.contextWindow,\n totalCostUsd: s.totalCostUsd,\n numTurns: s.numTurns,\n }\n return {\n promptTokens: s.inputTokens ?? 0,\n completionTokens: s.outputTokens ?? 0,\n totalTokens: (s.inputTokens ?? 0) + (s.outputTokens ?? 0),\n promptTokensDetails: {cachedTokens: s.cacheReadTokens, cacheWriteTokens: s.cacheWriteTokens},\n completionTokensDetails: {reasoningTokens: s.reasoningTokens},\n providerUsageDetails: provider,\n }\n}\n\n// Inverse of snapshotToTokenUsage: read a RUN_FINISHED usage back into our display shape.\nexport function tokenUsageToSnapshot(u: TokenUsage): UsageSnapshot {\n const p = (u.providerUsageDetails ?? {}) as ConcivProviderUsage\n return {\n modelId: p.modelId,\n contextWindow: p.contextWindow,\n inputTokens: u.promptTokens,\n outputTokens: u.completionTokens,\n cacheReadTokens: u.promptTokensDetails?.cachedTokens,\n cacheWriteTokens: u.promptTokensDetails?.cacheWriteTokens,\n reasoningTokens: u.completionTokensDetails?.reasoningTokens,\n totalCostUsd: p.totalCostUsd,\n numTurns: p.numTurns,\n }\n}\n\n// Live usage carried to the widget mid-turn as an AG-UI CUSTOM event, injected by core post-chat()\n// (the same seam conciv-ui uses). RUN_FINISHED.usage stays the canonical end-of-turn/persist value.\nexport const CONCIV_USAGE_EVENT = 'conciv-usage'\nexport function aguiUsageFor(snapshot: UsageSnapshot): StreamChunk {\n return {type: EventType.CUSTOM, name: CONCIV_USAGE_EVENT, value: snapshot}\n}\n\n// Context occupancy = prompt resident in the window (input + cache), excluding output; undefined when no tokens.\nexport function contextUsedTokens(s: UsageSnapshot): number | undefined {\n const parts = [s.inputTokens, s.cacheReadTokens, s.cacheWriteTokens]\n if (parts.every((p) => p === undefined)) return undefined\n return parts.reduce<number>((sum, p) => sum + (p ?? 0), 0)\n}\n"],"mappings":";;;AAIA,MAAa,sBAAsB,EAAE,OAAO;CAC1C,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS;CAC7B,eAAe,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS;CACvD,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS;CACrD,cAAc,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS;CACtD,iBAAiB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS;CACzD,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS;CAC1D,iBAAiB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS;CACzD,cAAc,EAAE,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS;CAChD,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS;AACpD,CAAC;AAYD,SAAgB,qBAAqB,GAA8B;CACjE,MAAM,WAAgC;EACpC,SAAS,EAAE;EACX,eAAe,EAAE;EACjB,cAAc,EAAE;EAChB,UAAU,EAAE;CACd;CACA,OAAO;EACL,cAAc,EAAE,eAAe;EAC/B,kBAAkB,EAAE,gBAAgB;EACpC,cAAc,EAAE,eAAe,MAAM,EAAE,gBAAgB;EACvD,qBAAqB;GAAC,cAAc,EAAE;GAAiB,kBAAkB,EAAE;EAAgB;EAC3F,yBAAyB,EAAC,iBAAiB,EAAE,gBAAe;EAC5D,sBAAsB;CACxB;AACF;AAGA,SAAgB,qBAAqB,GAA8B;CACjE,MAAM,IAAK,EAAE,wBAAwB,CAAC;CACtC,OAAO;EACL,SAAS,EAAE;EACX,eAAe,EAAE;EACjB,aAAa,EAAE;EACf,cAAc,EAAE;EAChB,iBAAiB,EAAE,qBAAqB;EACxC,kBAAkB,EAAE,qBAAqB;EACzC,iBAAiB,EAAE,yBAAyB;EAC5C,cAAc,EAAE;EAChB,UAAU,EAAE;CACd;AACF;AAIA,MAAa,qBAAqB;AAClC,SAAgB,aAAa,UAAsC;CACjE,OAAO;EAAC,MAAM,UAAU;EAAQ,MAAM;EAAoB,OAAO;CAAQ;AAC3E;AAGA,SAAgB,kBAAkB,GAAsC;CACtE,MAAM,QAAQ;EAAC,EAAE;EAAa,EAAE;EAAiB,EAAE;CAAgB;CACnE,IAAI,MAAM,OAAO,MAAM,MAAM,KAAA,CAAS,GAAG,OAAO,KAAA;CAChD,OAAO,MAAM,QAAgB,KAAK,MAAM,OAAO,KAAK,IAAI,CAAC;AAC3D"}
|
package/package.json
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@conciv/protocol",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Wire types shared by the conciv vite-plugin and widget.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ag-ui",
|
|
7
|
+
"conciv",
|
|
8
|
+
"protocol",
|
|
9
|
+
"types"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/conciv-dev/conciv/tree/main/packages/protocol#readme",
|
|
12
|
+
"bugs": "https://github.com/conciv-dev/conciv/issues",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/conciv-dev/conciv.git",
|
|
17
|
+
"directory": "packages/protocol"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"exports": {
|
|
24
|
+
"./chat-types": {
|
|
25
|
+
"types": "./dist/chat-types.d.ts",
|
|
26
|
+
"import": "./dist/chat-types.js"
|
|
27
|
+
},
|
|
28
|
+
"./ui-types": {
|
|
29
|
+
"types": "./dist/ui-types.d.ts",
|
|
30
|
+
"import": "./dist/ui-types.js"
|
|
31
|
+
},
|
|
32
|
+
"./done-types": {
|
|
33
|
+
"types": "./dist/done-types.d.ts",
|
|
34
|
+
"import": "./dist/done-types.js"
|
|
35
|
+
},
|
|
36
|
+
"./editor-types": {
|
|
37
|
+
"types": "./dist/editor-types.d.ts",
|
|
38
|
+
"import": "./dist/editor-types.js"
|
|
39
|
+
},
|
|
40
|
+
"./harness-types": {
|
|
41
|
+
"types": "./dist/harness-types.d.ts",
|
|
42
|
+
"import": "./dist/harness-types.js"
|
|
43
|
+
},
|
|
44
|
+
"./bundler-types": {
|
|
45
|
+
"types": "./dist/bundler-types.d.ts",
|
|
46
|
+
"import": "./dist/bundler-types.js"
|
|
47
|
+
},
|
|
48
|
+
"./config-types": {
|
|
49
|
+
"types": "./dist/config-types.d.ts",
|
|
50
|
+
"import": "./dist/config-types.js"
|
|
51
|
+
},
|
|
52
|
+
"./page-types": {
|
|
53
|
+
"types": "./dist/page-types.d.ts",
|
|
54
|
+
"import": "./dist/page-types.js"
|
|
55
|
+
},
|
|
56
|
+
"./page-introspect-types": {
|
|
57
|
+
"types": "./dist/page-introspect-types.d.ts",
|
|
58
|
+
"import": "./dist/page-introspect-types.js"
|
|
59
|
+
},
|
|
60
|
+
"./usage-types": {
|
|
61
|
+
"types": "./dist/usage-types.d.ts",
|
|
62
|
+
"import": "./dist/usage-types.js"
|
|
63
|
+
},
|
|
64
|
+
"./tool-view-types": {
|
|
65
|
+
"types": "./dist/tool-view-types.d.ts",
|
|
66
|
+
"import": "./dist/tool-view-types.js"
|
|
67
|
+
},
|
|
68
|
+
"./tool-timing": {
|
|
69
|
+
"types": "./dist/tool-timing.d.ts",
|
|
70
|
+
"import": "./dist/tool-timing.js"
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"publishConfig": {
|
|
74
|
+
"access": "public"
|
|
75
|
+
},
|
|
76
|
+
"dependencies": {
|
|
77
|
+
"@tanstack/ai": "^0.28.0",
|
|
78
|
+
"@tanstack/ai-client": "^0.16.3",
|
|
79
|
+
"zod": "^4.4.3"
|
|
80
|
+
},
|
|
81
|
+
"devDependencies": {
|
|
82
|
+
"@types/node": "^22.19.21",
|
|
83
|
+
"solid-js": "^1.9.13",
|
|
84
|
+
"tsdown": "^0.22.2",
|
|
85
|
+
"typescript": "^6.0.3",
|
|
86
|
+
"vitest": "^4.1.8"
|
|
87
|
+
},
|
|
88
|
+
"scripts": {
|
|
89
|
+
"build": "tsdown",
|
|
90
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
91
|
+
"lint": "oxlint",
|
|
92
|
+
"test": "vitest run",
|
|
93
|
+
"publint": "publint",
|
|
94
|
+
"attw": "attw --pack . --profile esm-only"
|
|
95
|
+
}
|
|
96
|
+
}
|