@lazyingart/agintiflow 0.20.50 → 0.20.52
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 +4 -4
- package/docs/student-committee-supervisor.md +10 -9
- package/package.json +1 -1
- package/references/student-committee-supervisor-mode.md +14 -13
- package/scripts/smoke-cli-chat.js +35 -2
- package/scripts/smoke-coding-tools.js +46 -0
- package/src/agent-runner.js +55 -11
- package/src/cli.js +13 -4
- package/src/i18n.js +1 -0
- package/src/interactive-cli.js +36 -9
package/README.md
CHANGED
|
@@ -97,7 +97,7 @@ For larger repositories, use `--profile large-codebase` or choose **Large codeba
|
|
|
97
97
|
|
|
98
98
|
AgInTiFlow can also spend cheap DeepSeek calls on parallel scout notes before the main executor starts a complicated task. It first writes a bounded project map to `.aginti/codebase-map.json`, then runs scouts for architecture, implementation, review, research, context mapping, tests, git workflow, integration, symbol tracing, and dependency risks. A coordinator Swarm Board is injected for the main agent and saved as `artifacts/scout-blackboard.json` in the session. The executor still does the real file/shell/browser work itself. Disable with `--no-parallel-scouts` or set `--scout-count 1..10`.
|
|
99
99
|
|
|
100
|
-
For complicated tasks that need stricter quality control, enable Student-Committee-Supervisor mode with `/
|
|
100
|
+
For complicated tasks that need stricter quality control, enable Student-Committee-Supervisor mode with `/scs`, `--scs`, or `--scs auto`. SCS uses the main model for a typed gate: committee drafts the next phase, student approves/monitors/rejects weak evidence, and supervisor executes with the normal guarded tools. It disables duplicate scout advice by default, logs typed `scs.*` events, caps retries to avoid deadlock, and stays off unless you opt in or choose auto mode. See [docs/student-committee-supervisor.md](docs/student-committee-supervisor.md).
|
|
101
101
|
|
|
102
102
|
The next productive-agent roadmap is tracked in [docs/productive-agent-roadmap.md](docs/productive-agent-roadmap.md): durable codebase maps, stronger scout blackboards, long-run checkpoints, LSP/symbol tools, test triage, and release automation. Runtime choices, Docker persistence, host full-access tradeoffs, tmux sessions, and rolling-plan autonomy are documented in [docs/runtime-modes-and-autonomy.md](docs/runtime-modes-and-autonomy.md). The supervised self-development protocol is in [docs/self-development-supervision.md](docs/self-development-supervision.md).
|
|
103
103
|
|
|
@@ -156,10 +156,10 @@ aginti aaps init "Project Workflow"
|
|
|
156
156
|
aginti aaps validate
|
|
157
157
|
aginti chat
|
|
158
158
|
# then in chat: /review [focus]
|
|
159
|
-
# then in chat: /
|
|
159
|
+
# then in chat: /scs auto
|
|
160
160
|
# then in chat: /aaps validate
|
|
161
161
|
aginti --profile code "write a small Python CLI app with tests"
|
|
162
|
-
aginti --
|
|
162
|
+
aginti --scs auto "fix this complicated project and verify it"
|
|
163
163
|
aginti --latex "draw a figure, write a short LaTeX report, and compile the PDF"
|
|
164
164
|
aginti "set up this project and run the tests"
|
|
165
165
|
```
|
|
@@ -170,7 +170,7 @@ Session cleanup is cwd-scoped by default. `aginti --remove-empty-sessions` shows
|
|
|
170
170
|
|
|
171
171
|
In interactive chat, `/review [focus]` starts a bounded repository review. It begins from git status/diff and project instructions, reads manifests/entry points/tests/changed files first, avoids generated or binary folders, limits discovery passes, and reports findings before any summary.
|
|
172
172
|
|
|
173
|
-
In interactive chat, `/
|
|
173
|
+
In interactive chat, `/scs` toggles SCS on or off for the session, `/scs auto` activates it only for complex/risky work, `/scs on` forces it on, `/scs off` restores the normal fast pipeline, and `/scs status` explains the current mode.
|
|
174
174
|
|
|
175
175
|
Run from a source checkout:
|
|
176
176
|
|
|
@@ -7,21 +7,22 @@ It is intentionally separate from the normal fast pipeline. Small requests shoul
|
|
|
7
7
|
## Commands
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
aginti --
|
|
11
|
-
aginti --
|
|
12
|
-
aginti --no-
|
|
10
|
+
aginti --scs "fix this complicated project and verify it"
|
|
11
|
+
aginti --scs auto "migrate this app and run the checks"
|
|
12
|
+
aginti --no-scs "answer this simple question"
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Inside interactive chat:
|
|
16
16
|
|
|
17
17
|
```text
|
|
18
|
-
/
|
|
19
|
-
/
|
|
20
|
-
/
|
|
21
|
-
/
|
|
18
|
+
/scs
|
|
19
|
+
/scs auto
|
|
20
|
+
/scs on
|
|
21
|
+
/scs off
|
|
22
|
+
/scs status
|
|
22
23
|
```
|
|
23
24
|
|
|
24
|
-
`/scs` is
|
|
25
|
+
`/scs` without arguments toggles the feature: off becomes on, and on/auto becomes off. The old `/enabless` spelling is accepted only as a compatibility alias for older sessions and scripts.
|
|
25
26
|
|
|
26
27
|
## Role Contract
|
|
27
28
|
|
|
@@ -57,7 +58,7 @@ The current implementation is deliberately bounded:
|
|
|
57
58
|
|
|
58
59
|
## Auto Mode
|
|
59
60
|
|
|
60
|
-
`/
|
|
61
|
+
`/scs auto` and `--scs auto` activate SCS for complex, risky, or long-running work. Signals include:
|
|
61
62
|
|
|
62
63
|
- high smart-routing complexity score;
|
|
63
64
|
- profiles such as code, app, Android/iOS, large-codebase, GitHub, maintenance, security, LaTeX, research, and supervision;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.52",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AgInTiFlow is a web-first coding agent and CLI with DeepSeek routing, sandboxed tools, model providers, canvas artifacts, and optional wrappers.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Student-Committee-Supervisor Mode
|
|
2
2
|
|
|
3
|
-
This note researches the current AgInTiFlow execution pipeline and proposes a standalone `/
|
|
3
|
+
This note researches the current AgInTiFlow execution pipeline and proposes a standalone `/scs` mode: Student-Committee-Supervisor, abbreviated `SCS`.
|
|
4
4
|
|
|
5
5
|
The name intentionally keeps the reversed-role joke: the "student" supervises, the "supervisor" executes, and the "committee" drafts but cannot decide.
|
|
6
6
|
|
|
@@ -40,7 +40,7 @@ Relevant implementation files:
|
|
|
40
40
|
|
|
41
41
|
## Proposed SCS Contract
|
|
42
42
|
|
|
43
|
-
`/
|
|
43
|
+
`/scs` enables a stricter internal workflow for the current interactive session.
|
|
44
44
|
|
|
45
45
|
Roles:
|
|
46
46
|
|
|
@@ -50,7 +50,7 @@ Roles:
|
|
|
50
50
|
| Committee | Main model | Draft candidate plans and alternatives. | Cannot approve, veto, replan after execution starts, or call tools. |
|
|
51
51
|
| Supervisor | Main model | Execute the approved plan with the existing tool loop. | Cannot draft its own initial plan, cannot approve its own plan, cannot declare strategic replans without student permission. |
|
|
52
52
|
|
|
53
|
-
The user asked that once `/
|
|
53
|
+
The user asked that once `/scs` is enabled, all SCS work uses the main model. This is sensible for determinism: no route/main mismatch, no cheap planner producing a plan that a stronger executor dislikes, and no confusing cross-model responsibility. It also makes cost predictable because the feature is opt-in.
|
|
54
54
|
|
|
55
55
|
## Pros
|
|
56
56
|
|
|
@@ -133,7 +133,7 @@ New config/state:
|
|
|
133
133
|
|
|
134
134
|
- `AGINTI_SCS_MODE=true`
|
|
135
135
|
- CLI flag: `--enable-scs`
|
|
136
|
-
- interactive command: `/
|
|
136
|
+
- interactive command: `/scs`, `/scs on`, `/scs auto`, `/scs off`, `/scs status`
|
|
137
137
|
- state fields:
|
|
138
138
|
- `state.enableScs`
|
|
139
139
|
- `state.scs.phase`
|
|
@@ -189,7 +189,7 @@ Recommended modes:
|
|
|
189
189
|
| `on` | SCS gates all non-trivial work in the session. |
|
|
190
190
|
| `auto` | SCS only activates for complex tasks, write actions, multi-step shell work, GitHub, system maintenance, Android/iOS, LaTeX/PDF, and long-running tasks. |
|
|
191
191
|
|
|
192
|
-
`/
|
|
192
|
+
`/scs` should toggle SCS on/off in interactive CLI. `/scs auto` keeps the mature complex-task gate for users who want quality control without paying the SCS cost on simple turns.
|
|
193
193
|
|
|
194
194
|
## Model Policy
|
|
195
195
|
|
|
@@ -215,10 +215,11 @@ Possible future improvement:
|
|
|
215
215
|
CLI:
|
|
216
216
|
|
|
217
217
|
```text
|
|
218
|
-
/
|
|
219
|
-
/
|
|
220
|
-
/
|
|
221
|
-
/
|
|
218
|
+
/scs
|
|
219
|
+
/scs on
|
|
220
|
+
/scs off
|
|
221
|
+
/scs auto
|
|
222
|
+
/scs status
|
|
222
223
|
```
|
|
223
224
|
|
|
224
225
|
Status output:
|
|
@@ -283,8 +284,8 @@ Implemented first slice:
|
|
|
283
284
|
|
|
284
285
|
- `src/scs-controller.js` provides mode normalization, auto activation, committee/student JSON calls, evidence packs, supervisor instructions, tool-failure monitoring, periodic progress review, and final finish gates.
|
|
285
286
|
- `src/config.js` adds `enableScs`/`scsActive` and switches active execution to the main model role when SCS is active.
|
|
286
|
-
- `src/interactive-cli.js` adds `/
|
|
287
|
-
- `src/cli.js` adds `--
|
|
287
|
+
- `src/interactive-cli.js` adds `/scs`, `/scs auto`, `/scs on`, `/scs off`, and `/scs status`. `/enabless` remains a compatibility alias only.
|
|
288
|
+
- `src/cli.js` adds `--scs`, `--scs auto`, and `--no-scs`. The older `--enabless` flags remain compatibility aliases only.
|
|
288
289
|
- `src/agent-runner.js` persists typed `scs.*` events, saves `scs-phase-001.json`, injects the approved supervisor phase, reviews failed tools, and gates finish.
|
|
289
290
|
|
|
290
291
|
Remaining roadmap:
|
|
@@ -317,12 +318,12 @@ Phase 5: auto mode
|
|
|
317
318
|
- Should SCS approval be required before any write tool, or only before the first phase starts?
|
|
318
319
|
- Should the student be allowed to require specific checks, or only accept/reject evidence?
|
|
319
320
|
- Should committee be one call or multiple candidate calls synthesized into one plan?
|
|
320
|
-
- Should `/enabless`
|
|
321
|
+
- Should `/enabless` remain as a hidden compatibility alias now that `/scs` is the serious public command?
|
|
321
322
|
- Should SCS decisions be shared through Skill Mesh as learned supervision skills?
|
|
322
323
|
|
|
323
324
|
## Recommendation
|
|
324
325
|
|
|
325
|
-
Implement `/
|
|
326
|
+
Implement `/scs` as the serious opt-in quality mode.
|
|
326
327
|
|
|
327
328
|
Start with one-main-model SCS and only gate the initial plan plus final finish. Then add failure-triggered student monitoring. Avoid per-tool approval in the first version; existing command and file guardrails already protect the dangerous paths, and too many monitor calls will make the product feel slow.
|
|
328
329
|
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
formatWorkspaceChange,
|
|
16
16
|
stripMarkdown,
|
|
17
17
|
} from "../src/interactive-cli.js";
|
|
18
|
+
import { parseArgs } from "../src/cli.js";
|
|
18
19
|
import { dockerPolicyTimeoutMs, dockerUserCommand } from "../src/docker-sandbox.js";
|
|
19
20
|
|
|
20
21
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
@@ -263,11 +264,20 @@ try {
|
|
|
263
264
|
if (
|
|
264
265
|
canonicalSlashPromptBuffer("/ve") !== "/venice" ||
|
|
265
266
|
canonicalSlashPromptBuffer("/v") !== "/venice" ||
|
|
267
|
+
canonicalSlashPromptBuffer("/sc") !== "/scs" ||
|
|
266
268
|
canonicalSlashPromptBuffer("/not-a-command") !== "/not-a-command" ||
|
|
267
269
|
canonicalSlashPromptBuffer("/venice off") !== "/venice off"
|
|
268
270
|
) {
|
|
269
271
|
throw new Error("slash command prompt canonicalization did not preserve final submitted command correctly");
|
|
270
272
|
}
|
|
273
|
+
const scsBooleanArgs = parseArgs(["--scs", "fix this project"]);
|
|
274
|
+
if (scsBooleanArgs.enableScs !== "on" || scsBooleanArgs.goal !== "fix this project") {
|
|
275
|
+
throw new Error("--scs should behave as a boolean flag when followed by a task");
|
|
276
|
+
}
|
|
277
|
+
const scsAutoArgs = parseArgs(["--scs", "auto", "fix this project"]);
|
|
278
|
+
if (scsAutoArgs.enableScs !== "auto" || scsAutoArgs.goal !== "fix this project") {
|
|
279
|
+
throw new Error("--scs auto should consume auto and preserve the task");
|
|
280
|
+
}
|
|
271
281
|
|
|
272
282
|
await runCli(["init"], "");
|
|
273
283
|
const instructions = await fs.readFile(path.join(tempRoot, "AGINTI.md"), "utf8");
|
|
@@ -280,8 +290,14 @@ try {
|
|
|
280
290
|
}
|
|
281
291
|
const helpResult = await runChat("/help\n/exit\n");
|
|
282
292
|
const misspelledAuxiliary = "/auxil" + "liary";
|
|
283
|
-
if (
|
|
284
|
-
|
|
293
|
+
if (
|
|
294
|
+
!helpResult.stdout.includes("/auxiliary") ||
|
|
295
|
+
!helpResult.stdout.includes("/review") ||
|
|
296
|
+
!helpResult.stdout.includes("/scs") ||
|
|
297
|
+
helpResult.stdout.includes("/enabless") ||
|
|
298
|
+
helpResult.stdout.includes(misspelledAuxiliary)
|
|
299
|
+
) {
|
|
300
|
+
throw new Error("interactive help did not expose the expected slash commands");
|
|
285
301
|
}
|
|
286
302
|
const zhHelpResult = await runCli(["chat", "--language", "zh-Hans"], "/help\n/exit\n");
|
|
287
303
|
if (!zhHelpResult.stdout.includes("命令:") || !zhHelpResult.stdout.includes("输入普通任务")) {
|
|
@@ -295,6 +311,22 @@ try {
|
|
|
295
311
|
if (!reviewResult.stdout.includes("Review focus: changed files only") || !reviewResult.stdout.includes("Mock run complete")) {
|
|
296
312
|
throw new Error("interactive /review did not launch the bounded review workflow");
|
|
297
313
|
}
|
|
314
|
+
const scsOnResult = await runChat("/scs\n");
|
|
315
|
+
if (!scsOnResult.stdout.includes("scs=on")) {
|
|
316
|
+
throw new Error("interactive /scs did not toggle SCS on");
|
|
317
|
+
}
|
|
318
|
+
const scsOffResult = await runCli(["chat", "--provider", "mock", "--routing", "manual", "--profile", "code", "--scs"], "/scs\n");
|
|
319
|
+
if (!scsOffResult.stdout.includes("scs=off")) {
|
|
320
|
+
throw new Error("interactive /scs did not toggle SCS off");
|
|
321
|
+
}
|
|
322
|
+
const scsStatusResult = await runChat("/scs status\n");
|
|
323
|
+
if (!scsStatusResult.stdout.includes("SCS mode: off")) {
|
|
324
|
+
throw new Error("interactive /scs status did not show current mode");
|
|
325
|
+
}
|
|
326
|
+
const scsAutoResult = await runChat("/scs auto\n");
|
|
327
|
+
if (!scsAutoResult.stdout.includes("scs=auto")) {
|
|
328
|
+
throw new Error("interactive /scs auto did not enable auto mode");
|
|
329
|
+
}
|
|
298
330
|
const abbreviatedSkillsResult = await runChat("/sk website\n/ex\n");
|
|
299
331
|
if (abbreviatedSkillsResult.stdout.includes("Unknown command") || !abbreviatedSkillsResult.stdout.includes("website-app")) {
|
|
300
332
|
throw new Error("interactive slash command prefix did not auto-select the first matching command");
|
|
@@ -372,6 +404,7 @@ try {
|
|
|
372
404
|
"auxiliary-command-spelling",
|
|
373
405
|
"skills-command",
|
|
374
406
|
"review-command",
|
|
407
|
+
"scs-command-toggle",
|
|
375
408
|
"slash-prefix-autoselect",
|
|
376
409
|
"slash-prefix-canonical-history",
|
|
377
410
|
"instructions-chat-edit",
|
|
@@ -85,6 +85,52 @@ try {
|
|
|
85
85
|
!staleDeepSeekState.messages.some((message) => message.role === "tool" && message.tool_call_id === "stale-call"),
|
|
86
86
|
"repaired DeepSeek history retained an orphan stale tool message"
|
|
87
87
|
);
|
|
88
|
+
const interruptedDeepSeekState = {
|
|
89
|
+
messages: [
|
|
90
|
+
{ role: "system", content: "system" },
|
|
91
|
+
{ role: "user", content: "old request" },
|
|
92
|
+
{
|
|
93
|
+
role: "assistant",
|
|
94
|
+
content: "Running checks.",
|
|
95
|
+
reasoning_content: "Need shell evidence.",
|
|
96
|
+
tool_calls: [
|
|
97
|
+
{ id: "call-a", type: "function", function: { name: "run_command", arguments: "{}" } },
|
|
98
|
+
{ id: "call-b", type: "function", function: { name: "run_command", arguments: "{}" } },
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
{ role: "tool", tool_call_id: "call-a", content: "{\"ok\":true}" },
|
|
102
|
+
{ role: "user", content: "Continue with this new request: /review" },
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
const interruptedRepair = repairModelMessageHistory(interruptedDeepSeekState, { provider: "deepseek" });
|
|
106
|
+
assert(interruptedRepair.changed, "interrupted tool-call history was not repaired");
|
|
107
|
+
assert(interruptedRepair.incompleteToolCallMessages === 1, "interrupted repair did not count the incomplete tool call");
|
|
108
|
+
assert(
|
|
109
|
+
!interruptedDeepSeekState.messages.some((message) => Array.isArray(message.tool_calls) && message.tool_calls.length > 0),
|
|
110
|
+
"interrupted repair retained incomplete assistant tool calls"
|
|
111
|
+
);
|
|
112
|
+
assert(
|
|
113
|
+
!interruptedDeepSeekState.messages.some((message) => message.role === "tool"),
|
|
114
|
+
"interrupted repair retained orphan partial tool result"
|
|
115
|
+
);
|
|
116
|
+
assert(
|
|
117
|
+
interruptedDeepSeekState.messages.at(-1)?.content === "Continue with this new request: /review",
|
|
118
|
+
"interrupted repair dropped the new user request"
|
|
119
|
+
);
|
|
120
|
+
const completeToolState = {
|
|
121
|
+
messages: [
|
|
122
|
+
{ role: "system", content: "system" },
|
|
123
|
+
{
|
|
124
|
+
role: "assistant",
|
|
125
|
+
content: "Using a tool.",
|
|
126
|
+
tool_calls: [{ id: "call-ok", type: "function", function: { name: "list_files", arguments: "{}" } }],
|
|
127
|
+
},
|
|
128
|
+
{ role: "tool", tool_call_id: "call-ok", content: "{\"ok\":true}" },
|
|
129
|
+
{ role: "user", content: "next" },
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
const completeRepair = repairModelMessageHistory(completeToolState, { provider: "openai" });
|
|
133
|
+
assert(!completeRepair.changed, "complete OpenAI-format tool history should not be modified");
|
|
88
134
|
const patchRoute = selectModelRoute({
|
|
89
135
|
routingMode: "smart",
|
|
90
136
|
provider: "deepseek",
|
package/src/agent-runner.js
CHANGED
|
@@ -190,32 +190,68 @@ function preserveAssistantMessage(message) {
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
export function repairModelMessageHistory(state, config = {}) {
|
|
193
|
-
if (
|
|
194
|
-
return {
|
|
193
|
+
if (!Array.isArray(state?.messages)) {
|
|
194
|
+
return {
|
|
195
|
+
changed: false,
|
|
196
|
+
droppedAssistantMessages: 0,
|
|
197
|
+
convertedAssistantMessages: 0,
|
|
198
|
+
droppedToolMessages: 0,
|
|
199
|
+
incompleteToolCallMessages: 0,
|
|
200
|
+
};
|
|
195
201
|
}
|
|
196
202
|
|
|
197
203
|
const repaired = [];
|
|
198
|
-
const droppedToolCallIds = new Set();
|
|
199
204
|
let droppedAssistantMessages = 0;
|
|
200
205
|
let convertedAssistantMessages = 0;
|
|
201
206
|
let droppedToolMessages = 0;
|
|
207
|
+
let incompleteToolCallMessages = 0;
|
|
202
208
|
|
|
203
|
-
for (
|
|
209
|
+
for (let index = 0; index < state.messages.length; index += 1) {
|
|
210
|
+
const message = state.messages[index];
|
|
204
211
|
if (message.role === "assistant") {
|
|
205
212
|
const hasReasoningContent = Boolean(message.reasoning_content || message.reasoningContent);
|
|
206
213
|
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
|
|
207
214
|
const content = String(message.content || "");
|
|
215
|
+
const requiresDeepSeekReasoning = config.provider === "deepseek" && !hasReasoningContent;
|
|
216
|
+
|
|
217
|
+
if (toolCalls.length > 0) {
|
|
218
|
+
const expectedIds = toolCalls.map((call) => String(call?.id || "")).filter(Boolean);
|
|
219
|
+
const expected = new Set(expectedIds);
|
|
220
|
+
const followingToolMessages = [];
|
|
221
|
+
const duplicateOrUnexpectedToolMessages = [];
|
|
222
|
+
const seen = new Set();
|
|
223
|
+
let cursor = index + 1;
|
|
224
|
+
|
|
225
|
+
while (cursor < state.messages.length && state.messages[cursor]?.role === "tool") {
|
|
226
|
+
const toolMessage = state.messages[cursor];
|
|
227
|
+
const toolCallId = String(toolMessage.tool_call_id || "");
|
|
228
|
+
if (expected.has(toolCallId) && !seen.has(toolCallId)) {
|
|
229
|
+
followingToolMessages.push(toolMessage);
|
|
230
|
+
seen.add(toolCallId);
|
|
231
|
+
} else {
|
|
232
|
+
duplicateOrUnexpectedToolMessages.push(toolMessage);
|
|
233
|
+
}
|
|
234
|
+
cursor += 1;
|
|
235
|
+
}
|
|
208
236
|
|
|
209
|
-
|
|
210
|
-
if (
|
|
237
|
+
const completeToolResults = expectedIds.length > 0 && expectedIds.every((id) => seen.has(id));
|
|
238
|
+
if (requiresDeepSeekReasoning || !completeToolResults) {
|
|
211
239
|
droppedAssistantMessages += 1;
|
|
240
|
+
droppedToolMessages += followingToolMessages.length + duplicateOrUnexpectedToolMessages.length;
|
|
241
|
+
if (!completeToolResults) incompleteToolCallMessages += 1;
|
|
242
|
+
index = cursor - 1;
|
|
212
243
|
continue;
|
|
213
244
|
}
|
|
214
245
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
246
|
+
repaired.push(preserveAssistantMessage(message));
|
|
247
|
+
repaired.push(...followingToolMessages);
|
|
248
|
+
droppedToolMessages += duplicateOrUnexpectedToolMessages.length;
|
|
249
|
+
index = cursor - 1;
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (requiresDeepSeekReasoning) {
|
|
254
|
+
if (content.startsWith("Execution plan:")) {
|
|
219
255
|
droppedAssistantMessages += 1;
|
|
220
256
|
continue;
|
|
221
257
|
}
|
|
@@ -236,7 +272,7 @@ export function repairModelMessageHistory(state, config = {}) {
|
|
|
236
272
|
continue;
|
|
237
273
|
}
|
|
238
274
|
|
|
239
|
-
if (message.role === "tool"
|
|
275
|
+
if (message.role === "tool") {
|
|
240
276
|
droppedToolMessages += 1;
|
|
241
277
|
continue;
|
|
242
278
|
}
|
|
@@ -259,6 +295,7 @@ export function repairModelMessageHistory(state, config = {}) {
|
|
|
259
295
|
droppedAssistantMessages,
|
|
260
296
|
convertedAssistantMessages,
|
|
261
297
|
droppedToolMessages,
|
|
298
|
+
incompleteToolCallMessages,
|
|
262
299
|
};
|
|
263
300
|
}
|
|
264
301
|
|
|
@@ -1314,6 +1351,13 @@ export async function runAgent(config) {
|
|
|
1314
1351
|
|
|
1315
1352
|
ensureChatState(state);
|
|
1316
1353
|
|
|
1354
|
+
const initialRepair = repairModelMessageHistory(state, config);
|
|
1355
|
+
if (initialRepair.changed) {
|
|
1356
|
+
await store.appendEvent("history.repaired", initialRepair);
|
|
1357
|
+
observers.event("history.repaired", initialRepair);
|
|
1358
|
+
await store.saveState(state);
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1317
1361
|
observers.log("session.ready", {
|
|
1318
1362
|
sessionId,
|
|
1319
1363
|
provider: config.provider,
|
package/src/cli.js
CHANGED
|
@@ -55,6 +55,15 @@ function readOption(argv, index) {
|
|
|
55
55
|
return value;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
function readOptionalScsMode(argv, index) {
|
|
59
|
+
const value = readOption(argv, index);
|
|
60
|
+
const normalized = String(value || "").trim().toLowerCase();
|
|
61
|
+
if (!["on", "off", "auto", "smart", "true", "false", "yes", "no", "enable", "disable", "enabled", "disabled", "1", "0"].includes(normalized)) {
|
|
62
|
+
return { mode: "on", consumed: false };
|
|
63
|
+
}
|
|
64
|
+
return { mode: value, consumed: true };
|
|
65
|
+
}
|
|
66
|
+
|
|
58
67
|
export function parseArgs(argv) {
|
|
59
68
|
const result = {
|
|
60
69
|
goal: "",
|
|
@@ -151,9 +160,9 @@ export function parseArgs(argv) {
|
|
|
151
160
|
continue;
|
|
152
161
|
}
|
|
153
162
|
if (arg === "--enabless" || arg === "--enable-scs" || arg === "--scs") {
|
|
154
|
-
const
|
|
155
|
-
result.enableScs =
|
|
156
|
-
if (
|
|
163
|
+
const { mode, consumed } = readOptionalScsMode(argv, i);
|
|
164
|
+
result.enableScs = mode;
|
|
165
|
+
if (consumed) i += 1;
|
|
157
166
|
continue;
|
|
158
167
|
}
|
|
159
168
|
if (arg === "--no-enabless" || arg === "--disable-scs" || arg === "--no-scs") {
|
|
@@ -395,7 +404,7 @@ export function parseArgs(argv) {
|
|
|
395
404
|
|
|
396
405
|
function printUsage() {
|
|
397
406
|
console.log(
|
|
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] [--
|
|
407
|
+
'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] [--scs|--scs auto|--no-scs] [--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"'
|
|
399
408
|
);
|
|
400
409
|
console.log(`Languages: ${["en", "ja", "zh-Hans", "zh-Hant", "ko", "fr", "es", "ar", "vi", "de", "ru"].map((code) => `${code}=${languageLabel(code)}`).join(", ")}`);
|
|
401
410
|
}
|
package/src/i18n.js
CHANGED
|
@@ -138,6 +138,7 @@ const TRANSLATIONS = {
|
|
|
138
138
|
helpSkillMesh: "Manage strict reviewed skill sharing.",
|
|
139
139
|
helpProfile: "Set task profile, e.g. code, website, latex, maintenance.",
|
|
140
140
|
helpWebSearch: "Enable or disable the web_search tool.",
|
|
141
|
+
helpEnableScs: "Toggle Student-Committee-Supervisor gated execution.",
|
|
141
142
|
helpScouts: "Enable parallel DeepSeek scouts and set scout count.",
|
|
142
143
|
helpRouting: "Set routing: smart, fast, complex, manual.",
|
|
143
144
|
helpProvider: "Open provider selector, or set deepseek/openai/qwen/venice/mock.",
|
package/src/interactive-cli.js
CHANGED
|
@@ -87,9 +87,8 @@ const SLASH_COMMANDS = [
|
|
|
87
87
|
"/skillsync",
|
|
88
88
|
"/profile",
|
|
89
89
|
"/web-search",
|
|
90
|
-
"/scouts",
|
|
91
|
-
"/enabless",
|
|
92
90
|
"/scs",
|
|
91
|
+
"/scouts",
|
|
93
92
|
"/models",
|
|
94
93
|
"/venice",
|
|
95
94
|
"/route",
|
|
@@ -667,8 +666,8 @@ function printHelp() {
|
|
|
667
666
|
` ${command("/skillmesh [status|off|record|share|sync]", "Manage strict reviewed skill sharing.", "helpSkillMesh")}`,
|
|
668
667
|
` ${command("/profile <name>", "Set task profile, e.g. code, website, latex, maintenance.", "helpProfile")}`,
|
|
669
668
|
` ${command("/web-search on|off", "Enable or disable the web_search tool.", "helpWebSearch")}`,
|
|
669
|
+
` ${command("/scs [on|auto|off|status]", "Toggle Student-Committee-Supervisor gated execution.", "helpEnableScs")}`,
|
|
670
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")}`,
|
|
672
671
|
` ${command("/routing <mode>", "Set routing: smart, fast, complex, manual.", "helpRouting")}`,
|
|
673
672
|
` ${command("/provider [name]", "Open provider selector, or set deepseek/openai/qwen/venice/mock.", "helpProvider")}`,
|
|
674
673
|
` ${command("/docker on", "Use docker-workspace with approved package installs.", "helpDockerOn")}`,
|
|
@@ -2808,14 +2807,40 @@ async function handleCommand(line, state, packageDir) {
|
|
|
2808
2807
|
}
|
|
2809
2808
|
if (command === "enabless" || command === "scs") {
|
|
2810
2809
|
const rawMode = String(value || "").trim().toLowerCase();
|
|
2811
|
-
const
|
|
2810
|
+
const currentMode = normalizeScsMode(state.enableScs || "off");
|
|
2811
|
+
const mode =
|
|
2812
|
+
rawMode === "toggle" || !rawMode
|
|
2813
|
+
? command === "scs"
|
|
2814
|
+
? currentMode === "off"
|
|
2815
|
+
? "on"
|
|
2816
|
+
: "off"
|
|
2817
|
+
: "on"
|
|
2818
|
+
: normalizeScsMode(value);
|
|
2812
2819
|
const knownMode =
|
|
2813
2820
|
!rawMode ||
|
|
2814
|
-
[
|
|
2815
|
-
|
|
2816
|
-
|
|
2821
|
+
[
|
|
2822
|
+
"on",
|
|
2823
|
+
"off",
|
|
2824
|
+
"auto",
|
|
2825
|
+
"smart",
|
|
2826
|
+
"status",
|
|
2827
|
+
"?",
|
|
2828
|
+
"toggle",
|
|
2829
|
+
"true",
|
|
2830
|
+
"false",
|
|
2831
|
+
"yes",
|
|
2832
|
+
"no",
|
|
2833
|
+
"y",
|
|
2834
|
+
"n",
|
|
2835
|
+
"1",
|
|
2836
|
+
"0",
|
|
2837
|
+
"enable",
|
|
2838
|
+
"disable",
|
|
2839
|
+
"enabled",
|
|
2840
|
+
"disabled",
|
|
2841
|
+
].includes(rawMode);
|
|
2817
2842
|
if (!knownMode) {
|
|
2818
|
-
printAgentMessage("Usage: /
|
|
2843
|
+
printAgentMessage("Usage: /scs [on|auto|off|status]. `/scs` toggles SCS on/off for the session.");
|
|
2819
2844
|
return true;
|
|
2820
2845
|
}
|
|
2821
2846
|
if (value === "status" || value === "?") {
|
|
@@ -2823,7 +2848,7 @@ async function handleCommand(line, state, packageDir) {
|
|
|
2823
2848
|
[
|
|
2824
2849
|
`SCS mode: ${state.enableScs || "off"}`,
|
|
2825
2850
|
"Student-Committee-Supervisor gates complex work with one main model: committee drafts, student approves/monitors, supervisor executes.",
|
|
2826
|
-
"Use `/
|
|
2851
|
+
"Use `/scs` to toggle, `/scs auto` for complex-task auto mode, `/scs on` to force it on, or `/scs off` for the normal fast pipeline.",
|
|
2827
2852
|
].join("\n")
|
|
2828
2853
|
);
|
|
2829
2854
|
return true;
|
|
@@ -2837,6 +2862,8 @@ async function handleCommand(line, state, packageDir) {
|
|
|
2837
2862
|
printAgentMessage("SCS enabled. Next run uses the main model for committee planning, student gates, and supervisor execution.");
|
|
2838
2863
|
} else if (state.enableScs === "auto") {
|
|
2839
2864
|
printAgentMessage("SCS auto enabled. It activates for complex, risky, or long-running tasks and stays off for simple turns.");
|
|
2865
|
+
} else {
|
|
2866
|
+
printAgentMessage("SCS disabled. Next run uses the normal routing pipeline.");
|
|
2840
2867
|
}
|
|
2841
2868
|
return true;
|
|
2842
2869
|
}
|