@xenosystem/agent-interface-electron-host 0.1.3 → 0.1.5

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.
@@ -9,6 +9,7 @@
9
9
  * built-in tools (Read, Write, Edit, Glob, Grep, Bash).
10
10
  */
11
11
  import { type PermissionWaitListener } from '@xenosystem/agent-interface-host';
12
+ import { type CommandExecutionResult } from '@xenosystem/agent-interface-host/node';
12
13
  export type { SdkAgentSurface } from './sdkAgentSurface.js';
13
14
  import type { SdkAgentSurface } from './sdkAgentSurface.js';
14
15
  import { type AgentPermissionProfileName, type AgentSandboxCapabilities, type RuntimeEventEnvelope, type RuntimeEventStore } from '@xenosystem/agent-interface-host/node';
@@ -41,6 +42,21 @@ export interface SurfaceApprovalRule {
41
42
  label?: string;
42
43
  createdAt?: number;
43
44
  }
45
+ /**
46
+ * Push a pinned node into the loop currently running for a conversation.
47
+ *
48
+ * Returns `undefined` when nothing is running — the caller turns that into a refusal that names
49
+ * the reason, rather than throwing, because "no turn is in flight" is a fact the operator can act
50
+ * on by starting one.
51
+ */
52
+ export declare function injectContextIntoActiveRun(conversationId: string, input: {
53
+ content: string;
54
+ sourceNodeId?: string;
55
+ label?: string;
56
+ }): Promise<{
57
+ status: 'injected' | 'deferred';
58
+ pendingCount: number;
59
+ } | undefined>;
44
60
  export declare function logAgentDebug(message: string, meta?: Record<string, unknown>): void;
45
61
  export type { AgentPermissionProfileName, AgentSandboxCapabilities, } from '@xenosystem/agent-interface-host/node';
46
62
  export interface SdkAgentRunOptions {
@@ -56,6 +72,12 @@ export interface SdkAgentRunOptions {
56
72
  role: string;
57
73
  content: string;
58
74
  }>;
75
+ /** XENO SPAWN §2.2 pin-forward queued between turns; delivered via `AgentLoop.injectContext()`. */
76
+ injections?: Array<{
77
+ content: string;
78
+ label?: string;
79
+ sourceNodeId?: string;
80
+ }>;
59
81
  systemPrompt?: string;
60
82
  maxIterations?: number;
61
83
  enableThinking?: boolean;
@@ -97,6 +119,28 @@ export interface SdkAgentRunOptions {
97
119
  * unlocks `debug-bypass`, so it must never be reached by default.
98
120
  */
99
121
  isProduction?: boolean;
122
+ /**
123
+ * Where this turn's Bash/PowerShell commands execute — ADE §5.3.
124
+ *
125
+ * Absent keeps today's local executor. Present is what lets a composition
126
+ * confine the agent without this file knowing about sandboxes.
127
+ */
128
+ executionEnvironment?: AgentCommandExecutionEnvironment;
129
+ }
130
+ export interface AgentCommandExecutionEnvironment {
131
+ resolutionForConversation(conversationId: string | undefined): {
132
+ executor: {
133
+ execute(request: {
134
+ argv: readonly [string, ...string[]];
135
+ cwd: string;
136
+ timeoutMs: number;
137
+ maxOutputBytes?: number;
138
+ }): Promise<CommandExecutionResult>;
139
+ };
140
+ isolation: {
141
+ isolation: string;
142
+ };
143
+ };
100
144
  }
101
145
  export declare function runSdkAgent(options: SdkAgentRunOptions): Promise<void>;
102
146
  export declare function grantSdkAccess(params: unknown): {
@@ -1 +1 @@
1
- {"version":3,"file":"sdkAgent.d.ts","sourceRoot":"","sources":["../src/sdkAgent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdkAgent.d.ts","sourceRoot":"","sources":["../src/sdkAgent.ts"],"names":[],"mappings":"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"}
package/dist/sdkAgent.js CHANGED
@@ -9,6 +9,7 @@
9
9
  * built-in tools (Read, Write, Edit, Glob, Grep, Bash).
10
10
  */
11
11
  import { createPermissionWaitRegistry, } from '@xenosystem/agent-interface-host';
12
+ import { commandSucceeded, commandShellArgv, LocalCommandExecutor, } from '@xenosystem/agent-interface-host/node';
12
13
  import { spawn } from 'child_process';
13
14
  import { mkdirSync, readFileSync, existsSync, readdirSync, statSync, writeFileSync } from 'fs';
14
15
  import { resolve as pathResolve, dirname, join, basename, extname, relative } from 'path';
@@ -52,6 +53,7 @@ const activePermissionEngines = new Map();
52
53
  const hubSessionRuntimes = new Map();
53
54
  const pendingSdkCheckpointRestores = new Map();
54
55
  const DEFAULT_AGENT_TOOL_TIMEOUT_MS = 120_000;
56
+ const fallbackCommandExecutor = new LocalCommandExecutor();
55
57
  const MAX_AGENT_TOOL_TIMEOUT_MS = 300_000;
56
58
  const AGENT_VISIBLE_PROGRESS_TIMEOUT_MS = 30_000;
57
59
  const AGENT_IDLE_PROGRESS_TIMEOUT_MS = 30_000;
@@ -73,6 +75,35 @@ const AGENT_CONTEXT_DISCOVERY_TOOL_NAMES = new Set([
73
75
  ]);
74
76
  /** Session-granted directories per requestId (conversation turn) */
75
77
  const sessionGrantedDirs = new Map();
78
+ /**
79
+ * Loops that are RUNNING RIGHT NOW, so a pinned node can reach one (XENO SPAWN §2.2).
80
+ *
81
+ * 🔴 MID-TURN ONLY, AND THAT IS STRUCTURAL RATHER THAN A SHORTCUT. On this lane the `AgentLoop`
82
+ * is constructed per run and awaited to completion — history is re-sent from the host's record on
83
+ * the next turn — so BETWEEN turns there is no loop in existence to inject into. The ACP lane is
84
+ * the opposite: its agent PROCESS persists across turns, which is why `xeno/context.inject` is
85
+ * natural there and this is not.
86
+ *
87
+ * A pin-forward between turns on this lane therefore belongs in the conversation record that seeds
88
+ * the next turn, not here. That route is NOT built; the capability declaration says so.
89
+ *
90
+ * ⚠️ Keyed by conversation, cleared in the run's `finally`, so an entry can never outlive the loop
91
+ * it points at — a stale handle would accept an injection into a loop that has already returned.
92
+ */
93
+ const activeAgentLoops = new Map();
94
+ /**
95
+ * Push a pinned node into the loop currently running for a conversation.
96
+ *
97
+ * Returns `undefined` when nothing is running — the caller turns that into a refusal that names
98
+ * the reason, rather than throwing, because "no turn is in flight" is a fact the operator can act
99
+ * on by starting one.
100
+ */
101
+ export async function injectContextIntoActiveRun(conversationId, input) {
102
+ const loop = activeAgentLoops.get(conversationId);
103
+ if (!loop)
104
+ return undefined;
105
+ return await loop.injectContext(input);
106
+ }
76
107
  export function logAgentDebug(message, meta) {
77
108
  if (process.env.NODE_ENV === 'production')
78
109
  return;
@@ -398,115 +429,54 @@ function truncateHubToolOutput(output, limit = 12_000) {
398
429
  const omitted = output.length - limit;
399
430
  return `${output.slice(0, headLength)}\n\n[xeno: output truncated; omitted ${omitted} middle characters]\n\n${output.slice(output.length - tailLength)}`;
400
431
  }
401
- function executeWindowsPowerShellTool(input, cwd) {
432
+ /**
433
+ * The THIRD adopter of `CommandExecutionPort` — ADE §5.3.
434
+ *
435
+ * 🔴 This used to `spawn('powershell.exe')` on the host as the signed-in user.
436
+ * That was the primary agent-reachable path the isolation inventory named, and
437
+ * the one `WorkspaceHostService.runCommand` adopting the port could not cover.
438
+ * Both now go through the same executor the composition binds per run.
439
+ */
440
+ function executeAgentShellCommand(input, cwd, environment, conversationId) {
402
441
  const command = typeof input.command === 'string' ? input.command : '';
442
+ if (!command.trim()) {
443
+ return Promise.resolve({ success: false, output: '', error: 'Missing required parameter: command' });
444
+ }
403
445
  const timeoutMs = normalizeToolTimeoutMs(input);
404
- return new Promise((resolve) => {
405
- if (!command.trim()) {
406
- resolve({ success: false, output: '', error: 'Missing required parameter: command' });
407
- return;
408
- }
409
- const child = spawn('powershell.exe', [
410
- '-NoLogo',
411
- '-NoProfile',
412
- '-NonInteractive',
413
- '-ExecutionPolicy',
414
- 'Bypass',
415
- '-Command',
416
- command,
417
- ], {
418
- cwd,
419
- env: {
420
- ...process.env,
421
- PYTHONUNBUFFERED: process.env.PYTHONUNBUFFERED || '1',
422
- },
423
- windowsHide: true,
424
- stdio: ['ignore', 'pipe', 'pipe'],
425
- });
426
- let stdout = '';
427
- let stderr = '';
428
- let settled = false;
429
- const finish = (result) => {
430
- if (settled)
431
- return;
432
- settled = true;
433
- clearTimeout(timer);
434
- resolve(result);
446
+ const resolution = environment?.resolutionForConversation(conversationId);
447
+ const executor = resolution?.executor ?? fallbackCommandExecutor;
448
+ const destination = resolution?.isolation.isolation === 'sandboxed' ? 'sandbox' : 'host';
449
+ return executor.execute({
450
+ argv: commandShellArgv(command, destination),
451
+ cwd,
452
+ timeoutMs,
453
+ }).then((result) => toolResultFromExecution(result));
454
+ }
455
+ function toolResultFromExecution(result) {
456
+ const output = truncateHubToolOutput([result.stdout.trimEnd(), result.stderr.trimEnd()].filter(Boolean).join('\n'));
457
+ if (commandSucceeded(result)) {
458
+ return { success: true, output };
459
+ }
460
+ if (result.timedOut) {
461
+ return {
462
+ success: false,
463
+ output,
464
+ error: result.error || 'The command timed out.',
435
465
  };
436
- const timer = setTimeout(() => {
437
- try {
438
- if (child.pid) {
439
- spawn('taskkill', ['/pid', String(child.pid), '/t', '/f'], {
440
- stdio: 'ignore',
441
- windowsHide: true,
442
- });
443
- }
444
- else {
445
- child.kill();
446
- }
447
- }
448
- catch {
449
- try {
450
- child.kill();
451
- }
452
- catch {
453
- // Ignore best-effort process cleanup errors.
454
- }
455
- }
456
- finish({
457
- success: false,
458
- output: truncateHubToolOutput(stdout),
459
- error: `Bash timed out after ${timeoutMs}ms. The PowerShell command was stopped.`,
460
- });
461
- }, timeoutMs);
462
- if (typeof timer.unref === 'function')
463
- timer.unref();
464
- child.stdout.on('data', (chunk) => {
465
- stdout += chunk.toString();
466
- });
467
- child.stderr.on('data', (chunk) => {
468
- stderr += chunk.toString();
469
- });
470
- child.on('error', (err) => {
471
- finish({
472
- success: false,
473
- output: truncateHubToolOutput(stdout),
474
- error: err.message || 'PowerShell command failed to start.',
475
- });
476
- });
477
- child.on('exit', (code) => {
478
- const output = truncateHubToolOutput([stdout.trimEnd(), stderr.trimEnd()].filter(Boolean).join('\n'));
479
- // 🔴 `code` is null when the process was KILLED BY A SIGNAL rather than
480
- // exiting. This used to read `code ?? 1`, which reported
481
- // "Command failed with exit code 1." — inventing a fact.
482
- //
483
- // The two are different things to act on: exit 1 means the program ran
484
- // and failed, so an agent reads the output and fixes the command. A
485
- // signal means something else stopped it — the OOM killer, an external
486
- // kill, a race with the timeout path above — and the command may be
487
- // entirely fine. Telling an agent the first when the second happened
488
- // sends it to debug code that never got to run.
489
- //
490
- // `EngineeringWorkbenchService` already keeps `exitCode: number | null`
491
- // for exactly this reason, and `xeno-use`'s `sandboxExec` makes its exit
492
- // code an Option so a signal-killed process cannot report success. When
493
- // execution routes through that seam this site would otherwise coerce
494
- // the null straight back out again.
495
- if (code === null) {
496
- finish({
497
- success: false,
498
- output,
499
- error: 'The command was terminated by a signal before it exited, so it has no exit code.',
500
- });
501
- return;
502
- }
503
- finish({
504
- success: code === 0,
505
- output,
506
- ...(code === 0 ? {} : { error: `Command failed with exit code ${code}.` }),
507
- });
508
- });
509
- });
466
+ }
467
+ if (result.exitCode === null) {
468
+ return {
469
+ success: false,
470
+ output,
471
+ error: result.error
472
+ || 'The command was terminated by a signal before it exited, so it has no exit code.',
473
+ };
474
+ }
475
+ return {
476
+ success: false,
477
+ output,
478
+ error: result.error || `Command failed with exit code ${result.exitCode}.`,
479
+ };
510
480
  }
511
481
  const FILE_READ_TOOL_NAMES = [
512
482
  'Read',
@@ -3188,7 +3158,7 @@ function wrapRegisteredMultiPathTool(toolRegistry, toolName, pathParams, allowed
3188
3158
  toolRegistry.register(wrappedTool);
3189
3159
  }
3190
3160
  export async function runSdkAgent(options) {
3191
- const { requestId, conversationId, sdkSessionId, subagentRunId, workspaceId, teamId, agentId, model, messages, systemPrompt, maxIterations = 10, enableThinking = false, getAuthToken, getPlatformAuthToken, mainWindow, signal, capabilities, permissionProfile, allowedDirectories, approvalRules: rawApprovalRules, allowTextOnlyFallback = false, toolExecution, onPersistedRuntimeEvent, runtimeEventStore: injectedRuntimeEventStore, coordinationTools, isProduction, } = options;
3161
+ const { requestId, conversationId, sdkSessionId, subagentRunId, workspaceId, teamId, agentId, model, messages, systemPrompt, maxIterations = 10, enableThinking = false, getAuthToken, getPlatformAuthToken, mainWindow, signal, capabilities, permissionProfile, allowedDirectories, approvalRules: rawApprovalRules, allowTextOnlyFallback = false, toolExecution, onPersistedRuntimeEvent, runtimeEventStore: injectedRuntimeEventStore, coordinationTools, isProduction, executionEnvironment, } = options;
3192
3162
  const approvalRules = normalizeApprovalRules(rawApprovalRules);
3193
3163
  const resolvedPermissionProfile = resolveAgentPermissionProfile({
3194
3164
  ...(permissionProfile ? { requestedProfile: permissionProfile } : {}),
@@ -3445,7 +3415,6 @@ export async function runSdkAgent(options) {
3445
3415
  // directory selection instead of the broken "terminal" pseudo-permission.
3446
3416
  const bashTool = toolRegistry.get('Bash');
3447
3417
  if (bashTool) {
3448
- const origExec = bashTool.execute.bind(bashTool);
3449
3418
  const wrappedBash = {
3450
3419
  definition: bashTool.definition,
3451
3420
  execute: async (input) => {
@@ -3495,10 +3464,7 @@ export async function runSdkAgent(options) {
3495
3464
  if (typeof input.timeout !== 'number' && typeof input.timeout_ms !== 'number') {
3496
3465
  input.timeout = DEFAULT_AGENT_TOOL_TIMEOUT_MS;
3497
3466
  }
3498
- if (process.platform === 'win32') {
3499
- return executeWindowsPowerShellTool(input, bashPolicyPath);
3500
- }
3501
- return executeToolWithHubTimeout('Bash', input, () => origExec(input));
3467
+ return executeAgentShellCommand(input, bashPolicyPath, executionEnvironment, conversationId);
3502
3468
  }
3503
3469
  };
3504
3470
  toolRegistry.unregister('Bash');
@@ -3738,6 +3704,35 @@ export async function runSdkAgent(options) {
3738
3704
  flushRendererTextBatch();
3739
3705
  sendRuntimeEventToRenderer(enrichedEvent);
3740
3706
  };
3707
+ /**
3708
+ * 🔴 THE SDK'S RUNTIME BUS HAD NO SUBSCRIBER. IT WAS A SEQUENCE COUNTER.
3709
+ *
3710
+ * `runtimeEventBus` is handed to the AgentLoop below, so the SDK emits its whole runtime stream
3711
+ * onto it — and this file used it for `nextSequence()` in 21 places and `subscribe()` in none.
3712
+ * Every event the SDK raised that the host does not separately hand-build was emitted into a bus
3713
+ * nobody listened to.
3714
+ *
3715
+ * That is exactly the `context.*` family, and it is the family XENO SPAWN §15 step 3 is made of:
3716
+ * `context.pressure` (how full the context is, after every model response that reported usage), `context.injected`
3717
+ * (§2.2 pin-forward) and `context.history.compacted` (§2.1's boundary). `RuntimeTimelineProjection`
3718
+ * has handlers for all three; nothing was ever feeding them on this lane.
3719
+ *
3720
+ * ⚠️ FILTERED TO `context.` ON PURPOSE — forwarding the whole bus would DOUBLE-COUNT. The host
3721
+ * already constructs its own envelopes for `turn.*`, `tool.completed`, `model.*.delta`,
3722
+ * `permission.profile.selected` and the `hub.*` family from callbacks, so those would arrive
3723
+ * twice. It builds no `context.*` event at all, which is why this prefix is the exact seam.
3724
+ *
3725
+ * Events from the bus already carry `id`, `sequence` and `timestamp`, so this is a passthrough
3726
+ * into the same sanitize/enrich/publish path every other event here takes.
3727
+ */
3728
+ runtimeEventBus.subscribe((event) => {
3729
+ if (!event || typeof event !== 'object' || Array.isArray(event))
3730
+ return;
3731
+ const type = event.type;
3732
+ if (typeof type !== 'string' || !type.startsWith('context.'))
3733
+ return;
3734
+ emitRuntimeEvent(event);
3735
+ });
3741
3736
  const clearVisibleProgressWatchdog = () => {
3742
3737
  if (!visibleProgressWatchdogTimer)
3743
3738
  return;
@@ -4690,6 +4685,41 @@ export async function runSdkAgent(options) {
4690
4685
  };
4691
4686
  signal.addEventListener('abort', onAbort, { once: true });
4692
4687
  scheduleVisibleProgressWatchdog();
4688
+ // Registered only for the lifetime of the run below, and only when there is a conversation to
4689
+ // key it by. See `activeAgentLoops` for why this cannot serve a between-turns pin-forward.
4690
+ if (conversationId)
4691
+ activeAgentLoops.set(conversationId, agent);
4692
+ /**
4693
+ * XENO SPAWN §2.2 — nodes pinned while NO turn was running, delivered now.
4694
+ *
4695
+ * 🔴 THE NORMAL CASE FOR PIN-FORWARD, and this lane used to refuse it. §2.2's own framing is an
4696
+ * operator pinning a node so the agent has it for whatever comes next; mid-turn is the exotic
4697
+ * one. The previous answer — "send it as the next prompt instead" — is exactly what §2.2 exists
4698
+ * to prevent, because a prompt makes the agent ANSWER the pinned node and puts a turn on the
4699
+ * timeline nobody asked for.
4700
+ *
4701
+ * ⚠️ Delivered through `AgentLoop.injectContext()` rather than by prepending to `messages`, so
4702
+ * this is the SAME code path as a mid-turn pin: one synthetic-user-message shape, one
4703
+ * `context.injected` emission carrying a real message id, one open-tool-exchange guard. Called
4704
+ * BEFORE `run()`, so nothing is outstanding and each flushes immediately — landing after the
4705
+ * history and before this turn's prompt, which is where recalled context belongs.
4706
+ *
4707
+ * ⚠️ Failures are logged and never thrown. A node that cannot be pinned must not destroy the
4708
+ * turn the user actually asked for — and `injectContext` throws on empty content, which is a
4709
+ * caller bug rather than a reason to lose the run.
4710
+ */
4711
+ for (const injection of options.injections ?? []) {
4712
+ try {
4713
+ await agent.injectContext(injection);
4714
+ }
4715
+ catch (error) {
4716
+ logAgentDebug('Queued context injection failed', {
4717
+ conversationId,
4718
+ label: injection.label,
4719
+ error: error instanceof Error ? error.message : String(error),
4720
+ });
4721
+ }
4722
+ }
4693
4723
  try {
4694
4724
  emitModelWaitRuntimeEvent('hub.model.request.started', 'hub-model-request-lifecycle', {
4695
4725
  message: 'Agent model run started.',
@@ -4841,6 +4871,11 @@ export async function runSdkAgent(options) {
4841
4871
  }
4842
4872
  }
4843
4873
  finally {
4874
+ // Before anything else: an entry that outlived its loop would accept an injection into a run
4875
+ // that has already returned, and report success for content nobody will ever see.
4876
+ if (conversationId && activeAgentLoops.get(conversationId) === agent) {
4877
+ activeAgentLoops.delete(conversationId);
4878
+ }
4844
4879
  flushRendererTextBatch();
4845
4880
  flushRendererCompatTextChunk();
4846
4881
  clearVisibleProgressWatchdog();