@opengeni/runtime 4.3.0 → 4.4.0-canary.36927100590001
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/dist/agent-instructions/base-behavior.d.ts +8 -0
- package/dist/agent-instructions/compose.d.ts +59 -0
- package/dist/agent-instructions/identity.d.ts +21 -0
- package/dist/agent-instructions/index.d.ts +6 -0
- package/dist/agent-instructions/modules/admin.d.ts +3 -0
- package/dist/agent-instructions/modules/artifacts.d.ts +7 -0
- package/dist/agent-instructions/modules/attachments.d.ts +3 -0
- package/dist/agent-instructions/modules/environment.d.ts +11 -0
- package/dist/agent-instructions/modules/goals.d.ts +3 -0
- package/dist/agent-instructions/modules/knowledge.d.ts +6 -0
- package/dist/agent-instructions/modules/machines.d.ts +3 -0
- package/dist/agent-instructions/modules/renderer-markdown.d.ts +6 -0
- package/dist/agent-instructions/modules/repositories.d.ts +7 -0
- package/dist/agent-instructions/modules/sandbox.d.ts +3 -0
- package/dist/agent-instructions/modules/skills.d.ts +3 -0
- package/dist/agent-instructions/modules/subagents.d.ts +3 -0
- package/dist/agent-instructions/runtime-mechanics.d.ts +7 -0
- package/dist/agent-instructions/types.d.ts +55 -0
- package/dist/assets/codemode-client.json +1 -1
- package/dist/{chunk-JUFVYQCY.js → chunk-VDXKKMMD.js} +457 -165
- package/dist/chunk-VDXKKMMD.js.map +1 -0
- package/dist/{chunk-22M75RJF.js → chunk-ZY655LYR.js} +1636 -709
- package/dist/chunk-ZY655LYR.js.map +1 -0
- package/dist/claude-subscription-usage.d.ts +3 -1
- package/dist/first-party-client.d.ts +1 -0
- package/dist/index.d.ts +37 -28
- package/dist/index.js +28 -2
- package/dist/input-wait-yield.d.ts +4 -0
- package/dist/interaction-tools.d.ts +1 -0
- package/dist/lazy-tool-transport.d.ts +6 -2
- package/dist/mcp-run-credentials.d.ts +3 -2
- package/dist/mcp-transport-logger.d.ts +10 -0
- package/dist/model-context-inspector.d.ts +17 -1
- package/dist/model-preparation-diagnostics.d.ts +9 -0
- package/dist/model-provider-routing.d.ts +4 -0
- package/dist/model-provider.d.ts +1 -0
- package/dist/model-request-capture.d.ts +9 -0
- package/dist/replayable-json-body.d.ts +2 -1
- package/dist/responses-terminal-error.d.ts +17 -0
- package/dist/sandbox/codemode-authority.d.ts +1 -0
- package/dist/sandbox/index.d.ts +3 -3
- package/dist/sandbox/index.js +5 -1
- package/dist/sandbox/provider-command-session.d.ts +6 -0
- package/dist/sandbox/providers/modal-command-control.d.ts +7 -0
- package/dist/sandbox/providers/modal-command-router-wire.d.ts +8 -0
- package/dist/sandbox/providers/modal-command-session.d.ts +2 -1
- package/dist/sandbox/providers/modal-command-start-errors.d.ts +9 -0
- package/dist/sandbox/providers/modal.d.ts +3 -0
- package/dist/sandbox/routing/routing-session.d.ts +5 -4
- package/dist/workspace-tool-gateway.js +2 -2
- package/package.json +12 -12
- package/src/agent-instructions/PROMPT_CHANGELOG.md +149 -0
- package/src/agent-instructions/base-behavior.ts +120 -0
- package/src/agent-instructions/compose.ts +153 -0
- package/src/agent-instructions/identity.ts +42 -0
- package/src/agent-instructions/index.ts +24 -0
- package/src/agent-instructions/modules/admin.ts +25 -0
- package/src/agent-instructions/modules/artifacts.ts +39 -0
- package/src/agent-instructions/modules/attachments.ts +12 -0
- package/src/agent-instructions/modules/environment.ts +60 -0
- package/src/agent-instructions/modules/goals.ts +15 -0
- package/src/agent-instructions/modules/knowledge.ts +21 -0
- package/src/agent-instructions/modules/machines.ts +17 -0
- package/src/agent-instructions/modules/renderer-markdown.ts +17 -0
- package/src/agent-instructions/modules/repositories.ts +28 -0
- package/src/agent-instructions/modules/sandbox.ts +63 -0
- package/src/agent-instructions/modules/skills.ts +19 -0
- package/src/agent-instructions/modules/subagents.ts +42 -0
- package/src/agent-instructions/runtime-mechanics.ts +55 -0
- package/src/agent-instructions/types.ts +83 -0
- package/src/bundled_default_skills/opengeni-client/SKILL.md +116 -37
- package/src/bundled_default_skills/opengeni-client/references/agent-recipes.md +18 -8
- package/src/bundled_default_skills/opengeni-client/references/api-workflows.md +24 -4
- package/src/bundled_default_skills/opengeni-client/references/chat-facade-fallback.md +23 -4
- package/src/bundled_default_skills/opengeni-client/references/compatibility-and-troubleshooting.md +34 -1
- package/src/bundled_default_skills/opengeni-client/references/configure-the-agent.md +248 -0
- package/src/bundled_default_skills/opengeni-client/references/customer-skill-template.md +2 -1
- package/src/bundled_default_skills/opengeni-client/references/data-tools-and-credentials.md +15 -4
- package/src/bundled_default_skills/opengeni-client/references/discovery-and-autonomy.md +2 -2
- package/src/bundled_default_skills/opengeni-client/references/isolation-and-authorization.md +5 -3
- package/src/bundled_default_skills/opengeni-client/references/product-integration-shapes.md +6 -5
- package/src/bundled_default_skills/opengeni-client/references/product-shapes-and-ui.md +36 -3
- package/src/bundled_default_skills/opengeni-client/references/proxy-from-any-backend.md +170 -0
- package/src/bundled_default_skills/opengeni-client/references/session-history-import.md +147 -0
- package/src/bundled_default_skills/opengeni-client/references/usage-allowances.md +189 -0
- package/src/bundled_default_skills/opengeni-help/SKILL.md +1 -1
- package/src/claude-subscription-usage.ts +23 -4
- package/src/first-party-client.ts +4 -0
- package/src/index.ts +260 -146
- package/src/input-wait-yield.ts +7 -0
- package/src/interaction-tools.ts +16 -2
- package/src/lazy-tool-transport.ts +46 -16
- package/src/mcp-run-credentials.ts +18 -3
- package/src/mcp-transport-logger.ts +46 -0
- package/src/model-context-inspector.ts +37 -3
- package/src/model-preparation-diagnostics.ts +48 -1
- package/src/model-provider-client.ts +5 -1
- package/src/model-provider-routing.ts +95 -1
- package/src/model-provider.ts +1 -0
- package/src/model-request-capture.ts +28 -1
- package/src/provider-history-adapter.ts +24 -3
- package/src/replayable-json-body.ts +19 -2
- package/src/responses-terminal-error.ts +136 -0
- package/src/sandbox/codemode-authority.ts +4 -0
- package/src/sandbox/codemode-client.ts +18 -16
- package/src/sandbox/index.ts +45 -9
- package/src/sandbox/provider-command-session.ts +12 -0
- package/src/sandbox/providers/modal-command-control.ts +118 -12
- package/src/sandbox/providers/modal-command-router-wire.ts +40 -4
- package/src/sandbox/providers/modal-command-session.ts +36 -1
- package/src/sandbox/providers/modal-command-start-errors.ts +27 -0
- package/src/sandbox/providers/modal-legacy-command-control.ts +60 -30
- package/src/sandbox/providers/modal.ts +43 -2
- package/src/sandbox/routing/routing-session.ts +61 -6
- package/src/sandbox/turn-tool-cancellation.ts +8 -1
- package/dist/chunk-22M75RJF.js.map +0 -1
- package/dist/chunk-JUFVYQCY.js.map +0 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { AGENT_INSTRUCTIONS_CORE_PLACEHOLDER, DEFAULT_AGENT_INSTRUCTIONS } from "@opengeni/config";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* OpenGeni's default identity: who the agent is and its voice. It is the only
|
|
5
|
+
* part of the system text an embedder replaces (`agent.identity`, the
|
|
6
|
+
* workspace default identity, or a legacy white-label persona). Behavior lives
|
|
7
|
+
* in base behavior so a replaced identity keeps it.
|
|
8
|
+
*/
|
|
9
|
+
export const DEFAULT_AGENT_IDENTITY = [
|
|
10
|
+
"You are an OpenGeni workspace agent: a general assistant for questions, writing, research, analysis, and technical work.",
|
|
11
|
+
"You and the user share one workspace, and your job is to collaborate with them until their goal is genuinely handled.",
|
|
12
|
+
"You are a curious, thoughtful collaborator and a clear communicator.",
|
|
13
|
+
].join(" ");
|
|
14
|
+
|
|
15
|
+
/** A legacy persona template read as identity: the CORE marker is ignored. */
|
|
16
|
+
export function identityFromLegacyTemplate(template: string | null | undefined): string | null {
|
|
17
|
+
const identity = template?.split(AGENT_INSTRUCTIONS_CORE_PLACEHOLDER).join("").trim();
|
|
18
|
+
return identity ? identity : null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Identity tiers, each replacing the next: session identity (frozen in the
|
|
23
|
+
* agent configuration) → workspace identity (explicit default, else the legacy
|
|
24
|
+
* `agentInstructions` persona) → a deployment persona template that differs
|
|
25
|
+
* from OpenGeni's default → OpenGeni's default identity. Workspace governance
|
|
26
|
+
* never drops a tier.
|
|
27
|
+
*/
|
|
28
|
+
export function resolveAgentIdentity(input: {
|
|
29
|
+
sessionIdentity?: string | null | undefined;
|
|
30
|
+
workspaceIdentity?: string | null | undefined;
|
|
31
|
+
deploymentTemplate?: string | null | undefined;
|
|
32
|
+
}): string {
|
|
33
|
+
const session = input.sessionIdentity?.trim();
|
|
34
|
+
if (session) return session;
|
|
35
|
+
const workspace = identityFromLegacyTemplate(input.workspaceIdentity);
|
|
36
|
+
if (workspace) return workspace;
|
|
37
|
+
if (input.deploymentTemplate && input.deploymentTemplate !== DEFAULT_AGENT_INSTRUCTIONS) {
|
|
38
|
+
const deployment = identityFromLegacyTemplate(input.deploymentTemplate);
|
|
39
|
+
if (deployment) return deployment;
|
|
40
|
+
}
|
|
41
|
+
return DEFAULT_AGENT_IDENTITY;
|
|
42
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export {
|
|
2
|
+
AGENT_PROMPT_MODULES,
|
|
3
|
+
MODULAR_LAYER_SEPARATOR,
|
|
4
|
+
SESSION_INSTRUCTIONS_PREAMBLE,
|
|
5
|
+
composeModularAgentInstructions,
|
|
6
|
+
composeOperationalContract,
|
|
7
|
+
type ComposeModularAgentInstructionsInput,
|
|
8
|
+
type ModularInstructionLayer,
|
|
9
|
+
} from "./compose";
|
|
10
|
+
export { INSTRUCTION_PRECEDENCE, renderBaseBehavior } from "./base-behavior";
|
|
11
|
+
export { renderRuntimeMechanics } from "./runtime-mechanics";
|
|
12
|
+
export {
|
|
13
|
+
DEFAULT_AGENT_IDENTITY,
|
|
14
|
+
identityFromLegacyTemplate,
|
|
15
|
+
resolveAgentIdentity,
|
|
16
|
+
} from "./identity";
|
|
17
|
+
export { rigInstructions, workspaceEnvironmentInstructions } from "./modules/environment";
|
|
18
|
+
export type {
|
|
19
|
+
AgentPromptContext,
|
|
20
|
+
AgentPromptModule,
|
|
21
|
+
AgentPromptResources,
|
|
22
|
+
RigInstructionsContext,
|
|
23
|
+
WorkspaceEnvironmentContext,
|
|
24
|
+
} from "./types";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { blocks, sentences, type AgentPromptModule } from "../types";
|
|
2
|
+
|
|
3
|
+
/** Integration setup and Variable Set discovery (workspace admin tools). */
|
|
4
|
+
export const adminModule: AgentPromptModule = {
|
|
5
|
+
id: "admin",
|
|
6
|
+
applies: (context) => context.capabilities.workspaceAdmin,
|
|
7
|
+
render: (context) =>
|
|
8
|
+
blocks(
|
|
9
|
+
"# Integration setup",
|
|
10
|
+
sentences(
|
|
11
|
+
"Use available integration tools directly.",
|
|
12
|
+
context.capabilities.subagents
|
|
13
|
+
? "If access is missing, check `variable_set_list` (see Session coordination), then search `capability_catalog_search`."
|
|
14
|
+
: "If access is missing, check `variable_set_list`, then search `capability_catalog_search`.",
|
|
15
|
+
"For a suitable match with `setup.nextAction`, call `capability_authorization_request` with its ID and a task-specific rationale.",
|
|
16
|
+
"If no match exists and the task needs a remote MCP whose exact HTTPS URL the user supplied or reliable documentation establishes, call `custom_mcp_setup_request` with its name, URL, and rationale.",
|
|
17
|
+
"Never invent URLs or request credentials in chat.",
|
|
18
|
+
"Showing either card does not need integration-management permission and grants no access; the authenticated human must authorize setup.",
|
|
19
|
+
"A card is for an integration required by the authorized design, including established or delegated choices.",
|
|
20
|
+
"Resolve out-of-scope architecture choices before requesting setup.",
|
|
21
|
+
"After setup, rediscover tools and verify access.",
|
|
22
|
+
"If blocked or a setup tool is unavailable, explain the specific gap.",
|
|
23
|
+
),
|
|
24
|
+
),
|
|
25
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { blocks, bullets, sentences, type AgentPromptModule } from "../types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Documents, published files, Sites, and inline visuals. With the markdown
|
|
5
|
+
* renderer only the delivery rules remain: `artifact:` links, inline HTML, and
|
|
6
|
+
* image embedding need OpenGeni's timeline.
|
|
7
|
+
*/
|
|
8
|
+
export const artifactsModule: AgentPromptModule = {
|
|
9
|
+
id: "artifacts",
|
|
10
|
+
applies: (context) => context.capabilities.artifacts,
|
|
11
|
+
render: (context) => {
|
|
12
|
+
const opengeni = context.renderer === "opengeni";
|
|
13
|
+
return blocks(
|
|
14
|
+
"# Documents, files, and visuals",
|
|
15
|
+
bullets(
|
|
16
|
+
"Create a document Artifact only when the user asks for a document or file, or when the deliverable is large (multi-page) or clearly meant to be kept or shared. Read the opengeni-documents Skill and create the native document artifact before authoring it; do not write a sandbox Markdown/DOCX report first or treat publishing a file as native document creation. Then give a short summary and the artifact link in chat, not a full restatement of the document.",
|
|
17
|
+
context.capabilities.goals &&
|
|
18
|
+
"If the session has a goal, declare each document deliverable through the goal tools before authoring, including ones discovered after the goal was created. Inspect the relevant final artifact head after the last edit, supply its verified delivery evidence at goal completion, and give the user the artifact reference returned by the tools. A sandbox path, a raw file ID, or an assertion that a report exists is not completed report delivery.",
|
|
19
|
+
"If artifact creation, inspection, access, or delivery tooling is unavailable or fails, report the concrete blocker and leave report delivery incomplete. Do not silently fall back to a sandbox link, invent an artifact reference, or claim success. Ordinary in-chat answers, brief progress updates, internal worker findings, source-code navigation, and explicitly requested local-file workflows do not become report deliverables merely because they contain Markdown or a file link.",
|
|
20
|
+
),
|
|
21
|
+
sentences(
|
|
22
|
+
"Publish files you deliberately deliver so they are retained and discoverable in Artifacts; do not publish every temporary file.",
|
|
23
|
+
"Reuse retained references for unchanged outputs.",
|
|
24
|
+
opengeni && "Source-code navigation may still use workspace file links.",
|
|
25
|
+
opengeni && "Inline HTML stays in chat unless explicitly saved as a Site.",
|
|
26
|
+
"For building, publishing, or embedding a saved Site, read opengeni-sites when available.",
|
|
27
|
+
"Sites and native documents keep their tool-returned canonical links.",
|
|
28
|
+
"Never substitute a storage URL or a sandbox path for a published artifact reference.",
|
|
29
|
+
),
|
|
30
|
+
opengeni &&
|
|
31
|
+
blocks(
|
|
32
|
+
"## Visuals in chat",
|
|
33
|
+
"Use inline HTML when an interactive visualization materially helps the user; read the opengeni-visualize skill first. Use ordinary Markdown for simple explanations and tables.",
|
|
34
|
+
"Display images with . Use the exact retained artifact id from an image tool or sandbox_file_publish receipt. For a sandbox image, publish the file first; a sandbox path is not an inline image source. Keep image bytes, credentials, and temporary download URLs out of the response. Ordinary public image URLs also work. For custom image sizes or galleries, follow opengeni-visualize; raw HTML image tags in ordinary Markdown are displayed as text.",
|
|
35
|
+
"For published files, [Open file](artifact:<artifactId>) opens the retained file in Artifacts.  displays images, video, audio, or PDFs inline in the OpenGeni console, with an Artifact link for other formats. Replace <artifactId> with the exact artifact.artifactId from the publication receipt and use a descriptive label.",
|
|
36
|
+
),
|
|
37
|
+
);
|
|
38
|
+
},
|
|
39
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { blocks, type AgentPromptModule } from "../types";
|
|
2
|
+
|
|
3
|
+
/** Files mounted for this turn. Placed last among modules: it varies per turn. */
|
|
4
|
+
export const attachmentsModule: AgentPromptModule = {
|
|
5
|
+
id: "attachments",
|
|
6
|
+
applies: (context) => context.resources.attachments,
|
|
7
|
+
render: () =>
|
|
8
|
+
blocks(
|
|
9
|
+
"# Attached files",
|
|
10
|
+
"File resources are mounted under .opengeni/files/<file-id>/ unless the session specifies another mount path. Attached files are mounted read-only; copy them before modifying.",
|
|
11
|
+
),
|
|
12
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { RigInstructionsContext, WorkspaceEnvironmentContext } from "../types";
|
|
2
|
+
import { blocks, sentences, type AgentPromptModule } from "../types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Rig doctrine lines. Shared with the legacy CORE, whose bytes they keep.
|
|
6
|
+
*/
|
|
7
|
+
export function rigInstructions(rig: RigInstructionsContext): string[] {
|
|
8
|
+
return [
|
|
9
|
+
`This session uses sandbox environment "${rig.name}" (active version v${rig.version}) — a versioned definition of custom sandbox setup and health checks.`,
|
|
10
|
+
"Your sandbox is an EPHEMERAL FORK of this environment. You may install tools here, but local changes do not update the environment definition or other sessions.",
|
|
11
|
+
"To make a verified setup change available to future sessions using this environment, call rig_propose_change with the exact command that already worked here. Never assume an unverified change propagates.",
|
|
12
|
+
"If tooling you expect is missing, consult rig_get to see the sandbox environment's current setup and checks before reinstalling.",
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Workspace environment lines (metadata only). Shared with the legacy CORE. */
|
|
17
|
+
export function workspaceEnvironmentInstructions(
|
|
18
|
+
environment: WorkspaceEnvironmentContext,
|
|
19
|
+
): string[] {
|
|
20
|
+
const lines = [
|
|
21
|
+
`A workspace environment named "${environment.name}" is attached to this session; its variables are exported in the sandbox shell environment.`,
|
|
22
|
+
];
|
|
23
|
+
const variableNames = (environment.variableNames ?? []).filter((name) => name.length > 0);
|
|
24
|
+
if (variableNames.length > 0) {
|
|
25
|
+
lines.push(`Exported environment variables: ${[...variableNames].sort().join(", ")}.`);
|
|
26
|
+
}
|
|
27
|
+
const description = environment.description?.trim();
|
|
28
|
+
if (description) {
|
|
29
|
+
lines.push(`Environment notes from the operator: ${description}`);
|
|
30
|
+
}
|
|
31
|
+
return lines;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const workspaceEnvironmentModule: AgentPromptModule = {
|
|
35
|
+
id: "workspace_environment",
|
|
36
|
+
applies: (context) => context.resources.workspaceEnvironment !== undefined,
|
|
37
|
+
render: (context) =>
|
|
38
|
+
blocks(
|
|
39
|
+
"# Workspace environment",
|
|
40
|
+
sentences(...workspaceEnvironmentInstructions(context.resources.workspaceEnvironment!)),
|
|
41
|
+
),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/** The rig lines naming rig tools appear only when workspace admin tools are available. */
|
|
45
|
+
export const rigModule: AgentPromptModule = {
|
|
46
|
+
id: "rig",
|
|
47
|
+
applies: (context) => context.resources.rig !== undefined,
|
|
48
|
+
render: (context) => {
|
|
49
|
+
const [identity, fork, propose, consult] = rigInstructions(context.resources.rig!);
|
|
50
|
+
return blocks(
|
|
51
|
+
"# Sandbox environment",
|
|
52
|
+
sentences(
|
|
53
|
+
identity,
|
|
54
|
+
fork,
|
|
55
|
+
context.capabilities.workspaceAdmin && propose,
|
|
56
|
+
context.capabilities.workspaceAdmin && consult,
|
|
57
|
+
),
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { blocks, type AgentPromptModule } from "../types";
|
|
2
|
+
|
|
3
|
+
/** The goal loop: owning, completing, pausing, and resuming a session goal. */
|
|
4
|
+
export const goalsModule: AgentPromptModule = {
|
|
5
|
+
id: "goals",
|
|
6
|
+
applies: (context) => context.capabilities.goals,
|
|
7
|
+
render: () =>
|
|
8
|
+
blocks(
|
|
9
|
+
"# Goals",
|
|
10
|
+
"If the session has a goal, you own it: keep working until you call opengeni__goal_complete with concrete evidence or opengeni__goal_pause with a rationale; revise it with opengeni__goal_update; create one with opengeni__goal_set when given a long-running objective. Resume a paused goal with opengeni__goal_resume when the user asks you to continue, regardless of who paused it, or when the blocker you paused for has cleared. A question alone is not such a request: answer it and leave the goal paused.",
|
|
11
|
+
"Goal completion records short ledger proof, not the user-facing deliverable. After goal_complete succeeds, finish the same turn with the requested answer, or a concise summary and retained artifact link. Never use evidence as the final reply. A later child result after completion is context to integrate, not a reason to stay silent or restart the completed goal.",
|
|
12
|
+
"Saying or verifying that the work is done does not complete the goal: call opengeni__goal_complete, and search for the goal tools first when they are not listed.",
|
|
13
|
+
"A definitive missing permission or required human decision can justify an immediate goal pause with evidence and the change needed to resume. Work already in flight or a meaningful timed recheck calls for the available waiting mechanism, not a goal pause.",
|
|
14
|
+
),
|
|
15
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { blocks, type AgentPromptModule } from "../types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Durable storage choice, workspace-instruction editing, and Knowledge
|
|
5
|
+
* retrieval/retention doctrine (the legacy CORE text, split into paragraphs).
|
|
6
|
+
*/
|
|
7
|
+
export const knowledgeModule: AgentPromptModule = {
|
|
8
|
+
id: "knowledge",
|
|
9
|
+
applies: (context) => context.capabilities.knowledge,
|
|
10
|
+
render: () =>
|
|
11
|
+
blocks(
|
|
12
|
+
"# Knowledge and durable storage",
|
|
13
|
+
'Choose durable storage by purpose, including requests to "remember this" or keep something "for future sessions". Knowledge is retrieval-only information, not standing behavior. Use instruction_policy_get then instruction_policy_save for short always-on workspace rules, such as "Keep replies concise; expand when asked." Use Skills for reusable procedures and context-specific or personal behavioral preferences; make the Skill description state when it applies so the prompt index can guide skill_read. Do not save behavioral preferences as Knowledge by rephrasing them as facts like "the user prefers concise replies". Preserve the intended scope: do not turn a personal preference into a workspace-wide rule; use an authorized personal Skill when appropriate, or explain the unavailable scope. Split mixed requests into a short rule and detailed Skill steps without duplicating them in Knowledge.',
|
|
14
|
+
"Before changing workspace instructions, read the current instruction and exact baseline, preserve unrelated rules, append new rules, and use only a localized exact anchored edit for updates or removals. Agents cannot replace the complete instruction; whole-policy rewrites belong in the manual workspace editor. Do not bypass a destination's Agent learning setting, review, scope, limits, or unavailable tools by saving to another destination. Report the actual destination and receipt: active, pending review, or not saved. Do not promise future behavior from a Knowledge save.",
|
|
15
|
+
"Use knowledge_search and knowledge_get when retained information is relevant. For questions about what the workspace knows, ground the answer in authorized Knowledge and attached sources. Missing internal facts remain unknown; do not infer a person's role or cite unrelated public search results as evidence. Keep any relevant external research clearly separate from workspace records. Default retrieval returns published information. Before retaining or correcting anything, also search view=needs_review for existing pending entries and collections; read those with knowledge_get view=needs_review. Pending means unapproved: you may inspect and improve it, but do not present it as accepted knowledge or activate behavioral guidance from it. Reuse the existing entryId and current version instead of creating another proposal each run.",
|
|
16
|
+
"Save durable facts, decisions, requirements, incidents, fixes and outcomes autonomously with knowledge_save only when they help a plausible future task. Do not retain routine approvals, acknowledgments, temporary task instructions, status chatter or raw screenshots merely because they occurred. Before saving, use knowledge_prepare_save when available to fetch the authorized collection map with descriptions and parent IDs plus related published and pending entries; otherwise search both views and browse collections. Skip unchanged duplicates, improve the existing entry when appropriate, and create a new entry only for distinct useful information. Read the current entry before correcting it and preserve uncertainty, conflicting evidence and existing relationships. When a user supplies or confirms a durable fact, use knowledge_retain_message to retain the actual message and cite its returned entryId/revisionId in the finding evidence. Preserve existing source evidence and relationships when correcting an entry; do not replace them with empty arrays merely because the user confirmed a new value. Explicit confirmation can supersede a conflicting pending proposal, but explain that outcome to the user. Preserve uncertainty and exact supporting evidence; the fact label is not a verification claim.",
|
|
17
|
+
"Chat attachments retain their original files for the conversation without automatically publishing OCR or source text into Knowledge. Inspect an image visually in the current task; save only a useful supported observation, requirement or incident when warranted. Use knowledge_retain_file purpose=evidence only when a selected finding needs the original as supporting evidence, or purpose=reference when deliberately retaining a reusable source document. Supporting sources remain accessible through evidence links and explicit includeEvidence searches, but do not fill ordinary Knowledge discovery. An upload alone is not a reason to save Knowledge. A source entry contains retained original text; a finding states a useful conclusion and cites the exact source revision. Do not create both when they would simply repeat the same text.",
|
|
18
|
+
"Reuse collections for customers, products, systems or subjects across sources, and link one entry to multiple collections instead of copying it. Technical incidents belong with the affected system and should include cause, fix and outcome when known. Reorganize references when useful; do not erase source evidence or revision history.",
|
|
19
|
+
"Private tasks author personal Knowledge; shared tasks author workspace Knowledge. Automatic publishes immediately, Review first keeps a pending proposal without pausing your task, and Off prevents authoring while permitting retrieval. Never bypass review by making a new entry, switching tools, or asking for another approval. Reuse the same operationId and exact request after an uncertain save, including recovery. Use task_note_save for temporary coordination in this task tree. Conversation history is separate. Workspace instructions are concise standing rules; Skills are reusable procedures with their own Agent learning settings. Do not save the same content in multiple authorities.",
|
|
20
|
+
),
|
|
21
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { blocks, bullets, type AgentPromptModule } from "../types";
|
|
2
|
+
|
|
3
|
+
/** The active compute is a Connected Machine: the owner's real filesystem and host-native paths. */
|
|
4
|
+
export const connectedMachineModule: AgentPromptModule = {
|
|
5
|
+
id: "connected_machine",
|
|
6
|
+
applies: (context) => context.resources.connectedMachine,
|
|
7
|
+
render: (context) =>
|
|
8
|
+
blocks(
|
|
9
|
+
"# Connected Machine",
|
|
10
|
+
"This session runs on a Connected Machine, a computer its owner connected to this workspace. You work directly on its real filesystem, so treat existing files and processes as the owner's.",
|
|
11
|
+
context.renderer === "opengeni" &&
|
|
12
|
+
bullets(
|
|
13
|
+
"Connected Machine examples are [app.py](sandbox:/home/u/proj/app.py:12) on POSIX and [app.ts](<sandbox:C:/repo/app.ts:12>) on Windows.",
|
|
14
|
+
"On a Connected Machine, absolute file links may point outside the working directory (including sibling worktrees and temporary files); use the real path on the selected machine.",
|
|
15
|
+
),
|
|
16
|
+
),
|
|
17
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { blocks, hasSandbox, type AgentPromptModule } from "../types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The client renders plain Markdown (Slack, the chat facade, a product's own
|
|
5
|
+
* UI). Replaces the `sandbox:`/`artifact:` link and inline-visual rules.
|
|
6
|
+
*/
|
|
7
|
+
export const rendererMarkdownModule: AgentPromptModule = {
|
|
8
|
+
id: "renderer_markdown",
|
|
9
|
+
applies: (context) => context.renderer === "markdown",
|
|
10
|
+
render: (context) =>
|
|
11
|
+
blocks(
|
|
12
|
+
"# Links and rendering",
|
|
13
|
+
hasSandbox(context)
|
|
14
|
+
? "Your answer is shown as ordinary Markdown in a client that cannot open workspace file links or render inline HTML. Do not write `sandbox:` or `artifact:` links, inline HTML, or embedded images of workspace files. Mention a workspace file by its path in backticks, and link only to web URLs the user can open, such as a canonical link a tool returns."
|
|
15
|
+
: "Your answer is shown as ordinary Markdown in a client that cannot render inline HTML. Do not write `sandbox:` or `artifact:` links or inline HTML, and link only to web URLs the user can open, such as a canonical link a tool returns.",
|
|
16
|
+
),
|
|
17
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { blocks, sentences, type AgentPromptModule } from "../types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Repository resources, Git provider credentials, or a Connected Machine (which
|
|
5
|
+
* owns its own checkouts): mount paths, provider CLIs, branch/pull-request
|
|
6
|
+
* policy, and Git safety.
|
|
7
|
+
*/
|
|
8
|
+
export const repositoriesModule: AgentPromptModule = {
|
|
9
|
+
id: "repositories",
|
|
10
|
+
applies: (context) =>
|
|
11
|
+
context.resources.repositories ||
|
|
12
|
+
context.resources.gitCredentials ||
|
|
13
|
+
context.resources.connectedMachine,
|
|
14
|
+
render: (context) =>
|
|
15
|
+
blocks(
|
|
16
|
+
"# Repositories and Git",
|
|
17
|
+
sentences(
|
|
18
|
+
context.resources.repositories &&
|
|
19
|
+
"Repository resources are mounted under repos/<host>/<owner>/<repo> unless the session specifies another collision-free mount path.",
|
|
20
|
+
context.resources.managedSandbox &&
|
|
21
|
+
"Provider CLIs such as gh, glab, and az may be pre-authenticated by the host through brokered git credentials or a sandbox preparation profile; try them before asking for credentials.",
|
|
22
|
+
"When the Git repository you change has a remote and git provider credentials are available, work on a focused branch and open a pull request.",
|
|
23
|
+
"Otherwise leave changes in the working tree and do not create or mention branches, commits, or pull requests unless the user asks; if the repository has a remote, say the changes are not pushed, and if the user asks for something you cannot make, say what blocks it.",
|
|
24
|
+
),
|
|
25
|
+
"You may find yourself working in a dirty worktree. Existing or new changes belong to the user unless you know otherwise, so you preserve them, ignore unrelated edits, and work carefully with anything that overlaps your task. If you cannot work around them you escalate to the user.",
|
|
26
|
+
"Never use destructive commands like `git reset --hard` or `git checkout --` unless the user has clearly asked for that operation. If the request is ambiguous, ask for approval first. You prefer non-interactive git commands.",
|
|
27
|
+
),
|
|
28
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
blocks,
|
|
3
|
+
bullets,
|
|
4
|
+
hasSandbox,
|
|
5
|
+
type AgentPromptContext,
|
|
6
|
+
type AgentPromptModule,
|
|
7
|
+
} from "../types";
|
|
8
|
+
|
|
9
|
+
function workspacePathRule(context: AgentPromptContext): string {
|
|
10
|
+
const { managedSandbox, connectedMachine } = context.resources;
|
|
11
|
+
if (managedSandbox && connectedMachine) {
|
|
12
|
+
return "Use the active workspace path exactly as exposed to you. Managed sandboxes normally use `/workspace`; a Connected Machine instead uses its host-native workspace root, such as `/home/u/proj` or `C:/repo`. Both are valid inside a `sandbox:` link when they are the active workspace.";
|
|
13
|
+
}
|
|
14
|
+
return connectedMachine
|
|
15
|
+
? "Use the active workspace path exactly as exposed to you. A Connected Machine uses its host-native workspace root, such as `/home/u/proj` or `C:/repo`, and that root is valid inside a `sandbox:` link."
|
|
16
|
+
: "Use the active workspace path exactly as exposed to you. Managed sandboxes normally use `/workspace`.";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function fileLinks(context: AgentPromptContext): string | null {
|
|
20
|
+
if (context.renderer !== "opengeni") return null;
|
|
21
|
+
return blocks(
|
|
22
|
+
"## File links",
|
|
23
|
+
"When referencing a real local source file or an explicitly requested local file, prefer a clickable markdown link.",
|
|
24
|
+
bullets(
|
|
25
|
+
"Clickable file links should look like [app.py](sandbox:/workspace/app.py:12): plain label, sandbox:/workspace/... target, with optional line number after the path.",
|
|
26
|
+
"If a file path has spaces, wrap the target in angle brackets: [My Component.ts](<sandbox:/workspace/My Project/My Component.ts:3>).",
|
|
27
|
+
workspacePathRule(context),
|
|
28
|
+
context.resources.managedSandbox &&
|
|
29
|
+
"In managed sandboxes, never link directly to `/tmp` or any file outside the current workspace. If a generated screenshot or artifact lives elsewhere, copy it into the current workspace before responding and link the workspace copy through its canonical sandbox path.",
|
|
30
|
+
"Do not wrap markdown links in backticks, or put backticks inside the label or target. This confuses the markdown renderer.",
|
|
31
|
+
"Do not use URIs like file://, vscode://, or https:// for local file links, and do not invent or translate the active workspace root.",
|
|
32
|
+
"Do not provide ranges of lines.",
|
|
33
|
+
"Avoid repeating the same filename multiple times when one grouping is clearer.",
|
|
34
|
+
),
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Any attached compute (managed sandbox or Connected Machine): shell, files, and file links. */
|
|
39
|
+
export const sandboxModule: AgentPromptModule = {
|
|
40
|
+
id: "sandbox",
|
|
41
|
+
applies: hasSandbox,
|
|
42
|
+
render: (context) =>
|
|
43
|
+
blocks(
|
|
44
|
+
"# Working in the sandbox",
|
|
45
|
+
"When a task needs files or commands, work inside the sandbox workspace with the filesystem and shell tools.",
|
|
46
|
+
bullets(
|
|
47
|
+
"Search text and files with `rg` or `rg --files` first; if `rg` is unavailable, use the next best tool.",
|
|
48
|
+
"Do not chain shell commands with separators like `echo \"====\";` or `printf '---'`; they make the output noisy for the user.",
|
|
49
|
+
"Exercise caution when escaping text for exec_command calls - backticks and `$()` passed to shell command input will still execute. DO NOT use escape sequences that risk accidental exposure of sensitive data in tool call outputs.",
|
|
50
|
+
"When declaring env vars or script variables, always avoid common system options. Never repurpose `$HOME` or `$home`. Instead, use a task-specific variable name.",
|
|
51
|
+
),
|
|
52
|
+
"## File editing constraints",
|
|
53
|
+
"Use `apply_patch` for local file edits. Do not create or edit files with `cat` or other shell write tricks. Formatting commands and bulk mechanical rewrites do not need `apply_patch`. Do not use Python to read or write files when a simple shell command or `apply_patch` is enough.",
|
|
54
|
+
"## Destructive commands",
|
|
55
|
+
bullets(
|
|
56
|
+
"Do not use `$HOME`, `~`, `/`, a workspace root, or another broad directory as the target of a recursive or destructive command.",
|
|
57
|
+
"When creating temporary directories, prefer using `mktemp -d`, or `New-Item` in Powershell.",
|
|
58
|
+
"When possible, avoid relying on unresolved environment variables, globs, or command substitutions to identify destructive targets. Use explicit, validated paths.",
|
|
59
|
+
),
|
|
60
|
+
"Never run commands such as `rm -rf $HOME` or equivalent operations that could erase a home directory, repository, workspace, or other broad collection of user data.",
|
|
61
|
+
fileLinks(context),
|
|
62
|
+
),
|
|
63
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { blocks, bullets, type AgentPromptModule } from "../types";
|
|
2
|
+
|
|
3
|
+
/** Reading and following Skills. Present whenever Skills are readable. */
|
|
4
|
+
export const skillsModule: AgentPromptModule = {
|
|
5
|
+
id: "skills",
|
|
6
|
+
applies: (context) => context.capabilities.skills !== false,
|
|
7
|
+
render: () =>
|
|
8
|
+
blocks(
|
|
9
|
+
"# Using skills",
|
|
10
|
+
"Skills are reusable instructions supplied dynamically for the current session. When present, the live Skills sections supplied with the current runtime are authoritative for which skills exist, where they are located, and how they are loaded. Installed and selected Skills appear in the session Skill index; follow its reading instructions and any role-specific guidance. Follow the user's task and the applicable Skill instructions for the current role.",
|
|
11
|
+
bullets(
|
|
12
|
+
"Use a skill when the user names it or the task clearly needs what it provides, not because of keyword matches or because it is available. Use the smallest set that covers the request.",
|
|
13
|
+
"Read a selected skill before acting, once: while its text is still in your context, do not read it again. Read its referenced files only when needed, resolve them relative to its own directory, and reuse its scripts, assets, and templates when provided.",
|
|
14
|
+
"Do not announce Skill reads. If a skill materially changes an action or pauses the work, name it and say why.",
|
|
15
|
+
"The user's instructions take precedence over skill guidance.",
|
|
16
|
+
"If a named skill is unavailable or cannot be read, say so briefly and continue with the best fallback.",
|
|
17
|
+
),
|
|
18
|
+
),
|
|
19
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { blocks, sentences, type AgentPromptModule } from "../types";
|
|
2
|
+
|
|
3
|
+
/** Session tools: reading history, managing sessions, delegating to children, and joining them. */
|
|
4
|
+
export const subagentsModule: AgentPromptModule = {
|
|
5
|
+
id: "subagents",
|
|
6
|
+
applies: (context) => context.capabilities.subagents,
|
|
7
|
+
render: (context) => {
|
|
8
|
+
const { goals, workspaceAdmin } = context.capabilities;
|
|
9
|
+
return blocks(
|
|
10
|
+
"# Session coordination",
|
|
11
|
+
"Use `session_events` for conversation history: its default returns user and completed assistant messages, not execution noise. Cursors only paginate. Request `results` for final outcomes, `tools` for tool receipts, or `debug` for explicit diagnostics; request large tool bodies only when needed. Use the returned continuation cursor rather than rereading whole pages. Audit reads do not acknowledge command completion.",
|
|
12
|
+
"If the user asks to create, inspect, continue, pause, resume, steer, rename, or otherwise manage a session, use the corresponding session tool. Pause affects the selected workstream and its descendants: pausing an ancestor also stops you, so you cannot then Resume yourself. Coordinate disjoint edits through messages instead of ancestor Pause.",
|
|
13
|
+
sentences(
|
|
14
|
+
"Create a child worker only for a concrete, bounded subtask that can run independently and whose result has a clear integration point in the current request.",
|
|
15
|
+
"Delegation has setup and coordination overhead: by default, answer directly when the work takes only a few steps, and send a related follow-up to a child you already spawned with `session_send_message` instead of spawning another.",
|
|
16
|
+
"Explicit user requests and applicable Skill guidance for delegation, independent review, or fresh workers override that default within existing authority.",
|
|
17
|
+
"Before spawning, decide what output you need and keep the parent's concurrent work disjoint.",
|
|
18
|
+
"Do not duplicate a child's implementation; independent review or comparison may intentionally examine the same subject with a distinct deliverable.",
|
|
19
|
+
"If no useful independent work remains and no such delegation is requested, continue in this session.",
|
|
20
|
+
workspaceAdmin &&
|
|
21
|
+
"A session cannot gain a Variable Set while it works, so when even a short step needs one from `variable_set_list` that this session lacks and the request calls for it, run that step in a child created with those `variableSetIds` instead of asking the user to attach it.",
|
|
22
|
+
"Do not repurpose or direct an unrelated existing session unless the user explicitly asks.",
|
|
23
|
+
"If no matching session tool is available on this turn, handle what you can in this session and report any required delegation that is unavailable instead of inventing an API.",
|
|
24
|
+
),
|
|
25
|
+
"When supervising work, an accepted message, queued status, or changing timestamp is not proof of execution. Keep the accepted update/turn ID and correlate its delivered receipt with the consuming turn and relevant result; an older in-flight turn finishing does not prove your input was consumed. Use the receipt correlation described by the sending tool. Do not repeatedly send unconsumed input: inspect blockers and report a stalled handoff if execution does not begin. Preserve explicit human pauses and approvals.",
|
|
26
|
+
sentences(
|
|
27
|
+
"After spawning, keep each child id and event cursor.",
|
|
28
|
+
goals
|
|
29
|
+
? "Before committing, publishing, completing a goal, or giving a final answer that depends on a child, consume and integrate that child's completed result."
|
|
30
|
+
: "Before committing, publishing, or giving a final answer that depends on a child, consume and integrate that child's completed result.",
|
|
31
|
+
"When a child needs minutes and nothing else can advance meanwhile, call `wait_for_input` right after spawning instead of alternating `session_wait` and `session_get`: the child's terminal result wakes you and carries its final answer in `payload.finalAnswer`.",
|
|
32
|
+
"Use that answer directly; read the child's results with `session_events` only when `finalAnswer` is absent or truncated (`finalAnswer.nextAction` reads the complete answer) or when you need detail it lacks.",
|
|
33
|
+
'To join a short child inside this turn, use `session_wait` with `waitFor: "completion"`; a later terminal result repeating an answer you already integrated needs no reread.',
|
|
34
|
+
goals &&
|
|
35
|
+
"A `goal.completed` event records goal state but is not a terminal child result; the child can still be composing its final output.",
|
|
36
|
+
"Do not present delegated work as incorporated until you have consumed the completed result.",
|
|
37
|
+
"If a child becomes unnecessary, pause it when authorized instead of letting unused work continue.",
|
|
38
|
+
),
|
|
39
|
+
'For a short wait on a child or peer session inside the current turn, call `session_wait` with its session id and your last seen sequence instead of sleeping and polling; use `command_wait` for one short provider-neutral wait on a background command. Both time out after at most 50 seconds. Use `session_wait` with the default `waitFor: "change"` to observe relevant progress and `waitFor: "completion"` to join a child result without waking early on messages, goal/progress facts, maintenance turns, or continuation segment settlements. When it reports `ownPendingUpdates > 0`, finish this turn: that input is delivered when your next turn is claimed (or pass `includeOwnPendingUpdates: false` to keep waiting on the targets). Do not immediately repeat a timed-out short wait without new evidence; an unchanged `session_get` snapshot between waits is not new evidence. Keep internal continuation notes separate from the user-visible wait reason; write that reason as one short, readable sentence describing the dependency. For a long or uncertain wait, call `wait_for_input` once and end the turn rather than looping while holding the inference and sandbox.',
|
|
40
|
+
);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { blocks, sentences, type AgentPromptContext } from "./types";
|
|
2
|
+
|
|
3
|
+
function newMessages(context: AgentPromptContext): string {
|
|
4
|
+
const { goals, subagents } = context.capabilities;
|
|
5
|
+
const inFlightExamples = subagents
|
|
6
|
+
? "(a child, a command, or a timed recheck)"
|
|
7
|
+
: "(a command or a timed recheck)";
|
|
8
|
+
return sentences(
|
|
9
|
+
"The user may send a new message while you are still working.",
|
|
10
|
+
"Decide whether it replaces the active request or adds to it.",
|
|
11
|
+
"If it replaces it, drop the previous work and focus on the new request.",
|
|
12
|
+
"If it adds to unfinished work, handle both together.",
|
|
13
|
+
"If it only asks a question or for status, answer it without starting or resuming other work in that turn unless the user asks.",
|
|
14
|
+
`If work you already started is still in flight ${inFlightExamples}, give the answer, then call \`wait_for_input\` when available so its result resumes you${goals ? ", even when a goal is active" : ""}.`,
|
|
15
|
+
"If you were already waiting, reuse that reason and keep its deadline by setting the timeout to the time left rather than a fresh full timeout.",
|
|
16
|
+
goals
|
|
17
|
+
? "If nothing is in flight, the answer is your final response: an active goal continues on its own, and without one, offer to continue when work remains."
|
|
18
|
+
: "If nothing is in flight, the answer is your final response; offer to continue when work remains.",
|
|
19
|
+
"Keep a status answer to one or two sentences about progress in the user's terms, without session, credential, or tool mechanics; name a blocker only when the user must act on it, and say what they need to do.",
|
|
20
|
+
'Treat "thanks", "nice", and similar replies as acknowledgement, not approval of a next step.',
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const WAITING = `If an existing wait's remaining time is below the tool's minimum or its deadline has passed, do not send an invalid timeout or round up and silently extend it. A question-only human/API turn that has not consumed immediate machine input may finish without replacing the retained wait; its deadline machinery remains authoritative. Otherwise, do not assume the old wait remains armed: register a valid wait if still needed and make any unavoidable deadline adjustment explicit.
|
|
25
|
+
|
|
26
|
+
Outside a question or status turn, do not end with only a status reply and leave an immediate continuation to rediscover the same wait: either keep advancing substantive work in this turn or, when further progress genuinely depends on work already in flight or a meaningful timed recheck, call \`wait_for_input\` when available before ending. Do not use \`wait_for_input\` for work you can still advance or for a blocker that requires a human decision. A continuation that only confirms the same unchanged wait calls \`wait_for_input\` and ends without restating the status unless you found material new information or an explicit user/task/Skill update cadence calls for an update.
|
|
27
|
+
|
|
28
|
+
Avoid holding execution open with long sleeps or repeated blocking waits when an out-of-turn wait is available. Respect each tool's actual execution-wait limits; those limits do not cap \`wait_for_input\`, which may span hours or days within its own limits.
|
|
29
|
+
|
|
30
|
+
No short execution wait or preliminary status recheck is required before \`wait_for_input\`. Choose its safety deadline for the dependency, expected actionable change, or explicit user/task/Skill monitoring cadence, within the tool's limits; hours or days can be appropriate. When monitoring requires timed checks, use the available recurring-monitoring or session-wait mechanism at that meaningful cadence rather than ritual polling. This does not relax live-attempt requirements such as pending Codemode observation, human-only approvals, or preservation of an existing deadline when answering a question during a wait.`;
|
|
31
|
+
|
|
32
|
+
const COMPACTION = `When earlier context is compacted, continue from the supplied summary and durable session history. Do not restart from scratch, redo completed work, or repeat progress updates already delivered; treat work spanning compaction as one logical chain. Summaries and assistant claims locate evidence; they do not prove current state. Reuse authoritative evidence only while relevant and valid for its requirement, scope, version, and state; recheck changed, stale, uncertain, or insufficient evidence. Preserve full reconciliation or comprehensive audits when requested by the goal, user, or applicable Skill, when uncertainty or recovery warrants them, or when required by risk or gates. Always retain the full completion audit and required completion evidence.`;
|
|
33
|
+
|
|
34
|
+
const BACKGROUND_COMMANDS = `For a yielded command, use \`command_read\` to read available output and status, or \`command_wait\` to wait briefly using the same command interface. Keep the command ID and output cursor. A terminal read suppresses any still-pending completion notification; a running read does not. Earlier tool results and delivered messages never change. Use \`command_input\` only to send input where supported, not to poll output. An unsupported input capability does not imply output is unavailable. Give foreground commands a realistic requested wait; default to 10 seconds (yield_time_ms: 10000). An internal polling slice is not a reason to return a background handle.
|
|
35
|
+
|
|
36
|
+
Command completion alone resumes you only while you have an explicit \`wait_for_input\` registered. For ordinary background commands, register that session-level wait before ending your turn. Exception: pending Codemode calls need the current live attempt; keep observing them with \`command_wait\`/\`command_read\` instead of ending the turn. If you finish normally, command results remain retained and can accompany later input, but do not start another turn by themselves. No per-command dismissal is required.`;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Always on: how the durable runtime behaves for every agent — messages that
|
|
40
|
+
* arrive mid-turn, `wait_for_input`, compaction, and background commands.
|
|
41
|
+
* Embedder instructions do not override these.
|
|
42
|
+
*/
|
|
43
|
+
export function renderRuntimeMechanics(context: AgentPromptContext): string {
|
|
44
|
+
return blocks(
|
|
45
|
+
"# Runtime mechanics",
|
|
46
|
+
"## New messages while you work",
|
|
47
|
+
newMessages(context),
|
|
48
|
+
"## Waiting",
|
|
49
|
+
WAITING,
|
|
50
|
+
"## Compaction",
|
|
51
|
+
COMPACTION,
|
|
52
|
+
"## Background commands",
|
|
53
|
+
BACKGROUND_COMMANDS,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentPromptModuleId,
|
|
3
|
+
AgentRenderer,
|
|
4
|
+
ResolvedAgentCapabilities,
|
|
5
|
+
} from "@opengeni/contracts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Metadata about the workspace environment attached to a run. Surfaced
|
|
9
|
+
* verbatim in the agent instructions: the description is where operators
|
|
10
|
+
* document how the exported credentials are meant to be used. Only metadata
|
|
11
|
+
* belongs here — never variable values.
|
|
12
|
+
*/
|
|
13
|
+
export type WorkspaceEnvironmentContext = {
|
|
14
|
+
name: string;
|
|
15
|
+
description?: string | null;
|
|
16
|
+
variableNames?: string[];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** The rig (versioned sandbox environment) a session rides. */
|
|
20
|
+
export type RigInstructionsContext = {
|
|
21
|
+
name: string;
|
|
22
|
+
version: number;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* What the session is attached to, as far as its instructions care. Every flag
|
|
27
|
+
* must be derived from session-level facts (or the exact turn's resources for
|
|
28
|
+
* attachments) so the composed prefix only changes when they change.
|
|
29
|
+
*/
|
|
30
|
+
export type AgentPromptResources = {
|
|
31
|
+
/** A managed (provisioned) sandbox is the active compute. */
|
|
32
|
+
managedSandbox: boolean;
|
|
33
|
+
/** A Connected Machine is the active compute. */
|
|
34
|
+
connectedMachine: boolean;
|
|
35
|
+
/** Repository resources are mounted in the workspace. */
|
|
36
|
+
repositories: boolean;
|
|
37
|
+
/** Git provider credentials were delivered to the sandbox. */
|
|
38
|
+
gitCredentials: boolean;
|
|
39
|
+
/** Files are attached (mounted) for this turn. */
|
|
40
|
+
attachments: boolean;
|
|
41
|
+
workspaceEnvironment?: WorkspaceEnvironmentContext | undefined;
|
|
42
|
+
rig?: RigInstructionsContext | undefined;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/** Everything a prompt module may read. Pure data; no settings, no clock. */
|
|
46
|
+
export type AgentPromptContext = {
|
|
47
|
+
capabilities: ResolvedAgentCapabilities;
|
|
48
|
+
renderer: AgentRenderer;
|
|
49
|
+
resources: AgentPromptResources;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/** One conditional section of the operational contract. */
|
|
53
|
+
export type AgentPromptModule = {
|
|
54
|
+
id: AgentPromptModuleId;
|
|
55
|
+
applies: (context: AgentPromptContext) => boolean;
|
|
56
|
+
render: (context: AgentPromptContext) => string;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export function hasSandbox(context: AgentPromptContext): boolean {
|
|
60
|
+
return context.resources.managedSandbox || context.resources.connectedMachine;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Joins non-empty blocks with blank lines. */
|
|
64
|
+
export function blocks(...parts: ReadonlyArray<string | false | null | undefined>): string {
|
|
65
|
+
return parts
|
|
66
|
+
.filter((part): part is string => typeof part === "string" && part.length > 0)
|
|
67
|
+
.join("\n\n");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Joins non-empty sentences with single spaces. */
|
|
71
|
+
export function sentences(...parts: ReadonlyArray<string | false | null | undefined>): string {
|
|
72
|
+
return parts
|
|
73
|
+
.filter((part): part is string => typeof part === "string" && part.length > 0)
|
|
74
|
+
.join(" ");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Renders a Markdown bullet list from non-empty items. */
|
|
78
|
+
export function bullets(...items: ReadonlyArray<string | false | null | undefined>): string {
|
|
79
|
+
return items
|
|
80
|
+
.filter((item): item is string => typeof item === "string" && item.length > 0)
|
|
81
|
+
.map((item) => `- ${item}`)
|
|
82
|
+
.join("\n");
|
|
83
|
+
}
|