@lazyingart/agintiflow 0.20.182 → 0.20.184
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/README.md +1 -1
- package/docs/student-committee-supervisor.md +5 -5
- package/package.json +1 -1
- package/public/app.js +399 -5
- package/public/index.html +34 -1
- package/public/styles.css +197 -2
- package/references/aginti-generalization-audit-2026-05-20.md +3 -2
- package/references/agintiflow-npm-publication-memory.md +12 -0
- package/references/agintiflow-paper-ui-generalization-plan-2026-05-31.md +283 -0
- package/references/bilingual-book-supervision-lessons.md +26 -25
- package/references/codex-session-cross-references.md +6 -6
- package/references/dynamic-step-budget-and-scs-auto.md +8 -8
- package/references/student-committee-supervisor-mode.md +1 -1
- package/scripts/smoke-cli-chat.js +3 -3
- package/scripts/smoke-dynamic-step-budget.js +2 -1
- package/scripts/smoke-model-roles.js +82 -0
- package/scripts/smoke-web-api.js +73 -2
- package/scripts/smoke-web-ui.js +55 -1
- package/skills/bilingual-interlinear-book/SKILL.md +6 -6
- package/src/agent-runner.js +11 -10
- package/src/cli.js +2 -1
- package/src/config.js +2 -2
- package/src/interactive-cli.js +2 -2
- package/src/scs-controller.js +19 -21
- package/src/web-db.js +7 -3
- package/web.js +311 -2
package/README.md
CHANGED
|
@@ -153,7 +153,7 @@ aginti --language de
|
|
|
153
153
|
| Save provider keys | `aginti auth`, `/auth`, `/login` |
|
|
154
154
|
| Review current repo | `/review [focus]` |
|
|
155
155
|
| Toggle SCS quality gate | `/scs` |
|
|
156
|
-
|
|
|
156
|
+
| Keep default auto SCS routing | `/scs auto` or `aginti --scs auto "task"` |
|
|
157
157
|
| Disable SCS for simple work | `/scs off` or `aginti --no-scs "task"` |
|
|
158
158
|
| Control dynamic step budgets | `--dynamic-steps auto\|on\|off` |
|
|
159
159
|
| Work with AAPS workflows | `aginti aaps status`, `/aaps validate` |
|
|
@@ -61,13 +61,13 @@ The current implementation is deliberately bounded:
|
|
|
61
61
|
|
|
62
62
|
## Auto Mode
|
|
63
63
|
|
|
64
|
-
`/scs auto` and `--scs auto` are
|
|
64
|
+
`/scs auto` and `--scs auto` are the default for users who want cheap simple turns without losing strict validation on risky work. Auto mode activates SCS for high-risk, evidence-heavy, or long-running work. Signals include:
|
|
65
65
|
|
|
66
|
-
- high smart-routing complexity score;
|
|
67
|
-
- profiles such as
|
|
68
|
-
- prompts mentioning
|
|
66
|
+
- very high smart-routing complexity score;
|
|
67
|
+
- profiles such as app, Android/iOS, large-codebase, GitHub, maintenance, QA, security, supervision, pipeline, and website;
|
|
68
|
+
- prompts mentioning failing tests, repo-wide changes, browser uploads, releases, deployments, tmux, emulators, Docker, PDFs, or similar high-friction workflows.
|
|
69
69
|
|
|
70
|
-
Auto mode stays off for simple turns,
|
|
70
|
+
Auto mode is the default. It stays off for simple turns, uses the main model for moderate complexity, and activates SCS only for high-risk or evidence-heavy turns.
|
|
71
71
|
|
|
72
72
|
## Dynamic Step Budgets
|
|
73
73
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.184",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AgInTiFlow is a project-aware agent workspace for hybrid wet-dry R&D, hardware-aware intelligence, software automation, and industrial workflows.",
|
|
6
6
|
"license": "Apache-2.0",
|
package/public/app.js
CHANGED
|
@@ -145,6 +145,14 @@ const translations = {
|
|
|
145
145
|
wrappersOffLabel: "wrapper tools off",
|
|
146
146
|
wrapperCapabilityTitle: "Agent wrappers",
|
|
147
147
|
workspaceCapabilityTitle: "Workspace files",
|
|
148
|
+
workspaceExplorerTitle: "Workspace explorer",
|
|
149
|
+
workspaceExplorerHelp: "Browse, classify, drag into chat, and open project files.",
|
|
150
|
+
workspaceRefreshButton: "Refresh",
|
|
151
|
+
workspaceAutomapButton: "Auto map",
|
|
152
|
+
workspaceWorkbenchTitle: "Workspace workbench",
|
|
153
|
+
workspaceNoFileSelected: "Select a file from the explorer.",
|
|
154
|
+
workspaceSaveButton: "Save file",
|
|
155
|
+
workspaceRevertButton: "Revert",
|
|
148
156
|
mcpCapabilityTitle: "MCP servers",
|
|
149
157
|
mcpEmpty: "No MCP servers configured.",
|
|
150
158
|
workspaceToolsLabel: "File tools",
|
|
@@ -746,6 +754,19 @@ const wrapperGridEl = document.querySelector("#wrapper-grid");
|
|
|
746
754
|
const workspaceStatusEl = document.querySelector("#workspace-status");
|
|
747
755
|
const workspaceToolsEl = document.querySelector("#workspace-tools");
|
|
748
756
|
const workspaceChangesEl = document.querySelector("#workspace-changes");
|
|
757
|
+
const workspaceExplorerEl = document.querySelector("#workspace-explorer");
|
|
758
|
+
const workspaceBrowserStatusEl = document.querySelector("#workspace-browser-status");
|
|
759
|
+
const workspaceLanesEl = document.querySelector("#workspace-lanes");
|
|
760
|
+
const workspaceTreeEl = document.querySelector("#workspace-tree");
|
|
761
|
+
const workspaceRefreshButton = document.querySelector("#workspace-refresh");
|
|
762
|
+
const workspaceAutomapButton = document.querySelector("#workspace-automap");
|
|
763
|
+
const workspaceActiveTitleEl = document.querySelector("#workspace-active-title");
|
|
764
|
+
const workspaceActiveMetaEl = document.querySelector("#workspace-active-meta");
|
|
765
|
+
const workspacePreviewEl = document.querySelector("#workspace-preview");
|
|
766
|
+
const workspaceEditorEl = document.querySelector("#workspace-editor");
|
|
767
|
+
const workspaceSaveButton = document.querySelector("#workspace-save");
|
|
768
|
+
const workspaceRevertButton = document.querySelector("#workspace-revert");
|
|
769
|
+
const workspaceEditorStatusEl = document.querySelector("#workspace-editor-status");
|
|
749
770
|
const mcpStatusEl = document.querySelector("#mcp-status");
|
|
750
771
|
const mcpGridEl = document.querySelector("#mcp-grid");
|
|
751
772
|
const mcpWarningsEl = document.querySelector("#mcp-warnings");
|
|
@@ -835,6 +856,31 @@ let currentArtifactTab = "canvas";
|
|
|
835
856
|
let artifactUnreadCount = 0;
|
|
836
857
|
let lastAnnouncedRunKey = "";
|
|
837
858
|
let quickVeniceModeActive = false;
|
|
859
|
+
const WORKSPACE_LANES = [
|
|
860
|
+
{ id: "all", label: "All" },
|
|
861
|
+
{ id: "source", label: "Source" },
|
|
862
|
+
{ id: "scripts", label: "Scripts" },
|
|
863
|
+
{ id: "docs", label: "Docs" },
|
|
864
|
+
{ id: "data", label: "Data" },
|
|
865
|
+
{ id: "media", label: "Media" },
|
|
866
|
+
{ id: "references", label: "Refs" },
|
|
867
|
+
{ id: "artifacts", label: "Artifacts" },
|
|
868
|
+
{ id: "logs", label: "Logs" },
|
|
869
|
+
{ id: "other", label: "Other" },
|
|
870
|
+
];
|
|
871
|
+
let workspaceBrowser = {
|
|
872
|
+
root: "",
|
|
873
|
+
files: [],
|
|
874
|
+
warnings: [],
|
|
875
|
+
activeLane: "all",
|
|
876
|
+
activePath: "",
|
|
877
|
+
activeContent: "",
|
|
878
|
+
savedContent: "",
|
|
879
|
+
overrides: {},
|
|
880
|
+
loading: false,
|
|
881
|
+
error: "",
|
|
882
|
+
initialized: false,
|
|
883
|
+
};
|
|
838
884
|
|
|
839
885
|
function normalizeLanguage(language) {
|
|
840
886
|
const lower = String(language || "").toLowerCase();
|
|
@@ -1156,6 +1202,278 @@ function renderWorkspacePanel(workspace = lastWorkspace, activity = lastWorkspac
|
|
|
1156
1202
|
.join("");
|
|
1157
1203
|
}
|
|
1158
1204
|
|
|
1205
|
+
function workspaceRoot() {
|
|
1206
|
+
return commandCwdField?.value.trim() || projectInfo?.commandCwd || projectInfo?.root || "";
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
function workspaceExt(filePath = "") {
|
|
1210
|
+
const name = String(filePath || "").toLowerCase();
|
|
1211
|
+
const index = name.lastIndexOf(".");
|
|
1212
|
+
return index >= 0 ? name.slice(index) : "";
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
function workspaceDir(filePath = "") {
|
|
1216
|
+
const normalized = String(filePath || "").replace(/\\/g, "/");
|
|
1217
|
+
const index = normalized.lastIndexOf("/");
|
|
1218
|
+
return index >= 0 ? normalized.slice(0, index) : "";
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
function workspaceBaseName(filePath = "") {
|
|
1222
|
+
return String(filePath || "").replace(/\\/g, "/").split("/").filter(Boolean).pop() || filePath;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
function inferWorkspaceLane(file = {}) {
|
|
1226
|
+
const filePath = String(file.path || "").toLowerCase();
|
|
1227
|
+
const first = filePath.split("/")[0] || "";
|
|
1228
|
+
const ext = workspaceExt(filePath);
|
|
1229
|
+
if (workspaceBrowser.overrides[file.path]) return workspaceBrowser.overrides[file.path];
|
|
1230
|
+
if (["artifacts", "runs", "outputs", "reports"].includes(first)) return "artifacts";
|
|
1231
|
+
if (["logs", "log", "events"].includes(first) || ext === ".log") return "logs";
|
|
1232
|
+
if (["data", "datasets", "tables"].includes(first) || [".csv", ".tsv", ".jsonl", ".xlsx", ".parquet"].includes(ext)) return "data";
|
|
1233
|
+
if (["docs", "doc", "references", "reference"].includes(first) || [".md", ".txt", ".tex", ".rst"].includes(ext)) return "docs";
|
|
1234
|
+
if (["refs", "bibliography"].includes(first) || [".bib", ".ris", ".enw"].includes(ext)) return "references";
|
|
1235
|
+
if (["scripts", "bin"].includes(first) || [".py", ".r", ".sh", ".m", ".pl"].includes(ext)) return "scripts";
|
|
1236
|
+
if ([".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".pdf", ".mp4", ".mov", ".wav", ".mp3"].includes(ext)) return "media";
|
|
1237
|
+
if ([".js", ".mjs", ".ts", ".tsx", ".jsx", ".css", ".html", ".go", ".rs", ".c", ".cpp", ".h", ".hpp", ".java", ".rb", ".php", ".lua"].includes(ext)) {
|
|
1238
|
+
return "source";
|
|
1239
|
+
}
|
|
1240
|
+
return "other";
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
function workspaceFilesByLane() {
|
|
1244
|
+
const groups = Object.fromEntries(WORKSPACE_LANES.map((lane) => [lane.id, []]));
|
|
1245
|
+
for (const file of workspaceBrowser.files) {
|
|
1246
|
+
groups.all.push(file);
|
|
1247
|
+
const lane = inferWorkspaceLane(file);
|
|
1248
|
+
if (!groups[lane]) groups.other.push(file);
|
|
1249
|
+
else groups[lane].push(file);
|
|
1250
|
+
}
|
|
1251
|
+
return groups;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
function workspaceActiveFile() {
|
|
1255
|
+
return workspaceBrowser.files.find((file) => file.path === workspaceBrowser.activePath) || null;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
function formatBytes(size = 0) {
|
|
1259
|
+
const value = Number(size || 0);
|
|
1260
|
+
if (value < 1024) return `${value} B`;
|
|
1261
|
+
if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)} KB`;
|
|
1262
|
+
return `${(value / 1024 / 1024).toFixed(1)} MB`;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
function workspaceRawUrl(filePath = "") {
|
|
1266
|
+
const params = new URLSearchParams({ commandCwd: workspaceBrowser.root || workspaceRoot(), path: filePath });
|
|
1267
|
+
return `/api/workspace/raw?${params.toString()}`;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
function setWorkspaceEditorStatus(message = "", kind = "info") {
|
|
1271
|
+
if (!workspaceEditorStatusEl) return;
|
|
1272
|
+
workspaceEditorStatusEl.textContent = message;
|
|
1273
|
+
workspaceEditorStatusEl.dataset.kind = kind;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
function renderWorkspaceExplorer() {
|
|
1277
|
+
if (!workspaceExplorerEl || !workspaceLanesEl || !workspaceTreeEl || !workspaceBrowserStatusEl) return;
|
|
1278
|
+
const groups = workspaceFilesByLane();
|
|
1279
|
+
const activeLane = workspaceBrowser.activeLane || "all";
|
|
1280
|
+
const warnings = workspaceBrowser.warnings?.length ? ` · ${workspaceBrowser.warnings.length} warning(s)` : "";
|
|
1281
|
+
const truncated = workspaceBrowser.truncated ? " · truncated" : "";
|
|
1282
|
+
const status = workspaceBrowser.loading
|
|
1283
|
+
? "Loading workspace..."
|
|
1284
|
+
: workspaceBrowser.error
|
|
1285
|
+
? `Workspace unavailable: ${workspaceBrowser.error}`
|
|
1286
|
+
: `${workspaceBrowser.files.length} files · ${workspaceBrowser.root || workspaceRoot()}${warnings}${truncated}`;
|
|
1287
|
+
workspaceBrowserStatusEl.textContent = status;
|
|
1288
|
+
|
|
1289
|
+
workspaceLanesEl.innerHTML = WORKSPACE_LANES.map((lane) => {
|
|
1290
|
+
const count = groups[lane.id]?.length || 0;
|
|
1291
|
+
return `
|
|
1292
|
+
<button
|
|
1293
|
+
type="button"
|
|
1294
|
+
class="workspace-lane"
|
|
1295
|
+
data-workspace-lane="${escapeHtml(lane.id)}"
|
|
1296
|
+
data-selected="${lane.id === activeLane}"
|
|
1297
|
+
title="Drop a file here to classify it as ${escapeHtml(lane.label)}"
|
|
1298
|
+
>
|
|
1299
|
+
<span>${escapeHtml(lane.label)}</span>
|
|
1300
|
+
<strong>${count}</strong>
|
|
1301
|
+
</button>
|
|
1302
|
+
`;
|
|
1303
|
+
}).join("");
|
|
1304
|
+
|
|
1305
|
+
const visibleFiles = (groups[activeLane] || []).slice().sort((left, right) => left.path.localeCompare(right.path));
|
|
1306
|
+
if (!visibleFiles.length) {
|
|
1307
|
+
workspaceTreeEl.innerHTML = `<p class="subtle workspace-empty">No files in this category.</p>`;
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
workspaceTreeEl.innerHTML = visibleFiles
|
|
1312
|
+
.map((file) => {
|
|
1313
|
+
const lane = inferWorkspaceLane(file);
|
|
1314
|
+
const active = file.path === workspaceBrowser.activePath;
|
|
1315
|
+
const meta = [lane, formatBytes(file.size), file.binary ? "binary" : "text"].join(" · ");
|
|
1316
|
+
return `
|
|
1317
|
+
<button
|
|
1318
|
+
type="button"
|
|
1319
|
+
class="workspace-file-row"
|
|
1320
|
+
data-workspace-file="${escapeHtml(file.path)}"
|
|
1321
|
+
data-selected="${active}"
|
|
1322
|
+
draggable="true"
|
|
1323
|
+
>
|
|
1324
|
+
<span class="workspace-file-main">
|
|
1325
|
+
<strong>${escapeHtml(workspaceBaseName(file.path))}</strong>
|
|
1326
|
+
<small>${escapeHtml(workspaceDir(file.path) || ".")}</small>
|
|
1327
|
+
</span>
|
|
1328
|
+
<span class="workspace-file-meta">${escapeHtml(meta)}</span>
|
|
1329
|
+
</button>
|
|
1330
|
+
`;
|
|
1331
|
+
})
|
|
1332
|
+
.join("");
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
function renderWorkspaceWorkbench() {
|
|
1336
|
+
if (!workspaceActiveTitleEl || !workspaceActiveMetaEl || !workspacePreviewEl || !workspaceEditorEl) return;
|
|
1337
|
+
const file = workspaceActiveFile();
|
|
1338
|
+
const dirty = workspaceBrowser.activeContent !== workspaceBrowser.savedContent;
|
|
1339
|
+
|
|
1340
|
+
if (!file) {
|
|
1341
|
+
workspaceActiveTitleEl.textContent = t("workspaceNoFileSelected");
|
|
1342
|
+
workspaceActiveMetaEl.textContent = t("workspaceNoFileSelected");
|
|
1343
|
+
workspacePreviewEl.innerHTML = `<p class="subtle">${t("workspaceNoFileSelected")}</p>`;
|
|
1344
|
+
workspaceEditorEl.hidden = true;
|
|
1345
|
+
if (workspaceSaveButton) workspaceSaveButton.disabled = true;
|
|
1346
|
+
if (workspaceRevertButton) workspaceRevertButton.disabled = true;
|
|
1347
|
+
setWorkspaceEditorStatus("");
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
workspaceActiveTitleEl.textContent = file.path;
|
|
1352
|
+
workspaceActiveMetaEl.textContent = `${inferWorkspaceLane(file)} · ${formatBytes(file.size)} · ${
|
|
1353
|
+
file.binary ? "preview-only" : dirty ? "edited" : "saved"
|
|
1354
|
+
}`;
|
|
1355
|
+
|
|
1356
|
+
const ext = workspaceExt(file.path);
|
|
1357
|
+
const rawUrl = workspaceRawUrl(file.path);
|
|
1358
|
+
if (file.binary) {
|
|
1359
|
+
workspaceEditorEl.hidden = true;
|
|
1360
|
+
if ([".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg"].includes(ext)) {
|
|
1361
|
+
workspacePreviewEl.innerHTML = `<img class="workspace-media-preview" src="${escapeHtml(rawUrl)}" alt="${escapeHtml(file.path)}" />`;
|
|
1362
|
+
} else if (ext === ".pdf") {
|
|
1363
|
+
workspacePreviewEl.innerHTML = `<iframe class="workspace-pdf-preview" src="${escapeHtml(rawUrl)}" title="${escapeHtml(file.path)}"></iframe>`;
|
|
1364
|
+
} else {
|
|
1365
|
+
workspacePreviewEl.innerHTML = `<p class="subtle">Binary file preview is unavailable. Use the raw file path or artifact canvas for specialized previews.</p>`;
|
|
1366
|
+
}
|
|
1367
|
+
if (workspaceSaveButton) workspaceSaveButton.disabled = true;
|
|
1368
|
+
if (workspaceRevertButton) workspaceRevertButton.disabled = true;
|
|
1369
|
+
setWorkspaceEditorStatus("Preview-only binary file.");
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
workspacePreviewEl.innerHTML = `<pre class="workspace-code-preview">${escapeHtml(workspaceBrowser.activeContent).slice(
|
|
1374
|
+
0,
|
|
1375
|
+
12000
|
|
1376
|
+
)}</pre>`;
|
|
1377
|
+
workspaceEditorEl.hidden = false;
|
|
1378
|
+
if (document.activeElement !== workspaceEditorEl && workspaceEditorEl.value !== workspaceBrowser.activeContent) {
|
|
1379
|
+
workspaceEditorEl.value = workspaceBrowser.activeContent;
|
|
1380
|
+
}
|
|
1381
|
+
if (workspaceSaveButton) workspaceSaveButton.disabled = !dirty;
|
|
1382
|
+
if (workspaceRevertButton) workspaceRevertButton.disabled = !dirty;
|
|
1383
|
+
setWorkspaceEditorStatus(dirty ? "Unsaved editor changes." : "File loaded.");
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
function renderWorkspaceBrowser() {
|
|
1387
|
+
renderWorkspaceExplorer();
|
|
1388
|
+
renderWorkspaceWorkbench();
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
async function refreshWorkspaceSnapshot({ preserveActive = true } = {}) {
|
|
1392
|
+
if (!workspaceExplorerEl) return;
|
|
1393
|
+
workspaceBrowser.loading = true;
|
|
1394
|
+
workspaceBrowser.error = "";
|
|
1395
|
+
renderWorkspaceExplorer();
|
|
1396
|
+
try {
|
|
1397
|
+
const response = await fetch("/api/workspace/snapshot", {
|
|
1398
|
+
method: "POST",
|
|
1399
|
+
headers: { "Content-Type": "application/json" },
|
|
1400
|
+
body: JSON.stringify({ commandCwd: workspaceRoot() }),
|
|
1401
|
+
});
|
|
1402
|
+
const data = await response.json().catch(() => ({}));
|
|
1403
|
+
if (!response.ok) throw new Error(data.error || "Workspace snapshot failed.");
|
|
1404
|
+
workspaceBrowser = {
|
|
1405
|
+
...workspaceBrowser,
|
|
1406
|
+
root: data.root || workspaceRoot(),
|
|
1407
|
+
files: data.files || [],
|
|
1408
|
+
warnings: data.warnings || [],
|
|
1409
|
+
truncated: Boolean(data.truncated),
|
|
1410
|
+
loading: false,
|
|
1411
|
+
error: "",
|
|
1412
|
+
initialized: true,
|
|
1413
|
+
};
|
|
1414
|
+
if (!preserveActive || !workspaceBrowser.files.some((file) => file.path === workspaceBrowser.activePath)) {
|
|
1415
|
+
workspaceBrowser.activePath = workspaceBrowser.files.find((file) => !file.binary)?.path || workspaceBrowser.files[0]?.path || "";
|
|
1416
|
+
const active = workspaceActiveFile();
|
|
1417
|
+
workspaceBrowser.activeContent = active?.content || "";
|
|
1418
|
+
workspaceBrowser.savedContent = active?.content || "";
|
|
1419
|
+
} else {
|
|
1420
|
+
const active = workspaceActiveFile();
|
|
1421
|
+
if (!active?.binary && workspaceBrowser.activeContent === workspaceBrowser.savedContent) {
|
|
1422
|
+
workspaceBrowser.activeContent = active?.content || "";
|
|
1423
|
+
workspaceBrowser.savedContent = active?.content || "";
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
} catch (error) {
|
|
1427
|
+
workspaceBrowser.loading = false;
|
|
1428
|
+
workspaceBrowser.error = error instanceof Error ? error.message : String(error);
|
|
1429
|
+
}
|
|
1430
|
+
renderWorkspaceBrowser();
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
function selectWorkspaceFile(filePath = "") {
|
|
1434
|
+
const file = workspaceBrowser.files.find((item) => item.path === filePath);
|
|
1435
|
+
if (!file) return;
|
|
1436
|
+
workspaceBrowser.activePath = file.path;
|
|
1437
|
+
workspaceBrowser.activeContent = file.content || "";
|
|
1438
|
+
workspaceBrowser.savedContent = file.content || "";
|
|
1439
|
+
renderWorkspaceBrowser();
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
async function saveWorkspaceEditor() {
|
|
1443
|
+
const file = workspaceActiveFile();
|
|
1444
|
+
if (!file || file.binary || !workspaceEditorEl) return;
|
|
1445
|
+
const content = workspaceEditorEl.value;
|
|
1446
|
+
setWorkspaceEditorStatus("Saving...");
|
|
1447
|
+
const response = await fetch("/api/workspace/write", {
|
|
1448
|
+
method: "POST",
|
|
1449
|
+
headers: { "Content-Type": "application/json" },
|
|
1450
|
+
body: JSON.stringify({ commandCwd: workspaceBrowser.root || workspaceRoot(), path: file.path, content }),
|
|
1451
|
+
});
|
|
1452
|
+
const data = await response.json().catch(() => ({}));
|
|
1453
|
+
if (!response.ok) {
|
|
1454
|
+
setWorkspaceEditorStatus(data.error || "Save failed.", "error");
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
workspaceBrowser.activeContent = content;
|
|
1458
|
+
workspaceBrowser.savedContent = content;
|
|
1459
|
+
showToast(`Saved ${file.path}.`);
|
|
1460
|
+
await refreshWorkspaceSnapshot({ preserveActive: true });
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
function revertWorkspaceEditor() {
|
|
1464
|
+
workspaceBrowser.activeContent = workspaceBrowser.savedContent;
|
|
1465
|
+
if (workspaceEditorEl) workspaceEditorEl.value = workspaceBrowser.savedContent;
|
|
1466
|
+
renderWorkspaceWorkbench();
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
function insertWorkspaceReference(filePath = "") {
|
|
1470
|
+
if (!chatInputEl || !filePath) return;
|
|
1471
|
+
const reference = `@file ${filePath}`;
|
|
1472
|
+
const current = chatInputEl.value.trimEnd();
|
|
1473
|
+
chatInputEl.value = current ? `${current}\n${reference}` : reference;
|
|
1474
|
+
chatInputEl.focus();
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1159
1477
|
function renderMcpPanel(mcp = lastMcp) {
|
|
1160
1478
|
lastMcp = mcp || null;
|
|
1161
1479
|
if (!mcpStatusEl || !mcpGridEl || !mcpWarningsEl) return;
|
|
@@ -1402,7 +1720,7 @@ function syncQuickModeControls() {
|
|
|
1402
1720
|
if (aapsModeToggle) aapsModeToggle.checked = (taskProfileField?.value || "auto") === "aaps";
|
|
1403
1721
|
if (veniceModeToggle) veniceModeToggle.checked = quickVeniceModeActive;
|
|
1404
1722
|
if (quickModeStatusEl) {
|
|
1405
|
-
const scs = enableScsField?.value || "
|
|
1723
|
+
const scs = enableScsField?.value || "auto";
|
|
1406
1724
|
const profile = taskProfileField?.value || "auto";
|
|
1407
1725
|
const route = `${routeProviderField?.value || "deepseek"}/${fieldValue(routeModelField) || "auto"}`;
|
|
1408
1726
|
const main = `${mainProviderField?.value || "deepseek"}/${fieldValue(mainModelField) || "auto"}`;
|
|
@@ -1451,8 +1769,8 @@ function applyVeniceMode(enabled) {
|
|
|
1451
1769
|
syncQuickModeControls();
|
|
1452
1770
|
}
|
|
1453
1771
|
|
|
1454
|
-
function applyScsMode(mode = enableScsField?.value || "
|
|
1455
|
-
if (enableScsField) enableScsField.value = ["on", "auto", "off"].includes(mode) ? mode : "
|
|
1772
|
+
function applyScsMode(mode = enableScsField?.value || "auto") {
|
|
1773
|
+
if (enableScsField) enableScsField.value = ["on", "auto", "off"].includes(mode) ? mode : "auto";
|
|
1456
1774
|
if (allowParallelScoutsField && enableScsField?.value === "on") {
|
|
1457
1775
|
allowParallelScoutsField.checked = false;
|
|
1458
1776
|
}
|
|
@@ -1663,6 +1981,7 @@ function applyLanguage(language, { persist = true } = {}) {
|
|
|
1663
1981
|
renderProjectStatus();
|
|
1664
1982
|
renderWrapperStatus();
|
|
1665
1983
|
renderWorkspacePanel();
|
|
1984
|
+
renderWorkspaceBrowser();
|
|
1666
1985
|
renderSandboxStatus();
|
|
1667
1986
|
updateRoutingHint();
|
|
1668
1987
|
updatePermissionHint();
|
|
@@ -1707,7 +2026,7 @@ function formPayload() {
|
|
|
1707
2026
|
allowWebSearch: allowWebSearchField?.checked ?? true,
|
|
1708
2027
|
allowMcpTools: allowMcpToolsField?.checked ?? true,
|
|
1709
2028
|
allowParallelScouts: allowParallelScoutsField?.checked ?? true,
|
|
1710
|
-
enableScs: enableScsField?.value || "
|
|
2029
|
+
enableScs: enableScsField?.value || "auto",
|
|
1711
2030
|
dynamicSteps: dynamicStepsField?.value || "auto",
|
|
1712
2031
|
veniceMode: quickVeniceModeActive,
|
|
1713
2032
|
parallelScoutCount: Math.min(Math.max(Number(parallelScoutCountField?.value) || 3, 1), 10),
|
|
@@ -3085,6 +3404,7 @@ async function refreshRun() {
|
|
|
3085
3404
|
await refreshChat();
|
|
3086
3405
|
await refreshSessions();
|
|
3087
3406
|
await refreshWorkspaceChanges();
|
|
3407
|
+
await refreshWorkspaceSnapshot({ preserveActive: true });
|
|
3088
3408
|
await refreshArtifacts({ loadSelected: artifactTunnelDialog?.open });
|
|
3089
3409
|
if (run.status === "finished") await flushAfterFinishQueue();
|
|
3090
3410
|
}
|
|
@@ -3335,6 +3655,7 @@ async function startRunFromGoal(goal, { clearComposer = false } = {}) {
|
|
|
3335
3655
|
sessionSelectEl.value = currentSessionId;
|
|
3336
3656
|
await refreshChat();
|
|
3337
3657
|
await refreshWorkspaceChanges();
|
|
3658
|
+
await refreshWorkspaceSnapshot({ preserveActive: true });
|
|
3338
3659
|
await refreshArtifacts({ loadSelected: artifactTunnelDialog?.open });
|
|
3339
3660
|
|
|
3340
3661
|
if (pollTimer) clearInterval(pollTimer);
|
|
@@ -3589,6 +3910,77 @@ commandCwdField?.addEventListener("input", () => {
|
|
|
3589
3910
|
commandCwdField?.addEventListener("change", () => {
|
|
3590
3911
|
schedulePreferenceSave();
|
|
3591
3912
|
refreshCommandCwdSuggestions(commandCwdField.value).catch(() => {});
|
|
3913
|
+
refreshWorkspaceSnapshot({ preserveActive: false }).catch(() => {});
|
|
3914
|
+
});
|
|
3915
|
+
|
|
3916
|
+
workspaceRefreshButton?.addEventListener("click", () => {
|
|
3917
|
+
refreshWorkspaceSnapshot({ preserveActive: true }).catch((error) => {
|
|
3918
|
+
setWorkspaceEditorStatus(String(error), "error");
|
|
3919
|
+
});
|
|
3920
|
+
});
|
|
3921
|
+
|
|
3922
|
+
workspaceAutomapButton?.addEventListener("click", () => {
|
|
3923
|
+
workspaceBrowser.overrides = {};
|
|
3924
|
+
renderWorkspaceBrowser();
|
|
3925
|
+
showToast("Workspace files auto-mapped by general category.");
|
|
3926
|
+
});
|
|
3927
|
+
|
|
3928
|
+
workspaceLanesEl?.addEventListener("click", (event) => {
|
|
3929
|
+
const button = event.target.closest("[data-workspace-lane]");
|
|
3930
|
+
if (!button) return;
|
|
3931
|
+
workspaceBrowser.activeLane = button.dataset.workspaceLane || "all";
|
|
3932
|
+
renderWorkspaceBrowser();
|
|
3933
|
+
});
|
|
3934
|
+
|
|
3935
|
+
workspaceLanesEl?.addEventListener("dragover", (event) => {
|
|
3936
|
+
if (event.target.closest("[data-workspace-lane]")) event.preventDefault();
|
|
3937
|
+
});
|
|
3938
|
+
|
|
3939
|
+
workspaceLanesEl?.addEventListener("drop", (event) => {
|
|
3940
|
+
const button = event.target.closest("[data-workspace-lane]");
|
|
3941
|
+
const filePath = event.dataTransfer?.getData("text/agintiflow-workspace-file") || event.dataTransfer?.getData("text/plain");
|
|
3942
|
+
const lane = button?.dataset.workspaceLane;
|
|
3943
|
+
if (!button || !filePath || !lane || lane === "all") return;
|
|
3944
|
+
event.preventDefault();
|
|
3945
|
+
workspaceBrowser.overrides[filePath] = lane;
|
|
3946
|
+
workspaceBrowser.activeLane = lane;
|
|
3947
|
+
renderWorkspaceBrowser();
|
|
3948
|
+
});
|
|
3949
|
+
|
|
3950
|
+
workspaceTreeEl?.addEventListener("click", (event) => {
|
|
3951
|
+
const row = event.target.closest("[data-workspace-file]");
|
|
3952
|
+
if (!row) return;
|
|
3953
|
+
selectWorkspaceFile(row.dataset.workspaceFile || "");
|
|
3954
|
+
});
|
|
3955
|
+
|
|
3956
|
+
workspaceTreeEl?.addEventListener("dragstart", (event) => {
|
|
3957
|
+
const row = event.target.closest("[data-workspace-file]");
|
|
3958
|
+
if (!row || !event.dataTransfer) return;
|
|
3959
|
+
event.dataTransfer.setData("text/agintiflow-workspace-file", row.dataset.workspaceFile || "");
|
|
3960
|
+
event.dataTransfer.setData("text/plain", row.dataset.workspaceFile || "");
|
|
3961
|
+
event.dataTransfer.effectAllowed = "copyMove";
|
|
3962
|
+
});
|
|
3963
|
+
|
|
3964
|
+
workspaceEditorEl?.addEventListener("input", () => {
|
|
3965
|
+
workspaceBrowser.activeContent = workspaceEditorEl.value;
|
|
3966
|
+
renderWorkspaceWorkbench();
|
|
3967
|
+
});
|
|
3968
|
+
|
|
3969
|
+
workspaceSaveButton?.addEventListener("click", () => {
|
|
3970
|
+
saveWorkspaceEditor().catch((error) => setWorkspaceEditorStatus(String(error), "error"));
|
|
3971
|
+
});
|
|
3972
|
+
|
|
3973
|
+
workspaceRevertButton?.addEventListener("click", revertWorkspaceEditor);
|
|
3974
|
+
|
|
3975
|
+
chatInputEl?.addEventListener("dragover", (event) => {
|
|
3976
|
+
if (event.dataTransfer?.types?.includes("text/agintiflow-workspace-file")) event.preventDefault();
|
|
3977
|
+
});
|
|
3978
|
+
|
|
3979
|
+
chatInputEl?.addEventListener("drop", (event) => {
|
|
3980
|
+
const filePath = event.dataTransfer?.getData("text/agintiflow-workspace-file");
|
|
3981
|
+
if (!filePath) return;
|
|
3982
|
+
event.preventDefault();
|
|
3983
|
+
insertWorkspaceReference(filePath);
|
|
3592
3984
|
});
|
|
3593
3985
|
|
|
3594
3986
|
chatInputEl.addEventListener("keydown", (event) => {
|
|
@@ -3724,6 +4116,7 @@ chatFormEl.addEventListener("submit", async (event) => {
|
|
|
3724
4116
|
await refreshSessions();
|
|
3725
4117
|
await refreshChat();
|
|
3726
4118
|
await refreshWorkspaceChanges();
|
|
4119
|
+
await refreshWorkspaceSnapshot({ preserveActive: true });
|
|
3727
4120
|
await refreshArtifacts({ loadSelected: artifactTunnelDialog?.open });
|
|
3728
4121
|
|
|
3729
4122
|
if (pollTimer) clearInterval(pollTimer);
|
|
@@ -3818,7 +4211,7 @@ async function loadConfig() {
|
|
|
3818
4211
|
if (allowWebSearchField) allowWebSearchField.checked = prefs.allowWebSearch ?? true;
|
|
3819
4212
|
if (allowMcpToolsField) allowMcpToolsField.checked = prefs.allowMcpTools ?? true;
|
|
3820
4213
|
if (allowParallelScoutsField) allowParallelScoutsField.checked = prefs.allowParallelScouts ?? true;
|
|
3821
|
-
if (enableScsField) enableScsField.value = prefs.enableScs || "
|
|
4214
|
+
if (enableScsField) enableScsField.value = prefs.enableScs || "auto";
|
|
3822
4215
|
if (dynamicStepsField) dynamicStepsField.value = prefs.dynamicSteps || "auto";
|
|
3823
4216
|
if (parallelScoutCountField) parallelScoutCountField.value = String(prefs.parallelScoutCount || 3);
|
|
3824
4217
|
allowWrapperToolsField.checked = prefs.allowWrapperTools ?? false;
|
|
@@ -3835,6 +4228,7 @@ async function loadConfig() {
|
|
|
3835
4228
|
renderWorkspacePanel(data.workspace, []);
|
|
3836
4229
|
renderMcpPanel(data.mcp || null);
|
|
3837
4230
|
await refreshWorkspaceChanges();
|
|
4231
|
+
await refreshWorkspaceSnapshot({ preserveActive: false });
|
|
3838
4232
|
renderSandboxLogs(data.sandbox?.logs || []);
|
|
3839
4233
|
if (quickVeniceModeActive) applyVeniceMode(true);
|
|
3840
4234
|
updateRoutingHint();
|
package/public/index.html
CHANGED
|
@@ -223,6 +223,22 @@
|
|
|
223
223
|
<button id="open-settings" type="button" class="secondary settings-button">Advanced settings</button>
|
|
224
224
|
</form>
|
|
225
225
|
</details>
|
|
226
|
+
|
|
227
|
+
<section id="workspace-explorer" class="workspace-explorer-card" aria-labelledby="workspace-explorer-title">
|
|
228
|
+
<div class="workspace-explorer-head">
|
|
229
|
+
<div>
|
|
230
|
+
<h2 id="workspace-explorer-title" data-i18n="workspaceExplorerTitle">Workspace explorer</h2>
|
|
231
|
+
<p class="subtle" data-i18n="workspaceExplorerHelp">Browse, classify, drag into chat, and open project files.</p>
|
|
232
|
+
</div>
|
|
233
|
+
<div class="workspace-explorer-actions">
|
|
234
|
+
<button id="workspace-refresh" type="button" class="secondary" data-i18n="workspaceRefreshButton">Refresh</button>
|
|
235
|
+
<button id="workspace-automap" type="button" class="secondary" data-i18n="workspaceAutomapButton">Auto map</button>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
<div id="workspace-browser-status" class="subtle workspace-browser-status" aria-live="polite">Loading workspace...</div>
|
|
239
|
+
<div id="workspace-lanes" class="workspace-lanes" aria-label="Workspace file categories"></div>
|
|
240
|
+
<div id="workspace-tree" class="workspace-tree" aria-live="polite"></div>
|
|
241
|
+
</section>
|
|
226
242
|
</section>
|
|
227
243
|
|
|
228
244
|
<section class="stack">
|
|
@@ -264,8 +280,8 @@
|
|
|
264
280
|
<label class="quick-mode-select">
|
|
265
281
|
<span data-i18n="scsModeLabel">SCS</span>
|
|
266
282
|
<select id="enableScs" name="enableScs">
|
|
267
|
-
<option value="on" data-i18n="scsOnOption">On</option>
|
|
268
283
|
<option value="auto" data-i18n="scsAutoOption">Auto</option>
|
|
284
|
+
<option value="on" data-i18n="scsOnOption">On</option>
|
|
269
285
|
<option value="off" data-i18n="scsOffOption">Off</option>
|
|
270
286
|
</select>
|
|
271
287
|
</label>
|
|
@@ -306,6 +322,23 @@
|
|
|
306
322
|
<div id="chat-pending" class="chat-pending" hidden></div>
|
|
307
323
|
</section>
|
|
308
324
|
|
|
325
|
+
<section id="workspace-workbench" class="panel workspace-workbench">
|
|
326
|
+
<div class="header-row">
|
|
327
|
+
<div>
|
|
328
|
+
<h2 data-i18n="workspaceWorkbenchTitle">Workspace workbench</h2>
|
|
329
|
+
<p id="workspace-active-meta" class="subtle" data-i18n="workspaceNoFileSelected">Select a file from the explorer.</p>
|
|
330
|
+
</div>
|
|
331
|
+
<div class="workspace-editor-actions">
|
|
332
|
+
<button id="workspace-revert" type="button" class="secondary" disabled data-i18n="workspaceRevertButton">Revert</button>
|
|
333
|
+
<button id="workspace-save" type="button" disabled data-i18n="workspaceSaveButton">Save file</button>
|
|
334
|
+
</div>
|
|
335
|
+
</div>
|
|
336
|
+
<div id="workspace-active-title" class="workspace-active-title" data-i18n="workspaceNoFileSelected">Select a file from the explorer.</div>
|
|
337
|
+
<div id="workspace-preview" class="workspace-preview"></div>
|
|
338
|
+
<textarea id="workspace-editor" class="workspace-editor" spellcheck="false" hidden></textarea>
|
|
339
|
+
<div id="workspace-editor-status" class="subtle workspace-editor-status"></div>
|
|
340
|
+
</section>
|
|
341
|
+
|
|
309
342
|
<section class="panel output-panel">
|
|
310
343
|
<div class="header-row">
|
|
311
344
|
<h2 data-i18n="runOutputTitle">Run output</h2>
|