@shawnstack/quickforge 1.7.5 → 1.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/AgentProfilesPage-Dl5Peqov.js +1 -0
- package/dist/assets/ChatPanelHost-D3987TUJ.js +307 -0
- package/dist/assets/CloudAccountSettingsPage-BG5Nn3bq.js +1 -0
- package/dist/assets/PluginsPage-BDKYfLna.js +1 -0
- package/dist/assets/ScheduledTasksPage--GAki3lB.js +2 -0
- package/dist/assets/SettingsWorkspacePage-DSy66Tuw.js +1696 -0
- package/dist/assets/ShareLinksSettingsPage-BQQMsvJo.js +1 -0
- package/dist/assets/SharedConversationPage-B9BUVCri.js +1 -0
- package/dist/assets/TerminalDock-CT1nYo7P.js +2 -0
- package/dist/assets/{WorkspaceInspector-D9kdnLDd.js → WorkspaceInspector-BnfDLf9a.js} +5 -5
- package/dist/assets/{dist-DLKC_odd.js → dist-yDHbi5ux.js} +1 -1
- package/dist/assets/{esm-Df4edDpj.js → esm-sdsK6gaB.js} +2 -2
- package/dist/assets/{icons-CXPP1fFT.js → icons-2D18YbSI.js} +1 -1
- package/dist/assets/index-1ei6nhs-.css +3 -0
- package/dist/assets/index-BivLuZvX.js +65 -0
- package/dist/assets/{mcp-servers-dialog-BUSPvaqI.js → mcp-servers-dialog-BEV4_TXC.js} +2 -2
- package/dist/assets/{logger-8REuLPGK.js → model-display-label-C6-0eDxF.js} +1 -1
- package/dist/assets/{monaco-D6OhXgjg.js → monaco-DvXErxp2.js} +1 -1
- package/dist/assets/{react-vendor-1KC5PyRx.js → react-vendor-3UaA-C9W.js} +1 -1
- package/dist/assets/{skills-dialog-BThnIUBs.js → skills-dialog-BTJ7mzk_.js} +3 -3
- package/dist/assets/{web-DoV8MSMn.js → web-B5qgZJRv.js} +1 -1
- package/dist/index.html +8 -8
- package/dist/sw.js +17 -0
- package/package.json +2 -1
- package/runtime-assets/agent/darwin-arm64/qf-agent +0 -0
- package/runtime-assets/agent/darwin-x64/qf-agent +0 -0
- package/runtime-assets/agent/linux-arm64/qf-agent +0 -0
- package/runtime-assets/agent/linux-x64/qf-agent +0 -0
- package/runtime-assets/agent/win32-x64/qf-agent.exe +0 -0
- package/server/access-policy.mjs +11 -0
- package/server/agent-manager.mjs +349 -48
- package/server/agent-profiles.mjs +27 -8
- package/server/auto-compaction.mjs +35 -8
- package/server/cloud/client.mjs +4 -7
- package/server/cloud/config.mjs +6 -5
- package/server/cloud/credential-store.mjs +10 -3
- package/server/cloud/identity.mjs +17 -60
- package/server/cloud/models.mjs +1 -1
- package/server/cloud/qf-agent-process.mjs +571 -0
- package/server/cloud/runtime.mjs +11 -5
- package/server/cloud/service-config.mjs +8 -4
- package/server/index.mjs +96 -37
- package/server/mcp/registry.mjs +8 -7
- package/server/message-converters.mjs +40 -19
- package/server/model-catalog.mjs +11 -4
- package/server/opencode-acp-agent.mjs +1151 -0
- package/server/public-api.mjs +11 -5
- package/server/routes/agent-profiles.mjs +6 -3
- package/server/routes/agent.mjs +43 -3
- package/server/routes/backup.mjs +5 -4
- package/server/routes/cloud.mjs +54 -35
- package/server/routes/shares.mjs +7 -8
- package/server/routes/storage.mjs +9 -24
- package/server/routes/system.mjs +7 -4
- package/server/utils/process-tree.mjs +78 -0
- package/dist/assets/AgentProfilesPage-XNjuqJs7.js +0 -1
- package/dist/assets/ChatPanelHost-CuF-PZpc.js +0 -292
- package/dist/assets/CloudAccountSettingsPage-GJSoi6sO.js +0 -1
- package/dist/assets/PluginsPage-BQgp0qN-.js +0 -1
- package/dist/assets/ScheduledTasksPage-DdekATzq.js +0 -2
- package/dist/assets/SettingsWorkspacePage-Cb54Ic91.js +0 -1639
- package/dist/assets/ShareLinksSettingsPage-C75WJpaF.js +0 -1
- package/dist/assets/SharedConversationPage-CjMtSQTW.js +0 -1
- package/dist/assets/TerminalDock-D4zJBJc4.js +0 -2
- package/dist/assets/index-_ZhK6bvp.js +0 -65
- package/dist/assets/index-iVV2bP_f.css +0 -3
|
@@ -75,7 +75,7 @@ function builtinProfileFromSubagent(definition, override = null) {
|
|
|
75
75
|
allowedTools: [...definition.allowedTools],
|
|
76
76
|
capabilityPolicy: definition.capabilityPolicy || inferCapabilityPolicy(definition.allowedTools),
|
|
77
77
|
model: modelReferenceSnapshot(override?.model || definition.model),
|
|
78
|
-
thinkingLevel: 'inherit',
|
|
78
|
+
thinkingLevel: normalizeAgentProfileThinkingLevel(override?.thinkingLevel || 'inherit'),
|
|
79
79
|
lifecycle: 'builtin',
|
|
80
80
|
managed: true,
|
|
81
81
|
maxRuntimeMs: definition.maxRuntimeMs || DEFAULT_MAX_RUNTIME_MS,
|
|
@@ -308,17 +308,36 @@ export async function updateCustomAgentProfile(id, patch) {
|
|
|
308
308
|
return { ...next, filePath: file, relativePath: `~/.quickforge/agents/${next.name}.md` }
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
-
export async function
|
|
311
|
+
export async function updateBuiltinAgentOverrides(id, patch = {}) {
|
|
312
312
|
const current = await getAgentProfile(id)
|
|
313
313
|
if (!current) throw requestError('Agent not found', 404)
|
|
314
|
-
if (!current.builtin) throw requestError('Only built-in agents support
|
|
315
|
-
const model = validateModelReference(normalizeModelReference(modelInput))
|
|
314
|
+
if (!current.builtin) throw requestError('Only built-in agents support overrides', 400)
|
|
316
315
|
const overrides = await readStore(BUILTIN_OVERRIDES_STORE).catch(() => ({}))
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
316
|
+
const base = overrides && typeof overrides === 'object' ? overrides : {}
|
|
317
|
+
const next = { ...base }
|
|
318
|
+
const entry = { ...(base[current.name] && typeof base[current.name] === 'object' ? base[current.name] : {}) }
|
|
319
|
+
|
|
320
|
+
if (Object.prototype.hasOwnProperty.call(patch, 'model')) {
|
|
321
|
+
const model = validateModelReference(normalizeModelReference(patch.model))
|
|
322
|
+
if (model.mode === 'fixed') entry.model = model
|
|
323
|
+
else delete entry.model
|
|
324
|
+
}
|
|
325
|
+
if (Object.prototype.hasOwnProperty.call(patch, 'thinkingLevel')) {
|
|
326
|
+
const thinkingLevel = normalizeAgentProfileThinkingLevel(patch.thinkingLevel)
|
|
327
|
+
if (thinkingLevel === 'inherit') delete entry.thinkingLevel
|
|
328
|
+
else entry.thinkingLevel = thinkingLevel
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (Object.keys(entry).length === 0) delete next[current.name]
|
|
332
|
+
else next[current.name] = entry
|
|
320
333
|
await writeStore(BUILTIN_OVERRIDES_STORE, next)
|
|
321
|
-
|
|
334
|
+
|
|
335
|
+
const definition = subagentDefinitions.find((item) => item.name === current.name)
|
|
336
|
+
return builtinProfileFromSubagent(definition, next[current.name] || null)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export async function updateBuiltinAgentModelOverride(id, modelInput) {
|
|
340
|
+
return updateBuiltinAgentOverrides(id, { model: modelInput })
|
|
322
341
|
}
|
|
323
342
|
|
|
324
343
|
export async function deleteCustomAgentProfile(id) {
|
|
@@ -18,6 +18,14 @@ export const DEFAULT_AUTO_COMPACT_SETTINGS = {
|
|
|
18
18
|
requireConfirmation: true,
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* 保留尾部(最近回合)的字符预算上限。当会话以工具消息为主、user 回合
|
|
23
|
+
* 稀疏时,按 keepRecentTurns 从尾部回溯会跨越大量工具消息,导致压缩
|
|
24
|
+
* 范围过小甚至为空(tailStart 与 compactedUpToIndex 重合)。达到该预算
|
|
25
|
+
* 时按当前用户轮次起点截断,将更早的完整工具链历史并入压缩范围。
|
|
26
|
+
*/
|
|
27
|
+
export const DEFAULT_MAX_TAIL_CHARS = 40000
|
|
28
|
+
|
|
21
29
|
const AUTO_COMPACT_MIN_INTERVAL_MS = 30_000
|
|
22
30
|
const AUTO_COMPACT_REJECTION_SUPPRESS_MS = 10 * 60_000
|
|
23
31
|
|
|
@@ -64,11 +72,13 @@ function contentToText(content) {
|
|
|
64
72
|
}).filter(Boolean).join('\n')
|
|
65
73
|
}
|
|
66
74
|
|
|
75
|
+
function messageChars(message) {
|
|
76
|
+
if (!message || typeof message !== 'object') return 0
|
|
77
|
+
return [message.role || '', contentToText(message.content), safeJson(message.attachments)].join('\n').length
|
|
78
|
+
}
|
|
79
|
+
|
|
67
80
|
function estimateMessagesChars(messages) {
|
|
68
|
-
return (Array.isArray(messages) ? messages : []).reduce((total, message) =>
|
|
69
|
-
if (!message || typeof message !== 'object') return total
|
|
70
|
-
return total + [message.role || '', contentToText(message.content), safeJson(message.attachments)].join('\n').length
|
|
71
|
-
}, 0)
|
|
81
|
+
return (Array.isArray(messages) ? messages : []).reduce((total, message) => total + messageChars(message), 0)
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
function isUserMessage(message) {
|
|
@@ -76,13 +86,26 @@ function isUserMessage(message) {
|
|
|
76
86
|
&& !isCompactSummaryMessage(message)
|
|
77
87
|
}
|
|
78
88
|
|
|
79
|
-
function
|
|
89
|
+
function isToolResultMessage(message) {
|
|
90
|
+
return message?.role === 'toolResult'
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function tailStartForRecentTurns(messages, keepRecentTurns, maxTailChars = DEFAULT_MAX_TAIL_CHARS) {
|
|
80
94
|
const source = Array.isArray(messages) ? messages : []
|
|
81
95
|
let seenUserTurns = 0
|
|
96
|
+
let tailChars = 0
|
|
82
97
|
for (let index = source.length - 1; index >= 0; index--) {
|
|
83
|
-
if (
|
|
84
|
-
|
|
98
|
+
if (isUserMessage(source[index])) seenUserTurns += 1
|
|
99
|
+
tailChars += messageChars(source[index])
|
|
85
100
|
if (seenUserTurns >= keepRecentTurns) return index
|
|
101
|
+
// 保留的尾部超过预算:仍按完整用户轮次切分,避免把当前运行中的
|
|
102
|
+
// assistant/toolResult 链从中间截断,导致压缩线落在一轮对话内部。
|
|
103
|
+
if (tailChars >= maxTailChars) {
|
|
104
|
+
for (let turnStart = index; turnStart >= 0; turnStart--) {
|
|
105
|
+
if (isUserMessage(source[turnStart])) return turnStart
|
|
106
|
+
}
|
|
107
|
+
return 0
|
|
108
|
+
}
|
|
86
109
|
}
|
|
87
110
|
return 0
|
|
88
111
|
}
|
|
@@ -145,7 +168,11 @@ export function buildAutoCompactLoopMessages(session, messages) {
|
|
|
145
168
|
if (!summaryMessage) return messages
|
|
146
169
|
const source = Array.isArray(messages) ? messages : []
|
|
147
170
|
const compactedUpToIndex = Math.min(source.length, Math.max(0, Number(session.contextCompaction?.compactedUpToIndex) || 0))
|
|
148
|
-
|
|
171
|
+
// 防御旧持久化数据:compactedUpToIndex 可能指向 toolResult,跳过开头的孤儿,
|
|
172
|
+
// 避免压缩后的消息序列以 tool 消息开头(LLM API 会拒绝孤立 tool 消息)
|
|
173
|
+
let tailStart = compactedUpToIndex
|
|
174
|
+
while (tailStart < source.length && isToolResultMessage(source[tailStart])) tailStart += 1
|
|
175
|
+
return [summaryMessage, ...source.slice(tailStart)]
|
|
149
176
|
}
|
|
150
177
|
|
|
151
178
|
export async function compactSessionInPlace({
|
package/server/cloud/client.mjs
CHANGED
|
@@ -60,19 +60,16 @@ export class CloudClient {
|
|
|
60
60
|
|
|
61
61
|
health(signal) { return this.request('healthz', { signal }) }
|
|
62
62
|
ready(signal) { return this.request('readyz', { signal }) }
|
|
63
|
-
registerGuest(input, idempotencyKey, signal) {
|
|
64
|
-
return this.request('v1/guest/installations', {
|
|
65
|
-
method: 'POST', body: input, headers: { 'Idempotency-Key': idempotencyKey }, signal,
|
|
66
|
-
})
|
|
67
|
-
}
|
|
68
63
|
refresh(refreshToken, signal) {
|
|
69
64
|
return this.request('oauth/token', {
|
|
70
65
|
method: 'POST', body: { grantType: 'refresh_token', refreshToken }, signal,
|
|
71
66
|
})
|
|
72
67
|
}
|
|
73
|
-
authorizeDevice(
|
|
68
|
+
authorizeDevice({ installationId, clientId = 'quickforge-desktop', publicKey, installationName, platform, clientVersion, signal } = {}) {
|
|
74
69
|
return this.request('oauth/device_authorization', {
|
|
75
|
-
method: 'POST',
|
|
70
|
+
method: 'POST',
|
|
71
|
+
body: { installationId, clientId, publicKey, installationName, platform, clientVersion },
|
|
72
|
+
signal,
|
|
76
73
|
})
|
|
77
74
|
}
|
|
78
75
|
exchangeDeviceCode(deviceCode, clientId = 'quickforge-desktop', signal) {
|
package/server/cloud/config.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import net from 'node:net'
|
|
|
3
3
|
const DEFAULT_TIMEOUT_MS = 10_000
|
|
4
4
|
|
|
5
5
|
function isLoopbackHost(hostname) {
|
|
6
|
-
const host = String(hostname || '').toLowerCase()
|
|
6
|
+
const host = String(hostname || '').toLowerCase().replace(/^\[|\]$/g, '')
|
|
7
7
|
if (host === 'localhost' || host.endsWith('.localhost')) return true
|
|
8
8
|
const ip = net.isIP(host)
|
|
9
9
|
if (ip === 4) return host.startsWith('127.')
|
|
@@ -25,10 +25,11 @@ export function parseCloudBaseUrl(value, _options = {}) {
|
|
|
25
25
|
if (url.username || url.password || url.search || url.hash) {
|
|
26
26
|
throw new Error('QUICKFORGE_CLOUD_URL must not contain credentials, query parameters, or fragments.')
|
|
27
27
|
}
|
|
28
|
-
if (url.protocol !== 'https:') {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
if (url.protocol !== 'https:' && url.protocol !== 'http:') {
|
|
29
|
+
throw new Error('QUICKFORGE_CLOUD_URL must use http or https.')
|
|
30
|
+
}
|
|
31
|
+
if (url.protocol === 'http:' && !isLoopbackHost(url.hostname)) {
|
|
32
|
+
throw new Error('QUICKFORGE_CLOUD_URL over HTTP is only allowed for loopback hosts.')
|
|
32
33
|
}
|
|
33
34
|
if (url.pathname.includes('..')) throw new Error('QUICKFORGE_CLOUD_URL contains an unsafe path.')
|
|
34
35
|
url.pathname = `${url.pathname.replace(/\/+$/, '')}/`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { generateKeyPair } from 'node:crypto'
|
|
1
|
+
import { generateKeyPair, randomUUID } from 'node:crypto'
|
|
2
2
|
import { promises as fs } from 'node:fs'
|
|
3
3
|
import os from 'node:os'
|
|
4
4
|
import path from 'node:path'
|
|
@@ -145,8 +145,15 @@ export function createCloudCredentialStore({
|
|
|
145
145
|
|
|
146
146
|
async function ensureInstallation() {
|
|
147
147
|
const current = await read()
|
|
148
|
-
if (current.publicKey && current.privateKeyPkcs8) return current
|
|
149
|
-
return update(async (record) =>
|
|
148
|
+
if (current.publicKey && current.privateKeyPkcs8 && current.installationId) return current
|
|
149
|
+
return update(async (record) => {
|
|
150
|
+
const keyPair = (record.publicKey && record.privateKeyPkcs8) ? {} : await generateInstallationKeyPair()
|
|
151
|
+
return {
|
|
152
|
+
...record,
|
|
153
|
+
...keyPair,
|
|
154
|
+
installationId: record.installationId || randomUUID(),
|
|
155
|
+
}
|
|
156
|
+
})
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
async function rotateInstallation() {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CloudApiError } from './client.mjs'
|
|
1
|
+
import { CloudApiError } from './client.mjs'
|
|
3
2
|
|
|
4
3
|
const SESSION_INVALID_CODES = new Set(['refresh_token_reused', 'installation_revoked', 'invalid_refresh_token'])
|
|
5
4
|
const DEVICE_PENDING_CODES = new Set(['authorization_pending', 'pending'])
|
|
@@ -11,7 +10,6 @@ const DEVICE_NETWORK_CAUSE_CODES = new Set(['ECONNREFUSED', 'ECONNRESET', 'ENETD
|
|
|
11
10
|
const DEVICE_CLIENT_ID = 'quickforge-desktop'
|
|
12
11
|
const MODEL_CACHE_TTL_MS = 60_000
|
|
13
12
|
const MODEL_CACHE_HARD_TTL_MS = 5 * 60_000
|
|
14
|
-
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
15
13
|
|
|
16
14
|
function tokenExpiry(expiresIn) {
|
|
17
15
|
const seconds = Number(expiresIn)
|
|
@@ -38,15 +36,6 @@ function isDeviceFlowNetworkError(error) {
|
|
|
38
36
|
return error instanceof TypeError || DEVICE_NETWORK_CAUSE_CODES.has(causeCode)
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
function registrationHash(record, serviceUrl) {
|
|
42
|
-
return createHash('sha256').update(JSON.stringify({
|
|
43
|
-
installationName: record.installationName,
|
|
44
|
-
platform: record.platform,
|
|
45
|
-
clientVersion: record.clientVersion,
|
|
46
|
-
publicKey: record.publicKey,
|
|
47
|
-
serviceUrl,
|
|
48
|
-
})).digest('base64url')
|
|
49
|
-
}
|
|
50
39
|
|
|
51
40
|
export class CloudIdentityManager {
|
|
52
41
|
constructor({ client, store, serviceUrl } = {}) {
|
|
@@ -92,45 +81,6 @@ export class CloudIdentityManager {
|
|
|
92
81
|
}
|
|
93
82
|
}
|
|
94
83
|
|
|
95
|
-
async startGuest({ signal } = {}) {
|
|
96
|
-
let record = await this.store.read()
|
|
97
|
-
this.assertSessionService(record)
|
|
98
|
-
if (record.rotateInstallationBeforeRegistration) {
|
|
99
|
-
record = await this.store.rotateInstallation()
|
|
100
|
-
} else {
|
|
101
|
-
record = await this.store.ensureInstallation()
|
|
102
|
-
}
|
|
103
|
-
const requestHash = registrationHash(record, this.serviceUrl)
|
|
104
|
-
let idempotencyKey = record.pendingRegistrationKey
|
|
105
|
-
if (!UUID_PATTERN.test(idempotencyKey || '') || record.pendingRegistrationHash !== requestHash) {
|
|
106
|
-
idempotencyKey = randomUUID()
|
|
107
|
-
await this.store.update((current) => ({
|
|
108
|
-
...current,
|
|
109
|
-
pendingRegistrationKey: idempotencyKey,
|
|
110
|
-
pendingRegistrationHash: requestHash,
|
|
111
|
-
}))
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const tokens = await this.client.registerGuest({
|
|
115
|
-
installationName: record.installationName,
|
|
116
|
-
platform: record.platform,
|
|
117
|
-
clientVersion: record.clientVersion,
|
|
118
|
-
publicKey: record.publicKey,
|
|
119
|
-
}, idempotencyKey, signal)
|
|
120
|
-
|
|
121
|
-
this.setAccess(tokens)
|
|
122
|
-
await this.store.update((current) => ({
|
|
123
|
-
...current,
|
|
124
|
-
mode: tokens.identityMode || 'guest',
|
|
125
|
-
installationId: tokens.installationId,
|
|
126
|
-
refreshToken: tokens.refreshToken,
|
|
127
|
-
sessionCloudUrl: this.serviceUrl,
|
|
128
|
-
pendingRegistrationKey: undefined,
|
|
129
|
-
pendingRegistrationHash: undefined,
|
|
130
|
-
pendingDeviceFlow: undefined,
|
|
131
|
-
}))
|
|
132
|
-
return this.getStatusWithRemoteSummary(signal)
|
|
133
|
-
}
|
|
134
84
|
|
|
135
85
|
async startDeviceFlow({ signal } = {}) {
|
|
136
86
|
let record = await this.store.read()
|
|
@@ -138,16 +88,23 @@ export class CloudIdentityManager {
|
|
|
138
88
|
if (record.mode === 'account' && record.refreshToken) {
|
|
139
89
|
throw new CloudApiError('QuickForge Cloud is already connected to an account.', { status: 409, code: 'cloud_account_already_connected' })
|
|
140
90
|
}
|
|
141
|
-
if (record.
|
|
142
|
-
await this.
|
|
143
|
-
record = await this.store.read()
|
|
91
|
+
if (record.rotateInstallationBeforeRegistration) {
|
|
92
|
+
record = await this.store.rotateInstallation()
|
|
144
93
|
}
|
|
145
|
-
|
|
146
|
-
|
|
94
|
+
record = await this.store.ensureInstallation()
|
|
95
|
+
if (!record.installationId || !record.publicKey) {
|
|
96
|
+
throw new CloudApiError('QuickForge Cloud installation identity is incomplete.', { status: 409, code: 'cloud_installation_missing' })
|
|
147
97
|
}
|
|
148
98
|
this.assertSessionService(record)
|
|
149
|
-
const
|
|
150
|
-
|
|
99
|
+
const authorization = await this.client.authorizeDevice({
|
|
100
|
+
installationId: record.installationId,
|
|
101
|
+
clientId: DEVICE_CLIENT_ID,
|
|
102
|
+
publicKey: record.publicKey,
|
|
103
|
+
installationName: record.installationName,
|
|
104
|
+
platform: record.platform,
|
|
105
|
+
clientVersion: record.clientVersion,
|
|
106
|
+
signal,
|
|
107
|
+
})
|
|
151
108
|
const expiresIn = Math.max(1, Number(authorization?.expiresIn) || 600)
|
|
152
109
|
const interval = Math.max(1, Number(authorization?.interval) || 5)
|
|
153
110
|
const pendingDeviceFlow = {
|
|
@@ -270,7 +227,7 @@ export class CloudIdentityManager {
|
|
|
270
227
|
this.setAccess(tokens)
|
|
271
228
|
await this.store.update((current) => ({
|
|
272
229
|
...current,
|
|
273
|
-
mode: tokens.identityMode || current.mode || '
|
|
230
|
+
mode: tokens.identityMode || current.mode || 'account',
|
|
274
231
|
installationId: tokens.installationId || current.installationId,
|
|
275
232
|
refreshToken: tokens.refreshToken,
|
|
276
233
|
sessionCloudUrl: this.serviceUrl,
|
|
@@ -338,7 +295,7 @@ export class CloudIdentityManager {
|
|
|
338
295
|
if (this.modelsPromise) return this.modelsPromise
|
|
339
296
|
this.modelsPromise = this.withAccessToken((token) => this.client.models(token, signal), { signal })
|
|
340
297
|
.then((response) => {
|
|
341
|
-
this.modelsCache = Array.isArray(response?.items) ? response.items : []
|
|
298
|
+
this.modelsCache = Array.isArray(response?.data) ? response.data : (Array.isArray(response?.items) ? response.items : [])
|
|
342
299
|
this.modelsCachedAt = Date.now()
|
|
343
300
|
return this.modelsCache
|
|
344
301
|
})
|
package/server/cloud/models.mjs
CHANGED
|
@@ -16,7 +16,7 @@ export function toPublicCloudModel(model) {
|
|
|
16
16
|
reasoning: Boolean(capabilities.reasoning),
|
|
17
17
|
input: capabilities.vision ? ['text', 'image'] : ['text'],
|
|
18
18
|
contextWindow: Number(model.contextWindow || 128_000),
|
|
19
|
-
maxTokens: Number(model.maxTokens ||
|
|
19
|
+
maxTokens: Number(model.maxTokens || 32_768),
|
|
20
20
|
quickforgeModelSource: CLOUD_SOURCE,
|
|
21
21
|
quickforgeCatalogId: id,
|
|
22
22
|
quickforgeCapabilities: {
|