fix(file-upload): isolate receipts by session instance
This commit is contained in:
1 parent
e6c6ec668f
commit
aa2ae5c779
13 files changed
+45
-56
No files matched your search
@@ -475,7 +475,6 @@ flowchart TD
|
||||
pkg_attachment_local --> pkg_attachment
|
||||
pkg_attachment_local --> pkg_home_paths
|
||||
pkg_client_connection --> pkg_scope
|
||||
pkg_client_file_upload --> pkg_scope
|
||||
pkg_authorization --> pkg_credentials
|
||||
pkg_authorization --> pkg_invariants
|
||||
pkg_authorization --> pkg_llm
|
||||
@@ -1405,6 +1404,7 @@ flowchart TD
|
||||
| [`base`](../packages/bundle/base) | `bundle` | — |
|
||||
| [`sdk-app`](../packages/bundle/sdk-app) | `bundle` | — |
|
||||
| [`sdk-minimal`](../packages/bundle/sdk-minimal) | `bundle` | — |
|
||||
| [`client-file-upload`](../packages/client/file-upload) | `client` | — |
|
||||
| [`client-hmr`](../packages/client/hmr) | `client` | — |
|
||||
| [`client-locale`](../packages/client/locale) | `client` | — |
|
||||
| [`client-modules`](../packages/client/modules) | `client` | — |
|
||||
@@ -1516,7 +1516,6 @@ flowchart TD
|
||||
| [`api-terminal-controller`](../packages/api/terminal-controller) | `api` | [`subprocess`](../packages/subprocess/subprocess) |
|
||||
| [`attachment-local`](../packages/attachment/attachment-local) | `attachment` | [`attachment`](../packages/attachment/attachment), [`home-paths`](../packages/util/home-paths) |
|
||||
| [`client-connection`](../packages/client/connection) | `client` | [`scope`](../packages/core/scope) |
|
||||
| [`client-file-upload`](../packages/client/file-upload) | `client` | [`scope`](../packages/core/scope) |
|
||||
| [`authorization`](../packages/credentials/authorization) | `credentials` | [`credentials`](../packages/credentials/credentials), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm) |
|
||||
| [`credentials-local`](../packages/credentials/credentials-local) | `credentials` | [`atomic-write`](../packages/util/atomic-write), [`credentials`](../packages/credentials/credentials), [`home-paths`](../packages/util/home-paths), [`launch-environment`](../packages/util/launch-environment) |
|
||||
| [`experimental-computer-use-cua-driver-mcp`](../packages/experimental/computer-use-cua-driver-mcp) | `experimental` | [`computer-use`](../packages/computer-use/computer-use) |
|
||||
|
||||
@@ -477,7 +477,6 @@ flowchart TD
|
||||
pkg_attachment_local --> pkg_attachment
|
||||
pkg_attachment_local --> pkg_home_paths
|
||||
pkg_client_connection --> pkg_scope
|
||||
pkg_client_file_upload --> pkg_scope
|
||||
pkg_authorization --> pkg_credentials
|
||||
pkg_authorization --> pkg_invariants
|
||||
pkg_authorization --> pkg_llm
|
||||
@@ -1407,6 +1406,7 @@ flowchart TD
|
||||
| [`base`](../packages/bundle/base) | `bundle` | — |
|
||||
| [`sdk-app`](../packages/bundle/sdk-app) | `bundle` | — |
|
||||
| [`sdk-minimal`](../packages/bundle/sdk-minimal) | `bundle` | — |
|
||||
| [`client-file-upload`](../packages/client/file-upload) | `client` | — |
|
||||
| [`client-hmr`](../packages/client/hmr) | `client` | — |
|
||||
| [`client-locale`](../packages/client/locale) | `client` | — |
|
||||
| [`client-modules`](../packages/client/modules) | `client` | — |
|
||||
@@ -1518,7 +1518,6 @@ flowchart TD
|
||||
| [`api-terminal-controller`](../packages/api/terminal-controller) | `api` | [`subprocess`](../packages/subprocess/subprocess) |
|
||||
| [`attachment-local`](../packages/attachment/attachment-local) | `attachment` | [`attachment`](../packages/attachment/attachment), [`home-paths`](../packages/util/home-paths) |
|
||||
| [`client-connection`](../packages/client/connection) | `client` | [`scope`](../packages/core/scope) |
|
||||
| [`client-file-upload`](../packages/client/file-upload) | `client` | [`scope`](../packages/core/scope) |
|
||||
| [`authorization`](../packages/credentials/authorization) | `credentials` | [`credentials`](../packages/credentials/credentials), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm) |
|
||||
| [`credentials-local`](../packages/credentials/credentials-local) | `credentials` | [`atomic-write`](../packages/util/atomic-write), [`credentials`](../packages/credentials/credentials), [`home-paths`](../packages/util/home-paths), [`launch-environment`](../packages/util/launch-environment) |
|
||||
| [`experimental-computer-use-cua-driver-mcp`](../packages/experimental/computer-use-cua-driver-mcp) | `experimental` | [`computer-use`](../packages/computer-use/computer-use) |
|
||||
|
||||
@@ -303,7 +303,7 @@ Source: [`packages/attachment/attachment/src/index.ts`](../../packages/attachmen
|
||||
|
||||
### `ctx.fileUploads` — `FileUploads`
|
||||
|
||||
Host service owning upload storage and Agent-scoped staged receipts.
|
||||
Host service owning upload storage and receipts keyed by each receiving Agent's exact Session.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
@@ -330,7 +330,7 @@ registerAgentResolver(resolve: AgentResolver): () => void
|
||||
async uploadStream(request: { readonly sessionId: SessionId readonly data: AsyncIterable<Uint8Array> readonly signal?: AbortSignal readonly name?: string }): Promise<FileUploadValue>
|
||||
|
||||
/**
|
||||
* Resolve one staged receipt inside its receiving Agent scope.
|
||||
* Resolve one staged receipt for the receiving Agent's exact Session.
|
||||
* @param agent - receiving Agent.
|
||||
* @param receiptId - opaque receipt minted for one completed upload.
|
||||
* @returns durable file reference, or `undefined` for an unknown or foreign receipt.
|
||||
|
||||
@@ -303,7 +303,7 @@ Source: [`packages/attachment/attachment/src/index.ts`](../../packages/attachmen
|
||||
|
||||
### `ctx.fileUploads` — `FileUploads`
|
||||
|
||||
Host service owning upload storage and Agent-scoped staged receipts.
|
||||
Host service owning upload storage and receipts keyed by each receiving Agent's exact Session.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
@@ -330,7 +330,7 @@ registerAgentResolver(resolve: AgentResolver): () => void
|
||||
async uploadStream(request: { readonly sessionId: SessionId readonly data: AsyncIterable<Uint8Array> readonly signal?: AbortSignal readonly name?: string }): Promise<FileUploadValue>
|
||||
|
||||
/**
|
||||
* Resolve one staged receipt inside its receiving Agent scope.
|
||||
* Resolve one staged receipt for the receiving Agent's exact Session.
|
||||
* @param agent - receiving Agent.
|
||||
* @param receiptId - opaque receipt minted for one completed upload.
|
||||
* @returns durable file reference, or `undefined` for an unknown or foreign receipt.
|
||||
|
||||
@@ -13,7 +13,7 @@ import CommandRuntime from '@deepseek-ai/dsh-commands'
|
||||
import { createScope } from '@deepseek-ai/dsh-scope'
|
||||
import FileUploads from '@deepseek-ai/dsh-client-file-upload'
|
||||
import type { FileUploadReceiptId } from '@deepseek-ai/dsh-client-file-upload/types'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { describe, expect, it, onTestFinished, vi } from 'vitest'
|
||||
import type { ApiSessionAgentController } from '../src/agent.ts'
|
||||
import { SessionCommandController } from '../src/commands.ts'
|
||||
import type { SessionRequestId } from '../src/types.ts'
|
||||
@@ -33,6 +33,7 @@ async function uploadHarness(origin?: 'subagent'): Promise<{
|
||||
uploadRoute: (request: Request) => Promise<Response>
|
||||
}> {
|
||||
const ctx = new Context()
|
||||
onTestFinished(() => ctx.fiber.dispose())
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
await ctx.plugin(CommandRuntime)
|
||||
@@ -266,7 +267,7 @@ describe('Session file uploads', () => {
|
||||
})).rejects.toMatchObject({ code: 'session/not-found' })
|
||||
})
|
||||
|
||||
it('rejects subagent uploads and access outside the receiving Agent scope', async () => {
|
||||
it('rejects subagent uploads before storing bytes', async () => {
|
||||
const child = await uploadHarness('subagent')
|
||||
await expect(child.uploads.upload(
|
||||
child.agent,
|
||||
@@ -277,16 +278,24 @@ describe('Session file uploads', () => {
|
||||
details: { reason: 'SUBAGENT_FILE_UNSUPPORTED' },
|
||||
})
|
||||
expect(child.saveFile).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
const ordinary = await uploadHarness()
|
||||
const receipt = await ordinary.uploads.upload(
|
||||
ordinary.agent,
|
||||
{ data: 'AAAA' },
|
||||
new AbortController().signal,
|
||||
)
|
||||
const foreignScope = { ...ordinary.agent, ctx: ordinary.ctx } as Agent
|
||||
expect(() => ordinary.uploads.resolve(foreignScope, receipt.receiptId))
|
||||
.toThrow('operation requires the Agent\'s own scope')
|
||||
it('isolates receipts by Session object even when Session ids match', async () => {
|
||||
const owner = await uploadHarness()
|
||||
const other = await uploadHarness()
|
||||
expect(other.agent.session.id).toBe(owner.agent.session.id)
|
||||
expect(other.agent.session).not.toBe(owner.agent.session)
|
||||
const receipt = await owner.uploads.upload(owner.agent, { data: 'AAAA' }, new AbortController().signal)
|
||||
const binding = owner.uploads.bindPrompt(owner.agent, [receipt.receiptId], 'owner-prompt')
|
||||
binding.commit()
|
||||
|
||||
expect(owner.uploads.resolve(other.agent, receipt.receiptId)).toBeUndefined()
|
||||
expect(() => owner.uploads.bindPrompt(other.agent, [receipt.receiptId], 'other-prompt'))
|
||||
.toThrow(expect.objectContaining({ code: 'session/attachment-invalid', details: { reason: 'FILE_NOT_STAGED' } }))
|
||||
owner.uploads.retirePrompt(other.agent, 'owner-prompt')
|
||||
expect(owner.uploads.resolve(owner.agent, receipt.receiptId)).toEqual(receipt.file)
|
||||
owner.uploads.retirePrompt(owner.agent, 'owner-prompt')
|
||||
expect(owner.uploads.resolve(owner.agent, receipt.receiptId)).toBeUndefined()
|
||||
})
|
||||
|
||||
it('retires accepted receipts after their rpcId becomes observable', async () => {
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
en: 9d5bbf52599b0d00
|
||||
zh: 7907542ce1e34549
|
||||
/deepseek-ai-dsh-client-file-upload/understand-the-implementation:
|
||||
en: da896ccc5ecbe207
|
||||
zh: f434a7572085ee1e
|
||||
en: f4927d1dd1428534
|
||||
zh: 5d0db8b297a8f1b2
|
||||
/deepseek-ai-dsh-client-file-upload/further-exploration:
|
||||
en: ac94eb9da9ecc296
|
||||
zh: 25cc3362e2bea330
|
||||
|
||||
@@ -44,11 +44,11 @@ The package has no Cordis configuration fields. A `Blob` uses XMLHttpRequest ins
|
||||
|
||||
The Client plugin provides `ctx.fileUpload`. Its `upload()` method receives the owning Session identity, assembles the raw route request, and invokes the generated Remote for exact bytes. The provider reads the optional pre-Cordis `__DSH_FILE_UPLOAD__` hook once. Without a hook, each Blob or stream request owns a short-lived Worker and releases it after completion, failure, or cancellation. With the hook, the service sends the body through the page-owned Fetch carrier; the Web Worker runtime transfers stream bodies through its request frame and exposes them to the Host HTTP bridge as backpressured chunks.
|
||||
|
||||
The Host plugin provides `ctx.fileUploads`. It owns the authenticated streaming route, encoded Remote fallback, command receipt resolver, and staged-receipt lifecycle; encoded admission, attachment-error recognition, and byte storage stay behind `ctx.attachments`. Receipt tables use the receiving Agent's Session object as their key. The Session Controller registers the resolver that can resume a cold ordinary Agent and consumes receipts during prompt admission. Prompt delivery holds each receipt binding in a disposable transaction: disposal restores the previous binding until successful delivery commits it, and queue or history observation then retires the committed receipt.
|
||||
The Host plugin provides `ctx.fileUploads`. It owns the authenticated streaming route, encoded Remote fallback, command receipt resolver, and staged-receipt lifecycle; encoded admission, attachment-error recognition, and byte storage stay behind `ctx.attachments`. Host callers supply an Agent with its runtime-owned context; receipt tables use that Agent's exact Session object as their key. The Session Controller registers the resolver that can resume a cold ordinary Agent and consumes receipts during prompt admission. Prompt delivery holds each receipt binding in a disposable transaction: disposal restores the previous binding until successful delivery commits it, and queue or history observation then retires the committed receipt.
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| [`src/index.ts`](src/index.ts) | Host streaming route, attachment-service admission, and Agent-scoped receipt lifecycle |
|
||||
| [`src/index.ts`](src/index.ts) | Host streaming route, attachment-service admission, and Session-owned receipt lifecycle |
|
||||
| [`src/types.ts`](src/types.ts) | encoded request, receipt, and durable result types |
|
||||
| [`src/client/contract.ts`](src/client/contract.ts) | Client upload, progress, and page-hook types |
|
||||
| [`src/client/runtime.ts`](src/client/runtime.ts) | Dedicated Worker and page-owned carrier implementations |
|
||||
|
||||
@@ -44,11 +44,11 @@ kind: "package-reference"
|
||||
|
||||
Client 插件提供 `ctx.fileUpload`。其 `upload()` 方法接收所属 Session 标识,组装原始路由请求,并为精确字节调用生成的 Remote。提供方只读取一次可选的 Cordis 启动前 `__DSH_FILE_UPLOAD__` 钩子。没有该钩子时,每个 Blob 或 stream 请求拥有一个短期 Worker,并在完成、失败或取消后释放。存在该钩子时,服务通过页面自己提供的 Fetch 载体发送请求体;Web Worker runtime 会通过请求帧转移 stream 请求体,再以带背压的分片形式交给 Host HTTP bridge。
|
||||
|
||||
Host 插件提供 `ctx.fileUploads`。它拥有经过认证的流式路由、编码 Remote 兜底、命令凭证解析器与暂存凭证生命周期;编码准入、附件错误识别与字节存储仍由 `ctx.attachments` 提供。凭证表以接收方 Agent 的 Session 对象为键。Session Controller 注册可恢复休眠普通 Agent 的解析器,并在 prompt 准入时消费凭证。Prompt 投递通过可释放事务持有每个凭证绑定。成功投递提交事务前,释放会恢复原绑定;提交后,队列或历史观察会退休该凭证。
|
||||
Host 插件提供 `ctx.fileUploads`。它拥有经过认证的流式路由、编码 Remote 兜底、命令凭证解析器与暂存凭证生命周期;编码准入、附件错误识别与字节存储仍由 `ctx.attachments` 提供。Host 调用方传入具有运行时所属上下文的 Agent;凭证表以该 Agent 的准确 Session 对象为键。Session Controller 注册可恢复休眠普通 Agent 的解析器,并在 prompt 准入时消费凭证。Prompt 投递通过可释放事务持有每个凭证绑定。成功投递提交事务前,释放会恢复原绑定;提交后,队列或历史观察会退休该凭证。
|
||||
|
||||
| 文件 | 职责 |
|
||||
|---|---|
|
||||
| [`src/index.ts`](src/index.ts) | Host 流式路由、附件服务准入与按 Agent scope 管理的凭证生命周期 |
|
||||
| [`src/index.ts`](src/index.ts) | Host 流式路由、附件服务准入与 Session 所属的凭证生命周期 |
|
||||
| [`src/types.ts`](src/types.ts) | 编码请求、凭证与持久结果类型 |
|
||||
| [`src/client/contract.ts`](src/client/contract.ts) | Client 上传、进度与页面钩子类型 |
|
||||
| [`src/client/runtime.ts`](src/client/runtime.ts) | 专用 Worker 与页面自有载体实现 |
|
||||
|
||||
@@ -67,15 +67,13 @@
|
||||
"@deepseek-ai/dsh-brand": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@deepseek-ai/cordis": "workspace:~",
|
||||
"@deepseek-ai/dsh-scope": "workspace:*"
|
||||
"@deepseek-ai/cordis": "workspace:~"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@deepseek-ai/cordis": "workspace:~",
|
||||
"@deepseek-ai/dsh-agent": "workspace:*",
|
||||
"@deepseek-ai/dsh-client-connection": "workspace:*",
|
||||
"@deepseek-ai/dsh-commands": "workspace:*",
|
||||
"@deepseek-ai/dsh-scope": "workspace:*",
|
||||
"@deepseek-ai/dsh-util-crypto": "workspace:*",
|
||||
"@deepseek-ai/dsh-api-remotes": "workspace:*",
|
||||
"@deepseek-ai/dsh-session": "workspace:*",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** Host file-upload service: streamed intake and Agent-scoped staged receipts. */
|
||||
/** Host file-upload service: streamed intake and Session-owned staged receipts. */
|
||||
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
@@ -6,7 +6,6 @@ import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import type { FileAttachmentRef } from '@deepseek-ai/dsh-attachment'
|
||||
import type {} from '@deepseek-ai/dsh-client-connection'
|
||||
import type { CommandFileReceiptResolver } from '@deepseek-ai/dsh-commands'
|
||||
import { scopeOf } from '@deepseek-ai/dsh-scope'
|
||||
import type { Session, SessionEvent, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import { Remote, RemoteError, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol'
|
||||
import { handleFileUploadHttp } from './http-route.ts'
|
||||
@@ -53,7 +52,7 @@ class PromptFileBindingGuard implements PromptFileBinding {
|
||||
}
|
||||
}
|
||||
|
||||
/** Host service owning upload storage and Agent-scoped staged receipts. */
|
||||
/** Host service owning upload storage and receipts keyed by each receiving Agent's exact Session. */
|
||||
export class FileUploads extends TypertRemoteService {
|
||||
static inject = ['agents', 'attachments', 'commands', 'connection']
|
||||
|
||||
@@ -131,13 +130,12 @@ export class FileUploads extends TypertRemoteService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve one staged receipt inside its receiving Agent scope.
|
||||
* Resolve one staged receipt for the receiving Agent's exact Session.
|
||||
* @param agent - receiving Agent.
|
||||
* @param receiptId - opaque receipt minted for one completed upload.
|
||||
* @returns durable file reference, or `undefined` for an unknown or foreign receipt.
|
||||
*/
|
||||
resolve(agent: Agent, receiptId: FileUploadReceiptId): FileAttachmentRef | undefined {
|
||||
this.assertAgentScope(agent)
|
||||
return this.stagedFiles.get(agent.session)?.get(receiptId)?.file
|
||||
}
|
||||
|
||||
@@ -154,7 +152,6 @@ export class FileUploads extends TypertRemoteService {
|
||||
receiptIds: readonly FileUploadReceiptId[],
|
||||
requestId: string,
|
||||
): PromptFileBinding {
|
||||
this.assertAgentScope(agent)
|
||||
const staged = this.stagedFiles.get(agent.session)
|
||||
const bound = receiptIds.map((receiptId) => {
|
||||
const upload = staged?.get(receiptId)
|
||||
@@ -176,7 +173,6 @@ export class FileUploads extends TypertRemoteService {
|
||||
* @param requestId - prompt identity carried by the queue occurrence.
|
||||
*/
|
||||
retirePrompt(agent: Agent, requestId: string): void {
|
||||
this.assertAgentScope(agent)
|
||||
this.retire(agent.session, requestId)
|
||||
}
|
||||
|
||||
@@ -223,12 +219,7 @@ export class FileUploads extends TypertRemoteService {
|
||||
return resolver(sessionId)
|
||||
}
|
||||
|
||||
private assertAgentScope(agent: Agent): void {
|
||||
if (scopeOf(agent.ctx) !== agent) throw new Error('file-upload: operation requires the Agent\'s own scope')
|
||||
}
|
||||
|
||||
private assertOrdinaryAgent(agent: Agent): void {
|
||||
this.assertAgentScope(agent)
|
||||
if (agent.session.header.origin === 'subagent') {
|
||||
throw new RemoteError(
|
||||
'subagent/attachment-invalid' as never,
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
{ "path": "../../../vendor/cordis" },
|
||||
{ "path": "../../util/brand" },
|
||||
{ "path": "../../core/agent" },
|
||||
{ "path": "../../core/scope" },
|
||||
{ "path": "../../core/session" },
|
||||
{ "path": "../../attachment/attachment" },
|
||||
{ "path": "../../interaction/commands" },
|
||||
|
||||
@@ -999,8 +999,8 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
|
||||
},
|
||||
{
|
||||
key: 'fileUploads',
|
||||
summary: 'Host service owning upload storage and Agent-scoped staged receipts.',
|
||||
description: 'Host service owning upload storage and Agent-scoped staged receipts.',
|
||||
summary: 'Host service owning upload storage and receipts keyed by each receiving Agent\'s exact Session.',
|
||||
description: 'Host service owning upload storage and receipts keyed by each receiving Agent\'s exact Session.',
|
||||
methods: [
|
||||
{
|
||||
signature: 'registerAgentResolver(resolve: AgentResolver): () => void',
|
||||
@@ -1022,7 +1022,7 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
|
||||
},
|
||||
{
|
||||
signature: 'resolve(agent: Agent, receiptId: FileUploadReceiptId): FileAttachmentRef | undefined',
|
||||
description: 'Resolve one staged receipt inside its receiving Agent scope.',
|
||||
description: 'Resolve one staged receipt for the receiving Agent\'s exact Session.',
|
||||
parameters: [{ name: 'agent', description: 'receiving Agent.' }, { name: 'receiptId', description: 'opaque receipt minted for one completed upload.' }],
|
||||
returns: 'durable file reference, or `undefined` for an unknown or foreign receipt.',
|
||||
},
|
||||
|
||||
Generated
+6
-12
@@ -1159,9 +1159,6 @@ importers:
|
||||
'@deepseek-ai/dsh-deque':
|
||||
specifier: workspace:*
|
||||
version: link:../../util/deque
|
||||
'@deepseek-ai/dsh-session':
|
||||
specifier: workspace:*
|
||||
version: link:../../core/session
|
||||
'@deepseek-ai/dsh-util-values':
|
||||
specifier: workspace:*
|
||||
version: link:../../util/values
|
||||
@@ -2852,9 +2849,6 @@ importers:
|
||||
'@deepseek-ai/dsh-commands':
|
||||
specifier: workspace:*
|
||||
version: link:../../interaction/commands
|
||||
'@deepseek-ai/dsh-scope':
|
||||
specifier: workspace:*
|
||||
version: link:../../core/scope
|
||||
'@deepseek-ai/dsh-session':
|
||||
specifier: workspace:*
|
||||
version: link:../../core/session
|
||||
@@ -9693,7 +9687,7 @@ importers:
|
||||
version: link:../../../vendor/schemastery
|
||||
'@earendil-works/pi-ai':
|
||||
specifier: ^0.87.1
|
||||
version: 0.87.1(patch_hash=b9bcce474fb2ac44633dff0fa722816a5bff5451b4575d5874035ea14ba70a4f)(@modelcontextprotocol/[email protected]([email protected]))([email protected])([email protected])
|
||||
version: 0.87.1(patch_hash=b9bcce474fb2ac44633dff0fa722816a5bff5451b4575d5874035ea14ba70a4f)(@modelcontextprotocol/[email protected]([email protected]))([email protected])([email protected])([email protected])
|
||||
devDependencies:
|
||||
'@deepseek-ai/cordis':
|
||||
specifier: workspace:~
|
||||
@@ -22668,15 +22662,15 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- '@algolia/client-search'
|
||||
|
||||
'@earendil-works/[email protected](patch_hash=b9bcce474fb2ac44633dff0fa722816a5bff5451b4575d5874035ea14ba70a4f)(@modelcontextprotocol/[email protected]([email protected]))([email protected])([email protected])':
|
||||
'@earendil-works/[email protected](patch_hash=b9bcce474fb2ac44633dff0fa722816a5bff5451b4575d5874035ea14ba70a4f)(@modelcontextprotocol/[email protected]([email protected]))([email protected])([email protected])([email protected])':
|
||||
dependencies:
|
||||
'@anthropic-ai/sdk': 0.124.0([email protected])
|
||||
'@aws-sdk/client-bedrock-runtime': 3.1127.0
|
||||
'@earendil-works/pi-telemetry': 0.87.1
|
||||
'@google/genai': 2.21.0(@modelcontextprotocol/[email protected]([email protected]))
|
||||
'@smithy/node-http-handler': 4.12.1
|
||||
http-proxy-agent: 9.1.0
|
||||
https-proxy-agent: 9.1.0
|
||||
http-proxy-agent: 9.1.0([email protected])
|
||||
https-proxy-agent: 9.1.0([email protected])
|
||||
openai: 6.40.0([email protected])([email protected])
|
||||
partial-json: 0.1.7
|
||||
typebox: 1.3.27
|
||||
@@ -26859,7 +26853,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
[email protected]:
|
||||
[email protected]([email protected]):
|
||||
dependencies:
|
||||
agent-base: 9.0.0
|
||||
debug: 4.4.3([email protected])
|
||||
@@ -26918,7 +26912,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
[email protected]:
|
||||
[email protected]([email protected]):
|
||||
dependencies:
|
||||
agent-base: 9.0.0
|
||||
debug: 4.4.3([email protected])
|
||||
|
||||
Reference in new issue
Block a user