@khalilgharbaoui/opencode-claude-code-plugin 0.43.0 → 0.44.0

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/index.d.ts CHANGED
@@ -362,6 +362,12 @@ interface ClaudeCodeConfig {
362
362
  interactiveAllowTools?: string[];
363
363
  /** With interactive: append this plugin's own prompts via --append-system-prompt-file. Defaults to true. */
364
364
  interactiveSystemPrompt?: boolean;
365
+ /**
366
+ * With the interactive transport: also append what the operator wrote that
367
+ * opencode forwarded (instruction files and the active agent's own prompt),
368
+ * verbatim and chosen by provenance. Off by default (h #g212).
369
+ */
370
+ interactiveUserInstructions?: boolean;
365
371
  cwd?: string;
366
372
  account?: string;
367
373
  configDir?: string;
@@ -481,6 +487,12 @@ interface ClaudeCodeProviderSettings {
481
487
  interactiveAllowTools?: string[];
482
488
  /** With interactive: append this plugin's own prompts via --append-system-prompt-file. Defaults to true. */
483
489
  interactiveSystemPrompt?: boolean;
490
+ /**
491
+ * With the interactive transport: also append what the operator wrote that
492
+ * opencode forwarded (instruction files and the active agent's own prompt),
493
+ * verbatim and chosen by provenance. Off by default (h #g212).
494
+ */
495
+ interactiveUserInstructions?: boolean;
484
496
  cwd?: string;
485
497
  name?: string;
486
498
  providerID?: string;
@@ -1370,6 +1382,11 @@ type AgentRecord = {
1370
1382
  * refused. Same account throughout; see `src/model-fallback.ts`.
1371
1383
  */
1372
1384
  fallbackModels?: string[];
1385
+ /**
1386
+ * The agent's own prompt as the operator wrote it: the markdown body, or
1387
+ * `prompt` in opencode.json. Read only by `interactiveUserInstructions`.
1388
+ */
1389
+ prompt?: string;
1373
1390
  };
1374
1391
  declare function getAgentRegistry(): Record<string, AgentRecord>;
1375
1392
  declare function getDefaultSubagentModel(): string | undefined;
package/dist/index.js CHANGED
@@ -7733,6 +7733,13 @@ function parseAgentFrontmatter(text) {
7733
7733
  }
7734
7734
  return record;
7735
7735
  }
7736
+ function agentMarkdownBody(text) {
7737
+ if (!text.startsWith("---")) return text.trim() || void 0;
7738
+ const lines = text.split(/\r?\n/);
7739
+ const close = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
7740
+ if (close === -1) return void 0;
7741
+ return lines.slice(close + 1).join("\n").trim() || void 0;
7742
+ }
7736
7743
  function parseFallbackModelList(value) {
7737
7744
  if (Array.isArray(value)) {
7738
7745
  return value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter(Boolean);
@@ -7756,6 +7763,8 @@ async function readAgentMarkdownRecords(directories) {
7756
7763
  try {
7757
7764
  const text = await readFile(path7.join(directory, entry), "utf8");
7758
7765
  records2[name] = parseAgentFrontmatter(text);
7766
+ const prompt = agentMarkdownBody(text);
7767
+ if (prompt) records2[name].prompt = prompt;
7759
7768
  } catch (err) {
7760
7769
  log.debug("failed to read agent markdown", {
7761
7770
  file: path7.join(directory, entry),
@@ -10284,7 +10293,7 @@ function spawnInteractiveProcess(opts) {
10284
10293
  import { readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
10285
10294
  import { homedir as homedir8 } from "os";
10286
10295
  import { randomUUID as randomUUID6 } from "crypto";
10287
- import { dirname as dirname6, join as join11 } from "path";
10296
+ import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join11 } from "path";
10288
10297
  function readPromptFileIfPresent(path11) {
10289
10298
  try {
10290
10299
  const content = readFileSync7(path11, "utf8").trim();
@@ -10390,6 +10399,36 @@ function extractSystemMessages(prompt) {
10390
10399
  }
10391
10400
  return out;
10392
10401
  }
10402
+ var CLAUDE_NATIVE_INSTRUCTION_FILES = /* @__PURE__ */ new Set(["CLAUDE.md", "CLAUDE.local.md"]);
10403
+ function userAuthoredInstructions(forwarded, opts = {}) {
10404
+ const readFile2 = opts.readFile ?? ((path11) => {
10405
+ try {
10406
+ return readFileSync7(path11, "utf8");
10407
+ } catch {
10408
+ return null;
10409
+ }
10410
+ });
10411
+ const out = [];
10412
+ const agentPrompt = opts.agentPrompt?.trim();
10413
+ if (agentPrompt && forwarded.includes(agentPrompt)) {
10414
+ out.push({ text: agentPrompt, content: agentPrompt });
10415
+ }
10416
+ const seen = /* @__PURE__ */ new Set();
10417
+ for (const match of forwarded.matchAll(/^Instructions from: (.+)$/gm)) {
10418
+ const path11 = match[1].trim();
10419
+ if (seen.has(path11) || !isAbsolute3(path11)) continue;
10420
+ if (CLAUDE_NATIVE_INSTRUCTION_FILES.has(basename2(path11))) continue;
10421
+ seen.add(path11);
10422
+ const file = readFile2(path11);
10423
+ if (!file?.trim()) continue;
10424
+ const start = match.index + match[0].length + 1;
10425
+ const content = forwarded.startsWith(file, start) ? file : forwarded.startsWith(file.trimEnd(), start) ? file.trimEnd() : null;
10426
+ if (content === null) continue;
10427
+ out.push({ text: `Instructions from: ${path11}
10428
+ ${content}`, content });
10429
+ }
10430
+ return out;
10431
+ }
10393
10432
  function buildAppendedSystemPrompt(cwd, includeMultiStepHint = true, extraSystemContent = [], options = {}) {
10394
10433
  const parts = [];
10395
10434
  if (options.compressionSummary?.trim()) {
@@ -10414,6 +10453,11 @@ ${options.compressionSummary.trim()}`
10414
10453
  if (pushGlobal) parts.push(globalAgents);
10415
10454
  if (pushWorkspace) parts.push(workspaceAgents);
10416
10455
  if (pushGlobal || pushWorkspace) parts.push(AGENTS_MAINTENANCE_HINT);
10456
+ for (const instruction of options.userInstructions ?? []) {
10457
+ const authored = instruction.content.trim();
10458
+ if (authored === globalAgents || authored === workspaceAgents) continue;
10459
+ parts.push(instruction.text);
10460
+ }
10417
10461
  if (includeMultiStepHint) parts.push(MULTI_STEP_TASK_HINT);
10418
10462
  const content = parts.join("\n\n");
10419
10463
  if (!content) return void 0;
@@ -13906,6 +13950,14 @@ var ClaudeCodeLanguageModel = class {
13906
13950
  "WebFetch"
13907
13951
  ]
13908
13952
  ];
13953
+ const userInstructions = self.config.interactiveUserInstructions === true ? userAuthoredInstructions(extractSystemMessages(options.prompt).join("\n\n"), {
13954
+ agentPrompt: getAgentRegistry()[self.getOpencodeAgent(options) ?? ""]?.prompt
13955
+ }) : [];
13956
+ if (userInstructions.length > 0) {
13957
+ log.info("forwarding user-authored instructions to the interactive TUI", {
13958
+ count: userInstructions.length
13959
+ });
13960
+ }
13909
13961
  const systemPromptFile = self.config.interactiveSystemPrompt === false ? void 0 : buildAppendedSystemPrompt(
13910
13962
  cwd,
13911
13963
  self.config.multiStepContinuation !== false,
@@ -13927,7 +13979,8 @@ var ClaudeCodeLanguageModel = class {
13927
13979
  opencodeCompressEnabled: wiring.opencodeToolDefs.some(
13928
13980
  (t) => t.name === "compress"
13929
13981
  ),
13930
- compressionSummary: getCompressionSummary(sk)
13982
+ compressionSummary: getCompressionSummary(sk),
13983
+ userInstructions
13931
13984
  }
13932
13985
  );
13933
13986
  if (self.config.interactiveSystemPrompt === false) {
@@ -15461,7 +15514,8 @@ function createClaudeCode(settings = {}) {
15461
15514
  interactive: settings.interactive,
15462
15515
  interactiveBypass: settings.interactiveBypass,
15463
15516
  interactiveAllowTools: settings.interactiveAllowTools,
15464
- interactiveSystemPrompt: settings.interactiveSystemPrompt
15517
+ interactiveSystemPrompt: settings.interactiveSystemPrompt,
15518
+ interactiveUserInstructions: settings.interactiveUserInstructions
15465
15519
  });
15466
15520
  };
15467
15521
  const provider = function(modelId) {
@@ -15680,7 +15734,8 @@ async function buildAgentRegistry(config) {
15680
15734
  forceModel: pick("forceModel") ?? records2[name]?.forceModel,
15681
15735
  reasoningEffort: pick("reasoningEffort") ?? records2[name]?.reasoningEffort,
15682
15736
  cacheTtl: pick("cacheTtl") ?? records2[name]?.cacheTtl,
15683
- fallbackModels: declaredChain.length ? declaredChain : records2[name]?.fallbackModels
15737
+ fallbackModels: declaredChain.length ? declaredChain : records2[name]?.fallbackModels,
15738
+ prompt: pick("prompt") ?? records2[name]?.prompt
15684
15739
  };
15685
15740
  }
15686
15741
  setAgentRegistry(records2);