agentxl 1.0.0 → 1.1.2

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.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +352 -197
  3. package/bin/agentxl-folder-picker.exe +0 -0
  4. package/bin/agentxl.js +44 -8
  5. package/dist/agent/models.d.ts +9 -9
  6. package/dist/agent/models.d.ts.map +1 -1
  7. package/dist/agent/models.js +44 -8
  8. package/dist/agent/models.js.map +1 -1
  9. package/dist/agent/prompt/folder-context.d.ts +26 -0
  10. package/dist/agent/prompt/folder-context.d.ts.map +1 -0
  11. package/dist/agent/prompt/folder-context.js +105 -0
  12. package/dist/agent/prompt/folder-context.js.map +1 -0
  13. package/dist/agent/prompt/system-prompt.d.ts +21 -0
  14. package/dist/agent/prompt/system-prompt.d.ts.map +1 -0
  15. package/dist/agent/prompt/system-prompt.js +130 -0
  16. package/dist/agent/prompt/system-prompt.js.map +1 -0
  17. package/dist/agent/session.d.ts +10 -4
  18. package/dist/agent/session.d.ts.map +1 -1
  19. package/dist/agent/session.js +53 -15
  20. package/dist/agent/session.js.map +1 -1
  21. package/dist/agent/tools/excel.d.ts +24 -0
  22. package/dist/agent/tools/excel.d.ts.map +1 -0
  23. package/dist/agent/tools/excel.js +132 -0
  24. package/dist/agent/tools/excel.js.map +1 -0
  25. package/dist/server/document-converter.d.ts +71 -0
  26. package/dist/server/document-converter.d.ts.map +1 -0
  27. package/dist/server/document-converter.js +353 -0
  28. package/dist/server/document-converter.js.map +1 -0
  29. package/dist/server/excel-bridge.d.ts +38 -0
  30. package/dist/server/excel-bridge.d.ts.map +1 -0
  31. package/dist/server/excel-bridge.js +75 -0
  32. package/dist/server/excel-bridge.js.map +1 -0
  33. package/dist/server/folder-picker.d.ts +9 -0
  34. package/dist/server/folder-picker.d.ts.map +1 -0
  35. package/dist/server/folder-picker.js +204 -0
  36. package/dist/server/folder-picker.js.map +1 -0
  37. package/dist/server/folder-scanner.d.ts +43 -0
  38. package/dist/server/folder-scanner.d.ts.map +1 -0
  39. package/dist/server/folder-scanner.js +161 -0
  40. package/dist/server/folder-scanner.js.map +1 -0
  41. package/dist/server/http.d.ts +19 -0
  42. package/dist/server/http.d.ts.map +1 -0
  43. package/dist/server/http.js +62 -0
  44. package/dist/server/http.js.map +1 -0
  45. package/dist/server/index.d.ts +16 -4
  46. package/dist/server/index.d.ts.map +1 -1
  47. package/dist/server/index.js +70 -246
  48. package/dist/server/index.js.map +1 -1
  49. package/dist/server/json-store.d.ts +19 -0
  50. package/dist/server/json-store.d.ts.map +1 -0
  51. package/dist/server/json-store.js +37 -0
  52. package/dist/server/json-store.js.map +1 -0
  53. package/dist/server/routes/agent.d.ts +16 -0
  54. package/dist/server/routes/agent.d.ts.map +1 -0
  55. package/dist/server/routes/agent.js +196 -0
  56. package/dist/server/routes/agent.js.map +1 -0
  57. package/dist/server/routes/excel.d.ts +10 -0
  58. package/dist/server/routes/excel.d.ts.map +1 -0
  59. package/dist/server/routes/excel.js +41 -0
  60. package/dist/server/routes/excel.js.map +1 -0
  61. package/dist/server/routes/folder.d.ts +15 -0
  62. package/dist/server/routes/folder.d.ts.map +1 -0
  63. package/dist/server/routes/folder.js +184 -0
  64. package/dist/server/routes/folder.js.map +1 -0
  65. package/dist/server/routes/workbook.d.ts +7 -0
  66. package/dist/server/routes/workbook.d.ts.map +1 -0
  67. package/dist/server/routes/workbook.js +31 -0
  68. package/dist/server/routes/workbook.js.map +1 -0
  69. package/dist/server/static.d.ts +12 -0
  70. package/dist/server/static.d.ts.map +1 -0
  71. package/dist/server/static.js +83 -0
  72. package/dist/server/static.js.map +1 -0
  73. package/dist/server/workbook-folder-store.d.ts +24 -0
  74. package/dist/server/workbook-folder-store.d.ts.map +1 -0
  75. package/dist/server/workbook-folder-store.js +76 -0
  76. package/dist/server/workbook-folder-store.js.map +1 -0
  77. package/dist/server/workbook-identity.d.ts +8 -0
  78. package/dist/server/workbook-identity.d.ts.map +1 -0
  79. package/dist/server/workbook-identity.js +57 -0
  80. package/dist/server/workbook-identity.js.map +1 -0
  81. package/manifest/manifest-hosted.xml +107 -0
  82. package/package.json +24 -10
  83. package/taskpane/dist/assets/index-BnD8psE_.js +224 -0
  84. package/taskpane/dist/assets/index-BuAcDfRq.css +1 -0
  85. package/taskpane/dist/index.html +2 -2
  86. package/taskpane/dist/assets/index-6sMpIYxE.css +0 -1
  87. package/taskpane/dist/assets/index-DyLrQ3Aa.js +0 -164
@@ -0,0 +1,204 @@
1
+ import { execFile } from "child_process";
2
+ import { existsSync } from "fs";
3
+ import { platform } from "os";
4
+ import { dirname, extname, join } from "path";
5
+ import { fileURLToPath } from "url";
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+ function sleep(ms) {
9
+ return new Promise((resolve) => setTimeout(resolve, ms));
10
+ }
11
+ function getProjectRoot() {
12
+ return join(__dirname, "..", "..");
13
+ }
14
+ function getPickerTimeoutMs() {
15
+ const raw = process.env.AGENTXL_PICK_FOLDER_TIMEOUT_MS?.trim();
16
+ const parsed = raw ? Number(raw) : NaN;
17
+ if (Number.isFinite(parsed) && parsed > 0) {
18
+ return parsed;
19
+ }
20
+ // No timeout by default — let the user take as long as they need.
21
+ // The picker is a blocking dialog; it closes when the user picks or cancels.
22
+ return 0;
23
+ }
24
+ function toFriendlyPickerError(error) {
25
+ if (error instanceof Error) {
26
+ const execError = error;
27
+ const message = execError.message.toLowerCase();
28
+ if (execError.killed ||
29
+ execError.signal === "SIGTERM" ||
30
+ message.includes("timed out") ||
31
+ message.includes("timeout")) {
32
+ return new Error("Native folder picker timed out. Paste the folder path manually instead.");
33
+ }
34
+ return error;
35
+ }
36
+ return new Error("Failed to open native folder picker");
37
+ }
38
+ function execFileAsync(command, args, timeoutMs) {
39
+ return new Promise((resolve, reject) => {
40
+ execFile(command, args, {
41
+ windowsHide: true,
42
+ // 0 means no timeout — let the user take as long as they need.
43
+ timeout: timeoutMs > 0 ? timeoutMs : 0,
44
+ }, (error, stdout) => {
45
+ if (error) {
46
+ reject(toFriendlyPickerError(error));
47
+ return;
48
+ }
49
+ resolve(stdout.toString());
50
+ });
51
+ });
52
+ }
53
+ function getFolderPickerHelperPath() {
54
+ const override = process.env.AGENTXL_FOLDER_PICKER_HELPER?.trim();
55
+ if (override) {
56
+ return override;
57
+ }
58
+ const projectRoot = getProjectRoot();
59
+ const candidates = [
60
+ join(projectRoot, "bin", "agentxl-folder-picker.exe"),
61
+ join(projectRoot, "tools", "folder-picker-win", "bin", "Release", "net8.0-windows", "win-x64", "publish", "agentxl-folder-picker.exe"),
62
+ join(projectRoot, "tools", "folder-picker-win", "bin", "Release", "net8.0-windows", "publish", "agentxl-folder-picker.exe"),
63
+ ];
64
+ for (const candidate of candidates) {
65
+ if (existsSync(candidate)) {
66
+ return candidate;
67
+ }
68
+ }
69
+ return null;
70
+ }
71
+ function buildHelperInvocation(helperPath, initialPath) {
72
+ const helperExt = extname(helperPath).toLowerCase();
73
+ const args = [];
74
+ if (initialPath && initialPath.trim().length > 0) {
75
+ args.push("--initial-path", initialPath.trim());
76
+ }
77
+ if ([".js", ".mjs", ".cjs"].includes(helperExt)) {
78
+ return {
79
+ command: process.execPath,
80
+ args: [helperPath, ...args],
81
+ };
82
+ }
83
+ return {
84
+ command: helperPath,
85
+ args,
86
+ };
87
+ }
88
+ function parseHelperResponse(stdout) {
89
+ const trimmed = stdout.trim();
90
+ if (!trimmed) {
91
+ throw new Error("Folder picker helper returned no output");
92
+ }
93
+ const lines = trimmed
94
+ .split(/\r?\n/)
95
+ .map((line) => line.trim())
96
+ .filter(Boolean);
97
+ const candidates = Array.from(new Set([lines.at(-1) ?? trimmed, trimmed]));
98
+ for (const candidate of candidates) {
99
+ try {
100
+ const parsed = JSON.parse(candidate);
101
+ if (parsed && typeof parsed.ok === "boolean") {
102
+ return parsed;
103
+ }
104
+ }
105
+ catch {
106
+ // Try next candidate.
107
+ }
108
+ }
109
+ throw new Error("Folder picker helper returned invalid JSON");
110
+ }
111
+ async function pickLocalFolderWithHelper(helperPath, timeoutMs, initialPath) {
112
+ const invocation = buildHelperInvocation(helperPath, initialPath);
113
+ const stdout = await execFileAsync(invocation.command, invocation.args, timeoutMs);
114
+ const response = parseHelperResponse(stdout);
115
+ if (!response.ok) {
116
+ throw new Error(response.error || "Folder picker helper failed");
117
+ }
118
+ if (response.cancelled) {
119
+ return null;
120
+ }
121
+ const folderPath = typeof response.folderPath === "string" ? response.folderPath.trim() : "";
122
+ return folderPath.length > 0 ? folderPath : null;
123
+ }
124
+ async function pickLocalFolderWithPowerShell(timeoutMs) {
125
+ const script = [
126
+ "Add-Type -AssemblyName System.Windows.Forms",
127
+ "[System.Windows.Forms.Application]::EnableVisualStyles()",
128
+ "$dialog = New-Object System.Windows.Forms.FolderBrowserDialog",
129
+ "$dialog.Description = 'Choose the folder with your supporting documents'",
130
+ "$dialog.ShowNewFolderButton = $false",
131
+ "$dialog.UseDescriptionForTitle = $true",
132
+ "$dialog.RootFolder = [System.Environment+SpecialFolder]::MyDocuments",
133
+ "if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $dialog.SelectedPath }",
134
+ ].join("; ");
135
+ const stdout = await execFileAsync("powershell", ["-NoProfile", "-STA", "-Command", script], timeoutMs);
136
+ const selected = stdout.trim();
137
+ return selected.length > 0 ? selected : null;
138
+ }
139
+ /** Detect which folder picker strategy will be used at runtime. */
140
+ export function getFolderPickerStrategy() {
141
+ const currentPlatform = platform();
142
+ if (currentPlatform === "win32") {
143
+ const helperPath = getFolderPickerHelperPath();
144
+ if (helperPath) {
145
+ return { platform: "win32", method: "native-helper", helperPath };
146
+ }
147
+ return { platform: "win32", method: "powershell", helperPath: null };
148
+ }
149
+ if (currentPlatform === "darwin") {
150
+ return { platform: "darwin", method: "osascript", helperPath: null };
151
+ }
152
+ return { platform: currentPlatform, method: "manual-only", helperPath: null };
153
+ }
154
+ export async function pickLocalFolder(initialPath) {
155
+ const testDelayRaw = process.env.AGENTXL_PICK_FOLDER_TEST_DELAY_MS?.trim();
156
+ const testDelayMs = testDelayRaw ? Number(testDelayRaw) : NaN;
157
+ if (Number.isFinite(testDelayMs) && testDelayMs > 0) {
158
+ await sleep(testDelayMs);
159
+ }
160
+ const testError = process.env.AGENTXL_PICK_FOLDER_TEST_ERROR?.trim();
161
+ if (testError) {
162
+ throw new Error(testError);
163
+ }
164
+ const testPath = process.env.AGENTXL_PICK_FOLDER_TEST_PATH;
165
+ if (testPath && testPath.trim().length > 0) {
166
+ return testPath.trim();
167
+ }
168
+ const currentPlatform = platform();
169
+ const timeoutMs = getPickerTimeoutMs();
170
+ if (currentPlatform === "win32") {
171
+ const helperPath = getFolderPickerHelperPath();
172
+ if (helperPath) {
173
+ try {
174
+ return await pickLocalFolderWithHelper(helperPath, timeoutMs, initialPath);
175
+ }
176
+ catch (error) {
177
+ const helperError = error instanceof Error ? error.message : "Folder picker helper failed";
178
+ if (helperError.toLowerCase().includes("timed out")) {
179
+ throw error instanceof Error ? error : new Error(helperError);
180
+ }
181
+ try {
182
+ return await pickLocalFolderWithPowerShell(timeoutMs);
183
+ }
184
+ catch (fallbackError) {
185
+ const fallbackMessage = fallbackError instanceof Error
186
+ ? fallbackError.message
187
+ : "PowerShell folder picker fallback failed";
188
+ throw new Error(`${helperError}. PowerShell fallback also failed: ${fallbackMessage}`);
189
+ }
190
+ }
191
+ }
192
+ return pickLocalFolderWithPowerShell(timeoutMs);
193
+ }
194
+ if (currentPlatform === "darwin") {
195
+ const stdout = await execFileAsync("osascript", [
196
+ "-e",
197
+ 'POSIX path of (choose folder with prompt "Choose the folder with your supporting documents")',
198
+ ], timeoutMs);
199
+ const selected = stdout.trim();
200
+ return selected.length > 0 ? selected.replace(/\/$/, "") : null;
201
+ }
202
+ throw new Error("Native folder picker is not supported on this platform yet");
203
+ }
204
+ //# sourceMappingURL=folder-picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-picker.js","sourceRoot":"","sources":["../../src/server/folder-picker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ export interface FileEntry {
2
+ /** File name with extension, e.g. "trial-balance.pdf" */
3
+ name: string;
4
+ /** Path relative to the linked folder root, e.g. "subfolder/trial-balance.pdf" */
5
+ relativePath: string;
6
+ /** Absolute path on disk */
7
+ absolutePath: string;
8
+ /** Lowercase extension including dot, e.g. ".pdf" */
9
+ extension: string;
10
+ /** File size in bytes */
11
+ sizeBytes: number;
12
+ /** Last modified time as ISO string */
13
+ modifiedAt: string;
14
+ /** Whether this file type is supported for content extraction */
15
+ supported: boolean;
16
+ }
17
+ export interface FolderInventory {
18
+ /** The folder that was scanned */
19
+ folderPath: string;
20
+ /** When the scan was performed */
21
+ scannedAt: string;
22
+ /** Total number of files found */
23
+ totalFiles: number;
24
+ /** Number of supported files */
25
+ supportedFiles: number;
26
+ /** All discovered files */
27
+ files: FileEntry[];
28
+ }
29
+ /**
30
+ * Recursively scan a folder and build a file inventory.
31
+ *
32
+ * @param folderPath - Absolute path to the folder to scan
33
+ * @returns FolderInventory with all discovered files
34
+ * @throws Error if the folder does not exist or is not accessible
35
+ */
36
+ export declare function scanFolder(folderPath: string): FolderInventory;
37
+ /** Save a folder inventory to disk for a given workbook. */
38
+ export declare function saveInventory(workbookId: string, inventory: FolderInventory): void;
39
+ /** Load a previously saved folder inventory. Returns null if not found. */
40
+ export declare function loadInventory(workbookId: string): FolderInventory | null;
41
+ /** Scan a folder, save the inventory, and return it. */
42
+ export declare function scanAndSaveInventory(workbookId: string, folderPath: string): FolderInventory;
43
+ //# sourceMappingURL=folder-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-scanner.d.ts","sourceRoot":"","sources":["../../src/server/folder-scanner.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,SAAS;IACxB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,2BAA2B;IAC3B,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAmED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAiF9D;AAUD,4DAA4D;AAC5D,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,eAAe,GACzB,IAAI,CAGN;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAMxE;AAED,wDAAwD;AACxD,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,eAAe,CAIjB"}
@@ -0,0 +1,161 @@
1
+ import { readdirSync, statSync, existsSync } from "fs";
2
+ import { join, extname, relative, basename } from "path";
3
+ import { getAgentXLDataDir } from "./workbook-folder-store.js";
4
+ import { writeJsonFileAtomic, readJsonFile } from "./json-store.js";
5
+ // ---------------------------------------------------------------------------
6
+ // Constants
7
+ // ---------------------------------------------------------------------------
8
+ /** File extensions that AgentXL can extract content from. */
9
+ const SUPPORTED_EXTENSIONS = new Set([
10
+ ".pdf",
11
+ ".csv",
12
+ ".xlsx",
13
+ ".xls",
14
+ ".txt",
15
+ ".md",
16
+ ".json",
17
+ ".tsv",
18
+ ".docx",
19
+ ".doc",
20
+ ]);
21
+ /** Directory names to always skip. */
22
+ const IGNORED_DIRS = new Set([
23
+ "node_modules",
24
+ ".git",
25
+ ".svn",
26
+ ".hg",
27
+ "__pycache__",
28
+ ".tox",
29
+ ".venv",
30
+ "venv",
31
+ ".env",
32
+ ".idea",
33
+ ".vscode",
34
+ "$RECYCLE.BIN",
35
+ "System Volume Information",
36
+ ".DS_Store",
37
+ "Thumbs.db",
38
+ ".agentxl-cache",
39
+ ]);
40
+ /** Maximum directory depth to recurse into. */
41
+ const MAX_DEPTH = 10;
42
+ /** Maximum number of files to include in the inventory. */
43
+ const MAX_FILES = 10_000;
44
+ // ---------------------------------------------------------------------------
45
+ // Scanner
46
+ // ---------------------------------------------------------------------------
47
+ function isHidden(name) {
48
+ return name.startsWith(".") && name !== "." && name !== "..";
49
+ }
50
+ function shouldSkipDir(name) {
51
+ return IGNORED_DIRS.has(name) || isHidden(name);
52
+ }
53
+ function isSupported(ext) {
54
+ return SUPPORTED_EXTENSIONS.has(ext.toLowerCase());
55
+ }
56
+ /**
57
+ * Recursively scan a folder and build a file inventory.
58
+ *
59
+ * @param folderPath - Absolute path to the folder to scan
60
+ * @returns FolderInventory with all discovered files
61
+ * @throws Error if the folder does not exist or is not accessible
62
+ */
63
+ export function scanFolder(folderPath) {
64
+ const trimmed = folderPath.trim();
65
+ if (!trimmed) {
66
+ throw new Error("Folder path is required");
67
+ }
68
+ if (!existsSync(trimmed)) {
69
+ throw new Error(`Folder does not exist: ${trimmed}`);
70
+ }
71
+ const stat = statSync(trimmed);
72
+ if (!stat.isDirectory()) {
73
+ throw new Error(`Path is not a directory: ${trimmed}`);
74
+ }
75
+ const files = [];
76
+ function walk(dir, depth) {
77
+ if (depth > MAX_DEPTH)
78
+ return;
79
+ if (files.length >= MAX_FILES)
80
+ return;
81
+ let entries;
82
+ try {
83
+ entries = readdirSync(dir);
84
+ }
85
+ catch {
86
+ return;
87
+ }
88
+ for (const entry of entries) {
89
+ if (files.length >= MAX_FILES)
90
+ return;
91
+ const fullPath = join(dir, entry);
92
+ let entryStat;
93
+ try {
94
+ entryStat = statSync(fullPath);
95
+ }
96
+ catch {
97
+ continue;
98
+ }
99
+ if (entryStat.isDirectory()) {
100
+ if (!shouldSkipDir(entry)) {
101
+ walk(fullPath, depth + 1);
102
+ }
103
+ continue;
104
+ }
105
+ if (!entryStat.isFile())
106
+ continue;
107
+ const ext = extname(entry).toLowerCase();
108
+ if (!ext && isHidden(entry))
109
+ continue;
110
+ files.push({
111
+ name: basename(entry),
112
+ relativePath: relative(trimmed, fullPath).replace(/\\/g, "/"),
113
+ absolutePath: fullPath,
114
+ extension: ext,
115
+ sizeBytes: entryStat.size,
116
+ modifiedAt: entryStat.mtime.toISOString(),
117
+ supported: isSupported(ext),
118
+ });
119
+ }
120
+ }
121
+ walk(trimmed, 0);
122
+ // Sort files: supported first, then alphabetically by relative path
123
+ files.sort((a, b) => {
124
+ if (a.supported !== b.supported)
125
+ return a.supported ? -1 : 1;
126
+ return a.relativePath.localeCompare(b.relativePath);
127
+ });
128
+ const supportedCount = files.filter((f) => f.supported).length;
129
+ return {
130
+ folderPath: trimmed,
131
+ scannedAt: new Date().toISOString(),
132
+ totalFiles: files.length,
133
+ supportedFiles: supportedCount,
134
+ files,
135
+ };
136
+ }
137
+ // ---------------------------------------------------------------------------
138
+ // Persistence
139
+ // ---------------------------------------------------------------------------
140
+ function getInventoryPath(workbookId) {
141
+ return join(getAgentXLDataDir(), "inventories", `${workbookId}.json`);
142
+ }
143
+ /** Save a folder inventory to disk for a given workbook. */
144
+ export function saveInventory(workbookId, inventory) {
145
+ const data = { version: 1, inventory };
146
+ writeJsonFileAtomic(getInventoryPath(workbookId), data);
147
+ }
148
+ /** Load a previously saved folder inventory. Returns null if not found. */
149
+ export function loadInventory(workbookId) {
150
+ const parsed = readJsonFile(getInventoryPath(workbookId));
151
+ if (!parsed || parsed.version !== 1 || !parsed.inventory)
152
+ return null;
153
+ return parsed.inventory;
154
+ }
155
+ /** Scan a folder, save the inventory, and return it. */
156
+ export function scanAndSaveInventory(workbookId, folderPath) {
157
+ const inventory = scanFolder(folderPath);
158
+ saveInventory(workbookId, inventory);
159
+ return inventory;
160
+ }
161
+ //# sourceMappingURL=folder-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-scanner.js","sourceRoot":"","sources":["../../src/server/folder-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * HTTP helpers — JSON responses, error responses, body parsing.
3
+ *
4
+ * Shared across all route handlers. No domain logic here.
5
+ */
6
+ import { IncomingMessage, ServerResponse } from "http";
7
+ /** Send a JSON response with CORS headers. */
8
+ export declare function sendJson(res: ServerResponse, status: number, body: Record<string, unknown>): void;
9
+ /** Send a JSON error response. */
10
+ export declare function sendError(res: ServerResponse, status: number, message: string): void;
11
+ /** Read the full request body as a string. */
12
+ export declare function readBody(req: IncomingMessage): Promise<string>;
13
+ /** Parse JSON body, returning null on failure. */
14
+ export declare function parseJsonBody(req: IncomingMessage): Promise<unknown | null>;
15
+ /** Send CORS preflight response. */
16
+ export declare function sendCorsPreflightResponse(res: ServerResponse): void;
17
+ /** Send 405 Method Not Allowed for a known route. */
18
+ export declare function sendMethodNotAllowed(res: ServerResponse, method: string, allowedMethod: string): void;
19
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAEvD,8CAA8C;AAC9C,wBAAgB,QAAQ,CACtB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,IAAI,CAUN;AAED,kCAAkC;AAClC,wBAAgB,SAAS,CACvB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,IAAI,CAEN;AAED,8CAA8C;AAC9C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAO9D;AAED,kDAAkD;AAClD,wBAAsB,aAAa,CACjC,GAAG,EAAE,eAAe,GACnB,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAOzB;AAED,oCAAoC;AACpC,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAQnE;AAED,qDAAqD;AACrD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,IAAI,CAWN"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * HTTP helpers — JSON responses, error responses, body parsing.
3
+ *
4
+ * Shared across all route handlers. No domain logic here.
5
+ */
6
+ /** Send a JSON response with CORS headers. */
7
+ export function sendJson(res, status, body) {
8
+ const payload = JSON.stringify(body);
9
+ res.writeHead(status, {
10
+ "Content-Type": "application/json; charset=utf-8",
11
+ "Access-Control-Allow-Origin": "*",
12
+ "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
13
+ "Access-Control-Allow-Headers": "Content-Type",
14
+ "Content-Length": Buffer.byteLength(payload),
15
+ });
16
+ res.end(payload);
17
+ }
18
+ /** Send a JSON error response. */
19
+ export function sendError(res, status, message) {
20
+ sendJson(res, status, { error: message });
21
+ }
22
+ /** Read the full request body as a string. */
23
+ export function readBody(req) {
24
+ return new Promise((resolve, reject) => {
25
+ const chunks = [];
26
+ req.on("data", (chunk) => chunks.push(chunk));
27
+ req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
28
+ req.on("error", reject);
29
+ });
30
+ }
31
+ /** Parse JSON body, returning null on failure. */
32
+ export async function parseJsonBody(req) {
33
+ try {
34
+ const raw = await readBody(req);
35
+ return raw.length > 0 ? JSON.parse(raw) : null;
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ /** Send CORS preflight response. */
42
+ export function sendCorsPreflightResponse(res) {
43
+ res.writeHead(204, {
44
+ "Access-Control-Allow-Origin": "*",
45
+ "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
46
+ "Access-Control-Allow-Headers": "Content-Type",
47
+ "Access-Control-Max-Age": "86400",
48
+ });
49
+ res.end();
50
+ }
51
+ /** Send 405 Method Not Allowed for a known route. */
52
+ export function sendMethodNotAllowed(res, method, allowedMethod) {
53
+ res.writeHead(405, {
54
+ "Content-Type": "application/json; charset=utf-8",
55
+ "Access-Control-Allow-Origin": "*",
56
+ Allow: allowedMethod,
57
+ });
58
+ res.end(JSON.stringify({
59
+ error: `Method ${method} not allowed. Use ${allowedMethod}.`,
60
+ }));
61
+ }
62
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,8CAA8C;AAC9C,MAAM,UAAU,QAAQ,CACtB,GAAmB,EACnB,MAAc,EACd,IAA6B;IAE7B,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACrC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE;QACpB,cAAc,EAAE,iCAAiC;QACjD,6BAA6B,EAAE,GAAG;QAClC,8BAA8B,EAAE,oBAAoB;QACpD,8BAA8B,EAAE,cAAc;QAC9C,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;KAC7C,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,SAAS,CACvB,GAAmB,EACnB,MAAc,EACd,OAAe;IAEf,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,QAAQ,CAAC,GAAoB;IAC3C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACtD,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACtE,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,kDAAkD;AAClD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAoB;IAEpB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;QAChC,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,yBAAyB,CAAC,GAAmB;IAC3D,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,6BAA6B,EAAE,GAAG;QAClC,8BAA8B,EAAE,oBAAoB;QACpD,8BAA8B,EAAE,cAAc;QAC9C,wBAAwB,EAAE,OAAO;KAClC,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,oBAAoB,CAClC,GAAmB,EACnB,MAAc,EACd,aAAqB;IAErB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,cAAc,EAAE,iCAAiC;QACjD,6BAA6B,EAAE,GAAG;QAClC,KAAK,EAAE,aAAa;KACrB,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;QACb,KAAK,EAAE,UAAU,MAAM,qBAAqB,aAAa,GAAG;KAC7D,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -1,3 +1,17 @@
1
+ /**
2
+ * AgentXL HTTPS server — thin wiring layer.
3
+ *
4
+ * Responsibilities:
5
+ * - Server lifecycle (start, stop)
6
+ * - Route dispatch
7
+ * - Version resolution
8
+ *
9
+ * All handler logic lives in:
10
+ * - src/server/routes/agent.ts
11
+ * - src/server/routes/folder.ts
12
+ * - src/server/routes/workbook.ts
13
+ * - src/server/static.ts
14
+ */
1
15
  import { type CertPair } from "./certs.js";
2
16
  /** Enable or disable request logging. */
3
17
  export declare function setVerbose(enabled: boolean): void;
@@ -5,11 +19,9 @@ export declare function setVerbose(enabled: boolean): void;
5
19
  * Start the HTTPS server.
6
20
  *
7
21
  * @param port - Port to listen on (default: 3001)
8
- * @param certs - Optional pre-loaded certificates. If not provided, will call ensureCerts().
22
+ * @param certs - Optional pre-loaded certificates.
9
23
  */
10
24
  export declare function startServer(port?: number, certs?: CertPair): Promise<void>;
11
- /**
12
- * Stop the HTTPS server gracefully.
13
- */
25
+ /** Stop the HTTPS server gracefully. */
14
26
  export declare function stopServer(): Promise<void>;
15
27
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAsYxD,yCAAyC;AACzC,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEjD;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,IAAI,GAAE,MAAa,EACnB,KAAK,CAAC,EAAE,QAAQ,GACf,OAAO,CAAC,IAAI,CAAC,CA0Cf;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAWhD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAiKxD,yCAAyC;AACzC,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEjD;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,IAAI,GAAE,MAAa,EACnB,KAAK,CAAC,EAAE,QAAQ,GACf,OAAO,CAAC,IAAI,CAAC,CA4Cf;AAED,wCAAwC;AACxC,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAWhD"}