@kolisachint/hoocode-agent 0.4.118 → 0.4.120
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 +86 -0
- package/dist/core/agent-session.d.ts +35 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +157 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extension-mcp-servers.d.ts +8 -1
- package/dist/core/extension-mcp-servers.d.ts.map +1 -1
- package/dist/core/extension-mcp-servers.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/plugins/authoring.d.ts.map +1 -1
- package/dist/core/extensions/plugins/authoring.js +5 -2
- package/dist/core/extensions/plugins/authoring.js.map +1 -1
- package/dist/core/extensions/plugins/formats/copilot.d.ts +16 -14
- package/dist/core/extensions/plugins/formats/copilot.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/copilot.js +64 -46
- package/dist/core/extensions/plugins/formats/copilot.js.map +1 -1
- package/dist/core/extensions/plugins/formats/jsonManifest.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/jsonManifest.js +6 -6
- package/dist/core/extensions/plugins/formats/jsonManifest.js.map +1 -1
- package/dist/core/extensions/plugins/formats/shared.d.ts +12 -1
- package/dist/core/extensions/plugins/formats/shared.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/shared.js +16 -0
- package/dist/core/extensions/plugins/formats/shared.js.map +1 -1
- package/dist/core/extensions/plugins/formats/types.d.ts +7 -2
- package/dist/core/extensions/plugins/formats/types.d.ts.map +1 -1
- package/dist/core/extensions/plugins/formats/types.js.map +1 -1
- package/dist/core/extensions/plugins/index.d.ts.map +1 -1
- package/dist/core/extensions/plugins/index.js +13 -0
- package/dist/core/extensions/plugins/index.js.map +1 -1
- package/dist/core/extensions/plugins/install.d.ts +23 -1
- package/dist/core/extensions/plugins/install.d.ts.map +1 -1
- package/dist/core/extensions/plugins/install.js +63 -5
- package/dist/core/extensions/plugins/install.js.map +1 -1
- package/dist/core/extensions/plugins/marketplace.d.ts.map +1 -1
- package/dist/core/extensions/plugins/marketplace.js +22 -16
- package/dist/core/extensions/plugins/marketplace.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +2 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +15 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +33 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/settings-defaults.d.ts +1 -1
- package/dist/core/settings-defaults.d.ts.map +1 -1
- package/dist/core/settings-defaults.js +1 -1
- package/dist/core/settings-defaults.js.map +1 -1
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/tools/plugins.d.ts.map +1 -1
- package/dist/core/tools/plugins.js +26 -5
- package/dist/core/tools/plugins.js.map +1 -1
- package/dist/core/tools/propose-plugin.d.ts.map +1 -1
- package/dist/core/tools/propose-plugin.js +10 -3
- package/dist/core/tools/propose-plugin.js.map +1 -1
- package/dist/extensions/core/mcp-loader.d.ts +11 -3
- package/dist/extensions/core/mcp-loader.d.ts.map +1 -1
- package/dist/extensions/core/mcp-loader.js +103 -18
- package/dist/extensions/core/mcp-loader.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +2 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +4 -4
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Modes use this class and add their own I/O layer on top.
|
|
14
14
|
*/
|
|
15
|
-
import { basename, dirname } from "node:path";
|
|
15
|
+
import { basename, dirname, sep } from "node:path";
|
|
16
16
|
import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, modelsAreEqual, resetApiProviders, } from "@kolisachint/hoocode-ai";
|
|
17
17
|
import { theme } from "../modes/interactive/theme/theme.js";
|
|
18
18
|
import { loadAgentRegistry } from "./agent-registry.js";
|
|
@@ -27,6 +27,7 @@ import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
|
|
|
27
27
|
import { exportSessionToHtml } from "./export-html/index.js";
|
|
28
28
|
import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
|
|
29
29
|
import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
|
|
30
|
+
import { parsePluginDir } from "./extensions/plugins/index.js";
|
|
30
31
|
import { emitSessionShutdownEvent } from "./extensions/runner.js";
|
|
31
32
|
import { expandPromptTemplate, tryExpandPromptTemplate } from "./prompt-templates.js";
|
|
32
33
|
import { clearProviderExhaustion, isProviderQuotaError, markProviderExhausted } from "./provider-health.js";
|
|
@@ -38,6 +39,21 @@ import { createAllToolDefinitions } from "./tools/index.js";
|
|
|
38
39
|
import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
|
|
39
40
|
import { updateWarmSubagentSkillPaths } from "./warm-subagent-pool-instance.js";
|
|
40
41
|
export { parseSkillBlock } from "./agent-session-skills.js";
|
|
42
|
+
function describeActivation(pluginId, skills, commands, agents, pendingReload) {
|
|
43
|
+
const parts = [];
|
|
44
|
+
const list = (label, caps, render) => {
|
|
45
|
+
if (caps.length > 0)
|
|
46
|
+
parts.push(`${label}: ${caps.map(render).join(", ")}`);
|
|
47
|
+
};
|
|
48
|
+
list("skills", skills, (c) => c.name);
|
|
49
|
+
list("commands", commands, (c) => `/${c.name}`);
|
|
50
|
+
list("subagents", agents, (c) => c.name);
|
|
51
|
+
const now = parts.length > 0 ? ` Active NOW (usable this turn) — ${parts.join("; ")}.` : "";
|
|
52
|
+
const later = pendingReload
|
|
53
|
+
? " This plugin also bundles executable capabilities (hooks/MCP servers); they activate automatically when the current turn ends."
|
|
54
|
+
: "";
|
|
55
|
+
return `Plugin "${pluginId}" activated in the live session.${now}${later}`;
|
|
56
|
+
}
|
|
41
57
|
// ============================================================================
|
|
42
58
|
// Constants
|
|
43
59
|
// ============================================================================
|
|
@@ -98,6 +114,20 @@ export class AgentSession {
|
|
|
98
114
|
// Base system prompt (without extension appends) - used to apply fresh appends each turn
|
|
99
115
|
_baseSystemPrompt = "";
|
|
100
116
|
_baseSystemPromptOptions;
|
|
117
|
+
/**
|
|
118
|
+
* Set when tools or the system prompt change while a run is in flight (a tool
|
|
119
|
+
* registered mid-turn, a plugin activated live). The agent loop snapshots its
|
|
120
|
+
* context at run start; this flag makes prepareNextTurn hand the loop a fresh
|
|
121
|
+
* systemPrompt + tools before the next provider request, so mid-turn
|
|
122
|
+
* capability changes are visible within the same turn.
|
|
123
|
+
*/
|
|
124
|
+
_runtimeContextDirty = false;
|
|
125
|
+
/**
|
|
126
|
+
* Set when a change needs a full reload (executable plugin capabilities:
|
|
127
|
+
* hooks, MCP servers, providers) that cannot be wired mid-turn. Consumed on
|
|
128
|
+
* agent_end: once the session is idle the reload runs automatically.
|
|
129
|
+
*/
|
|
130
|
+
_reloadWhenIdle = false;
|
|
101
131
|
constructor(config) {
|
|
102
132
|
this.agent = config.agent;
|
|
103
133
|
this.sessionManager = config.sessionManager;
|
|
@@ -168,6 +198,21 @@ export class AgentSession {
|
|
|
168
198
|
// (session persistence, extensions, auto-compaction, retry logic)
|
|
169
199
|
this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
|
|
170
200
|
this._installAgentToolHooks();
|
|
201
|
+
// Refresh the loop's frozen context snapshot between turns whenever tools or
|
|
202
|
+
// the system prompt changed mid-run (deferred MCP schema resolution, live
|
|
203
|
+
// plugin activation). Keeps the loop's message history; swaps prompt + tools.
|
|
204
|
+
this.agent.prepareNextTurn = (loopContext) => {
|
|
205
|
+
if (!this._runtimeContextDirty)
|
|
206
|
+
return undefined;
|
|
207
|
+
this._runtimeContextDirty = false;
|
|
208
|
+
return {
|
|
209
|
+
context: {
|
|
210
|
+
systemPrompt: this.agent.state.systemPrompt,
|
|
211
|
+
messages: loopContext.context.messages,
|
|
212
|
+
tools: this.agent.state.tools.slice(),
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
};
|
|
171
216
|
this._buildRuntime({
|
|
172
217
|
activeToolNames: this._initialActiveToolNames,
|
|
173
218
|
includeAllExtensionTools: true,
|
|
@@ -366,6 +411,18 @@ export class AgentSession {
|
|
|
366
411
|
this._retry.resolve();
|
|
367
412
|
await this._compaction.checkCompaction(msg);
|
|
368
413
|
}
|
|
414
|
+
// A live plugin activation (or uninstall) mid-run deferred its executable
|
|
415
|
+
// capabilities to a full reload; run it once the session settles. agent_end
|
|
416
|
+
// fires before the run's streaming flag clears, so defer one tick and
|
|
417
|
+
// re-check — if another run started meanwhile, the flag stays armed for the
|
|
418
|
+
// next agent_end.
|
|
419
|
+
if (event.type === "agent_end" && this._reloadWhenIdle) {
|
|
420
|
+
setTimeout(() => {
|
|
421
|
+
if (this._reloadWhenIdle && !this.isStreaming && !this.isCompacting) {
|
|
422
|
+
this._runIdleReload();
|
|
423
|
+
}
|
|
424
|
+
}, 0);
|
|
425
|
+
}
|
|
369
426
|
}
|
|
370
427
|
/** Extract text content from a message */
|
|
371
428
|
_getUserMessageText(message) {
|
|
@@ -597,6 +654,8 @@ export class AgentSession {
|
|
|
597
654
|
// Rebuild base system prompt with new tool set
|
|
598
655
|
this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames);
|
|
599
656
|
this.agent.state.systemPrompt = this._baseSystemPrompt;
|
|
657
|
+
// If a run is in flight, let prepareNextTurn hand the loop this new state.
|
|
658
|
+
this._runtimeContextDirty = true;
|
|
600
659
|
}
|
|
601
660
|
/** Whether compaction or branch summarization is currently running */
|
|
602
661
|
get isCompacting() {
|
|
@@ -1468,6 +1527,8 @@ export class AgentSession {
|
|
|
1468
1527
|
})();
|
|
1469
1528
|
},
|
|
1470
1529
|
getSystemPrompt: () => this.systemPrompt,
|
|
1530
|
+
activatePlugin: (pluginDir) => this.activatePlugin(pluginDir),
|
|
1531
|
+
requestReloadWhenIdle: () => this.requestReloadWhenIdle(),
|
|
1471
1532
|
}, {
|
|
1472
1533
|
registerProvider: (name, config) => {
|
|
1473
1534
|
this._modelRegistry.registerProvider(name, config);
|
|
@@ -1616,6 +1677,101 @@ export class AgentSession {
|
|
|
1616
1677
|
}
|
|
1617
1678
|
}
|
|
1618
1679
|
// =========================================================================
|
|
1680
|
+
// Live plugin activation (single-turn install → use)
|
|
1681
|
+
// =========================================================================
|
|
1682
|
+
/**
|
|
1683
|
+
* Activate a just-installed or just-authored plugin in the LIVE session, no
|
|
1684
|
+
* reload required. Passive capabilities — skills, slash commands, subagents,
|
|
1685
|
+
* themes — register immediately and become visible to the model on its next
|
|
1686
|
+
* provider request, even mid-turn (via the prepareNextTurn context refresh).
|
|
1687
|
+
*
|
|
1688
|
+
* Executable capabilities (hooks, MCP servers, providers) cannot be safely
|
|
1689
|
+
* wired into a run that is already streaming; when the plugin bundles any,
|
|
1690
|
+
* this schedules an automatic full reload for when the session next goes
|
|
1691
|
+
* idle (end of the current turn), so they still activate autonomously.
|
|
1692
|
+
*/
|
|
1693
|
+
activatePlugin(pluginDir) {
|
|
1694
|
+
const plugin = parsePluginDir(pluginDir);
|
|
1695
|
+
if (!plugin) {
|
|
1696
|
+
return { activated: false, message: `No recognizable plugin manifest at ${pluginDir}.` };
|
|
1697
|
+
}
|
|
1698
|
+
const metadata = { source: "plugin", scope: "project", origin: "top-level" };
|
|
1699
|
+
const paths = {
|
|
1700
|
+
skillPaths: plugin.skillsDir ? [{ path: plugin.skillsDir, metadata }] : undefined,
|
|
1701
|
+
slashCommandPaths: plugin.commandsDir ? [{ path: plugin.commandsDir, metadata }] : undefined,
|
|
1702
|
+
agentPaths: plugin.agentsDir ? [{ path: plugin.agentsDir, metadata }] : undefined,
|
|
1703
|
+
themePaths: plugin.themesDir ? [{ path: plugin.themesDir, metadata }] : undefined,
|
|
1704
|
+
};
|
|
1705
|
+
this._resourceLoader.extendResources(paths);
|
|
1706
|
+
updateSubagentSkillPaths(this._resourceLoader.getSkillPaths());
|
|
1707
|
+
updateWarmSubagentSkillPaths(this._resourceLoader.getSkillPaths());
|
|
1708
|
+
// Rebuild the system prompt (skills + agent catalog are injected there) and
|
|
1709
|
+
// mark the run context dirty so the refresh lands before the next provider
|
|
1710
|
+
// request in the current run.
|
|
1711
|
+
this._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());
|
|
1712
|
+
this.agent.state.systemPrompt = this._baseSystemPrompt;
|
|
1713
|
+
this._runtimeContextDirty = true;
|
|
1714
|
+
const underRoot = (filePath) => !!filePath && (filePath === plugin.root || filePath.startsWith(`${plugin.root}${sep}`));
|
|
1715
|
+
const skills = this._resourceLoader
|
|
1716
|
+
.getSkills()
|
|
1717
|
+
.skills.filter((s) => underRoot(s.filePath))
|
|
1718
|
+
.map((s) => ({ name: s.name, description: s.description }));
|
|
1719
|
+
const commands = this._resourceLoader
|
|
1720
|
+
.getPrompts()
|
|
1721
|
+
.prompts.filter((p) => underRoot(p.filePath))
|
|
1722
|
+
.map((p) => ({ name: p.name, description: p.description }));
|
|
1723
|
+
const agents = loadAgentRegistry({ cwd: this._cwd })
|
|
1724
|
+
.list()
|
|
1725
|
+
.filter((a) => underRoot(a.filePath))
|
|
1726
|
+
.map((a) => ({ name: a.name, description: a.description }));
|
|
1727
|
+
const needsReload = !!(plugin.hooks || plugin.mcpServers || (plugin.providers?.length ?? 0) > 0);
|
|
1728
|
+
if (needsReload) {
|
|
1729
|
+
this._reloadWhenIdle = true;
|
|
1730
|
+
if (!this.isStreaming && !this.isCompacting)
|
|
1731
|
+
this._runIdleReload();
|
|
1732
|
+
}
|
|
1733
|
+
return {
|
|
1734
|
+
activated: true,
|
|
1735
|
+
pluginId: plugin.id,
|
|
1736
|
+
skills,
|
|
1737
|
+
commands,
|
|
1738
|
+
agents,
|
|
1739
|
+
pendingReloadForExecutables: needsReload,
|
|
1740
|
+
message: describeActivation(plugin.id, skills, commands, agents, needsReload),
|
|
1741
|
+
};
|
|
1742
|
+
}
|
|
1743
|
+
/**
|
|
1744
|
+
* Ask for a full reload once the session is idle — used when a change (e.g.
|
|
1745
|
+
* uninstalling a plugin) can only take effect through the reload path. Runs
|
|
1746
|
+
* immediately when already idle.
|
|
1747
|
+
*/
|
|
1748
|
+
requestReloadWhenIdle() {
|
|
1749
|
+
this._reloadWhenIdle = true;
|
|
1750
|
+
if (!this.isStreaming && !this.isCompacting)
|
|
1751
|
+
this._runIdleReload();
|
|
1752
|
+
}
|
|
1753
|
+
/** Run the pending idle reload through the mode's reload flow when bound (UI refresh included). */
|
|
1754
|
+
_runIdleReload() {
|
|
1755
|
+
if (!this._reloadWhenIdle)
|
|
1756
|
+
return;
|
|
1757
|
+
this._reloadWhenIdle = false;
|
|
1758
|
+
const reloadFlow = this._extensionCommandContextActions?.reload;
|
|
1759
|
+
void (async () => {
|
|
1760
|
+
try {
|
|
1761
|
+
if (reloadFlow) {
|
|
1762
|
+
await reloadFlow();
|
|
1763
|
+
}
|
|
1764
|
+
else {
|
|
1765
|
+
await this.reload();
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
catch {
|
|
1769
|
+
// Auto-reload is best-effort; a failed reload leaves the session usable
|
|
1770
|
+
// and the plugin activates on the next manual /reload or restart.
|
|
1771
|
+
}
|
|
1772
|
+
})();
|
|
1773
|
+
}
|
|
1774
|
+
// =========================================================================
|
|
1619
1775
|
// Auto-Retry
|
|
1620
1776
|
// =========================================================================
|
|
1621
1777
|
/**
|