oh-my-opencode 3.1.4 → 3.1.6
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/agents/metis.d.ts +1 -1
- package/dist/agents/prometheus-prompt.d.ts +1 -1
- package/dist/cli/index.js +24 -23
- package/dist/features/opencode-skill-loader/types.d.ts +1 -1
- package/dist/index.js +563 -272
- package/dist/shared/agent-variant.d.ts +4 -0
- package/dist/shared/ollama-ndjson-parser.d.ts +108 -0
- package/dist/shared/opencode-version.d.ts +8 -0
- package/dist/shared/system-directive.d.ts +14 -0
- package/dist/shared/system-directive.test.d.ts +1 -0
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -236,6 +236,9 @@ function createSystemDirective(type) {
|
|
|
236
236
|
function isSystemDirective(text) {
|
|
237
237
|
return text.trimStart().startsWith(SYSTEM_DIRECTIVE_PREFIX);
|
|
238
238
|
}
|
|
239
|
+
function removeSystemReminders(text) {
|
|
240
|
+
return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/gi, "").trim();
|
|
241
|
+
}
|
|
239
242
|
var SYSTEM_DIRECTIVE_PREFIX = "[SYSTEM DIRECTIVE: OH-MY-OPENCODE", SystemDirectiveTypes;
|
|
240
243
|
var init_system_directive = __esm(() => {
|
|
241
244
|
SystemDirectiveTypes = {
|
|
@@ -4550,9 +4553,56 @@ var TAURI_APP_IDENTIFIER = "ai.opencode.desktop", TAURI_APP_IDENTIFIER_DEV = "ai
|
|
|
4550
4553
|
var init_opencode_config_dir = () => {};
|
|
4551
4554
|
|
|
4552
4555
|
// src/shared/opencode-version.ts
|
|
4553
|
-
|
|
4556
|
+
import { execSync } from "child_process";
|
|
4557
|
+
function parseVersion(version) {
|
|
4558
|
+
const cleaned = version.replace(/^v/, "").split("-")[0];
|
|
4559
|
+
return cleaned.split(".").map((n) => parseInt(n, 10) || 0);
|
|
4560
|
+
}
|
|
4561
|
+
function compareVersions(a, b) {
|
|
4562
|
+
const partsA = parseVersion(a);
|
|
4563
|
+
const partsB = parseVersion(b);
|
|
4564
|
+
const maxLen = Math.max(partsA.length, partsB.length);
|
|
4565
|
+
for (let i2 = 0;i2 < maxLen; i2++) {
|
|
4566
|
+
const numA = partsA[i2] ?? 0;
|
|
4567
|
+
const numB = partsB[i2] ?? 0;
|
|
4568
|
+
if (numA < numB)
|
|
4569
|
+
return -1;
|
|
4570
|
+
if (numA > numB)
|
|
4571
|
+
return 1;
|
|
4572
|
+
}
|
|
4573
|
+
return 0;
|
|
4574
|
+
}
|
|
4575
|
+
function isVersionGte(a, b) {
|
|
4576
|
+
return compareVersions(a, b) >= 0;
|
|
4577
|
+
}
|
|
4578
|
+
function getOpenCodeVersion() {
|
|
4579
|
+
if (cachedVersion !== NOT_CACHED) {
|
|
4580
|
+
return cachedVersion;
|
|
4581
|
+
}
|
|
4582
|
+
try {
|
|
4583
|
+
const result = execSync("opencode --version", {
|
|
4584
|
+
encoding: "utf-8",
|
|
4585
|
+
timeout: 5000,
|
|
4586
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
4587
|
+
}).trim();
|
|
4588
|
+
const versionMatch = result.match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
|
|
4589
|
+
cachedVersion = versionMatch?.[1] ?? null;
|
|
4590
|
+
return cachedVersion;
|
|
4591
|
+
} catch {
|
|
4592
|
+
cachedVersion = null;
|
|
4593
|
+
return null;
|
|
4594
|
+
}
|
|
4595
|
+
}
|
|
4596
|
+
function isOpenCodeVersionAtLeast(version) {
|
|
4597
|
+
const current = getOpenCodeVersion();
|
|
4598
|
+
if (!current)
|
|
4599
|
+
return true;
|
|
4600
|
+
return isVersionGte(current, version);
|
|
4601
|
+
}
|
|
4602
|
+
var OPENCODE_NATIVE_AGENTS_INJECTION_VERSION = "1.1.37", NOT_CACHED, cachedVersion;
|
|
4554
4603
|
var init_opencode_version = __esm(() => {
|
|
4555
4604
|
NOT_CACHED = Symbol("NOT_CACHED");
|
|
4605
|
+
cachedVersion = NOT_CACHED;
|
|
4556
4606
|
});
|
|
4557
4607
|
|
|
4558
4608
|
// src/shared/permission-compat.ts
|
|
@@ -4783,6 +4833,131 @@ function equalsIgnoreCase(a, b) {
|
|
|
4783
4833
|
return a.toLowerCase() === b.toLowerCase();
|
|
4784
4834
|
}
|
|
4785
4835
|
|
|
4836
|
+
// src/shared/model-requirements.ts
|
|
4837
|
+
var AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS;
|
|
4838
|
+
var init_model_requirements = __esm(() => {
|
|
4839
|
+
AGENT_MODEL_REQUIREMENTS = {
|
|
4840
|
+
sisyphus: {
|
|
4841
|
+
fallbackChain: [
|
|
4842
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4843
|
+
{ providers: ["zai-coding-plan"], model: "glm-4.7" },
|
|
4844
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
|
|
4845
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
4846
|
+
]
|
|
4847
|
+
},
|
|
4848
|
+
oracle: {
|
|
4849
|
+
fallbackChain: [
|
|
4850
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
|
|
4851
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4852
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
4853
|
+
]
|
|
4854
|
+
},
|
|
4855
|
+
librarian: {
|
|
4856
|
+
fallbackChain: [
|
|
4857
|
+
{ providers: ["zai-coding-plan"], model: "glm-4.7" },
|
|
4858
|
+
{ providers: ["opencode"], model: "big-pickle" },
|
|
4859
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" }
|
|
4860
|
+
]
|
|
4861
|
+
},
|
|
4862
|
+
explore: {
|
|
4863
|
+
fallbackChain: [
|
|
4864
|
+
{ providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" },
|
|
4865
|
+
{ providers: ["github-copilot"], model: "gpt-5-mini" },
|
|
4866
|
+
{ providers: ["opencode"], model: "gpt-5-nano" }
|
|
4867
|
+
]
|
|
4868
|
+
},
|
|
4869
|
+
"multimodal-looker": {
|
|
4870
|
+
fallbackChain: [
|
|
4871
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
|
|
4872
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
|
|
4873
|
+
{ providers: ["zai-coding-plan"], model: "glm-4.6v" },
|
|
4874
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
|
|
4875
|
+
{ providers: ["opencode"], model: "gpt-5-nano" }
|
|
4876
|
+
]
|
|
4877
|
+
},
|
|
4878
|
+
prometheus: {
|
|
4879
|
+
fallbackChain: [
|
|
4880
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4881
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
|
|
4882
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
4883
|
+
]
|
|
4884
|
+
},
|
|
4885
|
+
metis: {
|
|
4886
|
+
fallbackChain: [
|
|
4887
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4888
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
|
|
4889
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
|
|
4890
|
+
]
|
|
4891
|
+
},
|
|
4892
|
+
momus: {
|
|
4893
|
+
fallbackChain: [
|
|
4894
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "medium" },
|
|
4895
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5" },
|
|
4896
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
|
|
4897
|
+
]
|
|
4898
|
+
},
|
|
4899
|
+
atlas: {
|
|
4900
|
+
fallbackChain: [
|
|
4901
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
|
|
4902
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
|
|
4903
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
4904
|
+
]
|
|
4905
|
+
}
|
|
4906
|
+
};
|
|
4907
|
+
CATEGORY_MODEL_REQUIREMENTS = {
|
|
4908
|
+
"visual-engineering": {
|
|
4909
|
+
fallbackChain: [
|
|
4910
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" },
|
|
4911
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4912
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }
|
|
4913
|
+
]
|
|
4914
|
+
},
|
|
4915
|
+
ultrabrain: {
|
|
4916
|
+
fallbackChain: [
|
|
4917
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "xhigh" },
|
|
4918
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4919
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
4920
|
+
]
|
|
4921
|
+
},
|
|
4922
|
+
artistry: {
|
|
4923
|
+
fallbackChain: [
|
|
4924
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" },
|
|
4925
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4926
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }
|
|
4927
|
+
]
|
|
4928
|
+
},
|
|
4929
|
+
quick: {
|
|
4930
|
+
fallbackChain: [
|
|
4931
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
|
|
4932
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
|
|
4933
|
+
{ providers: ["opencode"], model: "gpt-5-nano" }
|
|
4934
|
+
]
|
|
4935
|
+
},
|
|
4936
|
+
"unspecified-low": {
|
|
4937
|
+
fallbackChain: [
|
|
4938
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
|
|
4939
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
|
|
4940
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" }
|
|
4941
|
+
]
|
|
4942
|
+
},
|
|
4943
|
+
"unspecified-high": {
|
|
4944
|
+
fallbackChain: [
|
|
4945
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4946
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
|
|
4947
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
4948
|
+
]
|
|
4949
|
+
},
|
|
4950
|
+
writing: {
|
|
4951
|
+
fallbackChain: [
|
|
4952
|
+
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
|
|
4953
|
+
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
|
|
4954
|
+
{ providers: ["zai-coding-plan"], model: "glm-4.7" },
|
|
4955
|
+
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }
|
|
4956
|
+
]
|
|
4957
|
+
}
|
|
4958
|
+
};
|
|
4959
|
+
});
|
|
4960
|
+
|
|
4786
4961
|
// src/shared/agent-variant.ts
|
|
4787
4962
|
function resolveAgentVariant(config, agentName) {
|
|
4788
4963
|
if (!agentName) {
|
|
@@ -4802,13 +4977,39 @@ function resolveAgentVariant(config, agentName) {
|
|
|
4802
4977
|
}
|
|
4803
4978
|
return config.categories?.[categoryName]?.variant;
|
|
4804
4979
|
}
|
|
4980
|
+
function resolveVariantForModel(config, agentName, currentModel) {
|
|
4981
|
+
const agentRequirement = AGENT_MODEL_REQUIREMENTS[agentName];
|
|
4982
|
+
if (agentRequirement) {
|
|
4983
|
+
return findVariantInChain(agentRequirement.fallbackChain, currentModel.providerID);
|
|
4984
|
+
}
|
|
4985
|
+
const agentOverrides = config.agents;
|
|
4986
|
+
const agentOverride = agentOverrides ? findCaseInsensitive(agentOverrides, agentName) : undefined;
|
|
4987
|
+
const categoryName = agentOverride?.category;
|
|
4988
|
+
if (categoryName) {
|
|
4989
|
+
const categoryRequirement = CATEGORY_MODEL_REQUIREMENTS[categoryName];
|
|
4990
|
+
if (categoryRequirement) {
|
|
4991
|
+
return findVariantInChain(categoryRequirement.fallbackChain, currentModel.providerID);
|
|
4992
|
+
}
|
|
4993
|
+
}
|
|
4994
|
+
return;
|
|
4995
|
+
}
|
|
4996
|
+
function findVariantInChain(fallbackChain, providerID) {
|
|
4997
|
+
for (const entry of fallbackChain) {
|
|
4998
|
+
if (entry.providers.includes(providerID)) {
|
|
4999
|
+
return entry.variant;
|
|
5000
|
+
}
|
|
5001
|
+
}
|
|
5002
|
+
return;
|
|
5003
|
+
}
|
|
4805
5004
|
function applyAgentVariant(config, agentName, message) {
|
|
4806
5005
|
const variant = resolveAgentVariant(config, agentName);
|
|
4807
5006
|
if (variant !== undefined && message.variant === undefined) {
|
|
4808
5007
|
message.variant = variant;
|
|
4809
5008
|
}
|
|
4810
5009
|
}
|
|
4811
|
-
var init_agent_variant = () => {
|
|
5010
|
+
var init_agent_variant = __esm(() => {
|
|
5011
|
+
init_model_requirements();
|
|
5012
|
+
});
|
|
4812
5013
|
|
|
4813
5014
|
// src/shared/session-cursor.ts
|
|
4814
5015
|
function buildMessageKey(message, index) {
|
|
@@ -4942,131 +5143,6 @@ var init_agent_tool_restrictions = __esm(() => {
|
|
|
4942
5143
|
};
|
|
4943
5144
|
});
|
|
4944
5145
|
|
|
4945
|
-
// src/shared/model-requirements.ts
|
|
4946
|
-
var AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS;
|
|
4947
|
-
var init_model_requirements = __esm(() => {
|
|
4948
|
-
AGENT_MODEL_REQUIREMENTS = {
|
|
4949
|
-
sisyphus: {
|
|
4950
|
-
fallbackChain: [
|
|
4951
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4952
|
-
{ providers: ["zai-coding-plan"], model: "glm-4.7" },
|
|
4953
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
|
|
4954
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
4955
|
-
]
|
|
4956
|
-
},
|
|
4957
|
-
oracle: {
|
|
4958
|
-
fallbackChain: [
|
|
4959
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
|
|
4960
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4961
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
4962
|
-
]
|
|
4963
|
-
},
|
|
4964
|
-
librarian: {
|
|
4965
|
-
fallbackChain: [
|
|
4966
|
-
{ providers: ["zai-coding-plan"], model: "glm-4.7" },
|
|
4967
|
-
{ providers: ["opencode"], model: "big-pickle" },
|
|
4968
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" }
|
|
4969
|
-
]
|
|
4970
|
-
},
|
|
4971
|
-
explore: {
|
|
4972
|
-
fallbackChain: [
|
|
4973
|
-
{ providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" },
|
|
4974
|
-
{ providers: ["github-copilot"], model: "gpt-5-mini" },
|
|
4975
|
-
{ providers: ["opencode"], model: "gpt-5-nano" }
|
|
4976
|
-
]
|
|
4977
|
-
},
|
|
4978
|
-
"multimodal-looker": {
|
|
4979
|
-
fallbackChain: [
|
|
4980
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
|
|
4981
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
|
|
4982
|
-
{ providers: ["zai-coding-plan"], model: "glm-4.6v" },
|
|
4983
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
|
|
4984
|
-
{ providers: ["opencode"], model: "gpt-5-nano" }
|
|
4985
|
-
]
|
|
4986
|
-
},
|
|
4987
|
-
prometheus: {
|
|
4988
|
-
fallbackChain: [
|
|
4989
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4990
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
|
|
4991
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
4992
|
-
]
|
|
4993
|
-
},
|
|
4994
|
-
metis: {
|
|
4995
|
-
fallbackChain: [
|
|
4996
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
4997
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
|
|
4998
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
|
|
4999
|
-
]
|
|
5000
|
-
},
|
|
5001
|
-
momus: {
|
|
5002
|
-
fallbackChain: [
|
|
5003
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "medium" },
|
|
5004
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5" },
|
|
5005
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" }
|
|
5006
|
-
]
|
|
5007
|
-
},
|
|
5008
|
-
atlas: {
|
|
5009
|
-
fallbackChain: [
|
|
5010
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
|
|
5011
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
|
|
5012
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
5013
|
-
]
|
|
5014
|
-
}
|
|
5015
|
-
};
|
|
5016
|
-
CATEGORY_MODEL_REQUIREMENTS = {
|
|
5017
|
-
"visual-engineering": {
|
|
5018
|
-
fallbackChain: [
|
|
5019
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" },
|
|
5020
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
5021
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }
|
|
5022
|
-
]
|
|
5023
|
-
},
|
|
5024
|
-
ultrabrain: {
|
|
5025
|
-
fallbackChain: [
|
|
5026
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "xhigh" },
|
|
5027
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
5028
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
5029
|
-
]
|
|
5030
|
-
},
|
|
5031
|
-
artistry: {
|
|
5032
|
-
fallbackChain: [
|
|
5033
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "max" },
|
|
5034
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
5035
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }
|
|
5036
|
-
]
|
|
5037
|
-
},
|
|
5038
|
-
quick: {
|
|
5039
|
-
fallbackChain: [
|
|
5040
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
|
|
5041
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
|
|
5042
|
-
{ providers: ["opencode"], model: "gpt-5-nano" }
|
|
5043
|
-
]
|
|
5044
|
-
},
|
|
5045
|
-
"unspecified-low": {
|
|
5046
|
-
fallbackChain: [
|
|
5047
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
|
|
5048
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
|
|
5049
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" }
|
|
5050
|
-
]
|
|
5051
|
-
},
|
|
5052
|
-
"unspecified-high": {
|
|
5053
|
-
fallbackChain: [
|
|
5054
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
|
|
5055
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
|
|
5056
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }
|
|
5057
|
-
]
|
|
5058
|
-
},
|
|
5059
|
-
writing: {
|
|
5060
|
-
fallbackChain: [
|
|
5061
|
-
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
|
|
5062
|
-
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
|
|
5063
|
-
{ providers: ["zai-coding-plan"], model: "glm-4.7" },
|
|
5064
|
-
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }
|
|
5065
|
-
]
|
|
5066
|
-
}
|
|
5067
|
-
};
|
|
5068
|
-
});
|
|
5069
|
-
|
|
5070
5146
|
// src/shared/connected-providers-cache.ts
|
|
5071
5147
|
import { existsSync as existsSync9, readFileSync as readFileSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
5072
5148
|
import { join as join12 } from "path";
|
|
@@ -5328,26 +5404,7 @@ function resolveModelWithFallback(input) {
|
|
|
5328
5404
|
}
|
|
5329
5405
|
if (fallbackChain && fallbackChain.length > 0) {
|
|
5330
5406
|
if (availableModels.size === 0) {
|
|
5331
|
-
|
|
5332
|
-
const connectedSet = connectedProviders ? new Set(connectedProviders) : null;
|
|
5333
|
-
if (connectedSet === null) {
|
|
5334
|
-
log("No cache available, skipping fallback chain to use system default");
|
|
5335
|
-
} else {
|
|
5336
|
-
for (const entry of fallbackChain) {
|
|
5337
|
-
for (const provider of entry.providers) {
|
|
5338
|
-
if (connectedSet.has(provider)) {
|
|
5339
|
-
const model = `${provider}/${entry.model}`;
|
|
5340
|
-
log("Model resolved via fallback chain (no model cache, using connected provider)", {
|
|
5341
|
-
provider,
|
|
5342
|
-
model: entry.model,
|
|
5343
|
-
variant: entry.variant
|
|
5344
|
-
});
|
|
5345
|
-
return { model, source: "provider-fallback", variant: entry.variant };
|
|
5346
|
-
}
|
|
5347
|
-
}
|
|
5348
|
-
}
|
|
5349
|
-
log("No matching provider in connected cache, falling through to system default");
|
|
5350
|
-
}
|
|
5407
|
+
log("No model cache available, skipping fallback chain to use system default");
|
|
5351
5408
|
}
|
|
5352
5409
|
for (const entry of fallbackChain) {
|
|
5353
5410
|
for (const provider of entry.providers) {
|
|
@@ -5371,7 +5428,6 @@ function resolveModelWithFallback(input) {
|
|
|
5371
5428
|
var init_model_resolver = __esm(() => {
|
|
5372
5429
|
init_logger();
|
|
5373
5430
|
init_model_availability();
|
|
5374
|
-
init_connected_providers_cache();
|
|
5375
5431
|
});
|
|
5376
5432
|
|
|
5377
5433
|
// src/shared/session-utils.ts
|
|
@@ -7531,9 +7587,9 @@ v${latestVersion} available. Restart OpenCode to apply.` : `OpenCode is now on S
|
|
|
7531
7587
|
return;
|
|
7532
7588
|
hasChecked = true;
|
|
7533
7589
|
setTimeout(async () => {
|
|
7534
|
-
const
|
|
7590
|
+
const cachedVersion2 = getCachedVersion();
|
|
7535
7591
|
const localDevVersion = getLocalDevVersion(ctx.directory);
|
|
7536
|
-
const displayVersion = localDevVersion ??
|
|
7592
|
+
const displayVersion = localDevVersion ?? cachedVersion2;
|
|
7537
7593
|
await showConfigErrorsIfAny(ctx);
|
|
7538
7594
|
await showModelCacheWarningIfNeeded(ctx);
|
|
7539
7595
|
await updateAndShowConnectedProvidersCacheStatus(ctx);
|
|
@@ -7560,8 +7616,8 @@ async function runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage) {
|
|
|
7560
7616
|
log("[auto-update-checker] Plugin not found in config");
|
|
7561
7617
|
return;
|
|
7562
7618
|
}
|
|
7563
|
-
const
|
|
7564
|
-
const currentVersion =
|
|
7619
|
+
const cachedVersion2 = getCachedVersion();
|
|
7620
|
+
const currentVersion = cachedVersion2 ?? pluginInfo.pinnedVersion;
|
|
7565
7621
|
if (!currentVersion) {
|
|
7566
7622
|
log("[auto-update-checker] No version found (cached or pinned)");
|
|
7567
7623
|
return;
|
|
@@ -18505,7 +18561,7 @@ async function executePreToolUseHooks(ctx, config, extendedConfig) {
|
|
|
18505
18561
|
}
|
|
18506
18562
|
if (result.stdout) {
|
|
18507
18563
|
try {
|
|
18508
|
-
const output = JSON.parse(result.stdout);
|
|
18564
|
+
const output = JSON.parse(result.stdout || "{}");
|
|
18509
18565
|
let decision;
|
|
18510
18566
|
let reason;
|
|
18511
18567
|
let modifiedInput;
|
|
@@ -18741,7 +18797,7 @@ ${result.stderr.trim()}`);
|
|
|
18741
18797
|
}
|
|
18742
18798
|
if (result.exitCode === 0 && result.stdout) {
|
|
18743
18799
|
try {
|
|
18744
|
-
const output = JSON.parse(result.stdout);
|
|
18800
|
+
const output = JSON.parse(result.stdout || "{}");
|
|
18745
18801
|
if (output.decision === "block") {
|
|
18746
18802
|
return {
|
|
18747
18803
|
block: true,
|
|
@@ -18934,7 +18990,7 @@ async function executeStopHooks(ctx, config, extendedConfig) {
|
|
|
18934
18990
|
}
|
|
18935
18991
|
if (result.stdout) {
|
|
18936
18992
|
try {
|
|
18937
|
-
const output = JSON.parse(result.stdout);
|
|
18993
|
+
const output = JSON.parse(result.stdout || "{}");
|
|
18938
18994
|
if (output.stop_hook_active !== undefined) {
|
|
18939
18995
|
stopHookActiveState.set(ctx.sessionId, output.stop_hook_active);
|
|
18940
18996
|
}
|
|
@@ -18991,7 +19047,7 @@ async function executePreCompactHooks(ctx, config, extendedConfig) {
|
|
|
18991
19047
|
}
|
|
18992
19048
|
if (result.stdout) {
|
|
18993
19049
|
try {
|
|
18994
|
-
const output = JSON.parse(result.stdout);
|
|
19050
|
+
const output = JSON.parse(result.stdout || "{}");
|
|
18995
19051
|
if (output.hookSpecificOutput?.additionalContext) {
|
|
18996
19052
|
collectedContext.push(...output.hookSpecificOutput.additionalContext);
|
|
18997
19053
|
} else if (output.context) {
|
|
@@ -19194,6 +19250,9 @@ ${result.inputLines ?? ""}`,
|
|
|
19194
19250
|
}
|
|
19195
19251
|
},
|
|
19196
19252
|
"tool.execute.after": async (input, output) => {
|
|
19253
|
+
if (!output) {
|
|
19254
|
+
return;
|
|
19255
|
+
}
|
|
19197
19256
|
const claudeConfig = await loadClaudeHooksConfig();
|
|
19198
19257
|
const extendedConfig = await loadPluginExtendedConfig();
|
|
19199
19258
|
const cachedInput = getToolInput(input.sessionID, input.tool, input.callID) || {};
|
|
@@ -20064,7 +20123,81 @@ You ARE the planner. Your job: create bulletproof work plans.
|
|
|
20064
20123
|
- External library APIs and constraints
|
|
20065
20124
|
- Similar implementations in OSS (via librarian)
|
|
20066
20125
|
|
|
20067
|
-
**NEVER plan blind. Context first, plan second
|
|
20126
|
+
**NEVER plan blind. Context first, plan second.**
|
|
20127
|
+
|
|
20128
|
+
---
|
|
20129
|
+
|
|
20130
|
+
## MANDATORY OUTPUT: PARALLEL TASK GRAPH + TODO LIST
|
|
20131
|
+
|
|
20132
|
+
**YOUR PRIMARY OUTPUT IS A PARALLEL EXECUTION TASK GRAPH.**
|
|
20133
|
+
|
|
20134
|
+
When you finalize a plan, you MUST structure it for maximum parallel execution:
|
|
20135
|
+
|
|
20136
|
+
### 1. Parallel Execution Waves (REQUIRED)
|
|
20137
|
+
|
|
20138
|
+
Analyze task dependencies and group independent tasks into parallel waves:
|
|
20139
|
+
|
|
20140
|
+
\`\`\`
|
|
20141
|
+
Wave 1 (Start Immediately - No Dependencies):
|
|
20142
|
+
\u251C\u2500\u2500 Task 1: [description] \u2192 category: X, skills: [a, b]
|
|
20143
|
+
\u2514\u2500\u2500 Task 4: [description] \u2192 category: Y, skills: [c]
|
|
20144
|
+
|
|
20145
|
+
Wave 2 (After Wave 1 Completes):
|
|
20146
|
+
\u251C\u2500\u2500 Task 2: [depends: 1] \u2192 category: X, skills: [a]
|
|
20147
|
+
\u251C\u2500\u2500 Task 3: [depends: 1] \u2192 category: Z, skills: [d]
|
|
20148
|
+
\u2514\u2500\u2500 Task 5: [depends: 4] \u2192 category: Y, skills: [c]
|
|
20149
|
+
|
|
20150
|
+
Wave 3 (After Wave 2 Completes):
|
|
20151
|
+
\u2514\u2500\u2500 Task 6: [depends: 2, 3] \u2192 category: X, skills: [a, b]
|
|
20152
|
+
|
|
20153
|
+
Critical Path: Task 1 \u2192 Task 2 \u2192 Task 6
|
|
20154
|
+
Estimated Parallel Speedup: ~40% faster than sequential
|
|
20155
|
+
\`\`\`
|
|
20156
|
+
|
|
20157
|
+
### 2. Dependency Matrix (REQUIRED)
|
|
20158
|
+
|
|
20159
|
+
| Task | Depends On | Blocks | Can Parallelize With |
|
|
20160
|
+
|------|------------|--------|---------------------|
|
|
20161
|
+
| 1 | None | 2, 3 | 4 |
|
|
20162
|
+
| 2 | 1 | 6 | 3, 5 |
|
|
20163
|
+
| 3 | 1 | 6 | 2, 5 |
|
|
20164
|
+
| 4 | None | 5 | 1 |
|
|
20165
|
+
| 5 | 4 | None | 2, 3 |
|
|
20166
|
+
| 6 | 2, 3 | None | None (final) |
|
|
20167
|
+
|
|
20168
|
+
### 3. TODO List Structure (REQUIRED)
|
|
20169
|
+
|
|
20170
|
+
Each TODO item MUST include:
|
|
20171
|
+
|
|
20172
|
+
\`\`\`markdown
|
|
20173
|
+
- [ ] N. [Task Title]
|
|
20174
|
+
|
|
20175
|
+
**What to do**: [Clear steps]
|
|
20176
|
+
|
|
20177
|
+
**Dependencies**: [Task numbers this depends on] | None
|
|
20178
|
+
**Blocks**: [Task numbers that depend on this]
|
|
20179
|
+
**Parallel Group**: Wave N (with Tasks X, Y)
|
|
20180
|
+
|
|
20181
|
+
**Recommended Agent Profile**:
|
|
20182
|
+
- **Category**: \`[visual-engineering | ultrabrain | artistry | quick | unspecified-low | unspecified-high | writing]\`
|
|
20183
|
+
- **Skills**: [\`skill-1\`, \`skill-2\`]
|
|
20184
|
+
|
|
20185
|
+
**Acceptance Criteria**: [Verifiable conditions]
|
|
20186
|
+
\`\`\`
|
|
20187
|
+
|
|
20188
|
+
### 4. Agent Dispatch Summary (REQUIRED)
|
|
20189
|
+
|
|
20190
|
+
| Wave | Tasks | Dispatch Command |
|
|
20191
|
+
|------|-------|------------------|
|
|
20192
|
+
| 1 | 1, 4 | \`delegate_task(category="...", load_skills=[...], run_in_background=true)\` \xD7 2 |
|
|
20193
|
+
| 2 | 2, 3, 5 | \`delegate_task(...)\` \xD7 3 after Wave 1 completes |
|
|
20194
|
+
| 3 | 6 | \`delegate_task(...)\` final integration |
|
|
20195
|
+
|
|
20196
|
+
**WHY PARALLEL TASK GRAPH IS MANDATORY:**
|
|
20197
|
+
- Orchestrator (Sisyphus) executes tasks in parallel waves
|
|
20198
|
+
- Independent tasks run simultaneously via background agents
|
|
20199
|
+
- Proper dependency tracking prevents race conditions
|
|
20200
|
+
- Category + skills ensure optimal model routing per task`;
|
|
20068
20201
|
function isPlannerAgent(agentName) {
|
|
20069
20202
|
if (!agentName)
|
|
20070
20203
|
return false;
|
|
@@ -20169,52 +20302,52 @@ delegate_task(agent="oracle", prompt="Review my approach: [describe plan]")
|
|
|
20169
20302
|
YOU MUST LEVERAGE ALL AVAILABLE AGENTS / **CATEGORY + SKILLS** TO THEIR FULLEST POTENTIAL.
|
|
20170
20303
|
TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.
|
|
20171
20304
|
|
|
20172
|
-
## MANDATORY:
|
|
20305
|
+
## MANDATORY: PLAN AGENT INVOCATION (NON-NEGOTIABLE)
|
|
20173
20306
|
|
|
20174
|
-
**YOU MUST ALWAYS INVOKE
|
|
20307
|
+
**YOU MUST ALWAYS INVOKE THE PLAN AGENT FOR ANY NON-TRIVIAL TASK.**
|
|
20175
20308
|
|
|
20176
20309
|
| Condition | Action |
|
|
20177
20310
|
|-----------|--------|
|
|
20178
|
-
| Task has 2+ steps | MUST call
|
|
20179
|
-
| Task scope unclear | MUST call
|
|
20180
|
-
| Implementation required | MUST call
|
|
20181
|
-
| Architecture decision needed | MUST call
|
|
20311
|
+
| Task has 2+ steps | MUST call plan agent |
|
|
20312
|
+
| Task scope unclear | MUST call plan agent |
|
|
20313
|
+
| Implementation required | MUST call plan agent |
|
|
20314
|
+
| Architecture decision needed | MUST call plan agent |
|
|
20182
20315
|
|
|
20183
20316
|
\`\`\`
|
|
20184
|
-
delegate_task(subagent_type="
|
|
20317
|
+
delegate_task(subagent_type="plan", prompt="<gathered context + user request>")
|
|
20185
20318
|
\`\`\`
|
|
20186
20319
|
|
|
20187
|
-
**WHY
|
|
20188
|
-
-
|
|
20189
|
-
-
|
|
20190
|
-
-
|
|
20320
|
+
**WHY PLAN AGENT IS MANDATORY:**
|
|
20321
|
+
- Plan agent analyzes dependencies and parallel execution opportunities
|
|
20322
|
+
- Plan agent outputs a **parallel task graph** with waves and dependencies
|
|
20323
|
+
- Plan agent provides structured TODO list with category + skills per task
|
|
20191
20324
|
- YOU are an orchestrator, NOT an implementer
|
|
20192
20325
|
|
|
20193
|
-
### SESSION CONTINUITY WITH
|
|
20326
|
+
### SESSION CONTINUITY WITH PLAN AGENT (CRITICAL)
|
|
20194
20327
|
|
|
20195
|
-
**
|
|
20328
|
+
**Plan agent returns a session_id. USE IT for follow-up interactions.**
|
|
20196
20329
|
|
|
20197
20330
|
| Scenario | Action |
|
|
20198
20331
|
|----------|--------|
|
|
20199
|
-
|
|
|
20332
|
+
| Plan agent asks clarifying questions | \`delegate_task(session_id="{returned_session_id}", prompt="<your answer>")\` |
|
|
20200
20333
|
| Need to refine the plan | \`delegate_task(session_id="{returned_session_id}", prompt="Please adjust: <feedback>")\` |
|
|
20201
20334
|
| Plan needs more detail | \`delegate_task(session_id="{returned_session_id}", prompt="Add more detail to Task N")\` |
|
|
20202
20335
|
|
|
20203
20336
|
**WHY SESSION_ID IS CRITICAL:**
|
|
20204
|
-
-
|
|
20337
|
+
- Plan agent retains FULL conversation context
|
|
20205
20338
|
- No repeated exploration or context gathering
|
|
20206
20339
|
- Saves 70%+ tokens on follow-ups
|
|
20207
20340
|
- Maintains interview continuity until plan is finalized
|
|
20208
20341
|
|
|
20209
20342
|
\`\`\`
|
|
20210
20343
|
// WRONG: Starting fresh loses all context
|
|
20211
|
-
delegate_task(subagent_type="
|
|
20344
|
+
delegate_task(subagent_type="plan", prompt="Here's more info...")
|
|
20212
20345
|
|
|
20213
20346
|
// CORRECT: Resume preserves everything
|
|
20214
20347
|
delegate_task(session_id="ses_abc123", prompt="Here's my answer to your question: ...")
|
|
20215
20348
|
\`\`\`
|
|
20216
20349
|
|
|
20217
|
-
**FAILURE TO CALL
|
|
20350
|
+
**FAILURE TO CALL PLAN AGENT = INCOMPLETE WORK.**
|
|
20218
20351
|
|
|
20219
20352
|
---
|
|
20220
20353
|
|
|
@@ -20226,7 +20359,7 @@ delegate_task(session_id="ses_abc123", prompt="Here's my answer to your question
|
|
|
20226
20359
|
|-----------|--------|-----|
|
|
20227
20360
|
| Codebase exploration | delegate_task(subagent_type="explore", run_in_background=true) | Parallel, context-efficient |
|
|
20228
20361
|
| Documentation lookup | delegate_task(subagent_type="librarian", run_in_background=true) | Specialized knowledge |
|
|
20229
|
-
| Planning | delegate_task(subagent_type="plan") |
|
|
20362
|
+
| Planning | delegate_task(subagent_type="plan") | Parallel task graph + structured TODO list |
|
|
20230
20363
|
| Architecture/Debugging | delegate_task(subagent_type="oracle") | High-IQ reasoning |
|
|
20231
20364
|
| Implementation | delegate_task(category="...", load_skills=[...]) | Domain-optimized models |
|
|
20232
20365
|
|
|
@@ -20286,20 +20419,20 @@ delegate_task(..., run_in_background=true) // task_id_3
|
|
|
20286
20419
|
delegate_task(subagent_type="librarian", run_in_background=true, prompt="...")
|
|
20287
20420
|
\`\`\`
|
|
20288
20421
|
|
|
20289
|
-
2. **INVOKE
|
|
20422
|
+
2. **INVOKE PLAN AGENT** (MANDATORY for non-trivial tasks):
|
|
20290
20423
|
\`\`\`
|
|
20291
|
-
result = delegate_task(subagent_type="
|
|
20424
|
+
result = delegate_task(subagent_type="plan", prompt="<context + request>")
|
|
20292
20425
|
// STORE the session_id for follow-ups!
|
|
20293
|
-
|
|
20426
|
+
plan_session_id = result.session_id
|
|
20294
20427
|
\`\`\`
|
|
20295
20428
|
|
|
20296
|
-
3. **ITERATE WITH
|
|
20429
|
+
3. **ITERATE WITH PLAN AGENT** (if clarification needed):
|
|
20297
20430
|
\`\`\`
|
|
20298
20431
|
// Use session_id to continue the conversation
|
|
20299
|
-
delegate_task(session_id=
|
|
20432
|
+
delegate_task(session_id=plan_session_id, prompt="<answer to plan agent's question>")
|
|
20300
20433
|
\`\`\`
|
|
20301
20434
|
|
|
20302
|
-
4. **EXECUTE VIA DELEGATION** (category + skills from
|
|
20435
|
+
4. **EXECUTE VIA DELEGATION** (category + skills from plan agent's output):
|
|
20303
20436
|
\`\`\`
|
|
20304
20437
|
delegate_task(category="...", load_skills=[...], prompt="<task from plan>")
|
|
20305
20438
|
\`\`\`
|
|
@@ -20378,9 +20511,9 @@ Write these criteria explicitly. Share with user if scope is non-trivial.
|
|
|
20378
20511
|
THE USER ASKED FOR X. DELIVER EXACTLY X. NOT A SUBSET. NOT A DEMO. NOT A STARTING POINT.
|
|
20379
20512
|
|
|
20380
20513
|
1. EXPLORES + LIBRARIANS (background)
|
|
20381
|
-
2. GATHER -> delegate_task(subagent_type="
|
|
20382
|
-
3. ITERATE WITH
|
|
20383
|
-
4. WORK BY DELEGATING TO CATEGORY + SKILLS AGENTS (following
|
|
20514
|
+
2. GATHER -> delegate_task(subagent_type="plan", prompt="<context + request>")
|
|
20515
|
+
3. ITERATE WITH PLAN AGENT (session_id resume) UNTIL PLAN IS FINALIZED
|
|
20516
|
+
4. WORK BY DELEGATING TO CATEGORY + SKILLS AGENTS (following plan agent's parallel task graph)
|
|
20384
20517
|
|
|
20385
20518
|
NOW.
|
|
20386
20519
|
|
|
@@ -20453,7 +20586,8 @@ function createKeywordDetectorHook(ctx, collector) {
|
|
|
20453
20586
|
return;
|
|
20454
20587
|
}
|
|
20455
20588
|
const currentAgent = getSessionAgent(input.sessionID) ?? input.agent;
|
|
20456
|
-
|
|
20589
|
+
const cleanText = removeSystemReminders(promptText);
|
|
20590
|
+
let detectedKeywords = detectKeywordsWithType(removeCodeBlocks2(cleanText), currentAgent);
|
|
20457
20591
|
if (isPlannerAgent(currentAgent)) {
|
|
20458
20592
|
detectedKeywords = detectedKeywords.filter((k) => k.type !== "ultrawork");
|
|
20459
20593
|
}
|
|
@@ -21577,6 +21711,9 @@ async function loadMcpJsonFromDir(skillDir) {
|
|
|
21577
21711
|
function parseAllowedTools(allowedTools) {
|
|
21578
21712
|
if (!allowedTools)
|
|
21579
21713
|
return;
|
|
21714
|
+
if (Array.isArray(allowedTools)) {
|
|
21715
|
+
return allowedTools.map((t) => t.trim()).filter(Boolean);
|
|
21716
|
+
}
|
|
21580
21717
|
return allowedTools.split(/\s+/).filter(Boolean);
|
|
21581
21718
|
}
|
|
21582
21719
|
async function loadSkillFromPath(skillPath, resolvedPath, defaultName, scope) {
|
|
@@ -21744,6 +21881,14 @@ init_deep_merge();
|
|
|
21744
21881
|
import { readFileSync as readFileSync21, existsSync as existsSync31 } from "fs";
|
|
21745
21882
|
import { dirname as dirname7, resolve as resolve6, isAbsolute as isAbsolute2 } from "path";
|
|
21746
21883
|
import { homedir as homedir10 } from "os";
|
|
21884
|
+
function parseAllowedToolsFromMetadata(allowedTools) {
|
|
21885
|
+
if (!allowedTools)
|
|
21886
|
+
return;
|
|
21887
|
+
if (Array.isArray(allowedTools)) {
|
|
21888
|
+
return allowedTools.map((t) => t.trim()).filter(Boolean);
|
|
21889
|
+
}
|
|
21890
|
+
return allowedTools.split(/\s+/).filter(Boolean);
|
|
21891
|
+
}
|
|
21747
21892
|
var SCOPE_PRIORITY = {
|
|
21748
21893
|
builtin: 1,
|
|
21749
21894
|
config: 2,
|
|
@@ -21835,7 +21980,7 @@ $ARGUMENTS
|
|
|
21835
21980
|
subtask: entry.subtask ?? fileMetadata.subtask,
|
|
21836
21981
|
argumentHint: entry["argument-hint"] || fileMetadata["argument-hint"]
|
|
21837
21982
|
};
|
|
21838
|
-
const allowedTools = entry["allowed-tools"] || (fileMetadata["allowed-tools"] ? fileMetadata["allowed-tools"]
|
|
21983
|
+
const allowedTools = entry["allowed-tools"] || (fileMetadata["allowed-tools"] ? parseAllowedToolsFromMetadata(fileMetadata["allowed-tools"]) : undefined);
|
|
21839
21984
|
return {
|
|
21840
21985
|
name,
|
|
21841
21986
|
path: entry.from ? resolveFilePath2(entry.from, configDir) : undefined,
|
|
@@ -24617,7 +24762,7 @@ ${contextInfo}`;
|
|
|
24617
24762
|
};
|
|
24618
24763
|
}
|
|
24619
24764
|
// src/hooks/atlas/index.ts
|
|
24620
|
-
import { execSync } from "child_process";
|
|
24765
|
+
import { execSync as execSync2 } from "child_process";
|
|
24621
24766
|
init_hook_message_injector();
|
|
24622
24767
|
init_logger();
|
|
24623
24768
|
init_system_directive();
|
|
@@ -24856,7 +25001,7 @@ function extractSessionIdFromOutput(output) {
|
|
|
24856
25001
|
}
|
|
24857
25002
|
function getGitDiffStats(directory) {
|
|
24858
25003
|
try {
|
|
24859
|
-
const output =
|
|
25004
|
+
const output = execSync2("git diff --numstat HEAD", {
|
|
24860
25005
|
cwd: directory,
|
|
24861
25006
|
encoding: "utf-8",
|
|
24862
25007
|
timeout: 5000,
|
|
@@ -24864,7 +25009,7 @@ function getGitDiffStats(directory) {
|
|
|
24864
25009
|
}).trim();
|
|
24865
25010
|
if (!output)
|
|
24866
25011
|
return [];
|
|
24867
|
-
const statusOutput =
|
|
25012
|
+
const statusOutput = execSync2("git status --porcelain", {
|
|
24868
25013
|
cwd: directory,
|
|
24869
25014
|
encoding: "utf-8",
|
|
24870
25015
|
timeout: 5000,
|
|
@@ -25161,6 +25306,9 @@ function createAtlasHook(ctx, options) {
|
|
|
25161
25306
|
}
|
|
25162
25307
|
},
|
|
25163
25308
|
"tool.execute.after": async (input, output) => {
|
|
25309
|
+
if (!output) {
|
|
25310
|
+
return;
|
|
25311
|
+
}
|
|
25164
25312
|
if (!isCallerOrchestrator(input.sessionID)) {
|
|
25165
25313
|
return;
|
|
25166
25314
|
}
|
|
@@ -43589,7 +43737,10 @@ async function executeSync(args, toolContext, ctx) {
|
|
|
43589
43737
|
const createResult = await ctx.client.session.create({
|
|
43590
43738
|
body: {
|
|
43591
43739
|
parentID: toolContext.sessionID,
|
|
43592
|
-
title: `${args.description} (@${args.subagent_type} subagent)
|
|
43740
|
+
title: `${args.description} (@${args.subagent_type} subagent)`,
|
|
43741
|
+
permission: [
|
|
43742
|
+
{ permission: "question", action: "deny", pattern: "*" }
|
|
43743
|
+
]
|
|
43593
43744
|
},
|
|
43594
43745
|
query: {
|
|
43595
43746
|
directory: parentDirectory
|
|
@@ -43597,6 +43748,17 @@ async function executeSync(args, toolContext, ctx) {
|
|
|
43597
43748
|
});
|
|
43598
43749
|
if (createResult.error) {
|
|
43599
43750
|
log(`[call_omo_agent] Session create error:`, createResult.error);
|
|
43751
|
+
const errorStr = String(createResult.error);
|
|
43752
|
+
if (errorStr.toLowerCase().includes("unauthorized")) {
|
|
43753
|
+
return `Error: Failed to create session (Unauthorized). This may be due to:
|
|
43754
|
+
1. OAuth token restrictions (e.g., Claude Code credentials are restricted to Claude Code only)
|
|
43755
|
+
2. Provider authentication issues
|
|
43756
|
+
3. Session permission inheritance problems
|
|
43757
|
+
|
|
43758
|
+
Try using a different provider or API key authentication.
|
|
43759
|
+
|
|
43760
|
+
Original error: ${createResult.error}`;
|
|
43761
|
+
}
|
|
43600
43762
|
return `Error: Failed to create session: ${createResult.error}`;
|
|
43601
43763
|
}
|
|
43602
43764
|
sessionID = createResult.data.id;
|
|
@@ -43837,7 +43999,10 @@ If the requested information is not found, clearly state what is missing.`;
|
|
|
43837
43999
|
const createResult = await ctx.client.session.create({
|
|
43838
44000
|
body: {
|
|
43839
44001
|
parentID: toolContext.sessionID,
|
|
43840
|
-
title: `look_at: ${args.goal.substring(0, 50)}
|
|
44002
|
+
title: `look_at: ${args.goal.substring(0, 50)}`,
|
|
44003
|
+
permission: [
|
|
44004
|
+
{ permission: "question", action: "deny", pattern: "*" }
|
|
44005
|
+
]
|
|
43841
44006
|
},
|
|
43842
44007
|
query: {
|
|
43843
44008
|
directory: parentDirectory
|
|
@@ -43845,27 +44010,63 @@ If the requested information is not found, clearly state what is missing.`;
|
|
|
43845
44010
|
});
|
|
43846
44011
|
if (createResult.error) {
|
|
43847
44012
|
log(`[look_at] Session create error:`, createResult.error);
|
|
44013
|
+
const errorStr = String(createResult.error);
|
|
44014
|
+
if (errorStr.toLowerCase().includes("unauthorized")) {
|
|
44015
|
+
return `Error: Failed to create session (Unauthorized). This may be due to:
|
|
44016
|
+
1. OAuth token restrictions (e.g., Claude Code credentials are restricted to Claude Code only)
|
|
44017
|
+
2. Provider authentication issues
|
|
44018
|
+
3. Session permission inheritance problems
|
|
44019
|
+
|
|
44020
|
+
Try using a different provider or API key authentication.
|
|
44021
|
+
|
|
44022
|
+
Original error: ${createResult.error}`;
|
|
44023
|
+
}
|
|
43848
44024
|
return `Error: Failed to create session: ${createResult.error}`;
|
|
43849
44025
|
}
|
|
43850
44026
|
const sessionID = createResult.data.id;
|
|
43851
44027
|
log(`[look_at] Created session: ${sessionID}`);
|
|
43852
44028
|
log(`[look_at] Sending prompt with file passthrough to session ${sessionID}`);
|
|
43853
|
-
|
|
43854
|
-
|
|
43855
|
-
|
|
43856
|
-
|
|
43857
|
-
|
|
43858
|
-
|
|
43859
|
-
|
|
43860
|
-
|
|
43861
|
-
|
|
43862
|
-
|
|
43863
|
-
|
|
43864
|
-
|
|
43865
|
-
|
|
43866
|
-
|
|
44029
|
+
try {
|
|
44030
|
+
await ctx.client.session.prompt({
|
|
44031
|
+
path: { id: sessionID },
|
|
44032
|
+
body: {
|
|
44033
|
+
agent: MULTIMODAL_LOOKER_AGENT,
|
|
44034
|
+
tools: {
|
|
44035
|
+
task: false,
|
|
44036
|
+
call_omo_agent: false,
|
|
44037
|
+
look_at: false,
|
|
44038
|
+
read: false
|
|
44039
|
+
},
|
|
44040
|
+
parts: [
|
|
44041
|
+
{ type: "text", text: prompt },
|
|
44042
|
+
{ type: "file", mime: mimeType, url: pathToFileURL2(args.file_path).href, filename }
|
|
44043
|
+
]
|
|
44044
|
+
}
|
|
44045
|
+
});
|
|
44046
|
+
} catch (promptError) {
|
|
44047
|
+
const errorMessage = promptError instanceof Error ? promptError.message : String(promptError);
|
|
44048
|
+
log(`[look_at] Prompt error:`, promptError);
|
|
44049
|
+
const isJsonParseError = errorMessage.includes("JSON") && (errorMessage.includes("EOF") || errorMessage.includes("parse"));
|
|
44050
|
+
if (isJsonParseError) {
|
|
44051
|
+
return `Error: Failed to analyze file - received malformed response from multimodal-looker agent.
|
|
44052
|
+
|
|
44053
|
+
This typically occurs when:
|
|
44054
|
+
1. The multimodal-looker model is not available or not connected
|
|
44055
|
+
2. The model does not support this file type (${mimeType})
|
|
44056
|
+
3. The API returned an empty or truncated response
|
|
44057
|
+
|
|
44058
|
+
File: ${args.file_path}
|
|
44059
|
+
MIME type: ${mimeType}
|
|
44060
|
+
|
|
44061
|
+
Try:
|
|
44062
|
+
- Ensure a vision-capable model (e.g., gemini-3-flash, gpt-5.2) is available
|
|
44063
|
+
- Check provider connections in opencode settings
|
|
44064
|
+
- For text files like .md, .txt, use the Read tool instead
|
|
44065
|
+
|
|
44066
|
+
Original error: ${errorMessage}`;
|
|
43867
44067
|
}
|
|
43868
|
-
|
|
44068
|
+
return `Error: Failed to send prompt to multimodal-looker agent: ${errorMessage}`;
|
|
44069
|
+
}
|
|
43869
44070
|
log(`[look_at] Prompt sent, fetching messages...`);
|
|
43870
44071
|
const messagesResult = await ctx.client.session.messages({
|
|
43871
44072
|
path: { id: sessionID }
|
|
@@ -44483,7 +44684,7 @@ To continue this session: session_id="${args.session_id}"`;
|
|
|
44483
44684
|
}
|
|
44484
44685
|
} else {
|
|
44485
44686
|
const resolution = resolveModelWithFallback({
|
|
44486
|
-
userModel: userCategories?.[args.category]?.model ?? sisyphusJuniorModel,
|
|
44687
|
+
userModel: userCategories?.[args.category]?.model ?? resolved.model ?? sisyphusJuniorModel,
|
|
44487
44688
|
fallbackChain: requirement.fallbackChain,
|
|
44488
44689
|
availableModels,
|
|
44489
44690
|
systemDefaultModel
|
|
@@ -44508,7 +44709,7 @@ To continue this session: session_id="${args.session_id}"`;
|
|
|
44508
44709
|
}
|
|
44509
44710
|
modelInfo = { model: actualModel, type: type2, source };
|
|
44510
44711
|
const parsedModel = parseModelString(actualModel);
|
|
44511
|
-
const variantToUse = userCategories?.[args.category]?.variant ?? resolvedVariant;
|
|
44712
|
+
const variantToUse = userCategories?.[args.category]?.variant ?? resolvedVariant ?? resolved.config.variant;
|
|
44512
44713
|
categoryModel = parsedModel ? variantToUse ? { ...parsedModel, variant: variantToUse } : parsedModel : undefined;
|
|
44513
44714
|
}
|
|
44514
44715
|
}
|
|
@@ -44681,6 +44882,11 @@ To continue this session: session_id="${sessionID}"`;
|
|
|
44681
44882
|
return `Cannot use subagent_type="${SISYPHUS_JUNIOR_AGENT}" directly. Use category parameter instead (e.g., ${categoryExamples}).
|
|
44682
44883
|
|
|
44683
44884
|
Sisyphus-Junior is spawned automatically when you specify a category. Pick the appropriate category for your task domain.`;
|
|
44885
|
+
}
|
|
44886
|
+
if (isPlanAgent(agentName) && isPlanAgent(parentAgent)) {
|
|
44887
|
+
return `You are prometheus. You cannot delegate to prometheus via delegate_task.
|
|
44888
|
+
|
|
44889
|
+
Create the work plan directly - that's your job as the planning agent.`;
|
|
44684
44890
|
}
|
|
44685
44891
|
agentToUse = agentName;
|
|
44686
44892
|
try {
|
|
@@ -44809,6 +45015,7 @@ To continue this session: session_id="${task.sessionID}"`;
|
|
|
44809
45015
|
}
|
|
44810
45016
|
});
|
|
44811
45017
|
try {
|
|
45018
|
+
const allowDelegateTask = isPlanAgent(agentToUse);
|
|
44812
45019
|
await client2.session.prompt({
|
|
44813
45020
|
path: { id: sessionID },
|
|
44814
45021
|
body: {
|
|
@@ -44816,7 +45023,7 @@ To continue this session: session_id="${task.sessionID}"`;
|
|
|
44816
45023
|
system: systemContent,
|
|
44817
45024
|
tools: {
|
|
44818
45025
|
task: false,
|
|
44819
|
-
delegate_task:
|
|
45026
|
+
delegate_task: allowDelegateTask,
|
|
44820
45027
|
call_omo_agent: true,
|
|
44821
45028
|
question: false
|
|
44822
45029
|
},
|
|
@@ -52919,6 +53126,8 @@ call_omo_agent(subagent_type="librarian", prompt="Find OSS implementations of Z.
|
|
|
52919
53126
|
- [Risk 2]: [Mitigation]
|
|
52920
53127
|
|
|
52921
53128
|
## Directives for Prometheus
|
|
53129
|
+
|
|
53130
|
+
### Core Directives
|
|
52922
53131
|
- MUST: [Required action]
|
|
52923
53132
|
- MUST: [Required action]
|
|
52924
53133
|
- MUST NOT: [Forbidden action]
|
|
@@ -52926,6 +53135,29 @@ call_omo_agent(subagent_type="librarian", prompt="Find OSS implementations of Z.
|
|
|
52926
53135
|
- PATTERN: Follow \`[file:lines]\`
|
|
52927
53136
|
- TOOL: Use \`[specific tool]\` for [purpose]
|
|
52928
53137
|
|
|
53138
|
+
### QA/Acceptance Criteria Directives (MANDATORY)
|
|
53139
|
+
> **ZERO USER INTERVENTION PRINCIPLE**: All acceptance criteria MUST be executable by agents.
|
|
53140
|
+
|
|
53141
|
+
- MUST: Write acceptance criteria as executable commands (curl, bun test, playwright actions)
|
|
53142
|
+
- MUST: Include exact expected outputs, not vague descriptions
|
|
53143
|
+
- MUST: Specify verification tool for each deliverable type (playwright for UI, curl for API, etc.)
|
|
53144
|
+
- MUST NOT: Create criteria requiring "user manually tests..."
|
|
53145
|
+
- MUST NOT: Create criteria requiring "user visually confirms..."
|
|
53146
|
+
- MUST NOT: Create criteria requiring "user clicks/interacts..."
|
|
53147
|
+
- MUST NOT: Use placeholders without concrete examples (bad: "[endpoint]", good: "/api/users")
|
|
53148
|
+
|
|
53149
|
+
Example of GOOD acceptance criteria:
|
|
53150
|
+
\`\`\`
|
|
53151
|
+
curl -s http://localhost:3000/api/health | jq '.status'
|
|
53152
|
+
# Assert: Output is "ok"
|
|
53153
|
+
\`\`\`
|
|
53154
|
+
|
|
53155
|
+
Example of BAD acceptance criteria (FORBIDDEN):
|
|
53156
|
+
\`\`\`
|
|
53157
|
+
User opens browser and checks if the page loads correctly.
|
|
53158
|
+
User confirms the button works as expected.
|
|
53159
|
+
\`\`\`
|
|
53160
|
+
|
|
52929
53161
|
## Recommended Approach
|
|
52930
53162
|
[1-2 sentence summary of how to proceed]
|
|
52931
53163
|
\`\`\`
|
|
@@ -52952,12 +53184,16 @@ call_omo_agent(subagent_type="librarian", prompt="Find OSS implementations of Z.
|
|
|
52952
53184
|
- Ask generic questions ("What's the scope?")
|
|
52953
53185
|
- Proceed without addressing ambiguity
|
|
52954
53186
|
- Make assumptions about user's codebase
|
|
53187
|
+
- Suggest acceptance criteria requiring user intervention ("user manually tests", "user confirms", "user clicks")
|
|
53188
|
+
- Leave QA/acceptance criteria vague or placeholder-heavy
|
|
52955
53189
|
|
|
52956
53190
|
**ALWAYS**:
|
|
52957
53191
|
- Classify intent FIRST
|
|
52958
53192
|
- Be specific ("Should this change UserService only, or also AuthService?")
|
|
52959
53193
|
- Explore before asking (for Build/Research intents)
|
|
52960
53194
|
- Provide actionable directives for Prometheus
|
|
53195
|
+
- Include QA automation directives in every output
|
|
53196
|
+
- Ensure acceptance criteria are agent-executable (commands, not human actions)
|
|
52961
53197
|
`;
|
|
52962
53198
|
var metisRestrictions = createAgentToolRestrictions([
|
|
52963
53199
|
"write",
|
|
@@ -55714,27 +55950,37 @@ Each TODO follows RED-GREEN-REFACTOR:
|
|
|
55714
55950
|
- Example: Create \`src/__tests__/example.test.ts\`
|
|
55715
55951
|
- Verify: \`bun test\` \u2192 1 test passes
|
|
55716
55952
|
|
|
55717
|
-
### If
|
|
55953
|
+
### If Automated Verification Only (NO User Intervention)
|
|
55718
55954
|
|
|
55719
|
-
**CRITICAL
|
|
55955
|
+
> **CRITICAL PRINCIPLE: ZERO USER INTERVENTION**
|
|
55956
|
+
>
|
|
55957
|
+
> **NEVER** create acceptance criteria that require:
|
|
55958
|
+
> - "User manually tests..." / "\uC0AC\uC6A9\uC790\uAC00 \uC9C1\uC811 \uD14C\uC2A4\uD2B8..."
|
|
55959
|
+
> - "User visually confirms..." / "\uC0AC\uC6A9\uC790\uAC00 \uB208\uC73C\uB85C \uD655\uC778..."
|
|
55960
|
+
> - "User interacts with..." / "\uC0AC\uC6A9\uC790\uAC00 \uC9C1\uC811 \uC870\uC791..."
|
|
55961
|
+
> - "Ask user to verify..." / "\uC0AC\uC6A9\uC790\uC5D0\uAC8C \uD655\uC778 \uC694\uCCAD..."
|
|
55962
|
+
> - ANY step that requires a human to perform an action
|
|
55963
|
+
>
|
|
55964
|
+
> **ALL verification MUST be automated and executable by the agent.**
|
|
55965
|
+
> If a verification cannot be automated, find an automated alternative or explicitly note it as a known limitation.
|
|
55720
55966
|
|
|
55721
|
-
Each TODO includes
|
|
55967
|
+
Each TODO includes EXECUTABLE verification procedures that agents can run directly:
|
|
55722
55968
|
|
|
55723
55969
|
**By Deliverable Type:**
|
|
55724
55970
|
|
|
55725
|
-
| Type | Verification Tool | Procedure |
|
|
55726
|
-
|
|
55727
|
-
| **Frontend/UI** | Playwright browser |
|
|
55728
|
-
| **TUI/CLI** | interactive_bash (tmux) |
|
|
55729
|
-
| **API/Backend** | curl / httpie |
|
|
55730
|
-
| **Library/Module** | Node/Python REPL |
|
|
55731
|
-
| **Config/Infra** | Shell commands |
|
|
55971
|
+
| Type | Verification Tool | Automated Procedure |
|
|
55972
|
+
|------|------------------|---------------------|
|
|
55973
|
+
| **Frontend/UI** | Playwright browser via playwright skill | Agent navigates, clicks, screenshots, asserts DOM state |
|
|
55974
|
+
| **TUI/CLI** | interactive_bash (tmux) | Agent runs command, captures output, validates expected strings |
|
|
55975
|
+
| **API/Backend** | curl / httpie via Bash | Agent sends request, parses response, validates JSON fields |
|
|
55976
|
+
| **Library/Module** | Node/Python REPL via Bash | Agent imports, calls function, compares output |
|
|
55977
|
+
| **Config/Infra** | Shell commands via Bash | Agent applies config, runs state check, validates output |
|
|
55732
55978
|
|
|
55733
|
-
**Evidence
|
|
55734
|
-
-
|
|
55735
|
-
- Screenshots for visual
|
|
55736
|
-
-
|
|
55737
|
-
-
|
|
55979
|
+
**Evidence Requirements (Agent-Executable):**
|
|
55980
|
+
- Command output captured and compared against expected patterns
|
|
55981
|
+
- Screenshots saved to .sisyphus/evidence/ for visual verification
|
|
55982
|
+
- JSON response fields validated with specific assertions
|
|
55983
|
+
- Exit codes checked (0 = success)
|
|
55738
55984
|
|
|
55739
55985
|
---
|
|
55740
55986
|
|
|
@@ -55844,53 +56090,76 @@ Parallel Speedup: ~40% faster than sequential
|
|
|
55844
56090
|
|
|
55845
56091
|
**Acceptance Criteria**:
|
|
55846
56092
|
|
|
55847
|
-
> CRITICAL:
|
|
55848
|
-
>
|
|
56093
|
+
> **CRITICAL: AGENT-EXECUTABLE VERIFICATION ONLY**
|
|
56094
|
+
>
|
|
56095
|
+
> - Acceptance = EXECUTION by the agent, not "user checks if it works"
|
|
56096
|
+
> - Every criterion MUST be verifiable by running a command or using a tool
|
|
56097
|
+
> - NO steps like "user opens browser", "user clicks", "user confirms"
|
|
56098
|
+
> - If you write "[placeholder]" - REPLACE IT with actual values based on task context
|
|
55849
56099
|
|
|
55850
56100
|
**If TDD (tests enabled):**
|
|
55851
|
-
- [ ] Test file created:
|
|
55852
|
-
- [ ] Test covers:
|
|
55853
|
-
- [ ]
|
|
55854
|
-
|
|
55855
|
-
**
|
|
55856
|
-
|
|
55857
|
-
|
|
55858
|
-
|
|
55859
|
-
|
|
55860
|
-
|
|
55861
|
-
|
|
55862
|
-
|
|
55863
|
-
|
|
55864
|
-
|
|
55865
|
-
|
|
55866
|
-
|
|
55867
|
-
|
|
55868
|
-
|
|
55869
|
-
|
|
55870
|
-
|
|
55871
|
-
|
|
55872
|
-
|
|
55873
|
-
|
|
55874
|
-
|
|
55875
|
-
|
|
55876
|
-
|
|
55877
|
-
|
|
55878
|
-
|
|
55879
|
-
|
|
55880
|
-
|
|
55881
|
-
|
|
55882
|
-
|
|
55883
|
-
|
|
55884
|
-
|
|
55885
|
-
|
|
55886
|
-
|
|
55887
|
-
|
|
55888
|
-
|
|
55889
|
-
|
|
55890
|
-
**
|
|
55891
|
-
|
|
55892
|
-
|
|
55893
|
-
-
|
|
56101
|
+
- [ ] Test file created: src/auth/login.test.ts
|
|
56102
|
+
- [ ] Test covers: successful login returns JWT token
|
|
56103
|
+
- [ ] bun test src/auth/login.test.ts \u2192 PASS (3 tests, 0 failures)
|
|
56104
|
+
|
|
56105
|
+
**Automated Verification (ALWAYS include, choose by deliverable type):**
|
|
56106
|
+
|
|
56107
|
+
**For Frontend/UI changes** (using playwright skill):
|
|
56108
|
+
\\\`\\\`\\\`
|
|
56109
|
+
# Agent executes via playwright browser automation:
|
|
56110
|
+
1. Navigate to: http://localhost:3000/login
|
|
56111
|
+
2. Fill: input[name="email"] with "test@example.com"
|
|
56112
|
+
3. Fill: input[name="password"] with "password123"
|
|
56113
|
+
4. Click: button[type="submit"]
|
|
56114
|
+
5. Wait for: selector ".dashboard-welcome" to be visible
|
|
56115
|
+
6. Assert: text "Welcome back" appears on page
|
|
56116
|
+
7. Screenshot: .sisyphus/evidence/task-1-login-success.png
|
|
56117
|
+
\\\`\\\`\\\`
|
|
56118
|
+
|
|
56119
|
+
**For TUI/CLI changes** (using interactive_bash):
|
|
56120
|
+
\\\`\\\`\\\`
|
|
56121
|
+
# Agent executes via tmux session:
|
|
56122
|
+
1. Command: ./my-cli --config test.yaml
|
|
56123
|
+
2. Wait for: "Configuration loaded" in output
|
|
56124
|
+
3. Send keys: "q" to quit
|
|
56125
|
+
4. Assert: Exit code 0
|
|
56126
|
+
5. Assert: Output contains "Goodbye"
|
|
56127
|
+
\\\`\\\`\\\`
|
|
56128
|
+
|
|
56129
|
+
**For API/Backend changes** (using Bash curl):
|
|
56130
|
+
\\\`\\\`\\\`bash
|
|
56131
|
+
# Agent runs:
|
|
56132
|
+
curl -s -X POST http://localhost:8080/api/users \\
|
|
56133
|
+
-H "Content-Type: application/json" \\
|
|
56134
|
+
-d '{"email":"new@test.com","name":"Test User"}' \\
|
|
56135
|
+
| jq '.id'
|
|
56136
|
+
# Assert: Returns non-empty UUID
|
|
56137
|
+
# Assert: HTTP status 201
|
|
56138
|
+
\\\`\\\`\\\`
|
|
56139
|
+
|
|
56140
|
+
**For Library/Module changes** (using Bash node/bun):
|
|
56141
|
+
\\\`\\\`\\\`bash
|
|
56142
|
+
# Agent runs:
|
|
56143
|
+
bun -e "import { validateEmail } from './src/utils/validate'; console.log(validateEmail('test@example.com'))"
|
|
56144
|
+
# Assert: Output is "true"
|
|
56145
|
+
|
|
56146
|
+
bun -e "import { validateEmail } from './src/utils/validate'; console.log(validateEmail('invalid'))"
|
|
56147
|
+
# Assert: Output is "false"
|
|
56148
|
+
\\\`\\\`\\\`
|
|
56149
|
+
|
|
56150
|
+
**For Config/Infra changes** (using Bash):
|
|
56151
|
+
\\\`\\\`\\\`bash
|
|
56152
|
+
# Agent runs:
|
|
56153
|
+
docker compose up -d
|
|
56154
|
+
# Wait 5s for containers
|
|
56155
|
+
docker compose ps --format json | jq '.[].State'
|
|
56156
|
+
# Assert: All states are "running"
|
|
56157
|
+
\\\`\\\`\\\`
|
|
56158
|
+
|
|
56159
|
+
**Evidence to Capture:**
|
|
56160
|
+
- [ ] Terminal output from verification commands (actual output, not expected)
|
|
56161
|
+
- [ ] Screenshot files in .sisyphus/evidence/ for UI changes
|
|
56162
|
+
- [ ] JSON response bodies for API changes
|
|
55894
56163
|
|
|
55895
56164
|
**Commit**: YES | NO (groups with N)
|
|
55896
56165
|
- Message: \`type(scope): desc\`
|
|
@@ -56292,7 +56561,19 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
56292
56561
|
const toolOutputTruncator = isHookEnabled("tool-output-truncator") ? createToolOutputTruncatorHook(ctx, {
|
|
56293
56562
|
experimental: pluginConfig.experimental
|
|
56294
56563
|
}) : null;
|
|
56295
|
-
|
|
56564
|
+
let directoryAgentsInjector = null;
|
|
56565
|
+
if (isHookEnabled("directory-agents-injector")) {
|
|
56566
|
+
const currentVersion = getOpenCodeVersion();
|
|
56567
|
+
const hasNativeSupport = currentVersion !== null && isOpenCodeVersionAtLeast(OPENCODE_NATIVE_AGENTS_INJECTION_VERSION);
|
|
56568
|
+
if (hasNativeSupport) {
|
|
56569
|
+
log("directory-agents-injector auto-disabled due to native OpenCode support", {
|
|
56570
|
+
currentVersion,
|
|
56571
|
+
nativeVersion: OPENCODE_NATIVE_AGENTS_INJECTION_VERSION
|
|
56572
|
+
});
|
|
56573
|
+
} else {
|
|
56574
|
+
directoryAgentsInjector = createDirectoryAgentsInjectorHook(ctx);
|
|
56575
|
+
}
|
|
56576
|
+
}
|
|
56296
56577
|
const directoryReadmeInjector = isHookEnabled("directory-readme-injector") ? createDirectoryReadmeInjectorHook(ctx) : null;
|
|
56297
56578
|
const emptyTaskResponseDetector = isHookEnabled("empty-task-response-detector") ? createEmptyTaskResponseDetectorHook(ctx) : null;
|
|
56298
56579
|
const thinkMode = isHookEnabled("think-mode") ? createThinkModeHook() : null;
|
|
@@ -56453,13 +56734,20 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
56453
56734
|
}
|
|
56454
56735
|
const message = output.message;
|
|
56455
56736
|
if (firstMessageVariantGate.shouldOverride(input.sessionID)) {
|
|
56456
|
-
const variant = resolveAgentVariant(pluginConfig, input.agent);
|
|
56737
|
+
const variant = input.model && input.agent ? resolveVariantForModel(pluginConfig, input.agent, input.model) : resolveAgentVariant(pluginConfig, input.agent);
|
|
56457
56738
|
if (variant !== undefined) {
|
|
56458
56739
|
message.variant = variant;
|
|
56459
56740
|
}
|
|
56460
56741
|
firstMessageVariantGate.markApplied(input.sessionID);
|
|
56461
56742
|
} else {
|
|
56462
|
-
|
|
56743
|
+
if (input.model && input.agent && message.variant === undefined) {
|
|
56744
|
+
const variant = resolveVariantForModel(pluginConfig, input.agent, input.model);
|
|
56745
|
+
if (variant !== undefined) {
|
|
56746
|
+
message.variant = variant;
|
|
56747
|
+
}
|
|
56748
|
+
} else {
|
|
56749
|
+
applyAgentVariant(pluginConfig, input.agent, message);
|
|
56750
|
+
}
|
|
56463
56751
|
}
|
|
56464
56752
|
await keywordDetector?.["chat.message"]?.(input, output);
|
|
56465
56753
|
await claudeCodeHooks["chat.message"]?.(input, output);
|
|
@@ -56636,6 +56924,9 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
56636
56924
|
}
|
|
56637
56925
|
},
|
|
56638
56926
|
"tool.execute.after": async (input, output) => {
|
|
56927
|
+
if (!output) {
|
|
56928
|
+
return;
|
|
56929
|
+
}
|
|
56639
56930
|
await claudeCodeHooks["tool.execute.after"](input, output);
|
|
56640
56931
|
await toolOutputTruncator?.["tool.execute.after"](input, output);
|
|
56641
56932
|
await contextWindowMonitor?.["tool.execute.after"](input, output);
|