@fxz26284407/yuanma-gateway 0.1.13 → 0.1.15
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/dist/antigravity-conversation.js +4 -1
- package/dist/antigravity-native.js +18 -6
- package/dist/antigravity.js +18 -6
- package/dist/deepseek-conversation.js +9 -1
- package/dist/deepseek.js +11 -5
- package/dist/mobile-history.js +5 -2
- package/dist/platform/macos.js +0 -1
- package/dist/platform/windows.js +1 -2
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { imageReferences } from './media.js';
|
|
1
2
|
import { createHash } from 'node:crypto';
|
|
2
3
|
import { basename } from 'node:path';
|
|
3
4
|
import { requireValue } from './domain.js';
|
|
@@ -107,7 +108,7 @@ export function nativeRecords(steps, fallbackTurn = 'agy-context') {
|
|
|
107
108
|
}
|
|
108
109
|
return records;
|
|
109
110
|
}
|
|
110
|
-
export function conversationPage(records, nextCursor, fullReplies = new Map()) {
|
|
111
|
+
export function conversationPage(records, nextCursor, fullReplies = new Map(), threadId = '') {
|
|
111
112
|
const turns = new Map();
|
|
112
113
|
for (const { step, turnId } of records)
|
|
113
114
|
for (const part of stepParts(step)) {
|
|
@@ -116,6 +117,8 @@ export function conversationPage(records, nextCursor, fullReplies = new Map()) {
|
|
|
116
117
|
const text = fullReplies.get(id) ?? part.text;
|
|
117
118
|
const truncated = (!reply && text.length > 1000) || (fields.includes(part.part === 'tools' ? 'tool_calls' : part.part) && !fullReplies.has(id));
|
|
118
119
|
const item = { id, type: part.role === 'user' ? 'userMessage' : reply ? 'agentMessage' : 'commandExecution', role: part.role, text: reply ? text : text.slice(0, 1000), totalChars: text.length, truncated };
|
|
120
|
+
if (reply)
|
|
121
|
+
item.images = imageReferences({ type: 'agentMessage', id, text }, turnId, threadId);
|
|
119
122
|
item.readId = id + ':' + fingerprint(step);
|
|
120
123
|
item.groupKey = turnId + ':' + step.step_index;
|
|
121
124
|
if (part.role === 'tool')
|
|
@@ -62,10 +62,22 @@ export class AntigravityNative {
|
|
|
62
62
|
await this.connect();
|
|
63
63
|
const authority = this.#authority;
|
|
64
64
|
try {
|
|
65
|
-
if (method === 'GetAllCascadeTrajectories'
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
if (method === 'GetAllCascadeTrajectories') {
|
|
66
|
+
try {
|
|
67
|
+
const snapshot = await this.readState('JetboxSubscribeToSummaries', {});
|
|
68
|
+
requireValue(snapshot && typeof snapshot === 'object' && !Array.isArray(snapshot) && (snapshot.updates !== undefined || Object.keys(snapshot).length === 0), 'PROTOCOL_INCOMPATIBLE', '桌面会话订阅格式已变化', 503);
|
|
69
|
+
return { trajectorySummaries: cascadeSummaries(snapshot.updates === undefined ? {} : { trajectorySummaries: snapshot.updates }) };
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (error.code !== 'UNSUPPORTED_METHOD')
|
|
73
|
+
throw error;
|
|
74
|
+
// Older servers may expose only the unary catalog.
|
|
75
|
+
const result = await this.rpc(authority, method, params, timeout, signal);
|
|
76
|
+
cascadeSummaries(result);
|
|
77
|
+
this.ready = true;
|
|
78
|
+
this.#checked = Date.now();
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
69
81
|
}
|
|
70
82
|
const result = await this.rpc(authority, method, params, timeout, signal);
|
|
71
83
|
if (method === 'GetCascadeTrajectorySteps') {
|
|
@@ -114,7 +126,7 @@ export class AntigravityNative {
|
|
|
114
126
|
} onEnd(error); };
|
|
115
127
|
const req = request({ hostname: '127.0.0.1', port: authority.port, path: '/exa.language_server_pb.LanguageServerService/' + method, method: 'POST', rejectUnauthorized: false, headers: { 'content-type': 'application/connect+json', 'connect-protocol-version': '1', 'x-codeium-csrf-token': authority.token } }, res => {
|
|
116
128
|
if (res.statusCode !== 200) {
|
|
117
|
-
finish(new Error('Antigravity 状态订阅不可用(HTTP ' + res.statusCode + ')'));
|
|
129
|
+
finish(Object.assign(new Error('Antigravity 状态订阅不可用(HTTP ' + res.statusCode + ')'), { code: res.statusCode === 404 || res.statusCode === 501 ? 'UNSUPPORTED_METHOD' : 'STREAM_UNAVAILABLE' }));
|
|
118
130
|
return;
|
|
119
131
|
}
|
|
120
132
|
if (!res.headers['content-type']?.startsWith('application/connect+json')) {
|
|
@@ -136,7 +148,7 @@ export class AntigravityNative {
|
|
|
136
148
|
const value = JSON.parse(buffer.subarray(5, 5 + length).toString('utf8'));
|
|
137
149
|
buffer = buffer.subarray(5 + length);
|
|
138
150
|
if (flags === 2) {
|
|
139
|
-
finish(value.error ? new Error('Antigravity 状态订阅中断') : undefined);
|
|
151
|
+
finish(value.error ? Object.assign(new Error('Antigravity 状态订阅中断'), { code: value.error.code === 'unimplemented' ? 'UNSUPPORTED_METHOD' : 'STREAM_UNAVAILABLE' }) : undefined);
|
|
140
152
|
return;
|
|
141
153
|
}
|
|
142
154
|
if (flags !== 0)
|
package/dist/antigravity.js
CHANGED
|
@@ -5,7 +5,7 @@ import { join, relative, isAbsolute, sep, basename, dirname, resolve } from 'nod
|
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
6
|
import { randomUUID } from 'node:crypto';
|
|
7
7
|
import { platform } from './platform.mjs';
|
|
8
|
-
import { imageChunk } from './media.js';
|
|
8
|
+
import { imageChunk, imageSources } from './media.js';
|
|
9
9
|
import { AntigravityNative, cascadeSummaries } from './antigravity-native.js';
|
|
10
10
|
import { messageInput, resolveExtensions } from './extensions.js';
|
|
11
11
|
import { iconSource, iconFields, extensionIconChunk } from './extension-icons.js';
|
|
@@ -1028,7 +1028,15 @@ export class AntigravityBackend {
|
|
|
1028
1028
|
async mediaChunk(threadId, turnId, itemId, index, offset, version) {
|
|
1029
1029
|
await this.session(threadId);
|
|
1030
1030
|
requireValue(Number.isSafeInteger(index) && index >= 0 && index < 8, 'INVALID_REQUEST', '图片索引无效', 400);
|
|
1031
|
-
const log = await this.log(threadId),
|
|
1031
|
+
const log = await this.log(threadId), live = this.follows.get(threadId);
|
|
1032
|
+
const matches = (r) => r.turnId === turnId && partId(r.step, 'content') === itemId;
|
|
1033
|
+
const record = nativeRecords(live?.steps ?? new Map(), live?.fallbackTurn).find(matches) ?? log.records.find(matches);
|
|
1034
|
+
if (record?.step.type === 'PLANNER_RESPONSE' && record.step.source === 'MODEL') {
|
|
1035
|
+
const text = await this.historyText(threadId, turnId, itemId);
|
|
1036
|
+
const source = imageSources({ type: 'agentMessage', text })[index];
|
|
1037
|
+
requireValue(source, 'MEDIA_NOT_FOUND', '输出图片不可用', 404);
|
|
1038
|
+
return imageChunk(source, offset, version);
|
|
1039
|
+
}
|
|
1032
1040
|
requireValue(record && record.step.type === 'USER_INPUT', 'MEDIA_NOT_FOUND', '图片消息已变化,请刷新', 404);
|
|
1033
1041
|
const raw = await this.desktop.call('GetCascadeTrajectorySteps', { cascadeId: threadId, stepOffset: record.step.step_index, trajectoryVerbosity: 'CLIENT_TRAJECTORY_VERBOSITY_FULL' });
|
|
1034
1042
|
const media = raw.steps?.[0]?.userInput?.media?.[index];
|
|
@@ -1074,7 +1082,7 @@ export class AntigravityBackend {
|
|
|
1074
1082
|
fullReplies.set(partId(step, 'content'), reply.text);
|
|
1075
1083
|
}
|
|
1076
1084
|
}
|
|
1077
|
-
const page = await this.enrichUserContent(conversationPage(records, start ? Buffer.from(JSON.stringify({ threadId, version: log.version, end: start })).toString('base64url') : null, fullReplies), records, threadId);
|
|
1085
|
+
const page = await this.enrichUserContent(conversationPage(records, start ? Buffer.from(JSON.stringify({ threadId, version: log.version, end: start })).toString('base64url') : null, fullReplies, threadId), records, threadId);
|
|
1078
1086
|
if (this.desktop.ready)
|
|
1079
1087
|
for (const project of this.projects)
|
|
1080
1088
|
if (await this.belongs(project, row)) {
|
|
@@ -1099,6 +1107,12 @@ export class AntigravityBackend {
|
|
|
1099
1107
|
async history(threadId) { return this.mobileHistory(threadId); }
|
|
1100
1108
|
async historyItem(threadId, turnId, itemId, offset) {
|
|
1101
1109
|
requireValue(Number.isSafeInteger(offset) && offset >= 0, 'INVALID_REQUEST', 'Invalid text offset', 400);
|
|
1110
|
+
const text = await this.historyText(threadId, turnId, itemId);
|
|
1111
|
+
requireValue(offset <= text.length, 'INVALID_REQUEST', 'Text offset exceeds message', 400);
|
|
1112
|
+
const end = Math.min(text.length, offset + 12000);
|
|
1113
|
+
return { text: text.slice(offset, end), totalChars: text.length, ...(end < text.length ? { nextOffset: end } : {}) };
|
|
1114
|
+
}
|
|
1115
|
+
async historyText(threadId, turnId, itemId) {
|
|
1102
1116
|
await this.session(threadId);
|
|
1103
1117
|
const log = await this.log(threadId);
|
|
1104
1118
|
const versioned = /^(agy:\d+:[a-f0-9]{16}:(?:content|thinking|tools)):([a-f0-9]{16})$/.exec(itemId), stableId = versioned?.[1] ?? itemId;
|
|
@@ -1117,9 +1131,7 @@ export class AntigravityBackend {
|
|
|
1117
1131
|
requireValue(value, 'ITEM_NOT_FOUND', '没有可读取的全文', 404);
|
|
1118
1132
|
text = value.text;
|
|
1119
1133
|
}
|
|
1120
|
-
|
|
1121
|
-
const end = Math.min(text.length, offset + 12000);
|
|
1122
|
-
return { text: text.slice(offset, end), totalChars: text.length, ...(end < text.length ? { nextOffset: end } : {}) };
|
|
1134
|
+
return text;
|
|
1123
1135
|
}
|
|
1124
1136
|
close() { for (const id of this.follows.keys())
|
|
1125
1137
|
this.unfollow(id); this.interactions.clear(); this.diffs.clear(); this.desktop.close(); this.runtimeCache.clear(); this.extensionCache.clear(); this.ready = false; this.logs.clear(); }
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { imageSources } from './media.js';
|
|
1
2
|
import { requireValue } from './domain.js';
|
|
2
3
|
const blocks = (content) => Array.isArray(content) ? content.filter(b => b.type === 'text').map(b => b.text ?? '').join('\n') : '';
|
|
4
|
+
export function deepseekOutputImages(event) {
|
|
5
|
+
return event.type === 'assistant/message' ? imageSources({ type: 'agentMessage', text: blocks(event.data.message?.content) }) : [];
|
|
6
|
+
}
|
|
3
7
|
function userText(event) {
|
|
4
8
|
if (event.data.source?.kind === 'user')
|
|
5
9
|
return blocks(event.data.content);
|
|
@@ -95,10 +99,14 @@ export const deepseekConversation = {
|
|
|
95
99
|
const media = e.type === 'tool/call' ? results.get(e.data.callId) : e;
|
|
96
100
|
const content = media?.type === 'user/message' ? media.data.content : media?.data.message?.content;
|
|
97
101
|
if (content && view)
|
|
98
|
-
view.images = content.filter((b) => b.type === 'image' && b.attachment).map((_b, index) => ({ id: JSON.stringify([threadId, media.seq, index]), threadId, turnId: turn, itemId: 'dsh:' + media.seq, index, label: '图片 ' + (index + 1) }));
|
|
102
|
+
view.images = [...content.filter((b) => b.type === 'image' && b.attachment), ...deepseekOutputImages(media)].slice(0, 8).map((_b, index) => ({ id: JSON.stringify([threadId, media.seq, index]), threadId, turnId: turn, itemId: 'dsh:' + media.seq, index, label: '图片 ' + (index + 1) }));
|
|
99
103
|
if (!turns.has(turn))
|
|
100
104
|
turns.set(turn, { id: turn, status: 'recorded', items: [] });
|
|
101
105
|
turns.get(turn).items.push(...thoughts, ...(view ? [view] : []));
|
|
106
|
+
if (view?.role === 'tool' && view.images?.length) {
|
|
107
|
+
turns.get(turn).items.push({ ...item(media, 'assistant', ''), id: view.id + ':images', images: view.images });
|
|
108
|
+
view.images = [];
|
|
109
|
+
}
|
|
102
110
|
}
|
|
103
111
|
return { data: [...turns.values()].reverse(), nextCursor };
|
|
104
112
|
}
|
package/dist/deepseek.js
CHANGED
|
@@ -5,11 +5,11 @@ import { homedir } from 'node:os';
|
|
|
5
5
|
import { join, relative, isAbsolute, sep } from 'node:path';
|
|
6
6
|
import { realpath, mkdir } from 'node:fs/promises';
|
|
7
7
|
import { createHash, randomUUID } from 'node:crypto';
|
|
8
|
-
import { deepseekConversation, deepseekToolText } from './deepseek-conversation.js';
|
|
8
|
+
import { deepseekConversation, deepseekToolText, deepseekOutputImages } from './deepseek-conversation.js';
|
|
9
9
|
import { permissionKey } from './permissions.js';
|
|
10
10
|
import { agentCommands, checkGoal } from './agent-commands.js';
|
|
11
11
|
import { digest } from './domain.js';
|
|
12
|
-
import { imageMime } from './media.js';
|
|
12
|
+
import { imageMime, imageChunk } from './media.js';
|
|
13
13
|
import { messageInput, resolveExtensions } from './extensions.js';
|
|
14
14
|
import { Fault, requireValue } from './domain.js';
|
|
15
15
|
/** Conversation work uses the desktop Host; auxiliary suggestions use only its installed model SDK. */
|
|
@@ -386,12 +386,18 @@ export class DeepSeekBackend {
|
|
|
386
386
|
const event = page.records.map((r) => r.event).find((e) => e.seq === seq);
|
|
387
387
|
requireValue(event && (event.data.turn === undefined || String(event.data.turn) === turnId), 'MEDIA_NOT_FOUND', 'Image event not found', 404);
|
|
388
388
|
const blocks = event.type === 'user/message' ? event.data.content : event.data.message?.content;
|
|
389
|
-
const
|
|
389
|
+
const attachments = blocks?.filter((b) => b.type === 'image' && b.attachment) ?? [];
|
|
390
|
+
if (index >= attachments.length) {
|
|
391
|
+
const source = deepseekOutputImages(event)[index - attachments.length];
|
|
392
|
+
requireValue(source, 'MEDIA_NOT_FOUND', 'Image reference not found', 404);
|
|
393
|
+
return imageChunk(source, offset, version);
|
|
394
|
+
}
|
|
395
|
+
const ref = attachments[index]?.attachment;
|
|
390
396
|
requireValue(ref, 'MEDIA_NOT_FOUND', 'Image reference not found', 404);
|
|
391
397
|
const key = id + '\0' + ref.attachmentId;
|
|
392
398
|
let cached = this.mediaCache.get(key);
|
|
393
399
|
if (!cached) {
|
|
394
|
-
const image = await this.call('session/attachment', { request: { sessionId: id,
|
|
400
|
+
const image = await this.call('session/attachment', { request: { sessionId: id, attachment: ref } });
|
|
395
401
|
requireValue(typeof image.data === 'string' && image.data.length <= Math.ceil(8 * 1024 * 1024 / 3) * 4, 'MEDIA_TOO_LARGE', '图片超过手机端 8 MiB 限制', 413);
|
|
396
402
|
const bytes = Buffer.from(image.data, 'base64'), mime = imageMime(bytes);
|
|
397
403
|
requireValue(bytes.length <= 8 * 1024 * 1024 && mime === image.attachment.mediaType, 'MEDIA_UNSUPPORTED', 'Invalid image attachment', 415);
|
|
@@ -615,7 +621,7 @@ export class DeepSeekBackend {
|
|
|
615
621
|
requireValue(actual.type === want.type && (want.type !== 'text' || actual.text === want.text), 'AMBIGUOUS_DELIVERY', 'Request ID has different content');
|
|
616
622
|
if (want.type === 'image') {
|
|
617
623
|
requireValue(actual.attachment?.mediaType === want.mediaType, 'AMBIGUOUS_DELIVERY', 'Image receipt differs');
|
|
618
|
-
const image = await this.call('session/attachment', { request: { sessionId: m.thread_id,
|
|
624
|
+
const image = await this.call('session/attachment', { request: { sessionId: m.thread_id, attachment: actual.attachment } });
|
|
619
625
|
// Harness normalizes admitted images. The exact rpcId above identifies
|
|
620
626
|
// the submission; verify its immutable stored attachment, not raw-byte equality.
|
|
621
627
|
const bytes = Buffer.from(image.data, 'base64');
|
package/dist/mobile-history.js
CHANGED
|
@@ -19,6 +19,8 @@ export function itemText(item) {
|
|
|
19
19
|
return (item.content ?? []).map((c) => c.type === 'text' ? userText(c.text ?? '') : ['skill', 'mention'].includes(c.type) ? '@' + c.name : '').filter(Boolean).join('\n');
|
|
20
20
|
if (item.type === 'imageView' || item.type === 'contextCompaction')
|
|
21
21
|
return '';
|
|
22
|
+
if (item.type === 'imageGeneration')
|
|
23
|
+
return item.failure?.message ?? '';
|
|
22
24
|
if (item.type === 'agentMessage')
|
|
23
25
|
return item.text ?? '';
|
|
24
26
|
if (item.type === 'commandExecution')
|
|
@@ -32,11 +34,12 @@ export function reasoningText(item) {
|
|
|
32
34
|
}
|
|
33
35
|
export function mobileHistoryPage(page, threadId = '') {
|
|
34
36
|
return { nextCursor: page.nextCursor ?? null, data: page.data.filter((e) => e.item.type !== 'reasoning' || itemText(e.item).trim()).map((e) => {
|
|
37
|
+
const assistant = e.item.type === 'agentMessage' || e.item.type === 'imageGeneration';
|
|
35
38
|
const text = itemText(e.item), truncated = text.length > 800;
|
|
36
39
|
const preview = text.slice(0, 800);
|
|
37
40
|
const question = asyncQuestions(e.turnId, page.data.map((x) => x.item)).find(q => q.sourceItemId === e.item.id);
|
|
38
|
-
const base = { role: e.item.type === 'userMessage' ? 'user' :
|
|
39
|
-
const item = e.item.type === 'userMessage' ? { ...base, type: 'userMessage', content: [{ type: 'text', text: preview }] } :
|
|
41
|
+
const base = { role: e.item.type === 'userMessage' ? 'user' : assistant ? 'assistant' : 'tool', ...(question ? { asyncQuestion: question } : {}), images: imageReferences(e.item, e.turnId, threadId), id: e.item.id, clientId: e.item.clientId, truncated, totalChars: text.length, ...(e.item.type !== 'userMessage' && !assistant ? { execution: executionSummary(e.item) } : {}) };
|
|
42
|
+
const item = e.item.type === 'userMessage' ? { ...base, type: 'userMessage', content: [{ type: 'text', text: preview }] } : assistant ? { ...base, type: 'agentMessage', text: preview, ...(typeof e.item.phase === 'string' ? { phase: e.item.phase } : {}), ...(typeof e.item.delivery === 'string' ? { delivery: e.item.delivery } : {}) } : { ...base, type: 'commandExecution', text: preview, command: e.item.type === 'commandExecution' ? '工具执行' : e.item.type, aggregatedOutput: preview };
|
|
40
43
|
return { id: e.turnId, status: 'recorded', items: [item] };
|
|
41
44
|
}) };
|
|
42
45
|
}
|
package/dist/platform/macos.js
CHANGED
|
@@ -153,7 +153,6 @@ export class MacOsAdapter extends HostAdapter {
|
|
|
153
153
|
discover: async () => {
|
|
154
154
|
const binary = '/Applications/Antigravity.app/Contents/Resources/bin/language_server';
|
|
155
155
|
const { stdout: version } = await exec('/usr/libexec/PlistBuddy', ['-c', 'Print :CFBundleShortVersionString', '/Applications/Antigravity.app/Contents/Info.plist']);
|
|
156
|
-
requireValue(['2.29.0', '2.31.0'].includes(version.trim()), 'PROTOCOL_INCOMPATIBLE', '当前适配 Antigravity App 2.29.0、2.31.0,请核对桌面版本', 503);
|
|
157
156
|
const { stdout } = await exec('/bin/ps', ['-axo', 'uid,pid,ppid,command'], { maxBuffer: 4 * 1024 * 1024 });
|
|
158
157
|
const rows = stdout.split('\n').flatMap(line => {
|
|
159
158
|
const match = /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/.exec(line);
|
package/dist/platform/windows.js
CHANGED
|
@@ -259,8 +259,7 @@ export class WindowsAdapter extends HostAdapter {
|
|
|
259
259
|
requireValue(resolve(parent.path).toLowerCase() === resolve(application).toLowerCase(), 'BACKEND_UNAVAILABLE', '无法核实 Antigravity LS 的桌面父进程', 503);
|
|
260
260
|
await trustedWindowsExecutable(parent.path);
|
|
261
261
|
const version = await windowsCommand(`(Get-Item -LiteralPath $d.path).VersionInfo.FileVersion|ConvertTo-Json -Compress`, { path: parent.path });
|
|
262
|
-
|
|
263
|
-
return { pid: desktop.pid, ports: desktop.ports, token: desktop.token };
|
|
262
|
+
return { pid: desktop.pid, ports: desktop.ports, token: desktop.token, version: typeof version === 'string' ? version : undefined };
|
|
264
263
|
},
|
|
265
264
|
diff: async (path, original, modified) => {
|
|
266
265
|
const root = join(this.gatewayHome, 'diff');
|