feat(server): pi module with upstream CRUD, server-side OAuth and token refresh
- /pi/providers, /pi/upstreams CRUD, test (auth-only by default, no cost), models - subscription login via pi models.login with a suspended interaction: browser mode waits for the pasted redirect URL, device mode polls server-side; per-provider login lock, readable callback-port-in-use errors - credential store locks the pi_upstream row (select for update) so api and worker refreshes never double-write a rotated refresh token - refreshPiTokens task: refresh before expiry; failure marks expired and opens a relogin decision, closed again after a successful login - runAgent picks upstreamId > agent_run.upstream_id > default upstream > legacy settings; credentials injected by the server, never logged Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
743fe2486d
commit
fd3ffe5a8d
13 files changed
+1617
-26
No files matched your search
@@ -29,12 +29,21 @@ export function registerAgentTasks(registry: TaskRegistry, env: () => AgentEnv)
|
||||
defineTask({
|
||||
name: "runAgent",
|
||||
version: 1,
|
||||
inputSchema: z.object({ agentRunId: id }),
|
||||
/** upstreamId:覆盖默认上游(W7-A);缺省用 agent_run.upstream_id,再缺省 settings.pi.defaultUpstreamId */
|
||||
inputSchema: z.object({ agentRunId: id, upstreamId: id.optional() }),
|
||||
retryPolicy: DB_RETRY,
|
||||
handler: async (t) => {
|
||||
const e = env();
|
||||
const runId = t.input.agentRunId;
|
||||
const upstreamId = t.input.upstreamId;
|
||||
await t.step.run("start", async () => {
|
||||
if (upstreamId)
|
||||
await e.ctx.db
|
||||
.updateTable("agent_run")
|
||||
.set({ upstream_id: upstreamId })
|
||||
.where("id", "=", runId)
|
||||
.where("started_at", "is", null)
|
||||
.execute();
|
||||
await e.ctx.db
|
||||
.updateTable("task")
|
||||
.set({ status: "running", started_at: new Date(), attempts: sql`attempts + 1` })
|
||||
|
||||
Reference in new issue
Block a user