@getforgeai/cli 0.1.0-beta.3 → 0.1.0-beta.4

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.
@@ -45,6 +45,12 @@ export type AgentProfile = {
45
45
  buildContinueArgs(prompt: string): string[];
46
46
  /** Non-secret env vars added to every agent spawn. */
47
47
  spawnEnv: Record<string, string>;
48
+ /**
49
+ * Whether the engine discovers skills deposited in .claude/skills on its
50
+ * own (Claude Code and OpenCode do). When false, prompts must carry an
51
+ * explicit pointer to the SKILL.md — see appendSkillPointer().
52
+ */
53
+ nativeSkillDiscovery: boolean;
48
54
  /** Container dir holding the session state snapshotted for resume. */
49
55
  stateDir: string;
50
56
  /** tar --exclude patterns — credentials and cache junk never leave the container. */
@@ -55,6 +61,15 @@ export type AgentProfile = {
55
61
  };
56
62
  /** Narrow an arbitrary config/dispatch string to a supported AgentType. */
57
63
  export declare function resolveAgentType(value: string | undefined): AgentType;
64
+ /**
65
+ * Make sure a cloud-provided prompt still leads the agent to the deposited
66
+ * skill. Cloud task/step commands (e.g. "forge_merge_back") replace the
67
+ * default prompt that pointed at the SKILL.md; engines with native skill
68
+ * discovery find the skill anyway, but Codex would otherwise never learn the
69
+ * skill exists. No-op when the engine discovers skills natively or when no
70
+ * skill was deposited.
71
+ */
72
+ export declare function appendSkillPointer(prompt: string, profile: AgentProfile, skillName: string | undefined): string;
58
73
  export declare function getAgentProfile(agentType: string | undefined): AgentProfile;
59
74
  /**
60
75
  * Instantiate the stream extractor matching the agent engine.
@@ -20,6 +20,19 @@ export function resolveAgentType(value) {
20
20
  return value;
21
21
  return DEFAULT_AGENT_TYPE;
22
22
  }
23
+ /**
24
+ * Make sure a cloud-provided prompt still leads the agent to the deposited
25
+ * skill. Cloud task/step commands (e.g. "forge_merge_back") replace the
26
+ * default prompt that pointed at the SKILL.md; engines with native skill
27
+ * discovery find the skill anyway, but Codex would otherwise never learn the
28
+ * skill exists. No-op when the engine discovers skills natively or when no
29
+ * skill was deposited.
30
+ */
31
+ export function appendSkillPointer(prompt, profile, skillName) {
32
+ if (profile.nativeSkillDiscovery || !skillName)
33
+ return prompt;
34
+ return `${prompt}\n\nThe "${skillName}" skill at .claude/skills/${skillName}/SKILL.md describes the procedure to follow — read it before starting.`;
35
+ }
23
36
  // ---------------------------------------------------------------------------
24
37
  // Claude Code
25
38
  // ---------------------------------------------------------------------------
@@ -60,6 +73,7 @@ const claudeProfile = {
60
73
  return ["--continue", ...this.buildArgs(prompt)];
61
74
  },
62
75
  spawnEnv: {},
76
+ nativeSkillDiscovery: true,
63
77
  stateDir: "/home/agent/.claude",
64
78
  snapshotExcludes: [
65
79
  "settings.json",
@@ -132,6 +146,7 @@ const codexProfile = {
132
146
  ];
133
147
  },
134
148
  spawnEnv: {},
149
+ nativeSkillDiscovery: false,
135
150
  stateDir: "/home/agent/.codex",
136
151
  snapshotExcludes: ["auth.json", "config.toml", "log"],
137
152
  authErrorPatterns: {
@@ -192,6 +207,8 @@ const openCodeProfile = {
192
207
  return ["run", "--continue", "--format", "json", prompt];
193
208
  },
194
209
  spawnEnv: { OPENCODE_PERMISSION: OPENCODE_PERMISSION_JSON },
210
+ // OpenCode reads .claude/skills natively (OPENCODE_DISABLE_CLAUDE_CODE_SKILLS opts out)
211
+ nativeSkillDiscovery: true,
195
212
  stateDir: "/home/agent/.local/share/opencode",
196
213
  snapshotExcludes: ["auth.json", "log", "bin", "cache"],
197
214
  authErrorPatterns: {
@@ -16,7 +16,7 @@ import { getDockerBridgeGatewayIp } from "../../vm/docker-executor.js";
16
16
  import { activeConnections } from "../../lib/connection-manager.js";
17
17
  import { vmLog } from "../../vm/log.js";
18
18
  import { getConfig } from "../../config/config-manager.js";
19
- import { getAgentProfile } from "../agent-profiles.js";
19
+ import { appendSkillPointer, getAgentProfile } from "../agent-profiles.js";
20
20
  // ---------------------------------------------------------------------------
21
21
  // Helpers
22
22
  // ---------------------------------------------------------------------------
@@ -168,8 +168,11 @@ export const dockerConnector = {
168
168
  await sm.materializeAgentAuth(params.taskId, profile.type);
169
169
  // 7. Start MCP bridge (TCP server on host for forge-mcp-relay in container)
170
170
  await startSessionMcpBridge(session, params);
171
- // 8. Spawn agent
172
- const prompt = params.prompt ?? buildDefaultPrompt(params.skillName);
171
+ // 8. Spawn agent. Cloud-provided prompts get a pointer to the deposited
172
+ // skill when the engine has no native skill discovery (Codex).
173
+ const prompt = params.prompt
174
+ ? appendSkillPointer(params.prompt, profile, params.skill?.name)
175
+ : buildDefaultPrompt(params.skillName);
173
176
  const agentArgs = profile.buildArgs(prompt);
174
177
  const env = {};
175
178
  vmLog.magenta("docker-connector", `Spawning ${profile.type} agent in container ${sessionId}`, sessionId);
@@ -330,7 +333,9 @@ export const dockerConnector = {
330
333
  }
331
334
  else {
332
335
  vmLog.warn("docker-connector", `Snapshot restore failed — falling back to prompt in ${sessionId}`, sessionId);
333
- const prompt = params.prompt ?? buildDefaultPrompt(params.skillName);
336
+ const prompt = params.prompt
337
+ ? appendSkillPointer(params.prompt, profile, params.skill?.name)
338
+ : buildDefaultPrompt(params.skillName);
334
339
  proxy = await sm.spawnAgent(params.taskId, profile.binary, profile.buildArgs(prompt), {}, profile.type);
335
340
  }
336
341
  // Workflow: keep container alive for idle window
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getforgeai/cli",
3
- "version": "0.1.0-beta.3",
3
+ "version": "0.1.0-beta.4",
4
4
  "description": "ForgeAI CLI — runs AI coding agents in local Docker containers with your own AI tokens, and connects them to the ForgeAI cockpit.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",