docs-combiner 0.2.2 → 1.0.0
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/agentApi/agentControlClaim.js +26 -0
- package/dist/agentApi/approachMatrixView.js +19 -0
- package/dist/agentApi/capabilitiesMeta.js +78 -0
- package/dist/agentApi/catalogUrlPresets.js +26 -0
- package/dist/agentApi/constants.js +11 -0
- package/dist/agentApi/creativeSelections.js +25 -0
- package/dist/agentApi/escalation.js +221 -0
- package/dist/agentApi/generatedPairsGuard.js +85 -0
- package/dist/agentApi/httpHelpers.js +77 -0
- package/dist/agentApi/imagesReadiness.js +60 -0
- package/dist/agentApi/jobStatus.js +113 -0
- package/dist/agentApi/productImageDrive.js +39 -0
- package/dist/agentApi/regenerateImages.js +125 -0
- package/dist/agentApi/rendererTypes.js +3 -0
- package/dist/agentApi/routes.js +440 -0
- package/dist/agentApi/sessionSnapshot.js +82 -0
- package/dist/agentApi/sessionTypes.js +2 -0
- package/dist/agentApi/spec.js +1045 -0
- package/dist/agentApi/types.js +2 -0
- package/dist/agentApi/validation.js +32 -0
- package/dist/campaignsCsv.js +420 -0
- package/dist/contentPairs.js +62 -0
- package/dist/flexcardBalance.js +88 -0
- package/dist/integrations/driveApi.js +420 -0
- package/dist/integrations/httpTimeout.js +116 -0
- package/dist/integrations/openrouter.js +532 -0
- package/dist/main.js +830 -165
- package/dist/models.js +17 -0
- package/dist/offerSettings.js +19 -0
- package/dist/preload.js +28 -0
- package/dist/promptOverrides.js +437 -0
- package/dist/prompts.js +1243 -0
- package/dist/renderer.js +19 -19
- package/dist/renderer.js.LICENSE.txt +4 -0
- package/dist/renderer.js.map +1 -1
- package/dist/server/app.js +378 -0
- package/dist/server/auth.js +74 -0
- package/dist/server/contentJobs.js +367 -0
- package/dist/server/driveCatalog.js +122 -0
- package/dist/server/driveProxy.js +220 -0
- package/dist/server/flexcardMeta.js +29 -0
- package/dist/server/googleAuth.js +84 -0
- package/dist/server/imageAssets.js +87 -0
- package/dist/server/imageJobs.js +776 -0
- package/dist/server/index.js +38 -0
- package/dist/server/jobEvents.js +116 -0
- package/dist/server/jobs.js +358 -0
- package/dist/server/openRouterMeta.js +58 -0
- package/dist/server/spec.js +544 -0
- package/dist/server/storage.js +133 -0
- package/dist/server/telegram.js +53 -0
- package/dist/server/workspaceSnapshot.js +273 -0
- package/package.json +18 -4
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.sendServerTelegramMessage = sendServerTelegramMessage;
|
|
13
|
+
function badRequest(message) {
|
|
14
|
+
const err = new Error(message);
|
|
15
|
+
err.status = 400;
|
|
16
|
+
return err;
|
|
17
|
+
}
|
|
18
|
+
function sendTelegramMessageViaBot(botToken, chatId, text) {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
const apiUrl = `https://api.telegram.org/bot${encodeURIComponent(botToken)}/sendMessage`;
|
|
21
|
+
const safeText = text.length > 4096 ? `${text.slice(0, 4090)}...` : text;
|
|
22
|
+
const res = yield fetch(apiUrl, {
|
|
23
|
+
method: 'POST',
|
|
24
|
+
headers: { 'Content-Type': 'application/json' },
|
|
25
|
+
body: JSON.stringify({
|
|
26
|
+
chat_id: chatId,
|
|
27
|
+
text: safeText,
|
|
28
|
+
disable_web_page_preview: true,
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
const body = yield res.json().catch(() => ({}));
|
|
32
|
+
if (!res.ok || (body === null || body === void 0 ? void 0 : body.ok) === false) {
|
|
33
|
+
const err = new Error((body === null || body === void 0 ? void 0 : body.description) || (body === null || body === void 0 ? void 0 : body.error) || `Telegram HTTP ${res.status}`);
|
|
34
|
+
err.status = res.status >= 400 ? res.status : 502;
|
|
35
|
+
throw err;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function sendServerTelegramMessage(store, text) {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
var _a, _b;
|
|
42
|
+
const config = yield store.readConfig();
|
|
43
|
+
const botToken = (_a = config.telegramBotToken) === null || _a === void 0 ? void 0 : _a.trim();
|
|
44
|
+
const chatId = (_b = config.telegramChatId) === null || _b === void 0 ? void 0 : _b.trim();
|
|
45
|
+
const message = text.trim();
|
|
46
|
+
if (!botToken || !chatId)
|
|
47
|
+
throw badRequest('telegramBotToken/telegramChatId are not configured on the server.');
|
|
48
|
+
if (!message)
|
|
49
|
+
throw badRequest('text is required.');
|
|
50
|
+
yield sendTelegramMessageViaBot(botToken, chatId, message);
|
|
51
|
+
return { ok: true };
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getWorkspaceSnapshot = getWorkspaceSnapshot;
|
|
13
|
+
const campaignsCsv_1 = require("../campaignsCsv");
|
|
14
|
+
const offerSettings_1 = require("../offerSettings");
|
|
15
|
+
const productImageDrive_1 = require("../agentApi/productImageDrive");
|
|
16
|
+
const driveApi_1 = require("../integrations/driveApi");
|
|
17
|
+
const googleAuth_1 = require("./googleAuth");
|
|
18
|
+
const PROJECT_SETTINGS_FILENAME = 'project-settings.json';
|
|
19
|
+
const LEGACY_PROJECT_SETTINGS_FILENAME = 'temp-generated-content.json';
|
|
20
|
+
class DriveApiError extends Error {
|
|
21
|
+
constructor(status, message) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.status = status;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
class BadRequestError extends Error {
|
|
27
|
+
constructor() {
|
|
28
|
+
super(...arguments);
|
|
29
|
+
this.status = 400;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function escapeDriveQueryString(value) {
|
|
33
|
+
return value.replace(/'/g, "\\'");
|
|
34
|
+
}
|
|
35
|
+
function normalizeDriveFiles(files) {
|
|
36
|
+
return (Array.isArray(files) ? files : [])
|
|
37
|
+
.map((file) => ({
|
|
38
|
+
id: String((file === null || file === void 0 ? void 0 : file.id) || '').trim(),
|
|
39
|
+
name: String((file === null || file === void 0 ? void 0 : file.name) || '').trim(),
|
|
40
|
+
}))
|
|
41
|
+
.filter(file => file.id && file.name)
|
|
42
|
+
.sort((a, b) => a.name.localeCompare(b.name, 'ru'));
|
|
43
|
+
}
|
|
44
|
+
function listFilesByQuery(token_1, q_1) {
|
|
45
|
+
return __awaiter(this, arguments, void 0, function* (token, q, fields = 'files(id,name)') {
|
|
46
|
+
const response = yield (0, driveApi_1.driveListFiles)(token, q, fields, { supportsAllDrives: true, pageSize: 200 });
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
const text = yield response.text().catch(() => '');
|
|
49
|
+
throw new DriveApiError(response.status, text || `Drive list failed (${response.status})`);
|
|
50
|
+
}
|
|
51
|
+
const data = yield response.json();
|
|
52
|
+
return normalizeDriveFiles(data.files);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function findNamedFileInFolder(token, parentFolderId, fileName) {
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
const q = `'${parentFolderId}' in parents and trashed = false and name = '${escapeDriveQueryString(fileName)}' and mimeType != 'application/vnd.google-apps.folder'`;
|
|
58
|
+
return (yield listFilesByQuery(token, q))[0] || null;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function findSettingsFileInFolder(token, folderId) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
for (const fileName of [PROJECT_SETTINGS_FILENAME, LEGACY_PROJECT_SETTINGS_FILENAME]) {
|
|
64
|
+
const file = yield findNamedFileInFolder(token, folderId, fileName);
|
|
65
|
+
if (file)
|
|
66
|
+
return file;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function findLegacyEnvFolderIds(token, folderId) {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
const q = `'${folderId}' in parents and trashed = false and name = 'env' and mimeType = 'application/vnd.google-apps.folder'`;
|
|
74
|
+
return (yield listFilesByQuery(token, q)).map(file => file.id);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function findSettingsFileInWorkspace(token, workspaceId) {
|
|
78
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
const rootFile = yield findSettingsFileInFolder(token, workspaceId);
|
|
80
|
+
if (rootFile)
|
|
81
|
+
return { file: rootFile, location: 'root' };
|
|
82
|
+
for (const envFolderId of yield findLegacyEnvFolderIds(token, workspaceId)) {
|
|
83
|
+
const legacyFile = yield findSettingsFileInFolder(token, envFolderId);
|
|
84
|
+
if (legacyFile)
|
|
85
|
+
return { file: legacyFile, location: 'legacy-env' };
|
|
86
|
+
}
|
|
87
|
+
return { file: null, location: null };
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function downloadTextFile(token, fileId) {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
const response = yield (0, driveApi_1.driveDownloadFile)(token, fileId);
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
const text = yield response.text().catch(() => '');
|
|
95
|
+
throw new DriveApiError(response.status, text || `Drive download failed (${response.status})`);
|
|
96
|
+
}
|
|
97
|
+
return response.text();
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function getFolderMetadata(token, folderId) {
|
|
101
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
+
const response = yield (0, driveApi_1.driveGetFileMetadata)(token, folderId, 'name,parents', { supportsAllDrives: true });
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
const text = yield response.text().catch(() => '');
|
|
105
|
+
throw new DriveApiError(response.status, text || `Drive folder metadata failed (${response.status})`);
|
|
106
|
+
}
|
|
107
|
+
const data = yield response.json();
|
|
108
|
+
const name = typeof (data === null || data === void 0 ? void 0 : data.name) === 'string' ? data.name.trim() : '';
|
|
109
|
+
const parents = Array.isArray(data === null || data === void 0 ? void 0 : data.parents) ? data.parents.filter((id) => typeof id === 'string') : [];
|
|
110
|
+
let parentName = '';
|
|
111
|
+
if (parents[0]) {
|
|
112
|
+
const parentResponse = yield (0, driveApi_1.driveGetFileMetadata)(token, parents[0], 'name', { supportsAllDrives: true });
|
|
113
|
+
if (parentResponse.ok) {
|
|
114
|
+
const parentData = yield parentResponse.json();
|
|
115
|
+
parentName = typeof (parentData === null || parentData === void 0 ? void 0 : parentData.name) === 'string' ? parentData.name.trim() : '';
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
id: folderId,
|
|
120
|
+
name,
|
|
121
|
+
parents,
|
|
122
|
+
parentName,
|
|
123
|
+
displayPath: parentName && name ? `${parentName}/${name}` : name,
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function loadCampaignsCsvRows(token, offersRootFolderId) {
|
|
128
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
129
|
+
if (!offersRootFolderId)
|
|
130
|
+
return { hasFile: false, fileId: null, rows: [], errors: [] };
|
|
131
|
+
const file = yield findNamedFileInFolder(token, offersRootFolderId, 'campaigns.csv');
|
|
132
|
+
if (!file)
|
|
133
|
+
return { hasFile: false, fileId: null, rows: [], errors: [] };
|
|
134
|
+
const parsed = (0, campaignsCsv_1.parseCampaignsCsvText)(yield downloadTextFile(token, file.id));
|
|
135
|
+
return { hasFile: true, fileId: file.id, rows: parsed.rows, errors: parsed.errors };
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function findChildFolderByName(token, parentFolderId, folderName) {
|
|
139
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
140
|
+
if (!parentFolderId || !(folderName === null || folderName === void 0 ? void 0 : folderName.trim()))
|
|
141
|
+
return null;
|
|
142
|
+
const q = `'${parentFolderId}' in parents and trashed = false and mimeType = 'application/vnd.google-apps.folder' and name = '${escapeDriveQueryString(folderName.trim())}'`;
|
|
143
|
+
return (yield listFilesByQuery(token, q))[0] || null;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function listImageFiles(token, folderId) {
|
|
147
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
148
|
+
const q = `'${folderId}' in parents and trashed = false and mimeType contains 'image/'`;
|
|
149
|
+
return (yield listFilesByQuery(token, q)).map(file => ({ id: file.id, name: file.name }));
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function loadOfferSettings(token, offerFolderId) {
|
|
153
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
if (!offerFolderId) {
|
|
155
|
+
return {
|
|
156
|
+
hasFile: false,
|
|
157
|
+
fileId: null,
|
|
158
|
+
fields: { generateProduct: '', generateAdditionalInfo: '' },
|
|
159
|
+
parseError: null,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
const file = yield findNamedFileInFolder(token, offerFolderId, offerSettings_1.OFFER_SETTINGS_FILENAME);
|
|
163
|
+
if (!file) {
|
|
164
|
+
return {
|
|
165
|
+
hasFile: false,
|
|
166
|
+
fileId: null,
|
|
167
|
+
fields: { generateProduct: '', generateAdditionalInfo: '' },
|
|
168
|
+
parseError: null,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
return {
|
|
173
|
+
hasFile: true,
|
|
174
|
+
fileId: file.id,
|
|
175
|
+
fields: (0, offerSettings_1.parseOfferSettingsData)(JSON.parse(yield downloadTextFile(token, file.id))),
|
|
176
|
+
parseError: null,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
return {
|
|
181
|
+
hasFile: true,
|
|
182
|
+
fileId: file.id,
|
|
183
|
+
fields: { generateProduct: '', generateAdditionalInfo: '' },
|
|
184
|
+
parseError: err instanceof Error ? err.message : String(err),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
function getWorkspaceSnapshot(store, workspaceId) {
|
|
190
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
191
|
+
const cleanWorkspaceId = workspaceId.trim();
|
|
192
|
+
if (!cleanWorkspaceId)
|
|
193
|
+
throw new BadRequestError('workspaceId is required.');
|
|
194
|
+
return (yield (0, googleAuth_1.withGoogleAccessTokenRetry)(store, (token) => __awaiter(this, void 0, void 0, function* () {
|
|
195
|
+
var _a, _b, _c, _d, _e;
|
|
196
|
+
const settings = yield store.readSettings();
|
|
197
|
+
const offersRootFolderId = (_b = (_a = settings.driveRoots) === null || _a === void 0 ? void 0 : _a.offersRootFolderId) === null || _b === void 0 ? void 0 : _b.trim();
|
|
198
|
+
const workspace = yield getFolderMetadata(token, cleanWorkspaceId);
|
|
199
|
+
const settingsFile = yield findSettingsFileInWorkspace(token, cleanWorkspaceId);
|
|
200
|
+
let projectSettingsData = null;
|
|
201
|
+
let projectSettingsParseError = null;
|
|
202
|
+
if (settingsFile.file) {
|
|
203
|
+
try {
|
|
204
|
+
projectSettingsData = JSON.parse(yield downloadTextFile(token, settingsFile.file.id));
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
projectSettingsParseError = err instanceof Error ? err.message : String(err);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const campaignsCsv = yield loadCampaignsCsvRows(token, offersRootFolderId);
|
|
211
|
+
const campaignRow = (0, campaignsCsv_1.findCampaignRowForFolder)(campaignsCsv.rows, {
|
|
212
|
+
folderId: workspace.id,
|
|
213
|
+
folderName: workspace.name,
|
|
214
|
+
displayPath: workspace.displayPath,
|
|
215
|
+
});
|
|
216
|
+
const offerName = (_c = campaignRow === null || campaignRow === void 0 ? void 0 : campaignRow.offer) !== null && _c !== void 0 ? _c : null;
|
|
217
|
+
const offerFolder = yield findChildFolderByName(token, offersRootFolderId, offerName);
|
|
218
|
+
const offerSettings = yield loadOfferSettings(token, (offerFolder === null || offerFolder === void 0 ? void 0 : offerFolder.id) || null);
|
|
219
|
+
const workspaceImages = yield listImageFiles(token, workspace.id);
|
|
220
|
+
const workspaceProduct = (0, productImageDrive_1.pickWorkspaceProductFile)(workspaceImages);
|
|
221
|
+
const offerImages = offerFolder ? yield listImageFiles(token, offerFolder.id) : [];
|
|
222
|
+
const offerProduct = offerFolder ? (0, productImageDrive_1.resolveOfferFolderProductFromImageFiles)(offerImages) : null;
|
|
223
|
+
let productSource = null;
|
|
224
|
+
let productFile = null;
|
|
225
|
+
if (workspaceProduct) {
|
|
226
|
+
productSource = 'workspace';
|
|
227
|
+
productFile = workspaceProduct;
|
|
228
|
+
}
|
|
229
|
+
else if (offerProduct === null || offerProduct === void 0 ? void 0 : offerProduct.ok) {
|
|
230
|
+
productSource = 'offer';
|
|
231
|
+
productFile = offerProduct.file;
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
status: 200,
|
|
235
|
+
value: {
|
|
236
|
+
ok: true,
|
|
237
|
+
workspace,
|
|
238
|
+
projectSettings: {
|
|
239
|
+
hasFile: Boolean(settingsFile.file),
|
|
240
|
+
fileId: ((_d = settingsFile.file) === null || _d === void 0 ? void 0 : _d.id) || null,
|
|
241
|
+
fileName: ((_e = settingsFile.file) === null || _e === void 0 ? void 0 : _e.name) || null,
|
|
242
|
+
location: settingsFile.location,
|
|
243
|
+
data: projectSettingsData,
|
|
244
|
+
parseError: projectSettingsParseError,
|
|
245
|
+
},
|
|
246
|
+
campaign: {
|
|
247
|
+
csv: {
|
|
248
|
+
hasFile: campaignsCsv.hasFile,
|
|
249
|
+
fileId: campaignsCsv.fileId,
|
|
250
|
+
errors: campaignsCsv.errors,
|
|
251
|
+
},
|
|
252
|
+
row: campaignRow,
|
|
253
|
+
offer: offerName,
|
|
254
|
+
},
|
|
255
|
+
offer: {
|
|
256
|
+
name: offerName,
|
|
257
|
+
folderId: (offerFolder === null || offerFolder === void 0 ? void 0 : offerFolder.id) || null,
|
|
258
|
+
settings: offerSettings,
|
|
259
|
+
},
|
|
260
|
+
productImage: {
|
|
261
|
+
source: productSource,
|
|
262
|
+
file: productFile,
|
|
263
|
+
workspaceHasProduct: Boolean(workspaceProduct),
|
|
264
|
+
workspaceImageCount: workspaceImages.length,
|
|
265
|
+
offerImageCount: offerImages.length,
|
|
266
|
+
offerError: offerProduct && !offerProduct.ok ? offerProduct.code : null,
|
|
267
|
+
offerFileNames: offerProduct && !offerProduct.ok ? offerProduct.files.map(file => file.name) : [],
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
}))).value;
|
|
272
|
+
});
|
|
273
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docs-combiner",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Combine titles, texts, and images into a product feed table",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"bin": {
|
|
@@ -15,11 +15,19 @@
|
|
|
15
15
|
"start:dev": "npm run build:dev && electron .",
|
|
16
16
|
"build": "webpack --config webpack.config.js && tsc",
|
|
17
17
|
"build:dev": "webpack --config webpack.config.js --mode development && tsc",
|
|
18
|
+
"build:server": "tsc -p tsconfig.server.json",
|
|
19
|
+
"start:server": "node dist/server/index.js",
|
|
18
20
|
"prepublishOnly": "npm run build",
|
|
19
21
|
"dist": "npm run build && electron-builder",
|
|
20
22
|
"dist:win": "npm run build && electron-builder --win",
|
|
21
23
|
"dist:mac": "npm run build && electron-builder --mac",
|
|
22
|
-
"dist:linux": "npm run build && electron-builder --linux"
|
|
24
|
+
"dist:linux": "npm run build && electron-builder --linux",
|
|
25
|
+
"agent-api:smoke": "node scripts/agent-api-smoke.mjs",
|
|
26
|
+
"agent-api:smoke:drive": "DOCS_COMBINER_SMOKE_DRIVE=1 node scripts/agent-api-smoke.mjs",
|
|
27
|
+
"agent-api:mcp": "node scripts/agent-api-mcp.mjs",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"test:watch": "vitest",
|
|
30
|
+
"lint": "eslint src"
|
|
23
31
|
},
|
|
24
32
|
"build": {
|
|
25
33
|
"appId": "com.docs-combiner.app",
|
|
@@ -55,27 +63,33 @@
|
|
|
55
63
|
"author": "",
|
|
56
64
|
"license": "ISC",
|
|
57
65
|
"devDependencies": {
|
|
66
|
+
"@types/express": "^5.0.6",
|
|
58
67
|
"@types/react": "^19.2.7",
|
|
59
68
|
"@types/react-dom": "^19.2.3",
|
|
69
|
+
"@types/ws": "^8.18.1",
|
|
70
|
+
"@typescript-eslint/parser": "^8.63.0",
|
|
60
71
|
"css-loader": "^7.1.2",
|
|
61
72
|
"electron-builder": "^25.1.8",
|
|
73
|
+
"eslint": "^10.7.0",
|
|
62
74
|
"html-webpack-plugin": "^5.6.5",
|
|
63
75
|
"style-loader": "^4.0.0",
|
|
64
76
|
"ts-loader": "^9.5.4",
|
|
65
77
|
"typescript": "^5.0.0",
|
|
78
|
+
"vitest": "^4.1.7",
|
|
66
79
|
"webpack": "^5.103.0",
|
|
67
80
|
"webpack-cli": "^6.0.1"
|
|
68
81
|
},
|
|
69
82
|
"dependencies": {
|
|
70
|
-
"electron": "^28.0.0",
|
|
71
83
|
"@emotion/react": "^11.14.0",
|
|
72
84
|
"@emotion/styled": "^11.14.1",
|
|
73
85
|
"@mui/icons-material": "^7.3.5",
|
|
74
86
|
"@mui/material": "^7.3.5",
|
|
75
87
|
"cross-spawn": "^7.0.6",
|
|
76
|
-
"
|
|
88
|
+
"electron": "^28.0.0",
|
|
89
|
+
"express": "^5.2.1",
|
|
77
90
|
"react": "^19.2.0",
|
|
78
91
|
"react-dom": "^19.2.0",
|
|
92
|
+
"ws": "^8.21.0",
|
|
79
93
|
"xlsx": "^0.18.5"
|
|
80
94
|
}
|
|
81
95
|
}
|