orbit-codex-bridge 0.1.2 → 0.1.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/relay-agent.mjs CHANGED
@@ -69,7 +69,9 @@ export function createRelayAgent(options = {}) {
69
69
  requests.delete(request);
70
70
  resolve({statusCode:response.statusCode || 502,headers:{
71
71
  'content-type':response.headers['content-type'] || 'application/json',
72
- ...(response.headers['set-cookie'] ? {'set-cookie':response.headers['set-cookie']} : {})
72
+ ...(response.headers['set-cookie'] ? {'set-cookie':response.headers['set-cookie']} : {}),
73
+ ...Object.fromEntries(['content-disposition','content-length','accept-ranges','content-range','etag']
74
+ .filter(name=>typeof response.headers[name]==='string').map(name=>[name,response.headers[name]]))
73
75
  },body:Buffer.concat(chunks)});
74
76
  });
75
77
  });
@@ -97,7 +99,7 @@ export function createRelayAgent(options = {}) {
97
99
  const body = Buffer.from(message.body || '', 'base64');
98
100
  if (body.length > maxBody) return;
99
101
  const headers = {};
100
- for (const name of ['accept','content-type','cookie','user-agent']) {
102
+ for (const name of ['accept','content-type','cookie','user-agent','range','if-range','if-none-match']) {
101
103
  const value = message.headers?.[name];
102
104
  if (typeof value === 'string') headers[name] = value;
103
105
  }
package/relay-server.mjs CHANGED
@@ -71,13 +71,24 @@ function responseHeaders(headers, deviceId, secureCookie) {
71
71
  const token = paired.split(';')[0].slice('orbit_session='.length);
72
72
  safe['Set-Cookie'] = `${deviceCookieName(deviceId)}=${token}; HttpOnly; SameSite=Strict; Path=/; Max-Age=${token ? 43200 : 0}${secureCookie ? '; Secure' : ''}`;
73
73
  }
74
+ const contentType=headers?.['content-type'];
75
+ if(typeof contentType==='string'&&/^(?:application\/(?:json|pdf|zip|octet-stream)|text\/[a-z0-9.+-]+(?:;\s*charset=utf-8)?|image\/(?:png|jpeg|gif|webp|svg\+xml))$/i.test(contentType))safe['Content-Type']=contentType;
76
+ const disposition=headers?.['content-disposition'];
77
+ if(typeof disposition==='string'&&disposition.length<=1000
78
+ &&/^attachment;\s*filename="[^"\r\n]{1,180}";\s*filename\*=UTF-8''[a-zA-Z0-9%._~-]{1,600}$/.test(disposition))safe['Content-Disposition']=disposition;
79
+ const length=headers?.['content-length'];
80
+ if(/^\d{1,8}$/.test(String(length||'')))safe['Content-Length']=length;
81
+ if(/^(?:bytes \d+-\d+\/\d+|bytes \*\/\d+)$/.test(headers?.['content-range']||''))safe['Content-Range']=headers['content-range'];
82
+ if(headers?.['accept-ranges']==='bytes')safe['Accept-Ranges']='bytes';
83
+ if(typeof headers?.etag==='string'&&/^"orbit-\d+-\d+"$/.test(headers.etag))safe.ETag=headers.etag;
74
84
  return safe;
75
85
  }
76
86
 
77
87
  function isLocalApi(pathname, method) {
78
88
  if (method === 'GET') return ['/api/status','/api/threads','/api/models'].includes(pathname)
79
- || /^\/api\/threads\/[a-zA-Z0-9_-]{8,120}\/messages$/.test(pathname);
80
- return method === 'POST' && ['/api/pair','/api/logout','/api/pair/qr'].includes(pathname);
89
+ || /^\/api\/threads\/[a-zA-Z0-9_-]{8,120}\/(?:messages|files|file)$/.test(pathname);
90
+ return method === 'POST' && (['/api/pair','/api/logout','/api/pair/qr'].includes(pathname)
91
+ || /^\/api\/threads\/[a-zA-Z0-9_-]{8,120}\/attachments(?:\/remove)?$/.test(pathname));
81
92
  }
82
93
 
83
94
  function json(response, status, body, headers = {}) {
@@ -261,14 +272,14 @@ export function createRelayServer(options = {}) {
261
272
  const agent=agents.get(device.id);
262
273
  if(!agent||agent.socket.readyState!==WebSocket.OPEN)return json(response,503,{error:`电脑“${device.name}”当前不在线。`});
263
274
  if(accountConnect&&!agent.accountConnect)return json(response,409,{
264
- error:'请在电脑上更新 Orbit 连接器到 0.1.2 或更高版本后重试。',code:'connector_upgrade_required'
275
+ error:'请在电脑上更新 Orbit 连接器到 0.1.3 或更高版本后重试。',code:'connector_upgrade_required'
265
276
  });
266
277
  const body=await readBody(request);
267
278
  if (!store.hasSession(authenticated.tokenHash,authenticated.user.id)) return json(response,401,{error:'请先登录云端工作台。',code:'cloud_login_required'});
268
279
  chooseDevice(request, store.getUser(authenticated.user.id));
269
280
  const requestId=crypto.randomUUID();
270
281
  const headers={};
271
- for(const name of ['accept','content-type','host','origin','user-agent'])if(request.headers[name])headers[name]=request.headers[name];
282
+ for(const name of ['accept','content-type','host','origin','user-agent','range','if-range','if-none-match'])if(request.headers[name])headers[name]=request.headers[name];
272
283
  headers.cookie = localCookie(request,device.id);
273
284
  if(pendingHttp.size>=500)return json(response,429,{error:'请求过多,请稍后重试。'});
274
285
  const promise=new Promise((resolve,reject)=>{