mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
refactor(client): use settings Remote namespaces
This commit is contained in:
@@ -141,7 +141,7 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup
|
||||
// Regression pin for the reload flash: both steps are satisfied, yet each
|
||||
// must load private facts before deciding not to show. Dialog chrome lives
|
||||
// inside each visible branch, so the deciding window paints and blocks
|
||||
// nothing. Holding settings.describe widens that window from loopback
|
||||
// nothing. Holding settings/describe widens that window from loopback
|
||||
// RTT scale to a deterministic hundreds of milliseconds, removing all
|
||||
// timing dependence from the sampler assertions below.
|
||||
//
|
||||
@@ -162,7 +162,7 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup
|
||||
if (document.getElementById('root')?.inert === true) sightings.push('inert')
|
||||
}, 8)
|
||||
})
|
||||
// EVERY settings.describe issued before the release is held — not just
|
||||
// EVERY settings/describe issued before the release is held — not just
|
||||
// the first — so the pin cannot silently collapse back to loopback
|
||||
// timing if a second boot-time consumer of the join ever appears.
|
||||
let released = false
|
||||
@@ -171,7 +171,7 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup
|
||||
released = true
|
||||
for (const resolve of heldRoutes.splice(0)) resolve()
|
||||
}
|
||||
await page.route('**/api/settings.describe', async (route) => {
|
||||
await page.route('**/api/settings/describe', async (route) => {
|
||||
if (!released) await new Promise<void>((resolve) => { heldRoutes.push(resolve) })
|
||||
await route.continue()
|
||||
})
|
||||
@@ -182,7 +182,7 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup
|
||||
await page.waitForTimeout(600)
|
||||
releaseDescribe()
|
||||
await page.waitForTimeout(400)
|
||||
await page.unroute('**/api/settings.describe')
|
||||
await page.unroute('**/api/settings/describe')
|
||||
acknowledgeReloadConnectionLoss(tripwire, warningsBefore)
|
||||
expect(await page.evaluate(() =>
|
||||
(window as unknown as { __takeoverSightings: string[] }).__takeoverSightings)).toEqual([])
|
||||
|
||||
@@ -317,17 +317,6 @@ async function bootPreview(origin: string, browser: Browser): Promise<void> {
|
||||
type Result<T> = { result: { ok: true; value: T } | { ok: false; error: { code: string; message: string } } }
|
||||
interface PreviewApi {
|
||||
skills: { list(payload: { sessionId: string }): Promise<Result<{ skills: unknown[] }>> }
|
||||
settings: {
|
||||
describe(payload: object): Promise<Result<{ namespaces: Array<{ ns: string; revision: number }> }>>
|
||||
update(payload: { ns: string; patch: object; expectedRevision: number }): Promise<Result<unknown>>
|
||||
}
|
||||
credentials: {
|
||||
set(payload: { ref: string; value: string }): Promise<Result<unknown>>
|
||||
unset(payload: { ref: string }): Promise<Result<unknown>>
|
||||
describe(payload: { refs: string[] }): Promise<Result<{
|
||||
credentials: Record<string, { configured: boolean }>
|
||||
}>>
|
||||
}
|
||||
}
|
||||
interface PreviewTransport {
|
||||
fetch(input: string, init: RequestInit): Promise<Response>
|
||||
@@ -373,22 +362,44 @@ async function bootPreview(origin: string, browser: Browser): Promise<void> {
|
||||
if (!refreshed.result.ok) throw new Error(`skill.list refresh failed: ${refreshed.result.error.message}`)
|
||||
}
|
||||
await createDirectory('/dsh/workspace/.agents/skills', 'runtime-created')
|
||||
const settings = await api.settings.describe({})
|
||||
if (!settings.result.ok) throw new Error(`settings.describe failed: ${settings.result.error.message}`)
|
||||
const shell = settings.result.value.namespaces.find(namespace => namespace.ns === 'shell')
|
||||
if (shell === undefined) throw new Error('settings.describe omitted the shell namespace')
|
||||
const updated = await api.settings.update({ ns: 'shell', patch: { timeoutMs: 61_000 }, expectedRevision: shell.revision })
|
||||
if (!updated.result.ok) throw new Error(`settings.update failed: ${updated.result.error.message}`)
|
||||
const stored = await api.credentials.set({ ref: 'PREVIEW_TEST_SECRET', value: 'worker-only' })
|
||||
if (!stored.result.ok) throw new Error(`credentials.set failed: ${stored.result.error.message}`)
|
||||
const credentials = await api.credentials.describe({ refs: ['PREVIEW_TEST_SECRET'] })
|
||||
if (!credentials.result.ok) throw new Error(`credentials.describe failed: ${credentials.result.error.message}`)
|
||||
const removed = await api.credentials.unset({ ref: 'PREVIEW_TEST_SECRET' })
|
||||
if (!removed.result.ok) throw new Error(`credentials.unset failed: ${removed.result.error.message}`)
|
||||
// Settings and credentials both answer over the Remote carrier, so this
|
||||
// half of the sweep posts the generated endpoints directly like the
|
||||
// session read above.
|
||||
const remote = async <T>(endpoint: string, args: object): Promise<T> => {
|
||||
const answered = await transport.fetch(`/api/${endpoint}`, {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
type: 'client-request',
|
||||
rpcId: `preview-${endpoint.replace('/', '-')}`,
|
||||
method: endpoint,
|
||||
payload: { args },
|
||||
}),
|
||||
})
|
||||
const body = await answered.json() as Result<T>
|
||||
if (!body.result.ok) throw new Error(`${endpoint} failed: ${body.result.error.message}`)
|
||||
return body.result.value
|
||||
}
|
||||
const settings = await remote<{ namespaces: { ns: string; revision: number }[] }>(
|
||||
'settings/describe', {},
|
||||
)
|
||||
const shell = settings.namespaces.find(namespace => namespace.ns === 'shell')
|
||||
if (shell === undefined) throw new Error('settings/describe omitted the shell namespace')
|
||||
await remote('settings/update', {
|
||||
ns: 'shell',
|
||||
patch: { timeoutMs: 61_000 },
|
||||
expectedRevision: shell.revision,
|
||||
})
|
||||
await remote('credentials/set', { ref: 'PREVIEW_TEST_SECRET', value: 'worker-only' })
|
||||
const credentials = await remote<Record<string, { configured: boolean }>>(
|
||||
'credentials/describe',
|
||||
{ refs: ['PREVIEW_TEST_SECRET'] },
|
||||
)
|
||||
await remote('credentials/unset', { ref: 'PREVIEW_TEST_SECRET' })
|
||||
await new Promise((resolve) => { setTimeout(resolve, 250) })
|
||||
return {
|
||||
skillCount: skills.result.value.skills.length,
|
||||
credentialConfigured: credentials.result.value.credentials.PREVIEW_TEST_SECRET?.configured,
|
||||
credentialConfigured: credentials.PREVIEW_TEST_SECRET?.configured,
|
||||
}
|
||||
})
|
||||
expect(exercised.skillCount).toBeGreaterThan(0)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Cold boot may issue at most two settings.describe calls regardless of client
|
||||
// Cold boot may issue at most two settings/describe calls regardless of client
|
||||
// plugin count. No model call or replay fixture is involved.
|
||||
import type { Browser, Page } from 'playwright'
|
||||
import { chromium } from 'playwright'
|
||||
@@ -38,7 +38,7 @@ describe('startup RPC budget', () => {
|
||||
// absorbs the first-connection reset wave the budget must include.
|
||||
await page.getByRole('textbox', { name: 'Choose workspace' }).waitFor({ timeout: 30_000 })
|
||||
await page.waitForTimeout(3000)
|
||||
const describeCount = calls.filter(method => method === 'settings.describe').length
|
||||
const describeCount = calls.filter(method => method === 'settings/describe').length
|
||||
expect(describeCount, `startup /api calls:\n${calls.join('\n')}`).toBe(DESCRIBE_BUDGET)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user