zames_pro 2.69.0 → 2.71.0
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/CHANGELOG.md +12 -0
- package/README.md +8 -0
- package/dist/agent-loop.js +71 -1
- package/dist/browser.js +114 -212
- package/dist/commands.js +14 -0
- package/dist/config.js +18 -0
- package/dist/deepseek-ui.js +225 -0
- package/dist/i18n/config.js +8 -0
- package/dist/i18n/doctor.js +20 -0
- package/dist/index.js +56 -1
- package/dist/net-capture.js +3 -2
- package/dist/run-task.js +2 -1
- package/dist/subagent.js +119 -0
- package/dist/system-prompt.js +38 -1
- package/dist/tools.js +24 -1
- package/dist/ui-health.js +71 -0
- package/package.json +1 -1
- package/scripts/self-smoke.mjs +45 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.71.0] - 2026-10-08
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **subagent:** add the Task tool, enable subagents by default and instruct the model when to delegate
|
|
15
|
+
|
|
16
|
+
## [2.70.0] - 2026-10-08
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **browser:** centralize DeepSeek UI constants and add a UI health probe
|
|
21
|
+
|
|
10
22
|
## [2.69.0] - 2026-10-08
|
|
11
23
|
|
|
12
24
|
### Changed
|
package/README.md
CHANGED
|
@@ -100,6 +100,10 @@ Key pieces:
|
|
|
100
100
|
- **Project context** — reads `AGENTS.md`, `MEMORY.md`, skills (`SKILL.md`) and
|
|
101
101
|
custom commands from the repo and `~/.zames`, the same idea as Codex / Claude
|
|
102
102
|
Code.
|
|
103
|
+
- **Subagents** — the `Task` tool delegates a self-contained sub-task to an
|
|
104
|
+
agent in its own separate chat (isolated context), which returns only a
|
|
105
|
+
report, so heavy research does not flood the main context. On by default;
|
|
106
|
+
tune with `browser.subagents` / `browser.maxSubagents`.
|
|
103
107
|
- **MCP support** — plug in external tool servers (e.g. `@playwright/mcp`).
|
|
104
108
|
- **Scheduling** — `/loop`, `/cron` and `/jobs` repeat tasks on a timer.
|
|
105
109
|
- **Bilingual UI** — Russian / English (`/config lang`).
|
|
@@ -573,6 +577,10 @@ zames не вызывает API модели. Он запускает headless C
|
|
|
573
577
|
- **Контекст проекта** — читает `AGENTS.md`, `MEMORY.md`, навыки (`SKILL.md`) и
|
|
574
578
|
пользовательские команды из репозитория и `~/.zames`, как в Codex / Claude
|
|
575
579
|
Code.
|
|
580
|
+
- **Субагенты** — инструмент `Task` поручает самодостаточную подзадачу агенту
|
|
581
|
+
в отдельном чате (изолированный контекст), который возвращает только отчёт,
|
|
582
|
+
так что тяжёлая разведка не засоряет основной контекст. Включены по
|
|
583
|
+
умолчанию; настраиваются через `browser.subagents` / `browser.maxSubagents`.
|
|
576
584
|
- **Поддержка MCP** — подключение внешних серверов инструментов (например,
|
|
577
585
|
`@playwright/mcp`).
|
|
578
586
|
- **Планировщик** — `/loop`, `/cron` и `/jobs` повторяют задачи по таймеру.
|
package/dist/agent-loop.js
CHANGED
|
@@ -7,7 +7,7 @@ import { substituteAttachmentMarkers } from './commands.js';
|
|
|
7
7
|
import { normText } from './browser.js';
|
|
8
8
|
import { loadHooks, runPreToolUse, runPostToolUse, } from './hooks.js';
|
|
9
9
|
import { loadPermissions, decidePermission, } from './permissions.js';
|
|
10
|
-
export async function runAgentLoop({ browser, tools, task, workdir, maxIterations = 0, freshChat = false, sendSystemPrompt = false, transcript = null, attachments = [], onThinking = () => { }, onSendPause = () => { }, onSendState = () => { }, onNotice = () => { }, onAssistantThought = () => { }, onToolCall = () => { }, onToolResult = () => { }, onAssistantMessage = () => { }, onChatReady = () => { }, onWarning = () => { }, debugLog = false, locale = 'ru', askDeadlineMs = 240_000, maxAfterToolRetries = 6, onAutoCompact = null, autoCompactPct = 95, contextLimit = 1_000_000, getTokenUsage = null, hooks = undefined, permissions = undefined, onAskPermission = undefined, selfImprovement = false, }) {
|
|
10
|
+
export async function runAgentLoop({ browser, tools, task, workdir, maxIterations = 0, freshChat = false, sendSystemPrompt = false, transcript = null, attachments = [], onThinking = () => { }, onSendPause = () => { }, onSendState = () => { }, onNotice = () => { }, onAssistantThought = () => { }, onToolCall = () => { }, onToolResult = () => { }, onAssistantMessage = () => { }, onChatReady = () => { }, onWarning = () => { }, debugLog = false, locale = 'ru', askDeadlineMs = 240_000, maxAfterToolRetries = 6, onAutoCompact = null, autoCompactPct = 95, contextLimit = 1_000_000, getTokenUsage = null, hooks = undefined, permissions = undefined, onAskPermission = undefined, selfImprovement = false, onSubagent = null, }) {
|
|
11
11
|
// Resolve the hook config ONCE per task: a read per tool call would be
|
|
12
12
|
// wasteful, and a mid-task edit of hooks.json is not something to chase.
|
|
13
13
|
// `undefined` means "read .zames/hooks.json"; an explicit null disables
|
|
@@ -705,6 +705,76 @@ export async function runAgentLoop({ browser, tools, task, workdir, maxIteration
|
|
|
705
705
|
continue;
|
|
706
706
|
}
|
|
707
707
|
for (const call of callsToRun) {
|
|
708
|
+
// `Task` is a SEAM, not an ordinary tool: it is handled by the caller's
|
|
709
|
+
// onSubagent callback (a separate chat with its own context). It is not
|
|
710
|
+
// in `tools` when subagents are disabled, so it is matched by name here
|
|
711
|
+
// BEFORE the unknown-tool branch. With no callback we answer honestly
|
|
712
|
+
// instead of pretending the tool exists.
|
|
713
|
+
if (call.tool === 'Task') {
|
|
714
|
+
const rawPrompt = typeof call.args.prompt === 'string' ? call.args.prompt.trim() : '';
|
|
715
|
+
const rawType = String(call.args.subagent_type ?? '').toLowerCase();
|
|
716
|
+
const subType = rawType === 'explore' ? 'explore' : 'general';
|
|
717
|
+
const rawDesc = typeof call.args.description === 'string' ? call.args.description : '';
|
|
718
|
+
if (!onSubagent || !rawPrompt) {
|
|
719
|
+
const err = !onSubagent
|
|
720
|
+
? 'Subagents are not available in this run. Do the work yourself with the other tools.'
|
|
721
|
+
: 'Task requires a non-empty `prompt` argument.';
|
|
722
|
+
safeToolResult(err);
|
|
723
|
+
transcript?.log('tool_error', { tool: 'Task', error: err });
|
|
724
|
+
results.push({ tool: 'Task', result: err });
|
|
725
|
+
continue;
|
|
726
|
+
}
|
|
727
|
+
syncToolAbort();
|
|
728
|
+
safeToolCall('Task', call.args);
|
|
729
|
+
transcript?.log('subagent_start', {
|
|
730
|
+
type: subType,
|
|
731
|
+
description: rawDesc,
|
|
732
|
+
prompt: rawPrompt,
|
|
733
|
+
});
|
|
734
|
+
const poll = setInterval(syncToolAbort, 100);
|
|
735
|
+
if (typeof poll.unref === 'function')
|
|
736
|
+
poll.unref();
|
|
737
|
+
const subStart = Date.now();
|
|
738
|
+
let subResult;
|
|
739
|
+
try {
|
|
740
|
+
subResult = await onSubagent({
|
|
741
|
+
prompt: rawPrompt,
|
|
742
|
+
description: rawDesc,
|
|
743
|
+
type: subType,
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
catch (e) {
|
|
747
|
+
subResult = {
|
|
748
|
+
ok: false,
|
|
749
|
+
text: `Subagent error: ${e.message}`,
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
finally {
|
|
753
|
+
clearInterval(poll);
|
|
754
|
+
}
|
|
755
|
+
const subText = String(subResult.text || '').trim();
|
|
756
|
+
const subOut = subResult.ok
|
|
757
|
+
? subText || '(the subagent returned no report)'
|
|
758
|
+
: `Subagent failed: ${subText || 'unknown error'}`;
|
|
759
|
+
safeToolResult(subOut);
|
|
760
|
+
transcript?.log('subagent_done', {
|
|
761
|
+
type: subType,
|
|
762
|
+
ok: subResult.ok,
|
|
763
|
+
chars: subText.length,
|
|
764
|
+
durationMs: Date.now() - subStart,
|
|
765
|
+
});
|
|
766
|
+
results.push({ tool: 'Task', result: subOut });
|
|
767
|
+
// The subagent switched the chat underneath us and the callback has
|
|
768
|
+
// already restored the parent chat. Clear the stale-echo baseline:
|
|
769
|
+
// the capture left over from the subagent's chat would otherwise make
|
|
770
|
+
// the watchdog compare the parent's next answer against IT and fire.
|
|
771
|
+
lastRaw = '';
|
|
772
|
+
if (browser._abort || browser._stopped) {
|
|
773
|
+
transcript?.log('user_aborted');
|
|
774
|
+
return '(прервано пользователем)';
|
|
775
|
+
}
|
|
776
|
+
continue;
|
|
777
|
+
}
|
|
708
778
|
const tool = tools.find((t) => t.name === call.tool);
|
|
709
779
|
if (!tool) {
|
|
710
780
|
const err = `Unknown tool: ${call.tool}`;
|