@lazyingart/agintiflow 0.20.165 → 0.20.169

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazyingart/agintiflow",
3
- "version": "0.20.165",
3
+ "version": "0.20.169",
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
@@ -50,11 +50,23 @@ const translations = {
50
50
  modelLabel: "Model",
51
51
  goalLabel: "Goal",
52
52
  goalPlaceholder: "Open a site and summarize it, or use run_command for simple terminal inspection.",
53
+ runDefaultsTitle: "Run defaults",
54
+ runDefaultsHelp: "The chat box is the first goal for a new run. These controls set how that run starts.",
55
+ runDefaultsFoldHint: "Routing, safety, tool toggles, and key status.",
56
+ scsModeLabel: "SCS",
57
+ scsOnOption: "On",
58
+ scsAutoOption: "Auto",
59
+ scsOffOption: "Off",
60
+ aapsModeLabel: "AAPS",
61
+ veniceModeLabel: "Venice",
62
+ quickModeStatus: "CLI sync",
53
63
  startUrlLabel: "Start URL",
54
64
  startUrlPlaceholder: "https://news.ycombinator.com",
55
65
  allowedDomainsLabel: "Allowed domains",
56
66
  allowedDomainsPlaceholder: "news.ycombinator.com,github.com",
57
67
  commandCwdLabel: "Working directory",
68
+ commandCwdHelp: "Runs start from this working directory.",
69
+ commandCwdPlaceholder: "/home/user/project",
58
70
  maxStepsLabel: "Max steps",
59
71
  sandboxModeLabel: "Sandbox mode",
60
72
  permissionModeLabel: "Permission shortcut",
@@ -88,6 +100,10 @@ const translations = {
88
100
  webSearchLabel: "Enable web search",
89
101
  parallelScoutsLabel: "Parallel DeepSeek scouts",
90
102
  parallelScoutCountLabel: "Scout count",
103
+ dynamicStepsLabel: "Dynamic steps",
104
+ dynamicStepsAutoOption: "Auto",
105
+ dynamicStepsOnOption: "On",
106
+ dynamicStepsOffOption: "Off",
91
107
  wrapperToolLabel: "Enable agent wrappers",
92
108
  preferredWrapperLabel: "Preferred wrapper",
93
109
  dockerSandboxLabel: "Use Docker sandbox",
@@ -678,6 +694,10 @@ const languageField = document.querySelector("#language");
678
694
  const routingModeField = document.querySelector("#routingMode");
679
695
  const providerField = document.querySelector("#provider");
680
696
  const modelField = document.querySelector("#model");
697
+ const enableScsField = document.querySelector("#enableScs");
698
+ const aapsModeToggle = document.querySelector("#aapsModeToggle");
699
+ const veniceModeToggle = document.querySelector("#veniceModeToggle");
700
+ const quickModeStatusEl = document.querySelector("#quick-mode-status");
681
701
  const modelCatalogEl = document.querySelector("#model-catalog");
682
702
  const modelRoleGridEl = document.querySelector("#model-role-grid");
683
703
  const modelRoutePillEl = document.querySelector("#model-route-pill");
@@ -701,6 +721,8 @@ const setupApiKeyField = document.querySelector("#setup-api-key");
701
721
  const saveApiKeyButton = document.querySelector("#save-api-key");
702
722
  const setupStatusEl = document.querySelector("#setup-status");
703
723
  const taskProfileField = document.querySelector("#taskProfile");
724
+ const commandCwdField = document.querySelector("#commandCwd");
725
+ const commandCwdSuggestionsEl = document.querySelector("#command-cwd-suggestions");
704
726
  const permissionModeField = document.querySelector("#permissionMode");
705
727
  const permissionHintEl = document.querySelector("#permission-hint");
706
728
  const sandboxModeField = document.querySelector("#sandboxMode");
@@ -710,11 +732,13 @@ const logsEl = document.querySelector("#logs");
710
732
  const runMetaEl = document.querySelector("#run-meta");
711
733
  const stopRunButton = document.querySelector("#stop-run");
712
734
  const keyStatusEl = document.querySelector("#key-status");
735
+ const keyStatusListEl = document.querySelector("#key-status-list");
713
736
  const allowAuxiliaryToolsField = document.querySelector("#allowAuxiliaryTools");
714
737
  const allowWebSearchField = document.querySelector("#allowWebSearch");
715
738
  const allowMcpToolsField = document.querySelector("#allowMcpTools");
716
739
  const allowParallelScoutsField = document.querySelector("#allowParallelScouts");
717
740
  const parallelScoutCountField = document.querySelector("#parallelScoutCount");
741
+ const dynamicStepsField = document.querySelector("#dynamicSteps");
718
742
  const allowWrapperToolsField = document.querySelector("#allowWrapperTools");
719
743
  const preferredWrapperField = document.querySelector("#preferredWrapper");
720
744
  const wrapperStatusEl = document.querySelector("#wrapper-status");
@@ -910,31 +934,99 @@ function setRunStatus(status = "", { sessionId, detail = "", announce = false }
910
934
  function renderKeyStatus(status = lastKeyStatus) {
911
935
  lastKeyStatus = status;
912
936
  if (!status) return;
913
- keyStatusEl.textContent = `${t("keysLabel")}: OpenAI ${
914
- status.openai ? t("availableLabel") : t("missingLabel")
915
- } · DeepSeek ${status.deepseek ? t("availableLabel") : t("missingLabel")} · Qwen ${
916
- status.qwen ? t("availableLabel") : t("missingLabel")
917
- } · Venice ${
918
- status.venice ? t("availableLabel") : t("missingLabel")
919
- } · GRS AI ${
920
- status.grsai ? t("availableLabel") : t("missingLabel")
921
- } · ${t("mockLabel")} ${
922
- status.mock ? t("availableLabel") : t("missingLabel")
923
- }`;
937
+ const providers = [
938
+ ["OpenAI", status.openai],
939
+ ["DeepSeek", status.deepseek],
940
+ ["Qwen", status.qwen],
941
+ ["Venice", status.venice],
942
+ ["GRS AI", status.grsai],
943
+ [t("mockLabel"), status.mock],
944
+ ];
945
+ const available = providers.filter(([, ready]) => Boolean(ready)).length;
946
+ if (keyStatusEl) {
947
+ keyStatusEl.textContent = `${t("keysLabel")} ${available}/${providers.length}`;
948
+ keyStatusEl.dataset.ready = String(available > 0);
949
+ }
950
+ if (keyStatusListEl) {
951
+ keyStatusListEl.replaceChildren(
952
+ ...providers.map(([name, ready]) => {
953
+ const chip = document.createElement("div");
954
+ chip.className = "key-status-chip";
955
+ chip.dataset.ready = String(Boolean(ready));
956
+ const title = document.createElement("strong");
957
+ title.textContent = name;
958
+ const value = document.createElement("span");
959
+ value.textContent = ready ? t("availableLabel") : t("missingLabel");
960
+ chip.append(title, value);
961
+ return chip;
962
+ })
963
+ );
964
+ }
924
965
  if (setupCardEl) setupCardEl.hidden = Boolean(status.openai || status.deepseek || status.qwen || status.venice);
925
966
  }
926
967
 
927
968
  function renderProjectStatus(info = projectInfo) {
928
969
  projectInfo = info;
929
970
  if (!projectStatusEl || !info) return;
930
- projectStatusEl.textContent = [
931
- info.platform?.label ? `os=${info.platform.label}` : "",
932
- `root=${info.root || ""}`,
933
- `cwd=${info.commandCwd || ""}`,
934
- `sessions=${info.sessionsDir || ""}`,
935
- `db=${info.sessionDbPath || ""}`,
936
- `shared=${info.sharedSessionFolder ? "yes" : "no"}`,
937
- ].join(" · ");
971
+ const rows = [
972
+ ["OS", info.platform?.label || ""],
973
+ ["Root", info.root || ""],
974
+ ["CWD", info.commandCwd || ""],
975
+ ["Sessions", info.sessionsDir || ""],
976
+ ["Database", info.sessionDbPath || ""],
977
+ ["Shared", info.sharedSessionFolder ? "yes" : "no"],
978
+ ].filter(([, value]) => value !== "");
979
+ projectStatusEl.replaceChildren(
980
+ ...rows.map(([label, value]) => {
981
+ const chip = document.createElement("div");
982
+ chip.className = "project-status-chip";
983
+ if (String(value).length > 54) chip.dataset.wide = "true";
984
+ const title = document.createElement("strong");
985
+ title.textContent = label;
986
+ const body = document.createElement("span");
987
+ body.textContent = value;
988
+ chip.append(title, body);
989
+ return chip;
990
+ })
991
+ );
992
+ }
993
+
994
+ function baseDirectorySuggestions(info = projectInfo) {
995
+ const projectLfsRoot = info?.root?.includes("/ProjectsLFS/")
996
+ ? `${info.root.split("/ProjectsLFS/")[0]}/ProjectsLFS`
997
+ : "";
998
+ const values = [
999
+ info?.commandCwd,
1000
+ info?.root,
1001
+ info?.sessionsDir ? info.sessionsDir.replace(/\/\.agintiflow\/sessions$/, "") : "",
1002
+ projectLfsRoot,
1003
+ ].filter(Boolean);
1004
+ return [...new Set(values)];
1005
+ }
1006
+
1007
+ function renderCommandCwdSuggestions(suggestions = []) {
1008
+ if (!commandCwdSuggestionsEl) return;
1009
+ commandCwdSuggestionsEl.replaceChildren(
1010
+ ...suggestions.slice(0, 16).map((value) => {
1011
+ const option = document.createElement("option");
1012
+ option.value = value;
1013
+ return option;
1014
+ })
1015
+ );
1016
+ }
1017
+
1018
+ async function refreshCommandCwdSuggestions(query = "") {
1019
+ const fallback = baseDirectorySuggestions();
1020
+ renderCommandCwdSuggestions(fallback);
1021
+ try {
1022
+ const response = await fetch(`/api/path-suggestions?q=${encodeURIComponent(query || "")}`);
1023
+ const data = await response.json();
1024
+ if (response.ok && Array.isArray(data.suggestions)) {
1025
+ renderCommandCwdSuggestions([...new Set([...data.suggestions, ...fallback])]);
1026
+ }
1027
+ } catch {
1028
+ renderCommandCwdSuggestions(fallback);
1029
+ }
938
1030
  }
939
1031
 
940
1032
  function renderTaskProfiles(selected = "auto") {
@@ -962,8 +1054,7 @@ function recommendedMaxStepsForProfile(profile = "auto", goal = "") {
962
1054
 
963
1055
  function ensureRecommendedMaxStepsForCurrentTask(goalOverride = "") {
964
1056
  const maxStepsField = document.querySelector("#maxSteps");
965
- const goalField = document.querySelector("#goal");
966
- const recommended = recommendedMaxStepsForProfile(taskProfileField?.value || "auto", goalOverride || goalField?.value || "");
1057
+ const recommended = recommendedMaxStepsForProfile(taskProfileField?.value || "auto", goalOverride || chatInputEl?.value || "");
967
1058
  if (maxStepsField && Number(maxStepsField.value || 0) < recommended) {
968
1059
  maxStepsField.value = String(recommended);
969
1060
  }
@@ -1264,6 +1355,74 @@ function refreshModelDropdowns() {
1264
1355
  );
1265
1356
  }
1266
1357
 
1358
+ function selectedVeniceTextModel() {
1359
+ const options = providerModelOptions("venice");
1360
+ return (
1361
+ fieldValue(routeProviderField) === "venice" && fieldValue(routeModelField)
1362
+ ? fieldValue(routeModelField)
1363
+ : options.find((item) => item.id === "venice-uncensored-1-2")?.id || options[0]?.id || defaults.venice
1364
+ );
1365
+ }
1366
+
1367
+ function inferVeniceMode() {
1368
+ return [providerField?.value, routeProviderField?.value, mainProviderField?.value].includes("venice");
1369
+ }
1370
+
1371
+ function syncQuickModeControls() {
1372
+ if (aapsModeToggle) aapsModeToggle.checked = (taskProfileField?.value || "auto") === "aaps";
1373
+ if (veniceModeToggle) veniceModeToggle.checked = inferVeniceMode();
1374
+ if (quickModeStatusEl) {
1375
+ const scs = enableScsField?.value || "on";
1376
+ const profile = taskProfileField?.value || "auto";
1377
+ const route = `${routeProviderField?.value || "deepseek"}/${fieldValue(routeModelField) || "auto"}`;
1378
+ const main = `${mainProviderField?.value || "deepseek"}/${fieldValue(mainModelField) || "auto"}`;
1379
+ quickModeStatusEl.textContent = `scs=${scs} · profile=${profile} · route ${route} · main ${main}`;
1380
+ }
1381
+ }
1382
+
1383
+ function applyAapsMode(enabled) {
1384
+ if (!taskProfileField) return;
1385
+ taskProfileField.value = enabled ? "aaps" : taskProfileField.value === "aaps" ? "auto" : taskProfileField.value;
1386
+ ensureRecommendedMaxStepsForCurrentTask();
1387
+ syncQuickModeControls();
1388
+ }
1389
+
1390
+ function applyVeniceMode(enabled) {
1391
+ if (enabled) {
1392
+ const model = selectedVeniceTextModel();
1393
+ routingModeField.value = "smart";
1394
+ providerField.value = "deepseek";
1395
+ if (routeProviderField) routeProviderField.value = "venice";
1396
+ refreshModelDropdowns();
1397
+ if (routeModelField) setSelectOptions(routeModelField, providerModelOptions("venice"), model, defaults.venice);
1398
+ if (mainProviderField) mainProviderField.value = "venice";
1399
+ refreshModelDropdowns();
1400
+ if (mainModelField) setSelectOptions(mainModelField, providerModelOptions("venice"), model, defaults.venice);
1401
+ } else {
1402
+ routingModeField.value = "smart";
1403
+ providerField.value = "deepseek";
1404
+ if (routeProviderField?.value === "venice") routeProviderField.value = "deepseek";
1405
+ if (mainProviderField?.value === "venice") mainProviderField.value = "deepseek";
1406
+ refreshModelDropdowns();
1407
+ if (routeModelField && routeProviderField?.value === "deepseek") {
1408
+ setSelectOptions(routeModelField, providerModelOptions("deepseek"), "deepseek-v4-flash", "deepseek-v4-flash");
1409
+ }
1410
+ if (mainModelField && mainProviderField?.value === "deepseek") {
1411
+ setSelectOptions(mainModelField, providerModelOptions("deepseek"), "deepseek-v4-pro", "deepseek-v4-pro");
1412
+ }
1413
+ }
1414
+ updateRoutingHint();
1415
+ syncQuickModeControls();
1416
+ }
1417
+
1418
+ function applyScsMode(mode = enableScsField?.value || "on") {
1419
+ if (enableScsField) enableScsField.value = ["on", "auto", "off"].includes(mode) ? mode : "on";
1420
+ if (allowParallelScoutsField && enableScsField?.value === "on") {
1421
+ allowParallelScoutsField.checked = false;
1422
+ }
1423
+ syncQuickModeControls();
1424
+ }
1425
+
1267
1426
  function renderModelRoles() {
1268
1427
  if (!modelRoleGridEl) return;
1269
1428
  const roles = {
@@ -1373,6 +1532,7 @@ function updateRoutingHint() {
1373
1532
  fieldValue(modelField) || defaults[providerField.value] || ""
1374
1533
  }`;
1375
1534
  renderModelOptions();
1535
+ syncQuickModeControls();
1376
1536
  }
1377
1537
 
1378
1538
  function updatePackageWarning() {
@@ -1498,7 +1658,7 @@ function formPayload() {
1498
1658
  auxiliaryModel: fieldValue(auxiliaryModelField) || "nano-banana-2",
1499
1659
  startUrl: document.querySelector("#startUrl").value.trim(),
1500
1660
  allowedDomains: document.querySelector("#allowedDomains").value.trim(),
1501
- commandCwd: document.querySelector("#commandCwd").value.trim(),
1661
+ commandCwd: commandCwdField?.value.trim() || "",
1502
1662
  maxSteps: Number(document.querySelector("#maxSteps").value) || 24,
1503
1663
  permissionMode: permissionModeField?.value || "normal",
1504
1664
  sandboxMode: sandboxModeField.value,
@@ -1511,6 +1671,8 @@ function formPayload() {
1511
1671
  allowWebSearch: allowWebSearchField?.checked ?? true,
1512
1672
  allowMcpTools: allowMcpToolsField?.checked ?? true,
1513
1673
  allowParallelScouts: allowParallelScoutsField?.checked ?? true,
1674
+ enableScs: enableScsField?.value || "on",
1675
+ dynamicSteps: dynamicStepsField?.value || "auto",
1514
1676
  parallelScoutCount: Math.min(Math.max(Number(parallelScoutCountField?.value) || 3, 1), 10),
1515
1677
  allowWrapperTools: allowWrapperToolsField.checked,
1516
1678
  preferredWrapper: preferredWrapperField.value,
@@ -2971,6 +3133,7 @@ providerField.addEventListener("change", () => {
2971
3133
  modelField.value = defaults[providerField.value] || "";
2972
3134
  }
2973
3135
  updateRoutingHint();
3136
+ syncQuickModeControls();
2974
3137
  schedulePreferenceSave();
2975
3138
  });
2976
3139
 
@@ -2982,6 +3145,21 @@ modelCatalogEl?.addEventListener("click", (event) => {
2982
3145
  schedulePreferenceSave();
2983
3146
  });
2984
3147
 
3148
+ enableScsField?.addEventListener("change", () => {
3149
+ applyScsMode(enableScsField.value);
3150
+ schedulePreferenceSave();
3151
+ });
3152
+
3153
+ aapsModeToggle?.addEventListener("change", () => {
3154
+ applyAapsMode(aapsModeToggle.checked);
3155
+ schedulePreferenceSave();
3156
+ });
3157
+
3158
+ veniceModeToggle?.addEventListener("change", () => {
3159
+ applyVeniceMode(veniceModeToggle.checked);
3160
+ schedulePreferenceSave();
3161
+ });
3162
+
2985
3163
  modelField.addEventListener("change", updateRoutingHint);
2986
3164
  [routeProviderField, routeModelField, mainProviderField, mainModelField, spareProviderField, spareModelField, spareReasoningField, wrapperModelField, wrapperReasoningField, auxiliaryProviderField, auxiliaryModelField]
2987
3165
  .filter(Boolean)
@@ -2990,12 +3168,14 @@ modelField.addEventListener("change", updateRoutingHint);
2990
3168
  if (field === routeProviderField || field === mainProviderField || field === spareProviderField || field === auxiliaryProviderField) refreshModelDropdowns();
2991
3169
  renderModelRoles();
2992
3170
  renderModelOptions();
3171
+ syncQuickModeControls();
2993
3172
  schedulePreferenceSave();
2994
3173
  });
2995
3174
  field.addEventListener("change", () => {
2996
3175
  if (field === routeProviderField || field === mainProviderField || field === spareProviderField || field === auxiliaryProviderField) refreshModelDropdowns();
2997
3176
  renderModelRoles();
2998
3177
  renderModelOptions();
3178
+ syncQuickModeControls();
2999
3179
  schedulePreferenceSave();
3000
3180
  });
3001
3181
  });
@@ -3007,8 +3187,10 @@ permissionModeField?.addEventListener("change", () => {
3007
3187
  });
3008
3188
  allowWrapperToolsField.addEventListener("change", () => renderWrapperStatus());
3009
3189
  preferredWrapperField.addEventListener("change", () => renderWrapperStatus());
3190
+ dynamicStepsField?.addEventListener("change", schedulePreferenceSave);
3010
3191
  taskProfileField?.addEventListener("change", () => {
3011
3192
  ensureRecommendedMaxStepsForCurrentTask();
3193
+ syncQuickModeControls();
3012
3194
  schedulePreferenceSave();
3013
3195
  });
3014
3196
 
@@ -3038,6 +3220,22 @@ saveApiKeyButton?.addEventListener("click", async () => {
3038
3220
  form.addEventListener("input", schedulePreferenceSave);
3039
3221
  form.addEventListener("change", schedulePreferenceSave);
3040
3222
 
3223
+ let commandCwdSuggestTimer = null;
3224
+ commandCwdField?.addEventListener("focus", () => {
3225
+ refreshCommandCwdSuggestions(commandCwdField.value).catch(() => {});
3226
+ });
3227
+ commandCwdField?.addEventListener("input", () => {
3228
+ schedulePreferenceSave();
3229
+ clearTimeout(commandCwdSuggestTimer);
3230
+ commandCwdSuggestTimer = setTimeout(() => {
3231
+ refreshCommandCwdSuggestions(commandCwdField.value).catch(() => {});
3232
+ }, 120);
3233
+ });
3234
+ commandCwdField?.addEventListener("change", () => {
3235
+ schedulePreferenceSave();
3236
+ refreshCommandCwdSuggestions(commandCwdField.value).catch(() => {});
3237
+ });
3238
+
3041
3239
  chatInputEl.addEventListener("keydown", (event) => {
3042
3240
  if (event.key === "Enter" && !event.shiftKey && !event.ctrlKey && !event.metaKey && !event.altKey) {
3043
3241
  event.preventDefault();
@@ -3118,9 +3316,7 @@ window.addEventListener("keydown", (event) => {
3118
3316
 
3119
3317
  form.addEventListener("submit", async (event) => {
3120
3318
  event.preventDefault();
3121
-
3122
- const goal = document.querySelector("#goal").value.trim();
3123
- await startRunFromGoal(goal);
3319
+ chatInputEl?.focus();
3124
3320
  });
3125
3321
 
3126
3322
  sessionSelectEl.addEventListener("change", async () => {
@@ -3237,7 +3433,7 @@ async function loadConfig() {
3237
3433
  renderTaskProfiles(prefs.taskProfile || "auto");
3238
3434
  document.querySelector("#startUrl").value = prefs.startUrl || "";
3239
3435
  document.querySelector("#allowedDomains").value = prefs.allowedDomains || "";
3240
- document.querySelector("#commandCwd").value = prefs.commandCwd || data.project?.root || "";
3436
+ if (commandCwdField) commandCwdField.value = prefs.commandCwd || data.project?.root || "";
3241
3437
  document.querySelector("#headless").checked = prefs.headless ?? data.defaults.headless;
3242
3438
  document.querySelector("#maxSteps").value = prefs.maxSteps ?? data.defaults.maxSteps;
3243
3439
  if (permissionModeField) permissionModeField.value = prefs.permissionMode || "normal";
@@ -3249,6 +3445,8 @@ async function loadConfig() {
3249
3445
  if (allowWebSearchField) allowWebSearchField.checked = prefs.allowWebSearch ?? true;
3250
3446
  if (allowMcpToolsField) allowMcpToolsField.checked = prefs.allowMcpTools ?? true;
3251
3447
  if (allowParallelScoutsField) allowParallelScoutsField.checked = prefs.allowParallelScouts ?? true;
3448
+ if (enableScsField) enableScsField.value = prefs.enableScs || "on";
3449
+ if (dynamicStepsField) dynamicStepsField.value = prefs.dynamicSteps || "auto";
3252
3450
  if (parallelScoutCountField) parallelScoutCountField.value = String(prefs.parallelScoutCount || 3);
3253
3451
  allowWrapperToolsField.checked = prefs.allowWrapperTools ?? false;
3254
3452
  preferredWrapperField.value = prefs.preferredWrapper || "codex";
@@ -3258,6 +3456,7 @@ async function loadConfig() {
3258
3456
 
3259
3457
  renderKeyStatus(data.keyStatus);
3260
3458
  renderProjectStatus(data.project);
3459
+ await refreshCommandCwdSuggestions(commandCwdField?.value || "");
3261
3460
  renderWrapperStatus(data.wrappers || []);
3262
3461
  refreshProviderDropdowns();
3263
3462
  renderWorkspacePanel(data.workspace, []);
@@ -3267,6 +3466,7 @@ async function loadConfig() {
3267
3466
  updateRoutingHint();
3268
3467
  updatePermissionHint();
3269
3468
  updatePackageWarning();
3469
+ syncQuickModeControls();
3270
3470
 
3271
3471
  renderSessions(data.sessions || []);
3272
3472
  if (data.sessions && data.sessions.length > 0) {
package/public/index.html CHANGED
@@ -36,13 +36,30 @@
36
36
  <p class="subtle" data-i18n="intro">
37
37
  Project-aware, low-cost agent for real problems
38
38
  </p>
39
- <details class="project-card">
40
- <summary>
41
- <strong data-i18n="projectStatusTitle">Project folder</strong>
42
- <span class="project-card-toggle" aria-hidden="true"></span>
43
- </summary>
44
- <p id="project-status" class="subtle">Loading project context...</p>
45
- </details>
39
+ <section class="workspace-search-card" aria-labelledby="workspace-search-title">
40
+ <div class="workspace-search-head">
41
+ <div>
42
+ <strong id="workspace-search-title" data-i18n="projectStatusTitle">Project folder</strong>
43
+ <p class="subtle" data-i18n="commandCwdHelp">Runs start from this working directory.</p>
44
+ </div>
45
+ </div>
46
+ <label class="workspace-search-field">
47
+ <span data-i18n="commandCwdLabel">Working directory</span>
48
+ <input
49
+ id="commandCwd"
50
+ name="commandCwd"
51
+ type="search"
52
+ value="/home/lachlan/ProjectsLFS/Agent"
53
+ list="command-cwd-suggestions"
54
+ autocomplete="off"
55
+ spellcheck="false"
56
+ data-i18n-placeholder="commandCwdPlaceholder"
57
+ placeholder="/home/lachlan/ProjectsLFS/Agent"
58
+ />
59
+ <datalist id="command-cwd-suggestions"></datalist>
60
+ </label>
61
+ <div id="project-status" class="project-status-grid" aria-live="polite">Loading project context...</div>
62
+ </section>
46
63
 
47
64
  <section id="setup-card" class="setup-card" hidden>
48
65
  <div>
@@ -84,22 +101,20 @@
84
101
  </div>
85
102
  </section>
86
103
 
87
- <form id="run-form">
88
- <label>
89
- <span data-i18n="goalLabel">Goal</span>
90
- <textarea
91
- id="goal"
92
- name="goal"
93
- rows="5"
94
- data-i18n-placeholder="goalPlaceholder"
95
- placeholder="Open a site and summarize it, or use run_command for simple terminal inspection."
96
- ></textarea>
97
- </label>
98
-
99
- <div class="actions run-start-actions">
100
- <button type="submit" data-i18n="startRunButton">Start run</button>
101
- <span id="key-status" class="subtle"></span>
102
- </div>
104
+ <details id="run-defaults-card" class="run-defaults-card">
105
+ <summary class="run-defaults-summary">
106
+ <span>
107
+ <strong data-i18n="runDefaultsTitle">Run defaults</strong>
108
+ <span class="subtle" data-i18n="runDefaultsFoldHint">Routing, safety, tool toggles, and key status.</span>
109
+ </span>
110
+ <span id="key-status" class="key-status-summary"></span>
111
+ <span class="project-card-toggle" aria-hidden="true"></span>
112
+ </summary>
113
+ <form id="run-form" class="run-defaults-form">
114
+ <div class="run-defaults-head">
115
+ <p class="subtle" data-i18n="runDefaultsHelp">The chat box is the first goal for a new run. These controls set how that run starts.</p>
116
+ <div id="key-status-list" class="key-status-list" aria-live="polite"></div>
117
+ </div>
103
118
 
104
119
  <label>
105
120
  <span data-i18n="routingModeLabel">Routing policy</span>
@@ -143,14 +158,18 @@
143
158
  </label>
144
159
 
145
160
  <div class="grid">
146
- <label>
147
- <span data-i18n="commandCwdLabel">Working directory</span>
148
- <input id="commandCwd" name="commandCwd" type="text" value="/home/lachlan/ProjectsLFS/Agent" />
149
- </label>
150
161
  <label>
151
162
  <span data-i18n="maxStepsLabel">Max steps</span>
152
163
  <input id="maxSteps" name="maxSteps" type="number" min="1" max="50" value="24" />
153
164
  </label>
165
+ <label>
166
+ <span data-i18n="dynamicStepsLabel">Dynamic steps</span>
167
+ <select id="dynamicSteps" name="dynamicSteps">
168
+ <option value="auto" data-i18n="dynamicStepsAutoOption">Auto</option>
169
+ <option value="on" data-i18n="dynamicStepsOnOption">On</option>
170
+ <option value="off" data-i18n="dynamicStepsOffOption">Off</option>
171
+ </select>
172
+ </label>
154
173
  </div>
155
174
  <p id="package-warning" class="subtle package-warning"></p>
156
175
 
@@ -202,7 +221,8 @@
202
221
  </div>
203
222
 
204
223
  <button id="open-settings" type="button" class="secondary settings-button">Advanced settings</button>
205
- </form>
224
+ </form>
225
+ </details>
206
226
  </section>
207
227
 
208
228
  <section class="stack">
@@ -240,6 +260,27 @@
240
260
  <strong id="run-state-text" data-i18n="runStateIdle">Ready</strong>
241
261
  <span id="run-state-detail" class="subtle" data-i18n="runStateIdleDetail">Select a conversation or type a new goal below.</span>
242
262
  </div>
263
+ <div class="quick-mode-bar" aria-label="Run mode shortcuts">
264
+ <label class="quick-mode-select">
265
+ <span data-i18n="scsModeLabel">SCS</span>
266
+ <select id="enableScs" name="enableScs">
267
+ <option value="on" data-i18n="scsOnOption">On</option>
268
+ <option value="auto" data-i18n="scsAutoOption">Auto</option>
269
+ <option value="off" data-i18n="scsOffOption">Off</option>
270
+ </select>
271
+ </label>
272
+ <label class="switch-label compact-switch">
273
+ <input id="aapsModeToggle" name="aapsModeToggle" type="checkbox" />
274
+ <span class="switch" aria-hidden="true"></span>
275
+ <span data-i18n="aapsModeLabel">AAPS</span>
276
+ </label>
277
+ <label class="switch-label compact-switch">
278
+ <input id="veniceModeToggle" name="veniceModeToggle" type="checkbox" />
279
+ <span class="switch" aria-hidden="true"></span>
280
+ <span data-i18n="veniceModeLabel">Venice</span>
281
+ </label>
282
+ <span id="quick-mode-status" class="subtle quick-mode-status"></span>
283
+ </div>
243
284
  <form id="chat-form" class="chat-form">
244
285
  <textarea
245
286
  id="chat-input"