@opencode-ai/client 0.0.0-dev-18706 → 0.0.0-dev-18709
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/effect/api/api.d.ts +17 -0
- package/dist/effect/api.d.ts +1 -0
- package/dist/effect/client.d.ts +2526 -0
- package/dist/effect/client.js +29 -0
- package/dist/effect/generated/client.d.ts +18 -1
- package/dist/effect/generated/client.js +7 -0
- package/dist/effect/index.d.ts +4 -2
- package/dist/effect/index.js +1 -0
- package/dist/effect/rpc.d.ts +20 -0
- package/dist/effect/rpc.js +49 -0
- package/dist/promise/api.d.ts +3 -2
- package/dist/promise/client.d.ts +255 -0
- package/dist/promise/client.js +13 -0
- package/dist/promise/generated/client.d.ts +4 -1
- package/dist/promise/generated/client.js +11 -0
- package/dist/promise/generated/types.d.ts +63 -9
- package/dist/promise/generated/types.js +2 -0
- package/dist/promise/index.d.ts +4 -2
- package/dist/promise/index.js +1 -0
- package/dist/promise/rpc.d.ts +32 -0
- package/dist/promise/rpc.js +86 -0
- package/dist/rpc-runtime.d.ts +21 -0
- package/dist/rpc-runtime.js +32 -0
- package/dist/shared-events.d.ts +8 -0
- package/dist/shared-events.js +133 -0
- package/dist/solid/connection.js +1 -1
- package/dist/solid/data.d.ts +7 -6
- package/package.json +6 -5
|
@@ -27,6 +27,17 @@ export type PluginSource = {
|
|
|
27
27
|
} | {
|
|
28
28
|
type: "sdk";
|
|
29
29
|
};
|
|
30
|
+
export type PluginFeatures = {
|
|
31
|
+
server?: true;
|
|
32
|
+
tui?: true;
|
|
33
|
+
rpc?: true;
|
|
34
|
+
};
|
|
35
|
+
export type PluginState = {
|
|
36
|
+
status: "active";
|
|
37
|
+
} | {
|
|
38
|
+
status: "failed";
|
|
39
|
+
error: string;
|
|
40
|
+
};
|
|
30
41
|
export type SessionForkBoundary = {
|
|
31
42
|
type: "before";
|
|
32
43
|
messageID: string;
|
|
@@ -504,6 +515,9 @@ export type SkillInfo = {
|
|
|
504
515
|
location: string;
|
|
505
516
|
content: string;
|
|
506
517
|
};
|
|
518
|
+
export type RpcOutput = {
|
|
519
|
+
output?: any;
|
|
520
|
+
};
|
|
507
521
|
export type PermissionReply = "once" | "always" | "reject";
|
|
508
522
|
export type Pty = {
|
|
509
523
|
id: string;
|
|
@@ -669,16 +683,10 @@ export type PermissionRule = {
|
|
|
669
683
|
effect: PermissionEffect;
|
|
670
684
|
};
|
|
671
685
|
export type PluginInfo = {
|
|
672
|
-
id: string;
|
|
673
|
-
source: PluginSource;
|
|
674
|
-
status: "active";
|
|
675
|
-
tui: boolean;
|
|
676
|
-
} | {
|
|
677
686
|
id?: string;
|
|
678
687
|
source: PluginSource;
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
tui: boolean;
|
|
688
|
+
features: PluginFeatures;
|
|
689
|
+
state: PluginState;
|
|
682
690
|
};
|
|
683
691
|
export type SessionMessageLocationSwitched = {
|
|
684
692
|
id: string;
|
|
@@ -703,6 +711,18 @@ export type SessionInboxMovePayload = {
|
|
|
703
711
|
projectID: string;
|
|
704
712
|
subpath?: string;
|
|
705
713
|
};
|
|
714
|
+
export type V2EventRpc = {
|
|
715
|
+
id: string;
|
|
716
|
+
created: number;
|
|
717
|
+
metadata?: {
|
|
718
|
+
[x: string]: any;
|
|
719
|
+
} | undefined;
|
|
720
|
+
type: `${"rpc."}${string}`;
|
|
721
|
+
location: LocationRef;
|
|
722
|
+
data: {
|
|
723
|
+
[x: string]: any;
|
|
724
|
+
};
|
|
725
|
+
};
|
|
706
726
|
export type V2EventServerConnected = {
|
|
707
727
|
id: string;
|
|
708
728
|
metadata?: {
|
|
@@ -3105,7 +3125,7 @@ export type IntegrationInfo = {
|
|
|
3105
3125
|
methods: Array<IntegrationMethod>;
|
|
3106
3126
|
connections: Array<ConnectionInfo>;
|
|
3107
3127
|
};
|
|
3108
|
-
export type V2Event = ModelsDevRefreshed | CredentialUpdated | CredentialSwitched | IntegrationUpdated | CatalogUpdated | AgentUpdated | SessionCreated | SessionAgentSelected | SessionModelSelected | SessionMoved | SessionRenamed | SessionViewed | SessionUsageUpdated | SessionDeleted | SessionForked | SessionInboxDelivered | SessionInboxEnqueued | SessionInboxCancelled | SessionInboxDeliveryChanged | SessionExecutionStarted | SessionExecutionSucceeded | SessionExecutionFailed | SessionExecutionInterrupted | SessionInstructionsUpdated | SessionSynthetic | SessionSkillActivated | SessionShellStarted | SessionShellEnded | SessionStepStarted | SessionStepStreamed | SessionStepEnded | SessionStepFailed | SessionTextStarted | SessionTextDelta | SessionTextEnded | SessionReasoningStarted | SessionReasoningDelta | SessionReasoningEnded | SessionToolInputStarted | SessionToolInputDelta | SessionToolInputEnded | SessionToolCalled | SessionToolProgress | SessionToolSuccess | SessionToolFailed | SessionRetryScheduled | SessionCompactionStarted | SessionCompactionDelta | SessionCompactionEnded | SessionCompactionFailed | SessionRevertStaged | SessionRevertCleared | SessionRevertCommitted | SessionMessageContentUpdated | FilesystemChanged | ReferenceUpdated | PermissionAsked | PermissionReplied | PluginAdded | PluginUpdated | ProjectUpdated | WorktreeUpdated | WorktreeResolved | CommandUpdated | ConfigUpdated | SkillUpdated | PtyCreated | PtyUpdated | PtyExited | PtyDeleted | PersistentPtyAdded | PersistentPtyRemoved | ShellCreated | ShellExited | ShellDeleted | FormCreated | FormReplied | FormCancelled | WebsearchUpdated | SessionStatusUpdated | SessionIdle | TuiPromptAppend | TuiCommandExecute | TuiToastShow | TuiSessionSelect | InstallationUpdated | InstallationUpdateAvailable | VcsBranchUpdated | McpStatusChanged | McpResourcesChanged | V2EventServerConnected;
|
|
3128
|
+
export type V2Event = ModelsDevRefreshed | CredentialUpdated | CredentialSwitched | IntegrationUpdated | CatalogUpdated | AgentUpdated | SessionCreated | SessionAgentSelected | SessionModelSelected | SessionMoved | SessionRenamed | SessionViewed | SessionUsageUpdated | SessionDeleted | SessionForked | SessionInboxDelivered | SessionInboxEnqueued | SessionInboxCancelled | SessionInboxDeliveryChanged | SessionExecutionStarted | SessionExecutionSucceeded | SessionExecutionFailed | SessionExecutionInterrupted | SessionInstructionsUpdated | SessionSynthetic | SessionSkillActivated | SessionShellStarted | SessionShellEnded | SessionStepStarted | SessionStepStreamed | SessionStepEnded | SessionStepFailed | SessionTextStarted | SessionTextDelta | SessionTextEnded | SessionReasoningStarted | SessionReasoningDelta | SessionReasoningEnded | SessionToolInputStarted | SessionToolInputDelta | SessionToolInputEnded | SessionToolCalled | SessionToolProgress | SessionToolSuccess | SessionToolFailed | SessionRetryScheduled | SessionCompactionStarted | SessionCompactionDelta | SessionCompactionEnded | SessionCompactionFailed | SessionRevertStaged | SessionRevertCleared | SessionRevertCommitted | SessionMessageContentUpdated | FilesystemChanged | ReferenceUpdated | PermissionAsked | PermissionReplied | PluginAdded | PluginUpdated | ProjectUpdated | WorktreeUpdated | WorktreeResolved | CommandUpdated | ConfigUpdated | SkillUpdated | PtyCreated | PtyUpdated | PtyExited | PtyDeleted | PersistentPtyAdded | PersistentPtyRemoved | ShellCreated | ShellExited | ShellDeleted | FormCreated | FormReplied | FormCancelled | WebsearchUpdated | SessionStatusUpdated | SessionIdle | TuiPromptAppend | TuiCommandExecute | TuiToastShow | TuiSessionSelect | InstallationUpdated | InstallationUpdateAvailable | VcsBranchUpdated | McpStatusChanged | McpResourcesChanged | V2EventRpc | V2EventServerConnected;
|
|
3109
3129
|
export type SessionLogItem = SessionEventDurable | EventLogSynced;
|
|
3110
3130
|
export type UnauthorizedError = {
|
|
3111
3131
|
readonly _tag: "UnauthorizedError";
|
|
@@ -3234,6 +3254,20 @@ export type PermissionNotFoundError = {
|
|
|
3234
3254
|
readonly message: string;
|
|
3235
3255
|
};
|
|
3236
3256
|
export declare const isPermissionNotFoundError: (value: unknown) => value is PermissionNotFoundError;
|
|
3257
|
+
export type RpcError = {
|
|
3258
|
+
readonly _tag: "RpcError";
|
|
3259
|
+
readonly type: string;
|
|
3260
|
+
readonly message: string;
|
|
3261
|
+
readonly data?: unknown | undefined;
|
|
3262
|
+
};
|
|
3263
|
+
export declare const isRpcError: (value: unknown) => value is RpcError;
|
|
3264
|
+
export type RpcInternalError = {
|
|
3265
|
+
readonly _tag: "RpcInternalError";
|
|
3266
|
+
readonly type: "rpc.internal" | "rpc.invalid_output";
|
|
3267
|
+
readonly message: string;
|
|
3268
|
+
readonly data?: unknown | undefined;
|
|
3269
|
+
};
|
|
3270
|
+
export declare const isRpcInternalError: (value: unknown) => value is RpcInternalError;
|
|
3237
3271
|
export type PtyNotFoundError = {
|
|
3238
3272
|
readonly _tag: "PtyNotFoundError";
|
|
3239
3273
|
readonly ptyID: string;
|
|
@@ -7637,6 +7671,26 @@ export type SkillListOutput = {
|
|
|
7637
7671
|
};
|
|
7638
7672
|
data: Array<SkillInfo>;
|
|
7639
7673
|
};
|
|
7674
|
+
export type RpcCallInput = {
|
|
7675
|
+
readonly rpcID: {
|
|
7676
|
+
readonly rpcID: string;
|
|
7677
|
+
readonly method: string;
|
|
7678
|
+
}["rpcID"];
|
|
7679
|
+
readonly method: {
|
|
7680
|
+
readonly rpcID: string;
|
|
7681
|
+
readonly method: string;
|
|
7682
|
+
}["method"];
|
|
7683
|
+
readonly location?: {
|
|
7684
|
+
readonly location?: {
|
|
7685
|
+
readonly directory?: string | undefined;
|
|
7686
|
+
readonly workspace?: string | undefined;
|
|
7687
|
+
} | undefined;
|
|
7688
|
+
}["location"];
|
|
7689
|
+
readonly input?: {
|
|
7690
|
+
readonly input: JsonValue;
|
|
7691
|
+
}["input"];
|
|
7692
|
+
};
|
|
7693
|
+
export type RpcCallOutput = RpcOutput;
|
|
7640
7694
|
export type EventSubscribeOutput = V2Event;
|
|
7641
7695
|
export type PtyListInput = {
|
|
7642
7696
|
readonly location?: {
|
|
@@ -22,6 +22,8 @@ export const isFormNotFoundError = (value) => typeof value === "object" && value
|
|
|
22
22
|
export const isFormAlreadySettledError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "FormAlreadySettledError";
|
|
23
23
|
export const isFormInvalidAnswerError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "FormInvalidAnswerError";
|
|
24
24
|
export const isPermissionNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "PermissionNotFoundError";
|
|
25
|
+
export const isRpcError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "RpcError";
|
|
26
|
+
export const isRpcInternalError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "RpcInternalError";
|
|
25
27
|
export const isPtyNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "PtyNotFoundError";
|
|
26
28
|
export const isForbiddenError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ForbiddenError";
|
|
27
29
|
export const isShellNotFoundError = (value) => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ShellNotFoundError";
|
package/dist/promise/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { OpenCode } from "./client.js";
|
|
1
2
|
export * from "./generated/index.js";
|
|
2
|
-
export
|
|
3
|
+
export { OpenCode } from "./client.js";
|
|
4
|
+
export type { AgentApi, CatalogApi, CommandApi, ConfigApi, EventApi, IntegrationApi, ModelApi, PluginApi, ProviderApi, ReferenceApi, RpcApi, RpcCallOptions, RpcClient, RpcEventPayload, WebSearchApi, SessionApi, SkillApi, } from "./api.js";
|
|
3
5
|
export type { EventSubscribeOutput as OpenCodeEvent } from "./generated/types.js";
|
|
4
|
-
export type OpenCodeClient = ReturnType<typeof
|
|
6
|
+
export type OpenCodeClient = ReturnType<typeof OpenCode.make>;
|
package/dist/promise/index.js
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Rpc } from "@opencode-ai/schema/rpc";
|
|
2
|
+
import type { make, RequestOptions } from "./generated/client.js";
|
|
3
|
+
import type { EventSubscribeOutput, LocationGetInput } from "./generated/types.js";
|
|
4
|
+
type RpcEvent = Extract<EventSubscribeOutput, {
|
|
5
|
+
type: `rpc.${string}`;
|
|
6
|
+
}>;
|
|
7
|
+
export interface RpcCallOptions extends RequestOptions {
|
|
8
|
+
readonly location?: LocationGetInput["location"];
|
|
9
|
+
}
|
|
10
|
+
export type RpcArguments<Input, Options> = unknown extends Input ? [input: Input, options?: Options] : undefined extends Input ? [input?: Input, options?: Options] : [input: Input, options?: Options];
|
|
11
|
+
export type RpcClient<D extends Rpc.PortableDefinition, Options = RpcCallOptions> = {
|
|
12
|
+
readonly [Name in keyof D["methods"]]: (...args: RpcArguments<Rpc.Input<D["methods"][Name]["input"]>, Options>) => Promise<Rpc.Output<D["methods"][Name]["output"]>>;
|
|
13
|
+
} & {
|
|
14
|
+
readonly events: {
|
|
15
|
+
readonly subscribe: <Name extends keyof D["events"] & string>(name: Name, options?: Pick<RequestOptions, "signal">) => AsyncIterable<RpcEventPayload<D, Name>>;
|
|
16
|
+
readonly on: <Name extends keyof D["events"] & string>(name: Name, handler: (event: RpcEventPayload<D, Name>) => Promise<void> | void, options?: Pick<RequestOptions, "signal">) => () => void;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
type RpcEventPayloadFor<D extends Rpc.PortableDefinition, Name extends keyof D["events"] & string> = Omit<RpcEvent, "type" | "data"> & {
|
|
20
|
+
type: `rpc.${D["id"]}.${Name}`;
|
|
21
|
+
data: Rpc.EventData<D["events"][Name]["schema"]>;
|
|
22
|
+
};
|
|
23
|
+
export type RpcEventPayload<D extends Rpc.PortableDefinition, Name extends keyof D["events"] & string = keyof D["events"] & string> = {
|
|
24
|
+
[K in Name]: RpcEventPayloadFor<D, K>;
|
|
25
|
+
}[Name];
|
|
26
|
+
export interface RpcApi<Options = RpcCallOptions> {
|
|
27
|
+
<D extends Rpc.PortableDefinition>(definition: D): RpcClient<D, Options>;
|
|
28
|
+
}
|
|
29
|
+
export declare function makeRpc(raw: ReturnType<typeof make>, events: {
|
|
30
|
+
subscribe(options?: Pick<RequestOptions, "signal">): AsyncIterable<EventSubscribeOutput>;
|
|
31
|
+
}): RpcApi;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { isRpcError, isRpcInternalError } from "./generated/types.js";
|
|
2
|
+
export function makeRpc(raw, events) {
|
|
3
|
+
return (definition) => {
|
|
4
|
+
const subscribe = (name, options) => {
|
|
5
|
+
if (!Object.hasOwn(definition.events, name))
|
|
6
|
+
throw new Error(`Unknown RPC event: ${definition.id}.${name}`);
|
|
7
|
+
const type = eventType(definition, name);
|
|
8
|
+
return {
|
|
9
|
+
[Symbol.asyncIterator]() {
|
|
10
|
+
const controller = new AbortController();
|
|
11
|
+
const signal = options?.signal ? AbortSignal.any([controller.signal, options.signal]) : controller.signal;
|
|
12
|
+
const iterator = (async function* () {
|
|
13
|
+
try {
|
|
14
|
+
for await (const published of events.subscribe({ signal })) {
|
|
15
|
+
if (signal.aborted)
|
|
16
|
+
return;
|
|
17
|
+
if (published.type !== type)
|
|
18
|
+
continue;
|
|
19
|
+
// SAFETY: The exact RPC type was selected above; Promise contracts require no client-side transform.
|
|
20
|
+
// oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion
|
|
21
|
+
yield published;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (!signal.aborted)
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
controller.abort();
|
|
30
|
+
}
|
|
31
|
+
})();
|
|
32
|
+
return {
|
|
33
|
+
next: () => iterator.next(),
|
|
34
|
+
return: () => {
|
|
35
|
+
// Interrupt a pending source read before closing the generator.
|
|
36
|
+
controller.abort();
|
|
37
|
+
return iterator.return();
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
// SAFETY: Every runtime key comes from this definition's method and event maps, which define RpcClient's mapped keys.
|
|
44
|
+
// oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion
|
|
45
|
+
return Object.assign(Object.fromEntries(Object.keys(definition.methods).map((name) => [
|
|
46
|
+
name,
|
|
47
|
+
async (input, options) => {
|
|
48
|
+
try {
|
|
49
|
+
const result = await raw.rpc.call({
|
|
50
|
+
rpcID: definition.id,
|
|
51
|
+
method: name,
|
|
52
|
+
// SAFETY: The method schema defines the accepted input; this assertion bridges it to the generic JSON transport.
|
|
53
|
+
// oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion
|
|
54
|
+
input: input,
|
|
55
|
+
location: options?.location,
|
|
56
|
+
}, { signal: options?.signal, headers: options?.headers });
|
|
57
|
+
return result.output;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (!isRpcError(error) && !isRpcInternalError(error))
|
|
61
|
+
throw error;
|
|
62
|
+
throw error.data === undefined
|
|
63
|
+
? { type: error.type, message: error.message }
|
|
64
|
+
: { type: error.type, message: error.message, data: error.data };
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
])), {
|
|
68
|
+
events: {
|
|
69
|
+
subscribe,
|
|
70
|
+
on: (name, handler, options) => {
|
|
71
|
+
const controller = new AbortController();
|
|
72
|
+
const signal = options?.signal ? AbortSignal.any([controller.signal, options.signal]) : controller.signal;
|
|
73
|
+
const source = subscribe(name, { signal });
|
|
74
|
+
void (async () => {
|
|
75
|
+
for await (const event of source)
|
|
76
|
+
await handler(event);
|
|
77
|
+
})().catch((error) => console.error(error));
|
|
78
|
+
return () => controller.abort();
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function eventType(definition, name) {
|
|
85
|
+
return `rpc.${definition.id}.${name}`;
|
|
86
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export * as RpcRuntime from "./rpc-runtime.js";
|
|
2
|
+
import type { Rpc } from "@opencode-ai/schema/rpc";
|
|
3
|
+
import { Effect, Schema } from "effect";
|
|
4
|
+
export declare function read(schema: Rpc.Method["output"], value: unknown): Effect.Effect<unknown, Schema.SchemaError, never>;
|
|
5
|
+
export declare function readError(method: Rpc.Method, error: unknown): Effect.Effect<never, unknown>;
|
|
6
|
+
export declare const event: <D extends Rpc.Definition, Name extends keyof D["events"] & string>(definition: D, name: Name, schema: Rpc.EventDefinition, event: {
|
|
7
|
+
readonly id: string & import("effect/Brand").Brand<"Event.ID">;
|
|
8
|
+
readonly location: {
|
|
9
|
+
readonly directory: string & import("effect/Brand").Brand<"AbsolutePath">;
|
|
10
|
+
readonly workspaceID?: (string & import("effect/Brand").Brand<"Workspace.ID">) | undefined;
|
|
11
|
+
};
|
|
12
|
+
readonly data: {
|
|
13
|
+
readonly [x: string]: unknown;
|
|
14
|
+
};
|
|
15
|
+
readonly type: `rpc.${string}`;
|
|
16
|
+
readonly created: number;
|
|
17
|
+
readonly metadata?: {
|
|
18
|
+
readonly [x: string]: unknown;
|
|
19
|
+
} | undefined;
|
|
20
|
+
}) => Effect.Effect<Rpc.EventPayload<D, Name>, unknown, never>;
|
|
21
|
+
export declare function eventType<const D extends Rpc.Definition, const Name extends keyof D["events"] & string>(definition: D, name: Name): `rpc.${D["id"]}.${Name}`;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export * as RpcRuntime from "./rpc-runtime.js";
|
|
2
|
+
import { RpcError, RpcInternalError } from "@opencode-ai/protocol/errors";
|
|
3
|
+
import { Effect, Schema } from "effect";
|
|
4
|
+
export function read(schema, value) {
|
|
5
|
+
// Standard Schema results have already been parsed by the server.
|
|
6
|
+
return Schema.isSchema(schema) ? Schema.decodeUnknownEffect(schema)(value) : Effect.succeed(value);
|
|
7
|
+
}
|
|
8
|
+
export function readError(method, error) {
|
|
9
|
+
if (!(error instanceof RpcError) && !(error instanceof RpcInternalError))
|
|
10
|
+
return Effect.fail(error);
|
|
11
|
+
if (!method.errors || !Object.hasOwn(method.errors, error.type)) {
|
|
12
|
+
return Effect.fail(error.data === undefined
|
|
13
|
+
? { type: error.type, message: error.message }
|
|
14
|
+
: { type: error.type, message: error.message, data: error.data });
|
|
15
|
+
}
|
|
16
|
+
return read(method.errors[error.type], error.data).pipe(Effect.catch((cause) => Effect.die(cause)), Effect.flatMap((data) => Effect.fail(data === undefined
|
|
17
|
+
? { type: error.type, message: error.message }
|
|
18
|
+
: { type: error.type, message: error.message, data })));
|
|
19
|
+
}
|
|
20
|
+
export const event = Effect.fn("Client.Rpc.event")(function* (definition, name, schema, event) {
|
|
21
|
+
const data = yield* read(schema.schema, event.data);
|
|
22
|
+
// SAFETY: The event type was selected by the caller and data was decoded with this event's schema.
|
|
23
|
+
// oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion
|
|
24
|
+
return {
|
|
25
|
+
...event,
|
|
26
|
+
type: eventType(definition, name),
|
|
27
|
+
data,
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
export function eventType(definition, name) {
|
|
31
|
+
return `rpc.${definition.id}.${name}`;
|
|
32
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
export * as SharedEvents from "./shared-events.js";
|
|
2
|
+
export function make(connect) {
|
|
3
|
+
let current;
|
|
4
|
+
const delivered = Promise.resolve();
|
|
5
|
+
function stop(connection) {
|
|
6
|
+
connection.connected = undefined;
|
|
7
|
+
connection.controller.abort();
|
|
8
|
+
if (current === connection)
|
|
9
|
+
current = undefined;
|
|
10
|
+
}
|
|
11
|
+
async function run(connection) {
|
|
12
|
+
let iterator;
|
|
13
|
+
let completion = {};
|
|
14
|
+
try {
|
|
15
|
+
if (connection.controller.signal.aborted)
|
|
16
|
+
return;
|
|
17
|
+
iterator = connect(connection.controller.signal)[Symbol.asyncIterator]();
|
|
18
|
+
while (!connection.controller.signal.aborted) {
|
|
19
|
+
const item = await iterator.next();
|
|
20
|
+
if (item.done || connection.controller.signal.aborted)
|
|
21
|
+
break;
|
|
22
|
+
if (item.value.type === "server.connected")
|
|
23
|
+
connection.connected = item.value;
|
|
24
|
+
await Promise.all(Array.from(connection.subscribers, (subscriber) => subscriber.push(item.value)));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
completion = { error };
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
stop(connection);
|
|
32
|
+
try {
|
|
33
|
+
await iterator?.return?.();
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (!("error" in completion))
|
|
37
|
+
completion = { error };
|
|
38
|
+
}
|
|
39
|
+
connection.subscribers.forEach((subscriber) => subscriber.finish(completion));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
subscribe(options) {
|
|
44
|
+
return {
|
|
45
|
+
[Symbol.asyncIterator]() {
|
|
46
|
+
const pending = [];
|
|
47
|
+
let started = false;
|
|
48
|
+
let completion;
|
|
49
|
+
let connection;
|
|
50
|
+
let offered;
|
|
51
|
+
function finish(result) {
|
|
52
|
+
completion = result;
|
|
53
|
+
offered?.accepted.resolve();
|
|
54
|
+
offered = undefined;
|
|
55
|
+
options?.signal?.removeEventListener("abort", abort);
|
|
56
|
+
if (connection?.subscribers.delete(subscriber) && !connection.subscribers.size)
|
|
57
|
+
stop(connection);
|
|
58
|
+
pending.splice(0).forEach((request) => {
|
|
59
|
+
if ("error" in result)
|
|
60
|
+
request.reject(result.error);
|
|
61
|
+
else
|
|
62
|
+
request.resolve({ done: true, value: undefined });
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function abort() {
|
|
66
|
+
finish({});
|
|
67
|
+
}
|
|
68
|
+
const subscriber = {
|
|
69
|
+
finish,
|
|
70
|
+
push(value) {
|
|
71
|
+
if (completion)
|
|
72
|
+
return delivered;
|
|
73
|
+
const request = pending.shift();
|
|
74
|
+
if (request) {
|
|
75
|
+
request.resolve({ done: false, value });
|
|
76
|
+
return delivered;
|
|
77
|
+
}
|
|
78
|
+
const accepted = Promise.withResolvers();
|
|
79
|
+
offered = { value, accepted };
|
|
80
|
+
return accepted.promise;
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
function start() {
|
|
84
|
+
if (completion)
|
|
85
|
+
return;
|
|
86
|
+
const fresh = !current;
|
|
87
|
+
connection = current ?? {
|
|
88
|
+
controller: new AbortController(),
|
|
89
|
+
subscribers: new Set(),
|
|
90
|
+
};
|
|
91
|
+
current = connection;
|
|
92
|
+
connection.subscribers.add(subscriber);
|
|
93
|
+
if (connection.connected)
|
|
94
|
+
void subscriber.push(connection.connected);
|
|
95
|
+
if (fresh)
|
|
96
|
+
void run(connection);
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
next() {
|
|
100
|
+
if (offered) {
|
|
101
|
+
const current = offered;
|
|
102
|
+
offered = undefined;
|
|
103
|
+
current.accepted.resolve();
|
|
104
|
+
return Promise.resolve({ done: false, value: current.value });
|
|
105
|
+
}
|
|
106
|
+
if (completion) {
|
|
107
|
+
if ("error" in completion)
|
|
108
|
+
return Promise.reject(completion.error);
|
|
109
|
+
return Promise.resolve({ done: true, value: undefined });
|
|
110
|
+
}
|
|
111
|
+
if (options?.signal?.aborted) {
|
|
112
|
+
abort();
|
|
113
|
+
return Promise.resolve({ done: true, value: undefined });
|
|
114
|
+
}
|
|
115
|
+
const request = Promise.withResolvers();
|
|
116
|
+
pending.push(request);
|
|
117
|
+
if (!started) {
|
|
118
|
+
started = true;
|
|
119
|
+
options?.signal?.addEventListener("abort", abort, { once: true });
|
|
120
|
+
start();
|
|
121
|
+
}
|
|
122
|
+
return request.promise;
|
|
123
|
+
},
|
|
124
|
+
return() {
|
|
125
|
+
finish({});
|
|
126
|
+
return Promise.resolve({ done: true, value: undefined });
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
package/dist/solid/connection.js
CHANGED
|
@@ -62,7 +62,7 @@ export function createClientConnection(initialApi, options) {
|
|
|
62
62
|
return { error: undefined, connectedAt };
|
|
63
63
|
if (event.done)
|
|
64
64
|
return { error: new Error("Event stream disconnected"), connectedAt };
|
|
65
|
-
if ("durable" in event.value)
|
|
65
|
+
if ("durable" in event.value && event.value.durable)
|
|
66
66
|
options.log?.debug?.("event", {
|
|
67
67
|
type: event.value.type,
|
|
68
68
|
aggregateID: event.value.durable.aggregateID,
|
package/dist/solid/data.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import type { AgentInfo, CommandInfo, FormCancelInput, FormInfo, FormReplyInput, IntegrationInfo, LocationRef, LocationGetOutput, McpResource, McpServer, ModelInfo, ModelRef, PermissionSavedInfo, PermissionRequest, PermissionReplyInput, Project, ProviderInfo, ReferenceInfo, SessionMessageInfo, SessionInfo, SessionInboxInfo, SessionInboxCompaction, ShellInfo, SkillInfo, VcsInfo, OpenCodeEvent, OpenCodeClient, WebSearchProvider } from "../promise";
|
|
2
2
|
import { type SessionPromptInput } from "../promise";
|
|
3
3
|
export type DataSessionStatus = "idle" | "running";
|
|
4
|
+
type OpenCodeEventMap = {
|
|
5
|
+
[Type in OpenCodeEvent["type"]]: Extract<OpenCodeEvent, {
|
|
6
|
+
type: Type;
|
|
7
|
+
}>;
|
|
8
|
+
};
|
|
4
9
|
export type CreateDataInput = {
|
|
5
10
|
readonly api: () => OpenCodeClient;
|
|
6
11
|
readonly directory: string;
|
|
7
12
|
readonly event: {
|
|
8
|
-
readonly on: <Type extends OpenCodeEvent["type"]>(type: Type, handler: (event:
|
|
9
|
-
type: Type;
|
|
10
|
-
}>) => void) => () => void;
|
|
13
|
+
readonly on: <Type extends OpenCodeEvent["type"]>(type: Type, handler: (event: OpenCodeEventMap[Type]) => void) => () => void;
|
|
11
14
|
readonly listen: (handler: (event: {
|
|
12
15
|
name: OpenCodeEvent["type"];
|
|
13
16
|
details: OpenCodeEvent;
|
|
@@ -25,9 +28,7 @@ type ShellWithLocation = ShellInfo & {
|
|
|
25
28
|
};
|
|
26
29
|
export declare function locationKey(location: LocationRef): string;
|
|
27
30
|
export declare function createData(config: CreateDataInput): {
|
|
28
|
-
on: <Type extends OpenCodeEvent["type"]>(type: Type, handler: (event:
|
|
29
|
-
type: Type;
|
|
30
|
-
}>) => void) => () => void;
|
|
31
|
+
on: <Type extends OpenCodeEvent["type"]>(type: Type, handler: (event: OpenCodeEventMap[Type]) => void) => () => void;
|
|
31
32
|
listen: (handler: (event: {
|
|
32
33
|
name: OpenCodeEvent["type"];
|
|
33
34
|
details: OpenCodeEvent;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@opencode-ai/client",
|
|
4
|
-
"version": "0.0.0-dev-
|
|
4
|
+
"version": "0.0.0-dev-18709",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"typecheck": "tsgo --noEmit"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@opencode-ai/schema": "0.0.0-dev-
|
|
61
|
-
"@opencode-ai/protocol": "0.0.0-dev-
|
|
60
|
+
"@opencode-ai/schema": "0.0.0-dev-18709",
|
|
61
|
+
"@opencode-ai/protocol": "0.0.0-dev-18709"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"effect": "4.0.0-rc.112",
|
|
@@ -74,11 +74,12 @@
|
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
77
|
-
"@opencode-ai/httpapi-codegen": "0.0.0-dev-
|
|
77
|
+
"@opencode-ai/httpapi-codegen": "0.0.0-dev-18709",
|
|
78
78
|
"@tsconfig/bun": "1.0.9",
|
|
79
79
|
"@types/bun": "1.3.13",
|
|
80
80
|
"@typescript/native-preview": "7.0.0-dev.20251207.1",
|
|
81
81
|
"effect": "4.0.0-rc.112",
|
|
82
|
-
"solid-js": "1.9.15"
|
|
82
|
+
"solid-js": "1.9.15",
|
|
83
|
+
"zod": "4.1.8"
|
|
83
84
|
}
|
|
84
85
|
}
|