@lazyingart/agintiflow 0.20.186 → 0.20.188
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 +8 -1
- package/docs/model-selection.md +21 -0
- package/package.json +1 -1
- package/public/app.js +115 -33
- package/public/index.html +9 -2
- package/public/styles.css +155 -8
- package/references/agintiflow-npm-publication-memory.md +22 -0
- package/scripts/smoke-auth.js +44 -5
- package/scripts/smoke-model-roles.js +14 -0
- package/scripts/smoke-web-api.js +30 -0
- package/scripts/smoke-web-ui.js +16 -1
- package/src/auth-onboarding.js +15 -4
- package/src/capabilities.js +3 -1
- package/src/cli.js +6 -5
- package/src/config.js +7 -5
- package/src/guardrails.js +3 -3
- package/src/i18n.js +11 -11
- package/src/interactive-cli.js +86 -8
- package/src/json-specialist.js +2 -2
- package/src/model-client.js +14 -3
- package/src/model-routing.js +316 -0
- package/src/project.js +31 -7
- package/src/redaction.js +2 -1
- package/web.js +27 -1
package/README.md
CHANGED
|
@@ -85,11 +85,12 @@ aginti init --template aaps
|
|
|
85
85
|
aginti init --template supervision
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
On first interactive use, AgInTiFlow opens an auth wizard if no main model key is found. Pick DeepSeek, OpenAI, Qwen, or Venice, paste the key, and it saves to the ignored project-local `.aginti/.env` file with restricted permissions. You can rerun setup any time:
|
|
88
|
+
On first interactive use, AgInTiFlow opens an auth wizard if no main model key is found. Pick DeepSeek, OpenAI, OpenRouter, Qwen, or Venice, paste the key, and it saves to the ignored project-local `.aginti/.env` file with restricted permissions. You can rerun setup any time:
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
91
|
aginti auth
|
|
92
92
|
aginti auth deepseek
|
|
93
|
+
aginti auth openrouter
|
|
93
94
|
aginti auth venice
|
|
94
95
|
aginti login grsai
|
|
95
96
|
```
|
|
@@ -99,6 +100,7 @@ Provider signup and key pages:
|
|
|
99
100
|
| Provider | Register / key page | API base URL used by AgInTiFlow |
|
|
100
101
|
| --- | --- | --- |
|
|
101
102
|
| DeepSeek | [https://platform.deepseek.com/api_keys](https://platform.deepseek.com/api_keys) | `https://api.deepseek.com` |
|
|
103
|
+
| OpenRouter | [https://openrouter.ai/settings/keys](https://openrouter.ai/settings/keys) | `https://openrouter.ai/api/v1` |
|
|
102
104
|
| Venice | [https://venice.ai/settings/api](https://venice.ai/settings/api) | `https://api.venice.ai/api/v1` |
|
|
103
105
|
| OpenAI | [https://platform.openai.com/api-keys](https://platform.openai.com/api-keys) | `https://api.openai.com/v1` |
|
|
104
106
|
| Qwen / DashScope | [https://bailian.console.aliyun.com/](https://bailian.console.aliyun.com/) | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` |
|
|
@@ -273,6 +275,7 @@ Useful selectors:
|
|
|
273
275
|
```
|
|
274
276
|
|
|
275
277
|
Venice routes can be used for optional uncensored or less restricted creative work. DeepSeek remains the economic default for normal engineering workflows. See [docs/model-selection.md](docs/model-selection.md) and [references/venice-model-reference.md](references/venice-model-reference.md).
|
|
278
|
+
OpenRouter is available as a first-class OpenAI-compatible provider with one key and company-grouped model buckets such as OpenRouter OpenAI, Anthropic, Google, DeepSeek, Qwen, Meta, Mistral, Moonshot, and xAI.
|
|
276
279
|
|
|
277
280
|
## AAPS And Large Workflows
|
|
278
281
|
|
|
@@ -348,6 +351,9 @@ Common environment variables:
|
|
|
348
351
|
```bash
|
|
349
352
|
DEEPSEEK_API_KEY=...
|
|
350
353
|
OPENAI_API_KEY=...
|
|
354
|
+
OPENROUTER_API_KEY=...
|
|
355
|
+
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
|
|
356
|
+
OPENROUTER_MODEL=openrouter/auto
|
|
351
357
|
QWEN_API_KEY=...
|
|
352
358
|
VENICE_API_KEY=...
|
|
353
359
|
GRSAI_API_KEY=...
|
|
@@ -365,6 +371,7 @@ Project-local keys:
|
|
|
365
371
|
```bash
|
|
366
372
|
aginti init
|
|
367
373
|
printf '%s' "$DEEPSEEK_API_KEY" | aginti keys set deepseek --stdin
|
|
374
|
+
printf '%s' "$OPENROUTER_API_KEY" | aginti keys set openrouter --stdin
|
|
368
375
|
printf '%s' "$VENICE_API_KEY" | aginti keys set venice --stdin
|
|
369
376
|
```
|
|
370
377
|
|
package/docs/model-selection.md
CHANGED
|
@@ -25,6 +25,8 @@ aginti --list-routes
|
|
|
25
25
|
|
|
26
26
|
# one-shot overrides
|
|
27
27
|
aginti --route-model deepseek-v4-flash --main-model deepseek-v4-pro "fix this project"
|
|
28
|
+
aginti --provider openrouter --model openrouter/auto --routing manual "try a gateway route"
|
|
29
|
+
aginti --provider openrouter --model anthropic/claude-sonnet-4.6 --routing manual "draft a design review"
|
|
28
30
|
aginti --provider venice --model venice-uncensored-1-2 --routing manual "draft a note"
|
|
29
31
|
aginti --spare-provider openai --spare-model gpt-5.4 --spare-reasoning medium "review this design"
|
|
30
32
|
aginti --allow-wrappers --wrapper codex --wrapper-model gpt-5.5 "patch this bug"
|
|
@@ -63,6 +65,13 @@ Provider families:
|
|
|
63
65
|
| DeepSeek | `deepseek-v4-flash`, `deepseek-v4-pro` |
|
|
64
66
|
| Venice | `venice-uncensored-1-2`, `venice-uncensored`, `gemma-4-uncensored` |
|
|
65
67
|
| OpenAI | `gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.3-codex`, `gpt-5.3-codex-spark`, `gpt-5.2`; each has low/medium/high/xhigh reasoning |
|
|
68
|
+
| OpenRouter | `openrouter/auto`, `openrouter/pareto-code`, `openrouter/free` |
|
|
69
|
+
| OpenRouter OpenAI | `openai/gpt-5.5`, `openai/gpt-5.4`, `openai/gpt-5.4-mini`, `openai/gpt-4o` |
|
|
70
|
+
| OpenRouter Anthropic | Claude routes such as `anthropic/claude-sonnet-4.6`, `anthropic/claude-opus-4.7`, `anthropic/claude-opus-4.8-fast` |
|
|
71
|
+
| OpenRouter Google | Gemini/Gemma routes such as `google/gemini-3.5-flash`, `google/gemini-3.1-flash-lite`, `google/gemma-4-31b-it` |
|
|
72
|
+
| OpenRouter DeepSeek | `deepseek/deepseek-v4-flash`, `deepseek/deepseek-v4-pro`, `deepseek/deepseek-r1-0528` |
|
|
73
|
+
| OpenRouter Qwen | Qwen routes such as `qwen/qwen3.7-max`, `qwen/qwen3.6-flash`, `qwen/qwen3.6-plus` |
|
|
74
|
+
| OpenRouter Meta/Mistral/Moonshot/xAI | `meta-llama/llama-4-maverick`, `mistralai/mistral-medium-3-5`, `moonshotai/kimi-k2.6`, `x-ai/grok-4.3` |
|
|
66
75
|
| Venice GPT | GPT-family Venice routes such as `openai-gpt-55`, `openai-gpt-54`, `openai-gpt-54-mini`, `openai-gpt-53-codex`, `openai-gpt-52` |
|
|
67
76
|
| Venice Gemma | Gemma instruct routes such as `google-gemma-4-31b-it`, `google-gemma-4-26b-a4b-it`, `google-gemma-3-27b-it` |
|
|
68
77
|
| Venice Claude | Claude Sonnet/Opus routes such as `claude-sonnet-4-6`, `claude-opus-4-7`, `claude-opus-4-6` |
|
|
@@ -96,6 +105,16 @@ It keeps smart routing enabled. If the Venice key is missing, run `/auth venice`
|
|
|
96
105
|
| --- | --- | --- |
|
|
97
106
|
| `deepseek` | DeepSeek | Default route/main because V4 Flash and V4 Pro are cheap and strong. |
|
|
98
107
|
| `openai` | OpenAI | Spare/frontier checks, Codex-family work, and explicit manual routes. |
|
|
108
|
+
| `openrouter` | OpenRouter | OpenAI-compatible gateway with auto/free/code routers. |
|
|
109
|
+
| `openrouter-openai` | OpenRouter | OpenAI-family models through OpenRouter. |
|
|
110
|
+
| `openrouter-anthropic` | OpenRouter | Claude-family models through OpenRouter. |
|
|
111
|
+
| `openrouter-google` | OpenRouter | Gemini/Gemma models through OpenRouter. |
|
|
112
|
+
| `openrouter-deepseek` | OpenRouter | DeepSeek models through OpenRouter. |
|
|
113
|
+
| `openrouter-qwen` | OpenRouter | Qwen models through OpenRouter. |
|
|
114
|
+
| `openrouter-meta` | OpenRouter | Meta Llama models through OpenRouter. |
|
|
115
|
+
| `openrouter-mistral` | OpenRouter | Mistral models through OpenRouter. |
|
|
116
|
+
| `openrouter-moonshot` | OpenRouter | Moonshot/Kimi models through OpenRouter. |
|
|
117
|
+
| `openrouter-xai` | OpenRouter | xAI Grok models through OpenRouter. |
|
|
99
118
|
| `qwen` | Qwen | Chinese and general-purpose OpenAI-compatible tasks. |
|
|
100
119
|
| `venice` | Venice | Venice-native text shortcuts: Venice 1.2, Venice 1.1, and Gemma 4 Uncensored. |
|
|
101
120
|
| `venice-gpt` | Venice | GPT-family models through Venice. |
|
|
@@ -118,8 +137,10 @@ Keys are set per project and stored only in ignored `.aginti/.env`:
|
|
|
118
137
|
|
|
119
138
|
```bash
|
|
120
139
|
aginti auth
|
|
140
|
+
aginti auth openrouter
|
|
121
141
|
aginti auth venice
|
|
122
142
|
aginti keys status
|
|
143
|
+
printf '%s' "$OPENROUTER_API_KEY" | aginti keys set openrouter --stdin
|
|
123
144
|
printf '%s' "$VENICE_API_KEY" | aginti keys set venice --stdin
|
|
124
145
|
```
|
|
125
146
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.188",
|
|
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
|
@@ -820,6 +820,7 @@ const ariaLabelNodes = [...document.querySelectorAll("[data-i18n-aria-label]")];
|
|
|
820
820
|
|
|
821
821
|
const defaults = {
|
|
822
822
|
openai: "gpt-5.4-mini",
|
|
823
|
+
openrouter: "openrouter/auto",
|
|
823
824
|
deepseek: "deepseek-v4-flash",
|
|
824
825
|
qwen: "qwen-plus",
|
|
825
826
|
venice: "venice-uncensored-1-2",
|
|
@@ -983,6 +984,7 @@ function renderKeyStatus(status = lastKeyStatus) {
|
|
|
983
984
|
if (!status) return;
|
|
984
985
|
const providers = [
|
|
985
986
|
["OpenAI", status.openai],
|
|
987
|
+
["OpenRouter", status.openrouter],
|
|
986
988
|
["DeepSeek", status.deepseek],
|
|
987
989
|
["Qwen", status.qwen],
|
|
988
990
|
["Venice", status.venice],
|
|
@@ -1009,7 +1011,7 @@ function renderKeyStatus(status = lastKeyStatus) {
|
|
|
1009
1011
|
})
|
|
1010
1012
|
);
|
|
1011
1013
|
}
|
|
1012
|
-
if (setupCardEl) setupCardEl.hidden = Boolean(status.openai || status.deepseek || status.qwen || status.venice);
|
|
1014
|
+
if (setupCardEl) setupCardEl.hidden = Boolean(status.openai || status.openrouter || status.deepseek || status.qwen || status.venice);
|
|
1013
1015
|
}
|
|
1014
1016
|
|
|
1015
1017
|
function renderProjectStatus(info = projectInfo) {
|
|
@@ -1251,6 +1253,37 @@ function workspaceFilesByLane() {
|
|
|
1251
1253
|
return groups;
|
|
1252
1254
|
}
|
|
1253
1255
|
|
|
1256
|
+
function buildWorkspaceFolderTree(files = []) {
|
|
1257
|
+
const root = { name: "", path: "", dirs: new Map(), files: [] };
|
|
1258
|
+
for (const file of files) {
|
|
1259
|
+
const parts = String(file.path || "")
|
|
1260
|
+
.split("/")
|
|
1261
|
+
.filter(Boolean);
|
|
1262
|
+
if (!parts.length) continue;
|
|
1263
|
+
const fileName = parts.pop();
|
|
1264
|
+
let node = root;
|
|
1265
|
+
let currentPath = "";
|
|
1266
|
+
for (const part of parts) {
|
|
1267
|
+
currentPath = currentPath ? `${currentPath}/${part}` : part;
|
|
1268
|
+
if (!node.dirs.has(part)) node.dirs.set(part, { name: part, path: currentPath, dirs: new Map(), files: [] });
|
|
1269
|
+
node = node.dirs.get(part);
|
|
1270
|
+
}
|
|
1271
|
+
node.files.push({ ...file, name: file.name || fileName });
|
|
1272
|
+
}
|
|
1273
|
+
return root;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
function workspaceFolderCount(node) {
|
|
1277
|
+
if (!node) return 0;
|
|
1278
|
+
let count = node.files?.length || 0;
|
|
1279
|
+
for (const child of node.dirs?.values?.() || []) count += workspaceFolderCount(child);
|
|
1280
|
+
return count;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
function sortWorkspaceFiles(left, right) {
|
|
1284
|
+
return String(left.path || "").localeCompare(String(right.path || ""));
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1254
1287
|
function workspaceActiveFile() {
|
|
1255
1288
|
return workspaceBrowser.files.find((file) => file.path === workspaceBrowser.activePath) || null;
|
|
1256
1289
|
}
|
|
@@ -1279,12 +1312,18 @@ function renderWorkspaceExplorer() {
|
|
|
1279
1312
|
const activeLane = workspaceBrowser.activeLane || "all";
|
|
1280
1313
|
const warnings = workspaceBrowser.warnings?.length ? ` · ${workspaceBrowser.warnings.length} warning(s)` : "";
|
|
1281
1314
|
const truncated = workspaceBrowser.truncated ? " · truncated" : "";
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1315
|
+
if (workspaceBrowser.loading) {
|
|
1316
|
+
workspaceBrowserStatusEl.textContent = "Loading workspace...";
|
|
1317
|
+
} else if (workspaceBrowser.error) {
|
|
1318
|
+
workspaceBrowserStatusEl.textContent = `Workspace unavailable: ${workspaceBrowser.error}`;
|
|
1319
|
+
} else {
|
|
1320
|
+
workspaceBrowserStatusEl.innerHTML = `
|
|
1321
|
+
<span class="workspace-status-chip">${workspaceBrowser.files.length} files</span>
|
|
1322
|
+
<span class="workspace-status-chip">${escapeHtml(activeLane)}</span>
|
|
1323
|
+
<code class="workspace-root-path">${escapeHtml(workspaceBrowser.root || workspaceRoot())}</code>
|
|
1324
|
+
${warnings || truncated ? `<span class="workspace-status-warn">${escapeHtml(`${warnings}${truncated}`.replace(/^ · /, ""))}</span>` : ""}
|
|
1325
|
+
`;
|
|
1326
|
+
}
|
|
1288
1327
|
|
|
1289
1328
|
workspaceLanesEl.innerHTML = WORKSPACE_LANES.map((lane) => {
|
|
1290
1329
|
const count = groups[lane.id]?.length || 0;
|
|
@@ -1302,34 +1341,69 @@ function renderWorkspaceExplorer() {
|
|
|
1302
1341
|
`;
|
|
1303
1342
|
}).join("");
|
|
1304
1343
|
|
|
1305
|
-
const visibleFiles = (groups[activeLane] || []).slice().sort(
|
|
1344
|
+
const visibleFiles = (groups[activeLane] || []).slice().sort(sortWorkspaceFiles);
|
|
1306
1345
|
if (!visibleFiles.length) {
|
|
1307
1346
|
workspaceTreeEl.innerHTML = `<p class="subtle workspace-empty">No files in this category.</p>`;
|
|
1308
1347
|
return;
|
|
1309
1348
|
}
|
|
1310
1349
|
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1350
|
+
const tree = buildWorkspaceFolderTree(visibleFiles);
|
|
1351
|
+
workspaceTreeEl.innerHTML = `
|
|
1352
|
+
<div class="workspace-tree-toolbar">
|
|
1353
|
+
<span>${escapeHtml(WORKSPACE_LANES.find((lane) => lane.id === activeLane)?.label || "Files")}</span>
|
|
1354
|
+
<strong>${visibleFiles.length}</strong>
|
|
1355
|
+
</div>
|
|
1356
|
+
<div class="workspace-folder-root">
|
|
1357
|
+
${renderWorkspaceFolderNode(tree, 0)}
|
|
1358
|
+
</div>
|
|
1359
|
+
`;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
function renderWorkspaceFileNode(file, depth = 0) {
|
|
1363
|
+
const lane = inferWorkspaceLane(file);
|
|
1364
|
+
const active = file.path === workspaceBrowser.activePath;
|
|
1365
|
+
const meta = [lane, formatBytes(file.size), file.binary ? "binary" : "text"].join(" · ");
|
|
1366
|
+
return `
|
|
1367
|
+
<button
|
|
1368
|
+
type="button"
|
|
1369
|
+
class="workspace-file-row workspace-tree-file"
|
|
1370
|
+
data-workspace-file="${escapeHtml(file.path)}"
|
|
1371
|
+
data-selected="${active}"
|
|
1372
|
+
draggable="true"
|
|
1373
|
+
style="--depth: ${depth};"
|
|
1374
|
+
>
|
|
1375
|
+
<span class="workspace-file-icon" aria-hidden="true">${file.binary ? "bin" : "txt"}</span>
|
|
1376
|
+
<span class="workspace-file-main">
|
|
1377
|
+
<strong>${escapeHtml(workspaceBaseName(file.path))}</strong>
|
|
1378
|
+
<small>${escapeHtml(workspaceDir(file.path) || ".")}</small>
|
|
1379
|
+
</span>
|
|
1380
|
+
<span class="workspace-file-meta">${escapeHtml(meta)}</span>
|
|
1381
|
+
</button>
|
|
1382
|
+
`;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
function renderWorkspaceFolderNode(node, depth = 0) {
|
|
1386
|
+
const dirs = [...(node.dirs?.values?.() || [])].sort((left, right) => left.name.localeCompare(right.name));
|
|
1387
|
+
const files = (node.files || []).slice().sort(sortWorkspaceFiles);
|
|
1388
|
+
const children = [
|
|
1389
|
+
...dirs.map((child) => renderWorkspaceFolderNode(child, depth + 1)),
|
|
1390
|
+
...files.map((file) => renderWorkspaceFileNode(file, depth)),
|
|
1391
|
+
].join("");
|
|
1392
|
+
if (depth === 0) return children;
|
|
1393
|
+
const activeInside = workspaceBrowser.activePath && workspaceBrowser.activePath.startsWith(`${node.path}/`);
|
|
1394
|
+
const open = depth <= 2 || activeInside;
|
|
1395
|
+
return `
|
|
1396
|
+
<details class="workspace-folder" ${open ? "open" : ""} style="--depth: ${Math.max(depth - 1, 0)};">
|
|
1397
|
+
<summary>
|
|
1398
|
+
<span class="workspace-folder-icon" aria-hidden="true">></span>
|
|
1399
|
+
<span class="workspace-folder-name">${escapeHtml(node.name)}</span>
|
|
1400
|
+
<small>${workspaceFolderCount(node)}</small>
|
|
1401
|
+
</summary>
|
|
1402
|
+
<div class="workspace-folder-children">
|
|
1403
|
+
${children}
|
|
1404
|
+
</div>
|
|
1405
|
+
</details>
|
|
1406
|
+
`;
|
|
1333
1407
|
}
|
|
1334
1408
|
|
|
1335
1409
|
function renderWorkspaceWorkbench() {
|
|
@@ -1539,6 +1613,7 @@ function fieldValue(field) {
|
|
|
1539
1613
|
const providerLabels = {
|
|
1540
1614
|
deepseek: "DeepSeek",
|
|
1541
1615
|
openai: "OpenAI",
|
|
1616
|
+
openrouter: "OpenRouter",
|
|
1542
1617
|
qwen: "Qwen",
|
|
1543
1618
|
venice: "Venice",
|
|
1544
1619
|
mock: "Mock local",
|
|
@@ -1562,14 +1637,14 @@ function setChoiceOptions(select, options, selectedValue = "", fallbackValue = "
|
|
|
1562
1637
|
}
|
|
1563
1638
|
|
|
1564
1639
|
function configuredTextProviders({ includeMock = true } = {}) {
|
|
1565
|
-
const base = ["deepseek", "openai", "qwen", "venice"];
|
|
1640
|
+
const base = ["deepseek", "openai", "openrouter", "qwen", "venice"];
|
|
1566
1641
|
if (includeMock) base.push("mock");
|
|
1567
1642
|
if (Object.keys(modelCatalog || {}).length === 0) return base;
|
|
1568
1643
|
return base.filter((provider) => provider === "mock" || Array.isArray(modelCatalog[provider]));
|
|
1569
1644
|
}
|
|
1570
1645
|
|
|
1571
1646
|
function refreshProviderDropdowns() {
|
|
1572
|
-
setChoiceOptions(setupProviderField, ["deepseek", "openai", "qwen", "venice", "grsai"], setupProviderField?.value || "deepseek", "deepseek");
|
|
1647
|
+
setChoiceOptions(setupProviderField, ["deepseek", "openai", "openrouter", "qwen", "venice", "grsai"], setupProviderField?.value || "deepseek", "deepseek");
|
|
1573
1648
|
setChoiceOptions(providerField, configuredTextProviders({ includeMock: true }), providerField?.value || "deepseek", "deepseek");
|
|
1574
1649
|
setChoiceOptions(routeProviderField, configuredTextProviders({ includeMock: true }), routeProviderField?.value || "deepseek", "deepseek");
|
|
1575
1650
|
setChoiceOptions(mainProviderField, configuredTextProviders({ includeMock: false }), mainProviderField?.value || "deepseek", "deepseek");
|
|
@@ -3802,7 +3877,13 @@ deleteSessionButton.addEventListener("click", () => {
|
|
|
3802
3877
|
});
|
|
3803
3878
|
|
|
3804
3879
|
providerField.addEventListener("change", () => {
|
|
3805
|
-
if (
|
|
3880
|
+
if (
|
|
3881
|
+
providerField.value === "mock" ||
|
|
3882
|
+
providerField.value === "venice" ||
|
|
3883
|
+
providerField.value === "openai" ||
|
|
3884
|
+
providerField.value === "openrouter" ||
|
|
3885
|
+
providerField.value === "qwen"
|
|
3886
|
+
) {
|
|
3806
3887
|
routingModeField.value = "manual";
|
|
3807
3888
|
}
|
|
3808
3889
|
|
|
@@ -4136,6 +4217,7 @@ async function loadConfig() {
|
|
|
4136
4217
|
taskProfiles = data.taskProfiles || [];
|
|
4137
4218
|
projectInfo = data.project || null;
|
|
4138
4219
|
defaults.openai = data.defaults?.openai?.model || defaults.openai;
|
|
4220
|
+
defaults.openrouter = data.defaults?.openrouter?.model || defaults.openrouter;
|
|
4139
4221
|
defaults.qwen = data.defaults?.qwen?.model || defaults.qwen;
|
|
4140
4222
|
defaults.venice = data.defaults?.venice?.model || defaults.venice;
|
|
4141
4223
|
defaults.deepseek = routingPresets.fast?.model || data.defaults?.deepseek?.model || defaults.deepseek;
|
package/public/index.html
CHANGED
|
@@ -65,10 +65,10 @@
|
|
|
65
65
|
<div>
|
|
66
66
|
<strong data-i18n="setupTitle">Provider setup</strong>
|
|
67
67
|
<p class="subtle" data-i18n="setupHelp">
|
|
68
|
-
DeepSeek/OpenAI/Qwen/Venice keys are missing. Use mock mode, export an env var, or save a project-local key.
|
|
68
|
+
DeepSeek/OpenAI/OpenRouter/Qwen/Venice keys are missing. Use mock mode, export an env var, or save a project-local key.
|
|
69
69
|
</p>
|
|
70
70
|
<p class="subtle" data-i18n="setupEnvHelp">
|
|
71
|
-
Env vars: DEEPSEEK_API_KEY, OPENAI_API_KEY, QWEN_API_KEY, VENICE_API_KEY, or LLM_API_KEY. Mock mode remains available for local tests.
|
|
71
|
+
Env vars: DEEPSEEK_API_KEY, OPENAI_API_KEY, OPENROUTER_API_KEY, QWEN_API_KEY, VENICE_API_KEY, or LLM_API_KEY. Mock mode remains available for local tests.
|
|
72
72
|
</p>
|
|
73
73
|
<p class="subtle key-links">
|
|
74
74
|
<span data-i18n="setupKeyLinksLabel">Get keys:</span>
|
|
@@ -76,6 +76,8 @@
|
|
|
76
76
|
<span aria-hidden="true">·</span>
|
|
77
77
|
<a href="https://platform.openai.com/api-keys" target="_blank" rel="noreferrer" data-i18n="openaiKeyLink">OpenAI API keys</a>
|
|
78
78
|
<span aria-hidden="true">·</span>
|
|
79
|
+
<a href="https://openrouter.ai/settings/keys" target="_blank" rel="noreferrer">OpenRouter API keys</a>
|
|
80
|
+
<span aria-hidden="true">·</span>
|
|
79
81
|
<a href="https://venice.ai" target="_blank" rel="noreferrer">Venice API</a>
|
|
80
82
|
</p>
|
|
81
83
|
</div>
|
|
@@ -85,6 +87,7 @@
|
|
|
85
87
|
<select id="setup-provider">
|
|
86
88
|
<option value="deepseek">DeepSeek</option>
|
|
87
89
|
<option value="openai">OpenAI</option>
|
|
90
|
+
<option value="openrouter">OpenRouter</option>
|
|
88
91
|
<option value="qwen">Qwen</option>
|
|
89
92
|
<option value="venice">Venice</option>
|
|
90
93
|
<option value="grsai">GRS AI image</option>
|
|
@@ -132,6 +135,7 @@
|
|
|
132
135
|
<select id="provider" name="provider">
|
|
133
136
|
<option value="deepseek">DeepSeek</option>
|
|
134
137
|
<option value="openai">OpenAI</option>
|
|
138
|
+
<option value="openrouter">OpenRouter</option>
|
|
135
139
|
<option value="qwen">Qwen</option>
|
|
136
140
|
<option value="venice">Venice</option>
|
|
137
141
|
<option value="mock" data-i18n="mockProviderOption">Mock local</option>
|
|
@@ -414,6 +418,7 @@
|
|
|
414
418
|
<select id="routeProvider" name="routeProvider">
|
|
415
419
|
<option value="deepseek">DeepSeek</option>
|
|
416
420
|
<option value="openai">OpenAI</option>
|
|
421
|
+
<option value="openrouter">OpenRouter</option>
|
|
417
422
|
<option value="qwen">Qwen</option>
|
|
418
423
|
<option value="venice">Venice</option>
|
|
419
424
|
<option value="mock">Mock</option>
|
|
@@ -427,6 +432,7 @@
|
|
|
427
432
|
<select id="mainProvider" name="mainProvider">
|
|
428
433
|
<option value="deepseek">DeepSeek</option>
|
|
429
434
|
<option value="openai">OpenAI</option>
|
|
435
|
+
<option value="openrouter">OpenRouter</option>
|
|
430
436
|
<option value="qwen">Qwen</option>
|
|
431
437
|
<option value="venice">Venice</option>
|
|
432
438
|
</select>
|
|
@@ -438,6 +444,7 @@
|
|
|
438
444
|
<span>Spare</span>
|
|
439
445
|
<select id="spareProvider" name="spareProvider">
|
|
440
446
|
<option value="openai">OpenAI</option>
|
|
447
|
+
<option value="openrouter">OpenRouter</option>
|
|
441
448
|
<option value="deepseek">DeepSeek</option>
|
|
442
449
|
<option value="qwen">Qwen</option>
|
|
443
450
|
<option value="venice">Venice</option>
|
package/public/styles.css
CHANGED
|
@@ -959,10 +959,43 @@ button.danger {
|
|
|
959
959
|
}
|
|
960
960
|
|
|
961
961
|
.workspace-browser-status {
|
|
962
|
+
display: flex;
|
|
963
|
+
flex-wrap: wrap;
|
|
964
|
+
align-items: center;
|
|
965
|
+
gap: 7px;
|
|
962
966
|
line-height: 1.35;
|
|
963
967
|
overflow-wrap: anywhere;
|
|
964
968
|
}
|
|
965
969
|
|
|
970
|
+
.workspace-status-chip {
|
|
971
|
+
padding: 4px 8px;
|
|
972
|
+
border: 1px solid rgba(15, 118, 110, 0.16);
|
|
973
|
+
border-radius: 999px;
|
|
974
|
+
background: rgba(255, 253, 250, 0.86);
|
|
975
|
+
color: var(--ink);
|
|
976
|
+
font-size: 0.76rem;
|
|
977
|
+
font-weight: 700;
|
|
978
|
+
text-transform: capitalize;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
.workspace-root-path {
|
|
982
|
+
min-width: 0;
|
|
983
|
+
max-width: 100%;
|
|
984
|
+
padding: 5px 8px;
|
|
985
|
+
border: 1px solid rgba(15, 118, 110, 0.14);
|
|
986
|
+
border-radius: 10px;
|
|
987
|
+
background: rgba(13, 148, 136, 0.07);
|
|
988
|
+
color: #155e75;
|
|
989
|
+
font-family: "IBM Plex Mono", "SFMono-Regular", monospace;
|
|
990
|
+
font-size: 0.76rem;
|
|
991
|
+
overflow-wrap: anywhere;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
.workspace-status-warn {
|
|
995
|
+
color: #b45309;
|
|
996
|
+
font-size: 0.76rem;
|
|
997
|
+
}
|
|
998
|
+
|
|
966
999
|
.workspace-lanes {
|
|
967
1000
|
display: grid;
|
|
968
1001
|
grid-template-columns: repeat(auto-fit, minmax(82px, 1fr));
|
|
@@ -995,11 +1028,105 @@ button.danger {
|
|
|
995
1028
|
}
|
|
996
1029
|
|
|
997
1030
|
.workspace-tree {
|
|
998
|
-
display: grid;
|
|
999
|
-
gap: 7px;
|
|
1000
1031
|
max-height: 440px;
|
|
1001
1032
|
overflow: auto;
|
|
1002
|
-
padding
|
|
1033
|
+
padding: 8px;
|
|
1034
|
+
border: 1px solid rgba(15, 118, 110, 0.12);
|
|
1035
|
+
border-radius: 16px;
|
|
1036
|
+
background:
|
|
1037
|
+
linear-gradient(180deg, rgba(255, 253, 250, 0.88), rgba(240, 253, 250, 0.58)),
|
|
1038
|
+
rgba(255, 255, 255, 0.72);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
.workspace-tree-toolbar {
|
|
1042
|
+
position: sticky;
|
|
1043
|
+
top: 0;
|
|
1044
|
+
z-index: 1;
|
|
1045
|
+
display: flex;
|
|
1046
|
+
justify-content: space-between;
|
|
1047
|
+
align-items: center;
|
|
1048
|
+
gap: 10px;
|
|
1049
|
+
margin: -8px -8px 8px;
|
|
1050
|
+
padding: 8px 10px;
|
|
1051
|
+
border-bottom: 1px solid rgba(15, 118, 110, 0.1);
|
|
1052
|
+
background: rgba(255, 253, 250, 0.95);
|
|
1053
|
+
color: var(--muted);
|
|
1054
|
+
font-size: 0.78rem;
|
|
1055
|
+
font-weight: 700;
|
|
1056
|
+
text-transform: uppercase;
|
|
1057
|
+
letter-spacing: 0.03em;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
.workspace-tree-toolbar strong {
|
|
1061
|
+
color: var(--accent);
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
.workspace-folder-root,
|
|
1065
|
+
.workspace-folder-children {
|
|
1066
|
+
display: grid;
|
|
1067
|
+
gap: 4px;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
.workspace-folder {
|
|
1071
|
+
margin-left: calc(var(--depth, 0) * 12px);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
.workspace-folder summary {
|
|
1075
|
+
display: flex;
|
|
1076
|
+
align-items: center;
|
|
1077
|
+
gap: 7px;
|
|
1078
|
+
min-height: 32px;
|
|
1079
|
+
padding: 6px 8px;
|
|
1080
|
+
border: 1px solid transparent;
|
|
1081
|
+
border-radius: 11px;
|
|
1082
|
+
color: var(--ink);
|
|
1083
|
+
cursor: pointer;
|
|
1084
|
+
list-style: none;
|
|
1085
|
+
user-select: none;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
.workspace-folder summary::-webkit-details-marker {
|
|
1089
|
+
display: none;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
.workspace-folder summary:hover {
|
|
1093
|
+
border-color: rgba(15, 118, 110, 0.16);
|
|
1094
|
+
background: rgba(240, 253, 250, 0.72);
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
.workspace-folder-icon {
|
|
1098
|
+
display: inline-grid;
|
|
1099
|
+
place-items: center;
|
|
1100
|
+
width: 18px;
|
|
1101
|
+
height: 18px;
|
|
1102
|
+
border: 1px solid rgba(15, 118, 110, 0.18);
|
|
1103
|
+
border-radius: 6px;
|
|
1104
|
+
color: var(--accent);
|
|
1105
|
+
font-family: "IBM Plex Mono", "SFMono-Regular", monospace;
|
|
1106
|
+
font-size: 0.68rem;
|
|
1107
|
+
transition: transform 0.16s ease;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
.workspace-folder[open] > summary .workspace-folder-icon {
|
|
1111
|
+
transform: rotate(90deg);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
.workspace-folder-name {
|
|
1115
|
+
min-width: 0;
|
|
1116
|
+
overflow: hidden;
|
|
1117
|
+
text-overflow: ellipsis;
|
|
1118
|
+
white-space: nowrap;
|
|
1119
|
+
font-weight: 750;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
.workspace-folder summary small {
|
|
1123
|
+
margin-left: auto;
|
|
1124
|
+
color: var(--muted);
|
|
1125
|
+
font-size: 0.72rem;
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
.workspace-folder-children {
|
|
1129
|
+
margin-top: 4px;
|
|
1003
1130
|
}
|
|
1004
1131
|
|
|
1005
1132
|
.workspace-empty {
|
|
@@ -1011,18 +1138,23 @@ button.danger {
|
|
|
1011
1138
|
|
|
1012
1139
|
.workspace-file-row {
|
|
1013
1140
|
display: grid;
|
|
1014
|
-
grid-template-columns: minmax(0, 1fr);
|
|
1015
|
-
gap:
|
|
1141
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
1142
|
+
gap: 6px 8px;
|
|
1143
|
+
align-items: center;
|
|
1016
1144
|
width: 100%;
|
|
1017
|
-
padding: 10px
|
|
1145
|
+
padding: 8px 10px;
|
|
1018
1146
|
border: 1px solid rgba(217, 119, 6, 0.16);
|
|
1019
|
-
border-radius:
|
|
1147
|
+
border-radius: 12px;
|
|
1020
1148
|
background: rgba(255, 253, 250, 0.72);
|
|
1021
1149
|
color: var(--ink);
|
|
1022
1150
|
cursor: pointer;
|
|
1023
1151
|
text-align: left;
|
|
1024
1152
|
}
|
|
1025
1153
|
|
|
1154
|
+
.workspace-tree-file {
|
|
1155
|
+
margin-left: calc(var(--depth, 0) * 12px);
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1026
1158
|
.workspace-file-row:hover {
|
|
1027
1159
|
border-color: rgba(15, 118, 110, 0.34);
|
|
1028
1160
|
background: rgba(240, 253, 250, 0.72);
|
|
@@ -1030,10 +1162,24 @@ button.danger {
|
|
|
1030
1162
|
|
|
1031
1163
|
.workspace-file-row[data-selected="true"] {
|
|
1032
1164
|
border-color: rgba(15, 118, 110, 0.58);
|
|
1033
|
-
background: linear-gradient(135deg, rgba(15, 118, 110, 0.
|
|
1165
|
+
background: linear-gradient(135deg, rgba(15, 118, 110, 0.22), rgba(255, 255, 255, 0.96));
|
|
1034
1166
|
box-shadow: 0 0 0 2px rgba(15, 118, 110, 0.1);
|
|
1035
1167
|
}
|
|
1036
1168
|
|
|
1169
|
+
.workspace-file-icon {
|
|
1170
|
+
display: inline-grid;
|
|
1171
|
+
place-items: center;
|
|
1172
|
+
width: 30px;
|
|
1173
|
+
height: 24px;
|
|
1174
|
+
border-radius: 8px;
|
|
1175
|
+
background: rgba(15, 118, 110, 0.09);
|
|
1176
|
+
color: #155e75;
|
|
1177
|
+
font-family: "IBM Plex Mono", "SFMono-Regular", monospace;
|
|
1178
|
+
font-size: 0.62rem;
|
|
1179
|
+
font-weight: 800;
|
|
1180
|
+
text-transform: uppercase;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1037
1183
|
.workspace-file-main {
|
|
1038
1184
|
display: grid;
|
|
1039
1185
|
gap: 1px;
|
|
@@ -1050,6 +1196,7 @@ button.danger {
|
|
|
1050
1196
|
|
|
1051
1197
|
.workspace-file-main small,
|
|
1052
1198
|
.workspace-file-meta {
|
|
1199
|
+
grid-column: 2;
|
|
1053
1200
|
color: var(--muted);
|
|
1054
1201
|
font-size: 0.76rem;
|
|
1055
1202
|
}
|
|
@@ -10,6 +10,28 @@ This note records the working publication route for AgInTiFlow so future release
|
|
|
10
10
|
|
|
11
11
|
Latest verified release:
|
|
12
12
|
|
|
13
|
+
- Version: `0.20.187`
|
|
14
|
+
- Commit: `9339b2e`
|
|
15
|
+
- GitHub Actions run: `https://github.com/lazyingart/AgInTiFlow/actions/runs/26701125864`
|
|
16
|
+
- Workflow result: success
|
|
17
|
+
- npm registry check: `npm view @lazyingart/agintiflow version dist-tags.latest --registry=https://registry.npmjs.org` returned `0.20.187`.
|
|
18
|
+
- Installed verification: `npm install -g @lazyingart/agintiflow@0.20.187` then `aginti --version` returned `0.20.187`.
|
|
19
|
+
- Webapp verification: `aginti webapp restart --port 3210` then `curl -fsS http://127.0.0.1:3210/health` returned `version":"0.20.187"` from the global npm package path.
|
|
20
|
+
- Workspace explorer verification: `POST /api/workspace/snapshot` returned no `.aginti/`, `.aginti-work/`, `.sessions/`, or `.env` entries for the project root.
|
|
21
|
+
|
|
22
|
+
Previous verified release:
|
|
23
|
+
|
|
24
|
+
- Version: `0.20.186`
|
|
25
|
+
- Commit: `f32a748`
|
|
26
|
+
- GitHub Actions run: `https://github.com/lazyingart/AgInTiFlow/actions/runs/26700782132`
|
|
27
|
+
- Workflow result: success
|
|
28
|
+
- npm registry check: `npm view @lazyingart/agintiflow version dist-tags.latest --registry=https://registry.npmjs.org` returned `0.20.186`.
|
|
29
|
+
- Installed verification: `npm install -g @lazyingart/agintiflow@0.20.186` then `aginti --version` returned `0.20.186`.
|
|
30
|
+
- Webapp verification: `aginti webapp restart --port 3210` then `curl -fsS http://127.0.0.1:3210/health` returned `version":"0.20.186"` from the global npm package path.
|
|
31
|
+
- Direct image CLI verification: `aginti image --json --dry-run --format svg` returned `requestedFormat:"svg"`, `actualFormat:"png"`, and a clear raster PNG fallback notice.
|
|
32
|
+
|
|
33
|
+
Previous verified release:
|
|
34
|
+
|
|
13
35
|
- Version: `0.20.185`
|
|
14
36
|
- Commit: `58d6087`
|
|
15
37
|
- GitHub Actions run: `https://github.com/lazyingart/AgInTiFlow/actions/runs/26700387931`
|