openpond 0.0.30-bootstrap.0 → 0.0.30
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 +19 -5
- package/dist/chunks/{app-layer-YKXEQGOW.js → app-layer-FIGCNZJX.js} +7 -4
- package/dist/chunks/{apps-GGSIN2ZF.js → apps-4RMNCKXS.js} +3 -3
- package/dist/chunks/{chunk-I6HN3ZGW.js → chunk-4S3XGFGL.js} +1 -1
- package/dist/chunks/{chunk-KRKGHVMQ.js → chunk-57P2GCW5.js} +1 -1
- package/dist/chunks/{chunk-4HYJG2JE.js → chunk-BBEVMP6O.js} +2 -2
- package/dist/chunks/{chunk-XSAXENQD.js → chunk-BNPFMGZD.js} +2 -2
- package/dist/chunks/{chunk-3CC6MH35.js → chunk-BNVHGSI7.js} +3 -3
- package/dist/chunks/{chunk-Q57SVPEH.js → chunk-BX4XSB2J.js} +5619 -6654
- package/dist/chunks/{chunk-Y6G6WRTG.js → chunk-DANRS43D.js} +57 -12
- package/dist/chunks/{chunk-FUP7EGT7.js → chunk-GGKA4HLQ.js} +2 -2
- package/dist/chunks/chunk-IUTUUNAX.js +1126 -0
- package/dist/chunks/{chunk-74O6FGVN.js → chunk-KEDXE4BA.js} +3 -3
- package/dist/chunks/{chunk-3Y4EL3P6.js → chunk-KMSMK7PI.js} +36 -35
- package/dist/chunks/{chunk-5G4E547X.js → chunk-MFS3SYUH.js} +1 -1
- package/dist/chunks/{chunk-NLBKZZEK.js → chunk-OV3KAFWB.js} +1 -1
- package/dist/chunks/{chunk-AUJLPKGI.js → chunk-RJXX6TJA.js} +2 -2
- package/dist/chunks/{cli-NVKNE4AZ.js → cli-2L4NB7HD.js} +5 -2
- package/dist/chunks/{cli-X3HPLSOV.js → cli-5RL7B2Z3.js} +5 -5
- package/dist/chunks/{core-commands-IM2UKLU4.js → core-commands-AZJZGTZS.js} +4 -4
- package/dist/chunks/{extend-YXCBULPO.js → extend-6IWYZI37.js} +8 -8
- package/dist/chunks/{harness-GMK6IY2U.js → harness-SSNXDSKM.js} +3 -3
- package/dist/chunks/{help-LMH5FGT2.js → help-MUJJMI3Q.js} +2 -1
- package/dist/chunks/{opchat-BWXZ32GX.js → opchat-RW4CFAQB.js} +5 -5
- package/dist/chunks/{organizations-4ISQRGMQ.js → organizations-V7DTNLSI.js} +73 -15
- package/dist/chunks/{profile-NLDZDT3L.js → profile-WDBKJ7YW.js} +6 -6
- package/dist/chunks/{project-agent-ZPVO25HA.js → project-agent-3TZ3BPYN.js} +5 -5
- package/dist/chunks/{sandbox-command-5GFJ2U3V.js → sandbox-command-HOYHF4NC.js} +4 -4
- package/dist/chunks/{sandbox-template-LZN4F55Z.js → sandbox-template-IYGB4CZU.js} +5 -5
- package/dist/chunks/{src-3RBI4DNN.js → src-CBPRIWG5.js} +7 -15
- package/dist/chunks/{src-EYXQS6XD.js → src-ZRQKSQTD.js} +14 -12
- package/dist/chunks/{teams-bot-WP3FHKGA.js → teams-bot-UWGCFL6C.js} +3 -3
- package/dist/cli.js +28 -17
- package/docs/command-reference.md +2 -1
- package/package.json +3 -1
|
@@ -0,0 +1,1126 @@
|
|
|
1
|
+
import { createRequire as __openpondCreateRequire } from "node:module"; var require = __openpondCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_OPENPOND_API_BASE_URL,
|
|
4
|
+
DEFAULT_OPENPOND_CHAT_MODEL,
|
|
5
|
+
DEFAULT_OPENPOND_WEB_BASE_URL,
|
|
6
|
+
ProviderCatalogSchema,
|
|
7
|
+
SandboxAppActionRegistrySchema,
|
|
8
|
+
checkOpenPondApiHealth,
|
|
9
|
+
createRepo,
|
|
10
|
+
getAppEnvironment,
|
|
11
|
+
getOpenPondAccount,
|
|
12
|
+
getOpenPondAccountBalance,
|
|
13
|
+
listApps,
|
|
14
|
+
listConfiguredProfiles,
|
|
15
|
+
loadGlobalConfig,
|
|
16
|
+
saveConfig,
|
|
17
|
+
saveProfileApiKey,
|
|
18
|
+
setActiveProfile
|
|
19
|
+
} from "./chunk-BX4XSB2J.js";
|
|
20
|
+
|
|
21
|
+
// ../../packages/runtime/dist/chat.js
|
|
22
|
+
import { randomUUID } from "node:crypto";
|
|
23
|
+
|
|
24
|
+
// ../../packages/runtime/dist/urls.js
|
|
25
|
+
var DEFAULT_OPENPOND_API_HOST = new URL(DEFAULT_OPENPOND_API_BASE_URL).hostname;
|
|
26
|
+
var DEFAULT_OPENPOND_WEB_HOST = new URL(DEFAULT_OPENPOND_WEB_BASE_URL).hostname;
|
|
27
|
+
var DEFAULT_OPENPOND_OPCHAT_API_BASE_URL = `${DEFAULT_OPENPOND_API_BASE_URL}/opchat/v1`;
|
|
28
|
+
function normalizeBaseUrl(value) {
|
|
29
|
+
if (!value)
|
|
30
|
+
return null;
|
|
31
|
+
const trimmed = value.trim();
|
|
32
|
+
return trimmed ? trimmed.replace(/\/+$/, "") : null;
|
|
33
|
+
}
|
|
34
|
+
function mapUiBaseToApiBase(baseUrl) {
|
|
35
|
+
const trimmed = normalizeBaseUrl(baseUrl);
|
|
36
|
+
if (!trimmed)
|
|
37
|
+
return null;
|
|
38
|
+
try {
|
|
39
|
+
const url = new URL(trimmed);
|
|
40
|
+
const host = url.hostname.toLowerCase();
|
|
41
|
+
if (host === DEFAULT_OPENPOND_API_HOST)
|
|
42
|
+
return DEFAULT_OPENPOND_API_BASE_URL;
|
|
43
|
+
if (host === DEFAULT_OPENPOND_WEB_HOST || host === "openpond.live" || host === "www.openpond.live") {
|
|
44
|
+
return DEFAULT_OPENPOND_API_BASE_URL;
|
|
45
|
+
}
|
|
46
|
+
if (host.startsWith("api."))
|
|
47
|
+
return trimmed;
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
function resolvePublicApiBaseUrl(account, config) {
|
|
54
|
+
const envBase = normalizeBaseUrl(process.env.OPENPOND_API_URL);
|
|
55
|
+
if (envBase)
|
|
56
|
+
return envBase;
|
|
57
|
+
const accountApiBase = normalizeBaseUrl(account?.apiBaseUrl);
|
|
58
|
+
if (accountApiBase)
|
|
59
|
+
return accountApiBase;
|
|
60
|
+
const configApiBase = normalizeBaseUrl(config.apiBaseUrl);
|
|
61
|
+
if (configApiBase)
|
|
62
|
+
return configApiBase;
|
|
63
|
+
const mappedEnvBase = mapUiBaseToApiBase(process.env.OPENPOND_BASE_URL);
|
|
64
|
+
if (mappedEnvBase)
|
|
65
|
+
return mappedEnvBase;
|
|
66
|
+
const mappedConfigBase = mapUiBaseToApiBase(account?.baseUrl || config.baseUrl);
|
|
67
|
+
return mappedConfigBase ?? DEFAULT_OPENPOND_API_BASE_URL;
|
|
68
|
+
}
|
|
69
|
+
function resolveHostedChatApiBaseUrl(account, config, publicApiBaseUrl) {
|
|
70
|
+
return resolveOpChatApiBaseUrl(account, config, publicApiBaseUrl);
|
|
71
|
+
}
|
|
72
|
+
function resolveOpChatApiBaseUrl(account, config, publicApiBaseUrl) {
|
|
73
|
+
const runtimeEnv = typeof process !== "undefined" ? process.env : {};
|
|
74
|
+
return normalizeOpChatApiBaseUrl(runtimeEnv.OPENPOND_OPCHAT_API_URL) ?? normalizeOpChatApiBaseUrl(account?.chatApiBaseUrl ?? config.chatApiBaseUrl) ?? normalizeOpChatApiBaseUrl(runtimeEnv.OPENPOND_CHAT_API_URL) ?? opChatBaseFromPublicApiBase(publicApiBaseUrl);
|
|
75
|
+
}
|
|
76
|
+
function normalizeOpChatApiBaseUrl(value) {
|
|
77
|
+
const normalized = normalizeBaseUrl(value);
|
|
78
|
+
if (!normalized)
|
|
79
|
+
return null;
|
|
80
|
+
try {
|
|
81
|
+
const url = new URL(normalized);
|
|
82
|
+
const segments = url.pathname.split("/").filter(Boolean);
|
|
83
|
+
const opChatIndex = segments.findIndex((segment) => segment.toLowerCase() === "opchat");
|
|
84
|
+
if (opChatIndex >= 0) {
|
|
85
|
+
url.pathname = `/${[...segments.slice(0, opChatIndex + 1), "v1"].join("/")}`;
|
|
86
|
+
url.search = "";
|
|
87
|
+
url.hash = "";
|
|
88
|
+
return normalizeBaseUrl(url.toString()) ?? null;
|
|
89
|
+
}
|
|
90
|
+
const v1Index = segments.findIndex((segment) => segment.toLowerCase() === "v1");
|
|
91
|
+
if (v1Index >= 0) {
|
|
92
|
+
url.pathname = "/opchat/v1";
|
|
93
|
+
url.search = "";
|
|
94
|
+
url.hash = "";
|
|
95
|
+
return normalizeBaseUrl(url.toString()) ?? null;
|
|
96
|
+
}
|
|
97
|
+
url.pathname = `${url.pathname.replace(/\/+$/, "")}/opchat/v1`.replace(/\/{2,}/g, "/");
|
|
98
|
+
url.search = "";
|
|
99
|
+
url.hash = "";
|
|
100
|
+
return normalizeBaseUrl(url.toString()) ?? null;
|
|
101
|
+
} catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function opChatBaseFromPublicApiBase(publicApiBaseUrl) {
|
|
106
|
+
return normalizeOpChatApiBaseUrl(publicApiBaseUrl) ?? DEFAULT_OPENPOND_OPCHAT_API_BASE_URL;
|
|
107
|
+
}
|
|
108
|
+
function deriveEnvironment(fallback) {
|
|
109
|
+
if (fallback?.trim())
|
|
110
|
+
return fallback.trim();
|
|
111
|
+
return "production";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ../../packages/runtime/dist/selectors.js
|
|
115
|
+
function accountToken(account) {
|
|
116
|
+
const candidates = [
|
|
117
|
+
account?.apiKey,
|
|
118
|
+
account?.session?.token,
|
|
119
|
+
account?.token
|
|
120
|
+
];
|
|
121
|
+
for (const value of candidates) {
|
|
122
|
+
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
123
|
+
if (trimmed)
|
|
124
|
+
return trimmed;
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
function handleEquals(left, right) {
|
|
129
|
+
return Boolean(left && right && left.toLowerCase() === right.toLowerCase());
|
|
130
|
+
}
|
|
131
|
+
function baseUrlEquals(left, right) {
|
|
132
|
+
return normalizeBaseUrl(left) === normalizeBaseUrl(right);
|
|
133
|
+
}
|
|
134
|
+
function profileKey(handle, baseUrl) {
|
|
135
|
+
const normalizedHandle = handle?.trim().toLowerCase() || "";
|
|
136
|
+
return `${normalizedHandle}|${normalizeBaseUrl(baseUrl) ?? "default"}`;
|
|
137
|
+
}
|
|
138
|
+
function selectorBaseUrl(selector) {
|
|
139
|
+
return normalizeBaseUrl(selector?.baseUrl);
|
|
140
|
+
}
|
|
141
|
+
function selectorFromAccount(account) {
|
|
142
|
+
const baseUrl = normalizeBaseUrl(account.baseUrl);
|
|
143
|
+
return baseUrl ? { handle: account.handle, baseUrl } : { handle: account.handle };
|
|
144
|
+
}
|
|
145
|
+
function normalizeActiveProfile(value) {
|
|
146
|
+
const handle = typeof value?.handle === "string" ? value.handle.trim() : "";
|
|
147
|
+
if (!handle)
|
|
148
|
+
return null;
|
|
149
|
+
const baseUrl = normalizeBaseUrl(value?.baseUrl);
|
|
150
|
+
return baseUrl ? { handle, baseUrl } : { handle };
|
|
151
|
+
}
|
|
152
|
+
function accountMatchesSelector(account, selector) {
|
|
153
|
+
if (!handleEquals(account.handle, selector.handle))
|
|
154
|
+
return false;
|
|
155
|
+
const baseUrl = selectorBaseUrl(selector);
|
|
156
|
+
if (baseUrl)
|
|
157
|
+
return baseUrlEquals(account.baseUrl, baseUrl);
|
|
158
|
+
return !normalizeBaseUrl(account.baseUrl);
|
|
159
|
+
}
|
|
160
|
+
function profileMatchesSelector(profile, selector) {
|
|
161
|
+
if (!handleEquals(profile.handle, selector.handle))
|
|
162
|
+
return false;
|
|
163
|
+
const baseUrl = selectorBaseUrl(selector);
|
|
164
|
+
if (baseUrl)
|
|
165
|
+
return baseUrlEquals(profile.baseUrl, baseUrl);
|
|
166
|
+
return !normalizeBaseUrl(profile.baseUrl);
|
|
167
|
+
}
|
|
168
|
+
function findActiveAccount(config, requestedHandle, requestedBaseUrl) {
|
|
169
|
+
const accounts = Array.isArray(config.accounts) ? config.accounts : [];
|
|
170
|
+
const requestedProfile = requestedHandle || process.env.OPENPOND_ACCOUNT ? normalizeActiveProfile({
|
|
171
|
+
handle: requestedHandle || process.env.OPENPOND_ACCOUNT || "",
|
|
172
|
+
baseUrl: requestedBaseUrl ?? process.env.OPENPOND_BASE_URL ?? null
|
|
173
|
+
}) : normalizeActiveProfile(config.activeProfile);
|
|
174
|
+
if (requestedProfile) {
|
|
175
|
+
const exact = accounts.find((account) => accountMatchesSelector(account, requestedProfile));
|
|
176
|
+
if (exact)
|
|
177
|
+
return exact;
|
|
178
|
+
const sameHandle = accounts.filter((account) => handleEquals(account.handle, requestedProfile.handle));
|
|
179
|
+
if (!selectorBaseUrl(requestedProfile) && sameHandle.length === 1)
|
|
180
|
+
return sameHandle[0] ?? null;
|
|
181
|
+
}
|
|
182
|
+
if (accounts[0])
|
|
183
|
+
return accounts[0];
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
function fallbackProfilesFromConfig(config) {
|
|
187
|
+
const accounts = Array.isArray(config.accounts) ? config.accounts : [];
|
|
188
|
+
const activeProfile = normalizeActiveProfile(config.activeProfile) ?? (accounts[0] ? selectorFromAccount(accounts[0]) : null);
|
|
189
|
+
return normalizeProfiles(accounts.map((account) => ({
|
|
190
|
+
handle: account.handle,
|
|
191
|
+
baseUrl: normalizeBaseUrl(account.baseUrl),
|
|
192
|
+
apiBaseUrl: normalizeBaseUrl(account.apiBaseUrl),
|
|
193
|
+
chatApiBaseUrl: normalizeBaseUrl(account.chatApiBaseUrl),
|
|
194
|
+
environment: deriveEnvironment(account.environment),
|
|
195
|
+
isActive: activeProfile ? accountMatchesSelector(account, activeProfile) : false,
|
|
196
|
+
hasApiKey: Boolean(account.apiKey?.trim()),
|
|
197
|
+
hasSessionToken: Boolean(account.session?.token?.trim() || account.token?.trim()),
|
|
198
|
+
sessionAppId: account.session?.appId ?? null,
|
|
199
|
+
sessionConversationId: account.session?.conversationId ?? null
|
|
200
|
+
})));
|
|
201
|
+
}
|
|
202
|
+
function normalizeProfiles(profiles) {
|
|
203
|
+
const result = /* @__PURE__ */ new Map();
|
|
204
|
+
for (const profile of profiles) {
|
|
205
|
+
const normalizedBaseUrl = normalizeBaseUrl(profile.baseUrl);
|
|
206
|
+
const key = `${profile.handle.toLowerCase()}|${normalizedBaseUrl ?? "default"}`;
|
|
207
|
+
const normalized = {
|
|
208
|
+
...profile,
|
|
209
|
+
baseUrl: normalizedBaseUrl,
|
|
210
|
+
apiBaseUrl: normalizeBaseUrl(profile.apiBaseUrl),
|
|
211
|
+
chatApiBaseUrl: normalizeBaseUrl(profile.chatApiBaseUrl),
|
|
212
|
+
environment: deriveEnvironment(profile.environment),
|
|
213
|
+
isActive: profile.isActive
|
|
214
|
+
};
|
|
215
|
+
const current = result.get(key);
|
|
216
|
+
if (!current || normalized.isActive && !current.isActive || normalized.hasApiKey && !current.hasApiKey) {
|
|
217
|
+
result.set(key, normalized);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return Array.from(result.values());
|
|
221
|
+
}
|
|
222
|
+
function profileAuthHealth(profile) {
|
|
223
|
+
return profile.hasApiKey || profile.hasSessionToken ? "signed_in" : "signed_out";
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ../../packages/runtime/dist/account-state.js
|
|
227
|
+
function normalizeHealth(health, apiBaseUrl) {
|
|
228
|
+
if (!health)
|
|
229
|
+
return null;
|
|
230
|
+
return {
|
|
231
|
+
reachable: health.reachable,
|
|
232
|
+
authenticated: health.authenticated,
|
|
233
|
+
apiBase: health.apiBase || apiBaseUrl,
|
|
234
|
+
latencyMs: health.latencyMs,
|
|
235
|
+
status: health.status,
|
|
236
|
+
service: health.service,
|
|
237
|
+
checkedAt: health.checkedAt,
|
|
238
|
+
error: health.error ?? null
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function normalizeProfile(response) {
|
|
242
|
+
const account = response?.account;
|
|
243
|
+
if (!account)
|
|
244
|
+
return null;
|
|
245
|
+
return {
|
|
246
|
+
id: account.id ?? null,
|
|
247
|
+
email: account.email ?? null,
|
|
248
|
+
name: account.name ?? null,
|
|
249
|
+
handle: account.handle ?? null,
|
|
250
|
+
image: account.image ?? null,
|
|
251
|
+
timezone: account.timezone ?? null,
|
|
252
|
+
isAdmin: account.isAdmin ?? null,
|
|
253
|
+
isVerified: account.isVerified ?? null,
|
|
254
|
+
dailyAgentAppId: account.dailyAgentAppId ?? null,
|
|
255
|
+
dailyAgentDeploymentId: account.dailyAgentDeploymentId ?? null,
|
|
256
|
+
credits: account.credits ?? null,
|
|
257
|
+
turnkeyWalletAddress: account.turnkeyWalletAddress ?? null,
|
|
258
|
+
turnkeyOperatingWalletAddress: account.turnkeyOperatingWalletAddress ?? null
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function normalizeProducts(products) {
|
|
262
|
+
return (products ?? []).map((product) => ({
|
|
263
|
+
...product,
|
|
264
|
+
id: product.id || product.userProductId || product.openPondProductId || product.name,
|
|
265
|
+
name: product.name,
|
|
266
|
+
type: product.type,
|
|
267
|
+
status: product.status,
|
|
268
|
+
isActive: product.isActive ?? null,
|
|
269
|
+
price: product.price ?? null,
|
|
270
|
+
currency: product.currency ?? null,
|
|
271
|
+
credits: product.credits ?? null
|
|
272
|
+
}));
|
|
273
|
+
}
|
|
274
|
+
function normalizeBalance(response, error) {
|
|
275
|
+
if (!response)
|
|
276
|
+
return null;
|
|
277
|
+
return {
|
|
278
|
+
balanceKind: response.balanceKind,
|
|
279
|
+
balanceUsd: response.balanceUsd ?? null,
|
|
280
|
+
balanceUsdCents: response.balanceUsdCents ?? null,
|
|
281
|
+
currency: response.currency,
|
|
282
|
+
asOf: response.asOf,
|
|
283
|
+
stale: response.stale ?? Boolean(error),
|
|
284
|
+
error: error ?? null,
|
|
285
|
+
breakdown: (response.breakdown ?? []).map((item) => ({
|
|
286
|
+
wallet: item.wallet,
|
|
287
|
+
chain: item.chain,
|
|
288
|
+
chainId: item.chainId ?? null,
|
|
289
|
+
asset: item.asset,
|
|
290
|
+
amount: item.amount ?? null,
|
|
291
|
+
usdValue: item.usdValue ?? null
|
|
292
|
+
}))
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
function isEmptyDefaultProfile(profile) {
|
|
296
|
+
return profile.handle.trim().toLowerCase() === "default" && !normalizeBaseUrl(profile.baseUrl) && !profile.hasApiKey && !profile.hasSessionToken;
|
|
297
|
+
}
|
|
298
|
+
function toAccountState(input) {
|
|
299
|
+
const { config, profiles, account, token, apiBaseUrl, accountResponse, balanceResponse, accountProfiles, health, authFailed, error, balanceError } = input;
|
|
300
|
+
const chatApiBaseUrl = resolveHostedChatApiBaseUrl(account, config, apiBaseUrl);
|
|
301
|
+
const profile = normalizeProfile(accountResponse ?? null);
|
|
302
|
+
const balance = normalizeBalance(balanceResponse, balanceError);
|
|
303
|
+
const configActiveProfile = normalizeActiveProfile(config.activeProfile);
|
|
304
|
+
const accountSelector = account ? selectorFromAccount(account) : null;
|
|
305
|
+
const activeSelector = accountSelector ?? configActiveProfile;
|
|
306
|
+
const displayHandle = profile?.handle || account?.handle || activeSelector?.handle || null;
|
|
307
|
+
const activeProfileRow = (activeSelector ? profiles.find((candidate) => profileMatchesSelector(candidate, activeSelector)) : null) ?? profiles.find((candidate) => candidate.isActive) ?? null;
|
|
308
|
+
const healthState = authFailed ? "auth_error" : token ? "signed_in" : "signed_out";
|
|
309
|
+
const label = profile?.name || profile?.handle || profile?.email || displayHandle || "Signed out";
|
|
310
|
+
const baseUrl = normalizeBaseUrl(activeProfileRow?.baseUrl || account?.baseUrl || DEFAULT_OPENPOND_WEB_BASE_URL);
|
|
311
|
+
const environment = deriveEnvironment(activeProfileRow?.environment || account?.environment);
|
|
312
|
+
const activeProfile = normalizeActiveProfile(activeSelector) ?? (displayHandle ? normalizeActiveProfile({ handle: displayHandle, baseUrl: activeProfileRow?.baseUrl ?? account?.baseUrl }) : null);
|
|
313
|
+
const profileRows = profiles.length > 0 ? profiles : displayHandle ? [
|
|
314
|
+
{
|
|
315
|
+
handle: displayHandle,
|
|
316
|
+
baseUrl: selectorBaseUrl(activeProfile) ?? normalizeBaseUrl(account?.baseUrl),
|
|
317
|
+
apiBaseUrl,
|
|
318
|
+
chatApiBaseUrl,
|
|
319
|
+
environment,
|
|
320
|
+
isActive: true,
|
|
321
|
+
hasApiKey: Boolean(token),
|
|
322
|
+
hasSessionToken: false,
|
|
323
|
+
sessionAppId: null,
|
|
324
|
+
sessionConversationId: null
|
|
325
|
+
}
|
|
326
|
+
] : [];
|
|
327
|
+
const visibleProfileRows = profileRows.filter((candidate) => !isEmptyDefaultProfile(candidate));
|
|
328
|
+
return {
|
|
329
|
+
state: healthState,
|
|
330
|
+
activeProfile,
|
|
331
|
+
label,
|
|
332
|
+
email: profile?.email ?? null,
|
|
333
|
+
avatarUrl: profile?.image ?? null,
|
|
334
|
+
environment,
|
|
335
|
+
baseUrl,
|
|
336
|
+
apiBaseUrl,
|
|
337
|
+
chatApiBaseUrl,
|
|
338
|
+
balanceLabel: balanceResponse?.balanceLabel ?? "$0.00",
|
|
339
|
+
balance,
|
|
340
|
+
creditsLabel: profile?.credits ?? null,
|
|
341
|
+
profile,
|
|
342
|
+
products: normalizeProducts(accountResponse?.products),
|
|
343
|
+
apiHealth: normalizeHealth(health ?? null, apiBaseUrl),
|
|
344
|
+
accounts: visibleProfileRows.map((candidate) => {
|
|
345
|
+
const candidateBaseUrl = normalizeBaseUrl(candidate.baseUrl);
|
|
346
|
+
const profileLookup = accountProfiles?.[profileKey(candidate.handle, candidateBaseUrl)] ?? null;
|
|
347
|
+
const candidateProfile = normalizeProfile(profileLookup?.response ?? null);
|
|
348
|
+
return {
|
|
349
|
+
handle: candidate.handle,
|
|
350
|
+
baseUrl: candidateBaseUrl,
|
|
351
|
+
apiBaseUrl: normalizeBaseUrl(candidate.apiBaseUrl),
|
|
352
|
+
chatApiBaseUrl: normalizeBaseUrl(candidate.chatApiBaseUrl),
|
|
353
|
+
environment: deriveEnvironment(candidate.environment),
|
|
354
|
+
isActive: activeProfile ? profileMatchesSelector(candidate, activeProfile) : false,
|
|
355
|
+
authHealth: profileLookup?.authFailed ? "auth_error" : profileAuthHealth(candidate),
|
|
356
|
+
displayLabel: candidateProfile?.name || candidateProfile?.handle || candidateProfile?.email || candidate.handle,
|
|
357
|
+
email: candidateProfile?.email ?? null,
|
|
358
|
+
avatarUrl: candidateProfile?.image ?? null
|
|
359
|
+
};
|
|
360
|
+
}),
|
|
361
|
+
error: error ?? health?.error ?? null
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// ../../packages/runtime/dist/config.js
|
|
366
|
+
import { readFileSync } from "node:fs";
|
|
367
|
+
import { homedir } from "node:os";
|
|
368
|
+
import { join } from "node:path";
|
|
369
|
+
function readRawOpenPondConfig() {
|
|
370
|
+
try {
|
|
371
|
+
const raw = JSON.parse(readFileSync(join(homedir(), ".openpond", "config.json"), "utf8"));
|
|
372
|
+
return raw && typeof raw === "object" ? raw : {};
|
|
373
|
+
} catch {
|
|
374
|
+
return {};
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
function mergeRawApiBaseConfig(config) {
|
|
378
|
+
const raw = readRawOpenPondConfig();
|
|
379
|
+
const rawAccounts = Array.isArray(raw.accounts) ? raw.accounts : [];
|
|
380
|
+
const accounts = Array.isArray(config.accounts) ? config.accounts : [];
|
|
381
|
+
return {
|
|
382
|
+
...config,
|
|
383
|
+
activeProfile: config.activeProfile ?? raw.activeProfile,
|
|
384
|
+
apiBaseUrl: config.apiBaseUrl ?? raw.apiBaseUrl,
|
|
385
|
+
chatApiBaseUrl: config.chatApiBaseUrl ?? raw.chatApiBaseUrl,
|
|
386
|
+
accounts: accounts.map((account) => {
|
|
387
|
+
const rawAccount = rawAccounts.find((candidate) => handleEquals(candidate.handle, account.handle) && baseUrlEquals(candidate.baseUrl, account.baseUrl)) ?? rawAccounts.find((candidate) => handleEquals(candidate.handle, account.handle));
|
|
388
|
+
return {
|
|
389
|
+
...account,
|
|
390
|
+
...typeof rawAccount?.apiBaseUrl === "string" && rawAccount.apiBaseUrl.trim() ? { apiBaseUrl: rawAccount.apiBaseUrl } : {},
|
|
391
|
+
...typeof rawAccount?.chatApiBaseUrl === "string" && rawAccount.chatApiBaseUrl.trim() ? { chatApiBaseUrl: rawAccount.chatApiBaseUrl } : {}
|
|
392
|
+
};
|
|
393
|
+
})
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// ../../packages/runtime/dist/account-context.js
|
|
398
|
+
async function loadProfiles(config) {
|
|
399
|
+
try {
|
|
400
|
+
return normalizeProfiles(await listConfiguredProfiles());
|
|
401
|
+
} catch {
|
|
402
|
+
return fallbackProfilesFromConfig(config);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
async function loadOpenPondAccountContext(requestedHandle, requestedBaseUrl) {
|
|
406
|
+
const config = mergeRawApiBaseConfig(await loadGlobalConfig().catch(() => ({})));
|
|
407
|
+
const profiles = await loadProfiles(config);
|
|
408
|
+
const account = findActiveAccount(config, requestedHandle, requestedBaseUrl);
|
|
409
|
+
const token = accountToken(account);
|
|
410
|
+
const apiBaseUrl = resolvePublicApiBaseUrl(account, config);
|
|
411
|
+
const chatApiBaseUrl = resolveHostedChatApiBaseUrl(account, config, apiBaseUrl);
|
|
412
|
+
return {
|
|
413
|
+
config,
|
|
414
|
+
profiles,
|
|
415
|
+
account,
|
|
416
|
+
token,
|
|
417
|
+
apiBaseUrl,
|
|
418
|
+
chatApiBaseUrl,
|
|
419
|
+
accountState: toAccountState({ config, profiles, account, token, apiBaseUrl })
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
async function switchOpenPondAccount(input) {
|
|
423
|
+
const baseUrl = normalizeBaseUrl(input.baseUrl);
|
|
424
|
+
await setActiveProfile(input.handle, {
|
|
425
|
+
baseUrl
|
|
426
|
+
});
|
|
427
|
+
return loadOpenPondAccountContext(input.handle, baseUrl);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// ../../packages/runtime/dist/errors.js
|
|
431
|
+
function errorMessage(error) {
|
|
432
|
+
return error instanceof Error ? error.message : String(error);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// ../../packages/runtime/dist/chat.js
|
|
436
|
+
var PROVIDER_CATALOG_FETCH_TIMEOUT_MS = 2500;
|
|
437
|
+
async function loadOpenPondProviderCatalog() {
|
|
438
|
+
const context = await loadOpenPondAccountContext();
|
|
439
|
+
if (!context.token) {
|
|
440
|
+
return {
|
|
441
|
+
catalog: null,
|
|
442
|
+
error: "No OpenPond API key or session token is configured."
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
const controller = new AbortController();
|
|
446
|
+
const timeout = setTimeout(() => {
|
|
447
|
+
controller.abort(new Error("OpenPond provider catalog request timed out."));
|
|
448
|
+
}, PROVIDER_CATALOG_FETCH_TIMEOUT_MS);
|
|
449
|
+
try {
|
|
450
|
+
const catalog = await listOpChatProviderCatalog({
|
|
451
|
+
apiBaseUrl: context.chatApiBaseUrl,
|
|
452
|
+
token: context.token,
|
|
453
|
+
signal: controller.signal
|
|
454
|
+
});
|
|
455
|
+
return {
|
|
456
|
+
catalog,
|
|
457
|
+
error: null
|
|
458
|
+
};
|
|
459
|
+
} catch (error) {
|
|
460
|
+
return {
|
|
461
|
+
catalog: null,
|
|
462
|
+
error: errorMessage(error)
|
|
463
|
+
};
|
|
464
|
+
} finally {
|
|
465
|
+
clearTimeout(timeout);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
async function* streamOpenPondHostedChatTurn(input) {
|
|
469
|
+
const context = await loadOpenPondAccountContext();
|
|
470
|
+
if (!context.token) {
|
|
471
|
+
throw new Error("OpenPond is signed out. Add an account in Settings before using OpenPond Chat.");
|
|
472
|
+
}
|
|
473
|
+
yield* streamOpChatChatCompletion({
|
|
474
|
+
apiBaseUrl: context.chatApiBaseUrl,
|
|
475
|
+
token: context.token,
|
|
476
|
+
model: input.model || DEFAULT_OPENPOND_CHAT_MODEL,
|
|
477
|
+
messages: input.messages,
|
|
478
|
+
tools: input.tools,
|
|
479
|
+
toolChoice: input.toolChoice,
|
|
480
|
+
requestId: input.requestId,
|
|
481
|
+
signal: input.signal
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
async function listOpChatProviderCatalog(options) {
|
|
485
|
+
const response = await fetch(opChatEndpointUrl(options.apiBaseUrl, "provider-catalog"), {
|
|
486
|
+
method: "GET",
|
|
487
|
+
headers: opChatHeaders(options.token, "application/json"),
|
|
488
|
+
signal: options.signal
|
|
489
|
+
});
|
|
490
|
+
if (!response.ok) {
|
|
491
|
+
throw new Error(`OpenPond OpChat provider catalog failed: ${response.status} ${await readOpChatError(response)}`);
|
|
492
|
+
}
|
|
493
|
+
return ProviderCatalogSchema.parse(await response.json());
|
|
494
|
+
}
|
|
495
|
+
async function* streamOpChatChatCompletion(options) {
|
|
496
|
+
const response = await fetch(opChatEndpointUrl(options.apiBaseUrl, "chat/completions"), {
|
|
497
|
+
method: "POST",
|
|
498
|
+
headers: opChatHeaders(options.token, "text/event-stream", options.requestId),
|
|
499
|
+
body: JSON.stringify(buildOpChatBody(options)),
|
|
500
|
+
signal: options.signal
|
|
501
|
+
});
|
|
502
|
+
if (!response.ok || !response.body) {
|
|
503
|
+
throw new Error(`OpenPond OpChat stream failed: ${response.status} ${await readOpChatError(response)}`);
|
|
504
|
+
}
|
|
505
|
+
let reasoningText = "";
|
|
506
|
+
let hasToolCalls = false;
|
|
507
|
+
let pendingFinish = null;
|
|
508
|
+
let latestRaw = null;
|
|
509
|
+
for await (const raw of parseOpChatSse(response.body, options.signal)) {
|
|
510
|
+
latestRaw = raw;
|
|
511
|
+
if (raw && typeof raw === "object" && "error" in raw) {
|
|
512
|
+
throw new Error(`OpenPond OpChat stream failed: ${errorMessageFromPayload(raw)}`);
|
|
513
|
+
}
|
|
514
|
+
const usage = parseUsage(raw);
|
|
515
|
+
if (usage)
|
|
516
|
+
yield { type: "usage", usage, raw };
|
|
517
|
+
for (const delta of streamDeltasFromChunk(raw)) {
|
|
518
|
+
if (delta.type === "reasoning_delta")
|
|
519
|
+
reasoningText += delta.text;
|
|
520
|
+
if (delta.type === "tool_call_delta")
|
|
521
|
+
hasToolCalls = true;
|
|
522
|
+
if (delta.type === "finish")
|
|
523
|
+
pendingFinish = delta;
|
|
524
|
+
else
|
|
525
|
+
yield delta;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
if (hasToolCalls && reasoningText) {
|
|
529
|
+
yield {
|
|
530
|
+
type: "continuation",
|
|
531
|
+
continuation: {
|
|
532
|
+
kind: "chat_completions_reasoning",
|
|
533
|
+
reasoningContent: reasoningText
|
|
534
|
+
},
|
|
535
|
+
raw: latestRaw
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
if (pendingFinish)
|
|
539
|
+
yield pendingFinish;
|
|
540
|
+
}
|
|
541
|
+
function buildOpChatBody(options) {
|
|
542
|
+
const body = {
|
|
543
|
+
model: options.model,
|
|
544
|
+
messages: options.messages.map(opChatMessage),
|
|
545
|
+
stream: true
|
|
546
|
+
};
|
|
547
|
+
if (options.tools) {
|
|
548
|
+
body.tools = options.tools;
|
|
549
|
+
}
|
|
550
|
+
if (options.toolChoice !== void 0) {
|
|
551
|
+
body.tool_choice = options.toolChoice;
|
|
552
|
+
}
|
|
553
|
+
return body;
|
|
554
|
+
}
|
|
555
|
+
function opChatMessage(message) {
|
|
556
|
+
const { continuation, ...projected } = message;
|
|
557
|
+
if (message.role === "assistant" && continuation?.kind === "chat_completions_reasoning") {
|
|
558
|
+
return {
|
|
559
|
+
...projected,
|
|
560
|
+
reasoning_content: continuation.reasoningContent
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
return projected;
|
|
564
|
+
}
|
|
565
|
+
function opChatEndpointUrl(apiBaseUrl, path) {
|
|
566
|
+
const normalized = apiBaseUrl.trim().replace(/\/+$/, "");
|
|
567
|
+
if (!normalized)
|
|
568
|
+
throw new Error("OpenPond OpChat API base URL is required.");
|
|
569
|
+
return `${normalized}/${path}`;
|
|
570
|
+
}
|
|
571
|
+
function opChatHeaders(token, accept, requestId) {
|
|
572
|
+
const trimmed = token.trim();
|
|
573
|
+
if (!trimmed)
|
|
574
|
+
throw new Error("OpenPond API key is required for OpChat.");
|
|
575
|
+
const headers = new Headers();
|
|
576
|
+
headers.set("Authorization", `Bearer ${trimmed}`);
|
|
577
|
+
headers.set("Content-Type", "application/json");
|
|
578
|
+
headers.set("Accept", accept);
|
|
579
|
+
headers.set("x-openpond-client", "openpond-app");
|
|
580
|
+
headers.set("x-openpond-request-id", requestId || randomUUID());
|
|
581
|
+
return headers;
|
|
582
|
+
}
|
|
583
|
+
async function readOpChatError(response) {
|
|
584
|
+
const text = await response.text().catch(() => "");
|
|
585
|
+
if (!text)
|
|
586
|
+
return response.statusText || `HTTP ${response.status}`;
|
|
587
|
+
try {
|
|
588
|
+
return errorMessageFromPayload(JSON.parse(text));
|
|
589
|
+
} catch {
|
|
590
|
+
return text;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function errorMessageFromPayload(payload) {
|
|
594
|
+
if (!payload || typeof payload !== "object")
|
|
595
|
+
return String(payload || "unknown_error");
|
|
596
|
+
const record = payload;
|
|
597
|
+
const error = record.error;
|
|
598
|
+
if (error && typeof error === "object") {
|
|
599
|
+
const errorRecord = error;
|
|
600
|
+
return [
|
|
601
|
+
stringValue(errorRecord.code),
|
|
602
|
+
stringValue(errorRecord.type),
|
|
603
|
+
stringValue(errorRecord.message)
|
|
604
|
+
].filter(Boolean).join(": ");
|
|
605
|
+
}
|
|
606
|
+
return [stringValue(record.error), stringValue(record.message)].filter(Boolean).join(": ") || JSON.stringify(payload);
|
|
607
|
+
}
|
|
608
|
+
async function* parseOpChatSse(stream, signal) {
|
|
609
|
+
const reader = stream.getReader();
|
|
610
|
+
const decoder = new TextDecoder();
|
|
611
|
+
let buffer = "";
|
|
612
|
+
const abortError = () => signal?.reason instanceof Error ? signal.reason : new Error("openpond_opchat_aborted");
|
|
613
|
+
try {
|
|
614
|
+
while (true) {
|
|
615
|
+
if (signal?.aborted)
|
|
616
|
+
throw abortError();
|
|
617
|
+
const result = await reader.read();
|
|
618
|
+
if (result.done)
|
|
619
|
+
break;
|
|
620
|
+
buffer += decoder.decode(result.value, { stream: true });
|
|
621
|
+
const blocks = buffer.split(/\r?\n\r?\n/);
|
|
622
|
+
buffer = blocks.pop() ?? "";
|
|
623
|
+
for (const block of blocks) {
|
|
624
|
+
for (const payload of parseSseBlock(block))
|
|
625
|
+
yield payload;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
} finally {
|
|
629
|
+
reader.releaseLock();
|
|
630
|
+
}
|
|
631
|
+
buffer += decoder.decode();
|
|
632
|
+
if (buffer.trim()) {
|
|
633
|
+
for (const payload of parseSseBlock(buffer))
|
|
634
|
+
yield payload;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
function parseSseBlock(block) {
|
|
638
|
+
const data = block.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).join("\n").trim();
|
|
639
|
+
if (!data || data === "[DONE]")
|
|
640
|
+
return [];
|
|
641
|
+
return [JSON.parse(data)];
|
|
642
|
+
}
|
|
643
|
+
function streamDeltasFromChunk(raw) {
|
|
644
|
+
if (!raw || typeof raw !== "object")
|
|
645
|
+
return [];
|
|
646
|
+
const record = raw;
|
|
647
|
+
const choices = Array.isArray(record.choices) ? record.choices : [];
|
|
648
|
+
const deltas = [];
|
|
649
|
+
for (const choice of choices) {
|
|
650
|
+
if (!choice || typeof choice !== "object")
|
|
651
|
+
continue;
|
|
652
|
+
const choiceRecord = choice;
|
|
653
|
+
const delta = choiceRecord.delta && typeof choiceRecord.delta === "object" ? choiceRecord.delta : {};
|
|
654
|
+
for (const key of ["content", "reasoning_content"]) {
|
|
655
|
+
const value = stringValue(delta[key]);
|
|
656
|
+
if (!value)
|
|
657
|
+
continue;
|
|
658
|
+
deltas.push({
|
|
659
|
+
type: key === "content" ? "text_delta" : "reasoning_delta",
|
|
660
|
+
text: value,
|
|
661
|
+
raw
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
const toolCalls = parseToolCalls(delta.tool_calls);
|
|
665
|
+
if (toolCalls.length > 0) {
|
|
666
|
+
deltas.push({ type: "tool_call_delta", toolCalls, raw });
|
|
667
|
+
}
|
|
668
|
+
const finishReason = stringValue(choiceRecord.finish_reason);
|
|
669
|
+
if (finishReason)
|
|
670
|
+
deltas.push({ type: "finish", finishReason, raw });
|
|
671
|
+
}
|
|
672
|
+
return deltas;
|
|
673
|
+
}
|
|
674
|
+
function parseToolCalls(value) {
|
|
675
|
+
return Array.isArray(value) ? value.filter((item) => Boolean(item) && typeof item === "object") : [];
|
|
676
|
+
}
|
|
677
|
+
function parseUsage(raw) {
|
|
678
|
+
if (!raw || typeof raw !== "object")
|
|
679
|
+
return null;
|
|
680
|
+
const usage = raw.usage;
|
|
681
|
+
if (!usage || typeof usage !== "object")
|
|
682
|
+
return null;
|
|
683
|
+
return usage;
|
|
684
|
+
}
|
|
685
|
+
function stringValue(value) {
|
|
686
|
+
return typeof value === "string" && value.trim() ? value : null;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// ../../packages/runtime/dist/version.js
|
|
690
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
691
|
+
var bundledRuntimeVersion;
|
|
692
|
+
function getBundledRuntimeVersion() {
|
|
693
|
+
if (bundledRuntimeVersion !== void 0)
|
|
694
|
+
return bundledRuntimeVersion ?? "openpond-code bundled";
|
|
695
|
+
try {
|
|
696
|
+
const packageJsonUrl = new URL("../package.json", import.meta.resolve("openpond"));
|
|
697
|
+
const packageJson = JSON.parse(readFileSync2(packageJsonUrl, "utf8"));
|
|
698
|
+
bundledRuntimeVersion = typeof packageJson.version === "string" ? `openpond-code@${packageJson.version}` : null;
|
|
699
|
+
} catch {
|
|
700
|
+
bundledRuntimeVersion = null;
|
|
701
|
+
}
|
|
702
|
+
return bundledRuntimeVersion ?? "openpond-code bundled";
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// ../../packages/runtime/dist/system-browser.js
|
|
706
|
+
import { spawn } from "node:child_process";
|
|
707
|
+
function resolveSystemBrowserCommand(url, platform = process.platform) {
|
|
708
|
+
if (platform === "darwin")
|
|
709
|
+
return { command: "open", args: [url] };
|
|
710
|
+
if (platform === "win32") {
|
|
711
|
+
return {
|
|
712
|
+
command: "rundll32.exe",
|
|
713
|
+
args: ["url.dll,FileProtocolHandler", url]
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
return { command: "xdg-open", args: [url] };
|
|
717
|
+
}
|
|
718
|
+
async function openUrlWithSystemBrowser(url, options = {}) {
|
|
719
|
+
const browser = options.command ?? resolveSystemBrowserCommand(url);
|
|
720
|
+
const handoffTimeoutMs = options.handoffTimeoutMs ?? 1500;
|
|
721
|
+
return new Promise((resolve) => {
|
|
722
|
+
let settled = false;
|
|
723
|
+
let timer = null;
|
|
724
|
+
const finish = (result) => {
|
|
725
|
+
if (settled)
|
|
726
|
+
return;
|
|
727
|
+
settled = true;
|
|
728
|
+
if (timer)
|
|
729
|
+
clearTimeout(timer);
|
|
730
|
+
resolve(result);
|
|
731
|
+
};
|
|
732
|
+
const child = spawn(browser.command, browser.args, {
|
|
733
|
+
detached: false,
|
|
734
|
+
shell: false,
|
|
735
|
+
stdio: "ignore",
|
|
736
|
+
windowsHide: true
|
|
737
|
+
});
|
|
738
|
+
child.once("error", (error) => {
|
|
739
|
+
const code = error.code;
|
|
740
|
+
finish({
|
|
741
|
+
opened: false,
|
|
742
|
+
error: code ? `browser launcher ${browser.command} failed (${code})` : `browser launcher ${browser.command} failed`
|
|
743
|
+
});
|
|
744
|
+
});
|
|
745
|
+
child.once("close", (code, signal) => {
|
|
746
|
+
if (code === 0) {
|
|
747
|
+
finish({ opened: true });
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
const detail = signal ? `signal ${signal}` : `code ${code ?? "unknown"}`;
|
|
751
|
+
finish({ opened: false, error: `browser launcher ${browser.command} exited with ${detail}` });
|
|
752
|
+
});
|
|
753
|
+
timer = setTimeout(() => {
|
|
754
|
+
child.unref();
|
|
755
|
+
finish({ opened: true });
|
|
756
|
+
}, handoffTimeoutMs);
|
|
757
|
+
timer.unref();
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// ../../packages/runtime/dist/apps.js
|
|
762
|
+
function normalizeApp(input) {
|
|
763
|
+
if (!input || typeof input !== "object")
|
|
764
|
+
return null;
|
|
765
|
+
const item = input;
|
|
766
|
+
const id = typeof item.id === "string" ? item.id : null;
|
|
767
|
+
const name = typeof item.name === "string" ? item.name : id;
|
|
768
|
+
if (!id || !name)
|
|
769
|
+
return null;
|
|
770
|
+
const deployment = item.latestDeployment && typeof item.latestDeployment === "object" ? item.latestDeployment : null;
|
|
771
|
+
const registryResult = SandboxAppActionRegistrySchema.safeParse(item.sandboxActionRegistry);
|
|
772
|
+
return {
|
|
773
|
+
id,
|
|
774
|
+
name,
|
|
775
|
+
description: typeof item.description === "string" ? item.description : null,
|
|
776
|
+
visibility: typeof item.visibility === "string" ? item.visibility : null,
|
|
777
|
+
gitOwner: typeof item.gitOwner === "string" ? item.gitOwner : null,
|
|
778
|
+
gitRepo: typeof item.gitRepo === "string" ? item.gitRepo : null,
|
|
779
|
+
gitHost: typeof item.gitHost === "string" ? item.gitHost : null,
|
|
780
|
+
defaultBranch: typeof item.defaultBranch === "string" ? item.defaultBranch : null,
|
|
781
|
+
sandbox: item.sandbox === true,
|
|
782
|
+
sandboxActionRegistry: registryResult.success ? registryResult.data : null,
|
|
783
|
+
sandboxManifestHash: typeof item.sandboxManifestHash === "string" ? item.sandboxManifestHash : null,
|
|
784
|
+
sandboxManifestPath: typeof item.sandboxManifestPath === "string" ? item.sandboxManifestPath : null,
|
|
785
|
+
sandboxManifestSyncedAt: typeof item.sandboxManifestSyncedAt === "string" ? item.sandboxManifestSyncedAt : item.sandboxManifestSyncedAt instanceof Date ? item.sandboxManifestSyncedAt.toISOString() : null,
|
|
786
|
+
sandboxManifestError: typeof item.sandboxManifestError === "string" ? item.sandboxManifestError : null,
|
|
787
|
+
updatedAt: typeof item.updatedAt === "string" ? item.updatedAt : null,
|
|
788
|
+
latestDeployment: deployment ? {
|
|
789
|
+
id: typeof deployment.id === "string" ? deployment.id : void 0,
|
|
790
|
+
status: typeof deployment.status === "string" ? deployment.status : void 0,
|
|
791
|
+
deploymentDomain: typeof deployment.deploymentDomain === "string" ? deployment.deploymentDomain : null,
|
|
792
|
+
createdAt: typeof deployment.createdAt === "string" ? deployment.createdAt : void 0,
|
|
793
|
+
isProduction: typeof deployment.isProduction === "boolean" ? deployment.isProduction : null,
|
|
794
|
+
gitBranch: typeof deployment.gitBranch === "string" ? deployment.gitBranch : null
|
|
795
|
+
} : null,
|
|
796
|
+
scheduleSummary: normalizeScheduleSummary(item.scheduleSummary)
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
function normalizeDateString(value) {
|
|
800
|
+
if (typeof value === "string")
|
|
801
|
+
return value;
|
|
802
|
+
if (value instanceof Date)
|
|
803
|
+
return value.toISOString();
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
function normalizeSchedule(input) {
|
|
807
|
+
if (!input || typeof input !== "object")
|
|
808
|
+
return null;
|
|
809
|
+
const item = input;
|
|
810
|
+
const id = typeof item.id === "string" ? item.id : null;
|
|
811
|
+
const name = typeof item.name === "string" ? item.name : id;
|
|
812
|
+
const deploymentId = typeof item.deploymentId === "string" ? item.deploymentId : null;
|
|
813
|
+
if (!id || !name || !deploymentId)
|
|
814
|
+
return null;
|
|
815
|
+
return {
|
|
816
|
+
id,
|
|
817
|
+
name,
|
|
818
|
+
description: typeof item.description === "string" ? item.description : null,
|
|
819
|
+
scheduleType: typeof item.scheduleType === "string" ? item.scheduleType : "cron",
|
|
820
|
+
scheduleExpression: typeof item.scheduleExpression === "string" ? item.scheduleExpression : "",
|
|
821
|
+
enabled: Boolean(item.enabled),
|
|
822
|
+
rawEnabled: typeof item.rawEnabled === "boolean" ? item.rawEnabled : void 0,
|
|
823
|
+
syncStatus: typeof item.syncStatus === "string" ? item.syncStatus : null,
|
|
824
|
+
syncError: typeof item.syncError === "string" ? item.syncError : null,
|
|
825
|
+
startAt: normalizeDateString(item.startAt),
|
|
826
|
+
endAt: normalizeDateString(item.endAt),
|
|
827
|
+
maxRuns: typeof item.maxRuns === "number" ? item.maxRuns : null,
|
|
828
|
+
executionCount: typeof item.executionCount === "number" ? item.executionCount : null,
|
|
829
|
+
lifecycleStatus: typeof item.lifecycleStatus === "string" ? item.lifecycleStatus : null,
|
|
830
|
+
lifecycleReason: typeof item.lifecycleReason === "string" ? item.lifecycleReason : null,
|
|
831
|
+
lastExecutionAt: normalizeDateString(item.lastExecutionAt),
|
|
832
|
+
lastExecutionStatus: typeof item.lastExecutionStatus === "string" ? item.lastExecutionStatus : null,
|
|
833
|
+
lastRunNowAt: normalizeDateString(item.lastRunNowAt),
|
|
834
|
+
lastRunNowStatus: typeof item.lastRunNowStatus === "string" ? item.lastRunNowStatus : null,
|
|
835
|
+
updatedAt: normalizeDateString(item.updatedAt) ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
836
|
+
deploymentId,
|
|
837
|
+
isProduction: typeof item.isProduction === "boolean" ? item.isProduction : void 0,
|
|
838
|
+
payload: item.payload
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
function normalizeScheduleSummary(input) {
|
|
842
|
+
if (!input || typeof input !== "object")
|
|
843
|
+
return null;
|
|
844
|
+
const item = input;
|
|
845
|
+
const schedules = Array.isArray(item.schedules) ? item.schedules.map(normalizeSchedule).filter((value) => Boolean(value)) : [];
|
|
846
|
+
const total = typeof item.total === "number" ? item.total : schedules.length;
|
|
847
|
+
const active = typeof item.active === "number" ? item.active : schedules.filter((schedule) => schedule.enabled).length;
|
|
848
|
+
const paused = typeof item.paused === "number" ? item.paused : Math.max(0, total - active);
|
|
849
|
+
return {
|
|
850
|
+
total,
|
|
851
|
+
active,
|
|
852
|
+
paused,
|
|
853
|
+
enabled: typeof item.enabled === "number" ? item.enabled : active,
|
|
854
|
+
disabled: typeof item.disabled === "number" ? item.disabled : paused,
|
|
855
|
+
nextRunAt: normalizeDateString(item.nextRunAt),
|
|
856
|
+
lastRunAt: normalizeDateString(item.lastRunAt),
|
|
857
|
+
schedules,
|
|
858
|
+
truncated: typeof item.truncated === "boolean" ? item.truncated : void 0
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
async function loadAccountProfileLookups(context) {
|
|
862
|
+
const accounts = Array.isArray(context.config.accounts) ? context.config.accounts : [];
|
|
863
|
+
const entries = await Promise.all(accounts.map(async (account) => {
|
|
864
|
+
const key = profileKey(account.handle, account.baseUrl);
|
|
865
|
+
const token = accountToken(account);
|
|
866
|
+
if (!token) {
|
|
867
|
+
return [key, { response: null, authFailed: false }];
|
|
868
|
+
}
|
|
869
|
+
try {
|
|
870
|
+
return [
|
|
871
|
+
key,
|
|
872
|
+
{
|
|
873
|
+
response: await getOpenPondAccount(resolvePublicApiBaseUrl(account, context.config), token),
|
|
874
|
+
authFailed: false
|
|
875
|
+
}
|
|
876
|
+
];
|
|
877
|
+
} catch {
|
|
878
|
+
return [key, { response: null, authFailed: true }];
|
|
879
|
+
}
|
|
880
|
+
}));
|
|
881
|
+
return Object.fromEntries(entries);
|
|
882
|
+
}
|
|
883
|
+
async function loadOpenPondApps(options = {}) {
|
|
884
|
+
const context = await loadOpenPondAccountContext();
|
|
885
|
+
if (!context.token) {
|
|
886
|
+
const accountProfiles2 = await loadAccountProfileLookups(context);
|
|
887
|
+
return {
|
|
888
|
+
account: toAccountState({ ...context, accountProfiles: accountProfiles2 }),
|
|
889
|
+
apps: [],
|
|
890
|
+
error: "No OpenPond API key or session token is configured."
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
const [healthResult, accountResult, balanceResult, appsResult, accountProfilesResult] = await Promise.allSettled([
|
|
894
|
+
checkOpenPondApiHealth(context.apiBaseUrl, context.token),
|
|
895
|
+
getOpenPondAccount(context.apiBaseUrl, context.token),
|
|
896
|
+
getOpenPondAccountBalance(context.apiBaseUrl, context.token),
|
|
897
|
+
listApps(context.apiBaseUrl, context.token, {
|
|
898
|
+
handle: context.account?.handle,
|
|
899
|
+
limit: options.limit ?? 20,
|
|
900
|
+
offset: options.offset ?? 0,
|
|
901
|
+
includeScheduled: options.includeScheduled ?? true
|
|
902
|
+
}),
|
|
903
|
+
loadAccountProfileLookups(context)
|
|
904
|
+
]);
|
|
905
|
+
const health = healthResult.status === "fulfilled" ? healthResult.value : null;
|
|
906
|
+
const accountResponse = accountResult.status === "fulfilled" ? accountResult.value : null;
|
|
907
|
+
const balanceResponse = balanceResult.status === "fulfilled" ? balanceResult.value : null;
|
|
908
|
+
const accountProfiles = accountProfilesResult.status === "fulfilled" ? accountProfilesResult.value : {};
|
|
909
|
+
if (accountResult.status === "fulfilled" && context.account) {
|
|
910
|
+
accountProfiles[profileKey(context.account.handle, context.account.baseUrl)] = {
|
|
911
|
+
response: accountResult.value,
|
|
912
|
+
authFailed: false
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
const appsSucceeded = appsResult.status === "fulfilled";
|
|
916
|
+
const accountSucceeded = accountResult.status === "fulfilled";
|
|
917
|
+
const anyAuthenticatedCallSucceeded = appsSucceeded || accountSucceeded || health?.authenticated === true;
|
|
918
|
+
const allAuthenticatedCallsFailed = !appsSucceeded && !accountSucceeded && health?.authenticated !== true;
|
|
919
|
+
const authError = health?.authenticated === false && !anyAuthenticatedCallSucceeded ? health.error || "OpenPond account authentication failed." : allAuthenticatedCallsFailed ? appsResult.status === "rejected" ? errorMessage(appsResult.reason) : accountResult.status === "rejected" ? errorMessage(accountResult.reason) : null : null;
|
|
920
|
+
const profileError = accountResult.status === "rejected" && anyAuthenticatedCallSucceeded ? `Profile unavailable: ${errorMessage(accountResult.reason)}` : null;
|
|
921
|
+
const appsError = appsResult.status === "rejected" ? errorMessage(appsResult.reason) : null;
|
|
922
|
+
const effectiveHealth = health && anyAuthenticatedCallSucceeded ? { ...health, authenticated: true, error: void 0 } : health;
|
|
923
|
+
return {
|
|
924
|
+
account: toAccountState({
|
|
925
|
+
...context,
|
|
926
|
+
accountResponse,
|
|
927
|
+
balanceResponse,
|
|
928
|
+
accountProfiles,
|
|
929
|
+
health: effectiveHealth,
|
|
930
|
+
authFailed: Boolean(authError),
|
|
931
|
+
error: authError ?? profileError,
|
|
932
|
+
balanceError: balanceResult.status === "rejected" ? errorMessage(balanceResult.reason) : null
|
|
933
|
+
}),
|
|
934
|
+
apps: appsResult.status === "fulfilled" ? appsResult.value.map(normalizeApp).filter((value) => Boolean(value)) : [],
|
|
935
|
+
error: appsError
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
async function createOpenPondRepoApp(input) {
|
|
939
|
+
const context = await loadOpenPondAccountContext();
|
|
940
|
+
if (!context.token) {
|
|
941
|
+
throw new Error("No OpenPond API key or session token is configured.");
|
|
942
|
+
}
|
|
943
|
+
return {
|
|
944
|
+
account: context,
|
|
945
|
+
response: await createRepo(context.apiBaseUrl, context.token, input)
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// ../../packages/runtime/dist/save-account.js
|
|
950
|
+
import { createHash } from "node:crypto";
|
|
951
|
+
function fallbackHandleForApiKey(apiKey) {
|
|
952
|
+
const digest = createHash("sha256").update(apiKey).digest("hex").slice(0, 8);
|
|
953
|
+
return `account-${digest}`;
|
|
954
|
+
}
|
|
955
|
+
function normalizeDerivedHandle(value) {
|
|
956
|
+
const trimmed = value?.trim();
|
|
957
|
+
if (!trimmed)
|
|
958
|
+
return null;
|
|
959
|
+
return trimmed.replace(/^@/, "");
|
|
960
|
+
}
|
|
961
|
+
async function deriveHandleForApiKey(input, apiBaseUrl) {
|
|
962
|
+
const explicit = normalizeDerivedHandle(input.handle);
|
|
963
|
+
if (explicit)
|
|
964
|
+
return explicit;
|
|
965
|
+
try {
|
|
966
|
+
const response = await getOpenPondAccount(apiBaseUrl, input.apiKey);
|
|
967
|
+
const account = response.account;
|
|
968
|
+
const fromProfile = normalizeDerivedHandle(account.handle) ?? normalizeDerivedHandle(account.email?.split("@")[0]) ?? normalizeDerivedHandle(account.id);
|
|
969
|
+
if (fromProfile)
|
|
970
|
+
return fromProfile;
|
|
971
|
+
} catch {
|
|
972
|
+
}
|
|
973
|
+
try {
|
|
974
|
+
const apps = await listApps(apiBaseUrl, input.apiKey);
|
|
975
|
+
const counts = /* @__PURE__ */ new Map();
|
|
976
|
+
for (const app of apps) {
|
|
977
|
+
const handle2 = normalizeDerivedHandle(app.handle);
|
|
978
|
+
if (!handle2)
|
|
979
|
+
continue;
|
|
980
|
+
counts.set(handle2, (counts.get(handle2) ?? 0) + 1);
|
|
981
|
+
}
|
|
982
|
+
const [handle] = Array.from(counts.entries()).sort((left, right) => right[1] - left[1])[0] ?? [];
|
|
983
|
+
if (handle)
|
|
984
|
+
return handle;
|
|
985
|
+
} catch {
|
|
986
|
+
}
|
|
987
|
+
return fallbackHandleForApiKey(input.apiKey);
|
|
988
|
+
}
|
|
989
|
+
async function saveOpenPondAccount(input) {
|
|
990
|
+
const baseUrl = input.baseUrl ?? DEFAULT_OPENPOND_WEB_BASE_URL;
|
|
991
|
+
const apiBaseUrl = normalizeBaseUrl(input.apiBaseUrl) ?? mapUiBaseToApiBase(baseUrl) ?? DEFAULT_OPENPOND_API_BASE_URL;
|
|
992
|
+
const chatApiBaseUrl = normalizeBaseUrl(input.chatApiBaseUrl);
|
|
993
|
+
const handle = await deriveHandleForApiKey(input, apiBaseUrl);
|
|
994
|
+
await saveProfileApiKey({
|
|
995
|
+
handle,
|
|
996
|
+
apiKey: input.apiKey,
|
|
997
|
+
baseUrl,
|
|
998
|
+
apiBaseUrl,
|
|
999
|
+
chatApiBaseUrl,
|
|
1000
|
+
environment: input.environment ?? "production",
|
|
1001
|
+
setActive: input.setActive
|
|
1002
|
+
});
|
|
1003
|
+
return loadOpenPondAccountContext(handle, baseUrl);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
// ../../packages/runtime/dist/update-account-config.js
|
|
1007
|
+
function findAccountIndex(accounts, handle, currentBaseUrl) {
|
|
1008
|
+
const normalizedCurrentBaseUrl = normalizeBaseUrl(currentBaseUrl);
|
|
1009
|
+
const exactIndex = accounts.findIndex((account) => handleEquals(account.handle, handle) && baseUrlEquals(account.baseUrl, normalizedCurrentBaseUrl));
|
|
1010
|
+
if (exactIndex !== -1)
|
|
1011
|
+
return exactIndex;
|
|
1012
|
+
const sameHandle = accounts.map((account, index) => ({ account, index })).filter(({ account }) => handleEquals(account.handle, handle));
|
|
1013
|
+
if (sameHandle.length === 1)
|
|
1014
|
+
return sameHandle[0].index;
|
|
1015
|
+
if (sameHandle.length > 1) {
|
|
1016
|
+
throw new Error(`Multiple OpenPond accounts match ${handle}; select one with its current base URL.`);
|
|
1017
|
+
}
|
|
1018
|
+
return -1;
|
|
1019
|
+
}
|
|
1020
|
+
function applyOptionalUrl(account, key, value) {
|
|
1021
|
+
if (value === void 0)
|
|
1022
|
+
return;
|
|
1023
|
+
const normalized = normalizeBaseUrl(value);
|
|
1024
|
+
if (normalized) {
|
|
1025
|
+
account[key] = normalized;
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
if (value === null || value.trim() === "")
|
|
1029
|
+
delete account[key];
|
|
1030
|
+
}
|
|
1031
|
+
async function updateOpenPondAccountConfig(input) {
|
|
1032
|
+
const handle = input.handle.trim();
|
|
1033
|
+
if (!handle)
|
|
1034
|
+
throw new Error("OpenPond account handle is required.");
|
|
1035
|
+
const config = await loadGlobalConfig();
|
|
1036
|
+
const accounts = (config.accounts ?? []).map((account) => ({ ...account }));
|
|
1037
|
+
const index = findAccountIndex(accounts, handle, input.currentBaseUrl);
|
|
1038
|
+
if (index === -1)
|
|
1039
|
+
throw new Error(`OpenPond account not found: ${handle}`);
|
|
1040
|
+
const previousAccount = accounts[index];
|
|
1041
|
+
const nextAccount = { ...previousAccount };
|
|
1042
|
+
applyOptionalUrl(nextAccount, "baseUrl", input.baseUrl);
|
|
1043
|
+
applyOptionalUrl(nextAccount, "apiBaseUrl", input.apiBaseUrl);
|
|
1044
|
+
applyOptionalUrl(nextAccount, "chatApiBaseUrl", input.chatApiBaseUrl);
|
|
1045
|
+
if (input.environment === null) {
|
|
1046
|
+
delete nextAccount.environment;
|
|
1047
|
+
} else if (typeof input.environment === "string" && input.environment.trim()) {
|
|
1048
|
+
nextAccount.environment = input.environment.trim();
|
|
1049
|
+
}
|
|
1050
|
+
const duplicateIndex = accounts.findIndex((account, candidateIndex) => candidateIndex !== index && handleEquals(account.handle, nextAccount.handle) && baseUrlEquals(account.baseUrl, nextAccount.baseUrl));
|
|
1051
|
+
if (duplicateIndex !== -1) {
|
|
1052
|
+
throw new Error("Another OpenPond account already uses that handle and base URL.");
|
|
1053
|
+
}
|
|
1054
|
+
const activeProfile = normalizeActiveProfile(config.activeProfile);
|
|
1055
|
+
const wasActive = Boolean(activeProfile && accountMatchesSelector(previousAccount, activeProfile));
|
|
1056
|
+
accounts[index] = nextAccount;
|
|
1057
|
+
await saveConfig({
|
|
1058
|
+
...config,
|
|
1059
|
+
accounts,
|
|
1060
|
+
activeProfile: input.setActive || wasActive ? selectorFromAccount(nextAccount) : config.activeProfile
|
|
1061
|
+
});
|
|
1062
|
+
return loadOpenPondAccountContext(nextAccount.handle, nextAccount.baseUrl);
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// ../../packages/runtime/dist/actions.js
|
|
1066
|
+
async function getOpenPondAppEnvironment(input) {
|
|
1067
|
+
const context = await loadOpenPondAccountContext();
|
|
1068
|
+
if (!context.token) {
|
|
1069
|
+
throw new Error("OpenPond is signed out. Add an account before reading app config.");
|
|
1070
|
+
}
|
|
1071
|
+
return getAppEnvironment(context.apiBaseUrl, context.token, input.appId);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// ../../packages/runtime/dist/ready-line-parser.js
|
|
1075
|
+
function createReadyLineParser(prefix, onReady) {
|
|
1076
|
+
let buffer = "";
|
|
1077
|
+
const processLine = (line) => {
|
|
1078
|
+
if (!line.startsWith(prefix))
|
|
1079
|
+
return;
|
|
1080
|
+
onReady(JSON.parse(line.slice(prefix.length)));
|
|
1081
|
+
};
|
|
1082
|
+
return {
|
|
1083
|
+
push(chunk) {
|
|
1084
|
+
buffer += chunk;
|
|
1085
|
+
while (true) {
|
|
1086
|
+
const lineEnd = nextLineEnd(buffer);
|
|
1087
|
+
if (lineEnd < 0)
|
|
1088
|
+
return;
|
|
1089
|
+
const line = buffer.slice(0, lineEnd).replace(/\r$/, "");
|
|
1090
|
+
const newlineLength = buffer[lineEnd] === "\r" && buffer[lineEnd + 1] === "\n" ? 2 : 1;
|
|
1091
|
+
buffer = buffer.slice(lineEnd + newlineLength);
|
|
1092
|
+
processLine(line);
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
1095
|
+
flush() {
|
|
1096
|
+
const line = buffer.trimEnd();
|
|
1097
|
+
buffer = "";
|
|
1098
|
+
if (line)
|
|
1099
|
+
processLine(line);
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
function nextLineEnd(value) {
|
|
1104
|
+
const lf = value.indexOf("\n");
|
|
1105
|
+
const cr = value.indexOf("\r");
|
|
1106
|
+
if (lf < 0)
|
|
1107
|
+
return cr;
|
|
1108
|
+
if (cr < 0)
|
|
1109
|
+
return lf;
|
|
1110
|
+
return Math.min(lf, cr);
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
export {
|
|
1114
|
+
loadOpenPondAccountContext,
|
|
1115
|
+
switchOpenPondAccount,
|
|
1116
|
+
loadOpenPondApps,
|
|
1117
|
+
createOpenPondRepoApp,
|
|
1118
|
+
loadOpenPondProviderCatalog,
|
|
1119
|
+
streamOpenPondHostedChatTurn,
|
|
1120
|
+
saveOpenPondAccount,
|
|
1121
|
+
updateOpenPondAccountConfig,
|
|
1122
|
+
getOpenPondAppEnvironment,
|
|
1123
|
+
getBundledRuntimeVersion,
|
|
1124
|
+
createReadyLineParser,
|
|
1125
|
+
openUrlWithSystemBrowser
|
|
1126
|
+
};
|