@lightcone-ai/daemon 0.14.10 → 0.14.12
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/package.json +1 -1
- package/src/publish-job-runner.js +81 -34
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@ import { KuaishouAdapter } from '../mcp-servers/publisher/adapters/kuaishou.js';
|
|
|
7
7
|
import { callOfficialTool } from '../mcp-servers/publisher/official-tool-client.js';
|
|
8
8
|
import { runPublishPrecheck } from '../mcp-servers/publisher/precheck.js';
|
|
9
9
|
import { withProfileLock } from './profile-lock.js';
|
|
10
|
+
import { profileDir as getBrowserProfileDir } from './browser-login.js';
|
|
10
11
|
|
|
11
12
|
const PLATFORM_ENV_KEYS = {
|
|
12
13
|
xhs: 'XHS_PROFILE_DIR',
|
|
@@ -36,10 +37,53 @@ function asObject(value) {
|
|
|
36
37
|
return {};
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
function
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
export function resolveProfileDir(platform, { ownerId } = {}) {
|
|
41
|
+
const envKey = PLATFORM_ENV_KEYS[platform];
|
|
42
|
+
const envValue = normalizeText(envKey ? process.env[envKey] : null);
|
|
43
|
+
if (envValue) {
|
|
44
|
+
return {
|
|
45
|
+
profileDir: envValue,
|
|
46
|
+
source: 'env',
|
|
47
|
+
envKey,
|
|
48
|
+
ownerId: normalizeText(ownerId),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const normalizedOwnerId = normalizeText(ownerId);
|
|
53
|
+
if (normalizedOwnerId) {
|
|
54
|
+
return {
|
|
55
|
+
profileDir: getBrowserProfileDir(platform, normalizedOwnerId),
|
|
56
|
+
source: 'owner',
|
|
57
|
+
envKey,
|
|
58
|
+
ownerId: normalizedOwnerId,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
profileDir: null,
|
|
64
|
+
source: 'missing_owner',
|
|
65
|
+
envKey,
|
|
66
|
+
ownerId: null,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function resolveExistingProfileDir(platform, { ownerId } = {}) {
|
|
71
|
+
const resolved = resolveProfileDir(platform, { ownerId });
|
|
72
|
+
if (!resolved.profileDir) {
|
|
73
|
+
throw new Error('publish:job missing owner_id; server must include it for cross-machine profile resolution');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!existsSync(resolved.profileDir)) {
|
|
77
|
+
if (resolved.source === 'env') {
|
|
78
|
+
throw new Error(`Profile dir from ${resolved.envKey} not found: ${resolved.profileDir}`);
|
|
79
|
+
}
|
|
80
|
+
throw new Error(
|
|
81
|
+
`Profile dir for ${platform} not found at ${resolved.profileDir}; ` +
|
|
82
|
+
'user must complete browser-login on this machine first'
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return resolved.profileDir;
|
|
43
87
|
}
|
|
44
88
|
|
|
45
89
|
function getAdapterClass(platform) {
|
|
@@ -53,22 +97,16 @@ function createStaticAdapter(platform) {
|
|
|
53
97
|
return new AdapterClass(null);
|
|
54
98
|
}
|
|
55
99
|
|
|
56
|
-
async function getAdapter(platform) {
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
throw new Error(`No profile dir for platform="${platform}". Has the user logged in and authorized this machine?`);
|
|
60
|
-
}
|
|
61
|
-
const cdp = await getSession(platform, profileDir);
|
|
100
|
+
async function getAdapter(platform, { ownerId } = {}) {
|
|
101
|
+
const resolvedProfileDir = resolveExistingProfileDir(platform, { ownerId });
|
|
102
|
+
const cdp = await getSession(platform, resolvedProfileDir);
|
|
62
103
|
const AdapterClass = getAdapterClass(platform);
|
|
63
104
|
return new AdapterClass(cdp);
|
|
64
105
|
}
|
|
65
106
|
|
|
66
|
-
async function withPublisherProfile(platform, fn) {
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
throw new Error(`No profile dir for platform="${platform}". Has the user logged in and authorized this machine?`);
|
|
70
|
-
}
|
|
71
|
-
return withProfileLock(platform, profileDir, {
|
|
107
|
+
async function withPublisherProfile(platform, { ownerId } = {}, fn) {
|
|
108
|
+
const resolvedProfileDir = resolveExistingProfileDir(platform, { ownerId });
|
|
109
|
+
return withProfileLock(platform, resolvedProfileDir, {
|
|
72
110
|
owner: `publisher:${platform}`,
|
|
73
111
|
timeoutMs: 30_000,
|
|
74
112
|
staleMs: 20 * 60 * 1000,
|
|
@@ -92,19 +130,20 @@ function decodeWorkspaceContent(content) {
|
|
|
92
130
|
return Buffer.from(decodeURIComponent(body), 'utf8');
|
|
93
131
|
}
|
|
94
132
|
|
|
95
|
-
async function
|
|
96
|
-
const
|
|
133
|
+
export async function fetchPublishJobWorkspaceFile({ serverUrl, machineApiKey, jobId, relPath }) {
|
|
134
|
+
const normalizedJobId = String(jobId ?? '').trim();
|
|
135
|
+
if (!normalizedJobId) {
|
|
136
|
+
throw new Error('publish job id is required to fetch workspace files');
|
|
137
|
+
}
|
|
138
|
+
const url = `${String(serverUrl).replace(/\/$/, '')}/internal/agent/publish-jobs/${encodeURIComponent(normalizedJobId)}/workspace-files?path=${encodeURIComponent(relPath)}`;
|
|
97
139
|
const res = await fetch(url, {
|
|
98
|
-
method,
|
|
99
140
|
headers: {
|
|
100
|
-
'Content-Type': 'application/json',
|
|
101
141
|
Authorization: `Bearer ${machineApiKey}`,
|
|
102
142
|
},
|
|
103
|
-
body: body != null ? JSON.stringify(body) : undefined,
|
|
104
143
|
});
|
|
105
144
|
if (!res.ok) {
|
|
106
145
|
const text = await res.text();
|
|
107
|
-
throw new Error(`
|
|
146
|
+
throw new Error(`publish-jobs workspace-files GET failed (${res.status}): ${text}`);
|
|
108
147
|
}
|
|
109
148
|
return res.json();
|
|
110
149
|
}
|
|
@@ -135,7 +174,15 @@ export function workspacePathFromMediaPath(filePath, workspaceId) {
|
|
|
135
174
|
return null;
|
|
136
175
|
}
|
|
137
176
|
|
|
138
|
-
async function materializeWorkspaceMedia({
|
|
177
|
+
export async function materializeWorkspaceMedia({
|
|
178
|
+
filePath,
|
|
179
|
+
workspaceId,
|
|
180
|
+
workspaceRootDir,
|
|
181
|
+
serverUrl,
|
|
182
|
+
machineApiKey,
|
|
183
|
+
jobId,
|
|
184
|
+
fetchWorkspaceFile = fetchPublishJobWorkspaceFile,
|
|
185
|
+
}) {
|
|
139
186
|
if (!filePath || existsSync(filePath)) return filePath;
|
|
140
187
|
|
|
141
188
|
const workspacePath = workspacePathFromMediaPath(filePath, workspaceId);
|
|
@@ -149,12 +196,11 @@ async function materializeWorkspaceMedia({ filePath, workspaceId, workspaceRootD
|
|
|
149
196
|
|
|
150
197
|
if (existsSync(localPath)) return localPath;
|
|
151
198
|
|
|
152
|
-
const data = await
|
|
199
|
+
const data = await fetchWorkspaceFile({
|
|
153
200
|
serverUrl,
|
|
154
201
|
machineApiKey,
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
endpoint: `/workspace-memory?path=${encodeURIComponent(workspacePath.relPath)}&workspaceId=${encodeURIComponent(workspacePath.workspaceId)}`,
|
|
202
|
+
jobId,
|
|
203
|
+
relPath: workspacePath.relPath,
|
|
158
204
|
});
|
|
159
205
|
mkdirSync(path.dirname(localPath), { recursive: true });
|
|
160
206
|
writeFileSync(localPath, decodeWorkspaceContent(data.content));
|
|
@@ -169,7 +215,7 @@ async function materializeMedia({
|
|
|
169
215
|
workspaceRootDir,
|
|
170
216
|
serverUrl,
|
|
171
217
|
machineApiKey,
|
|
172
|
-
|
|
218
|
+
jobId,
|
|
173
219
|
}) {
|
|
174
220
|
return {
|
|
175
221
|
images: await Promise.all(images.map(filePath => materializeWorkspaceMedia({
|
|
@@ -178,7 +224,7 @@ async function materializeMedia({
|
|
|
178
224
|
workspaceRootDir,
|
|
179
225
|
serverUrl,
|
|
180
226
|
machineApiKey,
|
|
181
|
-
|
|
227
|
+
jobId,
|
|
182
228
|
}))),
|
|
183
229
|
video: video ? await materializeWorkspaceMedia({
|
|
184
230
|
filePath: video,
|
|
@@ -186,7 +232,7 @@ async function materializeMedia({
|
|
|
186
232
|
workspaceRootDir,
|
|
187
233
|
serverUrl,
|
|
188
234
|
machineApiKey,
|
|
189
|
-
|
|
235
|
+
jobId,
|
|
190
236
|
}) : video,
|
|
191
237
|
cover: cover ? await materializeWorkspaceMedia({
|
|
192
238
|
filePath: cover,
|
|
@@ -194,7 +240,7 @@ async function materializeMedia({
|
|
|
194
240
|
workspaceRootDir,
|
|
195
241
|
serverUrl,
|
|
196
242
|
machineApiKey,
|
|
197
|
-
|
|
243
|
+
jobId,
|
|
198
244
|
}) : cover,
|
|
199
245
|
};
|
|
200
246
|
}
|
|
@@ -360,6 +406,7 @@ export async function runPublishJob({ serverUrl, machineApiKey, agentId, workspa
|
|
|
360
406
|
video,
|
|
361
407
|
cover,
|
|
362
408
|
} = buildJobInput(job);
|
|
409
|
+
const ownerId = normalizeText(job?.owner_id ?? job?.ownerId);
|
|
363
410
|
|
|
364
411
|
if (!platform) throw new Error('publish job missing platform');
|
|
365
412
|
if (!contentType) throw new Error('publish job missing content_type');
|
|
@@ -404,7 +451,7 @@ export async function runPublishJob({ serverUrl, machineApiKey, agentId, workspa
|
|
|
404
451
|
workspaceRootDir,
|
|
405
452
|
serverUrl,
|
|
406
453
|
machineApiKey,
|
|
407
|
-
|
|
454
|
+
jobId: job?.id,
|
|
408
455
|
});
|
|
409
456
|
const staticAdapter = createStaticAdapter(platform);
|
|
410
457
|
const req = staticAdapter.getRequirements(contentType);
|
|
@@ -420,8 +467,8 @@ export async function runPublishJob({ serverUrl, machineApiKey, agentId, workspa
|
|
|
420
467
|
});
|
|
421
468
|
|
|
422
469
|
try {
|
|
423
|
-
const { publishResult, healthCheck } = await withPublisherProfile(platform, async () => {
|
|
424
|
-
const adapter = await getAdapter(platform);
|
|
470
|
+
const { publishResult, healthCheck } = await withPublisherProfile(platform, { ownerId }, async () => {
|
|
471
|
+
const adapter = await getAdapter(platform, { ownerId });
|
|
425
472
|
const prePublishLogin = await adapter.checkLoginStatus();
|
|
426
473
|
if (prePublishLogin?.loggedIn === false) {
|
|
427
474
|
throw new Error(`LOGIN_EXPIRED:${platform}`);
|