@sift-wiki/conductor 0.0.0 → 0.2.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -1
- package/THIRD_PARTY_NOTICES.md +38 -0
- package/dist/adapters/claudeAgent.d.ts +23 -0
- package/dist/adapters/claudeAgent.js +164 -0
- package/dist/adapters/claudeAgent.js.map +1 -0
- package/dist/adapters/claudeParser.d.ts +5 -0
- package/dist/adapters/claudeParser.js +120 -0
- package/dist/adapters/claudeParser.js.map +1 -0
- package/dist/adapters/codexAgent.d.ts +28 -0
- package/dist/adapters/codexAgent.js +152 -0
- package/dist/adapters/codexAgent.js.map +1 -0
- package/dist/adapters/codexParser.d.ts +5 -0
- package/dist/adapters/codexParser.js +106 -0
- package/dist/adapters/codexParser.js.map +1 -0
- package/dist/adapters/config.d.ts +29 -0
- package/dist/adapters/config.js +286 -0
- package/dist/adapters/config.js.map +1 -0
- package/dist/adapters/doctor.d.ts +12 -0
- package/dist/adapters/doctor.js +20 -0
- package/dist/adapters/doctor.js.map +1 -0
- package/dist/adapters/errors.d.ts +7 -0
- package/dist/adapters/errors.js +19 -0
- package/dist/adapters/errors.js.map +1 -0
- package/dist/adapters/fakeAgent.d.ts +11 -0
- package/dist/adapters/fakeAgent.js +149 -0
- package/dist/adapters/fakeAgent.js.map +1 -0
- package/dist/adapters/httpAgent.d.ts +19 -0
- package/dist/adapters/httpAgent.js +164 -0
- package/dist/adapters/httpAgent.js.map +1 -0
- package/dist/adapters/output.d.ts +16 -0
- package/dist/adapters/output.js +48 -0
- package/dist/adapters/output.js.map +1 -0
- package/dist/adapters/processAgent.d.ts +21 -0
- package/dist/adapters/processAgent.js +166 -0
- package/dist/adapters/processAgent.js.map +1 -0
- package/dist/adapters/provider/discovery.d.ts +31 -0
- package/dist/adapters/provider/discovery.js +102 -0
- package/dist/adapters/provider/discovery.js.map +1 -0
- package/dist/adapters/provider/json.d.ts +4 -0
- package/dist/adapters/provider/json.js +21 -0
- package/dist/adapters/provider/json.js.map +1 -0
- package/dist/adapters/provider/lineStream.d.ts +8 -0
- package/dist/adapters/provider/lineStream.js +28 -0
- package/dist/adapters/provider/lineStream.js.map +1 -0
- package/dist/adapters/provider/outputSchemaFile.d.ts +5 -0
- package/dist/adapters/provider/outputSchemaFile.js +16 -0
- package/dist/adapters/provider/outputSchemaFile.js.map +1 -0
- package/dist/adapters/provider/prompt.d.ts +2 -0
- package/dist/adapters/provider/prompt.js +52 -0
- package/dist/adapters/provider/prompt.js.map +1 -0
- package/dist/adapters/provider/result.d.ts +23 -0
- package/dist/adapters/provider/result.js +116 -0
- package/dist/adapters/provider/result.js.map +1 -0
- package/dist/adapters/provider/runProvider.d.ts +16 -0
- package/dist/adapters/provider/runProvider.js +110 -0
- package/dist/adapters/provider/runProvider.js.map +1 -0
- package/dist/adapters/provider/setup.d.ts +50 -0
- package/dist/adapters/provider/setup.js +180 -0
- package/dist/adapters/provider/setup.js.map +1 -0
- package/dist/adapters/provider/store.d.ts +19 -0
- package/dist/adapters/provider/store.js +92 -0
- package/dist/adapters/provider/store.js.map +1 -0
- package/dist/adapters/provider/types.d.ts +58 -0
- package/dist/adapters/provider/types.js +2 -0
- package/dist/adapters/provider/types.js.map +1 -0
- package/dist/adapters/provider/version.d.ts +2 -0
- package/dist/adapters/provider/version.js +25 -0
- package/dist/adapters/provider/version.js.map +1 -0
- package/dist/adapters/types.d.ts +40 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/bridge/handler.d.ts +15 -0
- package/dist/bridge/handler.js +125 -0
- package/dist/bridge/handler.js.map +1 -0
- package/dist/bridge/localBridge.d.ts +49 -0
- package/dist/bridge/localBridge.js +157 -0
- package/dist/bridge/localBridge.js.map +1 -0
- package/dist/bridge/server.d.ts +11 -0
- package/dist/bridge/server.js +86 -0
- package/dist/bridge/server.js.map +1 -0
- package/dist/bridge/sessionRegistry.d.ts +23 -0
- package/dist/bridge/sessionRegistry.js +65 -0
- package/dist/bridge/sessionRegistry.js.map +1 -0
- package/dist/cli.d.ts +23 -0
- package/dist/cli.js +245 -0
- package/dist/cli.js.map +1 -0
- package/dist/conductorClient.d.ts +443 -0
- package/dist/conductorClient.js +281 -0
- package/dist/conductorClient.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.js +54 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon.d.ts +52 -0
- package/dist/daemon.js +324 -0
- package/dist/daemon.js.map +1 -0
- package/dist/desktop/adapterSetupView.d.ts +16 -0
- package/dist/desktop/adapterSetupView.js +13 -0
- package/dist/desktop/adapterSetupView.js.map +1 -0
- package/dist/desktop/app/contracts.d.ts +71 -0
- package/dist/desktop/app/contracts.js +19 -0
- package/dist/desktop/app/contracts.js.map +1 -0
- package/dist/desktop/app/controller.d.ts +58 -0
- package/dist/desktop/app/controller.js +161 -0
- package/dist/desktop/app/controller.js.map +1 -0
- package/dist/desktop/app/runtimeController.d.ts +22 -0
- package/dist/desktop/app/runtimeController.js +44 -0
- package/dist/desktop/app/runtimeController.js.map +1 -0
- package/dist/desktop/manifest.d.ts +17 -0
- package/dist/desktop/manifest.js +24 -0
- package/dist/desktop/manifest.js.map +1 -0
- package/dist/desktop/pairing.d.ts +13 -0
- package/dist/desktop/pairing.js +20 -0
- package/dist/desktop/pairing.js.map +1 -0
- package/dist/desktop/recovery.d.ts +33 -0
- package/dist/desktop/recovery.js +71 -0
- package/dist/desktop/recovery.js.map +1 -0
- package/dist/desktop/workBoardView.d.ts +41 -0
- package/dist/desktop/workBoardView.js +133 -0
- package/dist/desktop/workBoardView.js.map +1 -0
- package/dist/desktop/workGovernanceView.d.ts +70 -0
- package/dist/desktop/workGovernanceView.js +159 -0
- package/dist/desktop/workGovernanceView.js.map +1 -0
- package/dist/localApi/authorizedPairing.d.ts +12 -0
- package/dist/localApi/authorizedPairing.js +18 -0
- package/dist/localApi/authorizedPairing.js.map +1 -0
- package/dist/localApi/contracts.d.ts +253 -0
- package/dist/localApi/contracts.js +173 -0
- package/dist/localApi/contracts.js.map +1 -0
- package/dist/localApi/server.d.ts +20 -0
- package/dist/localApi/server.js +412 -0
- package/dist/localApi/server.js.map +1 -0
- package/dist/localApi/workConsole.d.ts +74 -0
- package/dist/localApi/workConsole.js +342 -0
- package/dist/localApi/workConsole.js.map +1 -0
- package/dist/localApi/workContracts.d.ts +213 -0
- package/dist/localApi/workContracts.js +130 -0
- package/dist/localApi/workContracts.js.map +1 -0
- package/dist/localApp/platform.d.ts +2 -0
- package/dist/localApp/platform.js +57 -0
- package/dist/localApp/platform.js.map +1 -0
- package/dist/localApp/service.d.ts +25 -0
- package/dist/localApp/service.js +114 -0
- package/dist/localApp/service.js.map +1 -0
- package/dist/pairing.d.ts +27 -0
- package/dist/pairing.js +45 -0
- package/dist/pairing.js.map +1 -0
- package/dist/redaction.d.ts +2 -0
- package/dist/redaction.js +34 -0
- package/dist/redaction.js.map +1 -0
- package/dist/release/validateDistribution.d.ts +51 -0
- package/dist/release/validateDistribution.js +54 -0
- package/dist/release/validateDistribution.js.map +1 -0
- package/dist/runtime/localLogSpool.d.ts +47 -0
- package/dist/runtime/localLogSpool.js +105 -0
- package/dist/runtime/localLogSpool.js.map +1 -0
- package/dist/runtime/localRunQueue.d.ts +31 -0
- package/dist/runtime/localRunQueue.js +76 -0
- package/dist/runtime/localRunQueue.js.map +1 -0
- package/dist/runtime/localSessionCache.d.ts +26 -0
- package/dist/runtime/localSessionCache.js +35 -0
- package/dist/runtime/localSessionCache.js.map +1 -0
- package/dist/runtime/process.d.ts +27 -0
- package/dist/runtime/process.js +128 -0
- package/dist/runtime/process.js.map +1 -0
- package/dist/runtime/runEnvironment.d.ts +12 -0
- package/dist/runtime/runEnvironment.js +59 -0
- package/dist/runtime/runEnvironment.js.map +1 -0
- package/dist/runtime/runEventRetryBuffer.d.ts +42 -0
- package/dist/runtime/runEventRetryBuffer.js +118 -0
- package/dist/runtime/runEventRetryBuffer.js.map +1 -0
- package/dist/runtime/runtimeService.d.ts +27 -0
- package/dist/runtime/runtimeService.js +112 -0
- package/dist/runtime/runtimeService.js.map +1 -0
- package/dist/runtime/sleep.d.ts +2 -0
- package/dist/runtime/sleep.js +21 -0
- package/dist/runtime/sleep.js.map +1 -0
- package/dist/runtime/taskExecution.d.ts +16 -0
- package/dist/runtime/taskExecution.js +74 -0
- package/dist/runtime/taskExecution.js.map +1 -0
- package/dist/runtime/wakeEnvelope.d.ts +76 -0
- package/dist/runtime/wakeEnvelope.js +60 -0
- package/dist/runtime/wakeEnvelope.js.map +1 -0
- package/dist/types.d.ts +121 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/userAuth/service.d.ts +26 -0
- package/dist/userAuth/service.js +170 -0
- package/dist/userAuth/service.js.map +1 -0
- package/dist/userAuth/store.d.ts +42 -0
- package/dist/userAuth/store.js +160 -0
- package/dist/userAuth/store.js.map +1 -0
- package/dist/userAuth/types.d.ts +63 -0
- package/dist/userAuth/types.js +29 -0
- package/dist/userAuth/types.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/dist/workTypes.d.ts +313 -0
- package/dist/workTypes.js +106 -0
- package/dist/workTypes.js.map +1 -0
- package/dist-web/assets/index-CWfnzdLn.css +1 -0
- package/dist-web/assets/index-D5X9InfE.js +72 -0
- package/dist-web/index.html +15 -0
- package/docs/provider-setup.md +81 -0
- package/docs/quickstart.md +62 -0
- package/docs/troubleshooting.md +63 -0
- package/package.json +75 -6
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CONDUCTOR_VERSION, PROTOCOL_VERSION } from "../version.js";
|
|
3
|
+
import { userAuthorizationStatusSchema } from "../userAuth/types.js";
|
|
4
|
+
export const localPairingStatusSchema = z.discriminatedUnion("paired", [
|
|
5
|
+
z.object({ paired: z.literal(false) }).strict(),
|
|
6
|
+
z.object({
|
|
7
|
+
paired: z.literal(true),
|
|
8
|
+
apiBaseUrl: z.url(),
|
|
9
|
+
conductorId: z.string().min(1).optional(),
|
|
10
|
+
displayName: z.string().min(1),
|
|
11
|
+
protocolVersion: z.string().min(1),
|
|
12
|
+
}).strict(),
|
|
13
|
+
]);
|
|
14
|
+
export const localHealthSchema = z.object({
|
|
15
|
+
ok: z.literal(true),
|
|
16
|
+
version: z.string().min(1),
|
|
17
|
+
protocolVersion: z.string().min(1),
|
|
18
|
+
}).strict();
|
|
19
|
+
export const runtimeServiceStatusSchema = z.object({
|
|
20
|
+
state: z.enum(["stopped", "starting", "running", "stopping", "failed"]),
|
|
21
|
+
startedAt: z.string().optional(),
|
|
22
|
+
stoppedAt: z.string().optional(),
|
|
23
|
+
lastResult: z.discriminatedUnion("status", [
|
|
24
|
+
z.object({ status: z.literal("idle") }).strict(),
|
|
25
|
+
z.object({ status: z.literal("completed"), runId: z.string() }).strict(),
|
|
26
|
+
z.object({ status: z.literal("cancelled"), runId: z.string() }).strict(),
|
|
27
|
+
z.object({ status: z.literal("failed"), runId: z.string() }).strict(),
|
|
28
|
+
]).optional(),
|
|
29
|
+
lastErrorMessage: z.string().optional(),
|
|
30
|
+
}).strict();
|
|
31
|
+
export const providerAgentViewSchema = z.object({
|
|
32
|
+
localKey: z.string().min(1),
|
|
33
|
+
displayName: z.string().min(1),
|
|
34
|
+
provider: z.enum(["codex", "claude-code"]),
|
|
35
|
+
workspaceName: z.string().min(1),
|
|
36
|
+
accessProfile: z.enum(["inspect", "workspace"]),
|
|
37
|
+
enabled: z.boolean(),
|
|
38
|
+
status: z.enum(["ready", "error"]),
|
|
39
|
+
message: z.string(),
|
|
40
|
+
hint: z.string().optional(),
|
|
41
|
+
remediation: z.enum(["install", "login", "upgrade", "select-folder", "resume", "retry"]).optional(),
|
|
42
|
+
providerVersion: z.string().optional(),
|
|
43
|
+
}).strict();
|
|
44
|
+
export const selectedFolderSchema = z.object({
|
|
45
|
+
token: z.string().min(1),
|
|
46
|
+
name: z.string().min(1),
|
|
47
|
+
}).strict();
|
|
48
|
+
export const providerDraftStatusSchema = z.object({
|
|
49
|
+
status: z.enum(["ready", "error"]),
|
|
50
|
+
message: z.string(),
|
|
51
|
+
hint: z.string().optional(),
|
|
52
|
+
remediation: z.enum(["install", "login", "upgrade", "select-folder", "resume", "retry"]).optional(),
|
|
53
|
+
providerVersion: z.string().optional(),
|
|
54
|
+
}).strict();
|
|
55
|
+
export const providerInstallPlanSchema = z.object({
|
|
56
|
+
provider: z.enum(["codex", "claude-code"]),
|
|
57
|
+
title: z.string(),
|
|
58
|
+
source: z.string(),
|
|
59
|
+
command: z.string().optional(),
|
|
60
|
+
officialUrl: z.url(),
|
|
61
|
+
}).strict();
|
|
62
|
+
export const providerLoginResultSchema = z.object({
|
|
63
|
+
ok: z.boolean(),
|
|
64
|
+
message: z.string(),
|
|
65
|
+
}).strict();
|
|
66
|
+
export const localSessionStatusSchema = z.object({
|
|
67
|
+
authenticated: z.literal(true),
|
|
68
|
+
csrfToken: z.string().min(1),
|
|
69
|
+
expiresAt: z.iso.datetime(),
|
|
70
|
+
}).strict();
|
|
71
|
+
export const localPairRequestSchema = z.object({
|
|
72
|
+
apiBaseUrl: z.url(),
|
|
73
|
+
code: z.string().min(1).max(500),
|
|
74
|
+
displayName: z.string().trim().min(1).max(100),
|
|
75
|
+
}).strict();
|
|
76
|
+
export const localAuthorizedPairRequestSchema = z.object({
|
|
77
|
+
displayName: z.string().trim().min(1).max(100),
|
|
78
|
+
}).strict();
|
|
79
|
+
export const localUserAuthorizationBeginSchema = z.object({
|
|
80
|
+
apiBaseUrl: z.url().optional(),
|
|
81
|
+
deviceLabel: z.string().trim().min(1).max(100).optional(),
|
|
82
|
+
}).strict();
|
|
83
|
+
export const localProviderDraftSchema = z.object({
|
|
84
|
+
provider: z.enum(["codex", "claude-code"]),
|
|
85
|
+
displayName: z.string().trim().min(1).max(100),
|
|
86
|
+
folderToken: z.string().min(1).max(500),
|
|
87
|
+
accessProfile: z.enum(["inspect", "workspace"]),
|
|
88
|
+
model: z.string().trim().min(1).max(200).optional(),
|
|
89
|
+
}).strict();
|
|
90
|
+
export const localAgentUpdateSchema = z.object({
|
|
91
|
+
localKey: z.string().min(1).max(500),
|
|
92
|
+
displayName: z.string().trim().min(1).max(100),
|
|
93
|
+
accessProfile: z.enum(["inspect", "workspace"]),
|
|
94
|
+
folderToken: z.string().min(1).max(500).optional(),
|
|
95
|
+
}).strict();
|
|
96
|
+
export const localAgentPauseSchema = z.object({
|
|
97
|
+
localKey: z.string().min(1).max(500),
|
|
98
|
+
paused: z.boolean(),
|
|
99
|
+
}).strict();
|
|
100
|
+
export const localAgentKeySchema = z.object({
|
|
101
|
+
localKey: z.string().min(1).max(500),
|
|
102
|
+
}).strict();
|
|
103
|
+
export const localProviderSchema = z.object({
|
|
104
|
+
provider: z.enum(["codex", "claude-code"]),
|
|
105
|
+
}).strict();
|
|
106
|
+
export function localHealth() {
|
|
107
|
+
return { ok: true, version: CONDUCTOR_VERSION, protocolVersion: PROTOCOL_VERSION };
|
|
108
|
+
}
|
|
109
|
+
export function createLocalControllerApi(controller, userAuthorization = unavailableUserAuthorization, work = unavailableWorkConsole, authorizedPairing = unavailableAuthorizedPairing, localDiagnostics = unavailableLocalDiagnostics) {
|
|
110
|
+
return {
|
|
111
|
+
health: () => Promise.resolve(localHealth()),
|
|
112
|
+
pairedStatus: async () => localStatusFromDesktop(await controller.pairedStatus()),
|
|
113
|
+
pair: async (input) => localStatusFromDesktop(await controller.pair(input)),
|
|
114
|
+
pairAuthorized: async (displayName) => localStatusFromDesktop(await authorizedPairing.pair(displayName)),
|
|
115
|
+
logout: async () => localStatusFromDesktop(await controller.logout()),
|
|
116
|
+
listAgents: () => controller.listAgents(),
|
|
117
|
+
selectFolder: () => controller.selectFolder(),
|
|
118
|
+
inspectDraft: (input) => controller.inspectDraft(input),
|
|
119
|
+
login: (input) => controller.login(input),
|
|
120
|
+
verifyAndAdd: (input) => controller.verifyAndAdd(input),
|
|
121
|
+
updateAgent: (input) => controller.updateAgent(input),
|
|
122
|
+
pauseAgent: (localKey, paused) => controller.pauseAgent(localKey, paused),
|
|
123
|
+
removeAgent: (localKey) => controller.removeAgent(localKey),
|
|
124
|
+
installPlan: (provider) => controller.installPlan(provider),
|
|
125
|
+
openOfficialProviderPage: (provider) => controller.openOfficialProviderPage(provider),
|
|
126
|
+
runtimeStatus: () => controller.runtimeStatus(),
|
|
127
|
+
startRuntime: () => controller.startRuntime(),
|
|
128
|
+
stopRuntime: () => controller.stopRuntime(),
|
|
129
|
+
clearLocalDiagnostics: async () => { await localDiagnostics.clear(); },
|
|
130
|
+
userAuthorizationStatus: async () => userAuthorizationStatusSchema.parse(await userAuthorization.status()),
|
|
131
|
+
beginUserAuthorization: async (input) => userAuthorizationStatusSchema.parse(await userAuthorization.begin(input)),
|
|
132
|
+
signOutUser: async () => userAuthorizationStatusSchema.parse(await userAuthorization.signOut()),
|
|
133
|
+
workSnapshot: (input) => work.snapshot(input),
|
|
134
|
+
createTask: (input) => work.createTask(input),
|
|
135
|
+
updateTask: (input) => work.updateTask(input),
|
|
136
|
+
commentTask: (input) => work.comment(input),
|
|
137
|
+
dispatchTask: (input) => work.dispatch(input),
|
|
138
|
+
decideApproval: (input) => work.decideApproval(input),
|
|
139
|
+
cancelRun: (runId) => work.cancelRun(runId),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const unavailableUserAuthorization = {
|
|
143
|
+
status: () => Promise.resolve({ state: "signed_out", storageKind: "memory" }),
|
|
144
|
+
begin: () => Promise.reject(new Error("Sift user authorization is unavailable.")),
|
|
145
|
+
signOut: () => Promise.resolve({ state: "signed_out", storageKind: "memory" }),
|
|
146
|
+
};
|
|
147
|
+
const unavailableWorkConsole = {
|
|
148
|
+
snapshot: () => Promise.resolve({ state: "unauthorized", message: "Sign in to Sift to manage shared work.", refreshedAt: new Date().toISOString(), projects: [], agents: [], queue: [], activity: [] }),
|
|
149
|
+
createTask: () => Promise.reject(new Error("Sign in to Sift to manage shared work.")),
|
|
150
|
+
updateTask: () => Promise.reject(new Error("Sign in to Sift to manage shared work.")),
|
|
151
|
+
comment: () => Promise.reject(new Error("Sign in to Sift to manage shared work.")),
|
|
152
|
+
dispatch: () => Promise.reject(new Error("Sign in to Sift to manage shared work.")),
|
|
153
|
+
decideApproval: () => Promise.reject(new Error("Sign in to Sift to manage shared work.")),
|
|
154
|
+
cancelRun: () => Promise.reject(new Error("Sign in to Sift to manage shared work.")),
|
|
155
|
+
};
|
|
156
|
+
const unavailableAuthorizedPairing = {
|
|
157
|
+
pair: () => Promise.reject(new Error("Sign in to Sift before connecting this computer automatically.")),
|
|
158
|
+
};
|
|
159
|
+
const unavailableLocalDiagnostics = {
|
|
160
|
+
clear: () => undefined,
|
|
161
|
+
};
|
|
162
|
+
function localStatusFromDesktop(status) {
|
|
163
|
+
if (!status.paired)
|
|
164
|
+
return { paired: false };
|
|
165
|
+
return localPairingStatusSchema.parse({
|
|
166
|
+
paired: true,
|
|
167
|
+
apiBaseUrl: status.apiBaseUrl,
|
|
168
|
+
...(status.conductorId === undefined ? {} : { conductorId: status.conductorId }),
|
|
169
|
+
displayName: status.displayName,
|
|
170
|
+
protocolVersion: status.protocolVersion,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/localApi/contracts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ConductorLocalApi } from "./contracts.js";
|
|
2
|
+
export type LocalWebServerOptions = {
|
|
3
|
+
api: ConductorLocalApi;
|
|
4
|
+
staticDirectory: string;
|
|
5
|
+
host?: "127.0.0.1" | "::1" | undefined;
|
|
6
|
+
preferredPort?: number | undefined;
|
|
7
|
+
bootstrapToken?: string | undefined;
|
|
8
|
+
now?: (() => number) | undefined;
|
|
9
|
+
sessionTtlMs?: number | undefined;
|
|
10
|
+
bootstrapTtlMs?: number | undefined;
|
|
11
|
+
maxBodyBytes?: number | undefined;
|
|
12
|
+
};
|
|
13
|
+
export type LocalWebServer = {
|
|
14
|
+
origin: string;
|
|
15
|
+
browserUrl: string;
|
|
16
|
+
port: number;
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
export declare function startLocalWebServer(options: LocalWebServerOptions): Promise<LocalWebServer>;
|
|
20
|
+
export declare function assertStaticAssets(staticDirectory: string): Promise<void>;
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { createReadStream } from "node:fs";
|
|
3
|
+
import { readFile, stat } from "node:fs/promises";
|
|
4
|
+
import { createServer } from "node:http";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { redactSecrets } from "../redaction.js";
|
|
8
|
+
import { localAgentKeySchema, localAgentPauseSchema, localAgentUpdateSchema, localAuthorizedPairRequestSchema, localPairRequestSchema, localProviderDraftSchema, localProviderSchema, localUserAuthorizationBeginSchema, } from "./contracts.js";
|
|
9
|
+
import { approvalDecisionRequestSchema, cancelRunRequestSchema, commentTaskRequestSchema, createTaskRequestSchema, dispatchTaskRequestSchema, updateTaskRequestSchema, } from "./workContracts.js";
|
|
10
|
+
const DEFAULT_PORT = 32145;
|
|
11
|
+
const MAX_PORT_ATTEMPTS = 20;
|
|
12
|
+
const DEFAULT_MAX_BODY_BYTES = 64 * 1024;
|
|
13
|
+
const DEFAULT_SESSION_TTL_MS = 8 * 60 * 60_000;
|
|
14
|
+
const DEFAULT_BOOTSTRAP_TTL_MS = 2 * 60_000;
|
|
15
|
+
const SESSION_COOKIE = "sift_conductor_session";
|
|
16
|
+
const CSRF_HEADER = "x-sift-csrf";
|
|
17
|
+
const HASHED_ASSET_PATTERN = /[.-][a-zA-Z0-9_-]{8,}\.(?:css|js|map|png|jpe?g|webp|woff2?)$/u;
|
|
18
|
+
export async function startLocalWebServer(options) {
|
|
19
|
+
const host = options.host ?? "127.0.0.1";
|
|
20
|
+
const preferredPort = options.preferredPort ?? DEFAULT_PORT;
|
|
21
|
+
const sessions = new Map();
|
|
22
|
+
const now = options.now ?? Date.now;
|
|
23
|
+
const bootstrap = {
|
|
24
|
+
token: options.bootstrapToken ?? randomToken(),
|
|
25
|
+
expiresAt: now() + (options.bootstrapTtlMs ?? DEFAULT_BOOTSTRAP_TTL_MS),
|
|
26
|
+
consumed: false,
|
|
27
|
+
};
|
|
28
|
+
const server = createServer((request, response) => {
|
|
29
|
+
void handleRequest({
|
|
30
|
+
...options,
|
|
31
|
+
request,
|
|
32
|
+
response,
|
|
33
|
+
sessions,
|
|
34
|
+
bootstrap,
|
|
35
|
+
now,
|
|
36
|
+
}).catch((error) => {
|
|
37
|
+
if (response.headersSent) {
|
|
38
|
+
response.destroy();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
writeError(response, 500, "internal_error", safeErrorMessage(error));
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
const port = await listenWithFallback(server, host, preferredPort);
|
|
45
|
+
const hostLabel = host === "::1" ? "[::1]" : host;
|
|
46
|
+
const origin = `http://${hostLabel}:${String(port)}`;
|
|
47
|
+
return {
|
|
48
|
+
origin,
|
|
49
|
+
browserUrl: `${origin}/#bootstrap=${encodeURIComponent(bootstrap.token)}`,
|
|
50
|
+
port,
|
|
51
|
+
close: () => closeServer(server),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
async function handleRequest(input) {
|
|
55
|
+
const { request, response } = input;
|
|
56
|
+
applySecurityHeaders(response);
|
|
57
|
+
if (!isLoopbackAddress(request.socket.remoteAddress)) {
|
|
58
|
+
writeError(response, 403, "loopback_required", "Local Conductor accepts loopback requests only.");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const host = request.headers.host;
|
|
62
|
+
if (host === undefined || !isAllowedHost(host, input.host ?? "127.0.0.1")) {
|
|
63
|
+
writeError(response, 403, "invalid_host", "Local Conductor rejected the Host header.");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const origin = `http://${host}`;
|
|
67
|
+
const url = new URL(request.url ?? "/", origin);
|
|
68
|
+
const context = { request, response, url, origin };
|
|
69
|
+
if (url.pathname === "/local-api/health" && request.method === "GET") {
|
|
70
|
+
writeJson(response, 200, await input.api.health());
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (url.pathname === "/local-api/session" && request.method === "POST") {
|
|
74
|
+
await exchangeBootstrap(context, input);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (url.pathname.startsWith("/local-api/")) {
|
|
78
|
+
const session = requireSession(context, input.sessions, input.now, input.sessionTtlMs);
|
|
79
|
+
if (session === undefined)
|
|
80
|
+
return;
|
|
81
|
+
if (request.method === "GET" && url.pathname === "/local-api/session") {
|
|
82
|
+
renewSession(response, session, input.now, input.sessionTtlMs);
|
|
83
|
+
writeJson(response, 200, sessionStatus(session));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (request.method !== "GET" && !validMutationHeaders(context, session))
|
|
87
|
+
return;
|
|
88
|
+
renewSession(response, session, input.now, input.sessionTtlMs);
|
|
89
|
+
await dispatchLocalApi(context, input.api, input.maxBodyBytes);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
await serveStatic(context, input.staticDirectory);
|
|
93
|
+
}
|
|
94
|
+
async function exchangeBootstrap(context, input) {
|
|
95
|
+
if (!validOrigin(context))
|
|
96
|
+
return;
|
|
97
|
+
const body = await readJson(context, z.object({ bootstrapToken: z.string().min(1).max(500) }).strict(), input.maxBodyBytes);
|
|
98
|
+
if (body === undefined)
|
|
99
|
+
return;
|
|
100
|
+
const tokenMatches = safeTokenEquals(body.bootstrapToken, input.bootstrap.token);
|
|
101
|
+
if (input.bootstrap.consumed || input.bootstrap.expiresAt <= input.now() || !tokenMatches) {
|
|
102
|
+
writeError(context.response, 401, "invalid_bootstrap", "The local browser bootstrap is invalid or expired.");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
input.bootstrap.consumed = true;
|
|
106
|
+
const session = {
|
|
107
|
+
id: randomToken(),
|
|
108
|
+
csrfToken: randomToken(),
|
|
109
|
+
expiresAt: input.now() + (input.sessionTtlMs ?? DEFAULT_SESSION_TTL_MS),
|
|
110
|
+
};
|
|
111
|
+
input.sessions.set(session.id, session);
|
|
112
|
+
setSessionCookie(context.response, session);
|
|
113
|
+
writeJson(context.response, 201, sessionStatus(session));
|
|
114
|
+
}
|
|
115
|
+
async function dispatchLocalApi(context, api, maxBodyBytes) {
|
|
116
|
+
const route = `${context.request.method ?? "GET"} ${context.url.pathname}`;
|
|
117
|
+
switch (route) {
|
|
118
|
+
case "GET /local-api/status": return writeJson(context.response, 200, await api.pairedStatus());
|
|
119
|
+
case "GET /local-api/agents": return writeJson(context.response, 200, await api.listAgents());
|
|
120
|
+
case "GET /local-api/runtime": return writeJson(context.response, 200, await api.runtimeStatus());
|
|
121
|
+
case "GET /local-api/user-authorization": return writeJson(context.response, 200, await api.userAuthorizationStatus());
|
|
122
|
+
case "GET /local-api/work": return writeJson(context.response, 200, await api.workSnapshot({
|
|
123
|
+
projectId: context.url.searchParams.get("projectId") ?? undefined,
|
|
124
|
+
taskId: context.url.searchParams.get("taskId") ?? undefined,
|
|
125
|
+
}));
|
|
126
|
+
case "POST /local-api/pair": return withBody(context, localPairRequestSchema, maxBodyBytes, async (body) => api.pair(body));
|
|
127
|
+
case "POST /local-api/pair/authorized": return withBody(context, localAuthorizedPairRequestSchema, maxBodyBytes, async (body) => api.pairAuthorized(body.displayName));
|
|
128
|
+
case "POST /local-api/logout": return withEmptyBody(context, maxBodyBytes, async () => api.logout());
|
|
129
|
+
case "POST /local-api/folders/select": return withEmptyBody(context, maxBodyBytes, async () => api.selectFolder());
|
|
130
|
+
case "POST /local-api/providers/inspect": return withBody(context, localProviderDraftSchema, maxBodyBytes, async (body) => api.inspectDraft(body));
|
|
131
|
+
case "POST /local-api/providers/login": return withBody(context, localProviderDraftSchema, maxBodyBytes, async (body) => api.login(body));
|
|
132
|
+
case "POST /local-api/agents": return withBody(context, localProviderDraftSchema, maxBodyBytes, async (body) => api.verifyAndAdd(body));
|
|
133
|
+
case "POST /local-api/agents/update": return withBody(context, localAgentUpdateSchema, maxBodyBytes, async (body) => api.updateAgent(body));
|
|
134
|
+
case "POST /local-api/agents/pause": return withBody(context, localAgentPauseSchema, maxBodyBytes, async (body) => api.pauseAgent(body.localKey, body.paused));
|
|
135
|
+
case "POST /local-api/agents/remove": return withBody(context, localAgentKeySchema, maxBodyBytes, async (body) => api.removeAgent(body.localKey));
|
|
136
|
+
case "POST /local-api/providers/install-plan": return withBody(context, localProviderSchema, maxBodyBytes, async (body) => api.installPlan(body.provider));
|
|
137
|
+
case "POST /local-api/providers/open-official": return withBody(context, localProviderSchema, maxBodyBytes, async (body) => api.openOfficialProviderPage(body.provider));
|
|
138
|
+
case "POST /local-api/runtime/start": return withEmptyBody(context, maxBodyBytes, async () => api.startRuntime());
|
|
139
|
+
case "POST /local-api/runtime/stop": return withEmptyBody(context, maxBodyBytes, async () => api.stopRuntime());
|
|
140
|
+
case "POST /local-api/diagnostics/clear": return withEmptyBody(context, maxBodyBytes, async () => api.clearLocalDiagnostics());
|
|
141
|
+
case "POST /local-api/user-authorization/begin": return withBody(context, localUserAuthorizationBeginSchema, maxBodyBytes, async (body) => api.beginUserAuthorization(body));
|
|
142
|
+
case "POST /local-api/user-authorization/sign-out": return withEmptyBody(context, maxBodyBytes, async () => api.signOutUser());
|
|
143
|
+
case "POST /local-api/work/tasks": return withBody(context, createTaskRequestSchema, maxBodyBytes, async (body) => api.createTask(body));
|
|
144
|
+
case "POST /local-api/work/tasks/update": return withBody(context, updateTaskRequestSchema, maxBodyBytes, async (body) => api.updateTask(body));
|
|
145
|
+
case "POST /local-api/work/tasks/comment": return withBody(context, commentTaskRequestSchema, maxBodyBytes, async (body) => api.commentTask(body));
|
|
146
|
+
case "POST /local-api/work/tasks/dispatch": return withBody(context, dispatchTaskRequestSchema, maxBodyBytes, async (body) => api.dispatchTask(body));
|
|
147
|
+
case "POST /local-api/work/approvals/decision": return withBody(context, approvalDecisionRequestSchema, maxBodyBytes, async (body) => api.decideApproval(body));
|
|
148
|
+
case "POST /local-api/work/runs/cancel": return withBody(context, cancelRunRequestSchema, maxBodyBytes, async (body) => api.cancelRun(body.runId));
|
|
149
|
+
default:
|
|
150
|
+
writeError(context.response, 404, "not_found", "Local API route was not found.");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async function withBody(context, schema, maxBodyBytes, operation) {
|
|
154
|
+
const body = await readJson(context, schema, maxBodyBytes);
|
|
155
|
+
if (body === undefined)
|
|
156
|
+
return;
|
|
157
|
+
writeJson(context.response, 200, await operation(body));
|
|
158
|
+
}
|
|
159
|
+
async function withEmptyBody(context, maxBodyBytes, operation) {
|
|
160
|
+
const body = await readJson(context, z.object({}).strict(), maxBodyBytes);
|
|
161
|
+
if (body === undefined)
|
|
162
|
+
return;
|
|
163
|
+
writeJson(context.response, 200, await operation());
|
|
164
|
+
}
|
|
165
|
+
async function readJson(context, schema, maxBodyBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
166
|
+
const contentType = context.request.headers["content-type"]?.split(";", 1)[0]?.trim().toLowerCase();
|
|
167
|
+
if (contentType !== "application/json") {
|
|
168
|
+
writeError(context.response, 415, "unsupported_content_type", "Local API requests require application/json.");
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
const chunks = [];
|
|
172
|
+
let size = 0;
|
|
173
|
+
for await (const chunk of context.request) {
|
|
174
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
175
|
+
size += buffer.byteLength;
|
|
176
|
+
if (size > maxBodyBytes) {
|
|
177
|
+
writeError(context.response, 413, "request_too_large", "Local API request body is too large.");
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
chunks.push(buffer);
|
|
181
|
+
}
|
|
182
|
+
try {
|
|
183
|
+
return schema.parse(JSON.parse(Buffer.concat(chunks).toString("utf8") || "{}"));
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
const code = error instanceof SyntaxError ? "invalid_json" : "invalid_request";
|
|
187
|
+
writeError(context.response, 400, code, "Local API request body is invalid.");
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function requireSession(context, sessions, now, sessionTtlMs = DEFAULT_SESSION_TTL_MS) {
|
|
192
|
+
const sessionId = parseCookies(context.request.headers.cookie)[SESSION_COOKIE];
|
|
193
|
+
const session = sessionId === undefined ? undefined : sessions.get(sessionId);
|
|
194
|
+
if (session === undefined || session.expiresAt <= now()) {
|
|
195
|
+
if (session !== undefined)
|
|
196
|
+
sessions.delete(session.id);
|
|
197
|
+
clearSessionCookie(context.response);
|
|
198
|
+
writeError(context.response, 401, "session_required", "Open Conductor from its current local startup URL.");
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
session.expiresAt = now() + sessionTtlMs;
|
|
202
|
+
return session;
|
|
203
|
+
}
|
|
204
|
+
function validMutationHeaders(context, session) {
|
|
205
|
+
if (!validOrigin(context))
|
|
206
|
+
return false;
|
|
207
|
+
const csrf = context.request.headers[CSRF_HEADER];
|
|
208
|
+
if (typeof csrf !== "string" || !safeTokenEquals(csrf, session.csrfToken)) {
|
|
209
|
+
writeError(context.response, 403, "csrf_required", "Local API mutation requires a valid CSRF token.");
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
function validOrigin(context) {
|
|
215
|
+
if (context.request.headers.origin !== context.origin) {
|
|
216
|
+
writeError(context.response, 403, "invalid_origin", "Local Conductor rejected the request origin.");
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
async function serveStatic(context, staticDirectory) {
|
|
222
|
+
if (context.request.method !== "GET" && context.request.method !== "HEAD") {
|
|
223
|
+
writeError(context.response, 405, "method_not_allowed", "This local resource is read-only.");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const requested = decodeURIComponent(context.url.pathname);
|
|
227
|
+
const relative = requested === "/" ? "index.html" : requested.replace(/^\/+/, "");
|
|
228
|
+
const candidate = safeStaticPath(staticDirectory, relative);
|
|
229
|
+
const existing = candidate === undefined ? undefined : await regularFile(candidate);
|
|
230
|
+
if (existing !== undefined) {
|
|
231
|
+
streamFile(context, existing);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (relative.startsWith("assets/")) {
|
|
235
|
+
writeError(context.response, 404, "asset_not_found", "Static asset was not found.");
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const indexPath = path.join(staticDirectory, "index.html");
|
|
239
|
+
if (await regularFile(indexPath) === undefined) {
|
|
240
|
+
writeError(context.response, 503, "ui_unavailable", "Conductor web assets are not installed.");
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
streamFile(context, indexPath);
|
|
244
|
+
}
|
|
245
|
+
function streamFile(context, filePath) {
|
|
246
|
+
context.response.statusCode = 200;
|
|
247
|
+
context.response.setHeader("content-type", contentType(filePath));
|
|
248
|
+
context.response.setHeader("cache-control", HASHED_ASSET_PATTERN.test(path.basename(filePath))
|
|
249
|
+
? "public, max-age=31536000, immutable"
|
|
250
|
+
: "no-cache");
|
|
251
|
+
if (context.request.method === "HEAD") {
|
|
252
|
+
context.response.end();
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
createReadStream(filePath).pipe(context.response);
|
|
256
|
+
}
|
|
257
|
+
async function regularFile(filePath) {
|
|
258
|
+
try {
|
|
259
|
+
return (await stat(filePath)).isFile() ? filePath : undefined;
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function safeStaticPath(root, relative) {
|
|
266
|
+
const resolvedRoot = path.resolve(root);
|
|
267
|
+
const resolved = path.resolve(resolvedRoot, relative);
|
|
268
|
+
return resolved === resolvedRoot || resolved.startsWith(`${resolvedRoot}${path.sep}`) ? resolved : undefined;
|
|
269
|
+
}
|
|
270
|
+
function applySecurityHeaders(response) {
|
|
271
|
+
response.setHeader("content-security-policy", "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src 'self'; font-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'self'");
|
|
272
|
+
response.setHeader("x-content-type-options", "nosniff");
|
|
273
|
+
response.setHeader("x-frame-options", "DENY");
|
|
274
|
+
response.setHeader("referrer-policy", "no-referrer");
|
|
275
|
+
response.setHeader("permissions-policy", "camera=(), microphone=(), geolocation=()");
|
|
276
|
+
response.setHeader("cross-origin-opener-policy", "same-origin");
|
|
277
|
+
response.setHeader("cross-origin-resource-policy", "same-origin");
|
|
278
|
+
}
|
|
279
|
+
function writeJson(response, status, body) {
|
|
280
|
+
response.statusCode = status;
|
|
281
|
+
response.setHeader("content-type", "application/json; charset=utf-8");
|
|
282
|
+
response.setHeader("cache-control", "no-store");
|
|
283
|
+
response.end(`${JSON.stringify(safeBrowserPayload(body ?? null))}\n`);
|
|
284
|
+
}
|
|
285
|
+
function writeError(response, status, code, message) {
|
|
286
|
+
writeJson(response, status, { error: { code, message: redactSecrets(message) } });
|
|
287
|
+
}
|
|
288
|
+
function sessionStatus(session) {
|
|
289
|
+
return { authenticated: true, csrfToken: session.csrfToken, expiresAt: new Date(session.expiresAt).toISOString() };
|
|
290
|
+
}
|
|
291
|
+
function renewSession(response, session, now, ttlMs = DEFAULT_SESSION_TTL_MS) {
|
|
292
|
+
session.expiresAt = now() + ttlMs;
|
|
293
|
+
setSessionCookie(response, session);
|
|
294
|
+
}
|
|
295
|
+
function setSessionCookie(response, session) {
|
|
296
|
+
response.setHeader("set-cookie", `${SESSION_COOKIE}=${session.id}; Path=/; HttpOnly; SameSite=Strict`);
|
|
297
|
+
}
|
|
298
|
+
function clearSessionCookie(response) {
|
|
299
|
+
response.setHeader("set-cookie", `${SESSION_COOKIE}=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0`);
|
|
300
|
+
}
|
|
301
|
+
function parseCookies(value) {
|
|
302
|
+
if (value === undefined)
|
|
303
|
+
return {};
|
|
304
|
+
return Object.fromEntries(value.split(";").map((part) => part.trim().split("=", 2)).filter((pair) => pair.length === 2));
|
|
305
|
+
}
|
|
306
|
+
function isAllowedHost(value, boundHost) {
|
|
307
|
+
const normalized = value.toLowerCase();
|
|
308
|
+
if (boundHost === "::1")
|
|
309
|
+
return /^\[::1\]:\d+$/u.test(normalized);
|
|
310
|
+
return /^(?:127\.0\.0\.1|localhost):\d+$/u.test(normalized);
|
|
311
|
+
}
|
|
312
|
+
function isLoopbackAddress(value) {
|
|
313
|
+
return value === "127.0.0.1" || value === "::1" || value === "::ffff:127.0.0.1";
|
|
314
|
+
}
|
|
315
|
+
function safeTokenEquals(left, right) {
|
|
316
|
+
const leftBuffer = Buffer.from(left);
|
|
317
|
+
const rightBuffer = Buffer.from(right);
|
|
318
|
+
return leftBuffer.byteLength === rightBuffer.byteLength && timingSafeEqual(leftBuffer, rightBuffer);
|
|
319
|
+
}
|
|
320
|
+
function randomToken() {
|
|
321
|
+
return randomBytes(32).toString("base64url");
|
|
322
|
+
}
|
|
323
|
+
function contentType(filePath) {
|
|
324
|
+
switch (path.extname(filePath).toLowerCase()) {
|
|
325
|
+
case ".html": return "text/html; charset=utf-8";
|
|
326
|
+
case ".js": return "text/javascript; charset=utf-8";
|
|
327
|
+
case ".css": return "text/css; charset=utf-8";
|
|
328
|
+
case ".json": return "application/json; charset=utf-8";
|
|
329
|
+
case ".svg": return "image/svg+xml";
|
|
330
|
+
case ".png": return "image/png";
|
|
331
|
+
case ".jpg":
|
|
332
|
+
case ".jpeg": return "image/jpeg";
|
|
333
|
+
case ".webp": return "image/webp";
|
|
334
|
+
case ".woff2": return "font/woff2";
|
|
335
|
+
default: return "application/octet-stream";
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
function safeErrorMessage(error) {
|
|
339
|
+
return error instanceof Error ? redactSecrets(error.message) : "Local Conductor request failed.";
|
|
340
|
+
}
|
|
341
|
+
const OMITTED_BROWSER_KEYS = new Set([
|
|
342
|
+
"credential",
|
|
343
|
+
"usercredential",
|
|
344
|
+
"machinecredential",
|
|
345
|
+
"accesstoken",
|
|
346
|
+
"refreshtoken",
|
|
347
|
+
"apikey",
|
|
348
|
+
"environment",
|
|
349
|
+
"env",
|
|
350
|
+
"rawprompt",
|
|
351
|
+
"prompt",
|
|
352
|
+
"workspacepath",
|
|
353
|
+
"pairingcode",
|
|
354
|
+
]);
|
|
355
|
+
function safeBrowserPayload(value) {
|
|
356
|
+
if (typeof value === "string")
|
|
357
|
+
return redactSecrets(value);
|
|
358
|
+
if (Array.isArray(value))
|
|
359
|
+
return value.map((entry) => safeBrowserPayload(entry));
|
|
360
|
+
if (typeof value !== "object" || value === null)
|
|
361
|
+
return value;
|
|
362
|
+
return Object.fromEntries(Object.entries(value)
|
|
363
|
+
.filter(([key]) => !OMITTED_BROWSER_KEYS.has(key.replace(/[_-]/gu, "").toLowerCase()))
|
|
364
|
+
.map(([key, entry]) => [key, safeBrowserPayload(entry)]));
|
|
365
|
+
}
|
|
366
|
+
async function listenWithFallback(server, host, preferredPort) {
|
|
367
|
+
for (let offset = 0; offset < MAX_PORT_ATTEMPTS; offset += 1) {
|
|
368
|
+
const port = preferredPort === 0 ? 0 : preferredPort + offset;
|
|
369
|
+
try {
|
|
370
|
+
return await listen(server, host, port);
|
|
371
|
+
}
|
|
372
|
+
catch (error) {
|
|
373
|
+
if (!isAddressInUse(error) || preferredPort === 0 || offset === MAX_PORT_ATTEMPTS - 1)
|
|
374
|
+
throw error;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
throw new Error("No loopback port is available for Sift Conductor.");
|
|
378
|
+
}
|
|
379
|
+
function listen(server, host, port) {
|
|
380
|
+
return new Promise((resolve, reject) => {
|
|
381
|
+
const onError = (error) => {
|
|
382
|
+
server.off("listening", onListening);
|
|
383
|
+
reject(error);
|
|
384
|
+
};
|
|
385
|
+
const onListening = () => {
|
|
386
|
+
server.off("error", onError);
|
|
387
|
+
const address = server.address();
|
|
388
|
+
if (address === null || typeof address === "string") {
|
|
389
|
+
reject(new Error("Local Conductor did not receive a TCP port."));
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
resolve(address.port);
|
|
393
|
+
};
|
|
394
|
+
server.once("error", onError);
|
|
395
|
+
server.once("listening", onListening);
|
|
396
|
+
server.listen(port, host);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
function closeServer(server) {
|
|
400
|
+
return new Promise((resolve, reject) => server.close((error) => error === undefined ? resolve() : reject(error)));
|
|
401
|
+
}
|
|
402
|
+
function isAddressInUse(error) {
|
|
403
|
+
return error instanceof Error && "code" in error && error.code === "EADDRINUSE";
|
|
404
|
+
}
|
|
405
|
+
export async function assertStaticAssets(staticDirectory) {
|
|
406
|
+
const indexPath = path.join(staticDirectory, "index.html");
|
|
407
|
+
const contents = await readFile(indexPath, "utf8");
|
|
408
|
+
if (!contents.includes("<div id=\"root\"></div>")) {
|
|
409
|
+
throw new Error("Conductor web entrypoint is missing its root element.");
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=server.js.map
|