@opencode-ai/client 0.0.0-dev-18400 → 0.0.0-dev-18407
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 +10 -0
- package/dist/effect/generated/client.d.ts +2 -1
- package/dist/effect/generated/client.js +2 -0
- package/dist/effect/service.js +16 -2
- package/dist/promise/generated/client.d.ts +2 -1
- package/dist/promise/generated/client.js +7 -0
- package/dist/promise/generated/types.d.ts +9 -0
- package/dist/promise/service.js +17 -4
- package/dist/pty-handoff.d.ts +9 -0
- package/dist/pty-handoff.js +121 -0
- package/dist/service-contender.d.ts +1 -1
- package/package.json +4 -4
package/dist/effect/api/api.d.ts
CHANGED
|
@@ -2115,6 +2115,15 @@ export type ExperimentalPersistentPtyCreateOutput = {
|
|
|
2115
2115
|
export type ExperimentalPersistentPtyCreateOperation<E = never> = (input: ExperimentalPersistentPtyCreateInput) => Effect.Effect<ExperimentalPersistentPtyCreateOutput, E>;
|
|
2116
2116
|
export type ExperimentalPersistentPtyShutdownOutput = void;
|
|
2117
2117
|
export type ExperimentalPersistentPtyShutdownOperation<E = never> = () => Effect.Effect<ExperimentalPersistentPtyShutdownOutput, E>;
|
|
2118
|
+
export type ExperimentalPersistentPtyHandoffOutput = {
|
|
2119
|
+
readonly handoff: {
|
|
2120
|
+
readonly directory: string;
|
|
2121
|
+
readonly instanceID: string;
|
|
2122
|
+
readonly ticket: string;
|
|
2123
|
+
readonly expiresAt: number;
|
|
2124
|
+
} | null;
|
|
2125
|
+
};
|
|
2126
|
+
export type ExperimentalPersistentPtyHandoffOperation<E = never> = () => Effect.Effect<ExperimentalPersistentPtyHandoffOutput, E>;
|
|
2118
2127
|
export type ExperimentalPersistentPtyGetInput = {
|
|
2119
2128
|
readonly ptyID: Pty.ID;
|
|
2120
2129
|
};
|
|
@@ -2216,6 +2225,7 @@ export interface ExperimentalApi<E = never> {
|
|
|
2216
2225
|
readonly list: ExperimentalPersistentPtyListOperation<E>;
|
|
2217
2226
|
readonly create: ExperimentalPersistentPtyCreateOperation<E>;
|
|
2218
2227
|
readonly shutdown: ExperimentalPersistentPtyShutdownOperation<E>;
|
|
2228
|
+
readonly handoff: ExperimentalPersistentPtyHandoffOperation<E>;
|
|
2219
2229
|
readonly get: ExperimentalPersistentPtyGetOperation<E>;
|
|
2220
2230
|
readonly update: ExperimentalPersistentPtyUpdateOperation<E>;
|
|
2221
2231
|
readonly snapshot: ExperimentalPersistentPtySnapshotOperation<E>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Effect, Stream, Schema } from "effect";
|
|
2
2
|
import { Sse } from "effect/unstable/encoding";
|
|
3
3
|
import { HttpClientError } from "effect/unstable/http";
|
|
4
|
-
import type { HealthGetOutput, ServerGetOutput, LocationGetInput, AgentListInput, AgentListOutput, AgentGetInput, AgentGetOutput, PluginListInput, PluginListOutput, SessionListInput, SessionListOutput, SessionStatsInput, SessionStatsOutput, SessionCreateInput, SessionImportInput, SessionExportInput, SessionExportOutput, SessionActiveOutput, SessionGetInput, SessionRemoveInput, SessionForkInput, SessionSwitchAgentInput, SessionSwitchModelInput, SessionRenameInput, SessionMoveInput, SessionPromptInput, SessionCommandInput, SessionSkillInput, SessionSyntheticInput, SessionShellInput, SessionCompactInput, SessionWaitInput, SessionRevertStageInput, SessionRevertClearInput, SessionRevertCommitInput, SessionContextInput, SessionContextOutput, SessionInboxListInput, SessionInboxListOutput, SessionInboxCancelInput, SessionInboxSteerInput, SessionInboxQueueInput, SessionInstructionsEntryListInput, SessionInstructionsEntryListOutput, SessionInstructionsEntryPutInput, SessionInstructionsEntryRemoveInput, SessionGenerateInput, SessionGenerateOutput, SessionLogInput, SessionLogOutput, SessionInterruptInput, SessionInterruptOutput, SessionBackgroundInput, SessionMessageInput, SessionMessageUpdateInput, SessionEnvironmentInput, SessionViewInput, MessageListInput, MessageListOutput, ModelListInput, ModelListOutput, ModelDefaultInput, ModelDefaultOutput, GenerateTextInput, GenerateTextOutput, ProviderListInput, ProviderListOutput, ProviderGetInput, ProviderGetOutput, IntegrationListInput, IntegrationListOutput, IntegrationGetInput, IntegrationGetOutput, IntegrationWellknownAddInput, IntegrationConnectKeyInput, IntegrationOauthConnectInput, IntegrationOauthConnectOutput, IntegrationOauthStatusInput, IntegrationOauthStatusOutput, IntegrationOauthCompleteInput, IntegrationOauthCancelInput, IntegrationCommandConnectInput, IntegrationCommandConnectOutput, IntegrationCommandStatusInput, IntegrationCommandStatusOutput, IntegrationCommandCancelInput, McpListInput, McpListOutput, McpAddInput, McpRemoveInput, McpConnectInput, McpDisconnectInput, McpResourceCatalogInput, McpResourceCatalogOutput, CredentialUpdateInput, CredentialActivateInput, CredentialRemoveInput, ProjectListOutput, ProjectUpdateInput, ProjectCurrentInput, FormRequestListInput, FormRequestListOutput, FormListInput, FormListOutput, FormCreateInput, FormGetInput, FormStateInput, FormReplyInput, FormCancelInput, PermissionRequestListInput, PermissionRequestListOutput, PermissionSavedListInput, PermissionSavedListOutput, PermissionSavedRemoveInput, PermissionCreateInput, PermissionCreateOutput, PermissionListInput, PermissionListOutput, PermissionGetInput, PermissionReplyInput, FileListInput, FileListOutput, FileFindInput, FileFindOutput, CommandListInput, CommandListOutput, SkillListInput, SkillListOutput, PtyListInput, PtyListOutput, PtyCreateInput, PtyCreateOutput, PtyGetInput, PtyGetOutput, PtyUpdateInput, PtyUpdateOutput, PtyRemoveInput, PtyConnectTokenInput, PtyConnectTokenOutput, ExperimentalPersistentPtyListInput, ExperimentalPersistentPtyListOutput, ExperimentalPersistentPtyCreateInput, ExperimentalPersistentPtyCreateOutput, ExperimentalPersistentPtyGetInput, ExperimentalPersistentPtyGetOutput, ExperimentalPersistentPtyUpdateInput, ExperimentalPersistentPtyUpdateOutput, ExperimentalPersistentPtySnapshotInput, ExperimentalPersistentPtySnapshotOutput, ExperimentalPersistentPtyRemoveInput, ExperimentalPersistentPtyConnectTokenInput, ShellListInput, ShellListOutput, ShellCreateInput, ShellCreateOutput, ShellGetInput, ShellGetOutput, ShellTimeoutInput, ShellTimeoutOutput, ShellOutputInput, ShellOutputOutput, ShellRemoveInput, ReferenceListInput, ReferenceListOutput, WorktreeListInput, WorktreeCreateInput, WorktreeRemoveInput, WorktreeRefreshInput, WorkspaceCreateInput, WorkspaceDestroyInput, VcsGetInput, VcsGetOutput, VcsStatusInput, VcsStatusOutput, VcsBranchesInput, VcsBranchesOutput, VcsDiffInput, VcsDiffOutput, DebugLocationListOutput, DebugLocationEvictInput, MigrationV1StatusOutput, WebsearchProvidersInput, WebsearchProvidersOutput, WebsearchQueryInput, WebsearchQueryOutput, ConfigGetInput, ConfigGetOutput } from "../api/api.js";
|
|
4
|
+
import type { HealthGetOutput, ServerGetOutput, LocationGetInput, AgentListInput, AgentListOutput, AgentGetInput, AgentGetOutput, PluginListInput, PluginListOutput, SessionListInput, SessionListOutput, SessionStatsInput, SessionStatsOutput, SessionCreateInput, SessionImportInput, SessionExportInput, SessionExportOutput, SessionActiveOutput, SessionGetInput, SessionRemoveInput, SessionForkInput, SessionSwitchAgentInput, SessionSwitchModelInput, SessionRenameInput, SessionMoveInput, SessionPromptInput, SessionCommandInput, SessionSkillInput, SessionSyntheticInput, SessionShellInput, SessionCompactInput, SessionWaitInput, SessionRevertStageInput, SessionRevertClearInput, SessionRevertCommitInput, SessionContextInput, SessionContextOutput, SessionInboxListInput, SessionInboxListOutput, SessionInboxCancelInput, SessionInboxSteerInput, SessionInboxQueueInput, SessionInstructionsEntryListInput, SessionInstructionsEntryListOutput, SessionInstructionsEntryPutInput, SessionInstructionsEntryRemoveInput, SessionGenerateInput, SessionGenerateOutput, SessionLogInput, SessionLogOutput, SessionInterruptInput, SessionInterruptOutput, SessionBackgroundInput, SessionMessageInput, SessionMessageUpdateInput, SessionEnvironmentInput, SessionViewInput, MessageListInput, MessageListOutput, ModelListInput, ModelListOutput, ModelDefaultInput, ModelDefaultOutput, GenerateTextInput, GenerateTextOutput, ProviderListInput, ProviderListOutput, ProviderGetInput, ProviderGetOutput, IntegrationListInput, IntegrationListOutput, IntegrationGetInput, IntegrationGetOutput, IntegrationWellknownAddInput, IntegrationConnectKeyInput, IntegrationOauthConnectInput, IntegrationOauthConnectOutput, IntegrationOauthStatusInput, IntegrationOauthStatusOutput, IntegrationOauthCompleteInput, IntegrationOauthCancelInput, IntegrationCommandConnectInput, IntegrationCommandConnectOutput, IntegrationCommandStatusInput, IntegrationCommandStatusOutput, IntegrationCommandCancelInput, McpListInput, McpListOutput, McpAddInput, McpRemoveInput, McpConnectInput, McpDisconnectInput, McpResourceCatalogInput, McpResourceCatalogOutput, CredentialUpdateInput, CredentialActivateInput, CredentialRemoveInput, ProjectListOutput, ProjectUpdateInput, ProjectCurrentInput, FormRequestListInput, FormRequestListOutput, FormListInput, FormListOutput, FormCreateInput, FormGetInput, FormStateInput, FormReplyInput, FormCancelInput, PermissionRequestListInput, PermissionRequestListOutput, PermissionSavedListInput, PermissionSavedListOutput, PermissionSavedRemoveInput, PermissionCreateInput, PermissionCreateOutput, PermissionListInput, PermissionListOutput, PermissionGetInput, PermissionReplyInput, FileListInput, FileListOutput, FileFindInput, FileFindOutput, CommandListInput, CommandListOutput, SkillListInput, SkillListOutput, PtyListInput, PtyListOutput, PtyCreateInput, PtyCreateOutput, PtyGetInput, PtyGetOutput, PtyUpdateInput, PtyUpdateOutput, PtyRemoveInput, PtyConnectTokenInput, PtyConnectTokenOutput, ExperimentalPersistentPtyListInput, ExperimentalPersistentPtyListOutput, ExperimentalPersistentPtyCreateInput, ExperimentalPersistentPtyCreateOutput, ExperimentalPersistentPtyHandoffOutput, ExperimentalPersistentPtyGetInput, ExperimentalPersistentPtyGetOutput, ExperimentalPersistentPtyUpdateInput, ExperimentalPersistentPtyUpdateOutput, ExperimentalPersistentPtySnapshotInput, ExperimentalPersistentPtySnapshotOutput, ExperimentalPersistentPtyRemoveInput, ExperimentalPersistentPtyConnectTokenInput, ShellListInput, ShellListOutput, ShellCreateInput, ShellCreateOutput, ShellGetInput, ShellGetOutput, ShellTimeoutInput, ShellTimeoutOutput, ShellOutputInput, ShellOutputOutput, ShellRemoveInput, ReferenceListInput, ReferenceListOutput, WorktreeListInput, WorktreeCreateInput, WorktreeRemoveInput, WorktreeRefreshInput, WorkspaceCreateInput, WorkspaceDestroyInput, VcsGetInput, VcsGetOutput, VcsStatusInput, VcsStatusOutput, VcsBranchesInput, VcsBranchesOutput, VcsDiffInput, VcsDiffOutput, DebugLocationListOutput, DebugLocationEvictInput, MigrationV1StatusOutput, WebsearchProvidersInput, WebsearchProvidersOutput, WebsearchQueryInput, WebsearchQueryOutput, ConfigGetInput, ConfigGetOutput } from "../api/api.js";
|
|
5
5
|
import { ClientError } from "./client-error.js";
|
|
6
6
|
export declare const make: (options?: {
|
|
7
7
|
readonly baseUrl?: URL | string;
|
|
@@ -2444,6 +2444,7 @@ export declare const make: (options?: {
|
|
|
2444
2444
|
list: (input: ExperimentalPersistentPtyListInput) => Effect.Effect<ExperimentalPersistentPtyListOutput, import("@opencode-ai/protocol/errors").InvalidRequestError | import("@opencode-ai/protocol/errors").UnauthorizedError | import("@opencode-ai/protocol/errors").ServiceUnavailableError | Schema.SchemaError | ClientError | HttpClientError.HttpClientError, never>;
|
|
2445
2445
|
create: (input: ExperimentalPersistentPtyCreateInput) => Effect.Effect<ExperimentalPersistentPtyCreateOutput, import("@opencode-ai/protocol/errors").InvalidRequestError | import("@opencode-ai/protocol/errors").UnauthorizedError | import("@opencode-ai/protocol/errors").ServiceUnavailableError | Schema.SchemaError | ClientError | HttpClientError.HttpClientError, never>;
|
|
2446
2446
|
shutdown: () => Effect.Effect<void, import("@opencode-ai/protocol/errors").InvalidRequestError | import("@opencode-ai/protocol/errors").UnauthorizedError | import("@opencode-ai/protocol/errors").ServiceUnavailableError | Schema.SchemaError | ClientError | HttpClientError.HttpClientError, never>;
|
|
2447
|
+
handoff: () => Effect.Effect<ExperimentalPersistentPtyHandoffOutput, import("@opencode-ai/protocol/errors").InvalidRequestError | import("@opencode-ai/protocol/errors").UnauthorizedError | import("@opencode-ai/protocol/errors").ServiceUnavailableError | Schema.SchemaError | ClientError | HttpClientError.HttpClientError, never>;
|
|
2447
2448
|
get: (input: ExperimentalPersistentPtyGetInput) => Effect.Effect<ExperimentalPersistentPtyGetOutput, import("@opencode-ai/protocol/errors").InvalidRequestError | import("@opencode-ai/protocol/errors").UnauthorizedError | import("@opencode-ai/protocol/errors").ServiceUnavailableError | import("@opencode-ai/protocol/errors").PtyNotFoundError | Schema.SchemaError | ClientError | HttpClientError.HttpClientError, never>;
|
|
2448
2449
|
update: (input: ExperimentalPersistentPtyUpdateInput) => Effect.Effect<ExperimentalPersistentPtyUpdateOutput, import("@opencode-ai/protocol/errors").InvalidRequestError | import("@opencode-ai/protocol/errors").UnauthorizedError | import("@opencode-ai/protocol/errors").ServiceUnavailableError | import("@opencode-ai/protocol/errors").PtyNotFoundError | Schema.SchemaError | ClientError | HttpClientError.HttpClientError, never>;
|
|
2449
2450
|
snapshot: (input: ExperimentalPersistentPtySnapshotInput) => Effect.Effect<ExperimentalPersistentPtySnapshotOutput, import("@opencode-ai/protocol/errors").InvalidRequestError | import("@opencode-ai/protocol/errors").UnauthorizedError | import("@opencode-ai/protocol/errors").ServiceUnavailableError | import("@opencode-ai/protocol/errors").PtyNotFoundError | Schema.SchemaError | ClientError | HttpClientError.HttpClientError, never>;
|
|
@@ -435,6 +435,7 @@ const EndpointExperimentalPersistentPtyCreate = (raw) => (input) => preserveEffe
|
|
|
435
435
|
},
|
|
436
436
|
}).pipe(Effect.mapError(mapClientError), Effect.map((value) => value.data)));
|
|
437
437
|
const EndpointExperimentalPersistentPtyShutdown = (raw) => () => preserveEffect()(raw["persistentPty.shutdown"]({}).pipe(Effect.mapError(mapClientError)));
|
|
438
|
+
const EndpointExperimentalPersistentPtyHandoff = (raw) => () => preserveEffect()(raw["persistentPty.handoff"]({}).pipe(Effect.mapError(mapClientError)));
|
|
438
439
|
const EndpointExperimentalPersistentPtyGet = (raw) => (input) => preserveEffect()(raw["persistentPty.get"]({ params: { ptyID: input["ptyID"] } }).pipe(Effect.mapError(mapClientError), Effect.map((value) => value.data)));
|
|
439
440
|
const EndpointExperimentalPersistentPtyUpdate = (raw) => (input) => preserveEffect()(raw["persistentPty.update"]({
|
|
440
441
|
params: { ptyID: input["ptyID"] },
|
|
@@ -451,6 +452,7 @@ const adaptGroupExperimental = (raw) => ({
|
|
|
451
452
|
list: EndpointExperimentalPersistentPtyList(raw),
|
|
452
453
|
create: EndpointExperimentalPersistentPtyCreate(raw),
|
|
453
454
|
shutdown: EndpointExperimentalPersistentPtyShutdown(raw),
|
|
455
|
+
handoff: EndpointExperimentalPersistentPtyHandoff(raw),
|
|
454
456
|
get: EndpointExperimentalPersistentPtyGet(raw),
|
|
455
457
|
update: EndpointExperimentalPersistentPtyUpdate(raw),
|
|
456
458
|
snapshot: EndpointExperimentalPersistentPtySnapshot(raw),
|
package/dist/effect/service.js
CHANGED
|
@@ -5,6 +5,7 @@ import { join } from "node:path";
|
|
|
5
5
|
import { contenderFailure, contenderFinished, spawnServiceContender, } from "../service-contender.js";
|
|
6
6
|
import { defaultEnsureTiming, ensureTiming } from "../service-timing.js";
|
|
7
7
|
import { matchesVersion } from "../service-version.js";
|
|
8
|
+
import { PtyHandoff } from "../pty-handoff.js";
|
|
8
9
|
export * from "../service.js";
|
|
9
10
|
// Find, start, and stop the local opencode background service.
|
|
10
11
|
//
|
|
@@ -55,9 +56,10 @@ export const ensure = Effect.fn("service.ensure")(function* (options = {}) {
|
|
|
55
56
|
const [command, ...args] = options.command ?? ["opencode", "serve", "--service"];
|
|
56
57
|
if (command === undefined)
|
|
57
58
|
return yield* Effect.fail(new Error("Missing service command"));
|
|
59
|
+
const env = yield* Effect.tryPromise(() => PtyHandoff.environment(options.file ?? fallback(), options.env));
|
|
58
60
|
return yield* Effect.try({
|
|
59
61
|
try: () => {
|
|
60
|
-
return spawnServiceContender(command, args,
|
|
62
|
+
return spawnServiceContender(command, args, env);
|
|
61
63
|
},
|
|
62
64
|
catch: (cause) => new Error("Failed to start server", { cause }),
|
|
63
65
|
});
|
|
@@ -73,6 +75,8 @@ export const ensure = Effect.fn("service.ensure")(function* (options = {}) {
|
|
|
73
75
|
};
|
|
74
76
|
if (timeouts.count >= 3) {
|
|
75
77
|
yield* announce("missing");
|
|
78
|
+
yield* Effect.logWarning("Background service is unresponsive; recovery cannot preserve persistent terminals");
|
|
79
|
+
yield* Effect.tryPromise(() => PtyHandoff.clear(options.file ?? fallback()));
|
|
76
80
|
yield* terminate(info, options, timing);
|
|
77
81
|
timeouts = undefined;
|
|
78
82
|
lastSpawn = Date.now() - spawnDelay;
|
|
@@ -83,13 +87,22 @@ export const ensure = Effect.fn("service.ensure")(function* (options = {}) {
|
|
|
83
87
|
if (service !== undefined) {
|
|
84
88
|
spawnDelay = timing.spawnDelay;
|
|
85
89
|
const compatible = !service.legacy && matchesVersion(service.version, options);
|
|
86
|
-
if (compatible && service.state === "ready")
|
|
90
|
+
if (compatible && service.state === "ready") {
|
|
91
|
+
yield* Effect.tryPromise(() => PtyHandoff.complete(options.file ?? fallback(), service.info));
|
|
87
92
|
return Option.some(service);
|
|
93
|
+
}
|
|
88
94
|
if (compatible && service.state === "failed")
|
|
89
95
|
return yield* Effect.fail(new Error("Background service failed to start"));
|
|
90
96
|
if (compatible)
|
|
91
97
|
return Option.none();
|
|
92
98
|
yield* announce("version-mismatch", service.version);
|
|
99
|
+
if (!service.legacy && service.state === "ready")
|
|
100
|
+
yield* Effect.tryPromise(() => PtyHandoff.prepare(options.file ?? fallback(), service.info, timing.requestTimeout));
|
|
101
|
+
else {
|
|
102
|
+
if (!service.legacy)
|
|
103
|
+
yield* Effect.logWarning("Background service is not ready; replacement cannot preserve persistent terminals");
|
|
104
|
+
yield* Effect.tryPromise(() => PtyHandoff.clear(options.file ?? fallback()));
|
|
105
|
+
}
|
|
93
106
|
yield* terminate(service.info, options, timing).pipe(Effect.ignore);
|
|
94
107
|
lastSpawn = 0;
|
|
95
108
|
return Option.none();
|
|
@@ -121,6 +134,7 @@ export const ensure = Effect.fn("service.ensure")(function* (options = {}) {
|
|
|
121
134
|
});
|
|
122
135
|
/** Stop the registered local service. */
|
|
123
136
|
export const stop = Effect.fn("service.stop")(function* (options = {}) {
|
|
137
|
+
yield* Effect.tryPromise(() => PtyHandoff.clear(options.file ?? fallback()));
|
|
124
138
|
const info = yield* read(options.file);
|
|
125
139
|
if (info !== undefined)
|
|
126
140
|
yield* terminate(info, options, defaultEnsureTiming);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ServerGetOutput, LocationGetInput, LocationGetOutput, AgentListInput, AgentListOutput, AgentGetInput, AgentGetOutput, PluginListInput, PluginListOutput, SessionListInput, SessionStatsInput, SessionCreateInput, SessionImportInput, SessionExportInput, SessionGetInput, SessionRemoveInput, SessionForkInput, SessionSwitchAgentInput, SessionSwitchModelInput, SessionRenameInput, SessionMoveInput, SessionPromptInput, SessionCommandInput, SessionSkillInput, SessionSyntheticInput, SessionShellInput, SessionCompactInput, SessionWaitInput, SessionRevertStageInput, SessionRevertClearInput, SessionRevertCommitInput, SessionContextInput, SessionInboxListInput, SessionInboxCancelInput, SessionInboxSteerInput, SessionInboxQueueInput, SessionInstructionsEntryListInput, SessionInstructionsEntryPutInput, SessionInstructionsEntryRemoveInput, SessionGenerateInput, SessionLogInput, SessionLogOutput, SessionInterruptInput, SessionBackgroundInput, SessionMessageInput, SessionMessageUpdateInput, SessionEnvironmentInput, SessionViewInput, MessageListInput, ModelListInput, ModelListOutput, ModelDefaultInput, ModelDefaultOutput, GenerateTextInput, ProviderListInput, ProviderListOutput, ProviderGetInput, ProviderGetOutput, IntegrationListInput, IntegrationListOutput, IntegrationGetInput, IntegrationGetOutput, IntegrationWellknownAddInput, IntegrationConnectKeyInput, IntegrationOauthConnectInput, IntegrationOauthConnectOutput, IntegrationOauthStatusInput, IntegrationOauthStatusOutput, IntegrationOauthCompleteInput, IntegrationOauthCancelInput, IntegrationCommandConnectInput, IntegrationCommandConnectOutput, IntegrationCommandStatusInput, IntegrationCommandStatusOutput, IntegrationCommandCancelInput, McpListInput, McpListOutput, McpAddInput, McpRemoveInput, McpConnectInput, McpDisconnectInput, McpResourceCatalogInput, McpResourceCatalogOutput, CredentialUpdateInput, CredentialActivateInput, CredentialRemoveInput, ProjectListOutput, ProjectUpdateInput, ProjectCurrentInput, FormRequestListInput, FormRequestListOutput, FormListInput, FormCreateInput, FormGetInput, FormStateInput, FormReplyInput, FormCancelInput, PermissionRequestListInput, PermissionRequestListOutput, PermissionSavedListInput, PermissionSavedRemoveInput, PermissionCreateInput, PermissionListInput, PermissionGetInput, PermissionReplyInput, FileReadInput, FileReadOutput, FileListInput, FileListOutput, FileFindInput, FileFindOutput, CommandListInput, CommandListOutput, SkillListInput, SkillListOutput, EventSubscribeOutput, PtyListInput, PtyListOutput, PtyCreateInput, PtyCreateOutput, PtyGetInput, PtyGetOutput, PtyUpdateInput, PtyUpdateOutput, PtyRemoveInput, PtyConnectTokenInput, PtyConnectTokenOutput, ExperimentalPersistentPtyListInput, ExperimentalPersistentPtyCreateInput, ExperimentalPersistentPtyGetInput, ExperimentalPersistentPtyUpdateInput, ExperimentalPersistentPtySnapshotInput, ExperimentalPersistentPtyRemoveInput, ExperimentalPersistentPtyConnectTokenInput, ShellListInput, ShellListOutput, ShellCreateInput, ShellCreateOutput, ShellGetInput, ShellGetOutput, ShellTimeoutInput, ShellTimeoutOutput, ShellOutputInput, ShellOutputOutput, ShellRemoveInput, ReferenceListInput, ReferenceListOutput, WorktreeListInput, WorktreeCreateInput, WorktreeRemoveInput, WorktreeRefreshInput, WorkspaceCreateInput, WorkspaceDestroyInput, VcsGetInput, VcsGetOutput, VcsStatusInput, VcsStatusOutput, VcsBranchesInput, VcsBranchesOutput, VcsDiffInput, VcsDiffOutput, DebugLocationListOutput, DebugLocationEvictInput, MigrationV1StatusOutput, WebsearchProvidersInput, WebsearchProvidersOutput, WebsearchQueryInput, WebsearchQueryOutput, ConfigGetInput, ConfigGetOutput } from "./types.js";
|
|
1
|
+
import type { ServerGetOutput, LocationGetInput, LocationGetOutput, AgentListInput, AgentListOutput, AgentGetInput, AgentGetOutput, PluginListInput, PluginListOutput, SessionListInput, SessionStatsInput, SessionCreateInput, SessionImportInput, SessionExportInput, SessionGetInput, SessionRemoveInput, SessionForkInput, SessionSwitchAgentInput, SessionSwitchModelInput, SessionRenameInput, SessionMoveInput, SessionPromptInput, SessionCommandInput, SessionSkillInput, SessionSyntheticInput, SessionShellInput, SessionCompactInput, SessionWaitInput, SessionRevertStageInput, SessionRevertClearInput, SessionRevertCommitInput, SessionContextInput, SessionInboxListInput, SessionInboxCancelInput, SessionInboxSteerInput, SessionInboxQueueInput, SessionInstructionsEntryListInput, SessionInstructionsEntryPutInput, SessionInstructionsEntryRemoveInput, SessionGenerateInput, SessionLogInput, SessionLogOutput, SessionInterruptInput, SessionBackgroundInput, SessionMessageInput, SessionMessageUpdateInput, SessionEnvironmentInput, SessionViewInput, MessageListInput, ModelListInput, ModelListOutput, ModelDefaultInput, ModelDefaultOutput, GenerateTextInput, ProviderListInput, ProviderListOutput, ProviderGetInput, ProviderGetOutput, IntegrationListInput, IntegrationListOutput, IntegrationGetInput, IntegrationGetOutput, IntegrationWellknownAddInput, IntegrationConnectKeyInput, IntegrationOauthConnectInput, IntegrationOauthConnectOutput, IntegrationOauthStatusInput, IntegrationOauthStatusOutput, IntegrationOauthCompleteInput, IntegrationOauthCancelInput, IntegrationCommandConnectInput, IntegrationCommandConnectOutput, IntegrationCommandStatusInput, IntegrationCommandStatusOutput, IntegrationCommandCancelInput, McpListInput, McpListOutput, McpAddInput, McpRemoveInput, McpConnectInput, McpDisconnectInput, McpResourceCatalogInput, McpResourceCatalogOutput, CredentialUpdateInput, CredentialActivateInput, CredentialRemoveInput, ProjectListOutput, ProjectUpdateInput, ProjectCurrentInput, FormRequestListInput, FormRequestListOutput, FormListInput, FormCreateInput, FormGetInput, FormStateInput, FormReplyInput, FormCancelInput, PermissionRequestListInput, PermissionRequestListOutput, PermissionSavedListInput, PermissionSavedRemoveInput, PermissionCreateInput, PermissionListInput, PermissionGetInput, PermissionReplyInput, FileReadInput, FileReadOutput, FileListInput, FileListOutput, FileFindInput, FileFindOutput, CommandListInput, CommandListOutput, SkillListInput, SkillListOutput, EventSubscribeOutput, PtyListInput, PtyListOutput, PtyCreateInput, PtyCreateOutput, PtyGetInput, PtyGetOutput, PtyUpdateInput, PtyUpdateOutput, PtyRemoveInput, PtyConnectTokenInput, PtyConnectTokenOutput, ExperimentalPersistentPtyListInput, ExperimentalPersistentPtyCreateInput, ExperimentalPersistentPtyHandoffOutput, ExperimentalPersistentPtyGetInput, ExperimentalPersistentPtyUpdateInput, ExperimentalPersistentPtySnapshotInput, ExperimentalPersistentPtyRemoveInput, ExperimentalPersistentPtyConnectTokenInput, ShellListInput, ShellListOutput, ShellCreateInput, ShellCreateOutput, ShellGetInput, ShellGetOutput, ShellTimeoutInput, ShellTimeoutOutput, ShellOutputInput, ShellOutputOutput, ShellRemoveInput, ReferenceListInput, ReferenceListOutput, WorktreeListInput, WorktreeCreateInput, WorktreeRemoveInput, WorktreeRefreshInput, WorkspaceCreateInput, WorkspaceDestroyInput, VcsGetInput, VcsGetOutput, VcsStatusInput, VcsStatusOutput, VcsBranchesInput, VcsBranchesOutput, VcsDiffInput, VcsDiffOutput, DebugLocationListOutput, DebugLocationEvictInput, MigrationV1StatusOutput, WebsearchProvidersInput, WebsearchProvidersOutput, WebsearchQueryInput, WebsearchQueryOutput, ConfigGetInput, ConfigGetOutput } from "./types.js";
|
|
2
2
|
export interface ClientOptions {
|
|
3
3
|
readonly baseUrl: string;
|
|
4
4
|
readonly fetch?: typeof globalThis.fetch;
|
|
@@ -198,6 +198,7 @@ export declare function make(options: ClientOptions): {
|
|
|
198
198
|
list: (input: ExperimentalPersistentPtyListInput, requestOptions?: RequestOptions) => Promise<import("./types.js").PersistentPtyInfo[]>;
|
|
199
199
|
create: (input: ExperimentalPersistentPtyCreateInput, requestOptions?: RequestOptions) => Promise<import("./types.js").PersistentPtyInfo>;
|
|
200
200
|
shutdown: (requestOptions?: RequestOptions) => Promise<void>;
|
|
201
|
+
handoff: (requestOptions?: RequestOptions) => Promise<ExperimentalPersistentPtyHandoffOutput>;
|
|
201
202
|
get: (input: ExperimentalPersistentPtyGetInput, requestOptions?: RequestOptions) => Promise<import("./types.js").PersistentPtyInfo>;
|
|
202
203
|
update: (input: ExperimentalPersistentPtyUpdateInput, requestOptions?: RequestOptions) => Promise<import("./types.js").PersistentPtyInfo>;
|
|
203
204
|
snapshot: (input: ExperimentalPersistentPtySnapshotInput, requestOptions?: RequestOptions) => Promise<import("./types.js").PersistentPtySnapshot>;
|
|
@@ -1046,6 +1046,13 @@ export function make(options) {
|
|
|
1046
1046
|
declaredStatuses: [503, 401, 400],
|
|
1047
1047
|
empty: true,
|
|
1048
1048
|
}, requestOptions),
|
|
1049
|
+
handoff: (requestOptions) => request({
|
|
1050
|
+
method: "POST",
|
|
1051
|
+
path: `/api/experimental/persistent-pty/handoff`,
|
|
1052
|
+
successStatus: 200,
|
|
1053
|
+
declaredStatuses: [503, 401, 400],
|
|
1054
|
+
empty: false,
|
|
1055
|
+
}, requestOptions),
|
|
1049
1056
|
get: (input, requestOptions) => request({
|
|
1050
1057
|
method: "GET",
|
|
1051
1058
|
path: `/api/experimental/persistent-pty/${encodeURIComponent(input.ptyID)}`,
|
|
@@ -562,6 +562,12 @@ export type PtyTicketConnectToken = {
|
|
|
562
562
|
ticket: string;
|
|
563
563
|
expires_in: number;
|
|
564
564
|
};
|
|
565
|
+
export type PersistentPtyHandoff = {
|
|
566
|
+
directory: string;
|
|
567
|
+
instanceID: string;
|
|
568
|
+
ticket: string;
|
|
569
|
+
expiresAt: number;
|
|
570
|
+
};
|
|
565
571
|
export type ShellInfo1 = {
|
|
566
572
|
id: string;
|
|
567
573
|
status: "running" | "exited" | "timeout" | "killed";
|
|
@@ -7844,6 +7850,9 @@ export type ExperimentalPersistentPtyCreateOutput = {
|
|
|
7844
7850
|
data: PersistentPtyInfo;
|
|
7845
7851
|
}["data"];
|
|
7846
7852
|
export type ExperimentalPersistentPtyShutdownOutput = void;
|
|
7853
|
+
export type ExperimentalPersistentPtyHandoffOutput = {
|
|
7854
|
+
handoff: PersistentPtyHandoff | null;
|
|
7855
|
+
};
|
|
7847
7856
|
export type ExperimentalPersistentPtyGetInput = {
|
|
7848
7857
|
readonly ptyID: {
|
|
7849
7858
|
readonly ptyID: string;
|
package/dist/promise/service.js
CHANGED
|
@@ -4,6 +4,7 @@ import { join } from "node:path";
|
|
|
4
4
|
import { contenderFailure, contenderFinished, spawnServiceContender, } from "../service-contender.js";
|
|
5
5
|
import { defaultEnsureTiming, ensureTiming } from "../service-timing.js";
|
|
6
6
|
import { matchesVersion } from "../service-version.js";
|
|
7
|
+
import { PtyHandoff } from "../pty-handoff.js";
|
|
7
8
|
export * from "../service.js";
|
|
8
9
|
// Find, start, and stop the local opencode background service.
|
|
9
10
|
//
|
|
@@ -34,12 +35,12 @@ export async function ensure(options = {}) {
|
|
|
34
35
|
announced = true;
|
|
35
36
|
options.onStart?.(reason, previousVersion);
|
|
36
37
|
};
|
|
37
|
-
const spawnContender = () => {
|
|
38
|
+
const spawnContender = async () => {
|
|
38
39
|
const [command, ...args] = options.command ?? ["opencode", "serve", "--service"];
|
|
39
40
|
if (command === undefined)
|
|
40
41
|
throw new Error("Missing service command");
|
|
41
42
|
try {
|
|
42
|
-
return spawnServiceContender(command, args, options.env);
|
|
43
|
+
return spawnServiceContender(command, args, await PtyHandoff.environment(options.file ?? fallback(), options.env));
|
|
43
44
|
}
|
|
44
45
|
catch (cause) {
|
|
45
46
|
throw new Error("Failed to start server", { cause });
|
|
@@ -57,6 +58,8 @@ export async function ensure(options = {}) {
|
|
|
57
58
|
};
|
|
58
59
|
if (timeouts.count >= 3) {
|
|
59
60
|
announce("missing");
|
|
61
|
+
console.warn("Background service is unresponsive; recovery cannot preserve persistent terminals");
|
|
62
|
+
await PtyHandoff.clear(options.file ?? fallback());
|
|
60
63
|
await terminate(registration.info, options, timing);
|
|
61
64
|
timeouts = undefined;
|
|
62
65
|
lastSpawn = Date.now() - spawnDelay;
|
|
@@ -68,12 +71,21 @@ export async function ensure(options = {}) {
|
|
|
68
71
|
spawnDelay = timing.spawnDelay;
|
|
69
72
|
const service = registration.service;
|
|
70
73
|
const compatible = !service.legacy && matchesVersion(service.version, options);
|
|
71
|
-
if (compatible && service.state === "ready")
|
|
74
|
+
if (compatible && service.state === "ready") {
|
|
75
|
+
await PtyHandoff.complete(options.file ?? fallback(), service.info);
|
|
72
76
|
return service.endpoint;
|
|
77
|
+
}
|
|
73
78
|
if (compatible && service.state === "failed")
|
|
74
79
|
throw new Error("Background service failed to start");
|
|
75
80
|
if (!compatible) {
|
|
76
81
|
announce("version-mismatch", service.version);
|
|
82
|
+
if (!service.legacy && service.state === "ready")
|
|
83
|
+
await PtyHandoff.prepare(options.file ?? fallback(), service.info, timing.requestTimeout);
|
|
84
|
+
else {
|
|
85
|
+
if (!service.legacy)
|
|
86
|
+
console.warn("Background service is not ready; replacement cannot preserve persistent terminals");
|
|
87
|
+
await PtyHandoff.clear(options.file ?? fallback());
|
|
88
|
+
}
|
|
77
89
|
await terminate(service.info, options, timing).catch(() => undefined);
|
|
78
90
|
lastSpawn = 0;
|
|
79
91
|
}
|
|
@@ -92,7 +104,7 @@ export async function ensure(options = {}) {
|
|
|
92
104
|
// Keep one candidate plus one lock probe so a pre-lock stall cannot block recovery.
|
|
93
105
|
if (contenders.size < 2 && Date.now() - lastSpawn >= spawnDelay) {
|
|
94
106
|
announce("missing");
|
|
95
|
-
contenders.add(spawnContender());
|
|
107
|
+
contenders.add(await spawnContender());
|
|
96
108
|
lastSpawn = Date.now();
|
|
97
109
|
}
|
|
98
110
|
}
|
|
@@ -105,6 +117,7 @@ export async function ensure(options = {}) {
|
|
|
105
117
|
}
|
|
106
118
|
/** Stop the registered local service. */
|
|
107
119
|
export async function stop(options = {}) {
|
|
120
|
+
await PtyHandoff.clear(options.file ?? fallback());
|
|
108
121
|
const info = await read(options.file);
|
|
109
122
|
if (info !== undefined)
|
|
110
123
|
await terminate(info, options, defaultEnsureTiming);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * as PtyHandoff from "./pty-handoff.js";
|
|
2
|
+
import type { Info } from "./service.js";
|
|
3
|
+
/** Publish the ticket before stopping its owner so every replacement contender can adopt it. */
|
|
4
|
+
export declare function prepare(file: string, info: Info, timeout: number): Promise<void>;
|
|
5
|
+
export declare function environment(file: string, env?: Readonly<Record<string, string>>): Promise<{
|
|
6
|
+
OPENCODE_PTY_HANDOFF: string | undefined;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function complete(file: string, info: Info): Promise<void>;
|
|
9
|
+
export declare function clear(file: string): Promise<void>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
export * as PtyHandoff from "./pty-handoff.js";
|
|
2
|
+
import { readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
/** Publish the ticket before stopping its owner so every replacement contender can adopt it. */
|
|
4
|
+
export async function prepare(file, info, timeout) {
|
|
5
|
+
const existing = await read(file);
|
|
6
|
+
if (existing !== undefined && existing.expiresAt > Date.now() && same(existing.source, info))
|
|
7
|
+
return;
|
|
8
|
+
const { ClientError, OpenCode } = await import("./promise/index.js");
|
|
9
|
+
const client = OpenCode.make({
|
|
10
|
+
baseUrl: info.url,
|
|
11
|
+
headers: info.password === undefined
|
|
12
|
+
? undefined
|
|
13
|
+
: { authorization: "Basic " + Buffer.from(`opencode:${info.password}`).toString("base64") },
|
|
14
|
+
});
|
|
15
|
+
const missing = (error) => error instanceof ClientError &&
|
|
16
|
+
error.reason === "UnexpectedStatus" &&
|
|
17
|
+
typeof error.cause === "object" &&
|
|
18
|
+
error.cause !== null &&
|
|
19
|
+
"status" in error.cause &&
|
|
20
|
+
error.cause.status === 404;
|
|
21
|
+
const result = await client.experimental.persistentPty.handoff({ signal: AbortSignal.timeout(timeout) }).then((value) => ({ value }), (cause) => ({ cause }));
|
|
22
|
+
if ("cause" in result) {
|
|
23
|
+
// Another caller may already have prepared and stopped this server.
|
|
24
|
+
const concurrent = await read(file);
|
|
25
|
+
if (concurrent !== undefined && concurrent.expiresAt > Date.now() && same(concurrent.source, info))
|
|
26
|
+
return;
|
|
27
|
+
if (!missing(result.cause))
|
|
28
|
+
throw new Error("Failed to prepare persistent terminals for service replacement", { cause: result.cause });
|
|
29
|
+
console.warn("Background service cannot hand off persistent terminals; shutting them down before replacement");
|
|
30
|
+
await client.experimental.persistentPty
|
|
31
|
+
.shutdown({ signal: AbortSignal.timeout(timeout) })
|
|
32
|
+
.catch((cause) => {
|
|
33
|
+
if (missing(cause))
|
|
34
|
+
return;
|
|
35
|
+
throw new Error("Failed to shut down persistent terminals before service replacement", { cause });
|
|
36
|
+
});
|
|
37
|
+
await publish(file, info, null);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const body = result.value;
|
|
41
|
+
if (typeof body !== "object" || body === null || !("handoff" in body))
|
|
42
|
+
throw new Error("Invalid persistent terminal handoff response");
|
|
43
|
+
if (body.handoff === null) {
|
|
44
|
+
await publish(file, info, null);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (!isHandoff(body.handoff) || body.handoff.expiresAt <= Date.now())
|
|
48
|
+
throw new Error("Invalid or expired persistent terminal handoff");
|
|
49
|
+
await publish(file, info, body.handoff);
|
|
50
|
+
}
|
|
51
|
+
async function publish(file, info, handoff) {
|
|
52
|
+
const temporary = `${file}.pty-handoff.${crypto.randomUUID()}.tmp`;
|
|
53
|
+
await writeFile(temporary, JSON.stringify({
|
|
54
|
+
source: { id: info.id, pid: info.pid, url: info.url },
|
|
55
|
+
handoff,
|
|
56
|
+
expiresAt: handoff?.expiresAt ?? Date.now() + 30_000,
|
|
57
|
+
}), { mode: 0o600, flag: "wx" });
|
|
58
|
+
await rename(temporary, file + ".pty-handoff").finally(() => rm(temporary, { force: true }));
|
|
59
|
+
}
|
|
60
|
+
export async function environment(file, env) {
|
|
61
|
+
const record = await read(file);
|
|
62
|
+
const current = await readFile(file, "utf8")
|
|
63
|
+
.then((text) => JSON.parse(text))
|
|
64
|
+
.catch(() => undefined);
|
|
65
|
+
const handoff = record !== undefined && record.expiresAt > Date.now() && (current === undefined || same(record.source, current))
|
|
66
|
+
? record.handoff
|
|
67
|
+
: undefined;
|
|
68
|
+
return { ...env, OPENCODE_PTY_HANDOFF: handoff == null ? undefined : JSON.stringify(handoff) };
|
|
69
|
+
}
|
|
70
|
+
export async function complete(file, info) {
|
|
71
|
+
const record = await read(file);
|
|
72
|
+
if (record !== undefined && !same(record.source, info))
|
|
73
|
+
await clear(file);
|
|
74
|
+
}
|
|
75
|
+
export async function clear(file) {
|
|
76
|
+
await rm(file + ".pty-handoff", { force: true });
|
|
77
|
+
}
|
|
78
|
+
async function read(file) {
|
|
79
|
+
const value = await readFile(file + ".pty-handoff", "utf8")
|
|
80
|
+
.then((text) => JSON.parse(text))
|
|
81
|
+
.catch(() => undefined);
|
|
82
|
+
if (typeof value !== "object" || value === null || !("source" in value) || !("handoff" in value))
|
|
83
|
+
return;
|
|
84
|
+
if (typeof value.source !== "object" || value.source === null)
|
|
85
|
+
return;
|
|
86
|
+
if (!("pid" in value.source) || typeof value.source.pid !== "number")
|
|
87
|
+
return;
|
|
88
|
+
if (!("url" in value.source) || typeof value.source.url !== "string")
|
|
89
|
+
return;
|
|
90
|
+
if ("id" in value.source && typeof value.source.id !== "string")
|
|
91
|
+
return;
|
|
92
|
+
if (value.handoff !== null && !isHandoff(value.handoff))
|
|
93
|
+
return;
|
|
94
|
+
if (!("expiresAt" in value) || typeof value.expiresAt !== "number" || !Number.isFinite(value.expiresAt))
|
|
95
|
+
return;
|
|
96
|
+
return {
|
|
97
|
+
source: {
|
|
98
|
+
id: "id" in value.source && typeof value.source.id === "string" ? value.source.id : undefined,
|
|
99
|
+
pid: value.source.pid,
|
|
100
|
+
url: value.source.url,
|
|
101
|
+
},
|
|
102
|
+
handoff: value.handoff,
|
|
103
|
+
expiresAt: value.expiresAt,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function same(left, right) {
|
|
107
|
+
return left.id === right.id && left.pid === right.pid && left.url === right.url;
|
|
108
|
+
}
|
|
109
|
+
function isHandoff(value) {
|
|
110
|
+
return (typeof value === "object" &&
|
|
111
|
+
value !== null &&
|
|
112
|
+
"directory" in value &&
|
|
113
|
+
typeof value.directory === "string" &&
|
|
114
|
+
"instanceID" in value &&
|
|
115
|
+
typeof value.instanceID === "string" &&
|
|
116
|
+
"ticket" in value &&
|
|
117
|
+
typeof value.ticket === "string" &&
|
|
118
|
+
"expiresAt" in value &&
|
|
119
|
+
typeof value.expiresAt === "number" &&
|
|
120
|
+
Number.isFinite(value.expiresAt));
|
|
121
|
+
}
|
|
@@ -6,6 +6,6 @@ export type ServiceContender = {
|
|
|
6
6
|
readonly stderr: () => string;
|
|
7
7
|
readonly release: () => void;
|
|
8
8
|
};
|
|
9
|
-
export declare function spawnServiceContender(command: string, args: ReadonlyArray<string>, env?: Readonly<Record<string, string>>): ServiceContender;
|
|
9
|
+
export declare function spawnServiceContender(command: string, args: ReadonlyArray<string>, env?: Readonly<Record<string, string | undefined>>): ServiceContender;
|
|
10
10
|
export declare function contenderFailure(contender: ServiceContender): Error | undefined;
|
|
11
11
|
export declare function contenderFinished(contender: ServiceContender): boolean;
|
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-18407",
|
|
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-18407",
|
|
61
|
+
"@opencode-ai/protocol": "0.0.0-dev-18407"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
64
|
"effect": "4.0.0-rc.111",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@effect/platform-node": "4.0.0-rc.111",
|
|
77
|
-
"@opencode-ai/httpapi-codegen": "0.0.0-dev-
|
|
77
|
+
"@opencode-ai/httpapi-codegen": "0.0.0-dev-18407",
|
|
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",
|