@opengeni/runtime 4.0.1 → 4.0.3-canary.36079201993001

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.
Files changed (48) hide show
  1. package/dist/{agent-RJQLKFIW.js → agent-ME6HT4DH.js} +2 -2
  2. package/dist/assets/codemode-client.json +1 -1
  3. package/dist/browser-action-json-schema.d.ts +4 -0
  4. package/dist/{chunk-J5AR5XAJ.js → chunk-GBVN7WSK.js} +377 -210
  5. package/dist/chunk-GBVN7WSK.js.map +1 -0
  6. package/dist/{chunk-ZG2YH25H.js → chunk-JAYHA6BF.js} +2 -2
  7. package/dist/{chunk-UNICCRW5.js → chunk-LZIXCZUV.js} +6 -3
  8. package/dist/{chunk-UNICCRW5.js.map → chunk-LZIXCZUV.js.map} +1 -1
  9. package/dist/{chunk-J6J3VYFW.js → chunk-OGG5NQLA.js} +597 -65
  10. package/dist/chunk-OGG5NQLA.js.map +1 -0
  11. package/dist/{chunk-SPT3PLMX.js → chunk-PRHMSM6C.js} +2 -2
  12. package/dist/context-compaction.d.ts +4 -2
  13. package/dist/index.d.ts +8 -6
  14. package/dist/index.js +9 -7
  15. package/dist/interaction-tools.d.ts +1 -1
  16. package/dist/{lazy-manifest-OEYEHNVY.js → lazy-manifest-GCGUFIWP.js} +3 -3
  17. package/dist/{localSources-TWHTEKGO.js → localSources-FDH65AFI.js} +4 -4
  18. package/dist/operational-instructions.d.ts +1 -1
  19. package/dist/sandbox/browser-control-client.d.ts +28 -1
  20. package/dist/sandbox/index.d.ts +2 -2
  21. package/dist/sandbox/index.js +6 -6
  22. package/dist/sandbox/providers/modal-command-router-wire.d.ts +8 -0
  23. package/dist/sandbox/providers/modal.d.ts +5 -6
  24. package/dist/workspace-tool-gateway.js +5 -5
  25. package/package.json +11 -11
  26. package/src/browser-action-json-schema.ts +10 -0
  27. package/src/bundled_artifact_skills/opengeni-documents/SKILL.md +4 -1
  28. package/src/bundled_artifact_skills/opengeni-documents/references/api.md +20 -0
  29. package/src/bundled_default_skills/opengeni-client/SKILL.md +4 -1
  30. package/src/bundled_default_skills/opengeni-client/references/discovery-and-autonomy.md +31 -0
  31. package/src/bundled_default_skills/opengeni-client/references/runtime-profile-and-verification.md +32 -0
  32. package/src/context-compaction.ts +19 -3
  33. package/src/index.ts +100 -36
  34. package/src/interaction-tools.ts +656 -48
  35. package/src/operational-instructions.ts +1 -1
  36. package/src/sandbox/browser-control-client.ts +241 -26
  37. package/src/sandbox/index.ts +3 -1
  38. package/src/sandbox/providers/modal-command-control.ts +7 -1
  39. package/src/sandbox/providers/modal-command-router-wire.ts +47 -6
  40. package/src/sandbox/providers/modal.ts +16 -24
  41. package/src/sandbox/routing/routing-session.ts +4 -2
  42. package/dist/chunk-J5AR5XAJ.js.map +0 -1
  43. package/dist/chunk-J6J3VYFW.js.map +0 -1
  44. /package/dist/{agent-RJQLKFIW.js.map → agent-ME6HT4DH.js.map} +0 -0
  45. /package/dist/{chunk-ZG2YH25H.js.map → chunk-JAYHA6BF.js.map} +0 -0
  46. /package/dist/{chunk-SPT3PLMX.js.map → chunk-PRHMSM6C.js.map} +0 -0
  47. /package/dist/{lazy-manifest-OEYEHNVY.js.map → lazy-manifest-GCGUFIWP.js.map} +0 -0
  48. /package/dist/{localSources-TWHTEKGO.js.map → localSources-FDH65AFI.js.map} +0 -0
@@ -52,6 +52,37 @@ Group tightly related unresolved decisions when that makes them easier to answer
52
52
 
53
53
  For a missing privacy answer, default provisionally to the smaller sharing boundary and explain the operational cost. Do not silently weaken isolation to reduce workspace count.
54
54
 
55
+ ### Keep product choices lightweight
56
+
57
+ When meaningful choices remain, group them into one short question interaction
58
+ using the host's existing structured human-input UI when available, or a concise
59
+ chat question otherwise. Recommend the setup that fits the product and let the
60
+ user accept it or adjust individual choices. Do not build a new questionnaire or
61
+ ask every integration the same questions. A suggested answer is not consent to
62
+ send data, share private content, or perform an external action.
63
+
64
+ Use product language for the relevant unresolved choices:
65
+
66
+ - **Learning across chats:** no new lasting learning, remember for each person,
67
+ or shared team knowledge. Explain briefly that chat history/retention is separate
68
+ and disabling learning does not delete history or existing authorized Knowledge.
69
+ - **Who can open chats:** only their owner, the team, or a choice on each chat.
70
+ Keep human visibility separate from agent access and Knowledge scope. Choose the
71
+ workspace mapping from the actual sharing boundary; private chats alone do not
72
+ require a workspace per person.
73
+ - **How the agent gets data:** current-page snapshots, read-only tools to fetch
74
+ more reports, or controlled queries for deeper analysis. State the meaningful
75
+ limitation of the recommendation. Confirm broader access or writes separately
76
+ only when they are part of the requested product.
77
+
78
+ For example, if all three choices are unresolved for a simple dashboard, propose
79
+ “Private chats, no learning between chats, and current-page data only” with a short
80
+ explanation that the agent cannot fetch another report on its own. Do not reuse
81
+ that default for a team assistant whose requirements already imply shared work.
82
+ Continue independent discovery while awaiting an answer; ask again only when new
83
+ information introduces a material decision. Summarize any provisional choices in
84
+ the handoff so they do not become invisible product decisions.
85
+
55
86
  ## Follow the wanted autonomy
56
87
 
57
88
  Infer the delivery mode from explicit user language first, then repository guidance and established team workflow:
@@ -154,4 +154,36 @@ silently linking identities or widening membership. Complete discoverable setup
154
154
  before handoff; identify operator-only blockers separately and do not depend on
155
155
  internal source, cluster access, prior chat memory, or undocumented local helpers.
156
156
 
157
+ ### Make the next step easy
158
+
159
+ Keep the user-facing handoff short: what works, what was verified, and the next
160
+ action needed to make it usable. Put detailed commands and configuration in the
161
+ repository setup guide and link it. When setup is blocked, show a compact checklist
162
+ in the conversation using existing text/link UI; no new setup-card renderer is
163
+ required.
164
+
165
+ For missing OpenGeni credentials, point to the selected deployment's Organization
166
+ settings: the overview shows **Organization ID** with a copy control, and
167
+ **Developer** contains **Create Organization API Key** plus another ID copy
168
+ control. Prefer a verified settings link or returned setup action over an invented
169
+ URL. Verify older/self-hosted UI availability before promising these controls.
170
+ Explain the key type and required access for the implemented calls: workspace
171
+ provisioning and chat writes need a write-capable organization key, not a read-only
172
+ key. State its actual scope without inventing granular permission switches.
173
+
174
+ Name the exact server configuration variables and secret-store destination. Fill
175
+ verified non-secret IDs yourself when authorized and unambiguous. Give a secure
176
+ interactive command or secret-manager action for the key; never ask the user to
177
+ paste a secret into chat or put it in a browser variable. Follow with the actual
178
+ deployment command/target and a first-question smoke test, including model/billing
179
+ readiness when unverified. Complete authorized steps yourself; clearly identify
180
+ any remaining owner login, secret entry, or deployment approval.
181
+
182
+ Resolve ordinary missing tools using the project's supported installation or
183
+ package-runner path where possible. Investigate dependency warnings enough to
184
+ state their effect and available fix. Surface only material unresolved risks or
185
+ user actions in plain language; keep routine audit counts and logs in the setup
186
+ or verification notes. Do not claim a warning is harmless without evidence, or
187
+ make unrelated upgrades merely to silence the report.
188
+
157
189
  If a durable customer integration Skill would reduce future rediscovery, generate one beside the integration code containing only stable, non-secret project facts and smoke probes. Do not turn the generic implementation Skill into the customer's analytics prompt, and do not make generated runtime behavior depend on the implementation workspace retaining this implementation Skill.
@@ -43,6 +43,10 @@ export type CompactionItem = Record<string, unknown>;
43
43
  export const COMPACTION_SUMMARY_MARKER = "opengeni_context_summary";
44
44
 
45
45
  export const SUMMARY_BUFFER_TOKENS = 20_000;
46
+ /** Leave input room on models whose entire context is smaller than the normal reserve. */
47
+ export function compactionSummaryOutputTokens(contextWindowTokens: number): number {
48
+ return Math.min(SUMMARY_BUFFER_TOKENS, Math.max(1, Math.floor(contextWindowTokens / 4)));
49
+ }
46
50
  // A single cumulative budget for all retained real user messages, matching
47
51
  // Codex core's build_compacted_history_with_limit (not a per-message allowance).
48
52
  export const COMPACT_USER_MESSAGE_MAX_TOKENS = 20_000;
@@ -1243,7 +1247,7 @@ export class EmptyCompactionSummaryError extends Error {
1243
1247
  constructor(diagnostics: Record<string, unknown> = {}) {
1244
1248
  const compact = JSON.stringify(diagnostics).slice(0, 2_000);
1245
1249
  super(
1246
- `Compaction summarizer returned no assistant text; active history was preserved${compact ? ` (${compact})` : ""}`,
1250
+ `Compaction could not produce a usable checkpoint; active history was preserved${compact ? ` (${compact})` : ""}`,
1247
1251
  );
1248
1252
  this.name = "EmptyCompactionSummaryError";
1249
1253
  this.diagnostics = diagnostics;
@@ -1520,10 +1524,18 @@ export function omitOpaqueArtifactsFromPortableCompactionHistory(
1520
1524
  }
1521
1525
  if (type === "reasoning" && hasOpaqueProviderArtifact(item)) {
1522
1526
  const projected = projectRejectedReasoningArtifact(item);
1527
+ if (Object.keys(projected).length === 1) {
1528
+ changed = true;
1529
+ continue;
1530
+ }
1523
1531
  changed ||= projected !== item;
1524
1532
  out.push(projected as CompactionItem);
1525
1533
  continue;
1526
1534
  }
1535
+ if (type === "reasoning" && Object.keys(item).length === 1) {
1536
+ changed = true;
1537
+ continue;
1538
+ }
1527
1539
  out.push(item);
1528
1540
  }
1529
1541
  return changed ? out : (items as CompactionItem[]);
@@ -1605,16 +1617,20 @@ function oldestLogicalUnitCuts(items: readonly CompactionItem[]): number[] {
1605
1617
 
1606
1618
  /**
1607
1619
  * Build the active history after compaction:
1608
- * the newest real user messages that fit one cumulative 20k-token budget
1620
+ * the newest real user messages that fit one cumulative, model-bounded budget
1609
1621
  * (prior summaries excluded, retained images preserved) plus one marked summary item.
1610
1622
  */
1611
1623
  export function buildCompactionReplacementHistory(
1612
1624
  items: readonly CompactionItem[],
1613
1625
  summaryBody: string,
1614
1626
  retainedItemTokens: (item: CompactionItem) => number = (item) => estimateTokens([item]),
1627
+ retainedMessageBudgetTokens = COMPACT_USER_MESSAGE_MAX_TOKENS,
1615
1628
  ): CompactionItem[] {
1616
1629
  const retainedReversed: CompactionItem[] = [];
1617
- let remaining = COMPACT_USER_MESSAGE_MAX_TOKENS;
1630
+ let remaining = Math.max(
1631
+ 0,
1632
+ Math.min(COMPACT_USER_MESSAGE_MAX_TOKENS, retainedMessageBudgetTokens),
1633
+ );
1618
1634
  for (let index = items.length - 1; index >= 0 && remaining > 0; index -= 1) {
1619
1635
  const item = items[index]!;
1620
1636
  if (!isUserMessage(item) || isCompactionSummary(item) || isAttachmentCatalog(item)) {
package/src/index.ts CHANGED
@@ -253,7 +253,7 @@ import { OPENGENI_OPERATIONAL_INSTRUCTIONS } from "./operational-instructions";
253
253
  import {
254
254
  CompactionProviderResponseError,
255
255
  EmptyCompactionSummaryError,
256
- SUMMARY_BUFFER_TOKENS,
256
+ compactionSummaryOutputTokens,
257
257
  buildRemoteCompactionV2PromptInput,
258
258
  extractRemoteCompactionV2OutputItem,
259
259
  estimateSerializedValueTokens,
@@ -262,6 +262,7 @@ import {
262
262
  } from "./context-compaction";
263
263
  import {
264
264
  createSandboxClient,
265
+ isModalTaskExecStartPreDispatchUnavailableError,
265
266
  isRoutingMutationOutcomeUnknownError,
266
267
  repairSerializedRunStateExposedPorts,
267
268
  restoredSandboxSessionStateFromEntry,
@@ -655,6 +656,7 @@ export {
655
656
  MIN_COMPACTION_THRESHOLD_RATIO,
656
657
  MAX_COMPACTION_THRESHOLD_RATIO,
657
658
  SUMMARY_BUFFER_TOKENS,
659
+ compactionSummaryOutputTokens,
658
660
  SUMMARY_PREFIX,
659
661
  USER_MESSAGE_TRUNCATION_MARKER,
660
662
  REMOTE_COMPACTION_TOOL_RESULT_OMISSION,
@@ -1004,17 +1006,17 @@ export async function generateSessionTitle(
1004
1006
  * call against the resolved provider. `input` is the active history plus
1005
1007
  * Codex's checkpoint prompt. Provider failures propagate to the compaction
1006
1008
  * lifecycle; there is no non-model fallback that silently discards history.
1007
- * The call deliberately does NOT
1008
- * request reasoning encryption, tools, or inline provider compaction; it is a
1009
- * self-contained summarize.
1009
+ * It is a single summary call: prepared Responses requests retain tool schemas
1010
+ * and provider settings for the existing prefix, but tool selection is disabled
1011
+ * and no tool execution loop or inline provider compaction runs.
1010
1012
  *
1011
1013
  * Provider-aware: the summary always runs on the SAME provider that serves the
1012
1014
  * turn (registry providers can't summarize through OpenAI/Azure, and vice
1013
1015
  * versa). `api: "chat"` providers (Fireworks) speak /v1/chat/completions, where
1014
1016
  * the summary is choices[0].message.content; `api: "responses"` (the default,
1015
1017
  * built-in OpenAI/Azure) speaks /v1/responses as before. When no client/api is
1016
- * supplied it uses the built-in OpenAI/Azure Responses path. store:false is set
1017
- * only on the OpenAI-platform Responses path (Azure rejects it; chat ignores it).
1018
+ * supplied it uses the built-in OpenAI/Azure Responses path. Non-Azure Responses
1019
+ * requests use store:false; the resolved Azure wire profile omits it.
1018
1020
  */
1019
1021
  export async function summarizeForCompaction(
1020
1022
  settings: Settings,
@@ -1027,6 +1029,8 @@ export async function summarizeForCompaction(
1027
1029
  model?: string;
1028
1030
  promptCacheKey?: string;
1029
1031
  systemInstructions?: string;
1032
+ preparedRequest?: Omit<ModelRequest, "input">;
1033
+ signal?: AbortSignal;
1030
1034
  onUsage?: (usage: ModelResponseUsage) => void | Promise<void>;
1031
1035
  } = {},
1032
1036
  ): Promise<string> {
@@ -1035,17 +1039,27 @@ export async function summarizeForCompaction(
1035
1039
  const model = options.model ?? settings.openaiModel;
1036
1040
  const provider = options.provider ?? configuredProviders(settings)[0];
1037
1041
  if (!provider) throw new Error("Built-in model provider is unavailable");
1038
- const maxTokens = options.maxOutputTokens ?? SUMMARY_BUFFER_TOKENS;
1042
+ const azureResponses = provider.wireProfile === "azure-openai";
1043
+ const maxTokens =
1044
+ options.maxOutputTokens ?? compactionSummaryOutputTokens(settings.contextWindowTokens);
1039
1045
  if (api === "chat") {
1040
1046
  const transcript = renderCompactionPromptInputForChat(input);
1041
1047
  let completion: unknown;
1042
1048
  try {
1043
- completion = await client.chat.completions.create({
1044
- model,
1045
- max_tokens: maxTokens,
1046
- messages: [{ role: "user", content: transcript }],
1047
- ...(options.promptCacheKey ? { prompt_cache_key: options.promptCacheKey } : {}),
1048
- } as any);
1049
+ completion = await client.chat.completions.create(
1050
+ {
1051
+ model,
1052
+ max_tokens: maxTokens,
1053
+ messages: [
1054
+ ...(options.systemInstructions
1055
+ ? [{ role: "system" as const, content: options.systemInstructions }]
1056
+ : []),
1057
+ { role: "user", content: transcript },
1058
+ ],
1059
+ ...(options.promptCacheKey ? { prompt_cache_key: options.promptCacheKey } : {}),
1060
+ } as any,
1061
+ options.signal ? { signal: options.signal } : undefined,
1062
+ );
1049
1063
  } catch (error) {
1050
1064
  throw new CompactionProviderResponseError(compactionProviderFailureDiagnostics(error), error);
1051
1065
  }
@@ -1053,8 +1067,23 @@ export async function summarizeForCompaction(
1053
1067
  if (usage) {
1054
1068
  await options.onUsage?.(usage);
1055
1069
  }
1056
- const text = (completion as { choices?: Array<{ message?: { content?: unknown } }> })
1057
- .choices?.[0]?.message?.content;
1070
+ const choice = (
1071
+ completion as {
1072
+ choices?: Array<{ finish_reason?: unknown; message?: { content?: unknown } }>;
1073
+ }
1074
+ ).choices?.[0];
1075
+ if (choice?.finish_reason !== "stop") {
1076
+ throw new EmptyCompactionSummaryError({
1077
+ stage: "chat_completion",
1078
+ reason: "non_stop_finish",
1079
+ finishReason: ["length", "content_filter", "tool_calls", "function_call"].includes(
1080
+ String(choice?.finish_reason),
1081
+ )
1082
+ ? choice?.finish_reason
1083
+ : "unknown",
1084
+ });
1085
+ }
1086
+ const text = choice.message?.content;
1058
1087
  const summary = typeof text === "string" ? text.trim() : "";
1059
1088
  if (!summary) {
1060
1089
  throw new EmptyCompactionSummaryError(compactionResponseDiagnostics(completion, summary));
@@ -1064,27 +1093,54 @@ export async function summarizeForCompaction(
1064
1093
  // Use the same SDK Responses adapter as the real agent call. It converts the
1065
1094
  // structured AgentInputItems (callId/providerData/etc.) to provider wire
1066
1095
  // items without flattening tool history into a fake user transcript.
1067
- const request: ModelRequest = {
1068
- systemInstructions: options.systemInstructions ?? "",
1069
- input: input.map(detachCompactionResponseItemIdentity) as AgentInputItem[],
1070
- modelSettings: {
1071
- maxTokens,
1072
- // Azure can select a historical tool despite empty schemas. Keep this
1073
- // verified policy off subscription/gateway transports with other contracts.
1074
- ...(provider.wireProfile === "azure-openai" ? { toolChoice: "none" as const } : {}),
1075
- // Azure rejects store:false; the Codex subscription transport enforces
1076
- // it independently. The OpenAI platform path remains explicitly storeless.
1077
- ...(settings.openaiProvider === "azure" ? {} : { store: false }),
1078
- ...(options.promptCacheKey
1079
- ? { providerData: { prompt_cache_key: options.promptCacheKey } }
1080
- : {}),
1081
- },
1082
- tools: [],
1083
- toolsExplicitlyProvided: true,
1084
- outputType: "text",
1085
- handoffs: [],
1086
- tracing: false,
1087
- };
1096
+ // The captured inference signal may have been aborted when its stream
1097
+ // stopped. Compaction must use the still-active turn signal instead.
1098
+ const preparedPrefix = options.preparedRequest
1099
+ ? (({ signal: _priorSignal, ...prefix }) => prefix)(options.preparedRequest)
1100
+ : null;
1101
+ const { store: _priorStore, ...preparedModelSettings } = preparedPrefix?.modelSettings ?? {};
1102
+ const request: ModelRequest = preparedPrefix
1103
+ ? {
1104
+ ...preparedPrefix,
1105
+ // The history copy is still portable: dependent stored response ids are
1106
+ // removed, and the final checkpoint instruction is appended by the caller.
1107
+ input: input.map(detachCompactionResponseItemIdentity) as AgentInputItem[],
1108
+ modelSettings: {
1109
+ ...preparedModelSettings,
1110
+ maxTokens,
1111
+ // Retain schemas for the warm prefix without letting the checkpoint
1112
+ // model select or execute a tool (including a historical Azure tool).
1113
+ toolChoice: "none",
1114
+ // The selected provider, not the deployment default, owns this wire
1115
+ // policy. Override any inherited value on a prepared Azure request.
1116
+ ...(azureResponses ? {} : { store: false }),
1117
+ },
1118
+ outputType: "text",
1119
+ tracing: false,
1120
+ ...(options.signal ? { signal: options.signal } : {}),
1121
+ }
1122
+ : {
1123
+ systemInstructions: options.systemInstructions ?? "",
1124
+ input: input.map(detachCompactionResponseItemIdentity) as AgentInputItem[],
1125
+ modelSettings: {
1126
+ maxTokens,
1127
+ // Azure can select a historical tool despite empty schemas. Keep this
1128
+ // verified policy off subscription/gateway transports with other contracts.
1129
+ ...(azureResponses ? { toolChoice: "none" as const } : {}),
1130
+ // Azure rejects store:false; the Codex subscription transport enforces
1131
+ // it independently. Other Responses routes remain explicitly storeless.
1132
+ ...(azureResponses ? {} : { store: false }),
1133
+ ...(options.promptCacheKey
1134
+ ? { providerData: { prompt_cache_key: options.promptCacheKey } }
1135
+ : {}),
1136
+ },
1137
+ tools: [],
1138
+ toolsExplicitlyProvided: true,
1139
+ outputType: "text",
1140
+ handoffs: [],
1141
+ tracing: false,
1142
+ ...(options.signal ? { signal: options.signal } : {}),
1143
+ };
1088
1144
  let response: unknown;
1089
1145
  try {
1090
1146
  response = await new CompactionResponsesModel(client, model, provider).fetchResponse(request);
@@ -3630,6 +3686,14 @@ function buildAgentCapabilitiesFromComposition(
3630
3686
  const caps: ReturnType<typeof Capabilities.default> = [
3631
3687
  filesystemCapability,
3632
3688
  shell({
3689
+ // The SDK normally renders every shell error into model-facing text.
3690
+ // Preserve that behavior except for client-side, pre-dispatch Modal
3691
+ // readiness proof, which reaches bounded same-turn recovery.
3692
+ execCommandErrorFunction: (_context, error) => {
3693
+ if (isModalTaskExecStartPreDispatchUnavailableError(error)) throw error;
3694
+ const details = error instanceof Error ? error.toString() : String(error);
3695
+ return `An error occurred while running the tool. Please try again. Error: ${details}`;
3696
+ },
3633
3697
  ...(toolCancellation ? {} : { configureTools: withExecOpCorrelation }),
3634
3698
  }),
3635
3699
  ];