@myagentroam/agent 0.10.20 → 0.10.22

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.
@@ -11,6 +11,7 @@ export declare function readModelCatalog(home: string): Promise<CliModelCatalog>
11
11
  export declare function writeModelCatalog(home: string, catalog: CliModelCatalog): Promise<void>;
12
12
  export declare function serializeModel(model: CliModelConfiguration): {
13
13
  apiKey: string;
14
+ conversationModel?: boolean;
14
15
  responsesConfigurationUpdates?: boolean;
15
16
  codexCredential?: boolean;
16
17
  responsesTransport?: import("./configuration.js").ResponsesTransport;
@@ -44,6 +45,7 @@ export declare function serializeModel(model: CliModelConfiguration): {
44
45
  credential: {
45
46
  type: "CODEX_AUTH_FILE";
46
47
  };
48
+ conversationModel?: boolean;
47
49
  responsesConfigurationUpdates?: boolean;
48
50
  codexCredential?: boolean;
49
51
  responsesTransport?: import("./configuration.js").ResponsesTransport;
@@ -67,6 +67,7 @@ declare const rawModelSchema: z.ZodObject<{
67
67
  max: "max";
68
68
  ultra: "ultra";
69
69
  }>>;
70
+ conversationModel: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
70
71
  titleGeneration: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
71
72
  codeMode: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
72
73
  fastMode: z.ZodOptional<z.ZodBoolean>;
@@ -99,7 +100,8 @@ declare const rawModelSchema: z.ZodObject<{
99
100
  }, z.core.$strict>>;
100
101
  enabled: z.ZodBoolean;
101
102
  }, z.core.$strict>;
102
- export interface MarAgentModelConfiguration extends Omit<z.infer<typeof rawModelSchema>, 'apiKey' | 'responsesPreviousResponseId' | 'responsesTransport'> {
103
+ export interface MarAgentModelConfiguration extends Omit<z.infer<typeof rawModelSchema>, 'apiKey' | 'responsesPreviousResponseId' | 'responsesTransport' | 'conversationModel'> {
104
+ conversationModel?: boolean;
103
105
  apiKey?: SecretValue;
104
106
  credentialProvider?: ModelCredentialProvider;
105
107
  /** Whether this Responses endpoint accepts native configuration_update input items. */
@@ -47,6 +47,7 @@ const rawModelSchema = z
47
47
  outputCapabilities: z.tuple([z.literal('TEXT')]),
48
48
  reasoningEfforts: z.array(marAgentReasoningEffortSchema),
49
49
  defaultReasoningEffort: marAgentReasoningEffortSchema.optional(),
50
+ conversationModel: z.boolean().optional().default(true),
50
51
  titleGeneration: z.boolean().optional().default(false),
51
52
  codeMode: z.boolean().optional().default(false),
52
53
  fastMode: z.boolean().optional(),
@@ -21,9 +21,12 @@ export function resolveAgentModels(configurations, requestedDefaultModelId) {
21
21
  const models = new Map(configuredModels.filter((model) => model.enabled).map((model) => [model.id, model]));
22
22
  if (models.size === 0)
23
23
  throw new MarAgentError('MAR_AGENT_MODEL_CONFIG_INVALID', 'At least one enabled model is required.');
24
- const defaultModelId = requestedDefaultModelId ?? models.keys().next().value;
25
- if (!models.has(defaultModelId))
26
- throw new MarAgentError('MAR_AGENT_MODEL_CONFIG_INVALID', 'Default model is unavailable.');
24
+ const defaultModelId = requestedDefaultModelId ??
25
+ [...models.values()].find((model) => model.conversationModel !== false)?.id;
26
+ if (!defaultModelId ||
27
+ !models.has(defaultModelId) ||
28
+ models.get(defaultModelId).conversationModel === false)
29
+ throw new MarAgentError('MAR_AGENT_MODEL_CONFIG_INVALID', 'Default conversation model is unavailable.');
27
30
  return { models, defaultModelId, credentialProviders };
28
31
  }
29
32
  export function createModelTurnSession(adapter) {
@@ -190,6 +190,10 @@ export function createSessionOpener(services) {
190
190
  services.assertCanStart();
191
191
  if ([...active.keys()].some((key) => key.startsWith(`${sessionId}:`)))
192
192
  throw new MarAgentError('MAR_AGENT_EXECUTION_ACTIVE', 'Session already has an active execution.');
193
+ const { models: executionModels, defaultModelId: executionDefaultModelId, generation: executionModelGeneration } = services.modelState();
194
+ if (mode !== 'compact' &&
195
+ executionModels.get(input.modelId ?? executionDefaultModelId)?.conversationModel === false)
196
+ throw new MarAgentError('MAR_AGENT_MODEL_DISABLED', 'The selected model is not a conversation model.');
193
197
  const executionId = randomUUID(), turnId = internal.turnId ?? randomUUID(), queue = new AsyncQueue(), controller = new AbortController();
194
198
  const abortSource = () => controller.abort(internal.signal?.reason);
195
199
  internal.signal?.addEventListener('abort', abortSource, { once: true });
@@ -199,7 +203,6 @@ export function createSessionOpener(services) {
199
203
  ...currentEnvironment,
200
204
  ...currentLocalTimeContext()
201
205
  };
202
- const { models: executionModels, defaultModelId: executionDefaultModelId, generation: executionModelGeneration } = services.modelState();
203
206
  const executionSystemInstruction = settings.systemInstruction;
204
207
  promptDefaults = {
205
208
  executionId,
@@ -610,7 +613,9 @@ export function createSessionOpener(services) {
610
613
  throw new MarAgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Host tools cannot use the MCP namespace.');
611
614
  const selectedModelForTools = executionModels.get(input.modelId ?? executionDefaultModelId);
612
615
  const builtinTools = BUILTIN_TOOL_DEFINITIONS.map((tool) => tool.name === 'agent_start'
613
- ? agentStartToolDefinitionWithModels([...executionModels.values()].map((configuration) => ({
616
+ ? agentStartToolDefinitionWithModels([...executionModels.values()]
617
+ .filter((configuration) => configuration.conversationModel !== false)
618
+ .map((configuration) => ({
614
619
  id: configuration.id,
615
620
  name: configuration.name,
616
621
  reasoningEfforts: configuration.reasoningEfforts
@@ -7,6 +7,7 @@ import type { SubagentController, SubagentMessageOptions, SubagentOutputOptions,
7
7
  export interface SubagentModelOption {
8
8
  readonly id: string;
9
9
  readonly name: string;
10
+ readonly conversationModel?: boolean;
10
11
  readonly reasoningEfforts: readonly MarAgentReasoningEffort[];
11
12
  readonly defaultReasoningEffort: MarAgentReasoningEffort;
12
13
  }
@@ -938,7 +938,7 @@ function validateTaskInput(input, native = false) {
938
938
  function resolveModel(execution, input) {
939
939
  const modelId = input.modelId ?? execution.modelId;
940
940
  const model = execution.models.get(modelId);
941
- if (!model)
941
+ if (!model || model.conversationModel === false)
942
942
  throw new MarAgentError('MAR_AGENT_SUBAGENT_MODEL_UNAVAILABLE', 'Selected model is unavailable for subagents.');
943
943
  if (input.reasoningEffort !== undefined &&
944
944
  !model.reasoningEfforts.includes(input.reasoningEffort))
package/dist/cli/main.js CHANGED
@@ -180,6 +180,7 @@ async function modelsCommand(home, arguments_, codexAuthFile) {
180
180
  defaultReasoningEffort: existing?.defaultReasoningEffort
181
181
  })
182
182
  : parseReasoningEffort(defaultReasoningEffortOption, '--default-reasoning-effort'),
183
+ conversationModel: existing?.conversationModel ?? true,
183
184
  titleGeneration: existing?.titleGeneration ?? false,
184
185
  codeMode: booleanFlag(arguments_, '--code-mode', '--no-code-mode', existing?.codeMode ?? false),
185
186
  ...(credential === 'codex-auth-file' && fastMode ? { fastMode: true } : {}),
@@ -252,7 +253,7 @@ async function main() {
252
253
  throw new MarAgentError('MAR_AGENT_CLI_ARGUMENT_INVALID', 'The deprecated --access option only accepts full-access.');
253
254
  const format = takeOption(arguments_, '--format') ?? 'text';
254
255
  const command = arguments_[0];
255
- const selectedModel = catalog.models.find((model) => model.id === modelId && model.enabled);
256
+ const selectedModel = catalog.models.find((model) => model.id === modelId && model.enabled && model.conversationModel !== false);
256
257
  if (selectedModel !== undefined)
257
258
  assertExternalCredentialAvailable(selectedModel, codexAuthFile);
258
259
  if (reasoningEffort && selectedModel && !selectedModel.reasoningEfforts.includes(reasoningEffort))
@@ -360,7 +361,8 @@ async function main() {
360
361
  models: runtime.models,
361
362
  currentModelId: modelId ??
362
363
  catalog.defaultModelId ??
363
- runtime.models.find((model) => model.enabled).id,
364
+ runtime.models.find((model) => model.enabled && model.conversationModel !== false)
365
+ .id,
364
366
  prompt: invocation.prompt,
365
367
  signal: titleController.signal
366
368
  }).catch(() => undefined);
package/dist/index.d.ts CHANGED
@@ -11,7 +11,7 @@ export { testMarAgentModelTransport } from './agent-core/model/transport-test.js
11
11
  export type { AccessMode, ExecutionMode, ExecutionResult, MarAgentImageMetadata, RolloutBudgetOptions, RunInput, RunInputImage } from './agent-core/runtime/contracts.js';
12
12
  export type { MarAgentEvent } from './agent-core/runtime/events.js';
13
13
  export { createMarAgent } from './agent-core/sdk/agent.js';
14
- export { generateModelText, type GenerateModelTextInput } from './shared/model-text.js';
14
+ export { generateModelText, type GenerateModelTextInput, type GenerateModelTextResult } from './shared/model-text.js';
15
15
  export type { CoreAgentExtensionContext, CoreSessionExtensionContext, CoreRuntimeExtension, CoreExtensionSnapshot, CoreExtensionSource, CoreExtensionDiagnostic, CoreDomainOperations, CoreDomainFacts, CoreHookRegistrar, CoreCapabilitySnapshot, CoreCommandSpec, CorePromptSection, CoreServiceDeclaration, CoreServiceDependency } from './agent-core/extensions/contracts.js';
16
16
  export type { CoreDisposer, CoreResourceRegistration, CoreResourceScope } from './agent-core/extensions/resources.js';
17
17
  export type { CoreHookOptions, CoreInterceptor } from './agent-core/extensions/hooks.js';
@@ -1,19 +1,26 @@
1
1
  import { type MarAgentModelConfiguration, type MarAgentReasoningEffort } from '../agent-core/model/configuration.js';
2
2
  import type { ModelAttemptDiagnostic, ModelUsage } from '../agent-core/model/contracts.js';
3
3
  import type { CoreCompactMessage } from '../agent-core/extensions/compaction.js';
4
+ import type { ClientToolDefinition, ToolCall } from '../agent-core/tools/contracts.js';
4
5
  export interface GenerateModelTextInput {
5
6
  readonly onModelUsage?: (usage: import('../agent-core/model/usage-observer.js').ModelRequestUsage) => Promise<void> | void;
6
7
  readonly onModelUsageFailure?: () => void;
7
8
  readonly model: MarAgentModelConfiguration;
8
9
  readonly system: string;
9
10
  readonly messages: readonly CoreCompactMessage[];
11
+ /** Declarative client tools only. Returned calls are never executed or continued here. */
12
+ readonly tools?: readonly ClientToolDefinition[];
13
+ readonly promptCacheKey?: string;
14
+ readonly cachePrefixMessages?: number;
10
15
  readonly reasoningEffort?: MarAgentReasoningEffort;
11
16
  readonly outputLimit?: number;
12
17
  readonly signal: AbortSignal;
13
18
  readonly onAttemptDiagnostic?: (diagnostic: ModelAttemptDiagnostic) => Promise<void> | void;
14
19
  }
15
- /** One tool-free request using the SDK transports. Credential providers remain caller-owned. */
16
- export declare function generateModelText(input: GenerateModelTextInput): Promise<{
17
- text: string;
18
- usage?: ModelUsage;
19
- } | undefined>;
20
+ export interface GenerateModelTextResult {
21
+ readonly text: string;
22
+ readonly toolCalls?: readonly ToolCall[];
23
+ readonly usage?: ModelUsage;
24
+ }
25
+ /** One request using the SDK transports, without tool execution or a Session. */
26
+ export declare function generateModelText(input: GenerateModelTextInput): Promise<GenerateModelTextResult | undefined>;
@@ -3,16 +3,20 @@ import { MarAgentError } from '../agent-core/error.js';
3
3
  import { AnthropicMessagesAdapter } from '../agent-core/model/anthropic-messages.js';
4
4
  import { OpenAiResponsesAdapter } from '../agent-core/model/openai-responses.js';
5
5
  import { resolveModelDefaultReasoningEffort } from '../agent-core/model/configuration.js';
6
- /** One tool-free request using the SDK transports. Credential providers remain caller-owned. */
6
+ /** One request using the SDK transports, without tool execution or a Session. */
7
7
  export async function generateModelText(input) {
8
8
  input.signal.throwIfAborted();
9
9
  if (!input.model.enabled)
10
10
  return undefined;
11
+ const tools = input.tools ?? [];
12
+ // Standalone calls expose only the caller's declared client tools, never hosted search.
13
+ const model = { ...input.model, hostedWebSearch: false };
11
14
  const adapter = input.model.protocol === 'OPENAI_RESPONSES'
12
- ? new OpenAiResponsesAdapter(input.model)
13
- : new AnthropicMessagesAdapter(input.model);
15
+ ? new OpenAiResponsesAdapter(model)
16
+ : new AnthropicMessagesAdapter(model);
14
17
  let text = '';
15
18
  let completed = false;
19
+ const toolCalls = [];
16
20
  let usage;
17
21
  try {
18
22
  for await (const event of adapter.start({
@@ -23,11 +27,15 @@ export async function generateModelText(input) {
23
27
  ? {}
24
28
  : { onModelUsageFailure: input.onModelUsageFailure }),
25
29
  system: input.system,
30
+ ...(input.cachePrefixMessages === undefined
31
+ ? {}
32
+ : { cachePrefixMessages: input.cachePrefixMessages }),
26
33
  messages: input.messages,
27
- tools: [],
28
- allowTools: false,
29
- toolChoice: 'none',
34
+ tools,
35
+ allowTools: tools.length > 0,
36
+ toolChoice: tools.length > 0 ? 'auto' : 'none',
30
37
  reasoningEffort: input.reasoningEffort ?? resolveModelDefaultReasoningEffort(input.model),
38
+ ...(input.promptCacheKey === undefined ? {} : { promptCacheKey: input.promptCacheKey }),
31
39
  ...(input.onAttemptDiagnostic ? { onAttemptDiagnostic: input.onAttemptDiagnostic } : {}),
32
40
  ...(input.outputLimit === undefined ? {} : { outputLimit: input.outputLimit })
33
41
  }, input.signal)) {
@@ -37,12 +45,22 @@ export async function generateModelText(input) {
37
45
  else if (event.type === 'usage')
38
46
  usage = event.usage;
39
47
  else if (event.type === 'completed')
40
- completed = event.reason === 'completed';
41
- else if (event.type === 'client_tool.call')
42
- throw new MarAgentError('MAR_AGENT_MODEL_PROTOCOL_ERROR', 'Text generation returned a tool call while tools were disabled.');
48
+ completed =
49
+ event.reason === 'completed' || (event.reason === 'tool_use' && toolCalls.length > 0);
50
+ else if (event.type === 'client_tool.call') {
51
+ if (!tools.some((tool) => tool.name === event.name) || event.argumentError !== undefined)
52
+ throw new MarAgentError('MAR_AGENT_MODEL_PROTOCOL_ERROR', 'Standalone generation returned an undeclared tool or invalid tool arguments.');
53
+ toolCalls.push({ name: event.name, callId: event.callId, arguments: event.arguments });
54
+ }
43
55
  }
44
56
  input.signal.throwIfAborted();
45
- return completed && text ? { text, ...(usage === undefined ? {} : { usage }) } : undefined;
57
+ return completed && (text || toolCalls.length > 0)
58
+ ? {
59
+ text,
60
+ ...(toolCalls.length > 0 ? { toolCalls } : {}),
61
+ ...(usage === undefined ? {} : { usage })
62
+ }
63
+ : undefined;
46
64
  }
47
65
  finally {
48
66
  await adapter.close?.();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/agent",
3
- "version": "0.10.20",
3
+ "version": "0.10.22",
4
4
  "description": "Embeddable MAR coding agent SDK and CLI.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",