@robota-sdk/agent-transport 3.0.0-beta.78 → 3.0.0-beta.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -26
- package/dist/browser/client.d.ts +2 -0
- package/dist/browser/client.js +1 -0
- package/dist/browser/index.d.ts +520 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +2 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/message-decoders-BB8n-H2X.d.ts +252 -0
- package/dist/browser/message-decoders-BB8n-H2X.d.ts.map +1 -0
- package/dist/browser/message-decoders-CDmDoZPR.js +2 -0
- package/dist/browser/message-decoders-CDmDoZPR.js.map +1 -0
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.cts +766 -0
- package/dist/node/index.d.cts.map +1 -0
- package/dist/node/index.d.ts +765 -27
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +1 -1
- package/dist/node/index.js.map +1 -1
- package/dist/node/node.cjs +1 -0
- package/dist/node/node.d.cts +109 -0
- package/dist/node/node.d.cts.map +1 -0
- package/dist/node/node.d.ts +109 -0
- package/dist/node/node.d.ts.map +1 -0
- package/dist/node/node.js +2 -0
- package/dist/node/node.js.map +1 -0
- package/package.json +68 -47
- package/src/__tests__/access-token-verifier.test.ts +672 -0
- package/src/__tests__/admission.test.ts +130 -0
- package/src/__tests__/channel-frames.test.ts +214 -0
- package/src/__tests__/driver-attribution-capability.test.ts +83 -0
- package/src/__tests__/handoff-chunking.test.ts +215 -0
- package/src/__tests__/handoff-manifest.test.ts +52 -0
- package/src/__tests__/message-decoders.test.ts +249 -0
- package/src/__tests__/outbound-delivery.test.ts +558 -0
- package/src/__tests__/peer-message-ledger.test.ts +200 -0
- package/src/__tests__/personal-usage-report.test.ts +193 -0
- package/src/__tests__/resume-buffer.test.ts +93 -0
- package/src/__tests__/session-event-delivery.test.ts +101 -0
- package/src/__tests__/session-message-handler-e5.test.ts +99 -0
- package/src/__tests__/session-message-handler.test.ts +590 -0
- package/src/__tests__/session-resume-bridge.test.ts +406 -0
- package/src/__tests__/submit-prompt-shape.test.ts +78 -0
- package/src/__tests__/usage-report-carrier.test.ts +98 -0
- package/src/__tests__/ws-broadcast-events.test.ts +84 -0
- package/src/background-messages.ts +169 -0
- package/src/channel-frames.ts +182 -0
- package/src/client.ts +9 -0
- package/src/handoff-chunking.ts +235 -0
- package/src/index.ts +112 -3
- package/src/message-decoders.ts +229 -0
- package/src/message-parser.ts +33 -0
- package/src/node/access-token-verifier.ts +363 -0
- package/src/node/admission.ts +153 -0
- package/src/node/handoff-manifest.ts +77 -0
- package/src/node/index.ts +10 -0
- package/src/outbound-delivery.ts +231 -0
- package/src/peer-message-ledger.ts +193 -0
- package/src/protocol-session.ts +28 -0
- package/src/resume-buffer.ts +123 -0
- package/src/session-events.ts +198 -0
- package/src/session-message-handler.ts +282 -0
- package/src/session-query-messages.ts +42 -0
- package/src/session-resume-bridge.ts +252 -0
- package/src/usage-messages.ts +195 -0
- package/src/wire-messages.ts +165 -0
- package/dist/node/headless/index.cjs +0 -1
- package/dist/node/headless/index.d.ts +0 -2
- package/dist/node/headless/index.js +0 -1
- package/dist/node/headless-DG_MEbf0.js +0 -19
- package/dist/node/headless-DG_MEbf0.js.map +0 -1
- package/dist/node/headless-xq77JBq0.cjs +0 -18
- package/dist/node/index-CrJ2Lhn3.d.ts +0 -96
- package/dist/node/index-CrJ2Lhn3.d.ts.map +0 -1
- package/dist/node/index-JIvzrtaA.d.ts +0 -52
- package/dist/node/index-JIvzrtaA.d.ts.map +0 -1
- package/dist/node/index-JTD_xtEQ.d.ts +0 -96
- package/dist/node/index-JTD_xtEQ.d.ts.map +0 -1
- package/dist/node/index-y_HBOfzO.d.ts +0 -52
- package/dist/node/index-y_HBOfzO.d.ts.map +0 -1
- package/dist/node/programmatic/index.cjs +0 -1
- package/dist/node/programmatic/index.d.ts +0 -2
- package/dist/node/programmatic/index.js +0 -1
- package/dist/node/programmatic-6wLf68qJ.cjs +0 -1
- package/dist/node/programmatic-70dxIXtS.js +0 -2
- package/dist/node/programmatic-70dxIXtS.js.map +0 -1
- package/dist/node/testing/index.cjs +0 -1
- package/dist/node/testing/index.d.ts +0 -2
- package/dist/node/testing/index.js +0 -1
- package/src/__tests__/programmatic/programmatic-ask-user.test.ts +0 -32
- package/src/__tests__/programmatic/programmatic-driver.test.ts +0 -107
- package/src/__tests__/programmatic/programmatic-flows.test.ts +0 -140
- package/src/__tests__/transport-registry.stop-all.test.ts +0 -53
- package/src/headless/HeadlessInteractionChannel.ts +0 -129
- package/src/headless/__tests__/headless-channel-options.test.ts +0 -106
- package/src/headless/__tests__/headless-goal-runner.test.ts +0 -108
- package/src/headless/__tests__/headless-provider-failure.integration.test.ts +0 -143
- package/src/headless/__tests__/headless-runner-initialization.test.ts +0 -45
- package/src/headless/__tests__/headless-runner.test.ts +0 -508
- package/src/headless/__tests__/headless-skill-activation.integration.test.ts +0 -430
- package/src/headless/__tests__/headless-transport.test.ts +0 -267
- package/src/headless/cli-input.ts +0 -50
- package/src/headless/headless-runner.ts +0 -230
- package/src/headless/headless-stream-json.ts +0 -148
- package/src/headless/headless-transport.ts +0 -43
- package/src/headless/index.ts +0 -8
- package/src/headless/print-terminal.ts +0 -57
- package/src/programmatic/ProgrammaticInteractionChannel.ts +0 -82
- package/src/programmatic/createProgrammaticAgent.ts +0 -71
- package/src/programmatic/index.ts +0 -5
- package/src/testing/index.ts +0 -10
- package/src/transport-registry.ts +0 -103
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"headless-DG_MEbf0.js","names":[],"sources":["../../src/headless/print-terminal.ts","../../src/headless/cli-input.ts","../../src/headless/headless-stream-json.ts","../../src/headless/headless-runner.ts","../../src/headless/headless-transport.ts","../../src/headless/HeadlessInteractionChannel.ts"],"sourcesContent":["/**\n * ITerminalOutput implementation for print mode (-p).\n *\n * Writes to stdout/stderr directly. The readline-based prompt and select are\n * only invoked if the agent triggers a permission-gated tool, which is rare in\n * one-shot print mode but must still work correctly.\n */\n\nimport * as readline from 'node:readline';\n\nimport type { ITerminalOutput, ISpinner } from '@robota-sdk/agent-core';\n\nexport class PrintTerminal implements ITerminalOutput {\n write(text: string): void {\n process.stdout.write(text);\n }\n writeLine(text: string): void {\n process.stdout.write(text + '\\n');\n }\n writeMarkdown(md: string): void {\n process.stdout.write(md);\n }\n writeError(text: string): void {\n process.stderr.write(text + '\\n');\n }\n prompt(question: string): Promise<string> {\n return new Promise<string>((resolve) => {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n historySize: 0,\n });\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer);\n });\n });\n }\n async select(options: string[], initialIndex = 0): Promise<number> {\n for (let i = 0; i < options.length; i++) {\n const marker = i === initialIndex ? '>' : ' ';\n process.stdout.write(` ${marker} ${i + 1}) ${options[i]}\\n`);\n }\n const answer = await this.prompt(\n ` Choose [1-${options.length}] (default: ${options[initialIndex]}): `,\n );\n const trimmed = answer.trim().toLowerCase();\n if (trimmed === '') return initialIndex;\n const num = parseInt(trimmed, 10);\n if (!isNaN(num) && num >= 1 && num <= options.length) return num - 1;\n return initialIndex;\n }\n spinner(_message: string): ISpinner {\n return { stop(): void {}, update(): void {} };\n }\n}\n","const PRINTABLE_ASCII_START = 32;\n\nexport const promptInput = (label: string, masked = false): Promise<string> =>\n new Promise<string>((resolve, reject) => {\n process.stdout.write(label);\n let input = '';\n const stdin = process.stdin;\n const wasRaw = stdin.isRaw;\n if (!stdin.isTTY) {\n reject(\n new Error(\n 'Cannot prompt for input: stdin is not a TTY.\\n' +\n 'Set your API key via environment variable instead:\\n' +\n ' ANTHROPIC_API_KEY=<key> robota\\n' +\n ' OPENAI_API_KEY=<key> robota',\n ),\n );\n return;\n }\n stdin.setRawMode(true);\n stdin.resume();\n stdin.setEncoding('utf8');\n const onData = (data: string): void => {\n for (const ch of data) {\n if (ch === '\\r' || ch === '\\n') {\n stdin.removeListener('data', onData);\n stdin.setRawMode(wasRaw ?? false);\n stdin.pause();\n process.stdout.write('\\n');\n resolve(input.trim());\n return;\n } else if (ch === '\\x7f' || ch === '\\b') {\n if (input.length > 0) {\n input = input.slice(0, -1);\n process.stdout.write('\\b \\b');\n }\n } else if (ch === '\\x03') {\n stdin.removeListener('data', onData);\n stdin.setRawMode(wasRaw ?? false);\n stdin.pause();\n process.stdout.write('\\n');\n process.exit(0);\n } else if (ch.charCodeAt(0) >= PRINTABLE_ASCII_START) {\n input += ch;\n process.stdout.write(masked ? '*' : ch);\n }\n }\n };\n stdin.on('data', onData);\n });\n","import { randomUUID } from 'node:crypto';\n\nimport type {\n ICommandResult,\n IExecutionResult,\n IInteractiveSession,\n TBackgroundJobGroupEvent,\n} from '@robota-sdk/agent-interface-transport';\nimport type { TBackgroundTaskEvent } from '@robota-sdk/agent-interface-transport';\n\ntype TSlashCommandExecution =\n | { readonly kind: 'not-slash' }\n | { readonly kind: 'command-result'; readonly result: ICommandResult }\n | { readonly kind: 'session-execution' };\n\nfunction parseSlashCommand(prompt: string): { name: string; args: string } | null {\n const trimmed = prompt.trimStart();\n if (!trimmed.startsWith('/')) return null;\n const withoutSlash = trimmed.slice(1);\n const [name = '', ...args] = withoutSlash.split(/\\s+/);\n if (name.length === 0) return null;\n return { name, args: args.join(' ') };\n}\n\nexport async function executeSlashCommandIfPresent(\n session: IInteractiveSession,\n prompt: string,\n): Promise<TSlashCommandExecution> {\n const command = parseSlashCommand(prompt);\n if (!command) return { kind: 'not-slash' };\n\n const result = await session.executeCommand(command.name, command.args);\n if (result) {\n if (result.effects?.some((effect) => effect.type === 'session-execution-started')) {\n return { kind: 'session-execution' };\n }\n return { kind: 'command-result', result };\n }\n return {\n kind: 'command-result',\n result: { message: `Unknown command \"/${command.name}\".`, success: false },\n };\n}\n\ntype TStreamJsonEvent =\n | {\n type: 'content_block_delta';\n delta: { type: 'text_delta'; text: string };\n }\n | {\n type: 'background_task_event';\n background_task_event: TBackgroundTaskEvent;\n }\n | {\n type: 'background_job_group_event';\n background_job_group_event: TBackgroundJobGroupEvent;\n };\n\ninterface IStreamJsonHandlers {\n onTextDelta: (text: string) => void;\n onBackgroundTaskEvent: (event: TBackgroundTaskEvent) => void;\n onBackgroundJobGroupEvent: (event: TBackgroundJobGroupEvent) => void;\n onComplete: (result: IExecutionResult) => void;\n onInterrupted: (result: IExecutionResult) => void;\n onError: (error: Error) => void;\n}\n\nfunction writeStreamJsonEvent(\n session: IInteractiveSession,\n getSessionId: (s: IInteractiveSession) => string,\n event: TStreamJsonEvent,\n): void {\n const output = JSON.stringify({\n type: 'stream_event',\n event,\n session_id: getSessionId(session),\n uuid: randomUUID(),\n });\n process.stdout.write(output + '\\n');\n}\n\nexport function subscribeStreamJsonEvents(\n session: IInteractiveSession,\n getSessionId: (s: IInteractiveSession) => string,\n writeJsonResult: (\n sessionId: string,\n result: string,\n subtype: 'success' | 'error',\n error?: Error,\n ) => void,\n resolve: (exitCode: number) => void,\n): () => void {\n const emit = (event: TStreamJsonEvent): void =>\n writeStreamJsonEvent(session, getSessionId, event);\n\n const onTextDelta = (text: string): void =>\n emit({ type: 'content_block_delta', delta: { type: 'text_delta', text } });\n const onBackgroundTaskEvent = (event: TBackgroundTaskEvent): void =>\n emit({ type: 'background_task_event', background_task_event: event });\n const onBackgroundJobGroupEvent = (event: TBackgroundJobGroupEvent): void =>\n emit({ type: 'background_job_group_event', background_job_group_event: event });\n\n const cleanup = (): void =>\n unsubscribeStreamJsonEvents(session, {\n onTextDelta,\n onBackgroundTaskEvent,\n onBackgroundJobGroupEvent,\n onComplete,\n onInterrupted,\n onError,\n });\n\n const onComplete = (result: IExecutionResult): void => {\n cleanup();\n writeJsonResult(getSessionId(session), result.response, 'success');\n resolve(0);\n };\n const onInterrupted = (result: IExecutionResult): void => {\n cleanup();\n writeJsonResult(getSessionId(session), result.response, 'success');\n resolve(0);\n };\n const onError = (error: Error): void => {\n cleanup();\n writeJsonResult(getSessionId(session), '', 'error', error);\n resolve(1);\n };\n\n session.on('text_delta', onTextDelta);\n session.on('background_task_event', onBackgroundTaskEvent);\n session.on('background_job_group_event', onBackgroundJobGroupEvent);\n session.on('complete', onComplete);\n session.on('interrupted', onInterrupted);\n session.on('error', onError);\n return cleanup;\n}\n\nfunction unsubscribeStreamJsonEvents(\n session: IInteractiveSession,\n handlers: IStreamJsonHandlers,\n): void {\n session.off('text_delta', handlers.onTextDelta);\n session.off('background_task_event', handlers.onBackgroundTaskEvent);\n session.off('background_job_group_event', handlers.onBackgroundJobGroupEvent);\n session.off('complete', handlers.onComplete);\n session.off('interrupted', handlers.onInterrupted);\n session.off('error', handlers.onError);\n}\n","import { executeSlashCommandIfPresent, subscribeStreamJsonEvents } from './headless-stream-json.js';\n\nimport type {\n IExecutionResult,\n IGoalEvent,\n IInteractiveSession,\n} from '@robota-sdk/agent-interface-transport';\n\nexport type TOutputFormat = 'text' | 'json' | 'stream-json';\n\n/** GOAL-001: options for an autonomous headless goal run. */\nexport interface IHeadlessGoalOptions {\n maxIterations?: number;\n}\n\nexport interface IHeadlessRunnerOptions {\n session: IInteractiveSession;\n outputFormat: TOutputFormat;\n}\n\n/** Exit code for a goal that stopped cleanly without being satisfied (bound/convergence/cancel). */\nexport const GOAL_NOT_SATISFIED_EXIT_CODE = 2;\n\nexport function createHeadlessRunner(options: IHeadlessRunnerOptions): {\n run: (prompt: string) => Promise<number>;\n runGoal: (objective: string, goalOptions?: IHeadlessGoalOptions) => Promise<number>;\n} {\n const { session, outputFormat } = options;\n return {\n run: (prompt: string): Promise<number> => {\n if (outputFormat === 'text') return runTextFormat(session, prompt);\n if (outputFormat === 'json') return runJsonFormat(session, prompt);\n return runStreamJsonFormat(session, prompt);\n },\n runGoal: (objective: string, goalOptions: IHeadlessGoalOptions = {}): Promise<number> =>\n runGoalFormat(session, objective, goalOptions, outputFormat),\n };\n}\n\n/**\n * GOAL-001: drive an autonomous goal to completion in headless mode. Streams each turn's response\n * for progress, then resolves when the goal stops: exit 0 if satisfied, {@link GOAL_NOT_SATISFIED_EXIT_CODE}\n * if it stopped at a bound (max-iterations / no-progress / cancelled), or 1 on a turn error.\n */\nfunction runGoalFormat(\n session: IInteractiveSession,\n objective: string,\n goalOptions: IHeadlessGoalOptions,\n outputFormat: TOutputFormat,\n): Promise<number> {\n return new Promise<number>((resolve) => {\n const cleanup = (): void => {\n session.off('complete', onComplete);\n session.off('error', onError);\n session.off('goal_event', onGoal);\n };\n const onComplete = (result: IExecutionResult): void => {\n if (result.response) process.stdout.write(result.response + '\\n');\n };\n const onError = (error: Error): void => {\n cleanup();\n if (outputFormat === 'text') process.stderr.write(error.message + '\\n');\n else writeJsonResult(getSessionId(session), '', 'error', error);\n resolve(1);\n };\n const onGoal = (event: IGoalEvent): void => {\n if (event.type !== 'goal_stopped') return;\n cleanup();\n const goal = event.goal;\n const satisfied = goal.stopReason === 'satisfied';\n const summary = satisfied\n ? `Goal satisfied after ${goal.iterations} iteration(s).`\n : `Goal stopped: ${goal.stopReason} (after ${goal.iterations} iteration(s)).`;\n if (outputFormat === 'text')\n (satisfied ? process.stdout : process.stderr).write(summary + '\\n');\n else writeJsonResult(getSessionId(session), summary, satisfied ? 'success' : 'error');\n resolve(satisfied ? 0 : GOAL_NOT_SATISFIED_EXIT_CODE);\n };\n\n session.on('complete', onComplete);\n session.on('error', onError);\n session.on('goal_event', onGoal);\n\n void session.setGoal(\n objective,\n goalOptions.maxIterations ? { maxIterations: goalOptions.maxIterations } : {},\n );\n });\n}\n\nexport function resolveErrorCode(error: Error): string {\n const msg = error.message.toLowerCase();\n if (msg.includes('api key') || msg.includes('no provider') || msg.includes('provider')) {\n return 'config_error';\n }\n if (msg.includes('tool') || msg.includes('execution')) {\n return 'tool_error';\n }\n return 'api_error';\n}\n\nexport function writeJsonResult(\n sessionId: string,\n result: string,\n subtype: 'success' | 'error',\n error?: Error,\n): void {\n const payload: Record<string, unknown> = {\n type: 'result',\n result,\n session_id: sessionId,\n subtype,\n };\n if (subtype === 'error' && error !== undefined) {\n payload['error_code'] = resolveErrorCode(error);\n }\n const output = JSON.stringify(payload);\n process.stdout.write(output + '\\n');\n}\n\nexport function getSessionId(session: IInteractiveSession): string {\n try {\n return session.getSession().getSessionId();\n } catch {\n // allow-fallback: session may not be initialized yet\n return '';\n }\n}\n\nfunction runTextFormat(session: IInteractiveSession, prompt: string): Promise<number> {\n return new Promise<number>((resolve) => {\n const cleanup = (): void => {\n session.off('complete', onComplete);\n session.off('interrupted', onInterrupted);\n session.off('error', onError);\n };\n const onComplete = (result: IExecutionResult): void => {\n cleanup();\n process.stdout.write(result.response + '\\n');\n resolve(0);\n };\n const onInterrupted = (result: IExecutionResult): void => {\n cleanup();\n if (result.response) process.stdout.write(result.response + '\\n');\n resolve(0);\n };\n const onError = (error: Error): void => {\n cleanup();\n process.stderr.write(error.message + '\\n');\n resolve(1);\n };\n\n session.on('complete', onComplete);\n session.on('interrupted', onInterrupted);\n session.on('error', onError);\n\n void executeSlashCommandIfPresent(session, prompt).then((cmd) => {\n if (cmd.kind === 'command-result') {\n cleanup();\n process.stdout.write(cmd.result.message + '\\n');\n resolve(cmd.result.success ? 0 : 1);\n return;\n }\n if (cmd.kind !== 'session-execution') void session.submit(prompt);\n });\n });\n}\n\nfunction runJsonFormat(session: IInteractiveSession, prompt: string): Promise<number> {\n return new Promise<number>((resolve) => {\n const cleanup = (): void => {\n session.off('complete', onComplete);\n session.off('interrupted', onInterrupted);\n session.off('error', onError);\n };\n const onComplete = (result: IExecutionResult): void => {\n cleanup();\n writeJsonResult(getSessionId(session), result.response, 'success');\n resolve(0);\n };\n const onInterrupted = (result: IExecutionResult): void => {\n cleanup();\n writeJsonResult(getSessionId(session), result.response, 'success');\n resolve(0);\n };\n const onError = (error: Error): void => {\n cleanup();\n writeJsonResult(getSessionId(session), '', 'error', error);\n resolve(1);\n };\n\n session.on('complete', onComplete);\n session.on('interrupted', onInterrupted);\n session.on('error', onError);\n\n void executeSlashCommandIfPresent(session, prompt).then((cmd) => {\n if (cmd.kind === 'command-result') {\n cleanup();\n writeJsonResult(\n getSessionId(session),\n cmd.result.message,\n cmd.result.success ? 'success' : 'error',\n );\n resolve(cmd.result.success ? 0 : 1);\n return;\n }\n if (cmd.kind !== 'session-execution') void session.submit(prompt);\n });\n });\n}\n\nfunction runStreamJsonFormat(session: IInteractiveSession, prompt: string): Promise<number> {\n return new Promise<number>((resolve) => {\n const cleanup = subscribeStreamJsonEvents(session, getSessionId, writeJsonResult, resolve);\n\n void executeSlashCommandIfPresent(session, prompt).then((cmd) => {\n if (cmd.kind === 'command-result') {\n cleanup();\n writeJsonResult(\n getSessionId(session),\n cmd.result.message,\n cmd.result.success ? 'success' : 'error',\n );\n resolve(cmd.result.success ? 0 : 1);\n return;\n }\n if (cmd.kind !== 'session-execution') void session.submit(prompt);\n });\n });\n}\n","/**\n * ITransportAdapter implementation for headless transport.\n *\n * Wraps createHeadlessRunner into the unified ITransportAdapter interface.\n * After start() completes, getExitCode() returns the runner's exit code.\n */\n\nimport { createHeadlessRunner } from './headless-runner.js';\n\nimport type { TOutputFormat } from './headless-runner.js';\nimport type { IInteractiveSession, ITransportAdapter } from '@robota-sdk/agent-interface-transport';\n\nexport interface IHeadlessTransportOptions {\n /** Output format: 'text', 'json', or 'stream-json'. */\n outputFormat: TOutputFormat;\n /** The prompt to execute. */\n prompt: string;\n}\n\nexport function createHeadlessTransport(\n options: IHeadlessTransportOptions,\n): ITransportAdapter<IInteractiveSession> & { getExitCode(): number } {\n let session: IInteractiveSession | null = null;\n let exitCode = 0;\n\n return {\n name: 'headless',\n attach(s: IInteractiveSession) {\n session = s;\n },\n async start() {\n if (!session) throw new Error('No session attached. Call attach() first.');\n const runner = createHeadlessRunner({ session, outputFormat: options.outputFormat });\n exitCode = await runner.run(options.prompt);\n },\n async stop() {\n /* no-op: headless runner completes in start() */\n },\n getExitCode() {\n return exitCode;\n },\n };\n}\n","/**\n * HeadlessInteractionChannel — owns session lifecycle for non-interactive (print) mode.\n *\n * Mirrors TuiInteractionChannel's ownership pattern: session creation lives here,\n * not in the caller. print-mode.ts constructs this and calls run().\n */\n\nimport { execSync } from 'node:child_process';\n\nimport { InteractiveSession } from '@robota-sdk/agent-framework';\n\nimport { createHeadlessRunner, type TOutputFormat } from './headless-runner.js';\n\nimport type { IAIProvider, TPermissionMode } from '@robota-sdk/agent-core';\nimport type {\n IBackgroundTaskRunner,\n ICommandHostAdapters,\n ICommandModule,\n TSubagentRunnerFactory,\n TShellExecFn,\n} from '@robota-sdk/agent-framework';\nimport type { IInteractiveSessionStore } from '@robota-sdk/agent-interface-transport';\n\nexport interface IHeadlessInteractionChannelOptions {\n cwd: string;\n provider: IAIProvider;\n outputFormat: TOutputFormat;\n permissionMode?: TPermissionMode;\n maxTurns?: number;\n sessionStore?: IInteractiveSessionStore;\n /** Continue/resume an existing session by id (print-mode parity with TUI). */\n resumeSessionId?: string;\n /** Fork the resumed session into a new independent session instead of appending. */\n forkSession?: boolean;\n sessionName?: string;\n bare?: boolean;\n allowedTools?: string[];\n deniedTools?: string[];\n appendSystemPrompt?: string;\n systemPrompt?: string;\n /** Name reported to the underlying agent config (resolved by the CLI, e.g. preset agentName). */\n agentName?: string;\n /** Active preset id selected at startup (PRESET-011 runtime state). Defaults to 'default'. */\n activePresetId?: string;\n /** Preset persona block composed as a `source: 'persona'` system-prompt section (priority 5). */\n persona?: string;\n /** Preset execution capability: activate agent runtime + subagent/background dispatch. */\n enableParallelSubagents?: boolean;\n /** Preset execution capability: run a post-task self-verification step. */\n selfVerification?: boolean;\n backgroundTaskRunners?: IBackgroundTaskRunner[];\n subagentRunnerFactory?: TSubagentRunnerFactory;\n commandModules?: readonly ICommandModule[];\n commandHostAdapters?: ICommandHostAdapters;\n shellExec?: TShellExecFn;\n}\n\nexport class HeadlessInteractionChannel {\n private readonly opts: IHeadlessInteractionChannelOptions;\n private exitCode = 0;\n\n constructor(options: IHeadlessInteractionChannelOptions) {\n this.opts = options;\n }\n\n async run(prompt: string): Promise<void> {\n const session = this.createSession();\n const runner = createHeadlessRunner({ session, outputFormat: this.opts.outputFormat });\n this.exitCode = await runner.run(prompt);\n await session.shutdown({ reason: 'prompt_input_exit', message: 'Headless transport complete' });\n }\n\n /**\n * GOAL-001: run an autonomous goal to completion (or a stop condition) in headless mode.\n * Mirrors {@link run} but drives the framework goal loop instead of a single prompt.\n */\n async runGoal(objective: string, options: { maxIterations?: number } = {}): Promise<void> {\n const session = this.createSession();\n const runner = createHeadlessRunner({ session, outputFormat: this.opts.outputFormat });\n this.exitCode = await runner.runGoal(objective, options);\n await session.shutdown({ reason: 'prompt_input_exit', message: 'Headless goal complete' });\n }\n\n private createSession(): InteractiveSession {\n const shellExec: TShellExecFn =\n this.opts.shellExec ??\n ((command: string) =>\n execSync(command, { timeout: 5000, encoding: 'utf-8', stdio: 'pipe' }).trimEnd());\n\n return new InteractiveSession({\n cwd: this.opts.cwd,\n provider: this.opts.provider,\n permissionMode: this.opts.permissionMode ?? 'bypassPermissions',\n // CMD-004: headless has no interactive renderer, so it injects no askHandler — the session's\n // getUserInteraction() returns undefined and each command applies its explicit no-human path\n // (e.g. /mode reports current, /exit and /clear proceed — never a silent guess).\n maxTurns: this.opts.maxTurns,\n sessionStore: this.opts.sessionStore,\n resumeSessionId: this.opts.resumeSessionId,\n forkSession: this.opts.forkSession,\n sessionName: this.opts.sessionName,\n bare: this.opts.bare || undefined,\n allowedTools: this.opts.allowedTools,\n deniedTools: this.opts.deniedTools,\n appendSystemPrompt: this.opts.appendSystemPrompt,\n ...(this.opts.persona !== undefined ? { persona: this.opts.persona } : {}),\n ...(this.opts.systemPrompt ? { systemPrompt: this.opts.systemPrompt } : {}),\n backgroundTaskRunners: this.opts.backgroundTaskRunners,\n subagentRunnerFactory: this.opts.subagentRunnerFactory,\n commandModules: this.opts.commandModules,\n commandHostAdapters: this.opts.commandHostAdapters,\n shellExec,\n agentName: this.opts.agentName,\n ...(this.opts.activePresetId !== undefined\n ? { activePresetId: this.opts.activePresetId }\n : {}),\n ...(this.opts.enableParallelSubagents !== undefined\n ? { enableParallelSubagents: this.opts.enableParallelSubagents }\n : {}),\n ...(this.opts.selfVerification !== undefined\n ? { selfVerification: this.opts.selfVerification }\n : {}),\n });\n }\n\n getExitCode(): number {\n return this.exitCode;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require("node:readline");c=s(c,1);let l=require("node:crypto"),u=require("node:child_process"),d=require("@robota-sdk/agent-framework");var f=class{write(e){process.stdout.write(e)}writeLine(e){process.stdout.write(e+`
|
|
2
|
-
`)}writeMarkdown(e){process.stdout.write(e)}writeError(e){process.stderr.write(e+`
|
|
3
|
-
`)}prompt(e){return new Promise(t=>{let n=c.createInterface({input:process.stdin,output:process.stdout,terminal:!1,historySize:0});n.question(e,e=>{n.close(),t(e)})})}async select(e,t=0){for(let n=0;n<e.length;n++){let r=n===t?`>`:` `;process.stdout.write(` ${r} ${n+1}) ${e[n]}\n`)}let n=(await this.prompt(` Choose [1-${e.length}] (default: ${e[t]}): `)).trim().toLowerCase();if(n===``)return t;let r=parseInt(n,10);return!isNaN(r)&&r>=1&&r<=e.length?r-1:t}spinner(e){return{stop(){},update(){}}}};const p=(e,t=!1)=>new Promise((n,r)=>{process.stdout.write(e);let i=``,a=process.stdin,o=a.isRaw;if(!a.isTTY){r(Error(`Cannot prompt for input: stdin is not a TTY.
|
|
4
|
-
Set your API key via environment variable instead:
|
|
5
|
-
ANTHROPIC_API_KEY=<key> robota
|
|
6
|
-
OPENAI_API_KEY=<key> robota`));return}a.setRawMode(!0),a.resume(),a.setEncoding(`utf8`);let s=e=>{for(let r of e)if(r===`\r`||r===`
|
|
7
|
-
`){a.removeListener(`data`,s),a.setRawMode(o??!1),a.pause(),process.stdout.write(`
|
|
8
|
-
`),n(i.trim());return}else r===``||r===`\b`?i.length>0&&(i=i.slice(0,-1),process.stdout.write(`\b \b`)):r===``?(a.removeListener(`data`,s),a.setRawMode(o??!1),a.pause(),process.stdout.write(`
|
|
9
|
-
`),process.exit(0)):r.charCodeAt(0)>=32&&(i+=r,process.stdout.write(t?`*`:r))};a.on(`data`,s)});function m(e){let t=e.trimStart();if(!t.startsWith(`/`))return null;let[n=``,...r]=t.slice(1).split(/\s+/);return n.length===0?null:{name:n,args:r.join(` `)}}async function h(e,t){let n=m(t);if(!n)return{kind:`not-slash`};let r=await e.executeCommand(n.name,n.args);return r?r.effects?.some(e=>e.type===`session-execution-started`)?{kind:`session-execution`}:{kind:`command-result`,result:r}:{kind:`command-result`,result:{message:`Unknown command "/${n.name}".`,success:!1}}}function g(e,t,n){let r=JSON.stringify({type:`stream_event`,event:n,session_id:t(e),uuid:(0,l.randomUUID)()});process.stdout.write(r+`
|
|
10
|
-
`)}function _(e,t,n,r){let i=n=>g(e,t,n),a=e=>i({type:`content_block_delta`,delta:{type:`text_delta`,text:e}}),o=e=>i({type:`background_task_event`,background_task_event:e}),s=e=>i({type:`background_job_group_event`,background_job_group_event:e}),c=()=>v(e,{onTextDelta:a,onBackgroundTaskEvent:o,onBackgroundJobGroupEvent:s,onComplete:l,onInterrupted:u,onError:d}),l=i=>{c(),n(t(e),i.response,`success`),r(0)},u=i=>{c(),n(t(e),i.response,`success`),r(0)},d=i=>{c(),n(t(e),``,`error`,i),r(1)};return e.on(`text_delta`,a),e.on(`background_task_event`,o),e.on(`background_job_group_event`,s),e.on(`complete`,l),e.on(`interrupted`,u),e.on(`error`,d),c}function v(e,t){e.off(`text_delta`,t.onTextDelta),e.off(`background_task_event`,t.onBackgroundTaskEvent),e.off(`background_job_group_event`,t.onBackgroundJobGroupEvent),e.off(`complete`,t.onComplete),e.off(`interrupted`,t.onInterrupted),e.off(`error`,t.onError)}function y(e){let{session:t,outputFormat:n}=e;return{run:e=>n===`text`?w(t,e):n===`json`?T(t,e):E(t,e),runGoal:(e,r={})=>b(t,e,r,n)}}function b(e,t,n,r){return new Promise(i=>{let a=()=>{e.off(`complete`,o),e.off(`error`,s),e.off(`goal_event`,c)},o=e=>{e.response&&process.stdout.write(e.response+`
|
|
11
|
-
`)},s=t=>{a(),r===`text`?process.stderr.write(t.message+`
|
|
12
|
-
`):S(C(e),``,`error`,t),i(1)},c=t=>{if(t.type!==`goal_stopped`)return;a();let n=t.goal,o=n.stopReason===`satisfied`,s=o?`Goal satisfied after ${n.iterations} iteration(s).`:`Goal stopped: ${n.stopReason} (after ${n.iterations} iteration(s)).`;r===`text`?(o?process.stdout:process.stderr).write(s+`
|
|
13
|
-
`):S(C(e),s,o?`success`:`error`),i(o?0:2)};e.on(`complete`,o),e.on(`error`,s),e.on(`goal_event`,c),e.setGoal(t,n.maxIterations?{maxIterations:n.maxIterations}:{})})}function x(e){let t=e.message.toLowerCase();return t.includes(`api key`)||t.includes(`no provider`)||t.includes(`provider`)?`config_error`:t.includes(`tool`)||t.includes(`execution`)?`tool_error`:`api_error`}function S(e,t,n,r){let i={type:`result`,result:t,session_id:e,subtype:n};n===`error`&&r!==void 0&&(i.error_code=x(r));let a=JSON.stringify(i);process.stdout.write(a+`
|
|
14
|
-
`)}function C(e){try{return e.getSession().getSessionId()}catch{return``}}function w(e,t){return new Promise(n=>{let r=()=>{e.off(`complete`,i),e.off(`interrupted`,a),e.off(`error`,o)},i=e=>{r(),process.stdout.write(e.response+`
|
|
15
|
-
`),n(0)},a=e=>{r(),e.response&&process.stdout.write(e.response+`
|
|
16
|
-
`),n(0)},o=e=>{r(),process.stderr.write(e.message+`
|
|
17
|
-
`),n(1)};e.on(`complete`,i),e.on(`interrupted`,a),e.on(`error`,o),h(e,t).then(i=>{if(i.kind===`command-result`){r(),process.stdout.write(i.result.message+`
|
|
18
|
-
`),n(+!i.result.success);return}i.kind!==`session-execution`&&e.submit(t)})})}function T(e,t){return new Promise(n=>{let r=()=>{e.off(`complete`,i),e.off(`interrupted`,a),e.off(`error`,o)},i=t=>{r(),S(C(e),t.response,`success`),n(0)},a=t=>{r(),S(C(e),t.response,`success`),n(0)},o=t=>{r(),S(C(e),``,`error`,t),n(1)};e.on(`complete`,i),e.on(`interrupted`,a),e.on(`error`,o),h(e,t).then(i=>{if(i.kind===`command-result`){r(),S(C(e),i.result.message,i.result.success?`success`:`error`),n(+!i.result.success);return}i.kind!==`session-execution`&&e.submit(t)})})}function E(e,t){return new Promise(n=>{let r=_(e,C,S,n);h(e,t).then(i=>{if(i.kind===`command-result`){r(),S(C(e),i.result.message,i.result.success?`success`:`error`),n(+!i.result.success);return}i.kind!==`session-execution`&&e.submit(t)})})}function D(e){let t=null,n=0;return{name:`headless`,attach(e){t=e},async start(){if(!t)throw Error(`No session attached. Call attach() first.`);n=await y({session:t,outputFormat:e.outputFormat}).run(e.prompt)},async stop(){},getExitCode(){return n}}}var O=class{opts;exitCode=0;constructor(e){this.opts=e}async run(e){let t=this.createSession(),n=y({session:t,outputFormat:this.opts.outputFormat});this.exitCode=await n.run(e),await t.shutdown({reason:`prompt_input_exit`,message:`Headless transport complete`})}async runGoal(e,t={}){let n=this.createSession(),r=y({session:n,outputFormat:this.opts.outputFormat});this.exitCode=await r.runGoal(e,t),await n.shutdown({reason:`prompt_input_exit`,message:`Headless goal complete`})}createSession(){let e=this.opts.shellExec??(e=>(0,u.execSync)(e,{timeout:5e3,encoding:`utf-8`,stdio:`pipe`}).trimEnd());return new d.InteractiveSession({cwd:this.opts.cwd,provider:this.opts.provider,permissionMode:this.opts.permissionMode??`bypassPermissions`,maxTurns:this.opts.maxTurns,sessionStore:this.opts.sessionStore,resumeSessionId:this.opts.resumeSessionId,forkSession:this.opts.forkSession,sessionName:this.opts.sessionName,bare:this.opts.bare||void 0,allowedTools:this.opts.allowedTools,deniedTools:this.opts.deniedTools,appendSystemPrompt:this.opts.appendSystemPrompt,...this.opts.persona===void 0?{}:{persona:this.opts.persona},...this.opts.systemPrompt?{systemPrompt:this.opts.systemPrompt}:{},backgroundTaskRunners:this.opts.backgroundTaskRunners,subagentRunnerFactory:this.opts.subagentRunnerFactory,commandModules:this.opts.commandModules,commandHostAdapters:this.opts.commandHostAdapters,shellExec:e,agentName:this.opts.agentName,...this.opts.activePresetId===void 0?{}:{activePresetId:this.opts.activePresetId},...this.opts.enableParallelSubagents===void 0?{}:{enableParallelSubagents:this.opts.enableParallelSubagents},...this.opts.selfVerification===void 0?{}:{selfVerification:this.opts.selfVerification}})}getExitCode(){return this.exitCode}};Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return O}});
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { IBackgroundTaskRunner, ICommandHostAdapters, ICommandModule, TShellExecFn, TSubagentRunnerFactory } from "@robota-sdk/agent-framework";
|
|
2
|
-
import { IInteractiveSession, IInteractiveSessionStore, ITransportAdapter } from "@robota-sdk/agent-interface-transport";
|
|
3
|
-
import { IAIProvider, ISpinner, ITerminalOutput, TPermissionMode } from "@robota-sdk/agent-core";
|
|
4
|
-
|
|
5
|
-
//#region src/headless/print-terminal.d.ts
|
|
6
|
-
declare class PrintTerminal implements ITerminalOutput {
|
|
7
|
-
write(text: string): void;
|
|
8
|
-
writeLine(text: string): void;
|
|
9
|
-
writeMarkdown(md: string): void;
|
|
10
|
-
writeError(text: string): void;
|
|
11
|
-
prompt(question: string): Promise<string>;
|
|
12
|
-
select(options: string[], initialIndex?: number): Promise<number>;
|
|
13
|
-
spinner(_message: string): ISpinner;
|
|
14
|
-
}
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region src/headless/cli-input.d.ts
|
|
17
|
-
declare const promptInput: (label: string, masked?: boolean) => Promise<string>;
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region src/headless/headless-runner.d.ts
|
|
20
|
-
type TOutputFormat = 'text' | 'json' | 'stream-json';
|
|
21
|
-
/** GOAL-001: options for an autonomous headless goal run. */
|
|
22
|
-
interface IHeadlessGoalOptions {
|
|
23
|
-
maxIterations?: number;
|
|
24
|
-
}
|
|
25
|
-
interface IHeadlessRunnerOptions {
|
|
26
|
-
session: IInteractiveSession;
|
|
27
|
-
outputFormat: TOutputFormat;
|
|
28
|
-
}
|
|
29
|
-
declare function createHeadlessRunner(options: IHeadlessRunnerOptions): {
|
|
30
|
-
run: (prompt: string) => Promise<number>;
|
|
31
|
-
runGoal: (objective: string, goalOptions?: IHeadlessGoalOptions) => Promise<number>;
|
|
32
|
-
};
|
|
33
|
-
//#endregion
|
|
34
|
-
//#region src/headless/headless-transport.d.ts
|
|
35
|
-
interface IHeadlessTransportOptions {
|
|
36
|
-
/** Output format: 'text', 'json', or 'stream-json'. */
|
|
37
|
-
outputFormat: TOutputFormat;
|
|
38
|
-
/** The prompt to execute. */
|
|
39
|
-
prompt: string;
|
|
40
|
-
}
|
|
41
|
-
declare function createHeadlessTransport(options: IHeadlessTransportOptions): ITransportAdapter<IInteractiveSession> & {
|
|
42
|
-
getExitCode(): number;
|
|
43
|
-
};
|
|
44
|
-
//#endregion
|
|
45
|
-
//#region src/headless/HeadlessInteractionChannel.d.ts
|
|
46
|
-
interface IHeadlessInteractionChannelOptions {
|
|
47
|
-
cwd: string;
|
|
48
|
-
provider: IAIProvider;
|
|
49
|
-
outputFormat: TOutputFormat;
|
|
50
|
-
permissionMode?: TPermissionMode;
|
|
51
|
-
maxTurns?: number;
|
|
52
|
-
sessionStore?: IInteractiveSessionStore;
|
|
53
|
-
/** Continue/resume an existing session by id (print-mode parity with TUI). */
|
|
54
|
-
resumeSessionId?: string;
|
|
55
|
-
/** Fork the resumed session into a new independent session instead of appending. */
|
|
56
|
-
forkSession?: boolean;
|
|
57
|
-
sessionName?: string;
|
|
58
|
-
bare?: boolean;
|
|
59
|
-
allowedTools?: string[];
|
|
60
|
-
deniedTools?: string[];
|
|
61
|
-
appendSystemPrompt?: string;
|
|
62
|
-
systemPrompt?: string;
|
|
63
|
-
/** Name reported to the underlying agent config (resolved by the CLI, e.g. preset agentName). */
|
|
64
|
-
agentName?: string;
|
|
65
|
-
/** Active preset id selected at startup (PRESET-011 runtime state). Defaults to 'default'. */
|
|
66
|
-
activePresetId?: string;
|
|
67
|
-
/** Preset persona block composed as a `source: 'persona'` system-prompt section (priority 5). */
|
|
68
|
-
persona?: string;
|
|
69
|
-
/** Preset execution capability: activate agent runtime + subagent/background dispatch. */
|
|
70
|
-
enableParallelSubagents?: boolean;
|
|
71
|
-
/** Preset execution capability: run a post-task self-verification step. */
|
|
72
|
-
selfVerification?: boolean;
|
|
73
|
-
backgroundTaskRunners?: IBackgroundTaskRunner[];
|
|
74
|
-
subagentRunnerFactory?: TSubagentRunnerFactory;
|
|
75
|
-
commandModules?: readonly ICommandModule[];
|
|
76
|
-
commandHostAdapters?: ICommandHostAdapters;
|
|
77
|
-
shellExec?: TShellExecFn;
|
|
78
|
-
}
|
|
79
|
-
declare class HeadlessInteractionChannel {
|
|
80
|
-
private readonly opts;
|
|
81
|
-
private exitCode;
|
|
82
|
-
constructor(options: IHeadlessInteractionChannelOptions);
|
|
83
|
-
run(prompt: string): Promise<void>;
|
|
84
|
-
/**
|
|
85
|
-
* GOAL-001: run an autonomous goal to completion (or a stop condition) in headless mode.
|
|
86
|
-
* Mirrors {@link run} but drives the framework goal loop instead of a single prompt.
|
|
87
|
-
*/
|
|
88
|
-
runGoal(objective: string, options?: {
|
|
89
|
-
maxIterations?: number;
|
|
90
|
-
}): Promise<void>;
|
|
91
|
-
private createSession;
|
|
92
|
-
getExitCode(): number;
|
|
93
|
-
}
|
|
94
|
-
//#endregion
|
|
95
|
-
export { IHeadlessRunnerOptions as a, promptInput as c, createHeadlessTransport as i, PrintTerminal as l, IHeadlessInteractionChannelOptions as n, TOutputFormat as o, IHeadlessTransportOptions as r, createHeadlessRunner as s, HeadlessInteractionChannel as t };
|
|
96
|
-
//# sourceMappingURL=index-CrJ2Lhn3.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-CrJ2Lhn3.d.ts","names":[],"sources":["../../src/headless/print-terminal.ts","../../src/headless/cli-input.ts","../../src/headless/headless-runner.ts","../../src/headless/headless-transport.ts","../../src/headless/HeadlessInteractionChannel.ts"],"mappings":";;;;;cAYa,aAAA,YAAyB,eAAA;EACpC,KAAA,CAAM,IAAA;EAGN,SAAA,CAAU,IAAA;EAGV,aAAA,CAAc,EAAA;EAGd,UAAA,CAAW,IAAA;EAGX,MAAA,CAAO,QAAA,WAAmB,OAAA;EAcpB,MAAA,CAAO,OAAA,YAAmB,YAAA,YAAmB,OAAA;EAcnD,OAAA,CAAQ,QAAA,WAAmB,QAAA;AAAA;;;cCnDhB,WAAA,GAAe,KAAA,UAAe,MAAA,eAAiB,OAAO;;;KCMvD,aAAA;;UAGK,oBAAA;EACf,aAAa;AAAA;AAAA,UAGE,sBAAA;EACf,OAAA,EAAS,mBAAA;EACT,YAAA,EAAc,aAAa;AAAA;AAAA,iBAMb,oBAAA,CAAqB,OAAA,EAAS,sBAAA;EAC5C,GAAA,GAAM,MAAA,aAAmB,OAAA;EACzB,OAAA,GAAU,SAAA,UAAmB,WAAA,GAAc,oBAAA,KAAyB,OAAA;AAAA;;;UCbrD,yBAAA;EH2BoC;EGzBnD,YAAA,EAAc,aAAa;EHFS;EGIpC,MAAA;AAAA;AAAA,iBAGc,uBAAA,CACd,OAAA,EAAS,yBAAA,GACR,iBAAA,CAAkB,mBAAA;EAAyB,WAAA;AAAA;;;UCE7B,kCAAA;EACf,GAAA;EACA,QAAA,EAAU,WAAA;EACV,YAAA,EAAc,aAAA;EACd,cAAA,GAAiB,eAAA;EACjB,QAAA;EACA,YAAA,GAAe,wBAAA;EJbf;EIeA,eAAA;EJZA;EIcA,WAAA;EACA,WAAA;EACA,IAAA;EACA,YAAA;EACA,WAAA;EACA,kBAAA;EACA,YAAA;EJAa;EIEb,SAAA;EJFmD;EIInD,cAAA;EJUQ;EIRR,OAAA;EJQmC;EINnC,uBAAA;;EAEA,gBAAA;EACA,qBAAA,GAAwB,qBAAA;EACxB,qBAAA,GAAwB,sBAAA;EACxB,cAAA,YAA0B,cAAA;EAC1B,mBAAA,GAAsB,oBAAA;EACtB,SAAA,GAAY,YAAA;AAAA;AAAA,cAGD,0BAAA;EAAA,iBACM,IAAA;EAAA,QACT,QAAA;cAEI,OAAA,EAAS,kCAAA;EAIf,GAAA,CAAI,MAAA,WAAiB,OAAA;;;AFzD7B;;EEoEQ,OAAA,CAAQ,SAAA,UAAmB,OAAA;IAAW,aAAA;EAAA,IAAgC,OAAA;EAAA,QAOpE,aAAA;EA0CR,WAAA;AAAA"}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { ICommandModule } from "@robota-sdk/agent-framework";
|
|
2
|
-
import { IAgentDriver, ICommandInfo, IInteractionChannel, IInteractiveSessionStore, InteractionEvent } from "@robota-sdk/agent-interface-transport";
|
|
3
|
-
import { IAIProvider, IActionRequest, TActionResponse, TPermissionMode } from "@robota-sdk/agent-core";
|
|
4
|
-
|
|
5
|
-
//#region src/programmatic/ProgrammaticInteractionChannel.d.ts
|
|
6
|
-
declare class ProgrammaticInteractionChannel implements IInteractionChannel {
|
|
7
|
-
/** Full structured event stream pushed by the framework, in order. */
|
|
8
|
-
readonly events: InteractionEvent[];
|
|
9
|
-
availableCommands: ICommandInfo[];
|
|
10
|
-
busy: boolean;
|
|
11
|
-
started: boolean;
|
|
12
|
-
stopped: boolean;
|
|
13
|
-
private submitHandler;
|
|
14
|
-
private readonly userActionResponses;
|
|
15
|
-
onSubmit(handler: (text: string) => Promise<void>): void;
|
|
16
|
-
write(event: InteractionEvent): void;
|
|
17
|
-
/**
|
|
18
|
-
* CMD-004 unified ask. Resolves from the pre-supplied queue (FIFO); an empty queue resolves
|
|
19
|
-
* `{ type: 'cancelled' }` so a programmatic run never blocks on an un-answered question.
|
|
20
|
-
*/
|
|
21
|
-
askUser(_request: IActionRequest): Promise<TActionResponse>;
|
|
22
|
-
setAvailableCommands(commands: ICommandInfo[]): void;
|
|
23
|
-
setBusy(busy: boolean): void;
|
|
24
|
-
start(): Promise<void>;
|
|
25
|
-
stop(): Promise<void>;
|
|
26
|
-
/** Push a user submission into the framework (the programmatic "user types and presses enter"). */
|
|
27
|
-
submit(text: string): Promise<void>;
|
|
28
|
-
/** Pre-answer the next `askUser` (CMD-004 unified ask). */
|
|
29
|
-
queueUserAction(response: TActionResponse): void;
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
//#region src/programmatic/createProgrammaticAgent.d.ts
|
|
33
|
-
interface ICreateProgrammaticAgentOptions {
|
|
34
|
-
/** Provider that answers the agent loop (e.g. a real provider, or the scripted provider in tests). */
|
|
35
|
-
provider: IAIProvider;
|
|
36
|
-
/** Working directory for session creation. */
|
|
37
|
-
cwd: string;
|
|
38
|
-
/** Slash-command modules to register (defaults to none). */
|
|
39
|
-
commandModules?: readonly ICommandModule[];
|
|
40
|
-
/** Optional session store for persistence. */
|
|
41
|
-
sessionStore?: IInteractiveSessionStore;
|
|
42
|
-
/** Permission mode for tool execution (e.g. `'bypassPermissions'` for unattended driving). */
|
|
43
|
-
permissionMode?: TPermissionMode;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Construct an in-process {@link IAgentDriver} bound to a real `InteractiveSession`. The returned
|
|
47
|
-
* driver's accessors are the shared `read*` helpers applied to the captured event stream.
|
|
48
|
-
*/
|
|
49
|
-
declare function createProgrammaticAgent(options: ICreateProgrammaticAgentOptions): IAgentDriver;
|
|
50
|
-
//#endregion
|
|
51
|
-
export { createProgrammaticAgent as n, ProgrammaticInteractionChannel as r, ICreateProgrammaticAgentOptions as t };
|
|
52
|
-
//# sourceMappingURL=index-JIvzrtaA.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-JIvzrtaA.d.ts","names":[],"sources":["../../src/programmatic/ProgrammaticInteractionChannel.ts","../../src/programmatic/createProgrammaticAgent.ts"],"mappings":";;;;;cAmBa,8BAAA,YAA0C,mBAAA;EA0BZ;EAAA,SAxBhC,MAAA,EAAQ,gBAAA;EAEjB,iBAAA,EAAmB,YAAA;EACnB,IAAA;EACA,OAAA;EACA,OAAA;EAAA,QAEQ,aAAA;EAAA,iBACS,mBAAA;EAIjB,QAAA,CAAS,OAAA,GAAU,IAAA,aAAiB,OAAA;EAIpC,KAAA,CAAM,KAAA,EAAO,gBAAA;EAhBJ;;;;EAwBH,OAAA,CAAQ,QAAA,EAAU,cAAA,GAAiB,OAAA,CAAQ,eAAA;EAIjD,oBAAA,CAAqB,QAAA,EAAU,YAAA;EAI/B,OAAA,CAAQ,IAAA;EAIF,KAAA,IAAS,OAAA;EAIT,IAAA,IAAQ,OAAA;EA5Bd;EAmCM,MAAA,CAAO,IAAA,WAAe,OAAA;EAnCQ;EA6CpC,eAAA,CAAgB,QAAA,EAAU,eAAA;AAAA;;;UCrDX,+BAAA;EDoB0B;EClBzC,QAAA,EAAU,WAAA;ED8BK;EC5Bf,GAAA;EDuC4B;ECrC5B,cAAA,YAA0B,cAAA;EDZ2B;ECcrD,YAAA,GAAe,wBAAA;EDdyD;ECgBxE,cAAA,GAAiB,eAAA;AAAA;;;;;iBAOH,uBAAA,CAAwB,OAAA,EAAS,+BAAA,GAAkC,YAAY"}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { IAIProvider, ISpinner, ITerminalOutput, TPermissionMode } from "@robota-sdk/agent-core";
|
|
2
|
-
import { IInteractiveSession, IInteractiveSessionStore, ITransportAdapter } from "@robota-sdk/agent-interface-transport";
|
|
3
|
-
import { IBackgroundTaskRunner, ICommandHostAdapters, ICommandModule, TShellExecFn, TSubagentRunnerFactory } from "@robota-sdk/agent-framework";
|
|
4
|
-
|
|
5
|
-
//#region src/headless/print-terminal.d.ts
|
|
6
|
-
declare class PrintTerminal implements ITerminalOutput {
|
|
7
|
-
write(text: string): void;
|
|
8
|
-
writeLine(text: string): void;
|
|
9
|
-
writeMarkdown(md: string): void;
|
|
10
|
-
writeError(text: string): void;
|
|
11
|
-
prompt(question: string): Promise<string>;
|
|
12
|
-
select(options: string[], initialIndex?: number): Promise<number>;
|
|
13
|
-
spinner(_message: string): ISpinner;
|
|
14
|
-
}
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region src/headless/cli-input.d.ts
|
|
17
|
-
declare const promptInput: (label: string, masked?: boolean) => Promise<string>;
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region src/headless/headless-runner.d.ts
|
|
20
|
-
type TOutputFormat = 'text' | 'json' | 'stream-json';
|
|
21
|
-
/** GOAL-001: options for an autonomous headless goal run. */
|
|
22
|
-
interface IHeadlessGoalOptions {
|
|
23
|
-
maxIterations?: number;
|
|
24
|
-
}
|
|
25
|
-
interface IHeadlessRunnerOptions {
|
|
26
|
-
session: IInteractiveSession;
|
|
27
|
-
outputFormat: TOutputFormat;
|
|
28
|
-
}
|
|
29
|
-
declare function createHeadlessRunner(options: IHeadlessRunnerOptions): {
|
|
30
|
-
run: (prompt: string) => Promise<number>;
|
|
31
|
-
runGoal: (objective: string, goalOptions?: IHeadlessGoalOptions) => Promise<number>;
|
|
32
|
-
};
|
|
33
|
-
//#endregion
|
|
34
|
-
//#region src/headless/headless-transport.d.ts
|
|
35
|
-
interface IHeadlessTransportOptions {
|
|
36
|
-
/** Output format: 'text', 'json', or 'stream-json'. */
|
|
37
|
-
outputFormat: TOutputFormat;
|
|
38
|
-
/** The prompt to execute. */
|
|
39
|
-
prompt: string;
|
|
40
|
-
}
|
|
41
|
-
declare function createHeadlessTransport(options: IHeadlessTransportOptions): ITransportAdapter<IInteractiveSession> & {
|
|
42
|
-
getExitCode(): number;
|
|
43
|
-
};
|
|
44
|
-
//#endregion
|
|
45
|
-
//#region src/headless/HeadlessInteractionChannel.d.ts
|
|
46
|
-
interface IHeadlessInteractionChannelOptions {
|
|
47
|
-
cwd: string;
|
|
48
|
-
provider: IAIProvider;
|
|
49
|
-
outputFormat: TOutputFormat;
|
|
50
|
-
permissionMode?: TPermissionMode;
|
|
51
|
-
maxTurns?: number;
|
|
52
|
-
sessionStore?: IInteractiveSessionStore;
|
|
53
|
-
/** Continue/resume an existing session by id (print-mode parity with TUI). */
|
|
54
|
-
resumeSessionId?: string;
|
|
55
|
-
/** Fork the resumed session into a new independent session instead of appending. */
|
|
56
|
-
forkSession?: boolean;
|
|
57
|
-
sessionName?: string;
|
|
58
|
-
bare?: boolean;
|
|
59
|
-
allowedTools?: string[];
|
|
60
|
-
deniedTools?: string[];
|
|
61
|
-
appendSystemPrompt?: string;
|
|
62
|
-
systemPrompt?: string;
|
|
63
|
-
/** Name reported to the underlying agent config (resolved by the CLI, e.g. preset agentName). */
|
|
64
|
-
agentName?: string;
|
|
65
|
-
/** Active preset id selected at startup (PRESET-011 runtime state). Defaults to 'default'. */
|
|
66
|
-
activePresetId?: string;
|
|
67
|
-
/** Preset persona block composed as a `source: 'persona'` system-prompt section (priority 5). */
|
|
68
|
-
persona?: string;
|
|
69
|
-
/** Preset execution capability: activate agent runtime + subagent/background dispatch. */
|
|
70
|
-
enableParallelSubagents?: boolean;
|
|
71
|
-
/** Preset execution capability: run a post-task self-verification step. */
|
|
72
|
-
selfVerification?: boolean;
|
|
73
|
-
backgroundTaskRunners?: IBackgroundTaskRunner[];
|
|
74
|
-
subagentRunnerFactory?: TSubagentRunnerFactory;
|
|
75
|
-
commandModules?: readonly ICommandModule[];
|
|
76
|
-
commandHostAdapters?: ICommandHostAdapters;
|
|
77
|
-
shellExec?: TShellExecFn;
|
|
78
|
-
}
|
|
79
|
-
declare class HeadlessInteractionChannel {
|
|
80
|
-
private readonly opts;
|
|
81
|
-
private exitCode;
|
|
82
|
-
constructor(options: IHeadlessInteractionChannelOptions);
|
|
83
|
-
run(prompt: string): Promise<void>;
|
|
84
|
-
/**
|
|
85
|
-
* GOAL-001: run an autonomous goal to completion (or a stop condition) in headless mode.
|
|
86
|
-
* Mirrors {@link run} but drives the framework goal loop instead of a single prompt.
|
|
87
|
-
*/
|
|
88
|
-
runGoal(objective: string, options?: {
|
|
89
|
-
maxIterations?: number;
|
|
90
|
-
}): Promise<void>;
|
|
91
|
-
private createSession;
|
|
92
|
-
getExitCode(): number;
|
|
93
|
-
}
|
|
94
|
-
//#endregion
|
|
95
|
-
export { IHeadlessRunnerOptions as a, promptInput as c, createHeadlessTransport as i, PrintTerminal as l, IHeadlessInteractionChannelOptions as n, TOutputFormat as o, IHeadlessTransportOptions as r, createHeadlessRunner as s, HeadlessInteractionChannel as t };
|
|
96
|
-
//# sourceMappingURL=index-JTD_xtEQ.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-JTD_xtEQ.d.ts","names":[],"sources":["../../src/headless/print-terminal.ts","../../src/headless/cli-input.ts","../../src/headless/headless-runner.ts","../../src/headless/headless-transport.ts","../../src/headless/HeadlessInteractionChannel.ts"],"mappings":";;;;;cAYa,aAAA,YAAyB,eAAA;EACpC,KAAA,CAAM,IAAA;EAGN,SAAA,CAAU,IAAA;EAGV,aAAA,CAAc,EAAA;EAGd,UAAA,CAAW,IAAA;EAGX,MAAA,CAAO,QAAA,WAAmB,OAAA;EAcpB,MAAA,CAAO,OAAA,YAAmB,YAAA,YAAmB,OAAA;EAcnD,OAAA,CAAQ,QAAA,WAAmB,QAAA;AAAA;;;cCnDhB,WAAA,GAAe,KAAA,UAAe,MAAA,eAAiB,OAAO;;;KCMvD,aAAA;;UAGK,oBAAA;EACf,aAAa;AAAA;AAAA,UAGE,sBAAA;EACf,OAAA,EAAS,mBAAA;EACT,YAAA,EAAc,aAAa;AAAA;AAAA,iBAMb,oBAAA,CAAqB,OAAA,EAAS,sBAAA;EAC5C,GAAA,GAAM,MAAA,aAAmB,OAAA;EACzB,OAAA,GAAU,SAAA,UAAmB,WAAA,GAAc,oBAAA,KAAyB,OAAA;AAAA;;;UCbrD,yBAAA;EH2BoC;EGzBnD,YAAA,EAAc,aAAa;EHFS;EGIpC,MAAA;AAAA;AAAA,iBAGc,uBAAA,CACd,OAAA,EAAS,yBAAA,GACR,iBAAA,CAAkB,mBAAA;EAAyB,WAAA;AAAA;;;UCE7B,kCAAA;EACf,GAAA;EACA,QAAA,EAAU,WAAA;EACV,YAAA,EAAc,aAAA;EACd,cAAA,GAAiB,eAAA;EACjB,QAAA;EACA,YAAA,GAAe,wBAAA;EJbf;EIeA,eAAA;EJZA;EIcA,WAAA;EACA,WAAA;EACA,IAAA;EACA,YAAA;EACA,WAAA;EACA,kBAAA;EACA,YAAA;EJAa;EIEb,SAAA;EJFmD;EIInD,cAAA;EJUQ;EIRR,OAAA;EJQmC;EINnC,uBAAA;;EAEA,gBAAA;EACA,qBAAA,GAAwB,qBAAA;EACxB,qBAAA,GAAwB,sBAAA;EACxB,cAAA,YAA0B,cAAA;EAC1B,mBAAA,GAAsB,oBAAA;EACtB,SAAA,GAAY,YAAA;AAAA;AAAA,cAGD,0BAAA;EAAA,iBACM,IAAA;EAAA,QACT,QAAA;cAEI,OAAA,EAAS,kCAAA;EAIf,GAAA,CAAI,MAAA,WAAiB,OAAA;;;AFzD7B;;EEoEQ,OAAA,CAAQ,SAAA,UAAmB,OAAA;IAAW,aAAA;EAAA,IAAgC,OAAA;EAAA,QAOpE,aAAA;EA0CR,WAAA;AAAA"}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { IAIProvider, IActionRequest, TActionResponse, TPermissionMode } from "@robota-sdk/agent-core";
|
|
2
|
-
import { IAgentDriver, ICommandInfo, IInteractionChannel, IInteractiveSessionStore, InteractionEvent } from "@robota-sdk/agent-interface-transport";
|
|
3
|
-
import { ICommandModule } from "@robota-sdk/agent-framework";
|
|
4
|
-
|
|
5
|
-
//#region src/programmatic/ProgrammaticInteractionChannel.d.ts
|
|
6
|
-
declare class ProgrammaticInteractionChannel implements IInteractionChannel {
|
|
7
|
-
/** Full structured event stream pushed by the framework, in order. */
|
|
8
|
-
readonly events: InteractionEvent[];
|
|
9
|
-
availableCommands: ICommandInfo[];
|
|
10
|
-
busy: boolean;
|
|
11
|
-
started: boolean;
|
|
12
|
-
stopped: boolean;
|
|
13
|
-
private submitHandler;
|
|
14
|
-
private readonly userActionResponses;
|
|
15
|
-
onSubmit(handler: (text: string) => Promise<void>): void;
|
|
16
|
-
write(event: InteractionEvent): void;
|
|
17
|
-
/**
|
|
18
|
-
* CMD-004 unified ask. Resolves from the pre-supplied queue (FIFO); an empty queue resolves
|
|
19
|
-
* `{ type: 'cancelled' }` so a programmatic run never blocks on an un-answered question.
|
|
20
|
-
*/
|
|
21
|
-
askUser(_request: IActionRequest): Promise<TActionResponse>;
|
|
22
|
-
setAvailableCommands(commands: ICommandInfo[]): void;
|
|
23
|
-
setBusy(busy: boolean): void;
|
|
24
|
-
start(): Promise<void>;
|
|
25
|
-
stop(): Promise<void>;
|
|
26
|
-
/** Push a user submission into the framework (the programmatic "user types and presses enter"). */
|
|
27
|
-
submit(text: string): Promise<void>;
|
|
28
|
-
/** Pre-answer the next `askUser` (CMD-004 unified ask). */
|
|
29
|
-
queueUserAction(response: TActionResponse): void;
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
//#region src/programmatic/createProgrammaticAgent.d.ts
|
|
33
|
-
interface ICreateProgrammaticAgentOptions {
|
|
34
|
-
/** Provider that answers the agent loop (e.g. a real provider, or the scripted provider in tests). */
|
|
35
|
-
provider: IAIProvider;
|
|
36
|
-
/** Working directory for session creation. */
|
|
37
|
-
cwd: string;
|
|
38
|
-
/** Slash-command modules to register (defaults to none). */
|
|
39
|
-
commandModules?: readonly ICommandModule[];
|
|
40
|
-
/** Optional session store for persistence. */
|
|
41
|
-
sessionStore?: IInteractiveSessionStore;
|
|
42
|
-
/** Permission mode for tool execution (e.g. `'bypassPermissions'` for unattended driving). */
|
|
43
|
-
permissionMode?: TPermissionMode;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Construct an in-process {@link IAgentDriver} bound to a real `InteractiveSession`. The returned
|
|
47
|
-
* driver's accessors are the shared `read*` helpers applied to the captured event stream.
|
|
48
|
-
*/
|
|
49
|
-
declare function createProgrammaticAgent(options: ICreateProgrammaticAgentOptions): IAgentDriver;
|
|
50
|
-
//#endregion
|
|
51
|
-
export { createProgrammaticAgent as n, ProgrammaticInteractionChannel as r, ICreateProgrammaticAgentOptions as t };
|
|
52
|
-
//# sourceMappingURL=index-y_HBOfzO.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-y_HBOfzO.d.ts","names":[],"sources":["../../src/programmatic/ProgrammaticInteractionChannel.ts","../../src/programmatic/createProgrammaticAgent.ts"],"mappings":";;;;;cAmBa,8BAAA,YAA0C,mBAAA;EA0BZ;EAAA,SAxBhC,MAAA,EAAQ,gBAAA;EAEjB,iBAAA,EAAmB,YAAA;EACnB,IAAA;EACA,OAAA;EACA,OAAA;EAAA,QAEQ,aAAA;EAAA,iBACS,mBAAA;EAIjB,QAAA,CAAS,OAAA,GAAU,IAAA,aAAiB,OAAA;EAIpC,KAAA,CAAM,KAAA,EAAO,gBAAA;EAhBJ;;;;EAwBH,OAAA,CAAQ,QAAA,EAAU,cAAA,GAAiB,OAAA,CAAQ,eAAA;EAIjD,oBAAA,CAAqB,QAAA,EAAU,YAAA;EAI/B,OAAA,CAAQ,IAAA;EAIF,KAAA,IAAS,OAAA;EAIT,IAAA,IAAQ,OAAA;EA5Bd;EAmCM,MAAA,CAAO,IAAA,WAAe,OAAA;EAnCQ;EA6CpC,eAAA,CAAgB,QAAA,EAAU,eAAA;AAAA;;;UCrDX,+BAAA;EDoB0B;EClBzC,QAAA,EAAU,WAAA;ED8BK;EC5Bf,GAAA;EDuC4B;ECrC5B,cAAA,YAA0B,cAAA;EDZ2B;ECcrD,YAAA,GAAe,wBAAA;EDdyD;ECgBxE,cAAA,GAAiB,eAAA;AAAA;;;;;iBAOH,uBAAA,CAAwB,OAAA,EAAS,+BAAA,GAAkC,YAAY"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../programmatic-6wLf68qJ.cjs");exports.ProgrammaticInteractionChannel=e.n,exports.createProgrammaticAgent=e.t;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,t}from"../programmatic-70dxIXtS.js";export{e as ProgrammaticInteractionChannel,t as createProgrammaticAgent};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
let e=require("@robota-sdk/agent-framework"),t=require("@robota-sdk/agent-interface-transport");var n=class{events=[];availableCommands=[];busy=!1;started=!1;stopped=!1;submitHandler=null;userActionResponses=[];onSubmit(e){this.submitHandler=e}write(e){this.events.push(e)}async askUser(e){return this.userActionResponses.shift()??{type:`cancelled`}}setAvailableCommands(e){this.availableCommands=e}setBusy(e){this.busy=e}async start(){this.started=!0}async stop(){this.stopped=!0}async submit(e){if(!this.submitHandler)throw Error(`ProgrammaticInteractionChannel: no submit handler registered — start the runtime first`);await this.submitHandler(e)}queueUserAction(e){this.userActionResponses.push(e)}};function r(r){let i=new n,a=(0,e.createInteractiveRuntime)({channel:i,commandModules:r.commandModules??[],provider:r.provider,cwd:r.cwd,sessionStore:r.sessionStore,permissionMode:r.permissionMode}),o=!1;return{events:i.events,start:async()=>{o||(o=!0,await a.start())},send:e=>i.submit(e),queueUserAction:e=>i.queueUserAction(e),assistantReplies:()=>(0,t.readAssistantReplies)(i.events),lastAssistantText:()=>(0,t.readLastAssistantText)(i.events),toolCalls:()=>(0,t.readToolCalls)(i.events),errors:()=>(0,t.readErrors)(i.events),stop:()=>a.stop()}}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return r}});
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{createInteractiveRuntime as e}from"@robota-sdk/agent-framework";import{readAssistantReplies as t,readErrors as n,readLastAssistantText as r,readToolCalls as i}from"@robota-sdk/agent-interface-transport";var a=class{events=[];availableCommands=[];busy=!1;started=!1;stopped=!1;submitHandler=null;userActionResponses=[];onSubmit(e){this.submitHandler=e}write(e){this.events.push(e)}async askUser(e){return this.userActionResponses.shift()??{type:`cancelled`}}setAvailableCommands(e){this.availableCommands=e}setBusy(e){this.busy=e}async start(){this.started=!0}async stop(){this.stopped=!0}async submit(e){if(!this.submitHandler)throw Error(`ProgrammaticInteractionChannel: no submit handler registered — start the runtime first`);await this.submitHandler(e)}queueUserAction(e){this.userActionResponses.push(e)}};function o(o){let s=new a,c=e({channel:s,commandModules:o.commandModules??[],provider:o.provider,cwd:o.cwd,sessionStore:o.sessionStore,permissionMode:o.permissionMode}),l=!1;return{events:s.events,start:async()=>{l||(l=!0,await c.start())},send:e=>s.submit(e),queueUserAction:e=>s.queueUserAction(e),assistantReplies:()=>t(s.events),lastAssistantText:()=>r(s.events),toolCalls:()=>i(s.events),errors:()=>n(s.events),stop:()=>c.stop()}}export{a as n,o as t};
|
|
2
|
-
//# sourceMappingURL=programmatic-70dxIXtS.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"programmatic-70dxIXtS.js","names":[],"sources":["../../src/programmatic/ProgrammaticInteractionChannel.ts","../../src/programmatic/createProgrammaticAgent.ts"],"sourcesContent":["/**\n * ProgrammaticInteractionChannel — an in-process IInteractionChannel adapter (INFRA-019).\n *\n * The \"programmatic preset\" adapter slot reserved by the interaction contract: instead of an Ink TUI\n * or a print runner, this channel lets a caller push a message in-process and read back the structured\n * `InteractionEvent` stream the framework already emits. It uses the documented one-way `write()`\n * protocol consumed by `createInteractiveRuntime` (not the TUI's direct-wiring path).\n *\n * Production transport adapter — lives in transport core. Tests and automation consume it; it never\n * depends on test code.\n */\n\nimport type { IActionRequest, TActionResponse } from '@robota-sdk/agent-core';\nimport type {\n IInteractionChannel,\n ICommandInfo,\n InteractionEvent,\n} from '@robota-sdk/agent-interface-transport';\n\nexport class ProgrammaticInteractionChannel implements IInteractionChannel {\n /** Full structured event stream pushed by the framework, in order. */\n readonly events: InteractionEvent[] = [];\n\n availableCommands: ICommandInfo[] = [];\n busy = false;\n started = false;\n stopped = false;\n\n private submitHandler: ((text: string) => Promise<void>) | null = null;\n private readonly userActionResponses: TActionResponse[] = [];\n\n // ── IInteractionChannel ──────────────────────────────────────\n\n onSubmit(handler: (text: string) => Promise<void>): void {\n this.submitHandler = handler;\n }\n\n write(event: InteractionEvent): void {\n this.events.push(event);\n }\n\n /**\n * CMD-004 unified ask. Resolves from the pre-supplied queue (FIFO); an empty queue resolves\n * `{ type: 'cancelled' }` so a programmatic run never blocks on an un-answered question.\n */\n async askUser(_request: IActionRequest): Promise<TActionResponse> {\n return this.userActionResponses.shift() ?? { type: 'cancelled' };\n }\n\n setAvailableCommands(commands: ICommandInfo[]): void {\n this.availableCommands = commands;\n }\n\n setBusy(busy: boolean): void {\n this.busy = busy;\n }\n\n async start(): Promise<void> {\n this.started = true;\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n }\n\n // ── Programmatic driving surface ─────────────────────────────\n\n /** Push a user submission into the framework (the programmatic \"user types and presses enter\"). */\n async submit(text: string): Promise<void> {\n if (!this.submitHandler) {\n throw new Error(\n 'ProgrammaticInteractionChannel: no submit handler registered — start the runtime first',\n );\n }\n await this.submitHandler(text);\n }\n\n /** Pre-answer the next `askUser` (CMD-004 unified ask). */\n queueUserAction(response: TActionResponse): void {\n this.userActionResponses.push(response);\n }\n}\n","/**\n * createProgrammaticAgent — the in-process implementation of the client-side agent contract\n * (`IAgentDriver`, INFRA-020; introduced as the programmatic driver in INFRA-019).\n *\n * Wraps `createInteractiveRuntime` with a {@link ProgrammaticInteractionChannel} so a caller can drive\n * the real agent structurally: `start()`, `send(text)` (awaits the whole turn), then read assistant\n * replies / tool calls / errors as data — no terminal, no PTY, no scraping. The observation accessors\n * delegate to the shared `read*` helpers in `@robota-sdk/agent-interface-transport`, so the\n * filter/derivation logic is not re-implemented here.\n */\n\nimport { createInteractiveRuntime } from '@robota-sdk/agent-framework';\nimport {\n readAssistantReplies,\n readErrors,\n readLastAssistantText,\n readToolCalls,\n} from '@robota-sdk/agent-interface-transport';\n\nimport { ProgrammaticInteractionChannel } from './ProgrammaticInteractionChannel.js';\n\nimport type { IAIProvider, TActionResponse, TPermissionMode } from '@robota-sdk/agent-core';\nimport type { ICommandModule, IInteractiveRuntime } from '@robota-sdk/agent-framework';\nimport type { IAgentDriver, IInteractiveSessionStore } from '@robota-sdk/agent-interface-transport';\n\nexport interface ICreateProgrammaticAgentOptions {\n /** Provider that answers the agent loop (e.g. a real provider, or the scripted provider in tests). */\n provider: IAIProvider;\n /** Working directory for session creation. */\n cwd: string;\n /** Slash-command modules to register (defaults to none). */\n commandModules?: readonly ICommandModule[];\n /** Optional session store for persistence. */\n sessionStore?: IInteractiveSessionStore;\n /** Permission mode for tool execution (e.g. `'bypassPermissions'` for unattended driving). */\n permissionMode?: TPermissionMode;\n}\n\n/**\n * Construct an in-process {@link IAgentDriver} bound to a real `InteractiveSession`. The returned\n * driver's accessors are the shared `read*` helpers applied to the captured event stream.\n */\nexport function createProgrammaticAgent(options: ICreateProgrammaticAgentOptions): IAgentDriver {\n const channel = new ProgrammaticInteractionChannel();\n const runtime: IInteractiveRuntime = createInteractiveRuntime({\n channel,\n commandModules: options.commandModules ?? [],\n provider: options.provider,\n cwd: options.cwd,\n sessionStore: options.sessionStore,\n permissionMode: options.permissionMode,\n });\n\n let started = false;\n\n return {\n events: channel.events,\n start: async (): Promise<void> => {\n if (started) return;\n started = true;\n await runtime.start();\n },\n send: (text: string): Promise<void> => channel.submit(text),\n queueUserAction: (response: TActionResponse): void => channel.queueUserAction(response),\n assistantReplies: (): string[] => readAssistantReplies(channel.events),\n lastAssistantText: (): string | undefined => readLastAssistantText(channel.events),\n toolCalls: () => readToolCalls(channel.events),\n errors: (): Error[] => readErrors(channel.events),\n stop: (): Promise<void> => runtime.stop(),\n };\n}\n"],"mappings":"kNAmBA,IAAa,EAAb,KAA2E,CAEzE,OAAsC,CAAC,EAEvC,kBAAoC,CAAC,EACrC,KAAO,GACP,QAAU,GACV,QAAU,GAEV,cAAkE,KAClE,oBAA0D,CAAC,EAI3D,SAAS,EAAgD,CACvD,KAAK,cAAgB,CACvB,CAEA,MAAM,EAA+B,CACnC,KAAK,OAAO,KAAK,CAAK,CACxB,CAMA,MAAM,QAAQ,EAAoD,CAChE,OAAO,KAAK,oBAAoB,MAAM,GAAK,CAAE,KAAM,WAAY,CACjE,CAEA,qBAAqB,EAAgC,CACnD,KAAK,kBAAoB,CAC3B,CAEA,QAAQ,EAAqB,CAC3B,KAAK,KAAO,CACd,CAEA,MAAM,OAAuB,CAC3B,KAAK,QAAU,EACjB,CAEA,MAAM,MAAsB,CAC1B,KAAK,QAAU,EACjB,CAKA,MAAM,OAAO,EAA6B,CACxC,GAAI,CAAC,KAAK,cACR,MAAU,MACR,wFACF,EAEF,MAAM,KAAK,cAAc,CAAI,CAC/B,CAGA,gBAAgB,EAAiC,CAC/C,KAAK,oBAAoB,KAAK,CAAQ,CACxC,CACF,ECvCA,SAAgB,EAAwB,EAAwD,CAC9F,IAAM,EAAU,IAAI,EACd,EAA+B,EAAyB,CAC5D,UACA,eAAgB,EAAQ,gBAAkB,CAAC,EAC3C,SAAU,EAAQ,SAClB,IAAK,EAAQ,IACb,aAAc,EAAQ,aACtB,eAAgB,EAAQ,cAC1B,CAAC,EAEG,EAAU,GAEd,MAAO,CACL,OAAQ,EAAQ,OAChB,MAAO,SAA2B,CAC5B,IACJ,EAAU,GACV,MAAM,EAAQ,MAAM,EACtB,EACA,KAAO,GAAgC,EAAQ,OAAO,CAAI,EAC1D,gBAAkB,GAAoC,EAAQ,gBAAgB,CAAQ,EACtF,qBAAkC,EAAqB,EAAQ,MAAM,EACrE,sBAA6C,EAAsB,EAAQ,MAAM,EACjF,cAAiB,EAAc,EAAQ,MAAM,EAC7C,WAAuB,EAAW,EAAQ,MAAM,EAChD,SAA2B,EAAQ,KAAK,CAC1C,CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@robota-sdk/agent-core/testing");Object.defineProperty(exports,"createScriptedProvider",{enumerable:!0,get:function(){return e.createScriptedProvider}});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{createScriptedProvider as e}from"@robota-sdk/agent-core/testing";export{e as createScriptedProvider};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CMD-004 PR-E: ProgrammaticInteractionChannel.askUser() — the unified ask path on the programmatic
|
|
3
|
-
* channel. FIFO from the pre-supplied queue; empty queue → cancelled (never blocks a headless run).
|
|
4
|
-
*/
|
|
5
|
-
import { describe, expect, it } from 'vitest';
|
|
6
|
-
|
|
7
|
-
import { ProgrammaticInteractionChannel } from '../../programmatic/ProgrammaticInteractionChannel.js';
|
|
8
|
-
|
|
9
|
-
import type { IActionRequest } from '@robota-sdk/agent-core';
|
|
10
|
-
|
|
11
|
-
const REQUEST: IActionRequest = {
|
|
12
|
-
id: 'q',
|
|
13
|
-
title: 'Pick',
|
|
14
|
-
options: [{ value: 'a', label: 'A' }],
|
|
15
|
-
maxSelect: 1,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
describe('ProgrammaticInteractionChannel.askUser', () => {
|
|
19
|
-
it('resolves cancelled when no answer is queued', async () => {
|
|
20
|
-
const channel = new ProgrammaticInteractionChannel();
|
|
21
|
-
expect(await channel.askUser(REQUEST)).toEqual({ type: 'cancelled' });
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('resolves queued answers FIFO, then cancelled once drained', async () => {
|
|
25
|
-
const channel = new ProgrammaticInteractionChannel();
|
|
26
|
-
channel.queueUserAction({ type: 'answer', values: ['a'] });
|
|
27
|
-
channel.queueUserAction({ type: 'cancelled' });
|
|
28
|
-
expect(await channel.askUser(REQUEST)).toEqual({ type: 'answer', values: ['a'] });
|
|
29
|
-
expect(await channel.askUser(REQUEST)).toEqual({ type: 'cancelled' });
|
|
30
|
-
expect(await channel.askUser(REQUEST)).toEqual({ type: 'cancelled' });
|
|
31
|
-
});
|
|
32
|
-
});
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* INFRA-019: in-process programmatic driving of the REAL agent.
|
|
3
|
-
*
|
|
4
|
-
* Drives `createProgrammaticAgent` (→ `createInteractiveRuntime` → a real `InteractiveSession`) with
|
|
5
|
-
* the deterministic scripted provider. No terminal, no PTY, no mocks of the framework loop: a message
|
|
6
|
-
* is pushed in-process and the structured `InteractionEvent` stream is asserted as data. This is the
|
|
7
|
-
* in-process form of "drive the agent at will" (TEST-008 north star).
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
11
|
-
import { tmpdir } from 'node:os';
|
|
12
|
-
import { join } from 'node:path';
|
|
13
|
-
|
|
14
|
-
import { createScriptedProvider } from '@robota-sdk/agent-core/testing';
|
|
15
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
16
|
-
|
|
17
|
-
import {
|
|
18
|
-
createProgrammaticAgent,
|
|
19
|
-
ProgrammaticInteractionChannel,
|
|
20
|
-
} from '../../programmatic/index.js';
|
|
21
|
-
|
|
22
|
-
import type { IAgentDriver } from '@robota-sdk/agent-interface-transport';
|
|
23
|
-
|
|
24
|
-
describe('programmatic in-process agent driver (INFRA-019)', () => {
|
|
25
|
-
let cwd: string;
|
|
26
|
-
let driver: IAgentDriver | undefined;
|
|
27
|
-
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
cwd = mkdtempSync(join(tmpdir(), 'robota-programmatic-'));
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
afterEach(async () => {
|
|
33
|
-
await driver?.stop();
|
|
34
|
-
driver = undefined;
|
|
35
|
-
rmSync(cwd, { recursive: true, force: true });
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('TC-01/02: send() drives a real turn and the scripted assistant reply is captured as data', async () => {
|
|
39
|
-
const scripted = createScriptedProvider([{ text: 'DRIVEN_ANSWER_42' }]);
|
|
40
|
-
driver = createProgrammaticAgent({ provider: scripted.provider, cwd });
|
|
41
|
-
|
|
42
|
-
await driver.start();
|
|
43
|
-
await driver.send('hello');
|
|
44
|
-
|
|
45
|
-
// TC-02: the reply is captured structurally — no terminal involved.
|
|
46
|
-
expect(driver.lastAssistantText()).toBe('DRIVEN_ANSWER_42');
|
|
47
|
-
expect(driver.assistantReplies()).toEqual(['DRIVEN_ANSWER_42']);
|
|
48
|
-
|
|
49
|
-
// Event order: the user message is recorded before the assistant completion.
|
|
50
|
-
const types = driver.events.map((e) => e.type);
|
|
51
|
-
expect(types).toContain('user-message');
|
|
52
|
-
expect(types).toContain('assistant-done');
|
|
53
|
-
expect(types.indexOf('user-message')).toBeLessThan(types.indexOf('assistant-done'));
|
|
54
|
-
expect(driver.errors()).toEqual([]);
|
|
55
|
-
|
|
56
|
-
// The scripted provider saw exactly the driven message.
|
|
57
|
-
const firstRequest = scripted.requests[0] ?? [];
|
|
58
|
-
const contents = firstRequest.map((m) => String(m.content));
|
|
59
|
-
expect(contents.some((c) => c.includes('hello'))).toBe(true);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('TC-03: a scripted tool-call turn runs the real tool loop and is captured in toolCalls()', async () => {
|
|
63
|
-
const target = join(cwd, 'greet.txt');
|
|
64
|
-
writeFileSync(target, 'Hello, world\n', 'utf8');
|
|
65
|
-
|
|
66
|
-
const scripted = createScriptedProvider([
|
|
67
|
-
{
|
|
68
|
-
toolCalls: [
|
|
69
|
-
{ name: 'Edit', args: { filePath: target, oldString: 'Hello', newString: 'Goodbye' } },
|
|
70
|
-
],
|
|
71
|
-
},
|
|
72
|
-
{ text: 'edit done' },
|
|
73
|
-
]);
|
|
74
|
-
driver = createProgrammaticAgent({
|
|
75
|
-
provider: scripted.provider,
|
|
76
|
-
cwd,
|
|
77
|
-
permissionMode: 'bypassPermissions',
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
await driver.start();
|
|
81
|
-
await driver.send('change the greeting');
|
|
82
|
-
|
|
83
|
-
// The real tool loop executed: the file on disk was mutated.
|
|
84
|
-
expect(readFileSync(target, 'utf8')).toBe('Goodbye, world\n');
|
|
85
|
-
// The tool call surfaced as structured data.
|
|
86
|
-
const calls = driver.toolCalls();
|
|
87
|
-
expect(calls.some((c) => c.name === 'Edit')).toBe(true);
|
|
88
|
-
expect(driver.lastAssistantText()).toBe('edit done');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('TC-04: queueUserAction pre-answers an askUser; empty queue resolves to cancelled', async () => {
|
|
92
|
-
const scripted = createScriptedProvider([{ text: 'noop' }]);
|
|
93
|
-
driver = createProgrammaticAgent({ provider: scripted.provider, cwd });
|
|
94
|
-
await driver.start();
|
|
95
|
-
|
|
96
|
-
// Exercise the unified ask contract in isolation (the FIFO queue the driver's queueUserAction feeds).
|
|
97
|
-
const channel = new ProgrammaticInteractionChannel();
|
|
98
|
-
const request = { id: 'x', title: 'ok?', options: [{ value: 'a', label: 'A' }], maxSelect: 1 };
|
|
99
|
-
|
|
100
|
-
channel.queueUserAction({ type: 'answer', values: ['a'] });
|
|
101
|
-
const answered = await channel.askUser(request);
|
|
102
|
-
expect(answered).toEqual({ type: 'answer', values: ['a'] });
|
|
103
|
-
|
|
104
|
-
const defaulted = await channel.askUser(request);
|
|
105
|
-
expect(defaulted).toEqual({ type: 'cancelled' });
|
|
106
|
-
});
|
|
107
|
-
});
|