@xingular/harness 1.0.0 → 1.1.1
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 +33 -5
- package/README.md +70 -19
- package/dist/cli.js +10321 -5785
- package/dist/sdk/agents/builtin.d.ts +2 -0
- package/dist/sdk/agents/builtin.js +34 -0
- package/dist/sdk/agents/narrow.d.ts +13 -0
- package/dist/sdk/agents/narrow.js +29 -0
- package/dist/sdk/agents/profiles.d.ts +80 -0
- package/dist/sdk/agents/profiles.js +221 -0
- package/dist/sdk/annotations/bridge.d.ts +42 -0
- package/dist/sdk/annotations/bridge.js +264 -0
- package/dist/sdk/annotations/capture.d.ts +116 -0
- package/dist/sdk/annotations/capture.js +308 -0
- package/dist/sdk/annotations/delivery.d.ts +72 -0
- package/dist/sdk/annotations/delivery.js +130 -0
- package/dist/sdk/annotations/inspect.d.ts +10 -0
- package/dist/sdk/annotations/inspect.js +33 -0
- package/dist/sdk/annotations/isolated.d.ts +6 -0
- package/dist/sdk/annotations/isolated.js +51 -0
- package/dist/sdk/annotations/pageScript.d.ts +28 -0
- package/dist/sdk/annotations/pageScript.js +570 -0
- package/dist/sdk/annotations/part.d.ts +10 -0
- package/dist/sdk/annotations/part.js +144 -0
- package/dist/sdk/annotations/queue.d.ts +4 -0
- package/dist/sdk/annotations/queue.js +40 -0
- package/dist/sdk/annotations/serverMethods.d.ts +3 -0
- package/dist/sdk/annotations/serverMethods.js +62 -0
- package/dist/sdk/annotations/store.d.ts +160 -0
- package/dist/sdk/annotations/store.js +386 -0
- package/dist/sdk/browser/index.d.ts +14 -3
- package/dist/sdk/browser/index.js +11 -4
- package/dist/sdk/browser/serverMethods.d.ts +3 -0
- package/dist/sdk/browser/serverMethods.js +7 -0
- package/dist/sdk/browser/session.d.ts +1 -0
- package/dist/sdk/browser/session.js +45 -9
- package/dist/sdk/cli.js +19 -11
- package/dist/sdk/core/bus.js +1 -1
- package/dist/sdk/core/env.d.ts +1 -1
- package/dist/sdk/core/env.js +1 -1
- package/dist/sdk/doctor/serverMethods.d.ts +3 -0
- package/dist/sdk/doctor/serverMethods.js +8 -0
- package/dist/sdk/harness.d.ts +15 -0
- package/dist/sdk/harness.js +44 -5
- package/dist/sdk/history/recall.js +8 -8
- package/dist/sdk/history/serverMethods.d.ts +3 -0
- package/dist/sdk/history/serverMethods.js +8 -0
- package/dist/sdk/hub/cli.d.ts +1 -1
- package/dist/sdk/hub/cli.js +1 -1
- package/dist/sdk/hub/schema.d.ts +1 -1
- package/dist/sdk/hub/serverMethods.d.ts +3 -0
- package/dist/sdk/hub/serverMethods.js +11 -0
- package/dist/sdk/index.d.ts +10 -0
- package/dist/sdk/index.js +7 -0
- package/dist/sdk/mcp/connections.js +14 -7
- package/dist/sdk/mcp/serverMethods.d.ts +3 -0
- package/dist/sdk/mcp/serverMethods.js +22 -0
- package/dist/sdk/plugins/builtin.d.ts +1 -0
- package/dist/sdk/plugins/builtin.js +128 -33
- package/dist/sdk/plugins/builtinRegistry.d.ts +53 -0
- package/dist/sdk/plugins/builtinRegistry.js +49 -0
- package/dist/sdk/plugins/cli.d.ts +1 -1
- package/dist/sdk/plugins/cli.js +4 -3
- package/dist/sdk/prompt/compile.d.ts +5 -2
- package/dist/sdk/prompt/compile.js +25 -8
- package/dist/sdk/refine/cli.d.ts +1 -1
- package/dist/sdk/refine/cli.js +2 -2
- package/dist/sdk/refine/serverMethods.d.ts +3 -0
- package/dist/sdk/refine/serverMethods.js +20 -0
- package/dist/sdk/server/methods.js +9 -86
- package/dist/sdk/server/params.d.ts +4 -0
- package/dist/sdk/server/params.js +11 -0
- package/dist/sdk/sessions/contracts.d.ts +17 -0
- package/dist/sdk/sessions/contracts.js +42 -3
- package/dist/sdk/sessions/planMode.d.ts +5 -2
- package/dist/sdk/sessions/planMode.js +12 -3
- package/dist/sdk/sessions/reasoningSummaries.d.ts +2 -2
- package/dist/sdk/sessions/reasoningSummaries.js +3 -3
- package/dist/sdk/sessions/registry.d.ts +1 -0
- package/dist/sdk/sessions/registry.js +4 -1
- package/dist/sdk/sessions/runIndex.js +7 -7
- package/dist/sdk/sessions/runStore.js +3 -1
- package/dist/sdk/sessions/runner.js +2 -2
- package/dist/sdk/sessions/sessions.d.ts +17 -5
- package/dist/sdk/sessions/sessions.js +79 -12
- package/dist/sdk/sessions/sideQuestionServerMethods.d.ts +3 -0
- package/dist/sdk/sessions/sideQuestionServerMethods.js +19 -0
- package/dist/sdk/sessions/sideQuestions.d.ts +66 -0
- package/dist/sdk/sessions/sideQuestions.js +290 -0
- package/dist/sdk/sessions/subagentServerMethods.d.ts +3 -0
- package/dist/sdk/sessions/subagentServerMethods.js +41 -0
- package/dist/sdk/sessions/subagentService.d.ts +13 -2
- package/dist/sdk/sessions/subagentService.js +34 -16
- package/dist/sdk/sessions/subagents.d.ts +9 -1
- package/dist/sdk/sessions/subagents.js +19 -0
- package/dist/sdk/terminal/browser.d.ts +62 -0
- package/dist/sdk/terminal/browser.js +41 -0
- package/dist/sdk/terminal/browserControl.d.ts +29 -0
- package/dist/sdk/terminal/browserControl.js +186 -0
- package/dist/sdk/terminal/commandHelp.d.ts +17 -0
- package/dist/sdk/terminal/commandHelp.js +20 -0
- package/dist/sdk/terminal/controller.d.ts +7 -1
- package/dist/sdk/terminal/controller.js +34 -2
- package/dist/sdk/terminal/opentui/subagentsWidget.d.ts +28 -0
- package/dist/sdk/terminal/opentui/subagentsWidget.js +52 -0
- package/dist/sdk/terminal/piExtension.js +33 -48
- package/dist/sdk/terminal/socket.d.ts +6 -3
- package/dist/sdk/terminal/socket.js +40 -9
- package/dist/sdk/terminal/standalone.d.ts +2 -0
- package/dist/sdk/terminal/standalone.js +50 -10
- package/dist/sdk/terminal/subagentMonitor.d.ts +38 -0
- package/dist/sdk/terminal/subagentMonitor.js +121 -0
- package/dist/sdk/terminal/terminals.d.ts +42 -6
- package/dist/sdk/terminal/terminals.js +359 -18
- package/dist/sdk/terminal/trajectory.js +2 -2
- package/dist/sdk/terminal/tui/annotateCommand.d.ts +3 -0
- package/dist/sdk/terminal/tui/annotateCommand.js +22 -0
- package/dist/sdk/terminal/tui/commandPages.d.ts +5 -1
- package/dist/sdk/terminal/tui/commandPages.js +54 -6
- package/dist/sdk/terminal/tui/commands.d.ts +8 -4
- package/dist/sdk/terminal/tui/commands.js +181 -58
- package/dist/sdk/terminal/tui/dialogGeometry.d.ts +2 -2
- package/dist/sdk/terminal/tui/dialogGeometry.js +4 -2
- package/dist/sdk/terminal/tui/dialogs.d.ts +6 -1
- package/dist/sdk/terminal/tui/dialogs.js +9 -2
- package/dist/sdk/terminal/tui/modelPicker.js +1 -6
- package/dist/sdk/terminal/tui/page.d.ts +3 -0
- package/dist/sdk/terminal/tui/pageOverlay.js +17 -6
- package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +26 -4
- package/dist/sdk/terminal/tui/pages/accountsPage.js +264 -36
- package/dist/sdk/terminal/tui/pages/agentsPage.d.ts +74 -0
- package/dist/sdk/terminal/tui/pages/agentsPage.js +190 -0
- package/dist/sdk/terminal/tui/pages/annotatePage.d.ts +94 -0
- package/dist/sdk/terminal/tui/pages/annotatePage.js +341 -0
- package/dist/sdk/terminal/tui/pages/browserPage.d.ts +87 -0
- package/dist/sdk/terminal/tui/pages/browserPage.js +738 -0
- package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +2 -0
- package/dist/sdk/terminal/tui/pages/doctorPage.js +103 -15
- package/dist/sdk/terminal/tui/pages/notesPage.d.ts +75 -0
- package/dist/sdk/terminal/tui/pages/notesPage.js +201 -0
- package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +8 -0
- package/dist/sdk/terminal/tui/pages/settingsPage.js +16 -1
- package/dist/sdk/terminal/tui/pages/subagentsPage.d.ts +23 -0
- package/dist/sdk/terminal/tui/pages/subagentsPage.js +70 -0
- package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +12 -5
- package/dist/sdk/terminal/tui/pages/trajectoryPage.js +156 -83
- package/dist/sdk/terminal/tui/pages/worktreesPage.d.ts +72 -0
- package/dist/sdk/terminal/tui/pages/worktreesPage.js +203 -0
- package/dist/sdk/terminal/tui/planMode.d.ts +1 -1
- package/dist/sdk/terminal/tui/planMode.js +1 -1
- package/dist/sdk/terminal/tui/pluginCommands.d.ts +14 -0
- package/dist/sdk/terminal/tui/pluginCommands.js +27 -0
- package/dist/sdk/terminal/tui/questions.d.ts +2 -0
- package/dist/sdk/terminal/tui/runtime.js +4 -2
- package/dist/sdk/terminal/tui/settingsModel.d.ts +2 -0
- package/dist/sdk/terminal/tui/settingsModel.js +32 -2
- package/dist/sdk/terminal/tui/sideQuestion.d.ts +26 -26
- package/dist/sdk/terminal/tui/sideQuestion.js +131 -98
- package/dist/sdk/terminal/tui/ui.d.ts +2 -0
- package/dist/sdk/terminal/tui/ui.js +1 -0
- package/dist/sdk/tools/askUser.js +26 -8
- package/dist/sdk/tools/checklist.js +2 -2
- package/dist/sdk/tools/harnessTools.d.ts +2 -0
- package/dist/sdk/tools/harnessTools.js +1 -1
- package/dist/sdk/tools/spawnSubagent.js +13 -4
- package/dist/sdk/web/part.d.ts +10 -0
- package/dist/sdk/web/part.js +6 -0
- package/dist/sdk/web/serverMethods.d.ts +3 -0
- package/dist/sdk/web/serverMethods.js +7 -0
- package/dist/sdk/wiki/serverMethods.d.ts +3 -0
- package/dist/sdk/wiki/serverMethods.js +26 -0
- package/dist/sdk/worktrees/cli.d.ts +11 -0
- package/dist/sdk/worktrees/cli.js +146 -0
- package/dist/sdk/worktrees/copy.d.ts +9 -0
- package/dist/sdk/worktrees/copy.js +111 -0
- package/dist/sdk/worktrees/git.d.ts +16 -0
- package/dist/sdk/worktrees/git.js +81 -0
- package/dist/sdk/worktrees/serverMethods.d.ts +3 -0
- package/dist/sdk/worktrees/serverMethods.js +30 -0
- package/dist/sdk/worktrees/service.d.ts +73 -0
- package/dist/sdk/worktrees/service.js +483 -0
- package/dist/sdk/worktrees/setup.d.ts +23 -0
- package/dist/sdk/worktrees/setup.js +65 -0
- package/dist/sdk/worktrees/types.d.ts +91 -0
- package/dist/sdk/worktrees/types.js +1 -0
- package/dist/sdk/world/cli.d.ts +2 -2
- package/dist/sdk/world/cli.js +6 -6
- package/dist/sdk/world/world.d.ts +3 -1
- package/dist/sdk/world/world.js +8 -9
- package/dist/terminal-opentui.js +14540 -7374
- package/dist/terminal-pi.js +285 -666
- package/docs/README.md +22 -2
- package/docs/architecture/00-overview.md +28 -16
- package/docs/architecture/02-sessions-and-runs.md +72 -15
- package/docs/architecture/03-variants.md +10 -2
- package/docs/architecture/04-prompt.md +26 -6
- package/docs/architecture/06-plugins-and-capabilities.md +39 -3
- package/docs/architecture/07-tools-and-gate.md +21 -6
- package/docs/architecture/09-accounts-and-connectors.md +8 -0
- package/docs/architecture/10-server-protocol.md +111 -2
- package/docs/architecture/11-terminal.md +185 -5
- package/docs/architecture/12-storage.md +15 -1
- package/docs/architecture/13-world-tools.md +28 -6
- package/docs/architecture/14-surfaces-and-parity.md +89 -0
- package/docs/architecture/README.md +15 -4
- package/docs/architecture/proposals/PROP-0006-run-checklist.md +4 -2
- package/docs/architecture/proposals/PROP-0013-resource-browser.md +58 -0
- package/docs/architecture/proposals/PROP-0014-fullscreen-browser-tabs.md +58 -0
- package/docs/architecture/proposals/PROP-0015-one-capability-surface.md +88 -0
- package/docs/architecture/proposals/PROP-0016-managed-worktrees.md +156 -0
- package/docs/architecture/proposals/PROP-0017-page-annotations.md +127 -0
- package/docs/architecture/proposals/PROP-0018-annotation-queue-and-app-targets.md +179 -0
- package/docs/architecture/proposals/PROP-0019-contextual-side-questions.md +122 -0
- package/docs/architecture/proposals/PROP-0020-builtin-feature-plugins.md +105 -0
- package/docs/architecture/proposals/PROP-0021-command-namespaces-and-duplicates.md +99 -0
- package/docs/architecture/proposals/PROP-0022-plan-only-questions.md +102 -0
- package/docs/architecture/proposals/PROP-0023-xagent-cli-name.md +61 -0
- package/docs/architecture/proposals/PROP-0024-question-sketch-previews.md +130 -0
- package/docs/architecture/proposals/PROP-0025-contextual-question-wireframes.md +49 -0
- package/docs/architecture/proposals/PROP-0026-connected-sketch-display.md +94 -0
- package/docs/architecture/proposals/PROP-0027-xingular-agent-product-identity.md +60 -0
- package/docs/architecture/proposals/PROP-0028-normalize-question-wireframes.md +55 -0
- package/docs/architecture/proposals/PROP-0029-agent-profiles.md +124 -0
- package/docs/architecture/proposals/PROP-0030-subagent-title.md +86 -0
- package/docs/architecture/proposals/README.md +25 -0
- package/docs/decisions/ADR-0009-xharness-command.md +6 -5
- package/docs/decisions/ADR-0014-public-release-baseline.md +3 -2
- package/docs/decisions/ADR-0015-resource-browser.md +28 -0
- package/docs/decisions/ADR-0016-fullscreen-browser-tabs.md +31 -0
- package/docs/decisions/ADR-0017-one-capability-surface.md +34 -0
- package/docs/decisions/ADR-0018-builtin-feature-plugins.md +35 -0
- package/docs/decisions/ADR-0019-managed-git-worktrees.md +31 -0
- package/docs/decisions/ADR-0020-page-annotations.md +37 -0
- package/docs/decisions/ADR-0021-required-command-namespaces.md +40 -0
- package/docs/decisions/ADR-0022-plan-only-question-tools.md +34 -0
- package/docs/decisions/ADR-0023-contextual-side-question-runs.md +35 -0
- package/docs/decisions/ADR-0024-xagent-command.md +40 -0
- package/docs/decisions/ADR-0025-question-choice-sketches.md +49 -0
- package/docs/decisions/ADR-0026-contextual-question-wireframes.md +58 -0
- package/docs/decisions/ADR-0027-connected-sketch-display.md +60 -0
- package/docs/decisions/ADR-0028-xingular-agent-product-identity.md +56 -0
- package/docs/decisions/ADR-0029-normalized-question-wireframe-borders.md +33 -0
- package/docs/decisions/ADR-0030-agent-profiles.md +43 -0
- package/docs/doctor.md +10 -4
- package/docs/features/README.md +26 -0
- package/docs/features/interfaces/README.md +1 -1
- package/docs/future-work.md +48 -0
- package/docs/parity.md +78 -0
- package/docs/releases/1.0.0.md +2 -2
- package/docs/releases/4.0.0.md +46 -0
- package/docs/releases/README.md +20 -15
- package/docs/study/00-index.md +5 -0
- package/docs/study/autonomous-engineering-sources.md +277 -0
- package/docs/study/autonomy-sources.md +147 -0
- package/docs/study/proactive-autonomy.md +408 -0
- package/docs/study/tui-resource-browser.md +78 -0
- package/docs/terminal-tui.md +325 -93
- package/package.json +3 -3
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Harness } from "../harness.js";
|
|
2
|
+
import type { Handler } from "../server/rpc.js";
|
|
3
|
+
import type { WorldOptions, WorldPart } from "../world/world.js";
|
|
4
|
+
import type { BrowserEngine } from "../browser/index.js";
|
|
5
|
+
import type { CallerContext } from "../core/caller.js";
|
|
6
|
+
import type { DispatchEnv } from "../tools/dispatch.js";
|
|
7
|
+
import type { ToolSpec } from "../tools/types.js";
|
|
8
|
+
import type { Subagents } from "../sessions/subagentService.js";
|
|
9
|
+
import type { ActiveRun } from "../sessions/registry.js";
|
|
10
|
+
import type { PluginDescriptor } from "./types.js";
|
|
11
|
+
export interface BuiltinPluginCommand {
|
|
12
|
+
pluginId: string;
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
namespace: 'unprefixed' | 'plugin';
|
|
16
|
+
}
|
|
17
|
+
export interface BuiltinWorldContext {
|
|
18
|
+
options: WorldOptions;
|
|
19
|
+
setting(pluginId: string, key: string): number;
|
|
20
|
+
browserEngine: BrowserEngine | null;
|
|
21
|
+
}
|
|
22
|
+
export interface BuiltinToolContext {
|
|
23
|
+
env: DispatchEnv;
|
|
24
|
+
caller: CallerContext;
|
|
25
|
+
variantDir: string | null;
|
|
26
|
+
run: ActiveRun;
|
|
27
|
+
runId: string;
|
|
28
|
+
allowedTools: readonly string[];
|
|
29
|
+
harnessTools: boolean;
|
|
30
|
+
subagents: Subagents;
|
|
31
|
+
sessionName: ToolSpec;
|
|
32
|
+
connectionTools?: () => ToolSpec[];
|
|
33
|
+
}
|
|
34
|
+
export interface BuiltinPluginModule {
|
|
35
|
+
descriptor: PluginDescriptor;
|
|
36
|
+
/** Stable order for model tools, independent of descriptor display order. */
|
|
37
|
+
toolOrder?: number;
|
|
38
|
+
tools?: (context: BuiltinToolContext) => ToolSpec[];
|
|
39
|
+
commands?: readonly Omit<BuiltinPluginCommand, 'pluginId' | 'namespace'>[];
|
|
40
|
+
createWorldPart?: (context: BuiltinWorldContext) => WorldPart | null;
|
|
41
|
+
serverMethods?: (harness: Harness) => Record<string, Handler>;
|
|
42
|
+
}
|
|
43
|
+
export interface BuiltinPluginRegistry {
|
|
44
|
+
readonly modules: readonly BuiltinPluginModule[];
|
|
45
|
+
descriptors(): PluginDescriptor[];
|
|
46
|
+
commands(): BuiltinPluginCommand[];
|
|
47
|
+
command(name: string): BuiltinPluginCommand | undefined;
|
|
48
|
+
tools(context: BuiltinToolContext): ToolSpec[];
|
|
49
|
+
worldParts(context: BuiltinWorldContext): WorldPart[];
|
|
50
|
+
serverMethods(harness: Harness): Record<string, Handler>;
|
|
51
|
+
}
|
|
52
|
+
/** One checked registry for the Harness-owned plugin modules and their surface contributions. */
|
|
53
|
+
export declare function createBuiltinPluginRegistry(modules: readonly BuiltinPluginModule[]): BuiltinPluginRegistry;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** One checked registry for the Harness-owned plugin modules and their surface contributions. */
|
|
2
|
+
export function createBuiltinPluginRegistry(modules) {
|
|
3
|
+
const pluginIds = new Set();
|
|
4
|
+
const commandNames = new Set();
|
|
5
|
+
for (const module of modules) {
|
|
6
|
+
const id = module.descriptor.id;
|
|
7
|
+
if (pluginIds.has(id))
|
|
8
|
+
throw new Error(`Duplicate built-in plugin id: ${id}`);
|
|
9
|
+
pluginIds.add(id);
|
|
10
|
+
for (const command of module.commands ?? []) {
|
|
11
|
+
if (!/^[a-z][a-z0-9-]*$/i.test(command.name))
|
|
12
|
+
throw new Error(`Invalid built-in plugin command: ${command.name}`);
|
|
13
|
+
if (commandNames.has(command.name))
|
|
14
|
+
throw new Error(`Duplicate built-in plugin command: ${command.name}`);
|
|
15
|
+
commandNames.add(command.name);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const commands = modules.flatMap(module => (module.commands ?? []).map(command => ({
|
|
19
|
+
pluginId: module.descriptor.id,
|
|
20
|
+
...command,
|
|
21
|
+
namespace: module.descriptor.required ? 'unprefixed' : 'plugin'
|
|
22
|
+
})));
|
|
23
|
+
const byCommand = new Map(commands.map(command => [command.name, command]));
|
|
24
|
+
const toolModules = modules.map((module, index) => ({ module, index })).filter(({ module }) => module.tools)
|
|
25
|
+
.sort((left, right) => (left.module.toolOrder ?? left.index) - (right.module.toolOrder ?? right.index));
|
|
26
|
+
return {
|
|
27
|
+
modules,
|
|
28
|
+
descriptors: () => modules.map(module => module.descriptor),
|
|
29
|
+
commands: () => [...commands],
|
|
30
|
+
command: name => byCommand.get(name),
|
|
31
|
+
tools: context => toolModules.flatMap(({ module }) => module.tools(context)),
|
|
32
|
+
worldParts: context => modules.flatMap(module => {
|
|
33
|
+
const part = module.createWorldPart?.(context);
|
|
34
|
+
return part ? [part] : [];
|
|
35
|
+
}),
|
|
36
|
+
serverMethods: harness => {
|
|
37
|
+
const methods = {};
|
|
38
|
+
for (const module of modules) {
|
|
39
|
+
const contributed = module.serverMethods?.(harness) ?? {};
|
|
40
|
+
for (const [name, handler] of Object.entries(contributed)) {
|
|
41
|
+
if (name in methods)
|
|
42
|
+
throw new Error(`Duplicate built-in server method: ${name}`);
|
|
43
|
+
methods[name] = handler;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return methods;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Harness, type HarnessOptions } from "../harness.js";
|
|
2
|
-
export declare const PLUGINS_USAGE = "Usage:
|
|
2
|
+
export declare const PLUGINS_USAGE = "Usage: xagent plugins <command> [options]\n\n list Every plugin and whether it is on\n show <plugin id> One plugin: what it brings, where it is on, its code\n install <source> A folder, an npm name, or a git address. It arrives off and untrusted\n remove <plugin id> Remove a plugin you installed\n update [plugin id] Fetch a newer version of one installed plugin, or of all\n attach <id> Switch a plugin, or one thing it brings, on\n detach <id> Switch it off\n trust <plugin id> [--yes] Show the files of its code, then trust them\n untrust <plugin id> Stop trusting its code\n\nOptions:\n --data <dir> Data directory (default: ~/.xingular-harness/data)\n --state <dir> State directory (default: ~/.xingular-harness/state)\n --cwd <dir> Also list what this working folder brings\n --project <id> attach/detach for one project instead of everywhere\n --agent <id> attach/detach for one agent instead of everywhere\n";
|
|
3
3
|
export interface PluginsCliDependencies {
|
|
4
4
|
home?: string;
|
|
5
5
|
cwd?: string;
|
package/dist/sdk/plugins/cli.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
// `
|
|
1
|
+
// `xagent plugins …`: plugin control for a person using the harness without an
|
|
2
2
|
// application. It runs outside any session, as the person who typed it, and acts directly.
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { join, resolve } from 'node:path';
|
|
5
5
|
import { createInterface } from 'node:readline/promises';
|
|
6
|
+
import { DEFAULT_PRODUCT_NAME } from "../core/env.js";
|
|
6
7
|
import { Harness } from "../harness.js";
|
|
7
8
|
import * as api from "./api.js";
|
|
8
9
|
import * as install from "./install.js";
|
|
9
|
-
export const PLUGINS_USAGE = `Usage:
|
|
10
|
+
export const PLUGINS_USAGE = `Usage: xagent plugins <command> [options]
|
|
10
11
|
|
|
11
12
|
list Every plugin and whether it is on
|
|
12
13
|
show <plugin id> One plugin: what it brings, where it is on, its code
|
|
@@ -81,7 +82,7 @@ export async function runPluginsCli(argv, dependencies = {}) {
|
|
|
81
82
|
}
|
|
82
83
|
const base = dependencies.cwd ?? process.cwd();
|
|
83
84
|
const root = join(dependencies.home ?? homedir(), '.xingular-harness');
|
|
84
|
-
const options = { dataRoot: parsed.values.data ? resolve(base, parsed.values.data) : join(root, 'data'), stateDir: parsed.values.state ? resolve(base, parsed.values.state) : join(root, 'state'), productName:
|
|
85
|
+
const options = { dataRoot: parsed.values.data ? resolve(base, parsed.values.data) : join(root, 'data'), stateDir: parsed.values.state ? resolve(base, parsed.values.state) : join(root, 'state'), productName: DEFAULT_PRODUCT_NAME };
|
|
85
86
|
// Built without opening the data root: a plugin command must not settle runs or migrate a Wiki
|
|
86
87
|
// that another process may be using.
|
|
87
88
|
const harness = dependencies.createHarness ? dependencies.createHarness(options) : new Harness(options);
|
|
@@ -4,6 +4,7 @@ import type { Materialised } from "../variant/materialise.js";
|
|
|
4
4
|
export declare const REFERENCES_BUDGET = 12000;
|
|
5
5
|
/** Where the harness's own sections sit; an application's sections are placed among them by `order`. */
|
|
6
6
|
export declare const SECTION_ORDER: {
|
|
7
|
+
readonly harnessIdentity: 5;
|
|
7
8
|
readonly system: 25;
|
|
8
9
|
readonly guardrails: 40;
|
|
9
10
|
readonly memory: 45;
|
|
@@ -21,7 +22,7 @@ export interface Source {
|
|
|
21
22
|
revision?: string | null;
|
|
22
23
|
}
|
|
23
24
|
export interface Section {
|
|
24
|
-
/** `identity`, `role`, `system`, `guardrails`, `memory`, `references`, `subagents`, `scripts`, `wiki`, `tools`, or an application's own. */
|
|
25
|
+
/** `harness-identity`, `identity`, `role`, `system`, `guardrails`, `memory`, `references`, `subagents`, `scripts`, `wiki`, `tools`, or an application's own. */
|
|
25
26
|
id: string;
|
|
26
27
|
title: string;
|
|
27
28
|
body: string;
|
|
@@ -105,6 +106,8 @@ export interface Launch {
|
|
|
105
106
|
toolGroups?: HostToolGroup[];
|
|
106
107
|
/** Appended to the tools section when it is cut. */
|
|
107
108
|
toolsPointer?: string;
|
|
109
|
+
/** Suppresses tool guidance for a run that deliberately has no callable tools. */
|
|
110
|
+
hideToolGuidance?: boolean;
|
|
108
111
|
/** Recorded with the pack: the application's name for who it is for. Defaults to `agent` or `session`. */
|
|
109
112
|
profile?: string;
|
|
110
113
|
}
|
|
@@ -129,7 +132,7 @@ export interface OrderedGroup extends ToolGroup {
|
|
|
129
132
|
* The caller's tools by group, in a fixed order. History and the Wiki are always there; the rest
|
|
130
133
|
* follows the switches in `launch.tools` and what the application provides.
|
|
131
134
|
*/
|
|
132
|
-
export declare function toolGroups(context: CallerContext, launch: Launch): OrderedGroup[];
|
|
135
|
+
export declare function toolGroups(context: CallerContext, launch: Launch, dataRoot?: string): OrderedGroup[];
|
|
133
136
|
/** Compiles the pack for a caller. It only reads the data root. */
|
|
134
137
|
export declare function compile(env: HarnessEnv, context: CallerContext, launch?: Launch, variant?: Materialised | null): ContextPack;
|
|
135
138
|
/** The pack as the one string a session receives. */
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// A pack is an ordered list of sections, each with its own character budget. The harness writes
|
|
5
5
|
// the sections that come from the session's variant (instructions, guardrails, memory, tool
|
|
6
6
|
// guidance, and the indexes of its subagents and scripts), the selected references, the Wiki
|
|
7
|
-
// pointer, and the tools
|
|
8
|
-
// role,
|
|
7
|
+
// pointer, and the tools. The foundation supplies its identity; the embedding application supplies
|
|
8
|
+
// any additional identity, role, and current work. Each run's pack is recorded in `runs/<id>/context.json`.
|
|
9
9
|
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
10
10
|
import { join } from 'node:path';
|
|
11
11
|
import { isSession, projectOf, usesCli } from "../core/caller.js";
|
|
@@ -13,7 +13,9 @@ import { isDir, now, readJson, safeId, writeJson } from "../core/fs.js";
|
|
|
13
13
|
import { charCount, compareText, lines, takeChars } from "../core/text.js";
|
|
14
14
|
import * as notes from "../wiki/notes.js";
|
|
15
15
|
import { isWorldTool, WORLD_GUIDANCE } from "../world/untrusted.js";
|
|
16
|
+
import { CHECKLIST_WRITE } from "../tools/checklist.js";
|
|
16
17
|
import { SESSION_NAME } from "../tools/sessionName.js";
|
|
18
|
+
const IDENTITY_BUDGET = 1000;
|
|
17
19
|
const WIKI_BUDGET = 2500;
|
|
18
20
|
const TOOLS_BUDGET = 8000;
|
|
19
21
|
const REPORTING_BUDGET = 2000;
|
|
@@ -22,7 +24,7 @@ export const REFERENCES_BUDGET = 12000;
|
|
|
22
24
|
const VARIANT_BUDGET = 30_000;
|
|
23
25
|
const NOTES_LISTED = 25;
|
|
24
26
|
/** Where the harness's own sections sit; an application's sections are placed among them by `order`. */
|
|
25
|
-
export const SECTION_ORDER = { system: 25, guardrails: 40, memory: 45, references: 50, subagents: 64, scripts: 66, wiki: 80, tools: 90, reporting: 95 };
|
|
27
|
+
export const SECTION_ORDER = { harnessIdentity: 5, system: 25, guardrails: 40, memory: 45, references: 50, subagents: 64, scripts: 66, wiki: 80, tools: 90, reporting: 95 };
|
|
26
28
|
/** How a run's final reply is shaped. Fixed text: it sits in the stable prefix of every pack. */
|
|
27
29
|
export const REPORTING_GUIDANCE = `When you finish work, write the final reply for a person who did not watch you work.
|
|
28
30
|
|
|
@@ -100,12 +102,13 @@ function wiki(root, context) {
|
|
|
100
102
|
* The caller's tools by group, in a fixed order. History and the Wiki are always there; the rest
|
|
101
103
|
* follows the switches in `launch.tools` and what the application provides.
|
|
102
104
|
*/
|
|
103
|
-
export function toolGroups(context, launch) {
|
|
105
|
+
export function toolGroups(context, launch, dataRoot) {
|
|
104
106
|
const enabled = launch.tools ?? [];
|
|
105
107
|
const session = isSession(context);
|
|
106
108
|
const cli = usesCli(context);
|
|
107
109
|
const native = NATIVE_GROUP.filter((name) => enabled.includes(name));
|
|
108
110
|
const wikiTools = WIKI_GROUP.filter((name) => name !== 'wiki_write' || enabled.includes(name));
|
|
111
|
+
const readGuidance = `Read-only file tools accept absolute paths and paths beginning with ~ anywhere this process has operating-system read access. The working folder is a default location, not a repository boundary.${dataRoot ? ` The Harness data root is ${dataRoot}.` : ''}`;
|
|
109
112
|
const groups = [
|
|
110
113
|
{
|
|
111
114
|
group: 'History',
|
|
@@ -127,12 +130,20 @@ export function toolGroups(context, launch) {
|
|
|
127
130
|
group: 'Native',
|
|
128
131
|
tools: native,
|
|
129
132
|
order: GROUP_ORDER.Native,
|
|
130
|
-
guidance: session
|
|
133
|
+
guidance: session
|
|
134
|
+
? `Files and shell: ${readGuidance} Edits and commands still pass through the Harness gate.`
|
|
135
|
+
: `Files (${native.join(', ')}): ${readGuidance} Edits and commands still pass through the current gate.`
|
|
131
136
|
},
|
|
132
137
|
// Web, browser and computer tools: the harness's own, and their results are untrusted (world/untrusted.ts).
|
|
133
138
|
{ group: 'World', tools: enabled.filter((name) => isWorldTool(name) && !(launch.toolGroups ?? []).some((group) => group.tools.includes(name))), order: GROUP_ORDER.World, guidance: `Web, browser and screen: ${WORLD_GUIDANCE}` },
|
|
134
139
|
...(launch.toolGroups ?? []).map((group) => ({ group: group.group, tools: group.tools, order: group.order, guidance: group.guidance }))
|
|
135
140
|
];
|
|
141
|
+
if (enabled.includes(CHECKLIST_WRITE)) {
|
|
142
|
+
groups.push({
|
|
143
|
+
group: 'Progress', tools: [CHECKLIST_WRITE], order: 87,
|
|
144
|
+
guidance: 'Progress: for work with several steps, write a checklist early with checklist_write and keep it current. The user follows your work from it, and a subagent\'s checklist shows as its progress in the user\'s list of subagents.'
|
|
145
|
+
});
|
|
146
|
+
}
|
|
136
147
|
if (enabled.includes(SESSION_NAME)) {
|
|
137
148
|
groups.push({
|
|
138
149
|
group: 'Session', tools: [SESSION_NAME], order: 88,
|
|
@@ -145,8 +156,10 @@ export function toolGroups(context, launch) {
|
|
|
145
156
|
const present = groups.filter((group) => group.tools.length);
|
|
146
157
|
// A session's file and shell tools are Pi's own, whatever the switches say.
|
|
147
158
|
if (session && !present.some((group) => group.group === 'Native')) {
|
|
148
|
-
present.push({ group: 'Native', tools: ['harness file and shell tools'], order: GROUP_ORDER.placeholder, guidance:
|
|
159
|
+
present.push({ group: 'Native', tools: ['harness file and shell tools'], order: GROUP_ORDER.placeholder, guidance: `Files and shell: ${readGuidance} Edits and commands still pass through the Harness gate.` });
|
|
149
160
|
}
|
|
161
|
+
if (launch.hideToolGuidance)
|
|
162
|
+
return [];
|
|
150
163
|
return present.map((group, index) => ({ group, index })).sort((left, right) => left.group.order - right.group.order || left.index - right.index).map(({ group }) => group);
|
|
151
164
|
}
|
|
152
165
|
/** One paragraph per tool group the caller has, then the harness's own tool guidance. */
|
|
@@ -207,13 +220,17 @@ function hostSection(host) {
|
|
|
207
220
|
/** Compiles the pack for a caller. It only reads the data root. */
|
|
208
221
|
export function compile(env, context, launch = {}, variant = null) {
|
|
209
222
|
const { root } = env;
|
|
210
|
-
const groups = toolGroups(context, launch);
|
|
223
|
+
const groups = toolGroups(context, launch, root);
|
|
211
224
|
const variantSource = variant ? [{ id: variant.scope ?? variant.dir, kind: 'variant', revision: variant.fingerprint }] : [];
|
|
212
225
|
const built = [
|
|
226
|
+
{
|
|
227
|
+
order: SECTION_ORDER.harnessIdentity,
|
|
228
|
+
section: section('harness-identity', 'Harness identity', `You are an AI agent running in ${env.productName}.`, IDENTITY_BUDGET, '', [])
|
|
229
|
+
},
|
|
213
230
|
...(variant?.sections ?? []).map((entry) => ({ order: entry.order, section: section(entry.id, entry.title, entry.body, VARIANT_BUDGET, '', variantSource) })),
|
|
214
231
|
{ order: SECTION_ORDER.references, section: selectedReferences(root, launch) },
|
|
215
232
|
{ order: SECTION_ORDER.wiki, section: wiki(root, context) },
|
|
216
|
-
{ order: SECTION_ORDER.tools, section: tools(groups, variant?.toolGuidance ?? '', launch.toolsPointer ?? '') },
|
|
233
|
+
{ order: SECTION_ORDER.tools, section: launch.hideToolGuidance ? null : tools(groups, variant?.toolGuidance ?? '', launch.toolsPointer ?? '') },
|
|
217
234
|
{ order: SECTION_ORDER.reporting, section: section('reporting', 'Reporting your work', REPORTING_GUIDANCE, REPORTING_BUDGET, '', []) },
|
|
218
235
|
...(launch.sections ?? []).map((host) => ({ order: host.order, section: hostSection(host) }))
|
|
219
236
|
].map((entry, index) => ({ ...entry, index }));
|
package/dist/sdk/refine/cli.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const REFINE_USAGE = "Usage:
|
|
1
|
+
export declare const REFINE_USAGE = "Usage: xagent refine <demo | run | matrix> [options]\n\n demo [--k N] [--mode parallel|sequential] [--out <dir>]\n Run the deterministic demo: no model, no credentials.\n run --variant <dir> --task <file.md> [--source <dir>] [--scope <id>] [--k N]\n [--mode parallel|sequential] [--data <dir>] [--state <dir>] [--model <id>]\n [--executor-model <id>] [--retain-workspaces]\n Refine a harness on one task with the default account. Costs about\n 4k executions and 3k improver sessions. --model sets the improver's\n model, --executor-model the executions' model. --retain-workspaces\n keeps each execution's files for grading afterwards.\n matrix --suite <file.json> [--data <dir>] [--out <file.json>]\n Evaluate variants on a task set with the demo executor: no model.\n Versions come from a variant directory ({ label, dir }) or a committed\n scope ({ label, scope, version? }); tasks are RefineTask records.\n Writes <data>/refine/<id>/matrix.json and --out's copy when given.\n";
|
|
2
2
|
export declare function runRefineCli(argv: string[], io?: {
|
|
3
3
|
write: (text: string) => void;
|
|
4
4
|
}): Promise<number>;
|
package/dist/sdk/refine/cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// `
|
|
1
|
+
// `xagent refine`: refinement from a terminal.
|
|
2
2
|
//
|
|
3
3
|
// refine demo [--k N] [--mode parallel|sequential] [--out <dir>]
|
|
4
4
|
// Runs the deterministic ledger demo end to end with no model and no credentials.
|
|
@@ -23,7 +23,7 @@ import { DemoExecutor, DemoImprover, demoBaseVariant, demoTasks } from "./demo.j
|
|
|
23
23
|
import { Library } from "./library.js";
|
|
24
24
|
import { runRefinement } from "./runner.js";
|
|
25
25
|
import { runMatrix } from "./suite.js";
|
|
26
|
-
export const REFINE_USAGE = `Usage:
|
|
26
|
+
export const REFINE_USAGE = `Usage: xagent refine <demo | run | matrix> [options]
|
|
27
27
|
|
|
28
28
|
demo [--k N] [--mode parallel|sequential] [--out <dir>]
|
|
29
29
|
Run the deterministic demo: no model, no credentials.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { optional, text } from "../server/params.js";
|
|
2
|
+
import { readSummary } from "./runner.js";
|
|
3
|
+
export function refinementServerMethods(harness) {
|
|
4
|
+
const root = () => harness.env.root;
|
|
5
|
+
return {
|
|
6
|
+
'refine.start': (params) => harness.refine.start({ task: params.task, k: typeof params.k === 'number' ? params.k : 1, mode: params.mode === 'sequential' ? 'sequential' : 'parallel', improver: params.improver ?? {}, executor: params.executor ?? undefined, baseVersion: optional(params, 'baseVersion'), retainWorkspaces: params.retainWorkspaces === true, id: optional(params, 'id') ?? undefined }),
|
|
7
|
+
'refine.get': (params) => harness.refine.get(text(params, 'id')),
|
|
8
|
+
'refine.list': (params) => harness.refine.list({ scope: optional(params, 'scope'), limit: typeof params.limit === 'number' ? params.limit : undefined }),
|
|
9
|
+
'refine.running': () => harness.refine.running(),
|
|
10
|
+
'refine.cancel': async (params) => {
|
|
11
|
+
await harness.refine.cancel(text(params, 'id'));
|
|
12
|
+
return readSummary(root(), text(params, 'id'));
|
|
13
|
+
},
|
|
14
|
+
'refine.candidates': (params) => harness.refine.candidates(text(params, 'id')),
|
|
15
|
+
'refine.adopt': (params) => harness.refine.adopt(text(params, 'id'), { label: optional(params, 'label') }),
|
|
16
|
+
'library.list': (params) => harness.refine.library(text(params, 'scope')),
|
|
17
|
+
'library.read': (params) => harness.refine.libraryEntry(text(params, 'scope'), text(params, 'area'), text(params, 'task')),
|
|
18
|
+
'library.forget': (params) => harness.refine.forget(text(params, 'scope'), text(params, 'area'), Array.isArray(params.tasks) ? params.tasks : [])
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -7,12 +7,10 @@ import { HarnessError, invalid } from "../core/errors.js";
|
|
|
7
7
|
import * as capabilities from "../capabilities/api.js";
|
|
8
8
|
import { loadRun as loadCapabilitySnapshot } from "../capabilities/runSnapshot.js";
|
|
9
9
|
import { capabilitySet } from "../capabilities/runSnapshot.js";
|
|
10
|
-
import { validateScopeIds } from "../mcp/connections.js";
|
|
11
|
-
import * as recall from "../history/recall.js";
|
|
12
10
|
import * as plugins from "../plugins/api.js";
|
|
11
|
+
import { BUILTIN_PLUGIN_REGISTRY } from "../plugins/builtin.js";
|
|
13
12
|
import * as install from "../plugins/install.js";
|
|
14
13
|
import { compile, load, render } from "../prompt/compile.js";
|
|
15
|
-
import { readSummary } from "../refine/runner.js";
|
|
16
14
|
import { continuationOf } from "../sessions/continuation.js";
|
|
17
15
|
import { selectHistory } from "../sessions/history.js";
|
|
18
16
|
import { runsSince } from "../sessions/runIndex.js";
|
|
@@ -25,14 +23,7 @@ import { seedVariant } from "../variant/seed.js";
|
|
|
25
23
|
import * as variants from "../variant/store.js";
|
|
26
24
|
import { PI_SURFACE } from "../variant/surface.js";
|
|
27
25
|
import { applyEdit, autotrigger, VariantError, validate } from "../variant/variant.js";
|
|
28
|
-
import
|
|
29
|
-
const text = (params, name) => {
|
|
30
|
-
const value = params[name];
|
|
31
|
-
if (typeof value !== 'string' || !value)
|
|
32
|
-
throw invalid(`${name} is required.`);
|
|
33
|
-
return value;
|
|
34
|
-
};
|
|
35
|
-
const optional = (params, name) => (typeof params[name] === 'string' && params[name] ? params[name] : null);
|
|
26
|
+
import { optional, text } from "./params.js";
|
|
36
27
|
const questionAnswer = (value) => {
|
|
37
28
|
const answer = value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
38
29
|
return {
|
|
@@ -64,32 +55,16 @@ function check(variant) {
|
|
|
64
55
|
return { ok: false, problems: error instanceof VariantError ? error.problems : [error instanceof Error ? error.message : String(error)] };
|
|
65
56
|
}
|
|
66
57
|
}
|
|
67
|
-
/** Only the named fields of a parameter object. */
|
|
68
|
-
function pick(params, keys) {
|
|
69
|
-
return Object.fromEntries(keys.filter((key) => key in params).map((key) => [key, params[key]]));
|
|
70
|
-
}
|
|
71
58
|
export function methods(harness) {
|
|
72
|
-
const { accounts, approvals,
|
|
59
|
+
const { accounts, approvals, runs, sessions, terminals, env } = harness;
|
|
73
60
|
const root = () => env.root;
|
|
74
61
|
const variantsChanged = (scope) => harness.bus.emit({ type: 'variants.changed', scope });
|
|
75
|
-
|
|
62
|
+
const builtins = BUILTIN_PLUGIN_REGISTRY.serverMethods(harness);
|
|
63
|
+
const foundation = {
|
|
76
64
|
// ---- The harness itself --------------------------------------------------------------------
|
|
77
|
-
'web.status': () => harness.world.searchStatus(),
|
|
78
|
-
'web.setKey': (params) => harness.world.setSearchKey(text(params, 'provider'), typeof params.key === 'string' ? params.key : null),
|
|
79
|
-
'browser.config': () => harness.world.browserConfig(),
|
|
80
|
-
'browser.configure': (params) => harness.world.configureBrowser(pick(params, ['headed', 'cdpUrl', 'executablePath', 'allowPrivate', 'allowedDomains'])),
|
|
81
65
|
'harness.status': () => ({ dataRoot: harness.dataRoot, productName: env.productName, recovery: harness.recovery, activeRuns: runs.activeRunIds() }),
|
|
82
|
-
'doctor.start': (params) => harness.doctor.start(params),
|
|
83
|
-
'doctor.read': (params) => harness.doctor.read(text(params, 'id')),
|
|
84
|
-
'doctor.cancel': (params) => harness.doctor.cancel(text(params, 'id')),
|
|
85
66
|
'harness.open': (params) => harness.open(text(params, 'dataRoot'), Array.isArray(params.agentIds) ? params.agentIds : []),
|
|
86
67
|
'harness.rebuildIndex': () => harness.rebuildIndex(),
|
|
87
|
-
'hub.list': (params) => harness.hub.list(params.refresh === true),
|
|
88
|
-
'hub.get': (params) => harness.hub.get(text(params, 'id'), text(params, 'version'), params.preview === true),
|
|
89
|
-
'hub.install': (params) => harness.hub.install(text(params, 'id'), text(params, 'version')),
|
|
90
|
-
'hub.preview': (params) => harness.hub.preview(text(params, 'id'), text(params, 'version'), typeof params.offset === 'number' ? params.offset : 0),
|
|
91
|
-
'hub.uninstall': (params) => harness.hub.uninstall(text(params, 'id'), text(params, 'version')),
|
|
92
|
-
'hub.readDocument': (params) => harness.hub.readDocument(text(params, 'id'), text(params, 'version')),
|
|
93
68
|
// ---- Accounts --------------------------------------------------------------------------------
|
|
94
69
|
'accounts.list': () => accounts.overview(),
|
|
95
70
|
'accounts.find': (params) => accounts.find(text(params, 'accountId')),
|
|
@@ -129,22 +104,6 @@ export function methods(harness) {
|
|
|
129
104
|
'approvals.remember': (params) => approvals.remember(text(params, 'sessionId'), text(params, 'target')),
|
|
130
105
|
'approvals.forget': (params) => approvals.forget(text(params, 'sessionId'), text(params, 'target')),
|
|
131
106
|
'approvals.forgetSession': (params) => approvals.forgetSession(text(params, 'sessionId')),
|
|
132
|
-
// ---- Connected apps --------------------------------------------------------------------------
|
|
133
|
-
'connections.list': () => apps.connections.list(),
|
|
134
|
-
'connections.forScope': (params) => apps.connections.forScope({ agentId: optional(params, 'agentId'), projectId: optional(params, 'projectId') }),
|
|
135
|
-
'connections.save': (params) => apps.save(params.input),
|
|
136
|
-
'connections.allowTool': (params) => apps.connections.allowTool(text(params, 'connectionId'), text(params, 'tool')),
|
|
137
|
-
'connections.remove': (params) => apps.remove(text(params, 'connectionId')),
|
|
138
|
-
'connections.test': (params) => apps.test(text(params, 'connectionId')),
|
|
139
|
-
'connections.signIn': (params) => apps.signIn(text(params, 'connectionId')),
|
|
140
|
-
'connections.signOut': (params) => apps.signOut(text(params, 'connectionId')),
|
|
141
|
-
'connections.runContext': (params) => apps.runContext(text(params, 'runId')),
|
|
142
|
-
'connections.refreshSource': (params) => apps.refreshSource(text(params, 'runId'), text(params, 'traceId'), text(params, 'sourceUri')),
|
|
143
|
-
'connections.setAgentScope': (params) => apps.setAgentScope(params.creator ?? {}, text(params, 'agentId'), Array.isArray(params.ids) ? params.ids : []),
|
|
144
|
-
'connections.removeAgentScope': (params) => apps.removeAgentScope(text(params, 'agentId')),
|
|
145
|
-
'connections.revision': () => apps.connections.revision(),
|
|
146
|
-
'connections.appClients': () => apps.appClients(),
|
|
147
|
-
'connections.validateScope': (params) => validateScopeIds(apps.connections.list(), { agentId: optional(params, 'agentId'), projectId: optional(params, 'projectId') }, Array.isArray(params.ids) ? params.ids : []),
|
|
148
107
|
// ---- Variants: the eight components that shape an agent ---------------------------------
|
|
149
108
|
'variants.surface': () => PI_SURFACE,
|
|
150
109
|
'variants.list': () => variants.scopes(root()).map((scope) => {
|
|
@@ -227,45 +186,8 @@ export function methods(harness) {
|
|
|
227
186
|
const built = materialise(root(), params.variant, { trust: harness.trust });
|
|
228
187
|
return { ...built, files: undefined };
|
|
229
188
|
},
|
|
230
|
-
// ---- Refinement: improving a harness from evidence -------------------------------------------
|
|
231
|
-
'refine.start': (params) => harness.refine.start({ task: params.task, k: typeof params.k === 'number' ? params.k : 1, mode: params.mode === 'sequential' ? 'sequential' : 'parallel', improver: params.improver ?? {}, executor: params.executor ?? undefined, baseVersion: optional(params, 'baseVersion'), retainWorkspaces: params.retainWorkspaces === true, id: optional(params, 'id') ?? undefined }),
|
|
232
|
-
'refine.get': (params) => harness.refine.get(text(params, 'id')),
|
|
233
|
-
'refine.list': (params) => harness.refine.list({ scope: optional(params, 'scope'), limit: typeof params.limit === 'number' ? params.limit : undefined }),
|
|
234
|
-
'refine.running': () => harness.refine.running(),
|
|
235
|
-
'refine.cancel': async (params) => {
|
|
236
|
-
await harness.refine.cancel(text(params, 'id'));
|
|
237
|
-
return readSummary(root(), text(params, 'id'));
|
|
238
|
-
},
|
|
239
|
-
'refine.candidates': (params) => harness.refine.candidates(text(params, 'id')),
|
|
240
|
-
'refine.adopt': (params) => harness.refine.adopt(text(params, 'id'), { label: optional(params, 'label') }),
|
|
241
|
-
'library.list': (params) => harness.refine.library(text(params, 'scope')),
|
|
242
|
-
'library.read': (params) => harness.refine.libraryEntry(text(params, 'scope'), text(params, 'area'), text(params, 'task')),
|
|
243
|
-
'library.forget': (params) => harness.refine.forget(text(params, 'scope'), text(params, 'area'), Array.isArray(params.tasks) ? params.tasks : []),
|
|
244
|
-
// ---- The Wiki: project notes ------------------------------------------------------------------
|
|
245
|
-
'wiki.list': (params) => notes.list(root(), params.project === undefined ? {} : { project: optional(params, 'project') }),
|
|
246
|
-
'wiki.read': (params) => notes.read(root(), text(params, 'path')),
|
|
247
|
-
'wiki.write': (params) => {
|
|
248
|
-
const note = notes.write(root(), text(params, 'path'), typeof params.text === 'string' ? params.text : '', { expectedUpdatedAt: optional(params, 'expectedUpdatedAt') });
|
|
249
|
-
harness.bus.emit({ type: 'wiki.changed' });
|
|
250
|
-
return note;
|
|
251
|
-
},
|
|
252
|
-
'wiki.remove': (params) => {
|
|
253
|
-
notes.remove(root(), text(params, 'path'));
|
|
254
|
-
harness.bus.emit({ type: 'wiki.changed' });
|
|
255
|
-
},
|
|
256
|
-
'wiki.search': (params) => notes.search(root(), typeof params.query === 'string' ? params.query : '', { project: optional(params, 'project'), limit: typeof params.limit === 'number' ? params.limit : undefined }),
|
|
257
|
-
'wiki.graph': () => notes.graph(root()),
|
|
258
|
-
'wiki.versions': (params) => notes.versions(root(), text(params, 'path')),
|
|
259
|
-
'wiki.version': (params) => notes.version(root(), text(params, 'path'), text(params, 'id')),
|
|
260
|
-
'wiki.ensureProject': () => {
|
|
261
|
-
notes.ensureLayout(root(), env.productName);
|
|
262
|
-
harness.bus.emit({ type: 'wiki.changed' });
|
|
263
|
-
},
|
|
264
189
|
// ---- What a session calls, on behalf of a caller the host names -------------------------------
|
|
265
190
|
'harness.call': (params) => dispatch(env, (params.context ?? {}), text(params, 'call'), params.params ?? {}, { variantDir: optional(params, 'variantDir') }),
|
|
266
|
-
// ---- Recall ------------------------------------------------------------------------------------
|
|
267
|
-
'recall.search': (params) => recall.searchAll(env, typeof params.query === 'string' ? params.query : '', params.filter ?? {}),
|
|
268
|
-
'recall.read': (params) => recall.read(root(), text(params, 'runId')),
|
|
269
191
|
// ---- The compiled prompt -----------------------------------------------------------------------
|
|
270
192
|
'context.compile': (params) => {
|
|
271
193
|
const variant = params.variant ? materialise(root(), params.variant, { trust: harness.trust }) : null;
|
|
@@ -354,9 +276,6 @@ export function methods(harness) {
|
|
|
354
276
|
runs.answerQuestions(text(params, 'runId'), text(params, 'batchId'), params.answers.map((item) => ({ questionId: text(item, 'questionId'), answer: questionAnswer(item.answer) })));
|
|
355
277
|
},
|
|
356
278
|
// ---- Sessions ----------------------------------------------------------------------------------
|
|
357
|
-
'subagents.spawn': (params) => harness.subagents.spawn(params),
|
|
358
|
-
'subagents.wait': (params) => harness.subagents.wait(params),
|
|
359
|
-
'subagents.results': (params) => harness.subagents.results(params),
|
|
360
279
|
'sessions.spawnSubagent': (params) => sessions.spawnSubagent(params),
|
|
361
280
|
'sessions.run': (params) => sessions.run(params),
|
|
362
281
|
'sessions.history': (params) => ({ sessionFile: selectHistory({ sessionDir: text(params, 'sessionDir'), resume: params.resume ?? null }) }),
|
|
@@ -367,4 +286,8 @@ export function methods(harness) {
|
|
|
367
286
|
'terminal.state': (params) => terminals.state(text(params, 'sessionId')),
|
|
368
287
|
'terminal.dispose': (params) => terminals.dispose(text(params, 'sessionId'))
|
|
369
288
|
};
|
|
289
|
+
const overlap = Object.keys(foundation).find(name => name in builtins);
|
|
290
|
+
if (overlap)
|
|
291
|
+
throw new Error(`Server method ${overlap} is owned by both Foundation and a built-in plugin.`);
|
|
292
|
+
return { ...builtins, ...foundation };
|
|
370
293
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type Params = Record<string, any>;
|
|
2
|
+
export declare const text: (params: Params, name: string) => string;
|
|
3
|
+
export declare const optional: (params: Params, name: string) => string | null;
|
|
4
|
+
export declare function pick<T extends string>(params: Params, keys: readonly T[]): Record<T, unknown>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { invalid } from "../core/errors.js";
|
|
2
|
+
export const text = (params, name) => {
|
|
3
|
+
const value = params[name];
|
|
4
|
+
if (typeof value !== 'string' || !value)
|
|
5
|
+
throw invalid(`${name} is required.`);
|
|
6
|
+
return value;
|
|
7
|
+
};
|
|
8
|
+
export const optional = (params, name) => (typeof params[name] === 'string' && params[name] ? params[name] : null);
|
|
9
|
+
export function pick(params, keys) {
|
|
10
|
+
return Object.fromEntries(keys.filter(key => key in params).map(key => [key, params[key]]));
|
|
11
|
+
}
|
|
@@ -50,10 +50,19 @@ export declare const toolAttachmentRefsSchema: z.ZodArray<z.ZodObject<{
|
|
|
50
50
|
mimeType: z.ZodString;
|
|
51
51
|
}, z.core.$strict>>;
|
|
52
52
|
export type ToolAttachmentRef = z.infer<typeof toolAttachmentRefSchema>;
|
|
53
|
+
export declare const QUESTION_SKETCH_MAX_LINES = 24;
|
|
54
|
+
export declare const QUESTION_SKETCH_MAX_COLUMNS = 80;
|
|
55
|
+
export declare const QUESTION_SKETCH_MAX_LENGTH: number;
|
|
56
|
+
export declare const QUESTION_SKETCH_PATTERN = "^(?:[\\x20-\\x7e]{0,80})(?:\\n[\\x20-\\x7e]{0,80}){0,23}$";
|
|
57
|
+
export declare const questionSketchSchema: z.ZodString;
|
|
58
|
+
export declare function questionSketchError(uiSketch: unknown, options: readonly {
|
|
59
|
+
sketch?: unknown;
|
|
60
|
+
}[]): string | undefined;
|
|
53
61
|
export declare const questionOptionSchema: z.ZodObject<{
|
|
54
62
|
label: z.ZodString;
|
|
55
63
|
description: z.ZodOptional<z.ZodString>;
|
|
56
64
|
recommended: z.ZodOptional<z.ZodBoolean>;
|
|
65
|
+
sketch: z.ZodOptional<z.ZodString>;
|
|
57
66
|
}, z.core.$strip>;
|
|
58
67
|
export type QuestionOption = z.infer<typeof questionOptionSchema>;
|
|
59
68
|
/** One line of the run's checklist. The list has no ids: every update replaces all of it. */
|
|
@@ -277,10 +286,12 @@ export declare const runEventPayloadSchemas: {
|
|
|
277
286
|
questionId: z.ZodString;
|
|
278
287
|
question: z.ZodString;
|
|
279
288
|
summary: z.ZodOptional<z.ZodString>;
|
|
289
|
+
uiSketch: z.ZodOptional<z.ZodLiteral<true>>;
|
|
280
290
|
options: z.ZodArray<z.ZodObject<{
|
|
281
291
|
label: z.ZodString;
|
|
282
292
|
description: z.ZodOptional<z.ZodString>;
|
|
283
293
|
recommended: z.ZodOptional<z.ZodBoolean>;
|
|
294
|
+
sketch: z.ZodOptional<z.ZodString>;
|
|
284
295
|
}, z.core.$strip>>;
|
|
285
296
|
multiSelect: z.ZodBoolean;
|
|
286
297
|
allowText: z.ZodBoolean;
|
|
@@ -500,6 +511,10 @@ export interface RunRecord {
|
|
|
500
511
|
/** The variant the run used: its scope and version fingerprint. */
|
|
501
512
|
variantScope?: string | null;
|
|
502
513
|
variantVersion?: string | null;
|
|
514
|
+
/** The agent profile a subagent started from (PROP-0029); null for a copy of its parent. */
|
|
515
|
+
profile?: string | null;
|
|
516
|
+
/** The short name a parent gave a subagent, shown in the roster (PROP-0030). */
|
|
517
|
+
title?: string | null;
|
|
503
518
|
}
|
|
504
519
|
export declare const runRecordSchema: z.ZodObject<{
|
|
505
520
|
resumedFromRunId: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
|
|
@@ -527,6 +542,8 @@ export declare const runRecordSchema: z.ZodObject<{
|
|
|
527
542
|
trigger: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
|
|
528
543
|
variantScope: z.ZodOptional<z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>>;
|
|
529
544
|
variantVersion: z.ZodOptional<z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>>;
|
|
545
|
+
profile: z.ZodOptional<z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>>;
|
|
546
|
+
title: z.ZodOptional<z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>>;
|
|
530
547
|
}, z.core.$strip>;
|
|
531
548
|
/** Records written before PROP-0009 name the variant `harnessScope` and `harnessVersion`. */
|
|
532
549
|
export declare function upgradeRunRecord(raw: unknown): unknown;
|
|
@@ -91,7 +91,39 @@ const approvalRequestedPayload = z.object({
|
|
|
91
91
|
automatic: approvalAutomaticSchema.optional()
|
|
92
92
|
});
|
|
93
93
|
const approvalResolvedPayload = z.object({ approvalId: z.string(), decision: z.enum(['approved', 'denied', 'native']), automatic: approvalAutomaticSchema.optional() });
|
|
94
|
-
export const
|
|
94
|
+
export const QUESTION_SKETCH_MAX_LINES = 24;
|
|
95
|
+
export const QUESTION_SKETCH_MAX_COLUMNS = 80;
|
|
96
|
+
export const QUESTION_SKETCH_MAX_LENGTH = QUESTION_SKETCH_MAX_LINES * QUESTION_SKETCH_MAX_COLUMNS + QUESTION_SKETCH_MAX_LINES - 1;
|
|
97
|
+
export const QUESTION_SKETCH_PATTERN = `^(?:[\\x20-\\x7e]{0,${QUESTION_SKETCH_MAX_COLUMNS}})(?:\\n[\\x20-\\x7e]{0,${QUESTION_SKETCH_MAX_COLUMNS}}){0,${QUESTION_SKETCH_MAX_LINES - 1}}$`;
|
|
98
|
+
export const questionSketchSchema = z.string()
|
|
99
|
+
.min(1)
|
|
100
|
+
.max(QUESTION_SKETCH_MAX_LENGTH)
|
|
101
|
+
.regex(new RegExp(QUESTION_SKETCH_PATTERN), 'Sketches use up to 24 LF-separated lines of at most 80 printable ASCII characters.')
|
|
102
|
+
.refine((sketch) => {
|
|
103
|
+
const lines = sketch.split('\n');
|
|
104
|
+
return lines.length <= QUESTION_SKETCH_MAX_LINES &&
|
|
105
|
+
lines.every((line) => line.length <= QUESTION_SKETCH_MAX_COLUMNS && /^[\x20-\x7e]*$/u.test(line)) &&
|
|
106
|
+
/[^ \n]/u.test(sketch);
|
|
107
|
+
}, 'A sketch needs visible content and must use up to 24 LF-separated lines of at most 80 printable ASCII characters.');
|
|
108
|
+
export function questionSketchError(uiSketch, options) {
|
|
109
|
+
if (uiSketch !== undefined && uiSketch !== true)
|
|
110
|
+
return 'Set uiSketch to true to enable question sketches.';
|
|
111
|
+
const sketches = options.map((option) => option.sketch);
|
|
112
|
+
if (uiSketch === true && sketches.some((sketch) => sketch === undefined))
|
|
113
|
+
return 'Sketch mode requires a sketch for every choice.';
|
|
114
|
+
if (uiSketch !== true && sketches.some((sketch) => sketch !== undefined))
|
|
115
|
+
return 'Choice sketches require uiSketch: true.';
|
|
116
|
+
if (sketches.some((sketch) => sketch !== undefined && !questionSketchSchema.safeParse(sketch).success)) {
|
|
117
|
+
return 'Each choice sketch must use 1–24 lines of at most 80 printable ASCII characters and contain a visible character.';
|
|
118
|
+
}
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
export const questionOptionSchema = z.object({
|
|
122
|
+
label: z.string().min(1),
|
|
123
|
+
description: z.string().optional(),
|
|
124
|
+
recommended: z.boolean().optional(),
|
|
125
|
+
sketch: questionSketchSchema.optional()
|
|
126
|
+
});
|
|
95
127
|
const questionBatchFields = {
|
|
96
128
|
batchId: z.string().min(1).optional(),
|
|
97
129
|
batchIndex: z.number().int().min(1).max(5).optional(),
|
|
@@ -110,12 +142,17 @@ const questionRequestedPayload = z.object({
|
|
|
110
142
|
questionId: z.string(),
|
|
111
143
|
question: z.string().min(1),
|
|
112
144
|
summary: z.string().min(1).max(100).optional(),
|
|
145
|
+
uiSketch: z.literal(true).optional(),
|
|
113
146
|
options: z.array(questionOptionSchema),
|
|
114
147
|
multiSelect: z.boolean(),
|
|
115
148
|
allowText: z.boolean(),
|
|
116
149
|
userOnly: z.boolean().optional(),
|
|
117
150
|
...questionBatchFields
|
|
118
|
-
}).superRefine(questionBatchRefinement)
|
|
151
|
+
}).superRefine(questionBatchRefinement).superRefine((value, context) => {
|
|
152
|
+
const error = questionSketchError(value.uiSketch, value.options);
|
|
153
|
+
if (error)
|
|
154
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ['options'], message: error });
|
|
155
|
+
});
|
|
119
156
|
const questionAnsweredPayload = z.object({
|
|
120
157
|
questionId: z.string(),
|
|
121
158
|
selected: z.array(z.string()),
|
|
@@ -281,7 +318,9 @@ export const runRecordSchema = z.object({
|
|
|
281
318
|
agentId: text,
|
|
282
319
|
trigger: text,
|
|
283
320
|
variantScope: text.optional(),
|
|
284
|
-
variantVersion: text.optional()
|
|
321
|
+
variantVersion: text.optional(),
|
|
322
|
+
profile: text.optional(),
|
|
323
|
+
title: text.optional()
|
|
285
324
|
});
|
|
286
325
|
/** Records written before PROP-0009 name the variant `harnessScope` and `harnessVersion`. */
|
|
287
326
|
export function upgradeRunRecord(raw) {
|