@di-code/coding-agent 0.1.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/dist/cli.d.ts +26 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +117 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/models-loader.d.ts +4 -0
- package/dist/config/models-loader.d.ts.map +1 -0
- package/dist/config/models-loader.js +134 -0
- package/dist/config/models-loader.js.map +1 -0
- package/dist/config/models-types.d.ts +23 -0
- package/dist/config/models-types.d.ts.map +1 -0
- package/dist/config/models-types.js +2 -0
- package/dist/config/models-types.js.map +1 -0
- package/dist/config/settings-loader.d.ts +3 -0
- package/dist/config/settings-loader.d.ts.map +1 -0
- package/dist/config/settings-loader.js +130 -0
- package/dist/config/settings-loader.js.map +1 -0
- package/dist/config/settings-types.d.ts +21 -0
- package/dist/config/settings-types.d.ts.map +1 -0
- package/dist/config/settings-types.js +2 -0
- package/dist/config/settings-types.js.map +1 -0
- package/dist/core/context-builder.d.ts +8 -0
- package/dist/core/context-builder.d.ts.map +1 -0
- package/dist/core/context-builder.js +46 -0
- package/dist/core/context-builder.js.map +1 -0
- package/dist/core/model-catalog-store.d.ts +8 -0
- package/dist/core/model-catalog-store.d.ts.map +1 -0
- package/dist/core/model-catalog-store.js +68 -0
- package/dist/core/model-catalog-store.js.map +1 -0
- package/dist/core/model-composer.d.ts +4 -0
- package/dist/core/model-composer.d.ts.map +1 -0
- package/dist/core/model-composer.js +37 -0
- package/dist/core/model-composer.js.map +1 -0
- package/dist/core/session/session-manager.d.ts +44 -0
- package/dist/core/session/session-manager.d.ts.map +1 -0
- package/dist/core/session/session-manager.js +138 -0
- package/dist/core/session/session-manager.js.map +1 -0
- package/dist/core/session/session-storage.d.ts +11 -0
- package/dist/core/session/session-storage.d.ts.map +1 -0
- package/dist/core/session/session-storage.js +382 -0
- package/dist/core/session/session-storage.js.map +1 -0
- package/dist/core/session/types.d.ts +65 -0
- package/dist/core/session/types.d.ts.map +1 -0
- package/dist/core/session/types.js +28 -0
- package/dist/core/session/types.js.map +1 -0
- package/dist/core/session.d.ts +80 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +262 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/tools/bash.d.ts +39 -0
- package/dist/core/tools/bash.d.ts.map +1 -0
- package/dist/core/tools/bash.js +208 -0
- package/dist/core/tools/bash.js.map +1 -0
- package/dist/core/tools/edit.d.ts +18 -0
- package/dist/core/tools/edit.d.ts.map +1 -0
- package/dist/core/tools/edit.js +107 -0
- package/dist/core/tools/edit.js.map +1 -0
- package/dist/core/tools/file-mutation-queue.d.ts +2 -0
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
- package/dist/core/tools/file-mutation-queue.js +24 -0
- package/dist/core/tools/file-mutation-queue.js.map +1 -0
- package/dist/core/tools/path-boundary.d.ts +3 -0
- package/dist/core/tools/path-boundary.d.ts.map +1 -0
- package/dist/core/tools/path-boundary.js +62 -0
- package/dist/core/tools/path-boundary.js.map +1 -0
- package/dist/core/tools/read.d.ts +17 -0
- package/dist/core/tools/read.d.ts.map +1 -0
- package/dist/core/tools/read.js +132 -0
- package/dist/core/tools/read.js.map +1 -0
- package/dist/core/tools/write.d.ts +17 -0
- package/dist/core/tools/write.d.ts.map +1 -0
- package/dist/core/tools/write.js +45 -0
- package/dist/core/tools/write.js.map +1 -0
- package/dist/entry.d.ts +3 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +27 -0
- package/dist/entry.js.map +1 -0
- package/dist/extensions/index.d.ts +5 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +3 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/runtime.d.ts +46 -0
- package/dist/extensions/runtime.d.ts.map +1 -0
- package/dist/extensions/runtime.js +179 -0
- package/dist/extensions/runtime.js.map +1 -0
- package/dist/extensions/trust.d.ts +8 -0
- package/dist/extensions/trust.d.ts.map +1 -0
- package/dist/extensions/trust.js +59 -0
- package/dist/extensions/trust.js.map +1 -0
- package/dist/extensions/types.d.ts +46 -0
- package/dist/extensions/types.d.ts.map +1 -0
- package/dist/extensions/types.js +2 -0
- package/dist/extensions/types.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +19 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +198 -0
- package/dist/main.js.map +1 -0
- package/dist/modes/interactive-components.d.ts +41 -0
- package/dist/modes/interactive-components.d.ts.map +1 -0
- package/dist/modes/interactive-components.js +195 -0
- package/dist/modes/interactive-components.js.map +1 -0
- package/dist/modes/interactive-layout.d.ts +20 -0
- package/dist/modes/interactive-layout.d.ts.map +1 -0
- package/dist/modes/interactive-layout.js +34 -0
- package/dist/modes/interactive-layout.js.map +1 -0
- package/dist/modes/interactive-state.d.ts +61 -0
- package/dist/modes/interactive-state.d.ts.map +1 -0
- package/dist/modes/interactive-state.js +201 -0
- package/dist/modes/interactive-state.js.map +1 -0
- package/dist/modes/interactive.d.ts +61 -0
- package/dist/modes/interactive.d.ts.map +1 -0
- package/dist/modes/interactive.js +436 -0
- package/dist/modes/interactive.js.map +1 -0
- package/dist/modes/json.d.ts +14 -0
- package/dist/modes/json.d.ts.map +1 -0
- package/dist/modes/json.js +26 -0
- package/dist/modes/json.js.map +1 -0
- package/dist/modes/print.d.ts +10 -0
- package/dist/modes/print.d.ts.map +1 -0
- package/dist/modes/print.js +28 -0
- package/dist/modes/print.js.map +1 -0
- package/dist/provider-onboarding.d.ts +13 -0
- package/dist/provider-onboarding.d.ts.map +1 -0
- package/dist/provider-onboarding.js +162 -0
- package/dist/provider-onboarding.js.map +1 -0
- package/dist/rpc/client.d.ts +38 -0
- package/dist/rpc/client.d.ts.map +1 -0
- package/dist/rpc/client.js +153 -0
- package/dist/rpc/client.js.map +1 -0
- package/dist/rpc/index.d.ts +5 -0
- package/dist/rpc/index.d.ts.map +1 -0
- package/dist/rpc/index.js +5 -0
- package/dist/rpc/index.js.map +1 -0
- package/dist/rpc/jsonl.d.ts +17 -0
- package/dist/rpc/jsonl.d.ts.map +1 -0
- package/dist/rpc/jsonl.js +52 -0
- package/dist/rpc/jsonl.js.map +1 -0
- package/dist/rpc/protocol.d.ts +80 -0
- package/dist/rpc/protocol.d.ts.map +1 -0
- package/dist/rpc/protocol.js +231 -0
- package/dist/rpc/protocol.js.map +1 -0
- package/dist/rpc/server.d.ts +41 -0
- package/dist/rpc/server.d.ts.map +1 -0
- package/dist/rpc/server.js +186 -0
- package/dist/rpc/server.js.map +1 -0
- package/dist/rpc-entry.d.ts +3 -0
- package/dist/rpc-entry.d.ts.map +1 -0
- package/dist/rpc-entry.js +28 -0
- package/dist/rpc-entry.js.map +1 -0
- package/dist/startup.d.ts +24 -0
- package/dist/startup.d.ts.map +1 -0
- package/dist/startup.js +227 -0
- package/dist/startup.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { createFauxProvider, MODELS } from "@di-code/ai";
|
|
2
|
+
import { Input, Key, KeybindingsManager, SelectList, Text, TUI } from "@di-code/tui";
|
|
3
|
+
import { resolveStartupRuntime } from "./startup.js";
|
|
4
|
+
export function shouldStartProviderOnboarding(command, isInteractiveTerminal, configuration) {
|
|
5
|
+
return (command.mode === "interactive" &&
|
|
6
|
+
isInteractiveTerminal &&
|
|
7
|
+
configuration.providers.length === 0 &&
|
|
8
|
+
!configuration.environment.DI_CODE_PROVIDER?.trim());
|
|
9
|
+
}
|
|
10
|
+
class OnboardingScreen {
|
|
11
|
+
title = new Text("di-code provider setup", 1, 1);
|
|
12
|
+
prompt = new Text("", 1, 0);
|
|
13
|
+
error = new Text("", 1, 0);
|
|
14
|
+
active = null;
|
|
15
|
+
setStep(prompt, active) {
|
|
16
|
+
this.prompt.setText(prompt);
|
|
17
|
+
this.error.setText("");
|
|
18
|
+
this.active = active;
|
|
19
|
+
}
|
|
20
|
+
setError(message) {
|
|
21
|
+
this.error.setText(message);
|
|
22
|
+
}
|
|
23
|
+
setCancelled() {
|
|
24
|
+
this.prompt.setText("Provider setup cancelled.");
|
|
25
|
+
this.error.setText("");
|
|
26
|
+
this.active = null;
|
|
27
|
+
}
|
|
28
|
+
render(width) {
|
|
29
|
+
return [
|
|
30
|
+
...this.title.render(width),
|
|
31
|
+
...this.prompt.render(width),
|
|
32
|
+
...this.error.render(width),
|
|
33
|
+
...(this.active?.render(width) ?? []),
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
invalidate() {
|
|
37
|
+
this.title.invalidate();
|
|
38
|
+
this.prompt.invalidate();
|
|
39
|
+
this.error.invalidate();
|
|
40
|
+
this.active?.invalidate();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function providerChoices() {
|
|
44
|
+
return [
|
|
45
|
+
{ value: "openai", providerId: "openai", label: "OpenAI", description: "OpenAI Responses API" },
|
|
46
|
+
{ value: "deepseek", providerId: "deepseek", label: "DeepSeek", description: "DeepSeek Responses API" },
|
|
47
|
+
{ value: "faux", providerId: "faux", label: "Faux (offline)", description: "Deterministic local provider" },
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
function modelsFor(providerId) {
|
|
51
|
+
if (providerId === "faux")
|
|
52
|
+
return [createFauxProvider({ responses: [] }).model];
|
|
53
|
+
return MODELS.filter((model) => model.provider === providerId);
|
|
54
|
+
}
|
|
55
|
+
function apiKeyEnvironmentVariable(providerId) {
|
|
56
|
+
if (providerId === "openai")
|
|
57
|
+
return "OPENAI_API_KEY";
|
|
58
|
+
if (providerId === "deepseek")
|
|
59
|
+
return "DEEPSEEK_API_KEY";
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
function modelChoices(models) {
|
|
63
|
+
return models.map((model) => ({
|
|
64
|
+
value: model.id,
|
|
65
|
+
label: model.name,
|
|
66
|
+
description: `${model.id}${model.reasoning ? " - reasoning" : ""}`,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
function onboardingSelectList(items) {
|
|
70
|
+
return new SelectList(items, {
|
|
71
|
+
keybindings: new KeybindingsManager({
|
|
72
|
+
"tui.select.cancel": [Key.escape, Key.ctrl("c"), Key.ctrl("d")],
|
|
73
|
+
}),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
export function runProviderOnboarding(options) {
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
const tui = new TUI(options.terminal);
|
|
79
|
+
const screen = new OnboardingScreen();
|
|
80
|
+
let settled = false;
|
|
81
|
+
let selectedProvider;
|
|
82
|
+
const finish = (runtime) => {
|
|
83
|
+
if (settled)
|
|
84
|
+
return;
|
|
85
|
+
settled = true;
|
|
86
|
+
if (runtime === undefined)
|
|
87
|
+
screen.setCancelled();
|
|
88
|
+
tui.stop({ finalLines: runtime ? ["Provider configured for this run."] : ["Provider setup cancelled."] });
|
|
89
|
+
resolve(runtime);
|
|
90
|
+
};
|
|
91
|
+
const fail = (cause) => {
|
|
92
|
+
if (settled)
|
|
93
|
+
return;
|
|
94
|
+
settled = true;
|
|
95
|
+
tui.stop({ finalLines: ["Provider setup failed."] });
|
|
96
|
+
reject(cause);
|
|
97
|
+
};
|
|
98
|
+
const finishSelection = (modelId, apiKey) => {
|
|
99
|
+
if (!selectedProvider)
|
|
100
|
+
return;
|
|
101
|
+
const keyVariable = apiKeyEnvironmentVariable(selectedProvider);
|
|
102
|
+
const environment = {
|
|
103
|
+
...options.configuration.environment,
|
|
104
|
+
DI_CODE_PROVIDER: selectedProvider,
|
|
105
|
+
DI_CODE_MODEL: modelId,
|
|
106
|
+
...(keyVariable && apiKey ? { [keyVariable]: apiKey } : {}),
|
|
107
|
+
};
|
|
108
|
+
try {
|
|
109
|
+
finish(resolveStartupRuntime(environment, options.configuration.providers));
|
|
110
|
+
}
|
|
111
|
+
catch (cause) {
|
|
112
|
+
fail(cause);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const showKey = (modelId, keyVariable) => {
|
|
116
|
+
const input = new Input({ mask: "*", cancelOnEndOfTransmission: true });
|
|
117
|
+
input.onSubmit = (value) => {
|
|
118
|
+
const key = value.trim();
|
|
119
|
+
if (key.length === 0) {
|
|
120
|
+
screen.setError("API key cannot be empty. Press Escape to cancel.");
|
|
121
|
+
tui.requestRender(true);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
finishSelection(modelId, key);
|
|
125
|
+
};
|
|
126
|
+
input.onEscape = () => finish(undefined);
|
|
127
|
+
screen.setStep(`Enter ${keyVariable} (input is hidden):`, input);
|
|
128
|
+
tui.setFocus(input);
|
|
129
|
+
tui.requestRender(true);
|
|
130
|
+
};
|
|
131
|
+
const showModels = (choice) => {
|
|
132
|
+
selectedProvider = choice.providerId;
|
|
133
|
+
const models = modelsFor(choice.providerId);
|
|
134
|
+
const modelList = onboardingSelectList(modelChoices(models));
|
|
135
|
+
modelList.onSelect = (item) => {
|
|
136
|
+
const keyVariable = apiKeyEnvironmentVariable(choice.providerId);
|
|
137
|
+
const existingKey = keyVariable ? options.configuration.environment[keyVariable]?.trim() : undefined;
|
|
138
|
+
if (keyVariable && !existingKey)
|
|
139
|
+
showKey(item.value, keyVariable);
|
|
140
|
+
else
|
|
141
|
+
finishSelection(item.value);
|
|
142
|
+
};
|
|
143
|
+
modelList.onCancel = () => finish(undefined);
|
|
144
|
+
screen.setStep(`Select a ${choice.label} model:`, modelList);
|
|
145
|
+
tui.setFocus(modelList);
|
|
146
|
+
tui.requestRender(true);
|
|
147
|
+
};
|
|
148
|
+
const providerList = onboardingSelectList(providerChoices());
|
|
149
|
+
providerList.onSelect = (item) => {
|
|
150
|
+
const choice = providerChoices().find((candidate) => candidate.value === item.value);
|
|
151
|
+
if (choice)
|
|
152
|
+
showModels(choice);
|
|
153
|
+
};
|
|
154
|
+
providerList.onCancel = () => finish(undefined);
|
|
155
|
+
screen.setStep("Select a provider:", providerList);
|
|
156
|
+
tui.addChild(screen);
|
|
157
|
+
tui.start();
|
|
158
|
+
tui.setFocus(providerList);
|
|
159
|
+
tui.requestRender(true);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=provider-onboarding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-onboarding.js","sourceRoot":"","sources":["../src/provider-onboarding.ts"],"names":[],"mappings":"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","sourcesContent":["import { createFauxProvider, MODELS, type Model } from \"@di-code/ai\";\nimport { Input, Key, KeybindingsManager, type SelectItem, SelectList, type Terminal, Text, TUI } from \"@di-code/tui\";\nimport type { CliCommand } from \"./cli.ts\";\nimport { resolveStartupRuntime, type StartupConfiguration, type StartupRuntime } from \"./startup.ts\";\n\nexport type StartupRunCommand = Extract<CliCommand, { kind: \"run\" }>;\n\nexport interface ProviderOnboardingOptions {\n\treadonly configuration: StartupConfiguration;\n\treadonly terminal: Terminal;\n}\n\nexport function shouldStartProviderOnboarding(\n\tcommand: StartupRunCommand,\n\tisInteractiveTerminal: boolean,\n\tconfiguration: StartupConfiguration,\n): boolean {\n\treturn (\n\t\tcommand.mode === \"interactive\" &&\n\t\tisInteractiveTerminal &&\n\t\tconfiguration.providers.length === 0 &&\n\t\t!configuration.environment.DI_CODE_PROVIDER?.trim()\n\t);\n}\n\ninterface OnboardingChoice extends SelectItem {\n\treadonly providerId: \"openai\" | \"deepseek\" | \"faux\";\n}\n\nclass OnboardingScreen {\n\tprivate readonly title = new Text(\"di-code provider setup\", 1, 1);\n\tprivate readonly prompt = new Text(\"\", 1, 0);\n\tprivate readonly error = new Text(\"\", 1, 0);\n\tprivate active: SelectList | Input | null = null;\n\n\tsetStep(prompt: string, active: SelectList | Input): void {\n\t\tthis.prompt.setText(prompt);\n\t\tthis.error.setText(\"\");\n\t\tthis.active = active;\n\t}\n\n\tsetError(message: string): void {\n\t\tthis.error.setText(message);\n\t}\n\n\tsetCancelled(): void {\n\t\tthis.prompt.setText(\"Provider setup cancelled.\");\n\t\tthis.error.setText(\"\");\n\t\tthis.active = null;\n\t}\n\n\trender(width: number): string[] {\n\t\treturn [\n\t\t\t...this.title.render(width),\n\t\t\t...this.prompt.render(width),\n\t\t\t...this.error.render(width),\n\t\t\t...(this.active?.render(width) ?? []),\n\t\t];\n\t}\n\n\tinvalidate(): void {\n\t\tthis.title.invalidate();\n\t\tthis.prompt.invalidate();\n\t\tthis.error.invalidate();\n\t\tthis.active?.invalidate();\n\t}\n}\n\nfunction providerChoices(): OnboardingChoice[] {\n\treturn [\n\t\t{ value: \"openai\", providerId: \"openai\", label: \"OpenAI\", description: \"OpenAI Responses API\" },\n\t\t{ value: \"deepseek\", providerId: \"deepseek\", label: \"DeepSeek\", description: \"DeepSeek Responses API\" },\n\t\t{ value: \"faux\", providerId: \"faux\", label: \"Faux (offline)\", description: \"Deterministic local provider\" },\n\t];\n}\n\nfunction modelsFor(providerId: OnboardingChoice[\"providerId\"]): readonly Model[] {\n\tif (providerId === \"faux\") return [createFauxProvider({ responses: [] }).model];\n\treturn MODELS.filter((model) => model.provider === providerId);\n}\n\nfunction apiKeyEnvironmentVariable(providerId: OnboardingChoice[\"providerId\"]): string | undefined {\n\tif (providerId === \"openai\") return \"OPENAI_API_KEY\";\n\tif (providerId === \"deepseek\") return \"DEEPSEEK_API_KEY\";\n\treturn undefined;\n}\n\nfunction modelChoices(models: readonly Model[]): SelectItem[] {\n\treturn models.map((model) => ({\n\t\tvalue: model.id,\n\t\tlabel: model.name,\n\t\tdescription: `${model.id}${model.reasoning ? \" - reasoning\" : \"\"}`,\n\t}));\n}\n\nfunction onboardingSelectList(items: readonly SelectItem[]): SelectList {\n\treturn new SelectList(items, {\n\t\tkeybindings: new KeybindingsManager({\n\t\t\t\"tui.select.cancel\": [Key.escape, Key.ctrl(\"c\"), Key.ctrl(\"d\")],\n\t\t}),\n\t});\n}\n\nexport function runProviderOnboarding(options: ProviderOnboardingOptions): Promise<StartupRuntime | undefined> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst tui = new TUI(options.terminal);\n\t\tconst screen = new OnboardingScreen();\n\t\tlet settled = false;\n\t\tlet selectedProvider: OnboardingChoice[\"providerId\"] | undefined;\n\n\t\tconst finish = (runtime: StartupRuntime | undefined): void => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tif (runtime === undefined) screen.setCancelled();\n\t\t\ttui.stop({ finalLines: runtime ? [\"Provider configured for this run.\"] : [\"Provider setup cancelled.\"] });\n\t\t\tresolve(runtime);\n\t\t};\n\n\t\tconst fail = (cause: unknown): void => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\ttui.stop({ finalLines: [\"Provider setup failed.\"] });\n\t\t\treject(cause);\n\t\t};\n\n\t\tconst finishSelection = (modelId: string, apiKey?: string): void => {\n\t\t\tif (!selectedProvider) return;\n\t\t\tconst keyVariable = apiKeyEnvironmentVariable(selectedProvider);\n\t\t\tconst environment = {\n\t\t\t\t...options.configuration.environment,\n\t\t\t\tDI_CODE_PROVIDER: selectedProvider,\n\t\t\t\tDI_CODE_MODEL: modelId,\n\t\t\t\t...(keyVariable && apiKey ? { [keyVariable]: apiKey } : {}),\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tfinish(resolveStartupRuntime(environment, options.configuration.providers));\n\t\t\t} catch (cause) {\n\t\t\t\tfail(cause);\n\t\t\t}\n\t\t};\n\n\t\tconst showKey = (modelId: string, keyVariable: string): void => {\n\t\t\tconst input = new Input({ mask: \"*\", cancelOnEndOfTransmission: true });\n\t\t\tinput.onSubmit = (value) => {\n\t\t\t\tconst key = value.trim();\n\t\t\t\tif (key.length === 0) {\n\t\t\t\t\tscreen.setError(\"API key cannot be empty. Press Escape to cancel.\");\n\t\t\t\t\ttui.requestRender(true);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfinishSelection(modelId, key);\n\t\t\t};\n\t\t\tinput.onEscape = () => finish(undefined);\n\t\t\tscreen.setStep(`Enter ${keyVariable} (input is hidden):`, input);\n\t\t\ttui.setFocus(input);\n\t\t\ttui.requestRender(true);\n\t\t};\n\n\t\tconst showModels = (choice: OnboardingChoice): void => {\n\t\t\tselectedProvider = choice.providerId;\n\t\t\tconst models = modelsFor(choice.providerId);\n\t\t\tconst modelList = onboardingSelectList(modelChoices(models));\n\t\t\tmodelList.onSelect = (item) => {\n\t\t\t\tconst keyVariable = apiKeyEnvironmentVariable(choice.providerId);\n\t\t\t\tconst existingKey = keyVariable ? options.configuration.environment[keyVariable]?.trim() : undefined;\n\t\t\t\tif (keyVariable && !existingKey) showKey(item.value, keyVariable);\n\t\t\t\telse finishSelection(item.value);\n\t\t\t};\n\t\t\tmodelList.onCancel = () => finish(undefined);\n\t\t\tscreen.setStep(`Select a ${choice.label} model:`, modelList);\n\t\t\ttui.setFocus(modelList);\n\t\t\ttui.requestRender(true);\n\t\t};\n\n\t\tconst providerList = onboardingSelectList(providerChoices());\n\t\tproviderList.onSelect = (item) => {\n\t\t\tconst choice = providerChoices().find((candidate) => candidate.value === item.value);\n\t\t\tif (choice) showModels(choice);\n\t\t};\n\t\tproviderList.onCancel = () => finish(undefined);\n\t\tscreen.setStep(\"Select a provider:\", providerList);\n\t\ttui.addChild(screen);\n\t\ttui.start();\n\t\ttui.setFocus(providerList);\n\t\ttui.requestRender(true);\n\t});\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Readable, Writable } from "node:stream";
|
|
2
|
+
import type { AssistantMessage } from "@di-code/ai";
|
|
3
|
+
import { type RpcErrorCode, type RpcEventRecord, type RpcSessionState } from "./protocol.ts";
|
|
4
|
+
export interface RpcTransport {
|
|
5
|
+
readonly readable: Readable;
|
|
6
|
+
readonly writable: Writable;
|
|
7
|
+
onExit?(listener: (code: number | null, signal: NodeJS.Signals | null) => void): () => void;
|
|
8
|
+
close?(): void;
|
|
9
|
+
}
|
|
10
|
+
export declare class RpcRemoteError extends Error {
|
|
11
|
+
readonly code: RpcErrorCode;
|
|
12
|
+
constructor(code: RpcErrorCode, message: string);
|
|
13
|
+
}
|
|
14
|
+
export declare class RpcClient {
|
|
15
|
+
private readonly transport;
|
|
16
|
+
private readonly decoder;
|
|
17
|
+
private readonly pending;
|
|
18
|
+
private readonly listeners;
|
|
19
|
+
private readonly removeExitListener?;
|
|
20
|
+
private closed;
|
|
21
|
+
constructor(transport: RpcTransport);
|
|
22
|
+
subscribe(listener: (event: RpcEventRecord) => void): () => void;
|
|
23
|
+
getState(): Promise<RpcSessionState>;
|
|
24
|
+
prompt(message: string, options?: {
|
|
25
|
+
readonly signal?: AbortSignal;
|
|
26
|
+
}): Promise<AssistantMessage>;
|
|
27
|
+
cancel(requestId: string): Promise<boolean>;
|
|
28
|
+
close(): void;
|
|
29
|
+
private request;
|
|
30
|
+
private readonly handleData;
|
|
31
|
+
private readonly handleEnd;
|
|
32
|
+
private readonly handleError;
|
|
33
|
+
private acceptLine;
|
|
34
|
+
private fail;
|
|
35
|
+
private rejectPending;
|
|
36
|
+
private detach;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/rpc/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,EAGN,KAAK,YAAY,EACjB,KAAK,cAAc,EAGnB,KAAK,eAAe,EAEpB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5F,KAAK,CAAC,IAAI,IAAI,CAAC;CACf;AAQD,qBAAa,cAAe,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;gBAEhB,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM;CAK/C;AAED,qBAAa,SAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8C;IACxE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAa;IACjD,OAAO,CAAC,MAAM,CAAS;gBAEX,SAAS,EAAE,YAAY;IAYnC,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI;IAK1D,QAAQ,IAAI,OAAO,CAAC,eAAe,CAAC;IAMpC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAiBnG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMjD,KAAK,IAAI,IAAI;IAQb,OAAO,CAAC,OAAO;IAoBf,OAAO,CAAC,QAAQ,CAAC,UAAU,CAMzB;IAEF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAQxB;IAEF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA4C;IAExE,OAAO,CAAC,UAAU;IAyBlB,OAAO,CAAC,IAAI;IAOZ,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,MAAM;CAOd"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { JsonlLineDecoder, serializeJsonLine } from "./jsonl.js";
|
|
3
|
+
import { parseRpcServerMessage, RPC_PROTOCOL_VERSION, } from "./protocol.js";
|
|
4
|
+
export class RpcRemoteError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
constructor(code, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "RpcRemoteError";
|
|
9
|
+
this.code = code;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class RpcClient {
|
|
13
|
+
transport;
|
|
14
|
+
decoder;
|
|
15
|
+
pending = new Map();
|
|
16
|
+
listeners = new Set();
|
|
17
|
+
removeExitListener;
|
|
18
|
+
closed = false;
|
|
19
|
+
constructor(transport) {
|
|
20
|
+
this.transport = transport;
|
|
21
|
+
this.decoder = new JsonlLineDecoder((line) => this.acceptLine(line));
|
|
22
|
+
transport.readable.on("data", this.handleData);
|
|
23
|
+
transport.readable.once("end", this.handleEnd);
|
|
24
|
+
transport.readable.once("error", this.handleError);
|
|
25
|
+
transport.writable.once("error", this.handleError);
|
|
26
|
+
this.removeExitListener = transport.onExit?.((code, signal) => {
|
|
27
|
+
this.fail(new RpcRemoteError("PROCESS_EXIT", `RPC process exited (code=${code} signal=${signal})`));
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
subscribe(listener) {
|
|
31
|
+
this.listeners.add(listener);
|
|
32
|
+
return () => this.listeners.delete(listener);
|
|
33
|
+
}
|
|
34
|
+
async getState() {
|
|
35
|
+
const result = await this.request("get_state", {});
|
|
36
|
+
if (result.method !== "get_state")
|
|
37
|
+
throw new Error("RPC get_state returned an incompatible result.");
|
|
38
|
+
return result.state;
|
|
39
|
+
}
|
|
40
|
+
async prompt(message, options = {}) {
|
|
41
|
+
const requestId = randomUUID();
|
|
42
|
+
const onAbort = () => {
|
|
43
|
+
void this.cancel(requestId).catch(() => undefined);
|
|
44
|
+
};
|
|
45
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
46
|
+
try {
|
|
47
|
+
const response = this.request("prompt", { message }, requestId);
|
|
48
|
+
if (options.signal?.aborted)
|
|
49
|
+
onAbort();
|
|
50
|
+
const result = await response;
|
|
51
|
+
if (result.method !== "prompt")
|
|
52
|
+
throw new Error("RPC prompt returned an incompatible result.");
|
|
53
|
+
return result.message;
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async cancel(requestId) {
|
|
60
|
+
const result = await this.request("cancel", { requestId });
|
|
61
|
+
if (result.method !== "cancel")
|
|
62
|
+
throw new Error("RPC cancel returned an incompatible result.");
|
|
63
|
+
return result.cancelled;
|
|
64
|
+
}
|
|
65
|
+
close() {
|
|
66
|
+
if (this.closed)
|
|
67
|
+
return;
|
|
68
|
+
this.closed = true;
|
|
69
|
+
this.detach();
|
|
70
|
+
this.transport.close?.();
|
|
71
|
+
this.rejectPending(new Error("RPC client is closed."));
|
|
72
|
+
}
|
|
73
|
+
request(method, params, id = randomUUID()) {
|
|
74
|
+
if (this.closed)
|
|
75
|
+
return Promise.reject(new Error("RPC client is closed."));
|
|
76
|
+
const request = { version: RPC_PROTOCOL_VERSION, kind: "request", id, method, params };
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
this.pending.set(id, { method, resolve, reject });
|
|
79
|
+
this.transport.writable.write(serializeJsonLine(request), (error) => {
|
|
80
|
+
if (!error)
|
|
81
|
+
return;
|
|
82
|
+
this.pending.delete(id);
|
|
83
|
+
reject(error);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
handleData = (chunk) => {
|
|
88
|
+
try {
|
|
89
|
+
this.decoder.push(chunk);
|
|
90
|
+
}
|
|
91
|
+
catch (cause) {
|
|
92
|
+
this.fail(cause instanceof Error ? cause : new Error(String(cause)));
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
handleEnd = () => {
|
|
96
|
+
try {
|
|
97
|
+
this.decoder.end();
|
|
98
|
+
}
|
|
99
|
+
catch (cause) {
|
|
100
|
+
this.fail(cause instanceof Error ? cause : new Error(String(cause)));
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
this.fail(new Error("RPC output ended before the client was closed."));
|
|
104
|
+
};
|
|
105
|
+
handleError = (error) => this.fail(error);
|
|
106
|
+
acceptLine(line) {
|
|
107
|
+
const message = parseRpcServerMessage(line);
|
|
108
|
+
if (message.kind === "event") {
|
|
109
|
+
for (const listener of this.listeners)
|
|
110
|
+
listener(structuredClone(message));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (!message.ok && message.id === undefined) {
|
|
114
|
+
this.fail(new Error(`${message.error.code}: ${message.error.message}`));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (message.id === undefined)
|
|
118
|
+
return;
|
|
119
|
+
const pending = this.pending.get(message.id);
|
|
120
|
+
if (!pending)
|
|
121
|
+
return;
|
|
122
|
+
this.pending.delete(message.id);
|
|
123
|
+
if (!message.ok) {
|
|
124
|
+
pending.reject(new RpcRemoteError(message.error.code, message.error.message));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (message.result.method !== pending.method) {
|
|
128
|
+
pending.reject(new Error(`RPC response method mismatch: expected ${pending.method}.`));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
pending.resolve(message.result);
|
|
132
|
+
}
|
|
133
|
+
fail(error) {
|
|
134
|
+
if (this.closed)
|
|
135
|
+
return;
|
|
136
|
+
this.closed = true;
|
|
137
|
+
this.detach();
|
|
138
|
+
this.rejectPending(error);
|
|
139
|
+
}
|
|
140
|
+
rejectPending(error) {
|
|
141
|
+
for (const pending of this.pending.values())
|
|
142
|
+
pending.reject(error);
|
|
143
|
+
this.pending.clear();
|
|
144
|
+
}
|
|
145
|
+
detach() {
|
|
146
|
+
this.transport.readable.off("data", this.handleData);
|
|
147
|
+
this.transport.readable.off("end", this.handleEnd);
|
|
148
|
+
this.transport.readable.off("error", this.handleError);
|
|
149
|
+
this.transport.writable.off("error", this.handleError);
|
|
150
|
+
this.removeExitListener?.();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/rpc/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { Readable, Writable } from \"node:stream\";\nimport type { AssistantMessage } from \"@di-code/ai\";\nimport { JsonlLineDecoder, serializeJsonLine } from \"./jsonl.ts\";\nimport {\n\tparseRpcServerMessage,\n\tRPC_PROTOCOL_VERSION,\n\ttype RpcErrorCode,\n\ttype RpcEventRecord,\n\ttype RpcMethod,\n\ttype RpcRequest,\n\ttype RpcSessionState,\n\ttype RpcSuccessResult,\n} from \"./protocol.ts\";\n\nexport interface RpcTransport {\n\treadonly readable: Readable;\n\treadonly writable: Writable;\n\tonExit?(listener: (code: number | null, signal: NodeJS.Signals | null) => void): () => void;\n\tclose?(): void;\n}\n\ninterface PendingRequest {\n\treadonly method: RpcMethod;\n\treadonly resolve: (result: RpcSuccessResult) => void;\n\treadonly reject: (error: Error) => void;\n}\n\nexport class RpcRemoteError extends Error {\n\treadonly code: RpcErrorCode;\n\n\tconstructor(code: RpcErrorCode, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"RpcRemoteError\";\n\t\tthis.code = code;\n\t}\n}\n\nexport class RpcClient {\n\tprivate readonly transport: RpcTransport;\n\tprivate readonly decoder: JsonlLineDecoder;\n\tprivate readonly pending = new Map<string, PendingRequest>();\n\tprivate readonly listeners = new Set<(event: RpcEventRecord) => void>();\n\tprivate readonly removeExitListener?: () => void;\n\tprivate closed = false;\n\n\tconstructor(transport: RpcTransport) {\n\t\tthis.transport = transport;\n\t\tthis.decoder = new JsonlLineDecoder((line) => this.acceptLine(line));\n\t\ttransport.readable.on(\"data\", this.handleData);\n\t\ttransport.readable.once(\"end\", this.handleEnd);\n\t\ttransport.readable.once(\"error\", this.handleError);\n\t\ttransport.writable.once(\"error\", this.handleError);\n\t\tthis.removeExitListener = transport.onExit?.((code, signal) => {\n\t\t\tthis.fail(new RpcRemoteError(\"PROCESS_EXIT\", `RPC process exited (code=${code} signal=${signal})`));\n\t\t});\n\t}\n\n\tsubscribe(listener: (event: RpcEventRecord) => void): () => void {\n\t\tthis.listeners.add(listener);\n\t\treturn () => this.listeners.delete(listener);\n\t}\n\n\tasync getState(): Promise<RpcSessionState> {\n\t\tconst result = await this.request(\"get_state\", {});\n\t\tif (result.method !== \"get_state\") throw new Error(\"RPC get_state returned an incompatible result.\");\n\t\treturn result.state;\n\t}\n\n\tasync prompt(message: string, options: { readonly signal?: AbortSignal } = {}): Promise<AssistantMessage> {\n\t\tconst requestId = randomUUID();\n\t\tconst onAbort = () => {\n\t\t\tvoid this.cancel(requestId).catch(() => undefined);\n\t\t};\n\t\toptions.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\ttry {\n\t\t\tconst response = this.request(\"prompt\", { message }, requestId);\n\t\t\tif (options.signal?.aborted) onAbort();\n\t\t\tconst result = await response;\n\t\t\tif (result.method !== \"prompt\") throw new Error(\"RPC prompt returned an incompatible result.\");\n\t\t\treturn result.message;\n\t\t} finally {\n\t\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\t}\n\t}\n\n\tasync cancel(requestId: string): Promise<boolean> {\n\t\tconst result = await this.request(\"cancel\", { requestId });\n\t\tif (result.method !== \"cancel\") throw new Error(\"RPC cancel returned an incompatible result.\");\n\t\treturn result.cancelled;\n\t}\n\n\tclose(): void {\n\t\tif (this.closed) return;\n\t\tthis.closed = true;\n\t\tthis.detach();\n\t\tthis.transport.close?.();\n\t\tthis.rejectPending(new Error(\"RPC client is closed.\"));\n\t}\n\n\tprivate request(method: \"prompt\", params: { readonly message: string }, id?: string): Promise<RpcSuccessResult>;\n\tprivate request(method: \"cancel\", params: { readonly requestId: string }, id?: string): Promise<RpcSuccessResult>;\n\tprivate request(method: \"get_state\", params: Record<string, never>, id?: string): Promise<RpcSuccessResult>;\n\tprivate request(\n\t\tmethod: RpcMethod,\n\t\tparams: { readonly message: string } | { readonly requestId: string } | Record<string, never>,\n\t\tid = randomUUID(),\n\t): Promise<RpcSuccessResult> {\n\t\tif (this.closed) return Promise.reject(new Error(\"RPC client is closed.\"));\n\t\tconst request = { version: RPC_PROTOCOL_VERSION, kind: \"request\", id, method, params } as RpcRequest;\n\t\treturn new Promise<RpcSuccessResult>((resolve, reject) => {\n\t\t\tthis.pending.set(id, { method, resolve, reject });\n\t\t\tthis.transport.writable.write(serializeJsonLine(request), (error) => {\n\t\t\t\tif (!error) return;\n\t\t\t\tthis.pending.delete(id);\n\t\t\t\treject(error);\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate readonly handleData = (chunk: string | Buffer): void => {\n\t\ttry {\n\t\t\tthis.decoder.push(chunk);\n\t\t} catch (cause) {\n\t\t\tthis.fail(cause instanceof Error ? cause : new Error(String(cause)));\n\t\t}\n\t};\n\n\tprivate readonly handleEnd = (): void => {\n\t\ttry {\n\t\t\tthis.decoder.end();\n\t\t} catch (cause) {\n\t\t\tthis.fail(cause instanceof Error ? cause : new Error(String(cause)));\n\t\t\treturn;\n\t\t}\n\t\tthis.fail(new Error(\"RPC output ended before the client was closed.\"));\n\t};\n\n\tprivate readonly handleError = (error: Error): void => this.fail(error);\n\n\tprivate acceptLine(line: string): void {\n\t\tconst message = parseRpcServerMessage(line);\n\t\tif (message.kind === \"event\") {\n\t\t\tfor (const listener of this.listeners) listener(structuredClone(message));\n\t\t\treturn;\n\t\t}\n\t\tif (!message.ok && message.id === undefined) {\n\t\t\tthis.fail(new Error(`${message.error.code}: ${message.error.message}`));\n\t\t\treturn;\n\t\t}\n\t\tif (message.id === undefined) return;\n\t\tconst pending = this.pending.get(message.id);\n\t\tif (!pending) return;\n\t\tthis.pending.delete(message.id);\n\t\tif (!message.ok) {\n\t\t\tpending.reject(new RpcRemoteError(message.error.code, message.error.message));\n\t\t\treturn;\n\t\t}\n\t\tif (message.result.method !== pending.method) {\n\t\t\tpending.reject(new Error(`RPC response method mismatch: expected ${pending.method}.`));\n\t\t\treturn;\n\t\t}\n\t\tpending.resolve(message.result);\n\t}\n\n\tprivate fail(error: Error): void {\n\t\tif (this.closed) return;\n\t\tthis.closed = true;\n\t\tthis.detach();\n\t\tthis.rejectPending(error);\n\t}\n\n\tprivate rejectPending(error: Error): void {\n\t\tfor (const pending of this.pending.values()) pending.reject(error);\n\t\tthis.pending.clear();\n\t}\n\n\tprivate detach(): void {\n\t\tthis.transport.readable.off(\"data\", this.handleData);\n\t\tthis.transport.readable.off(\"end\", this.handleEnd);\n\t\tthis.transport.readable.off(\"error\", this.handleError);\n\t\tthis.transport.writable.off(\"error\", this.handleError);\n\t\tthis.removeExitListener?.();\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rpc/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rpc/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC","sourcesContent":["export * from \"./client.ts\";\nexport * from \"./jsonl.ts\";\nexport * from \"./protocol.ts\";\nexport * from \"./server.ts\";\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const DEFAULT_RPC_MAX_LINE_BYTES = 1048576;
|
|
2
|
+
export declare function serializeJsonLine(value: unknown): string;
|
|
3
|
+
export declare class JsonlLineDecoder {
|
|
4
|
+
private buffer;
|
|
5
|
+
private readonly decoder;
|
|
6
|
+
private readonly maxLineBytes;
|
|
7
|
+
private readonly onLine;
|
|
8
|
+
constructor(onLine: (line: string) => void, options?: {
|
|
9
|
+
readonly maxLineBytes?: number;
|
|
10
|
+
});
|
|
11
|
+
push(chunk: string | Uint8Array): void;
|
|
12
|
+
end(): void;
|
|
13
|
+
private emitCompleteLines;
|
|
14
|
+
private emit;
|
|
15
|
+
private assertLineLimit;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=jsonl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../../src/rpc/jsonl.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,0BAA0B,UAAY,CAAC;AAEpD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAExD;AAED,qBAAa,gBAAgB;IAC5B,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;gBAEpC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,GAAE;QAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO;IAQ5F,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAMtC,GAAG,IAAI,IAAI;IASX,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,eAAe;CAKvB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { StringDecoder } from "node:string_decoder";
|
|
2
|
+
export const DEFAULT_RPC_MAX_LINE_BYTES = 1_048_576;
|
|
3
|
+
export function serializeJsonLine(value) {
|
|
4
|
+
return `${JSON.stringify(value)}\n`;
|
|
5
|
+
}
|
|
6
|
+
export class JsonlLineDecoder {
|
|
7
|
+
buffer = "";
|
|
8
|
+
decoder = new StringDecoder("utf8");
|
|
9
|
+
maxLineBytes;
|
|
10
|
+
onLine;
|
|
11
|
+
constructor(onLine, options = {}) {
|
|
12
|
+
this.onLine = onLine;
|
|
13
|
+
this.maxLineBytes = options.maxLineBytes ?? DEFAULT_RPC_MAX_LINE_BYTES;
|
|
14
|
+
if (!Number.isInteger(this.maxLineBytes) || this.maxLineBytes <= 0) {
|
|
15
|
+
throw new RangeError("maxLineBytes must be a positive integer");
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
push(chunk) {
|
|
19
|
+
this.buffer += typeof chunk === "string" ? chunk : this.decoder.write(Buffer.from(chunk));
|
|
20
|
+
this.emitCompleteLines();
|
|
21
|
+
this.assertLineLimit(this.buffer);
|
|
22
|
+
}
|
|
23
|
+
end() {
|
|
24
|
+
this.buffer += this.decoder.end();
|
|
25
|
+
this.emitCompleteLines();
|
|
26
|
+
if (this.buffer.length === 0)
|
|
27
|
+
return;
|
|
28
|
+
this.assertLineLimit(this.buffer);
|
|
29
|
+
this.emit(this.buffer);
|
|
30
|
+
this.buffer = "";
|
|
31
|
+
}
|
|
32
|
+
emitCompleteLines() {
|
|
33
|
+
while (true) {
|
|
34
|
+
const newlineIndex = this.buffer.indexOf("\n");
|
|
35
|
+
if (newlineIndex === -1)
|
|
36
|
+
return;
|
|
37
|
+
const line = this.buffer.slice(0, newlineIndex);
|
|
38
|
+
this.assertLineLimit(line);
|
|
39
|
+
this.emit(line);
|
|
40
|
+
this.buffer = this.buffer.slice(newlineIndex + 1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
emit(line) {
|
|
44
|
+
this.onLine(line.endsWith("\r") ? line.slice(0, -1) : line);
|
|
45
|
+
}
|
|
46
|
+
assertLineLimit(line) {
|
|
47
|
+
if (Buffer.byteLength(line, "utf8") > this.maxLineBytes) {
|
|
48
|
+
throw new RangeError(`RPC JSONL line exceeds ${this.maxLineBytes} bytes`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=jsonl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonl.js","sourceRoot":"","sources":["../../src/rpc/jsonl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,CAAC,MAAM,0BAA0B,GAAG,SAAS,CAAC;AAEpD,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC/C,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;AACrC,CAAC;AAED,MAAM,OAAO,gBAAgB;IACpB,MAAM,GAAG,EAAE,CAAC;IACH,OAAO,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IACpC,YAAY,CAAS;IACrB,MAAM,CAAyB;IAEhD,YAAY,MAA8B,EAAE,UAA8C,EAAE;QAC3F,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,0BAA0B,CAAC;QACvE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC;YACpE,MAAM,IAAI,UAAU,CAAC,yCAAyC,CAAC,CAAC;QACjE,CAAC;IACF,CAAC;IAED,IAAI,CAAC,KAA0B;QAC9B,IAAI,CAAC,MAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1F,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,GAAG;QACF,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAClC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACrC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IAClB,CAAC;IAEO,iBAAiB;QACxB,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC/C,IAAI,YAAY,KAAK,CAAC,CAAC;gBAAE,OAAO;YAChC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;YAChD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;QACnD,CAAC;IACF,CAAC;IAEO,IAAI,CAAC,IAAY;QACxB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;IAEO,eAAe,CAAC,IAAY;QACnC,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;YACzD,MAAM,IAAI,UAAU,CAAC,0BAA0B,IAAI,CAAC,YAAY,QAAQ,CAAC,CAAC;QAC3E,CAAC;IACF,CAAC;CACD","sourcesContent":["import { StringDecoder } from \"node:string_decoder\";\n\nexport const DEFAULT_RPC_MAX_LINE_BYTES = 1_048_576;\n\nexport function serializeJsonLine(value: unknown): string {\n\treturn `${JSON.stringify(value)}\\n`;\n}\n\nexport class JsonlLineDecoder {\n\tprivate buffer = \"\";\n\tprivate readonly decoder = new StringDecoder(\"utf8\");\n\tprivate readonly maxLineBytes: number;\n\tprivate readonly onLine: (line: string) => void;\n\n\tconstructor(onLine: (line: string) => void, options: { readonly maxLineBytes?: number } = {}) {\n\t\tthis.onLine = onLine;\n\t\tthis.maxLineBytes = options.maxLineBytes ?? DEFAULT_RPC_MAX_LINE_BYTES;\n\t\tif (!Number.isInteger(this.maxLineBytes) || this.maxLineBytes <= 0) {\n\t\t\tthrow new RangeError(\"maxLineBytes must be a positive integer\");\n\t\t}\n\t}\n\n\tpush(chunk: string | Uint8Array): void {\n\t\tthis.buffer += typeof chunk === \"string\" ? chunk : this.decoder.write(Buffer.from(chunk));\n\t\tthis.emitCompleteLines();\n\t\tthis.assertLineLimit(this.buffer);\n\t}\n\n\tend(): void {\n\t\tthis.buffer += this.decoder.end();\n\t\tthis.emitCompleteLines();\n\t\tif (this.buffer.length === 0) return;\n\t\tthis.assertLineLimit(this.buffer);\n\t\tthis.emit(this.buffer);\n\t\tthis.buffer = \"\";\n\t}\n\n\tprivate emitCompleteLines(): void {\n\t\twhile (true) {\n\t\t\tconst newlineIndex = this.buffer.indexOf(\"\\n\");\n\t\t\tif (newlineIndex === -1) return;\n\t\t\tconst line = this.buffer.slice(0, newlineIndex);\n\t\t\tthis.assertLineLimit(line);\n\t\t\tthis.emit(line);\n\t\t\tthis.buffer = this.buffer.slice(newlineIndex + 1);\n\t\t}\n\t}\n\n\tprivate emit(line: string): void {\n\t\tthis.onLine(line.endsWith(\"\\r\") ? line.slice(0, -1) : line);\n\t}\n\n\tprivate assertLineLimit(line: string): void {\n\t\tif (Buffer.byteLength(line, \"utf8\") > this.maxLineBytes) {\n\t\t\tthrow new RangeError(`RPC JSONL line exceeds ${this.maxLineBytes} bytes`);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { AssistantMessage } from "@di-code/ai";
|
|
2
|
+
import type { AgentSessionEvent } from "../core/session.ts";
|
|
3
|
+
export declare const RPC_PROTOCOL_VERSION: 1;
|
|
4
|
+
export declare const RPC_MAX_ID_LENGTH = 128;
|
|
5
|
+
export declare const RPC_MAX_PROMPT_LENGTH = 1000000;
|
|
6
|
+
export type RpcMethod = "prompt" | "cancel" | "get_state";
|
|
7
|
+
export type RpcRequest = {
|
|
8
|
+
readonly version: typeof RPC_PROTOCOL_VERSION;
|
|
9
|
+
readonly kind: "request";
|
|
10
|
+
readonly id: string;
|
|
11
|
+
readonly method: "prompt";
|
|
12
|
+
readonly params: {
|
|
13
|
+
readonly message: string;
|
|
14
|
+
};
|
|
15
|
+
} | {
|
|
16
|
+
readonly version: typeof RPC_PROTOCOL_VERSION;
|
|
17
|
+
readonly kind: "request";
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly method: "cancel";
|
|
20
|
+
readonly params: {
|
|
21
|
+
readonly requestId: string;
|
|
22
|
+
};
|
|
23
|
+
} | {
|
|
24
|
+
readonly version: typeof RPC_PROTOCOL_VERSION;
|
|
25
|
+
readonly kind: "request";
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly method: "get_state";
|
|
28
|
+
readonly params: Record<string, never>;
|
|
29
|
+
};
|
|
30
|
+
export interface RpcSessionState {
|
|
31
|
+
readonly sessionId: string;
|
|
32
|
+
readonly modelId: string;
|
|
33
|
+
readonly isStreaming: boolean;
|
|
34
|
+
readonly messageCount: number;
|
|
35
|
+
}
|
|
36
|
+
export type RpcSuccessResult = {
|
|
37
|
+
readonly method: "prompt";
|
|
38
|
+
readonly message: AssistantMessage;
|
|
39
|
+
} | {
|
|
40
|
+
readonly method: "cancel";
|
|
41
|
+
readonly cancelled: boolean;
|
|
42
|
+
} | {
|
|
43
|
+
readonly method: "get_state";
|
|
44
|
+
readonly state: RpcSessionState;
|
|
45
|
+
};
|
|
46
|
+
export type RpcErrorCode = "PARSE_ERROR" | "INVALID_REQUEST" | "UNSUPPORTED_VERSION" | "METHOD_NOT_FOUND" | "INVALID_PARAMS" | "BUSY" | "NOT_FOUND" | "CANCELLED" | "INTERNAL_ERROR" | "PROCESS_EXIT";
|
|
47
|
+
export interface RpcSuccessResponse {
|
|
48
|
+
readonly version: typeof RPC_PROTOCOL_VERSION;
|
|
49
|
+
readonly kind: "response";
|
|
50
|
+
readonly id: string;
|
|
51
|
+
readonly ok: true;
|
|
52
|
+
readonly result: RpcSuccessResult;
|
|
53
|
+
}
|
|
54
|
+
export interface RpcErrorResponse {
|
|
55
|
+
readonly version: typeof RPC_PROTOCOL_VERSION;
|
|
56
|
+
readonly kind: "response";
|
|
57
|
+
readonly id?: string;
|
|
58
|
+
readonly ok: false;
|
|
59
|
+
readonly error: {
|
|
60
|
+
readonly code: RpcErrorCode;
|
|
61
|
+
readonly message: string;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export interface RpcEventRecord {
|
|
65
|
+
readonly version: typeof RPC_PROTOCOL_VERSION;
|
|
66
|
+
readonly kind: "event";
|
|
67
|
+
readonly requestId: string;
|
|
68
|
+
readonly event: AgentSessionEvent;
|
|
69
|
+
}
|
|
70
|
+
export type RpcResponse = RpcSuccessResponse | RpcErrorResponse;
|
|
71
|
+
export type RpcServerMessage = RpcResponse | RpcEventRecord;
|
|
72
|
+
export declare class RpcProtocolError extends Error {
|
|
73
|
+
readonly code: RpcErrorCode;
|
|
74
|
+
readonly requestId?: string;
|
|
75
|
+
constructor(code: RpcErrorCode, message: string, requestId?: string);
|
|
76
|
+
}
|
|
77
|
+
export declare function parseRpcRequest(line: string): RpcRequest;
|
|
78
|
+
export declare function parseRpcServerMessage(line: string): RpcServerMessage;
|
|
79
|
+
export declare function rpcErrorResponse(error: RpcProtocolError): RpcErrorResponse;
|
|
80
|
+
//# sourceMappingURL=protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/rpc/protocol.ts"],"names":[],"mappings":"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"}
|