mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-11 04:00:38 +00:00
refactor(api): converge the Remote failure vocabulary and client surface
Single RemoteError with a merge-extensible, domain-prefixed code map; owners throw at the failure point; streams surface marked failures; clients consume ctx.remote directly with isRemoteFailure as the only discrimination point and construct no failure instances.
This commit is contained in:
@@ -9,7 +9,7 @@ import { Context } from '@deepseek-ai/cordis'
|
||||
import { credentialRef } from '@deepseek-ai/dsh-credentials'
|
||||
import type { CredentialProvider } from '@deepseek-ai/dsh-credentials'
|
||||
import type { CredentialInfo } from '@deepseek-ai/dsh-credentials/types'
|
||||
import { Remote, TypertRemoteFailure, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'
|
||||
import { Remote, RemoteError, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'
|
||||
import { z } from 'zod'
|
||||
|
||||
/**
|
||||
@@ -30,11 +30,7 @@ const unsetRequestSchema = z.object({ ref: credentialRefSchema })
|
||||
function parseRequest<T>(method: string, schema: z.ZodType<T>, value: unknown): T {
|
||||
const parsed = schema.safeParse(value)
|
||||
if (!parsed.success) {
|
||||
throw new TypertRemoteFailure({
|
||||
code: 'bad-request',
|
||||
message: `invalid payload for ${method}`,
|
||||
details: { issues: parsed.error.issues },
|
||||
})
|
||||
throw new RemoteError('gateway/bad-request', `invalid payload for ${method}`, { issues: parsed.error.issues })
|
||||
}
|
||||
return parsed.data
|
||||
}
|
||||
@@ -78,9 +74,10 @@ export class CredentialsController extends TypertRemoteService {
|
||||
* Describe several references for one configuration surface. Batched because
|
||||
* a settings page describes every reference its rows name at once, and one
|
||||
* round trip keeps those rows from settling separately.
|
||||
* @param refs - reference names, at most {@link MAX_DESCRIBE_REFS}; a name outside the grammar rejects the whole call as `bad-request`.
|
||||
* @param refs - reference names, at most {@link MAX_DESCRIBE_REFS}; a name outside the grammar
|
||||
* rejects the whole call as `gateway/bad-request`.
|
||||
* @returns one view per requested name, keyed by that name.
|
||||
* @throws TypertRemoteFailure when the request is invalid or no credential provider is mounted.
|
||||
* @throws RemoteError when the request is invalid or no credential provider is mounted.
|
||||
*/
|
||||
@Remote
|
||||
async describe(refs: string[]): Promise<Record<string, CredentialInfo>> {
|
||||
@@ -97,7 +94,7 @@ export class CredentialsController extends TypertRemoteService {
|
||||
* this direction only: no read path returns it.
|
||||
* @param ref - reference name to store under.
|
||||
* @param value - the non-empty secret value.
|
||||
* @throws TypertRemoteFailure when the request is invalid, no provider is mounted, or the provider refuses the write.
|
||||
* @throws RemoteError when the request is invalid, no provider is mounted, or the provider refuses the write.
|
||||
*/
|
||||
@Remote
|
||||
async set(ref: string, value: string): Promise<void> {
|
||||
@@ -110,7 +107,7 @@ export class CredentialsController extends TypertRemoteService {
|
||||
/**
|
||||
* Remove one reference from a configuration surface.
|
||||
* @param ref - reference name to remove.
|
||||
* @throws TypertRemoteFailure when the request is invalid, no provider is mounted, or the provider refuses the write.
|
||||
* @throws RemoteError when the request is invalid, no provider is mounted, or the provider refuses the write.
|
||||
*/
|
||||
@Remote
|
||||
async unset(ref: string): Promise<void> {
|
||||
@@ -124,17 +121,17 @@ export class CredentialsController extends TypertRemoteService {
|
||||
private provider(): CredentialProvider {
|
||||
const credentials = this.ctx.get('credentials')
|
||||
if (credentials === undefined) {
|
||||
throw new TypertRemoteFailure({
|
||||
code: 'internal',
|
||||
message: 'credentials service is absent: this deployment does not mount a credential provider (e.g. @deepseek-ai/dsh-credentials-local) in its composition',
|
||||
details: {},
|
||||
})
|
||||
throw new RemoteError(
|
||||
'gateway/internal',
|
||||
'credentials service is absent: this deployment does not mount a credential provider (e.g. @deepseek-ai/dsh-credentials-local) in its composition',
|
||||
{},
|
||||
)
|
||||
}
|
||||
return credentials
|
||||
}
|
||||
|
||||
/**
|
||||
* Run one remote write and report every refusal as `credential-rejected`
|
||||
* Run one remote write and report every refusal as `credential/rejected`
|
||||
* carrying the seam's own message: a read-only source shadowing the reference
|
||||
* is what a configuration surface must show verbatim. Callers brand the
|
||||
* reference before entering, so a name outside the grammar never reaches this
|
||||
@@ -145,11 +142,12 @@ export class CredentialsController extends TypertRemoteService {
|
||||
try {
|
||||
await write()
|
||||
} catch (error: unknown) {
|
||||
throw new TypertRemoteFailure({
|
||||
code: 'credential-rejected',
|
||||
message: error instanceof Error ? error.message : String(error),
|
||||
details: { ref },
|
||||
})
|
||||
throw new RemoteError(
|
||||
'credential/rejected',
|
||||
error instanceof Error ? error.message : String(error),
|
||||
{ ref },
|
||||
{ cause: error },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user