opencode-fixes-huihui 0.1.4-beta.15 → 0.1.4-beta.16
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/README.md +7 -1
- package/dist/index.js +16 -2
- package/dist/index.js.map +2 -2
- package/dist/sticky-session-plugin.d.ts.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -42,13 +42,19 @@ import {
|
|
|
42
42
|
|
|
43
43
|
在 `chat.params` 阶段执行,仅对 `@ai-sdk/openai` 或 `isCodex` provider 生效。
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
基础会话值优先级:
|
|
46
46
|
|
|
47
47
|
1. `OPENCODE_PROMPT_CACHE_KEY`
|
|
48
48
|
2. `OPENCODE_STICKY_SESSION_ID`
|
|
49
49
|
3. 现有 headers:`x-session-id` / `conversation_id` / `session_id`
|
|
50
50
|
4. `input.sessionID`
|
|
51
51
|
|
|
52
|
+
最终写入 headers / `promptCacheKey` 的会话值规则:
|
|
53
|
+
|
|
54
|
+
- 如果 `input.agent` 有值:`{baseSessionValue}__agent__{encodeURIComponent(lowercase(agent))}`
|
|
55
|
+
- 如果 `input.agent` 为空:直接使用 `baseSessionValue`
|
|
56
|
+
- 为避免重复后缀,插件会先剥离已有的 `__agent__...` 后缀,再拼接当前 agent
|
|
57
|
+
|
|
52
58
|
写入位置:
|
|
53
59
|
|
|
54
60
|
- `input.model.headers.x-session-id`
|
package/dist/index.js
CHANGED
|
@@ -132,12 +132,22 @@ var WormholeCache = createProviderPlugin("wormhole_a");
|
|
|
132
132
|
|
|
133
133
|
// src/sticky-session-plugin.ts
|
|
134
134
|
var OPENAI_PROVIDER_NPM = "@ai-sdk/openai";
|
|
135
|
+
var AGENT_SUFFIX_PREFIX = "__agent__";
|
|
135
136
|
var SESSION_HEADER_KEYS = [
|
|
136
137
|
"x-session-id",
|
|
137
138
|
"conversation_id",
|
|
138
139
|
"session_id"
|
|
139
140
|
];
|
|
140
141
|
var normalize = (value) => typeof value === "string" ? value.trim() : "";
|
|
142
|
+
var normalizeAgent = (value) => typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
143
|
+
var stripAgentSuffix = (value) => value.replace(/__agent__[%A-Za-z0-9._~-]+$/, "");
|
|
144
|
+
var buildAgentScopedSessionValue = (sessionValue, input) => {
|
|
145
|
+
const baseSessionValue = stripAgentSuffix(sessionValue);
|
|
146
|
+
const agent = normalizeAgent(input.agent);
|
|
147
|
+
if (!agent) return baseSessionValue;
|
|
148
|
+
const suffix = `${AGENT_SUFFIX_PREFIX}${encodeURIComponent(agent)}`;
|
|
149
|
+
return `${baseSessionValue}${suffix}`;
|
|
150
|
+
};
|
|
141
151
|
var pickHeaderSessionValue = (headers) => {
|
|
142
152
|
for (const key of SESSION_HEADER_KEYS) {
|
|
143
153
|
const value = normalize(headers[key]);
|
|
@@ -175,8 +185,12 @@ var StickySessionPlugin = async ({ client }) => {
|
|
|
175
185
|
const isCodex = isProviderCodexMap[input.model.providerID] ?? false;
|
|
176
186
|
if (!providerNpm.includes(OPENAI_PROVIDER_NPM) && !isCodex) return;
|
|
177
187
|
const headers = ensureHeaders(input.model);
|
|
178
|
-
const
|
|
179
|
-
if (!
|
|
188
|
+
const baseSessionValue = envOverride || pickHeaderSessionValue(headers) || normalize(input.sessionID);
|
|
189
|
+
if (!baseSessionValue) return;
|
|
190
|
+
const sessionValue = buildAgentScopedSessionValue(
|
|
191
|
+
baseSessionValue,
|
|
192
|
+
input
|
|
193
|
+
);
|
|
180
194
|
for (const key of SESSION_HEADER_KEYS) {
|
|
181
195
|
headers[key] = sessionValue;
|
|
182
196
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/logger.ts", "../src/opencode-anthropic-cache.ts", "../src/sticky-session-plugin.ts", "../src/superpowers.ts"],
|
|
4
|
-
"sourcesContent": ["import type { PluginInput } from \"@opencode-ai/plugin\";\n// Logger module for debugging\nconst ENV_DEBUG = \"OPENCODE_ANTHROPIC_CACHE_DEBUG\";\nlet _client: PluginInput[\"client\"] | null = null;\nfunction isDebugEnabled() {\n const val = process.env[ENV_DEBUG];\n return val === \"1\" || val?.toLowerCase() === \"true\";\n}\nexport function initLogger(client: PluginInput[\"client\"]) {\n _client = client;\n}\nexport function createLogger(module: string, prefix: string) {\n const service = `${prefix}.${module}`;\n const log = (\n level: \"debug\" | \"info\" | \"warn\" | \"error\",\n message: string,\n extra?: any,\n ) => {\n if (_client?.app && typeof _client.app.log === \"function\") {\n _client.app\n .log({ body: { service, level, message, extra } })\n .catch(() => {});\n return;\n }\n if (isDebugEnabled()) {\n const prefix = `[${service}]`;\n const args = extra ? [prefix, message, extra] : [prefix, message];\n switch (level) {\n case \"debug\":\n console.debug(...args);\n break;\n case \"info\":\n console.info(...args);\n break;\n case \"warn\":\n console.warn(...args);\n break;\n case \"error\":\n console.error(...args);\n break;\n }\n }\n };\n return {\n debug: (message: string, extra?: any) => log(\"debug\", message, extra),\n info: (message: string, extra?: any) => log(\"info\", message, extra),\n warn: (message: string, extra?: any) => log(\"warn\", message, extra),\n error: (message: string, extra?: any) => log(\"error\", message, extra),\n };\n}\n", "import type { Hooks, Plugin } from \"@opencode-ai/plugin\";\nimport { createLogger, initLogger } from \"./logger\";\n\nconst log = createLogger(\"fetch\", \"anthropic-cache\");\n// Session and project tracking\nlet currentSessionId = \"\";\nlet projectId = \"\";\nlet isInitialized = false;\nfunction buildUserId() {\n const pid = projectId || \"unknown\";\n const sid = currentSessionId || \"unknown\";\n return `user_${pid}_account__session_${sid}`;\n}\nfunction isJsonContentType(headers: Headers) {\n const ct = headers.get(\"content-type\") || \"\";\n return ct.includes(\"application/json\");\n}\nfunction parseBody(body?: unknown) {\n if (!body) return null;\n if (typeof body === \"string\") return body;\n if (body instanceof Uint8Array) return new TextDecoder().decode(body);\n return null;\n}\ntype CachePayload = {\n metadata?: {\n user_id?: string;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n};\n\n// Create the fetch interceptor that injects metadata.user_id\nfunction createCacheFetch(providerName: string) {\n return async (url: string | Request | URL, init?: RequestInit) => {\n const headers = new Headers(init?.headers);\n const method = (init?.method || \"GET\").toUpperCase();\n if (method !== \"POST\" || !isJsonContentType(headers)) {\n return fetch(url, init);\n }\n const rawBody = parseBody(init?.body);\n if (!rawBody) return fetch(url, init);\n let payload: CachePayload;\n try {\n payload = JSON.parse(rawBody) as CachePayload;\n } catch {\n log.warn(`[${providerName}] Failed to parse request body as JSON`);\n return fetch(url, init);\n }\n if (payload && typeof payload === \"object\") {\n if (!payload.metadata || typeof payload.metadata !== \"object\") {\n payload.metadata = {};\n }\n const meta = payload.metadata;\n if (meta.user_id == null) {\n meta.user_id = buildUserId();\n log.info(`[${providerName}] Injected user_id`, {\n user_id: meta.user_id,\n });\n }\n }\n headers.delete(\"content-length\");\n return fetch(url, { ...init, headers, body: JSON.stringify(payload) });\n };\n}\n// Shared event handler\nfunction createEventHandler(): Hooks[\"event\"] {\n return async ({ event }) => {\n if (event.type === \"session.created\" || event.type === \"session.updated\") {\n const props = event.properties;\n currentSessionId = props?.info?.id || \"\";\n log.debug(\"Session updated\", { sessionId: currentSessionId });\n }\n };\n}\n// Factory to create plugin for a specific provider\nfunction createProviderPlugin(providerName: string): Plugin {\n return async ({ project, client }) => {\n if (!isInitialized) {\n initLogger(client);\n projectId = project?.id || \"\";\n isInitialized = true;\n log.info(\"Plugin initialized\", { projectId });\n }\n log.info(`Auth handler registered for provider: ${providerName}`);\n return {\n event: createEventHandler(),\n auth: {\n provider: providerName,\n methods: [{ type: \"api\", label: \"key\" }],\n loader: async () => ({\n fetch: createCacheFetch(providerName),\n }),\n },\n };\n };\n}\n// Pre-built plugins for common providers\nexport const FoxcodeAwsCache = createProviderPlugin(\"foxcode-aws\");\nexport const AnthropicCache = createProviderPlugin(\"anthropic\");\nexport const AnthropicUltraCache = createProviderPlugin(\"anthropic-ultra\");\nexport const WormholeCache = createProviderPlugin(\"wormhole_a\");\n// Generic factory for custom provider names\nexport const createAnthropicCachePlugin = createProviderPlugin;\n", "import type { Plugin } from \"@opencode-ai/plugin\";\n\nconst OPENAI_PROVIDER_NPM = \"@ai-sdk/openai\";\nconst SESSION_HEADER_KEYS = [\n \"x-session-id\",\n \"conversation_id\",\n \"session_id\",\n] as const;\n\ntype HeaderMap = Record<string, unknown>;\n\nconst normalize = (value: unknown): string =>\n typeof value === \"string\" ? value.trim() : \"\";\n\nconst pickHeaderSessionValue = (headers: HeaderMap): string => {\n for (const key of SESSION_HEADER_KEYS) {\n const value = normalize(headers[key]);\n if (value) return value;\n }\n return \"\";\n};\n\nconst ensureHeaders = (model: { headers?: unknown }): HeaderMap => {\n if (model.headers && typeof model.headers === \"object\") {\n return model.headers as HeaderMap;\n }\n const headers: HeaderMap = {};\n model.headers = headers;\n return headers;\n};\n\n/**\n * set a session-scoped prompt cache key and session-scoped sticky routing headers for right.codes.\n *\n * Injects HTTP headers via `input.model.headers` so upstream proxies/load\n * balancers can keep a conversation pinned to one account.\n *\n * Headers injected for @ai-sdk/openai providers:\n * - x-session-id\n * - conversation_id\n * - session_id\n *\n * Source of truth (in order):\n * - env: OPENCODE_PROMPT_CACHE_KEY (manual override)\n * - env: OPENCODE_STICKY_SESSION_ID (manual override)\n * - model headers (x-session-id / conversation_id / session_id)\n * - opencode sessionID (default)\n */\nexport const StickySessionPlugin: Plugin = async ({ client }) => {\n const envPromptCacheKey = normalize(process.env.OPENCODE_PROMPT_CACHE_KEY);\n const envStickySessionID = normalize(process.env.OPENCODE_STICKY_SESSION_ID);\n const envOverride = envPromptCacheKey || envStickySessionID;\n const isProviderCodexMap: Record<string, boolean> = {};\n let inited = false;\n const init = async () => {\n if (inited) return;\n const resp = await client.config.providers();\n const providers = resp.data?.providers ?? [];\n for (const provider of providers) {\n isProviderCodexMap[provider.id] = Boolean(provider.options?.isCodex);\n }\n inited = true;\n };\n\n return {\n \"chat.params\": async (input, output) => {\n if (!inited) await init();\n const providerNpm = normalize(input.model.api.npm);\n const isCodex = isProviderCodexMap[input.model.providerID] ?? false;\n if (!providerNpm.includes(OPENAI_PROVIDER_NPM) && !isCodex) return;\n\n const headers = ensureHeaders(input.model);\n const sessionValue =\n envOverride ||\n pickHeaderSessionValue(headers) ||\n normalize(input.sessionID);\n if (!sessionValue) return;\n\n for (const key of SESSION_HEADER_KEYS) {\n headers[key] = sessionValue;\n }\n\n output.options.promptCacheKey = sessionValue;\n // if (isCodex && !output.options.instructions) {\n // output.options.instructions = \"\";\n // }\n },\n };\n};\n\nexport default StickySessionPlugin;\n", "/**\n * Superpowers plugin for OpenCode.ai\n *\n * Injects superpowers bootstrap context via system prompt transform.\n * Skills are discovered via OpenCode's native skill tool from symlinked directory.\n */\n\nimport path from 'path';\nimport fs from 'fs';\nimport os from 'os';\nimport { fileURLToPath } from 'url';\nimport type { Plugin } from '@opencode-ai/plugin';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst OH_MY_OPENAGENT_AGENTS = new Set([\n // https://github.com/code-yeongyu/oh-my-openagent\n 'sisyphus', 'hephaestus', 'oracle', 'librarian',\n 'explore', 'multimodal-looker', 'prometheus',\n 'metis', 'momus', 'atlas', 'sisyphus-junior',\n])\nconst PROMPT_INJECTION_AGENTS = new Set([\n 'plan', 'build', //'compaction',\n // https://github.com/alvinunreal/oh-my-opencode-slim\n 'orchestrator',\n // ...OH_MY_OPENAGENT_AGENTS,\n])\n\nconst normalizeAgentName = (name: unknown) =>\n typeof name === 'string' ? name.trim().toLowerCase() : '';\n\n// Simple frontmatter extraction (avoid dependency on skills-core for bootstrap)\nconst extractAndStripFrontmatter = (content: string) => {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n if (!match) return { frontmatter: {}, content };\n\n const frontmatterStr = match[1];\n const body = match[2];\n const frontmatter: Record<string, string> = {};\n\n for (const line of frontmatterStr.split('\\n')) {\n const colonIdx = line.indexOf(':');\n if (colonIdx > 0) {\n // \u55B5~ \u8FD9\u6BB5\u4EE3\u7801\u7684\u4F5C\u7528\u662F\u89E3\u6790 frontmatter \u7684\u6BCF\u4E00\u884C\uFF1A\n // 1. \u63D0\u53D6\u5192\u53F7\u524D\u7684\u90E8\u5206\u4F5C\u4E3A key \u5E76\u53BB\u9664\u7A7A\u683C\u3002\n // 2. \u63D0\u53D6\u5192\u53F7\u540E\u7684\u90E8\u5206\u4F5C\u4E3A value\uFF0C\u53BB\u9664\u7A7A\u683C\u5E76\u5265\u79BB\u4E24\u4FA7\u7684\u5F15\u53F7\u3002\n // 3. \u5C06\u7ED3\u679C\u5B58\u5165 frontmatter \u5BF9\u8C61\uFF08\u6B64\u5904\u9700\u65AD\u8A00\u7C7B\u578B\u4EE5\u907F\u514D TS \u7D22\u5F15\u9519\u8BEF\uFF09\u3002\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim().replace(/^[\"']|[\"']$/g, '');\n frontmatter[key] = value;\n }\n }\n\n return { frontmatter, content: body };\n};\n\n// Normalize a path: trim whitespace, expand ~, resolve to absolute\nconst normalizePath = (p: string, homeDir: string) => {\n if (!p || typeof p !== 'string') return null;\n let normalized = p.trim();\n if (!normalized) return null;\n if (normalized.startsWith('~/')) {\n normalized = path.join(homeDir, normalized.slice(2));\n } else if (normalized === '~') {\n normalized = homeDir;\n }\n return path.resolve(normalized);\n};\n\nexport const SuperpowersPlugin: Plugin = async ({ client, directory }) => {\n const homeDir = os.homedir();\n const superpowersSkillsDir = path.join(homeDir, '.agents/skills/superpowers');\n const latestAgentBySession = new Map<string, string>();\n // const superpowersSkillsDir = path.resolve(__dirname, '../../skills');\n // const envConfigDir = normalizePath(process.env.OPENCODE_CONFIG_DIR ?? '', homeDir);\n // const configDir = envConfigDir || path.join(homeDir, '.config/opencode');\n\n // Helper to generate bootstrap content\n const getBootstrapContent = () => {\n // Try to load using-superpowers skill\n const skillPath = path.join(superpowersSkillsDir, 'using-superpowers', 'SKILL.md');\n if (!fs.existsSync(skillPath)) return null;\n\n const fullContent = fs.readFileSync(skillPath, 'utf8');\n const { content } = extractAndStripFrontmatter(fullContent);\n\n const toolMapping = `**Tool Mapping for OpenCode:**\nWhen skills reference tools you don't have, substitute OpenCode equivalents:\n- \\`TodoWrite\\` \u2192 \\`update_plan\\`\n- \\`Task\\` tool with subagents \u2192 Use OpenCode's subagent system (@mention)\n- \\`Skill\\` tool \u2192 OpenCode's native \\`skill\\` tool\n- \\`Read\\`, \\`Write\\`, \\`Edit\\`, \\`Bash\\` \u2192 Your native tools\n\n**Skills location:**\nSuperpowers skills are in \\`${superpowersSkillsDir}/\\`\nUse OpenCode's native \\`skill\\` tool to list and load skills.`;\n\n return `<EXTREMELY_IMPORTANT>\nYou have superpowers.\n\n**IMPORTANT: The using-superpowers skill content is included below. It is ALREADY LOADED - you are currently following it. Do NOT use the skill tool to load \"using-superpowers\" again - that would be redundant.**\n\n${content}\n\n${toolMapping}\n</EXTREMELY_IMPORTANT>`;\n };\n\n return {\n 'chat.message': async (input) => {\n const agentName = normalizeAgentName(input.agent);\n if (!agentName) return;\n latestAgentBySession.set(input.sessionID, agentName);\n },\n // Use system prompt transform to inject bootstrap (fixes #226 agent reset bug)\n 'experimental.chat.system.transform': async (input, output) => {\n const sessionID = input.sessionID?.trim();\n const agentName = sessionID ? latestAgentBySession.get(sessionID) : undefined;\n if (!agentName || !PROMPT_INJECTION_AGENTS.has(agentName)) return;\n\n const bootstrap = getBootstrapContent();\n if (bootstrap) {\n if (!output.system) output.system = [];\n output.system.push(bootstrap);\n }\n }\n };\n};\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type { PluginInput } from \"@opencode-ai/plugin\";\n// Logger module for debugging\nconst ENV_DEBUG = \"OPENCODE_ANTHROPIC_CACHE_DEBUG\";\nlet _client: PluginInput[\"client\"] | null = null;\nfunction isDebugEnabled() {\n const val = process.env[ENV_DEBUG];\n return val === \"1\" || val?.toLowerCase() === \"true\";\n}\nexport function initLogger(client: PluginInput[\"client\"]) {\n _client = client;\n}\nexport function createLogger(module: string, prefix: string) {\n const service = `${prefix}.${module}`;\n const log = (\n level: \"debug\" | \"info\" | \"warn\" | \"error\",\n message: string,\n extra?: any,\n ) => {\n if (_client?.app && typeof _client.app.log === \"function\") {\n _client.app\n .log({ body: { service, level, message, extra } })\n .catch(() => {});\n return;\n }\n if (isDebugEnabled()) {\n const prefix = `[${service}]`;\n const args = extra ? [prefix, message, extra] : [prefix, message];\n switch (level) {\n case \"debug\":\n console.debug(...args);\n break;\n case \"info\":\n console.info(...args);\n break;\n case \"warn\":\n console.warn(...args);\n break;\n case \"error\":\n console.error(...args);\n break;\n }\n }\n };\n return {\n debug: (message: string, extra?: any) => log(\"debug\", message, extra),\n info: (message: string, extra?: any) => log(\"info\", message, extra),\n warn: (message: string, extra?: any) => log(\"warn\", message, extra),\n error: (message: string, extra?: any) => log(\"error\", message, extra),\n };\n}\n", "import type { Hooks, Plugin } from \"@opencode-ai/plugin\";\nimport { createLogger, initLogger } from \"./logger\";\n\nconst log = createLogger(\"fetch\", \"anthropic-cache\");\n// Session and project tracking\nlet currentSessionId = \"\";\nlet projectId = \"\";\nlet isInitialized = false;\nfunction buildUserId() {\n const pid = projectId || \"unknown\";\n const sid = currentSessionId || \"unknown\";\n return `user_${pid}_account__session_${sid}`;\n}\nfunction isJsonContentType(headers: Headers) {\n const ct = headers.get(\"content-type\") || \"\";\n return ct.includes(\"application/json\");\n}\nfunction parseBody(body?: unknown) {\n if (!body) return null;\n if (typeof body === \"string\") return body;\n if (body instanceof Uint8Array) return new TextDecoder().decode(body);\n return null;\n}\ntype CachePayload = {\n metadata?: {\n user_id?: string;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n};\n\n// Create the fetch interceptor that injects metadata.user_id\nfunction createCacheFetch(providerName: string) {\n return async (url: string | Request | URL, init?: RequestInit) => {\n const headers = new Headers(init?.headers);\n const method = (init?.method || \"GET\").toUpperCase();\n if (method !== \"POST\" || !isJsonContentType(headers)) {\n return fetch(url, init);\n }\n const rawBody = parseBody(init?.body);\n if (!rawBody) return fetch(url, init);\n let payload: CachePayload;\n try {\n payload = JSON.parse(rawBody) as CachePayload;\n } catch {\n log.warn(`[${providerName}] Failed to parse request body as JSON`);\n return fetch(url, init);\n }\n if (payload && typeof payload === \"object\") {\n if (!payload.metadata || typeof payload.metadata !== \"object\") {\n payload.metadata = {};\n }\n const meta = payload.metadata;\n if (meta.user_id == null) {\n meta.user_id = buildUserId();\n log.info(`[${providerName}] Injected user_id`, {\n user_id: meta.user_id,\n });\n }\n }\n headers.delete(\"content-length\");\n return fetch(url, { ...init, headers, body: JSON.stringify(payload) });\n };\n}\n// Shared event handler\nfunction createEventHandler(): Hooks[\"event\"] {\n return async ({ event }) => {\n if (event.type === \"session.created\" || event.type === \"session.updated\") {\n const props = event.properties;\n currentSessionId = props?.info?.id || \"\";\n log.debug(\"Session updated\", { sessionId: currentSessionId });\n }\n };\n}\n// Factory to create plugin for a specific provider\nfunction createProviderPlugin(providerName: string): Plugin {\n return async ({ project, client }) => {\n if (!isInitialized) {\n initLogger(client);\n projectId = project?.id || \"\";\n isInitialized = true;\n log.info(\"Plugin initialized\", { projectId });\n }\n log.info(`Auth handler registered for provider: ${providerName}`);\n return {\n event: createEventHandler(),\n auth: {\n provider: providerName,\n methods: [{ type: \"api\", label: \"key\" }],\n loader: async () => ({\n fetch: createCacheFetch(providerName),\n }),\n },\n };\n };\n}\n// Pre-built plugins for common providers\nexport const FoxcodeAwsCache = createProviderPlugin(\"foxcode-aws\");\nexport const AnthropicCache = createProviderPlugin(\"anthropic\");\nexport const AnthropicUltraCache = createProviderPlugin(\"anthropic-ultra\");\nexport const WormholeCache = createProviderPlugin(\"wormhole_a\");\n// Generic factory for custom provider names\nexport const createAnthropicCachePlugin = createProviderPlugin;\n", "import type { Plugin } from \"@opencode-ai/plugin\";\n\nconst OPENAI_PROVIDER_NPM = \"@ai-sdk/openai\";\nconst AGENT_SUFFIX_PREFIX = \"__agent__\";\nconst SESSION_HEADER_KEYS = [\n \"x-session-id\",\n \"conversation_id\",\n \"session_id\",\n] as const;\n\ntype HeaderMap = Record<string, unknown>;\n\nconst normalize = (value: unknown): string =>\n typeof value === \"string\" ? value.trim() : \"\";\n\nconst normalizeAgent = (value: unknown): string =>\n typeof value === \"string\" ? value.trim().toLowerCase() : \"\";\n\nconst stripAgentSuffix = (value: string): string =>\n value.replace(/__agent__[%A-Za-z0-9._~-]+$/, \"\");\n\nconst buildAgentScopedSessionValue = (\n sessionValue: string,\n input: { agent?: unknown },\n): string => {\n const baseSessionValue = stripAgentSuffix(sessionValue);\n const agent = normalizeAgent(input.agent);\n if (!agent) return baseSessionValue;\n\n const suffix = `${AGENT_SUFFIX_PREFIX}${encodeURIComponent(agent)}`;\n return `${baseSessionValue}${suffix}`;\n};\n\nconst pickHeaderSessionValue = (headers: HeaderMap): string => {\n for (const key of SESSION_HEADER_KEYS) {\n const value = normalize(headers[key]);\n if (value) return value;\n }\n return \"\";\n};\n\nconst ensureHeaders = (model: { headers?: unknown }): HeaderMap => {\n if (model.headers && typeof model.headers === \"object\") {\n return model.headers as HeaderMap;\n }\n const headers: HeaderMap = {};\n model.headers = headers;\n return headers;\n};\n\n/**\n * set a session-scoped prompt cache key and session-scoped sticky routing headers for right.codes.\n *\n * Injects HTTP headers via `input.model.headers` so upstream proxies/load\n * balancers can keep a conversation pinned to one account.\n *\n * Headers injected for @ai-sdk/openai providers:\n * - x-session-id\n * - conversation_id\n * - session_id\n *\n * Source of truth (in order):\n * - env: OPENCODE_PROMPT_CACHE_KEY (manual override)\n * - env: OPENCODE_STICKY_SESSION_ID (manual override)\n * - model headers (x-session-id / conversation_id / session_id)\n * - opencode sessionID (default)\n */\nexport const StickySessionPlugin: Plugin = async ({ client }) => {\n const envPromptCacheKey = normalize(process.env.OPENCODE_PROMPT_CACHE_KEY);\n const envStickySessionID = normalize(process.env.OPENCODE_STICKY_SESSION_ID);\n const envOverride = envPromptCacheKey || envStickySessionID;\n const isProviderCodexMap: Record<string, boolean> = {};\n let inited = false;\n const init = async () => {\n if (inited) return;\n const resp = await client.config.providers();\n const providers = resp.data?.providers ?? [];\n for (const provider of providers) {\n isProviderCodexMap[provider.id] = Boolean(provider.options?.isCodex);\n }\n inited = true;\n };\n\n return {\n \"chat.params\": async (input, output) => {\n if (!inited) await init();\n const providerNpm = normalize(input.model.api.npm);\n const isCodex = isProviderCodexMap[input.model.providerID] ?? false;\n if (!providerNpm.includes(OPENAI_PROVIDER_NPM) && !isCodex) return;\n\n const headers = ensureHeaders(input.model);\n const baseSessionValue =\n envOverride ||\n pickHeaderSessionValue(headers) ||\n normalize(input.sessionID);\n if (!baseSessionValue) return;\n\n const sessionValue = buildAgentScopedSessionValue(\n baseSessionValue,\n input,\n );\n\n for (const key of SESSION_HEADER_KEYS) {\n headers[key] = sessionValue;\n }\n\n output.options.promptCacheKey = sessionValue;\n // if (isCodex && !output.options.instructions) {\n // output.options.instructions = \"\";\n // }\n },\n };\n};\n\nexport default StickySessionPlugin;\n", "/**\n * Superpowers plugin for OpenCode.ai\n *\n * Injects superpowers bootstrap context via system prompt transform.\n * Skills are discovered via OpenCode's native skill tool from symlinked directory.\n */\n\nimport path from 'path';\nimport fs from 'fs';\nimport os from 'os';\nimport { fileURLToPath } from 'url';\nimport type { Plugin } from '@opencode-ai/plugin';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst OH_MY_OPENAGENT_AGENTS = new Set([\n // https://github.com/code-yeongyu/oh-my-openagent\n 'sisyphus', 'hephaestus', 'oracle', 'librarian',\n 'explore', 'multimodal-looker', 'prometheus',\n 'metis', 'momus', 'atlas', 'sisyphus-junior',\n])\nconst PROMPT_INJECTION_AGENTS = new Set([\n 'plan', 'build', //'compaction',\n // https://github.com/alvinunreal/oh-my-opencode-slim\n 'orchestrator',\n // ...OH_MY_OPENAGENT_AGENTS,\n])\n\nconst normalizeAgentName = (name: unknown) =>\n typeof name === 'string' ? name.trim().toLowerCase() : '';\n\n// Simple frontmatter extraction (avoid dependency on skills-core for bootstrap)\nconst extractAndStripFrontmatter = (content: string) => {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---\\n([\\s\\S]*)$/);\n if (!match) return { frontmatter: {}, content };\n\n const frontmatterStr = match[1];\n const body = match[2];\n const frontmatter: Record<string, string> = {};\n\n for (const line of frontmatterStr.split('\\n')) {\n const colonIdx = line.indexOf(':');\n if (colonIdx > 0) {\n // \u55B5~ \u8FD9\u6BB5\u4EE3\u7801\u7684\u4F5C\u7528\u662F\u89E3\u6790 frontmatter \u7684\u6BCF\u4E00\u884C\uFF1A\n // 1. \u63D0\u53D6\u5192\u53F7\u524D\u7684\u90E8\u5206\u4F5C\u4E3A key \u5E76\u53BB\u9664\u7A7A\u683C\u3002\n // 2. \u63D0\u53D6\u5192\u53F7\u540E\u7684\u90E8\u5206\u4F5C\u4E3A value\uFF0C\u53BB\u9664\u7A7A\u683C\u5E76\u5265\u79BB\u4E24\u4FA7\u7684\u5F15\u53F7\u3002\n // 3. \u5C06\u7ED3\u679C\u5B58\u5165 frontmatter \u5BF9\u8C61\uFF08\u6B64\u5904\u9700\u65AD\u8A00\u7C7B\u578B\u4EE5\u907F\u514D TS \u7D22\u5F15\u9519\u8BEF\uFF09\u3002\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim().replace(/^[\"']|[\"']$/g, '');\n frontmatter[key] = value;\n }\n }\n\n return { frontmatter, content: body };\n};\n\n// Normalize a path: trim whitespace, expand ~, resolve to absolute\nconst normalizePath = (p: string, homeDir: string) => {\n if (!p || typeof p !== 'string') return null;\n let normalized = p.trim();\n if (!normalized) return null;\n if (normalized.startsWith('~/')) {\n normalized = path.join(homeDir, normalized.slice(2));\n } else if (normalized === '~') {\n normalized = homeDir;\n }\n return path.resolve(normalized);\n};\n\nexport const SuperpowersPlugin: Plugin = async ({ client, directory }) => {\n const homeDir = os.homedir();\n const superpowersSkillsDir = path.join(homeDir, '.agents/skills/superpowers');\n const latestAgentBySession = new Map<string, string>();\n // const superpowersSkillsDir = path.resolve(__dirname, '../../skills');\n // const envConfigDir = normalizePath(process.env.OPENCODE_CONFIG_DIR ?? '', homeDir);\n // const configDir = envConfigDir || path.join(homeDir, '.config/opencode');\n\n // Helper to generate bootstrap content\n const getBootstrapContent = () => {\n // Try to load using-superpowers skill\n const skillPath = path.join(superpowersSkillsDir, 'using-superpowers', 'SKILL.md');\n if (!fs.existsSync(skillPath)) return null;\n\n const fullContent = fs.readFileSync(skillPath, 'utf8');\n const { content } = extractAndStripFrontmatter(fullContent);\n\n const toolMapping = `**Tool Mapping for OpenCode:**\nWhen skills reference tools you don't have, substitute OpenCode equivalents:\n- \\`TodoWrite\\` \u2192 \\`update_plan\\`\n- \\`Task\\` tool with subagents \u2192 Use OpenCode's subagent system (@mention)\n- \\`Skill\\` tool \u2192 OpenCode's native \\`skill\\` tool\n- \\`Read\\`, \\`Write\\`, \\`Edit\\`, \\`Bash\\` \u2192 Your native tools\n\n**Skills location:**\nSuperpowers skills are in \\`${superpowersSkillsDir}/\\`\nUse OpenCode's native \\`skill\\` tool to list and load skills.`;\n\n return `<EXTREMELY_IMPORTANT>\nYou have superpowers.\n\n**IMPORTANT: The using-superpowers skill content is included below. It is ALREADY LOADED - you are currently following it. Do NOT use the skill tool to load \"using-superpowers\" again - that would be redundant.**\n\n${content}\n\n${toolMapping}\n</EXTREMELY_IMPORTANT>`;\n };\n\n return {\n 'chat.message': async (input) => {\n const agentName = normalizeAgentName(input.agent);\n if (!agentName) return;\n latestAgentBySession.set(input.sessionID, agentName);\n },\n // Use system prompt transform to inject bootstrap (fixes #226 agent reset bug)\n 'experimental.chat.system.transform': async (input, output) => {\n const sessionID = input.sessionID?.trim();\n const agentName = sessionID ? latestAgentBySession.get(sessionID) : undefined;\n if (!agentName || !PROMPT_INJECTION_AGENTS.has(agentName)) return;\n\n const bootstrap = getBootstrapContent();\n if (bootstrap) {\n if (!output.system) output.system = [];\n output.system.push(bootstrap);\n }\n }\n };\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["log", "prefix"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sticky-session-plugin.d.ts","sourceRoot":"","sources":["../src/sticky-session-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"sticky-session-plugin.d.ts","sourceRoot":"","sources":["../src/sticky-session-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAkDlD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mBAAmB,EAAE,MA6CjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-fixes-huihui",
|
|
3
|
-
"version": "0.1.4-beta.
|
|
3
|
+
"version": "0.1.4-beta.16",
|
|
4
4
|
"description": "Unified sticky-session plugin for opencode with session headers and prompt cache key.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
"node": ">=18"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@biomejs/biome": "^2.4.
|
|
53
|
-
"@opencode-ai/plugin": "^1.
|
|
52
|
+
"@biomejs/biome": "^2.4.9",
|
|
53
|
+
"@opencode-ai/plugin": "^1.3.3",
|
|
54
54
|
"@types/node": "^25.5.0",
|
|
55
55
|
"esbuild": "^0.27.4",
|
|
56
|
-
"typescript": "^
|
|
56
|
+
"typescript": "^6.0.2"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"opencode-anthropic-cache": "^1.0.0"
|