@lazyingart/agintiflow 0.20.49 → 0.20.50
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 +15 -2
- package/docs/aaps.md +70 -0
- package/docs/student-committee-supervisor.md +104 -0
- package/package.json +4 -2
- package/references/aaps-agintiflow-integration-design.md +710 -0
- package/references/student-committee-supervisor-mode.md +331 -0
- package/scripts/smoke-aaps-adapter.js +67 -0
- package/skills/aaps/SKILL.md +23 -2
- package/src/aaps-adapter.js +742 -0
- package/src/agent-runner.js +216 -5
- package/src/cli.js +57 -1
- package/src/config.js +24 -7
- package/src/i18n.js +1 -0
- package/src/interactive-cli.js +73 -1
- package/src/scs-controller.js +471 -0
- package/src/task-profiles.js +2 -1
package/src/agent-runner.js
CHANGED
|
@@ -27,6 +27,15 @@ import { hostShellOption, platformInfo, platformLabel } from "./platform.js";
|
|
|
27
27
|
import { captureTmuxPane, listTmuxSessions, sendTmuxKeys, startTmuxSession } from "./tmux-tools.js";
|
|
28
28
|
import { languageInstruction } from "./i18n.js";
|
|
29
29
|
import { flushHousekeeping } from "./housekeeping.js";
|
|
30
|
+
import {
|
|
31
|
+
buildSupervisorInstruction,
|
|
32
|
+
createScsPlan,
|
|
33
|
+
reviewScsFinish,
|
|
34
|
+
reviewScsProgress,
|
|
35
|
+
reviewScsToolResult,
|
|
36
|
+
shouldReviewScsProgress,
|
|
37
|
+
shouldReviewToolResult,
|
|
38
|
+
} from "./scs-controller.js";
|
|
30
39
|
|
|
31
40
|
const exec = promisify(execCallback);
|
|
32
41
|
const BROWSER_TOOLS = new Set(["open_url", "open_workspace_file", "preview_workspace", "click", "type", "scroll", "press", "back"]);
|
|
@@ -332,6 +341,9 @@ async function createInitialState(config, sessionId) {
|
|
|
332
341
|
config.allowParallelScouts
|
|
333
342
|
? `Parallel DeepSeek scouts may run before complex execution. Scout count: ${config.parallelScoutCount}.`
|
|
334
343
|
: "Parallel scouts are disabled.",
|
|
344
|
+
config.scsActive
|
|
345
|
+
? "Student-Committee-Supervisor mode is active. A committee/student gate will approve a phase plan, and you will execute as the supervisor under the approved phase constraints."
|
|
346
|
+
: "",
|
|
335
347
|
`Task profile: ${taskProfile.label}. ${taskProfile.prompt}`,
|
|
336
348
|
skillContext,
|
|
337
349
|
engineeringGuidance,
|
|
@@ -378,6 +390,7 @@ async function createInitialState(config, sessionId) {
|
|
|
378
390
|
: "",
|
|
379
391
|
config.allowWebSearch ? "Web search tool: enabled." : "Web search tool: disabled.",
|
|
380
392
|
config.allowParallelScouts ? `Parallel scouts: enabled count=${config.parallelScoutCount}.` : "Parallel scouts: disabled.",
|
|
393
|
+
config.scsActive ? "SCS mode: active. Wait for the approved supervisor phase instruction before treating the plan as executable." : "",
|
|
381
394
|
`Task profile: ${taskProfile.label}. ${taskProfile.prompt}`,
|
|
382
395
|
skillContext,
|
|
383
396
|
engineeringGuidance,
|
|
@@ -1283,6 +1296,8 @@ export async function runAgent(config) {
|
|
|
1283
1296
|
model: config.model,
|
|
1284
1297
|
routingMode: config.routingMode,
|
|
1285
1298
|
routeReason: config.routeReason,
|
|
1299
|
+
scsActive: Boolean(config.scsActive),
|
|
1300
|
+
scsMode: config.enableScs || "off",
|
|
1286
1301
|
goal: config.goal,
|
|
1287
1302
|
});
|
|
1288
1303
|
await store.appendEvent("skills.selected", {
|
|
@@ -1305,17 +1320,75 @@ export async function runAgent(config) {
|
|
|
1305
1320
|
model: config.model,
|
|
1306
1321
|
routingMode: config.routingMode,
|
|
1307
1322
|
routeReason: config.routeReason,
|
|
1323
|
+
scsActive: Boolean(config.scsActive),
|
|
1324
|
+
scsMode: config.enableScs || "off",
|
|
1308
1325
|
});
|
|
1309
1326
|
|
|
1310
1327
|
try {
|
|
1311
1328
|
throwIfAborted(config);
|
|
1312
1329
|
if (!state.plan) {
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1330
|
+
if (config.scsActive) {
|
|
1331
|
+
const scsPlan = await createScsPlan(client, config, state, {
|
|
1332
|
+
events: await store.loadEvents(),
|
|
1333
|
+
taskProfile: config.taskProfile,
|
|
1334
|
+
goal: config.goal,
|
|
1335
|
+
});
|
|
1336
|
+
state.plan = scsPlan.plan;
|
|
1337
|
+
state.meta.scs = scsPlan.scs;
|
|
1338
|
+
state.messages.push({
|
|
1339
|
+
role: "user",
|
|
1340
|
+
content: scsPlan.supervisorInstruction,
|
|
1341
|
+
});
|
|
1342
|
+
state.meta.scs.supervisorInstructionInjected = true;
|
|
1343
|
+
await store.saveJsonArtifact("scs-phase-001.json", scsPlan.scs).catch(() => "");
|
|
1344
|
+
await store.appendEvent("scs.enabled", {
|
|
1345
|
+
mode: config.enableScs,
|
|
1346
|
+
model: `${config.provider}/${config.model}`,
|
|
1347
|
+
});
|
|
1348
|
+
await store.appendEvent("scs.committee.plan_drafted", {
|
|
1349
|
+
phase: scsPlan.scs.phase,
|
|
1350
|
+
phaseGoal: scsPlan.scs.phaseGoal,
|
|
1351
|
+
plan: scsPlan.plan,
|
|
1352
|
+
acceptanceCriteria: scsPlan.scs.acceptanceCriteria,
|
|
1353
|
+
});
|
|
1354
|
+
await store.appendEvent(`scs.student.${scsPlan.scs.student.decision}`, scsPlan.scs.student);
|
|
1355
|
+
await store.appendEvent("scs.supervisor.phase_started", {
|
|
1356
|
+
phase: scsPlan.scs.phase,
|
|
1357
|
+
phaseGoal: scsPlan.scs.phaseGoal,
|
|
1358
|
+
});
|
|
1359
|
+
await store.savePlan(scsPlan.plan);
|
|
1360
|
+
await store.appendEvent("plan.created", { plan: scsPlan.plan, scs: true });
|
|
1361
|
+
await store.saveState(state);
|
|
1362
|
+
observers.event("plan.created", { plan: scsPlan.plan, scs: true });
|
|
1363
|
+
observers.event("scs.student.approve_plan", scsPlan.scs.student);
|
|
1364
|
+
emitConsole(config, `SCS: student approved phase plan (${Math.round((scsPlan.scs.student.confidence || 0) * 100)}%).`, {
|
|
1365
|
+
kind: "meta",
|
|
1366
|
+
});
|
|
1367
|
+
} else {
|
|
1368
|
+
const plan = await createPlan(client, config, state);
|
|
1369
|
+
state.plan = plan;
|
|
1370
|
+
await store.savePlan(plan);
|
|
1371
|
+
await store.appendEvent("plan.created", { plan });
|
|
1372
|
+
await store.saveState(state);
|
|
1373
|
+
observers.event("plan.created", { plan });
|
|
1374
|
+
}
|
|
1375
|
+
} else if (config.scsActive && !state.meta?.scs?.supervisorInstructionInjected) {
|
|
1376
|
+
state.meta.scs = state.meta.scs || {
|
|
1377
|
+
enabled: true,
|
|
1378
|
+
mode: config.enableScs || "on",
|
|
1379
|
+
active: true,
|
|
1380
|
+
model: `${config.provider}/${config.model}`,
|
|
1381
|
+
phase: 1,
|
|
1382
|
+
plan: state.plan,
|
|
1383
|
+
finishRejects: 0,
|
|
1384
|
+
monitorReviews: 0,
|
|
1385
|
+
};
|
|
1386
|
+
state.messages.push({
|
|
1387
|
+
role: "user",
|
|
1388
|
+
content: buildSupervisorInstruction(state.meta.scs),
|
|
1389
|
+
});
|
|
1390
|
+
state.meta.scs.supervisorInstructionInjected = true;
|
|
1317
1391
|
await store.saveState(state);
|
|
1318
|
-
observers.event("plan.created", { plan });
|
|
1319
1392
|
}
|
|
1320
1393
|
|
|
1321
1394
|
if (shouldRunParallelScouts(config, state)) {
|
|
@@ -1379,6 +1452,8 @@ export async function runAgent(config) {
|
|
|
1379
1452
|
routingMode: config.routingMode,
|
|
1380
1453
|
routeReason: config.routeReason,
|
|
1381
1454
|
taskProfile: config.taskProfile,
|
|
1455
|
+
scsActive: Boolean(config.scsActive),
|
|
1456
|
+
scsMode: config.enableScs || "off",
|
|
1382
1457
|
commandCwd: config.commandCwd,
|
|
1383
1458
|
allowShellTool: config.allowShellTool,
|
|
1384
1459
|
allowWrapperTools: config.allowWrapperTools,
|
|
@@ -1399,6 +1474,7 @@ export async function runAgent(config) {
|
|
|
1399
1474
|
emitConsole(config, `Provider: ${config.provider}`, { kind: "meta" });
|
|
1400
1475
|
emitConsole(config, `Model: ${config.model}`, { kind: "meta" });
|
|
1401
1476
|
emitConsole(config, `Routing: ${config.routingMode} (${config.routeReason})`, { kind: "meta" });
|
|
1477
|
+
if (config.scsActive) emitConsole(config, `SCS: ${config.enableScs || "on"} using main-model policy`, { kind: "meta" });
|
|
1402
1478
|
emitConsole(config, `Workspace: ${config.commandCwd}`, { kind: "meta" });
|
|
1403
1479
|
emitConsole(config, `Sessions: ${config.sessionsDir}`, { kind: "meta" });
|
|
1404
1480
|
if (config.projectSessionsDir) emitConsole(config, `Project session index: ${config.projectSessionsDir}`, { kind: "meta" });
|
|
@@ -1517,6 +1593,37 @@ export async function runAgent(config) {
|
|
|
1517
1593
|
continue;
|
|
1518
1594
|
}
|
|
1519
1595
|
const fallback = assistantMessage.content?.trim() || "No tool call returned.";
|
|
1596
|
+
if (config.scsActive) {
|
|
1597
|
+
const decision = await reviewScsFinish(client, config, state, fallback, {
|
|
1598
|
+
events: await store.loadEvents(),
|
|
1599
|
+
taskProfile: config.taskProfile,
|
|
1600
|
+
goal: config.goal,
|
|
1601
|
+
});
|
|
1602
|
+
state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || "on", active: true };
|
|
1603
|
+
state.meta.scs.lastStudentDecision = decision;
|
|
1604
|
+
await store.appendEvent(`scs.student.${decision.decision}`, decision);
|
|
1605
|
+
observers.event(`scs.student.${decision.decision}`, {
|
|
1606
|
+
decision: decision.decision,
|
|
1607
|
+
reason: decision.reason,
|
|
1608
|
+
});
|
|
1609
|
+
if (decision.decision === "finish_rejected") {
|
|
1610
|
+
state.meta.scs.finishRejects = (state.meta.scs.finishRejects || 0) + 1;
|
|
1611
|
+
state.messages.push({
|
|
1612
|
+
role: "user",
|
|
1613
|
+
content: [
|
|
1614
|
+
"SCS student rejected the proposed finish.",
|
|
1615
|
+
`Reason: ${decision.reason || "Finish lacked enough evidence."}`,
|
|
1616
|
+
"Supervisor: continue with the approved phase, collect concrete evidence, or call finish with a clear blocker.",
|
|
1617
|
+
].join("\n"),
|
|
1618
|
+
});
|
|
1619
|
+
state.stepsCompleted = step;
|
|
1620
|
+
state.updatedAt = new Date().toISOString();
|
|
1621
|
+
await store.saveState(state);
|
|
1622
|
+
emitConsole(config, `SCS: finish rejected: ${decision.reason || "needs more evidence"}`, { kind: "meta" });
|
|
1623
|
+
continue;
|
|
1624
|
+
}
|
|
1625
|
+
emitConsole(config, `SCS: finish approved (${Math.round((decision.confidence || 0) * 100)}%).`, { kind: "meta" });
|
|
1626
|
+
}
|
|
1520
1627
|
appendChatEntry(state, "assistant", fallback);
|
|
1521
1628
|
await store.appendEvent("session.finished", {
|
|
1522
1629
|
result: fallback,
|
|
@@ -1547,6 +1654,43 @@ export async function runAgent(config) {
|
|
|
1547
1654
|
});
|
|
1548
1655
|
await applyToolLoopGuard(state, toolResult, store, observers);
|
|
1549
1656
|
|
|
1657
|
+
if (config.scsActive && shouldReviewToolResult(toolResult, state)) {
|
|
1658
|
+
const decision = await reviewScsToolResult(client, config, state, toolResult, {
|
|
1659
|
+
events: await store.loadEvents(),
|
|
1660
|
+
taskProfile: config.taskProfile,
|
|
1661
|
+
goal: config.goal,
|
|
1662
|
+
});
|
|
1663
|
+
state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || "on", active: true };
|
|
1664
|
+
state.meta.scs.monitorReviews = (state.meta.scs.monitorReviews || 0) + 1;
|
|
1665
|
+
state.meta.scs.lastStudentDecision = decision;
|
|
1666
|
+
await store.appendEvent(`scs.student.${decision.decision}`, {
|
|
1667
|
+
...decision,
|
|
1668
|
+
toolName: toolResult.toolName,
|
|
1669
|
+
});
|
|
1670
|
+
observers.event(`scs.student.${decision.decision}`, {
|
|
1671
|
+
decision: decision.decision,
|
|
1672
|
+
reason: decision.reason,
|
|
1673
|
+
toolName: toolResult.toolName,
|
|
1674
|
+
});
|
|
1675
|
+
if (decision.decision === "rethink_plan" || decision.decision === "reject_phase") {
|
|
1676
|
+
state.messages.push({
|
|
1677
|
+
role: "user",
|
|
1678
|
+
content: [
|
|
1679
|
+
"SCS student monitor requested a rethink based on tool evidence.",
|
|
1680
|
+
`Decision: ${decision.decision}`,
|
|
1681
|
+
`Reason: ${decision.reason || "No reason provided."}`,
|
|
1682
|
+
decision.nextRequiredAction ? `Next required action: ${decision.nextRequiredAction}` : "",
|
|
1683
|
+
"Supervisor: do not repeat the same failed call. Adjust within the approved phase or finish with a concrete blocker if the phase is invalidated.",
|
|
1684
|
+
]
|
|
1685
|
+
.filter(Boolean)
|
|
1686
|
+
.join("\n"),
|
|
1687
|
+
});
|
|
1688
|
+
emitConsole(config, `SCS: ${decision.decision} after ${toolResult.toolName}: ${decision.reason || "reviewed"}`, {
|
|
1689
|
+
kind: "meta",
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1550
1694
|
if (toolResult.toolName === "run_command") {
|
|
1551
1695
|
observers.log("command.output", {
|
|
1552
1696
|
command: redactSensitiveText(toolResult.args?.command || ""),
|
|
@@ -1580,6 +1724,37 @@ export async function runAgent(config) {
|
|
|
1580
1724
|
}
|
|
1581
1725
|
|
|
1582
1726
|
if (toolResult.done) {
|
|
1727
|
+
if (config.scsActive) {
|
|
1728
|
+
const decision = await reviewScsFinish(client, config, state, toolResult.result, {
|
|
1729
|
+
events: await store.loadEvents(),
|
|
1730
|
+
taskProfile: config.taskProfile,
|
|
1731
|
+
goal: config.goal,
|
|
1732
|
+
});
|
|
1733
|
+
state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || "on", active: true };
|
|
1734
|
+
state.meta.scs.lastStudentDecision = decision;
|
|
1735
|
+
await store.appendEvent(`scs.student.${decision.decision}`, decision);
|
|
1736
|
+
observers.event(`scs.student.${decision.decision}`, {
|
|
1737
|
+
decision: decision.decision,
|
|
1738
|
+
reason: decision.reason,
|
|
1739
|
+
});
|
|
1740
|
+
if (decision.decision === "finish_rejected") {
|
|
1741
|
+
state.meta.scs.finishRejects = (state.meta.scs.finishRejects || 0) + 1;
|
|
1742
|
+
state.messages.push({
|
|
1743
|
+
role: "user",
|
|
1744
|
+
content: [
|
|
1745
|
+
"SCS student rejected the proposed finish.",
|
|
1746
|
+
`Reason: ${decision.reason || "Finish lacked enough evidence."}`,
|
|
1747
|
+
"Supervisor: continue with the approved phase, collect concrete evidence, or call finish with a clear blocker.",
|
|
1748
|
+
].join("\n"),
|
|
1749
|
+
});
|
|
1750
|
+
state.stepsCompleted = step;
|
|
1751
|
+
state.updatedAt = new Date().toISOString();
|
|
1752
|
+
await store.saveState(state);
|
|
1753
|
+
emitConsole(config, `SCS: finish rejected: ${decision.reason || "needs more evidence"}`, { kind: "meta" });
|
|
1754
|
+
continue;
|
|
1755
|
+
}
|
|
1756
|
+
emitConsole(config, `SCS: finish approved (${Math.round((decision.confidence || 0) * 100)}%).`, { kind: "meta" });
|
|
1757
|
+
}
|
|
1583
1758
|
const queuedCount = await injectQueuedUserMessages(store, state, observers);
|
|
1584
1759
|
if (queuedCount > 0) {
|
|
1585
1760
|
state.stepsCompleted = step;
|
|
@@ -1615,6 +1790,42 @@ export async function runAgent(config) {
|
|
|
1615
1790
|
|
|
1616
1791
|
if (continueForQueuedInput) continue;
|
|
1617
1792
|
|
|
1793
|
+
if (config.scsActive && shouldReviewScsProgress(step, state)) {
|
|
1794
|
+
const decision = await reviewScsProgress(client, config, state, {
|
|
1795
|
+
events: await store.loadEvents(),
|
|
1796
|
+
taskProfile: config.taskProfile,
|
|
1797
|
+
goal: config.goal,
|
|
1798
|
+
});
|
|
1799
|
+
state.meta.scs = state.meta.scs || { enabled: true, mode: config.enableScs || "on", active: true };
|
|
1800
|
+
state.meta.scs.monitorReviews = (state.meta.scs.monitorReviews || 0) + 1;
|
|
1801
|
+
state.meta.scs.lastStudentDecision = decision;
|
|
1802
|
+
await store.appendEvent(`scs.student.${decision.decision}`, {
|
|
1803
|
+
...decision,
|
|
1804
|
+
step,
|
|
1805
|
+
trigger: "periodic",
|
|
1806
|
+
});
|
|
1807
|
+
observers.event(`scs.student.${decision.decision}`, {
|
|
1808
|
+
decision: decision.decision,
|
|
1809
|
+
reason: decision.reason,
|
|
1810
|
+
trigger: "periodic",
|
|
1811
|
+
});
|
|
1812
|
+
if (decision.decision === "rethink_plan" || decision.decision === "reject_phase") {
|
|
1813
|
+
state.messages.push({
|
|
1814
|
+
role: "user",
|
|
1815
|
+
content: [
|
|
1816
|
+
"SCS student requested a periodic rethink.",
|
|
1817
|
+
`Decision: ${decision.decision}`,
|
|
1818
|
+
`Reason: ${decision.reason || "No reason provided."}`,
|
|
1819
|
+
decision.nextRequiredAction ? `Next required action: ${decision.nextRequiredAction}` : "",
|
|
1820
|
+
"Supervisor: adjust the next action within the approved phase, collect stronger evidence, or finish with a concrete blocker if the phase is invalidated.",
|
|
1821
|
+
]
|
|
1822
|
+
.filter(Boolean)
|
|
1823
|
+
.join("\n"),
|
|
1824
|
+
});
|
|
1825
|
+
emitConsole(config, `SCS: periodic ${decision.decision}: ${decision.reason || "reviewed"}`, { kind: "meta" });
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1618
1829
|
await injectQueuedUserMessages(store, state, observers);
|
|
1619
1830
|
|
|
1620
1831
|
state.stepsCompleted = step;
|
package/src/cli.js
CHANGED
|
@@ -34,6 +34,7 @@ import { languageLabel, resolveLanguage } from "./i18n.js";
|
|
|
34
34
|
import { maybeAutoUpdate } from "./auto-update.js";
|
|
35
35
|
import { readHousekeepingSummary } from "./housekeeping.js";
|
|
36
36
|
import { handleSkillMeshCommand } from "./skillmesh.js";
|
|
37
|
+
import { handleAapsCliCommand } from "./aaps-adapter.js";
|
|
37
38
|
import fs from "node:fs/promises";
|
|
38
39
|
import path from "node:path";
|
|
39
40
|
import { fileURLToPath } from "node:url";
|
|
@@ -105,6 +106,7 @@ export function parseArgs(argv) {
|
|
|
105
106
|
image: false,
|
|
106
107
|
language: "",
|
|
107
108
|
autoUpdate: undefined,
|
|
109
|
+
enableScs: "",
|
|
108
110
|
};
|
|
109
111
|
|
|
110
112
|
const parts = [];
|
|
@@ -148,6 +150,16 @@ export function parseArgs(argv) {
|
|
|
148
150
|
result.autoUpdate = true;
|
|
149
151
|
continue;
|
|
150
152
|
}
|
|
153
|
+
if (arg === "--enabless" || arg === "--enable-scs" || arg === "--scs") {
|
|
154
|
+
const value = readOption(argv, i);
|
|
155
|
+
result.enableScs = value || "on";
|
|
156
|
+
if (value) i += 1;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (arg === "--no-enabless" || arg === "--disable-scs" || arg === "--no-scs") {
|
|
160
|
+
result.enableScs = "off";
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
151
163
|
if (arg === "--start-url") {
|
|
152
164
|
result.startUrl = readOption(argv, i);
|
|
153
165
|
i += 1;
|
|
@@ -383,11 +395,40 @@ export function parseArgs(argv) {
|
|
|
383
395
|
|
|
384
396
|
function printUsage() {
|
|
385
397
|
console.log(
|
|
386
|
-
'Usage: aginti [chat] OR aginti web [--port 3210] OR aginti update OR aginti models OR aginti skills [query] OR aginti skillmesh [status|off|record|share|sync|serve|service] OR aginti housekeeping [--json] OR aginti auth [deepseek|openai|qwen|venice|grsai] OR aginti resume [--all-sessions] [latest|<session-id>] ["prompt"] OR aginti --remove-empty-sessions OR aginti --remove-sessions OR aginti queue <session-id> "message" OR aginti [--no-auto-update] [--language en|ja|zh-Hans|zh-Hant|ko|fr|es|ar|vi|de|ru] [--image] [--latex] [--routing smart|fast|complex|manual] [--provider deepseek|openai|qwen|venice|mock] [--model MODEL] [--route-model MODEL] [--main-model MODEL] [--spare-model MODEL --spare-reasoning medium] [--aux-provider grsai|venice --aux-model MODEL] [--sandbox-mode host|docker-readonly|docker-workspace] [--package-install-policy block|prompt|allow] [--approve-package-installs] [--allow-shell|--no-shell] [--allow-file-tools|--no-file-tools] [--web-search|--no-web-search] [--parallel-scouts|--no-parallel-scouts --scout-count 1..10] [--allow-auxiliary-tools|--no-auxiliary-tools] [--allow-wrappers --wrapper codex --wrapper-model gpt-5.5] [--list-models|--list-routes] "your task"'
|
|
398
|
+
'Usage: aginti [chat] OR aginti web [--port 3210] OR aginti update OR aginti models OR aginti aaps [status|init|files|validate|compile|check|run] OR aginti skills [query] OR aginti skillmesh [status|off|record|share|sync|serve|service] OR aginti housekeeping [--json] OR aginti auth [deepseek|openai|qwen|venice|grsai] OR aginti resume [--all-sessions] [latest|<session-id>] ["prompt"] OR aginti --remove-empty-sessions OR aginti --remove-sessions OR aginti queue <session-id> "message" OR aginti [--no-auto-update] [--language en|ja|zh-Hans|zh-Hant|ko|fr|es|ar|vi|de|ru] [--image] [--latex] [--enabless|--enabless auto|--no-enabless] [--routing smart|fast|complex|manual] [--provider deepseek|openai|qwen|venice|mock] [--model MODEL] [--route-model MODEL] [--main-model MODEL] [--spare-model MODEL --spare-reasoning medium] [--aux-provider grsai|venice --aux-model MODEL] [--sandbox-mode host|docker-readonly|docker-workspace] [--package-install-policy block|prompt|allow] [--approve-package-installs] [--allow-shell|--no-shell] [--allow-file-tools|--no-file-tools] [--web-search|--no-web-search] [--parallel-scouts|--no-parallel-scouts --scout-count 1..10] [--allow-auxiliary-tools|--no-auxiliary-tools] [--allow-wrappers --wrapper codex --wrapper-model gpt-5.5] [--list-models|--list-routes] "your task"'
|
|
387
399
|
);
|
|
388
400
|
console.log(`Languages: ${["en", "ja", "zh-Hans", "zh-Hant", "ko", "fr", "es", "ar", "vi", "de", "ru"].map((code) => `${code}=${languageLabel(code)}`).join(", ")}`);
|
|
389
401
|
}
|
|
390
402
|
|
|
403
|
+
function stripLeadingGlobalOptions(argv = []) {
|
|
404
|
+
let index = 0;
|
|
405
|
+
const options = {
|
|
406
|
+
commandCwd: "",
|
|
407
|
+
};
|
|
408
|
+
while (index < argv.length) {
|
|
409
|
+
const arg = argv[index];
|
|
410
|
+
if (arg === "--no-auto-update" || arg === "--auto-update") {
|
|
411
|
+
index += 1;
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
if (arg === "--language" || arg === "--lang" || arg === "-L") {
|
|
415
|
+
index += readOption(argv, index) ? 2 : 1;
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (arg === "--cwd") {
|
|
419
|
+
const cwd = readOption(argv, index);
|
|
420
|
+
if (cwd) options.commandCwd = path.resolve(cwd);
|
|
421
|
+
index += cwd ? 2 : 1;
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
argv: argv.slice(index),
|
|
428
|
+
options,
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
391
432
|
function providerLabel(provider) {
|
|
392
433
|
const normalized = String(provider || "").toLowerCase();
|
|
393
434
|
if (normalized === "openai") return "OpenAI";
|
|
@@ -421,6 +462,7 @@ function agentDefaults(args) {
|
|
|
421
462
|
allowAuxiliaryTools: args.allowAuxiliaryTools ?? true,
|
|
422
463
|
allowWebSearch: args.allowWebSearch ?? true,
|
|
423
464
|
allowParallelScouts: args.allowParallelScouts ?? true,
|
|
465
|
+
enableScs: args.enableScs || process.env.AGINTI_SCS_MODE || "off",
|
|
424
466
|
parallelScoutCount: args.parallelScoutCount || (Number.isFinite(envScoutCount) && envScoutCount > 0 ? envScoutCount : 3),
|
|
425
467
|
sandboxMode: args.sandboxMode || envSandboxMode || "docker-workspace",
|
|
426
468
|
packageInstallPolicy: args.packageInstallPolicy || envPackageInstallPolicy || "allow",
|
|
@@ -1036,6 +1078,20 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
1036
1078
|
});
|
|
1037
1079
|
if (autoUpdateResult.restarted) process.exit(autoUpdateResult.exitCode ?? 0);
|
|
1038
1080
|
|
|
1081
|
+
const stripped = stripLeadingGlobalOptions(argv);
|
|
1082
|
+
const commandArgv = stripped.argv;
|
|
1083
|
+
const commandCwd = stripped.options.commandCwd || process.cwd();
|
|
1084
|
+
|
|
1085
|
+
if (commandArgv[0] === "aaps") {
|
|
1086
|
+
try {
|
|
1087
|
+
await handleAapsCliCommand(commandArgv.slice(1), { cwd: commandCwd, packageDir });
|
|
1088
|
+
} catch (error) {
|
|
1089
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
1090
|
+
process.exit(1);
|
|
1091
|
+
}
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1039
1095
|
if (argv.includes("--remove-empty-sessions") || argv[0] === "remove-empty-sessions") {
|
|
1040
1096
|
await handleRemoveSessionsCommand({ emptyOnly: true });
|
|
1041
1097
|
return;
|
package/src/config.js
CHANGED
|
@@ -7,6 +7,7 @@ import { loadProjectEnv, projectPaths, resolveProjectRoot } from "./project.js";
|
|
|
7
7
|
import { normalizeTaskProfile } from "./task-profiles.js";
|
|
8
8
|
import { recommendedMaxStepsForTask } from "./engineering-guidance.js";
|
|
9
9
|
import { resolveLanguage } from "./i18n.js";
|
|
10
|
+
import { normalizeScsMode, shouldActivateScs } from "./scs-controller.js";
|
|
10
11
|
|
|
11
12
|
function parseBoolean(value, fallback) {
|
|
12
13
|
if (value === undefined) return fallback;
|
|
@@ -75,7 +76,15 @@ export function resolveRuntimeConfig(args, overrides = {}) {
|
|
|
75
76
|
auxiliaryModel: overrides.auxiliaryModel || args.auxiliaryModel || process.env.AGINTI_AUX_MODEL || "",
|
|
76
77
|
});
|
|
77
78
|
|
|
78
|
-
const
|
|
79
|
+
const scsMode = normalizeScsMode(overrides.enableScs ?? args.enableScs ?? process.env.AGINTI_SCS_MODE ?? "off");
|
|
80
|
+
const scsActive = shouldActivateScs(scsMode, {
|
|
81
|
+
goal: args.goal || "",
|
|
82
|
+
taskProfile,
|
|
83
|
+
complexityScore: route.complexityScore,
|
|
84
|
+
});
|
|
85
|
+
const activeProvider = scsActive && route.provider !== "mock" ? modelRoles.main.provider : route.provider;
|
|
86
|
+
const activeModel = scsActive && route.provider !== "mock" ? modelRoles.main.model : route.model;
|
|
87
|
+
const defaults = getProviderDefaults(activeProvider);
|
|
79
88
|
const defaultMaxSteps = recommendedMaxStepsForTask({
|
|
80
89
|
goal: args.goal || "",
|
|
81
90
|
taskProfile,
|
|
@@ -86,6 +95,14 @@ export function resolveRuntimeConfig(args, overrides = {}) {
|
|
|
86
95
|
const requestedSandboxMode =
|
|
87
96
|
overrides.sandboxMode || args.sandboxMode || process.env.SANDBOX_MODE || (dockerRequested ? "docker-workspace" : "host");
|
|
88
97
|
const sandboxMode = normalizeSandboxMode(requestedSandboxMode);
|
|
98
|
+
const explicitParallelScouts =
|
|
99
|
+
overrides.allowParallelScouts !== undefined ||
|
|
100
|
+
args.allowParallelScouts !== undefined ||
|
|
101
|
+
process.env.AGINTI_PARALLEL_SCOUTS !== undefined;
|
|
102
|
+
const allowParallelScouts = parseBoolean(
|
|
103
|
+
overrides.allowParallelScouts ?? args.allowParallelScouts ?? process.env.AGINTI_PARALLEL_SCOUTS,
|
|
104
|
+
true
|
|
105
|
+
);
|
|
89
106
|
|
|
90
107
|
return {
|
|
91
108
|
...defaults,
|
|
@@ -100,6 +117,9 @@ export function resolveRuntimeConfig(args, overrides = {}) {
|
|
|
100
117
|
language,
|
|
101
118
|
routeReason: route.reason,
|
|
102
119
|
routeComplexityScore: route.complexityScore,
|
|
120
|
+
enableScs: scsMode,
|
|
121
|
+
scsActive,
|
|
122
|
+
scsModelPolicy: scsActive ? "main" : "route",
|
|
103
123
|
modelRoles,
|
|
104
124
|
routeProvider: modelRoles.route.provider,
|
|
105
125
|
routeModel: modelRoles.route.model,
|
|
@@ -114,10 +134,10 @@ export function resolveRuntimeConfig(args, overrides = {}) {
|
|
|
114
134
|
auxiliaryModel: modelRoles.auxiliary.model,
|
|
115
135
|
requestedProvider,
|
|
116
136
|
requestedModel: overrides.model || args.model || process.env.LLM_MODEL || "",
|
|
117
|
-
provider:
|
|
137
|
+
provider: activeProvider,
|
|
118
138
|
apiKey: overrides.apiKey || defaults.apiKey,
|
|
119
139
|
baseURL: overrides.baseURL || defaults.baseURL,
|
|
120
|
-
model:
|
|
140
|
+
model: activeModel || defaults.model,
|
|
121
141
|
maxSteps: parseNumber(overrides.maxSteps ?? args.maxSteps ?? process.env.MAX_STEPS, defaultMaxSteps),
|
|
122
142
|
headless: parseBoolean(overrides.headless ?? args.headless ?? process.env.HEADLESS, false),
|
|
123
143
|
allowedDomains: Array.isArray(overrides.allowedDomains)
|
|
@@ -136,10 +156,7 @@ export function resolveRuntimeConfig(args, overrides = {}) {
|
|
|
136
156
|
true
|
|
137
157
|
),
|
|
138
158
|
allowWebSearch: parseBoolean(overrides.allowWebSearch ?? args.allowWebSearch ?? process.env.ALLOW_WEB_SEARCH, true),
|
|
139
|
-
allowParallelScouts:
|
|
140
|
-
overrides.allowParallelScouts ?? args.allowParallelScouts ?? process.env.AGINTI_PARALLEL_SCOUTS,
|
|
141
|
-
true
|
|
142
|
-
),
|
|
159
|
+
allowParallelScouts: scsActive && !explicitParallelScouts ? false : allowParallelScouts,
|
|
143
160
|
parallelScoutCount: clampNumber(
|
|
144
161
|
parseNumber(overrides.parallelScoutCount ?? args.parallelScoutCount ?? process.env.AGINTI_SCOUT_COUNT, 3),
|
|
145
162
|
1,
|
package/src/i18n.js
CHANGED
|
@@ -130,6 +130,7 @@ const TRANSLATIONS = {
|
|
|
130
130
|
helpSpare: "Open spare selector, or set e.g. /spare openai/gpt-5.4 medium.",
|
|
131
131
|
helpWrapper: "Configure optional external wrapper.",
|
|
132
132
|
helpAuxiliary: "Manage optional auxiliary skills, including image generation.",
|
|
133
|
+
helpAaps: "Manage AAPS workflows through the optional @lazyingart/aaps adapter.",
|
|
133
134
|
helpNew: "Start a fresh session on the next message.",
|
|
134
135
|
helpResume: "Continue a saved session.",
|
|
135
136
|
helpSessions: "List recent sessions in this project.",
|
package/src/interactive-cli.js
CHANGED
|
@@ -33,6 +33,8 @@ import {
|
|
|
33
33
|
setSkillMeshMode,
|
|
34
34
|
skillMeshModeChoices,
|
|
35
35
|
} from "./skillmesh.js";
|
|
36
|
+
import { normalizeScsMode } from "./scs-controller.js";
|
|
37
|
+
import { formatAapsResult, runAapsAction } from "./aaps-adapter.js";
|
|
36
38
|
|
|
37
39
|
const useColor = Boolean(input.isTTY && output.isTTY && process.env.AGINTIFLOW_NO_COLOR !== "1");
|
|
38
40
|
const ansi = {
|
|
@@ -73,6 +75,7 @@ const SLASH_COMMANDS = [
|
|
|
73
75
|
"/instructions",
|
|
74
76
|
"/memory",
|
|
75
77
|
"/auxiliary",
|
|
78
|
+
"/aaps",
|
|
76
79
|
"/new",
|
|
77
80
|
"/resume",
|
|
78
81
|
"/sessions",
|
|
@@ -85,6 +88,8 @@ const SLASH_COMMANDS = [
|
|
|
85
88
|
"/profile",
|
|
86
89
|
"/web-search",
|
|
87
90
|
"/scouts",
|
|
91
|
+
"/enabless",
|
|
92
|
+
"/scs",
|
|
88
93
|
"/models",
|
|
89
94
|
"/venice",
|
|
90
95
|
"/route",
|
|
@@ -652,6 +657,7 @@ function printHelp() {
|
|
|
652
657
|
` ${command("/spare [provider/model] [reasoning]", "Open spare selector, or set e.g. /spare openai/gpt-5.4 medium.", "helpSpare")}`,
|
|
653
658
|
` ${command("/wrapper [on|off|codex model reasoning]", "Configure optional external wrapper.", "helpWrapper")}`,
|
|
654
659
|
` ${command("/auxiliary [status|grsai|venice|model [provider/model]|on|off|image]", "Manage optional auxiliary skills, including image generation.", "helpAuxiliary")}`,
|
|
660
|
+
` ${command("/aaps [status|init|files|validate|compile|check|run]", "Manage AAPS workflows through the optional @lazyingart/aaps adapter.", "helpAaps")}`,
|
|
655
661
|
` ${command("/new", "Start a fresh session on the next message.", "helpNew")}`,
|
|
656
662
|
` ${command("/resume <session-id>", "Continue a saved session.", "helpResume")}`,
|
|
657
663
|
` ${command("/review [focus]", "Run a bounded repo/diff review with controlled context gathering.", "helpReview")}`,
|
|
@@ -662,6 +668,7 @@ function printHelp() {
|
|
|
662
668
|
` ${command("/profile <name>", "Set task profile, e.g. code, website, latex, maintenance.", "helpProfile")}`,
|
|
663
669
|
` ${command("/web-search on|off", "Enable or disable the web_search tool.", "helpWebSearch")}`,
|
|
664
670
|
` ${command("/scouts on|off|<1-10>", "Enable parallel DeepSeek scouts and set scout count.", "helpScouts")}`,
|
|
671
|
+
` ${command("/enabless [auto|off|status]", "Enable Student-Committee-Supervisor gated execution.", "helpEnableScs")}`,
|
|
665
672
|
` ${command("/routing <mode>", "Set routing: smart, fast, complex, manual.", "helpRouting")}`,
|
|
666
673
|
` ${command("/provider [name]", "Open provider selector, or set deepseek/openai/qwen/venice/mock.", "helpProvider")}`,
|
|
667
674
|
` ${command("/docker on", "Use docker-workspace with approved package installs.", "helpDockerOn")}`,
|
|
@@ -1602,7 +1609,7 @@ function printStatus(state) {
|
|
|
1602
1609
|
);
|
|
1603
1610
|
printSystemLine(`profile=${state.taskProfile} maxSteps=${state.maxSteps}`);
|
|
1604
1611
|
printSystemLine(
|
|
1605
|
-
`shell=${state.allowShellTool} files=${state.allowFileTools} webSearch=${state.allowWebSearch} scouts=${state.allowParallelScouts}:${state.parallelScoutCount} auxiliary=${state.allowAuxiliaryTools} sandbox=${state.sandboxMode} installs=${state.packageInstallPolicy}`
|
|
1612
|
+
`shell=${state.allowShellTool} files=${state.allowFileTools} webSearch=${state.allowWebSearch} scouts=${state.allowParallelScouts}:${state.parallelScoutCount} scs=${state.enableScs || "off"} auxiliary=${state.allowAuxiliaryTools} sandbox=${state.sandboxMode} installs=${state.packageInstallPolicy}`
|
|
1606
1613
|
);
|
|
1607
1614
|
if (state.sandboxMode !== "host") {
|
|
1608
1615
|
printSystemLine(`dockerWorkspace=/workspace -> ${state.commandCwd || process.cwd()}`);
|
|
@@ -1737,6 +1744,7 @@ function createState(args = {}) {
|
|
|
1737
1744
|
allowAuxiliaryTools: args.allowAuxiliaryTools ?? true,
|
|
1738
1745
|
allowWebSearch: args.allowWebSearch ?? true,
|
|
1739
1746
|
allowParallelScouts: args.allowParallelScouts ?? true,
|
|
1747
|
+
enableScs: normalizeScsMode(args.enableScs || process.env.AGINTI_SCS_MODE || "off"),
|
|
1740
1748
|
parallelScoutCount: args.parallelScoutCount || 3,
|
|
1741
1749
|
allowWrapperTools: args.allowWrapperTools ?? false,
|
|
1742
1750
|
allowDestructive: args.allowDestructive ?? false,
|
|
@@ -2629,6 +2637,35 @@ async function handleCommand(line, state, packageDir) {
|
|
|
2629
2637
|
printAgentMessage("Usage: /auxiliary [status|select|grsai|venice|model [grsai/nano-banana-2]|on|off|image]");
|
|
2630
2638
|
return true;
|
|
2631
2639
|
}
|
|
2640
|
+
if (command === "aaps") {
|
|
2641
|
+
const [action = "status", ...aapsArgs] = value.split(/\s+/).filter(Boolean);
|
|
2642
|
+
const normalizedAction = String(action || "status").toLowerCase();
|
|
2643
|
+
if (normalizedAction === "on" || normalizedAction === "auto") {
|
|
2644
|
+
state.taskProfile = "aaps";
|
|
2645
|
+
state.maxSteps = Math.max(state.maxSteps, 36);
|
|
2646
|
+
printSystemLine(`aaps=${normalizedAction} profile=aaps maxSteps=${state.maxSteps}`);
|
|
2647
|
+
printAgentMessage("AAPS mode enabled. Use `/aaps init`, `/aaps validate`, `/aaps compile`, or write normal requests about .aaps workflows.");
|
|
2648
|
+
return true;
|
|
2649
|
+
}
|
|
2650
|
+
if (normalizedAction === "off") {
|
|
2651
|
+
state.taskProfile = "auto";
|
|
2652
|
+
printSystemLine("aaps=off profile=auto");
|
|
2653
|
+
return true;
|
|
2654
|
+
}
|
|
2655
|
+
try {
|
|
2656
|
+
const result = await runAapsAction(normalizedAction, aapsArgs, {
|
|
2657
|
+
cwd: state.commandCwd || process.cwd(),
|
|
2658
|
+
packageDir,
|
|
2659
|
+
});
|
|
2660
|
+
printAgentMessage(formatAapsResult(result));
|
|
2661
|
+
if (result.ok === false && result.error) {
|
|
2662
|
+
printSystemLine(`aaps=failed ${result.error}`);
|
|
2663
|
+
}
|
|
2664
|
+
} catch (error) {
|
|
2665
|
+
printAgentMessage(error instanceof Error ? error.message : String(error));
|
|
2666
|
+
}
|
|
2667
|
+
return true;
|
|
2668
|
+
}
|
|
2632
2669
|
if (command === "new") {
|
|
2633
2670
|
state.sessionId = "";
|
|
2634
2671
|
printAgentMessage("Next message will start a new session.");
|
|
@@ -2769,6 +2806,40 @@ async function handleCommand(line, state, packageDir) {
|
|
|
2769
2806
|
printSystemLine(`parallelScouts=${state.allowParallelScouts ? "on" : "off"} count=${state.parallelScoutCount}`);
|
|
2770
2807
|
return true;
|
|
2771
2808
|
}
|
|
2809
|
+
if (command === "enabless" || command === "scs") {
|
|
2810
|
+
const rawMode = String(value || "").trim().toLowerCase();
|
|
2811
|
+
const mode = value ? normalizeScsMode(value) : "on";
|
|
2812
|
+
const knownMode =
|
|
2813
|
+
!rawMode ||
|
|
2814
|
+
["on", "off", "auto", "smart", "status", "?", "true", "false", "yes", "no", "y", "n", "1", "0", "enable", "disable", "enabled", "disabled"].includes(
|
|
2815
|
+
rawMode
|
|
2816
|
+
);
|
|
2817
|
+
if (!knownMode) {
|
|
2818
|
+
printAgentMessage("Usage: /enabless [auto|off|status]. `/enabless` turns SCS on for the session.");
|
|
2819
|
+
return true;
|
|
2820
|
+
}
|
|
2821
|
+
if (value === "status" || value === "?") {
|
|
2822
|
+
printAgentMessage(
|
|
2823
|
+
[
|
|
2824
|
+
`SCS mode: ${state.enableScs || "off"}`,
|
|
2825
|
+
"Student-Committee-Supervisor gates complex work with one main model: committee drafts, student approves/monitors, supervisor executes.",
|
|
2826
|
+
"Use `/enabless` for on, `/enabless auto` for complex-task auto mode, or `/enabless off` for the normal fast pipeline.",
|
|
2827
|
+
].join("\n")
|
|
2828
|
+
);
|
|
2829
|
+
return true;
|
|
2830
|
+
}
|
|
2831
|
+
state.enableScs = mode;
|
|
2832
|
+
if (mode === "on") {
|
|
2833
|
+
state.allowParallelScouts = false;
|
|
2834
|
+
}
|
|
2835
|
+
printSystemLine(`scs=${state.enableScs}${state.enableScs !== "off" ? ` main=${state.mainProvider || "deepseek"}/${state.mainModel || "deepseek-v4-pro"}` : ""}`);
|
|
2836
|
+
if (state.enableScs === "on") {
|
|
2837
|
+
printAgentMessage("SCS enabled. Next run uses the main model for committee planning, student gates, and supervisor execution.");
|
|
2838
|
+
} else if (state.enableScs === "auto") {
|
|
2839
|
+
printAgentMessage("SCS auto enabled. It activates for complex, risky, or long-running tasks and stays off for simple turns.");
|
|
2840
|
+
}
|
|
2841
|
+
return true;
|
|
2842
|
+
}
|
|
2772
2843
|
if (command === "models") {
|
|
2773
2844
|
printModelRoles(state);
|
|
2774
2845
|
return true;
|
|
@@ -3024,6 +3095,7 @@ async function runPrompt(prompt, state, packageDir) {
|
|
|
3024
3095
|
allowAuxiliaryTools: state.allowAuxiliaryTools,
|
|
3025
3096
|
allowWebSearch: state.allowWebSearch,
|
|
3026
3097
|
allowParallelScouts: state.allowParallelScouts,
|
|
3098
|
+
enableScs: state.enableScs,
|
|
3027
3099
|
parallelScoutCount: state.parallelScoutCount,
|
|
3028
3100
|
allowWrapperTools: state.allowWrapperTools,
|
|
3029
3101
|
allowDestructive: state.allowDestructive,
|