t3code-cli 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +2 -2
- package/dist/index.js +1 -1
- package/dist/{runtime-DU_hs0MM.js → runtime-CMPZpQaG.js} +9930 -2845
- package/package.json +4 -2
- package/src/application/model-selection.ts +13 -15
- package/src/application/models.ts +1 -1
- package/src/application/project-commands.ts +6 -4
- package/src/application/service.ts +26 -22
- package/src/application/shell-sequence.ts +1 -1
- package/src/application/thread-commands.ts +32 -22
- package/src/application/thread-wait.ts +4 -4
- package/src/auth/error.ts +5 -1
- package/src/auth/pairing.ts +6 -2
- package/src/auth/transport.ts +21 -10
- package/src/cli/model-format.ts +1 -1
- package/src/cli/project-format.ts +3 -3
- package/src/cli/thread-format.ts +6 -6
- package/src/config/url.ts +46 -2
- package/src/domain/helpers.ts +11 -3
- package/src/domain/model-config.ts +1 -1
- package/src/domain/thread-lifecycle.ts +24 -30
- package/src/index.ts +6 -6
- package/src/orchestration/layer.ts +41 -48
- package/src/orchestration/service.ts +20 -11
- package/src/rpc/error.ts +12 -0
- package/src/rpc/layer.ts +4 -4
- package/src/rpc/service.ts +2 -3
- package/src/rpc/ws-group.ts +43 -0
- package/src/domain/command-schema.ts +0 -82
- package/src/domain/schema.ts +0 -162
- package/src/protocol/schema.ts +0 -105
|
@@ -1,19 +1,13 @@
|
|
|
1
|
-
import * as Schema from "effect/Schema";
|
|
2
|
-
|
|
3
1
|
import {
|
|
4
|
-
|
|
5
|
-
type
|
|
6
|
-
type
|
|
7
|
-
type
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from "./schema.ts";
|
|
12
|
-
|
|
13
|
-
const isThreadMessageSentEvent = Schema.is(ThreadMessageSentEventSchema);
|
|
14
|
-
const isThreadSessionSetEvent = Schema.is(ThreadSessionSetEventSchema);
|
|
2
|
+
OrchestrationMessage,
|
|
3
|
+
type OrchestrationEvent,
|
|
4
|
+
type OrchestrationMessage as OrchestrationMessageType,
|
|
5
|
+
type OrchestrationThread,
|
|
6
|
+
type OrchestrationThreadShell,
|
|
7
|
+
} from "@t3tools/contracts";
|
|
8
|
+
import * as Schema from "effect/Schema";
|
|
15
9
|
|
|
16
|
-
export function isThreadActive(thread:
|
|
10
|
+
export function isThreadActive(thread: OrchestrationThreadShell | OrchestrationThread) {
|
|
17
11
|
return (
|
|
18
12
|
thread.session?.status === "starting" ||
|
|
19
13
|
thread.session?.status === "running" ||
|
|
@@ -22,18 +16,18 @@ export function isThreadActive(thread: ThreadShell | ThreadDetail) {
|
|
|
22
16
|
);
|
|
23
17
|
}
|
|
24
18
|
|
|
25
|
-
export function threadStatus(thread:
|
|
19
|
+
export function threadStatus(thread: OrchestrationThreadShell | OrchestrationThread) {
|
|
26
20
|
if (isPendingStart(thread)) {
|
|
27
21
|
return "pending";
|
|
28
22
|
}
|
|
29
23
|
return thread.session?.status ?? thread.latestTurn?.state ?? "unknown";
|
|
30
24
|
}
|
|
31
25
|
|
|
32
|
-
export function latestAssistantMessage(thread:
|
|
26
|
+
export function latestAssistantMessage(thread: OrchestrationThread) {
|
|
33
27
|
return thread.messages.toReversed().find((message) => message.role === "assistant");
|
|
34
28
|
}
|
|
35
29
|
|
|
36
|
-
export function isThreadCompleteEnough(thread:
|
|
30
|
+
export function isThreadCompleteEnough(thread: OrchestrationThread) {
|
|
37
31
|
if (thread.session?.status === "error" || thread.session?.status === "interrupted") {
|
|
38
32
|
return true;
|
|
39
33
|
}
|
|
@@ -45,16 +39,16 @@ export function isThreadCompleteEnough(thread: ThreadDetail) {
|
|
|
45
39
|
}
|
|
46
40
|
|
|
47
41
|
export function applyThreadEvent(
|
|
48
|
-
current:
|
|
49
|
-
event:
|
|
50
|
-
messages: Map<string,
|
|
42
|
+
current: OrchestrationThread,
|
|
43
|
+
event: OrchestrationEvent,
|
|
44
|
+
messages: Map<string, OrchestrationMessageType>,
|
|
51
45
|
) {
|
|
52
46
|
const message = messageFromEvent(event, messages);
|
|
53
47
|
if (message !== null) {
|
|
54
48
|
messages.set(messageKey(message), message);
|
|
55
49
|
return { ...current, messages: [...messages.values()] };
|
|
56
50
|
}
|
|
57
|
-
if (
|
|
51
|
+
if (event.type === "thread.session-set") {
|
|
58
52
|
return {
|
|
59
53
|
...current,
|
|
60
54
|
session: event.payload.session,
|
|
@@ -64,32 +58,32 @@ export function applyThreadEvent(
|
|
|
64
58
|
}
|
|
65
59
|
|
|
66
60
|
export function messageFromEvent(
|
|
67
|
-
event:
|
|
68
|
-
existingMessages: Map<string,
|
|
69
|
-
):
|
|
70
|
-
if (
|
|
61
|
+
event: OrchestrationEvent,
|
|
62
|
+
existingMessages: Map<string, OrchestrationMessageType> = new Map(),
|
|
63
|
+
): OrchestrationMessageType | null {
|
|
64
|
+
if (event.type !== "thread.message-sent") {
|
|
71
65
|
return null;
|
|
72
66
|
}
|
|
73
67
|
const payload = event.payload;
|
|
74
68
|
const id = payload.messageId;
|
|
75
69
|
const previous = existingMessages.get(id);
|
|
76
70
|
const text = payload.text;
|
|
77
|
-
return Schema.decodeUnknownSync(
|
|
71
|
+
return Schema.decodeUnknownSync(OrchestrationMessage)({
|
|
78
72
|
id,
|
|
79
73
|
role: payload.role,
|
|
80
74
|
text: text.length > 0 || previous === undefined ? text : previous.text,
|
|
81
75
|
turnId: payload.turnId,
|
|
82
|
-
|
|
76
|
+
streaming: payload.streaming,
|
|
83
77
|
createdAt: payload.createdAt,
|
|
84
78
|
updatedAt: payload.updatedAt,
|
|
85
79
|
});
|
|
86
80
|
}
|
|
87
81
|
|
|
88
|
-
export function messageKey(message:
|
|
89
|
-
return message.id
|
|
82
|
+
export function messageKey(message: OrchestrationMessageType) {
|
|
83
|
+
return message.id;
|
|
90
84
|
}
|
|
91
85
|
|
|
92
|
-
function isPendingStart(thread:
|
|
86
|
+
function isPendingStart(thread: OrchestrationThreadShell | OrchestrationThread) {
|
|
93
87
|
if (thread.session !== null || thread.latestTurn !== null || !("messages" in thread)) {
|
|
94
88
|
return false;
|
|
95
89
|
}
|
package/src/index.ts
CHANGED
|
@@ -7,12 +7,12 @@ export type {
|
|
|
7
7
|
} from "./application/service.ts";
|
|
8
8
|
export type { ApplicationError } from "./application/error.ts";
|
|
9
9
|
export type {
|
|
10
|
-
|
|
10
|
+
OrchestrationMessage,
|
|
11
|
+
OrchestrationProjectShell,
|
|
12
|
+
OrchestrationShellSnapshot,
|
|
13
|
+
OrchestrationThread,
|
|
14
|
+
OrchestrationThreadShell,
|
|
11
15
|
ServerProvider,
|
|
12
|
-
|
|
13
|
-
ThreadDetail,
|
|
14
|
-
ThreadMessage,
|
|
15
|
-
ThreadShell,
|
|
16
|
-
} from "./domain/schema.ts";
|
|
16
|
+
} from "@t3tools/contracts";
|
|
17
17
|
export { NodeEnvironmentLive } from "./environment/layer.ts";
|
|
18
18
|
export { AppLayer, AuthAppLayer } from "./runtime.ts";
|
|
@@ -4,34 +4,35 @@ import * as Option from "effect/Option";
|
|
|
4
4
|
import * as Schedule from "effect/Schedule";
|
|
5
5
|
import * as Sink from "effect/Sink";
|
|
6
6
|
import * as Stream from "effect/Stream";
|
|
7
|
-
import { RpcClientError } from "effect/unstable/rpc";
|
|
8
|
-
|
|
9
|
-
import { type ClientOrchestrationCommand } from "../domain/command-schema.ts";
|
|
10
7
|
import {
|
|
11
8
|
ORCHESTRATION_WS_METHODS,
|
|
12
|
-
|
|
13
|
-
type ThreadStreamItem,
|
|
9
|
+
ThreadId,
|
|
14
10
|
WS_METHODS,
|
|
15
|
-
|
|
11
|
+
type ClientOrchestrationCommand,
|
|
12
|
+
type OrchestrationShellStreamItem,
|
|
13
|
+
type OrchestrationThreadStreamItem,
|
|
14
|
+
} from "@t3tools/contracts";
|
|
15
|
+
import { RpcClientError } from "effect/unstable/rpc";
|
|
16
|
+
|
|
16
17
|
import { RpcError } from "../rpc/error.ts";
|
|
17
18
|
import { T3Rpc, type WsClient } from "../rpc/service.ts";
|
|
19
|
+
import type { CliRpcRequestError } from "../rpc/ws-group.ts";
|
|
18
20
|
import { T3Orchestration, type OpenThread } from "./service.ts";
|
|
19
21
|
|
|
20
|
-
type
|
|
22
|
+
type RpcRequestError = RpcClientError.RpcClientError | CliRpcRequestError;
|
|
21
23
|
|
|
22
24
|
const rpcRetrySchedule = Schedule.exponential("100 millis").pipe(
|
|
23
25
|
Schedule.take(4),
|
|
24
26
|
Schedule.collectWhile(
|
|
25
|
-
(metadata: Schedule.Metadata
|
|
26
|
-
metadata.input instanceof RpcClientError.RpcClientError,
|
|
27
|
+
(metadata: Schedule.Metadata) => metadata.input instanceof RpcClientError.RpcClientError,
|
|
27
28
|
),
|
|
28
29
|
);
|
|
29
30
|
|
|
30
31
|
function runRpc<A>(
|
|
31
32
|
rpc: T3Rpc["Service"],
|
|
32
33
|
method: string,
|
|
33
|
-
f: (client: WsClient) => Effect.Effect<A,
|
|
34
|
-
) {
|
|
34
|
+
f: (client: WsClient) => Effect.Effect<A, RpcRequestError>,
|
|
35
|
+
): Effect.Effect<A, RpcError> {
|
|
35
36
|
return Effect.gen(function* () {
|
|
36
37
|
const client = yield* rpc.getClient;
|
|
37
38
|
return yield* f(client);
|
|
@@ -41,15 +42,13 @@ function runRpc<A>(
|
|
|
41
42
|
),
|
|
42
43
|
Effect.retry(rpcRetrySchedule),
|
|
43
44
|
Effect.catchTags({
|
|
44
|
-
RpcClientError: (error) =>
|
|
45
|
-
Effect.fail(
|
|
46
|
-
new RpcError({
|
|
47
|
-
message: error.message,
|
|
48
|
-
method,
|
|
49
|
-
cause: error,
|
|
50
|
-
}),
|
|
51
|
-
),
|
|
52
45
|
RpcError: (error) => Effect.fail(error),
|
|
46
|
+
EnvironmentAuthorizationError: (error) => Effect.fail(toRpcRequestError(error, method)),
|
|
47
|
+
RpcClientError: (error) => Effect.fail(toRpcRequestError(error, method)),
|
|
48
|
+
KeybindingsConfigParseError: (error) => Effect.fail(toRpcRequestError(error, method)),
|
|
49
|
+
OrchestrationDispatchCommandError: (error) => Effect.fail(toRpcRequestError(error, method)),
|
|
50
|
+
OrchestrationGetSnapshotError: (error) => Effect.fail(toRpcRequestError(error, method)),
|
|
51
|
+
ServerSettingsError: (error) => Effect.fail(toRpcRequestError(error, method)),
|
|
53
52
|
}),
|
|
54
53
|
);
|
|
55
54
|
}
|
|
@@ -57,23 +56,21 @@ function runRpc<A>(
|
|
|
57
56
|
function subscribeRpc<A>(
|
|
58
57
|
rpc: T3Rpc["Service"],
|
|
59
58
|
method: string,
|
|
60
|
-
f: (client: WsClient) => Stream.Stream<A,
|
|
61
|
-
) {
|
|
59
|
+
f: (client: WsClient) => Stream.Stream<A, RpcRequestError>,
|
|
60
|
+
): Stream.Stream<A, RpcError> {
|
|
62
61
|
return Stream.unwrap(Effect.map(rpc.getClient, f)).pipe(
|
|
63
62
|
Stream.tapError((error) =>
|
|
64
63
|
error instanceof RpcClientError.RpcClientError ? rpc.disconnect : Effect.void,
|
|
65
64
|
),
|
|
66
65
|
Stream.retry(rpcRetrySchedule),
|
|
67
66
|
Stream.catchTags({
|
|
68
|
-
RpcClientError: (error) =>
|
|
69
|
-
Stream.fail(
|
|
70
|
-
new RpcError({
|
|
71
|
-
message: error.message,
|
|
72
|
-
method,
|
|
73
|
-
cause: error,
|
|
74
|
-
}),
|
|
75
|
-
),
|
|
76
67
|
RpcError: (error) => Stream.fail(error),
|
|
68
|
+
EnvironmentAuthorizationError: (error) => Stream.fail(toRpcRequestError(error, method)),
|
|
69
|
+
RpcClientError: (error) => Stream.fail(toRpcRequestError(error, method)),
|
|
70
|
+
KeybindingsConfigParseError: (error) => Stream.fail(toRpcRequestError(error, method)),
|
|
71
|
+
OrchestrationDispatchCommandError: (error) => Stream.fail(toRpcRequestError(error, method)),
|
|
72
|
+
OrchestrationGetSnapshotError: (error) => Stream.fail(toRpcRequestError(error, method)),
|
|
73
|
+
ServerSettingsError: (error) => Stream.fail(toRpcRequestError(error, method)),
|
|
77
74
|
}),
|
|
78
75
|
);
|
|
79
76
|
}
|
|
@@ -83,20 +80,8 @@ export const makeT3Orchestration = Effect.fn("makeT3Orchestration")(function* ()
|
|
|
83
80
|
const dispatch = Effect.fn("T3OrchestrationLive.dispatch")(function* (
|
|
84
81
|
command: ClientOrchestrationCommand,
|
|
85
82
|
) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
Effect.tapErrorTag("RpcClientError", () => rpc.disconnect),
|
|
89
|
-
Effect.catchTags({
|
|
90
|
-
RpcClientError: (error) =>
|
|
91
|
-
Effect.fail(
|
|
92
|
-
new RpcError({
|
|
93
|
-
message: error.message,
|
|
94
|
-
method: ORCHESTRATION_WS_METHODS.dispatchCommand,
|
|
95
|
-
cause: error,
|
|
96
|
-
}),
|
|
97
|
-
),
|
|
98
|
-
RpcError: (error) => Effect.fail(error),
|
|
99
|
-
}),
|
|
83
|
+
return yield* runRpc(rpc, ORCHESTRATION_WS_METHODS.dispatchCommand, (client) =>
|
|
84
|
+
client[ORCHESTRATION_WS_METHODS.dispatchCommand](command),
|
|
100
85
|
);
|
|
101
86
|
});
|
|
102
87
|
const getServerConfig = Effect.fn("T3OrchestrationLive.getServerConfig")(function* () {
|
|
@@ -126,7 +111,7 @@ export const makeT3Orchestration = Effect.fn("makeT3Orchestration")(function* ()
|
|
|
126
111
|
) {
|
|
127
112
|
const item = yield* Stream.runHead(
|
|
128
113
|
subscribeRpc(rpc, ORCHESTRATION_WS_METHODS.subscribeThread, (client) =>
|
|
129
|
-
client[ORCHESTRATION_WS_METHODS.subscribeThread]({ threadId }),
|
|
114
|
+
client[ORCHESTRATION_WS_METHODS.subscribeThread]({ threadId: ThreadId.make(threadId) }),
|
|
130
115
|
),
|
|
131
116
|
);
|
|
132
117
|
const value = Option.getOrUndefined(item);
|
|
@@ -144,17 +129,17 @@ export const makeT3Orchestration = Effect.fn("makeT3Orchestration")(function* ()
|
|
|
144
129
|
subscribeRpc(rpc, ORCHESTRATION_WS_METHODS.subscribeShell, (client) =>
|
|
145
130
|
client[ORCHESTRATION_WS_METHODS.subscribeShell]({}),
|
|
146
131
|
).pipe(
|
|
147
|
-
Stream.map((item:
|
|
132
|
+
Stream.map((item: OrchestrationShellStreamItem) =>
|
|
148
133
|
item.kind === "snapshot" ? item.snapshot.snapshotSequence : item.sequence,
|
|
149
134
|
),
|
|
150
135
|
);
|
|
151
136
|
const watchThreadItems = (threadId: string) =>
|
|
152
137
|
subscribeRpc(rpc, ORCHESTRATION_WS_METHODS.subscribeThread, (client) =>
|
|
153
|
-
client[ORCHESTRATION_WS_METHODS.subscribeThread]({ threadId }),
|
|
138
|
+
client[ORCHESTRATION_WS_METHODS.subscribeThread]({ threadId: ThreadId.make(threadId) }),
|
|
154
139
|
);
|
|
155
140
|
const openThread = Effect.fn("T3OrchestrationLive.openThread")(function* (threadId: string) {
|
|
156
141
|
return yield* watchThreadItems(threadId).pipe(
|
|
157
|
-
Stream.peel(Sink.head<
|
|
142
|
+
Stream.peel(Sink.head<OrchestrationThreadStreamItem>()),
|
|
158
143
|
Effect.flatMap(([item, rest]) => {
|
|
159
144
|
const value = Option.getOrUndefined(item);
|
|
160
145
|
if (value === undefined || value.kind !== "snapshot") {
|
|
@@ -169,7 +154,7 @@ export const makeT3Orchestration = Effect.fn("makeT3Orchestration")(function* ()
|
|
|
169
154
|
snapshot: value.snapshot.thread,
|
|
170
155
|
events: rest.pipe(
|
|
171
156
|
Stream.filter(
|
|
172
|
-
(next): next is Extract<
|
|
157
|
+
(next): next is Extract<OrchestrationThreadStreamItem, { readonly kind: "event" }> =>
|
|
173
158
|
next.kind === "event",
|
|
174
159
|
),
|
|
175
160
|
Stream.map((next) => next.event),
|
|
@@ -191,3 +176,11 @@ export const makeT3Orchestration = Effect.fn("makeT3Orchestration")(function* ()
|
|
|
191
176
|
});
|
|
192
177
|
|
|
193
178
|
export const T3OrchestrationLive = Layer.effect(T3Orchestration, makeT3Orchestration());
|
|
179
|
+
|
|
180
|
+
function toRpcRequestError(error: RpcRequestError, method: string) {
|
|
181
|
+
return new RpcError({
|
|
182
|
+
message: error.message,
|
|
183
|
+
method,
|
|
184
|
+
cause: error,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
@@ -2,33 +2,42 @@ import * as Context from "effect/Context";
|
|
|
2
2
|
import type * as Effect from "effect/Effect";
|
|
3
3
|
import type * as Scope from "effect/Scope";
|
|
4
4
|
import type * as Stream from "effect/Stream";
|
|
5
|
+
import type {
|
|
6
|
+
ClientOrchestrationCommand,
|
|
7
|
+
DispatchResult,
|
|
8
|
+
OrchestrationEvent,
|
|
9
|
+
OrchestrationShellSnapshot,
|
|
10
|
+
OrchestrationThread,
|
|
11
|
+
OrchestrationThreadStreamItem,
|
|
12
|
+
ServerProviders,
|
|
13
|
+
} from "@t3tools/contracts";
|
|
5
14
|
|
|
6
|
-
import type { ClientOrchestrationCommand, DispatchResult } from "../domain/command-schema.ts";
|
|
7
|
-
import type { ServerConfig, ShellSnapshot, ThreadDetail, ThreadEvent } from "../domain/schema.ts";
|
|
8
15
|
import type { RpcError } from "../rpc/error.ts";
|
|
9
16
|
|
|
10
17
|
export type OrchestrationError = RpcError;
|
|
11
18
|
|
|
12
19
|
export type OpenThread = {
|
|
13
|
-
readonly snapshot:
|
|
14
|
-
readonly events: Stream.Stream<
|
|
20
|
+
readonly snapshot: OrchestrationThread;
|
|
21
|
+
readonly events: Stream.Stream<OrchestrationEvent, OrchestrationError>;
|
|
15
22
|
};
|
|
16
23
|
|
|
17
|
-
export type
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
export type ServerConfigForCli = {
|
|
25
|
+
readonly providers: ServerProviders;
|
|
26
|
+
};
|
|
20
27
|
|
|
21
28
|
export type Orchestration = {
|
|
22
29
|
readonly dispatch: (
|
|
23
30
|
command: ClientOrchestrationCommand,
|
|
24
31
|
) => Effect.Effect<DispatchResult, OrchestrationError>;
|
|
25
|
-
readonly getServerConfig: () => Effect.Effect<
|
|
26
|
-
readonly getShellSnapshot: () => Effect.Effect<
|
|
27
|
-
readonly getThreadSnapshot: (
|
|
32
|
+
readonly getServerConfig: () => Effect.Effect<ServerConfigForCli, OrchestrationError>;
|
|
33
|
+
readonly getShellSnapshot: () => Effect.Effect<OrchestrationShellSnapshot, OrchestrationError>;
|
|
34
|
+
readonly getThreadSnapshot: (
|
|
35
|
+
threadId: string,
|
|
36
|
+
) => Effect.Effect<OrchestrationThread, OrchestrationError>;
|
|
28
37
|
readonly watchShellSequence: () => Stream.Stream<number, OrchestrationError, Scope.Scope>;
|
|
29
38
|
readonly watchThreadItems: (
|
|
30
39
|
threadId: string,
|
|
31
|
-
) => Stream.Stream<
|
|
40
|
+
) => Stream.Stream<OrchestrationThreadStreamItem, OrchestrationError, Scope.Scope>;
|
|
32
41
|
readonly openThread: (
|
|
33
42
|
threadId: string,
|
|
34
43
|
) => Effect.Effect<OpenThread, OrchestrationError, Scope.Scope>;
|
package/src/rpc/error.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import * as Schema from "effect/Schema";
|
|
2
|
+
import {
|
|
3
|
+
EnvironmentAuthorizationError,
|
|
4
|
+
KeybindingsConfigError,
|
|
5
|
+
OrchestrationDispatchCommandError,
|
|
6
|
+
OrchestrationGetSnapshotError,
|
|
7
|
+
ServerSettingsError,
|
|
8
|
+
} from "@t3tools/contracts";
|
|
2
9
|
import { HttpClientError } from "effect/unstable/http";
|
|
3
10
|
import { RpcClientError } from "effect/unstable/rpc";
|
|
4
11
|
|
|
@@ -12,6 +19,11 @@ import { ConfigError, UrlError } from "../config/error.ts";
|
|
|
12
19
|
|
|
13
20
|
const RpcErrorCauseSchema = Schema.Union([
|
|
14
21
|
RpcClientError.RpcClientError,
|
|
22
|
+
EnvironmentAuthorizationError,
|
|
23
|
+
KeybindingsConfigError,
|
|
24
|
+
OrchestrationDispatchCommandError,
|
|
25
|
+
OrchestrationGetSnapshotError,
|
|
26
|
+
ServerSettingsError,
|
|
15
27
|
AuthConfigError,
|
|
16
28
|
AuthLocalError,
|
|
17
29
|
AuthPairingUrlError,
|
package/src/rpc/layer.ts
CHANGED
|
@@ -13,12 +13,12 @@ import * as Socket from "effect/unstable/socket/Socket";
|
|
|
13
13
|
|
|
14
14
|
import { T3Auth } from "../auth/service.ts";
|
|
15
15
|
import { T3Config } from "../config/service.ts";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
16
|
+
import { toWebSocketEndpointUrl } from "../config/url.ts";
|
|
17
|
+
import { CliWsRpcGroup } from "./ws-group.ts";
|
|
18
18
|
import { RpcError } from "./error.ts";
|
|
19
19
|
import { T3Rpc, type WsClient } from "./service.ts";
|
|
20
20
|
|
|
21
|
-
const makeClient = RpcClient.make(
|
|
21
|
+
const makeClient = RpcClient.make(CliWsRpcGroup);
|
|
22
22
|
const connectionRetrySchedule = Schedule.exponential("100 millis").pipe(Schedule.take(4));
|
|
23
23
|
|
|
24
24
|
type Connection = {
|
|
@@ -77,7 +77,7 @@ const makeWsUrl = Effect.fn("makeWsUrl")(function* (input: {
|
|
|
77
77
|
}) {
|
|
78
78
|
const resolved = yield* input.config.resolve();
|
|
79
79
|
const wsToken = yield* input.auth.issueWebSocketToken();
|
|
80
|
-
const wsUrl = yield*
|
|
80
|
+
const wsUrl = yield* toWebSocketEndpointUrl(resolved.url, "/ws");
|
|
81
81
|
const request = HttpClientRequest.get(wsUrl).pipe(
|
|
82
82
|
HttpClientRequest.setUrlParam("wsToken", wsToken.token),
|
|
83
83
|
);
|
package/src/rpc/service.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import * as Context from "effect/Context";
|
|
2
2
|
import type * as Effect from "effect/Effect";
|
|
3
3
|
import type { RpcClient, RpcClientError } from "effect/unstable/rpc";
|
|
4
|
-
|
|
5
|
-
import type { WsRpcGroup } from "../protocol/schema.ts";
|
|
4
|
+
import type { CliWsRpcGroup } from "./ws-group.ts";
|
|
6
5
|
import type { RpcError } from "./error.ts";
|
|
7
6
|
|
|
8
|
-
export type WsClient = RpcClient.FromGroup<typeof
|
|
7
|
+
export type WsClient = RpcClient.FromGroup<typeof CliWsRpcGroup, RpcClientError.RpcClientError>;
|
|
9
8
|
|
|
10
9
|
export type T3RpcService = {
|
|
11
10
|
readonly getClient: Effect.Effect<WsClient, RpcError>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EnvironmentAuthorizationError,
|
|
3
|
+
KeybindingsConfigError,
|
|
4
|
+
OrchestrationDispatchCommandError,
|
|
5
|
+
OrchestrationGetSnapshotError,
|
|
6
|
+
ServerConfig,
|
|
7
|
+
ServerProviders,
|
|
8
|
+
ServerSettingsError,
|
|
9
|
+
WS_METHODS,
|
|
10
|
+
WsOrchestrationDispatchCommandRpc,
|
|
11
|
+
WsOrchestrationSubscribeShellRpc,
|
|
12
|
+
WsOrchestrationSubscribeThreadRpc,
|
|
13
|
+
} from "@t3tools/contracts";
|
|
14
|
+
import * as Schema from "effect/Schema";
|
|
15
|
+
import { Rpc, RpcGroup } from "effect/unstable/rpc";
|
|
16
|
+
|
|
17
|
+
export const FallbackServerConfig = Schema.Struct({
|
|
18
|
+
providers: ServerProviders,
|
|
19
|
+
});
|
|
20
|
+
export type FallbackServerConfig = typeof FallbackServerConfig.Type;
|
|
21
|
+
|
|
22
|
+
export const CliServerConfig = Schema.Union([ServerConfig, FallbackServerConfig]);
|
|
23
|
+
export type CliServerConfig = typeof CliServerConfig.Type;
|
|
24
|
+
|
|
25
|
+
export const WsServerGetConfigRpc = Rpc.make(WS_METHODS.serverGetConfig, {
|
|
26
|
+
payload: Schema.Struct({}),
|
|
27
|
+
success: CliServerConfig,
|
|
28
|
+
error: Schema.Union([KeybindingsConfigError, ServerSettingsError, EnvironmentAuthorizationError]),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const CliWsRpcGroup = RpcGroup.make(
|
|
32
|
+
WsOrchestrationDispatchCommandRpc,
|
|
33
|
+
WsOrchestrationSubscribeShellRpc,
|
|
34
|
+
WsOrchestrationSubscribeThreadRpc,
|
|
35
|
+
WsServerGetConfigRpc,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
export type CliRpcRequestError =
|
|
39
|
+
| EnvironmentAuthorizationError
|
|
40
|
+
| KeybindingsConfigError
|
|
41
|
+
| OrchestrationDispatchCommandError
|
|
42
|
+
| OrchestrationGetSnapshotError
|
|
43
|
+
| ServerSettingsError;
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import * as Schema from "effect/Schema";
|
|
2
|
-
|
|
3
|
-
import { ModelSelectionSchema } from "./schema.ts";
|
|
4
|
-
|
|
5
|
-
export const DispatchResultSchema = Schema.Struct({
|
|
6
|
-
sequence: Schema.Number,
|
|
7
|
-
});
|
|
8
|
-
export type DispatchResult = typeof DispatchResultSchema.Type;
|
|
9
|
-
|
|
10
|
-
export const ProjectCreateCommandSchema = Schema.Struct({
|
|
11
|
-
type: Schema.Literal("project.create"),
|
|
12
|
-
commandId: Schema.String,
|
|
13
|
-
projectId: Schema.String,
|
|
14
|
-
title: Schema.String,
|
|
15
|
-
workspaceRoot: Schema.String,
|
|
16
|
-
createdAt: Schema.String,
|
|
17
|
-
});
|
|
18
|
-
export type ProjectCreateCommand = typeof ProjectCreateCommandSchema.Type;
|
|
19
|
-
|
|
20
|
-
export const ThreadCreateCommandSchema = Schema.Struct({
|
|
21
|
-
type: Schema.Literal("thread.create"),
|
|
22
|
-
commandId: Schema.String,
|
|
23
|
-
threadId: Schema.String,
|
|
24
|
-
projectId: Schema.String,
|
|
25
|
-
title: Schema.String,
|
|
26
|
-
modelSelection: ModelSelectionSchema,
|
|
27
|
-
runtimeMode: Schema.Literal("full-access"),
|
|
28
|
-
interactionMode: Schema.Literal("default"),
|
|
29
|
-
branch: Schema.Null,
|
|
30
|
-
worktreePath: Schema.NullOr(Schema.String),
|
|
31
|
-
createdAt: Schema.String,
|
|
32
|
-
});
|
|
33
|
-
export type ThreadCreateCommand = typeof ThreadCreateCommandSchema.Type;
|
|
34
|
-
|
|
35
|
-
export const ThreadTurnStartCommandSchema = Schema.Struct({
|
|
36
|
-
type: Schema.Literal("thread.turn.start"),
|
|
37
|
-
commandId: Schema.String,
|
|
38
|
-
threadId: Schema.String,
|
|
39
|
-
message: Schema.Struct({
|
|
40
|
-
messageId: Schema.String,
|
|
41
|
-
role: Schema.Literal("user"),
|
|
42
|
-
text: Schema.String,
|
|
43
|
-
attachments: Schema.Array(Schema.Never),
|
|
44
|
-
}),
|
|
45
|
-
modelSelection: Schema.optionalKey(ModelSelectionSchema),
|
|
46
|
-
titleSeed: Schema.optionalKey(Schema.String),
|
|
47
|
-
runtimeMode: Schema.Literal("full-access"),
|
|
48
|
-
interactionMode: Schema.Literal("default"),
|
|
49
|
-
bootstrap: Schema.optionalKey(
|
|
50
|
-
Schema.Struct({
|
|
51
|
-
createThread: Schema.optionalKey(
|
|
52
|
-
Schema.Struct({
|
|
53
|
-
projectId: Schema.String,
|
|
54
|
-
title: Schema.String,
|
|
55
|
-
modelSelection: ModelSelectionSchema,
|
|
56
|
-
runtimeMode: Schema.Literal("full-access"),
|
|
57
|
-
interactionMode: Schema.Literal("default"),
|
|
58
|
-
branch: Schema.Null,
|
|
59
|
-
worktreePath: Schema.NullOr(Schema.String),
|
|
60
|
-
createdAt: Schema.String,
|
|
61
|
-
}),
|
|
62
|
-
),
|
|
63
|
-
}),
|
|
64
|
-
),
|
|
65
|
-
createdAt: Schema.String,
|
|
66
|
-
});
|
|
67
|
-
export type ThreadTurnStartCommand = typeof ThreadTurnStartCommandSchema.Type;
|
|
68
|
-
|
|
69
|
-
export const ThreadArchiveCommandSchema = Schema.Struct({
|
|
70
|
-
type: Schema.Literal("thread.archive"),
|
|
71
|
-
commandId: Schema.String,
|
|
72
|
-
threadId: Schema.String,
|
|
73
|
-
});
|
|
74
|
-
export type ThreadArchiveCommand = typeof ThreadArchiveCommandSchema.Type;
|
|
75
|
-
|
|
76
|
-
export const ClientOrchestrationCommandSchema = Schema.Union([
|
|
77
|
-
ProjectCreateCommandSchema,
|
|
78
|
-
ThreadArchiveCommandSchema,
|
|
79
|
-
ThreadCreateCommandSchema,
|
|
80
|
-
ThreadTurnStartCommandSchema,
|
|
81
|
-
]);
|
|
82
|
-
export type ClientOrchestrationCommand = typeof ClientOrchestrationCommandSchema.Type;
|