oh-my-opencode 3.5.1 → 3.5.3
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/cli/index.js +43 -22
- package/dist/cli/run/poll-for-completion.d.ts +1 -0
- package/dist/config/schema/categories.d.ts +2 -0
- package/dist/config/schema/oh-my-opencode-config.d.ts +1 -0
- package/dist/features/background-agent/background-event-handler.d.ts +1 -0
- package/dist/features/background-agent/manager.d.ts +2 -0
- package/dist/features/background-agent/session-idle-event-handler.d.ts +10 -0
- package/dist/features/background-agent/session-task-cleanup.d.ts +10 -0
- package/dist/features/background-agent/stale-task-pruner.d.ts +7 -1
- package/dist/hooks/auto-update-checker/checker/pinned-version-updater.d.ts +1 -0
- package/dist/hooks/auto-update-checker/checker.d.ts +1 -1
- package/dist/hooks/prometheus-md-only/agent-matcher.d.ts +1 -0
- package/dist/index.js +295 -92
- package/dist/shared/merge-categories.d.ts +6 -0
- package/package.json +8 -8
package/dist/cli/index.js
CHANGED
|
@@ -7052,6 +7052,12 @@ var init_tmux = __esm(() => {
|
|
|
7052
7052
|
var init_model_suggestion_retry = __esm(() => {
|
|
7053
7053
|
init_logger();
|
|
7054
7054
|
});
|
|
7055
|
+
|
|
7056
|
+
// src/shared/opencode-server-auth.ts
|
|
7057
|
+
var init_opencode_server_auth = __esm(() => {
|
|
7058
|
+
init_logger();
|
|
7059
|
+
});
|
|
7060
|
+
|
|
7055
7061
|
// src/shared/port-utils.ts
|
|
7056
7062
|
async function isPortAvailable(port, hostname = "127.0.0.1") {
|
|
7057
7063
|
try {
|
|
@@ -7128,6 +7134,7 @@ var init_shared = __esm(() => {
|
|
|
7128
7134
|
init_session_utils();
|
|
7129
7135
|
init_tmux();
|
|
7130
7136
|
init_model_suggestion_retry();
|
|
7137
|
+
init_opencode_server_auth();
|
|
7131
7138
|
init_port_utils();
|
|
7132
7139
|
init_git_worktree();
|
|
7133
7140
|
init_safe_create_hook();
|
|
@@ -8326,10 +8333,9 @@ var init_cached_version = __esm(() => {
|
|
|
8326
8333
|
|
|
8327
8334
|
// src/hooks/auto-update-checker/checker/pinned-version-updater.ts
|
|
8328
8335
|
import * as fs9 from "fs";
|
|
8329
|
-
function
|
|
8336
|
+
function replacePluginEntry(configPath, oldEntry, newEntry) {
|
|
8330
8337
|
try {
|
|
8331
8338
|
const content = fs9.readFileSync(configPath, "utf-8");
|
|
8332
|
-
const newEntry = `${PACKAGE_NAME3}@${newVersion}`;
|
|
8333
8339
|
const pluginMatch = content.match(/"plugin"\s*:\s*\[/);
|
|
8334
8340
|
if (!pluginMatch || pluginMatch.index === undefined) {
|
|
8335
8341
|
log(`[auto-update-checker] No "plugin" array found in ${configPath}`);
|
|
@@ -8368,6 +8374,10 @@ function updatePinnedVersion(configPath, oldEntry, newVersion) {
|
|
|
8368
8374
|
return false;
|
|
8369
8375
|
}
|
|
8370
8376
|
}
|
|
8377
|
+
function revertPinnedVersion(configPath, failedVersion, originalEntry) {
|
|
8378
|
+
const failedEntry = `${PACKAGE_NAME3}@${failedVersion}`;
|
|
8379
|
+
return replacePluginEntry(configPath, failedEntry, originalEntry);
|
|
8380
|
+
}
|
|
8371
8381
|
var init_pinned_version_updater = __esm(() => {
|
|
8372
8382
|
init_logger();
|
|
8373
8383
|
init_constants3();
|
|
@@ -8642,23 +8652,23 @@ async function runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage) {
|
|
|
8642
8652
|
return;
|
|
8643
8653
|
}
|
|
8644
8654
|
if (pluginInfo.isPinned) {
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
log("[auto-update-checker] Failed to update pinned version in config");
|
|
8649
|
-
return;
|
|
8650
|
-
}
|
|
8651
|
-
log(`[auto-update-checker] Config updated: ${pluginInfo.entry} \u2192 ${PACKAGE_NAME3}@${latestVersion}`);
|
|
8655
|
+
await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
8656
|
+
log(`[auto-update-checker] User-pinned version detected (${pluginInfo.entry}), skipping auto-update. Notification only.`);
|
|
8657
|
+
return;
|
|
8652
8658
|
}
|
|
8653
8659
|
invalidatePackage(PACKAGE_NAME3);
|
|
8654
8660
|
const installSuccess = await runBunInstallSafe();
|
|
8655
8661
|
if (installSuccess) {
|
|
8656
8662
|
await showAutoUpdatedToast(ctx, currentVersion, latestVersion);
|
|
8657
8663
|
log(`[auto-update-checker] Update installed: ${currentVersion} \u2192 ${latestVersion}`);
|
|
8658
|
-
|
|
8659
|
-
await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
8660
|
-
log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
|
|
8664
|
+
return;
|
|
8661
8665
|
}
|
|
8666
|
+
if (pluginInfo.isPinned) {
|
|
8667
|
+
revertPinnedVersion(pluginInfo.configPath, latestVersion, pluginInfo.entry);
|
|
8668
|
+
log("[auto-update-checker] Config reverted due to install failure");
|
|
8669
|
+
}
|
|
8670
|
+
await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
8671
|
+
log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
|
|
8662
8672
|
}
|
|
8663
8673
|
var init_background_update_check = __esm(() => {
|
|
8664
8674
|
init_config_manager();
|
|
@@ -8867,7 +8877,7 @@ var {
|
|
|
8867
8877
|
// package.json
|
|
8868
8878
|
var package_default = {
|
|
8869
8879
|
name: "oh-my-opencode",
|
|
8870
|
-
version: "3.5.
|
|
8880
|
+
version: "3.5.3",
|
|
8871
8881
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
8872
8882
|
main: "dist/index.js",
|
|
8873
8883
|
types: "dist/index.d.ts",
|
|
@@ -8941,13 +8951,13 @@ var package_default = {
|
|
|
8941
8951
|
typescript: "^5.7.3"
|
|
8942
8952
|
},
|
|
8943
8953
|
optionalDependencies: {
|
|
8944
|
-
"oh-my-opencode-darwin-arm64": "3.5.
|
|
8945
|
-
"oh-my-opencode-darwin-x64": "3.5.
|
|
8946
|
-
"oh-my-opencode-linux-arm64": "3.5.
|
|
8947
|
-
"oh-my-opencode-linux-arm64-musl": "3.5.
|
|
8948
|
-
"oh-my-opencode-linux-x64": "3.5.
|
|
8949
|
-
"oh-my-opencode-linux-x64-musl": "3.5.
|
|
8950
|
-
"oh-my-opencode-windows-x64": "3.5.
|
|
8954
|
+
"oh-my-opencode-darwin-arm64": "3.5.3",
|
|
8955
|
+
"oh-my-opencode-darwin-x64": "3.5.3",
|
|
8956
|
+
"oh-my-opencode-linux-arm64": "3.5.3",
|
|
8957
|
+
"oh-my-opencode-linux-arm64-musl": "3.5.3",
|
|
8958
|
+
"oh-my-opencode-linux-x64": "3.5.3",
|
|
8959
|
+
"oh-my-opencode-linux-x64-musl": "3.5.3",
|
|
8960
|
+
"oh-my-opencode-windows-x64": "3.5.3"
|
|
8951
8961
|
},
|
|
8952
8962
|
trustedDependencies: [
|
|
8953
8963
|
"@ast-grep/cli",
|
|
@@ -22716,7 +22726,8 @@ var CategoryConfigSchema = exports_external.object({
|
|
|
22716
22726
|
textVerbosity: exports_external.enum(["low", "medium", "high"]).optional(),
|
|
22717
22727
|
tools: exports_external.record(exports_external.string(), exports_external.boolean()).optional(),
|
|
22718
22728
|
prompt_append: exports_external.string().optional(),
|
|
22719
|
-
is_unstable_agent: exports_external.boolean().optional()
|
|
22729
|
+
is_unstable_agent: exports_external.boolean().optional(),
|
|
22730
|
+
disable: exports_external.boolean().optional()
|
|
22720
22731
|
});
|
|
22721
22732
|
var BuiltinCategoryNameSchema = exports_external.enum([
|
|
22722
22733
|
"visual-engineering",
|
|
@@ -24748,11 +24759,14 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
|
|
|
24748
24759
|
var DEFAULT_POLL_INTERVAL_MS = 500;
|
|
24749
24760
|
var DEFAULT_REQUIRED_CONSECUTIVE = 3;
|
|
24750
24761
|
var ERROR_GRACE_CYCLES = 3;
|
|
24762
|
+
var MIN_STABILIZATION_MS = 1e4;
|
|
24751
24763
|
async function pollForCompletion(ctx, eventState, abortController, options = {}) {
|
|
24752
24764
|
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
24753
24765
|
const requiredConsecutive = options.requiredConsecutive ?? DEFAULT_REQUIRED_CONSECUTIVE;
|
|
24766
|
+
const minStabilizationMs = options.minStabilizationMs ?? MIN_STABILIZATION_MS;
|
|
24754
24767
|
let consecutiveCompleteChecks = 0;
|
|
24755
24768
|
let errorCycleCount = 0;
|
|
24769
|
+
let firstWorkTimestamp = null;
|
|
24756
24770
|
while (!abortController.signal.aborted) {
|
|
24757
24771
|
await new Promise((resolve2) => setTimeout(resolve2, pollIntervalMs));
|
|
24758
24772
|
if (eventState.mainSessionError) {
|
|
@@ -24780,6 +24794,13 @@ Session ended with error: ${eventState.lastError}`));
|
|
|
24780
24794
|
consecutiveCompleteChecks = 0;
|
|
24781
24795
|
continue;
|
|
24782
24796
|
}
|
|
24797
|
+
if (firstWorkTimestamp === null) {
|
|
24798
|
+
firstWorkTimestamp = Date.now();
|
|
24799
|
+
}
|
|
24800
|
+
if (Date.now() - firstWorkTimestamp < minStabilizationMs) {
|
|
24801
|
+
consecutiveCompleteChecks = 0;
|
|
24802
|
+
continue;
|
|
24803
|
+
}
|
|
24783
24804
|
const shouldExit = await checkCompletionConditions(ctx);
|
|
24784
24805
|
if (shouldExit) {
|
|
24785
24806
|
consecutiveCompleteChecks++;
|
|
@@ -24844,7 +24865,7 @@ Interrupted. Shutting down...`));
|
|
|
24844
24865
|
});
|
|
24845
24866
|
console.log(import_picocolors14.default.dim(`Session: ${sessionID}`));
|
|
24846
24867
|
const ctx = { client: client3, sessionID, directory, abortController };
|
|
24847
|
-
const events = await client3.event.subscribe();
|
|
24868
|
+
const events = await client3.event.subscribe({ query: { directory } });
|
|
24848
24869
|
const eventState = createEventState();
|
|
24849
24870
|
const eventProcessor = processEvents(ctx, events.stream, eventState).catch(() => {});
|
|
24850
24871
|
console.log(import_picocolors14.default.dim(`
|
|
@@ -3,5 +3,6 @@ import type { EventState } from "./events";
|
|
|
3
3
|
export interface PollOptions {
|
|
4
4
|
pollIntervalMs?: number;
|
|
5
5
|
requiredConsecutive?: number;
|
|
6
|
+
minStabilizationMs?: number;
|
|
6
7
|
}
|
|
7
8
|
export declare function pollForCompletion(ctx: RunContext, eventState: EventState, abortController: AbortController, options?: PollOptions): Promise<number>;
|
|
@@ -27,6 +27,7 @@ export declare const CategoryConfigSchema: z.ZodObject<{
|
|
|
27
27
|
tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
28
28
|
prompt_append: z.ZodOptional<z.ZodString>;
|
|
29
29
|
is_unstable_agent: z.ZodOptional<z.ZodBoolean>;
|
|
30
|
+
disable: z.ZodOptional<z.ZodBoolean>;
|
|
30
31
|
}, z.core.$strip>;
|
|
31
32
|
export declare const BuiltinCategoryNameSchema: z.ZodEnum<{
|
|
32
33
|
"visual-engineering": "visual-engineering";
|
|
@@ -66,6 +67,7 @@ export declare const CategoriesConfigSchema: z.ZodRecord<z.ZodString, z.ZodObjec
|
|
|
66
67
|
tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
67
68
|
prompt_append: z.ZodOptional<z.ZodString>;
|
|
68
69
|
is_unstable_agent: z.ZodOptional<z.ZodBoolean>;
|
|
70
|
+
disable: z.ZodOptional<z.ZodBoolean>;
|
|
69
71
|
}, z.core.$strip>>;
|
|
70
72
|
export type CategoryConfig = z.infer<typeof CategoryConfigSchema>;
|
|
71
73
|
export type CategoriesConfig = z.infer<typeof CategoriesConfigSchema>;
|
|
@@ -1158,6 +1158,7 @@ export declare const OhMyOpenCodeConfigSchema: z.ZodObject<{
|
|
|
1158
1158
|
tools: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
1159
1159
|
prompt_append: z.ZodOptional<z.ZodString>;
|
|
1160
1160
|
is_unstable_agent: z.ZodOptional<z.ZodBoolean>;
|
|
1161
|
+
disable: z.ZodOptional<z.ZodBoolean>;
|
|
1161
1162
|
}, z.core.$strip>>>;
|
|
1162
1163
|
claude_code: z.ZodOptional<z.ZodObject<{
|
|
1163
1164
|
mcp: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -7,6 +7,7 @@ export declare function handleBackgroundEvent(args: {
|
|
|
7
7
|
event: Event;
|
|
8
8
|
findBySession: (sessionID: string) => BackgroundTask | undefined;
|
|
9
9
|
getAllDescendantTasks: (sessionID: string) => BackgroundTask[];
|
|
10
|
+
releaseConcurrencyKey?: (key: string) => void;
|
|
10
11
|
cancelTask: (taskId: string, options: {
|
|
11
12
|
source: string;
|
|
12
13
|
reason: string;
|
|
@@ -114,6 +114,8 @@ export declare class BackgroundManager {
|
|
|
114
114
|
private formatDuration;
|
|
115
115
|
private isAbortedSessionError;
|
|
116
116
|
private getErrorText;
|
|
117
|
+
private isRecord;
|
|
118
|
+
private getSessionErrorMessage;
|
|
117
119
|
private hasRunningTasks;
|
|
118
120
|
private pruneStaleTasksAndNotifications;
|
|
119
121
|
private checkAndInterruptStaleTasks;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BackgroundTask } from "./types";
|
|
2
|
+
export declare function handleSessionIdleBackgroundEvent(args: {
|
|
3
|
+
properties: Record<string, unknown>;
|
|
4
|
+
findBySession: (sessionID: string) => BackgroundTask | undefined;
|
|
5
|
+
idleDeferralTimers: Map<string, ReturnType<typeof setTimeout>>;
|
|
6
|
+
validateSessionHasOutput: (sessionID: string) => Promise<boolean>;
|
|
7
|
+
checkSessionTodos: (sessionID: string) => Promise<boolean>;
|
|
8
|
+
tryCompleteTask: (task: BackgroundTask, source: string) => Promise<boolean>;
|
|
9
|
+
emitIdleEvent: (sessionID: string) => void;
|
|
10
|
+
}): void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BackgroundTask } from "./types";
|
|
2
|
+
export declare function cleanupTaskAfterSessionEnds(args: {
|
|
3
|
+
task: BackgroundTask;
|
|
4
|
+
tasks: Map<string, BackgroundTask>;
|
|
5
|
+
idleDeferralTimers: Map<string, ReturnType<typeof setTimeout>>;
|
|
6
|
+
completionTimers: Map<string, ReturnType<typeof setTimeout>>;
|
|
7
|
+
cleanupPendingByParent: (task: BackgroundTask) => void;
|
|
8
|
+
clearNotificationsForTask: (taskId: string) => void;
|
|
9
|
+
releaseConcurrencyKey?: (key: string) => void;
|
|
10
|
+
}): void;
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import type { BackgroundTask } from "./types";
|
|
1
|
+
import type { BackgroundTask, LaunchInput } from "./types";
|
|
2
2
|
import type { ConcurrencyManager } from "./concurrency";
|
|
3
|
+
type QueueItem = {
|
|
4
|
+
task: BackgroundTask;
|
|
5
|
+
input: LaunchInput;
|
|
6
|
+
};
|
|
3
7
|
export declare function pruneStaleState(args: {
|
|
4
8
|
tasks: Map<string, BackgroundTask>;
|
|
5
9
|
notifications: Map<string, BackgroundTask[]>;
|
|
10
|
+
queuesByKey: Map<string, QueueItem[]>;
|
|
6
11
|
concurrencyManager: ConcurrencyManager;
|
|
7
12
|
cleanupPendingByParent: (task: BackgroundTask) => void;
|
|
8
13
|
clearNotificationsForTask: (taskId: string) => void;
|
|
9
14
|
}): void;
|
|
15
|
+
export {};
|
|
@@ -3,6 +3,6 @@ export { getLocalDevVersion } from "./checker/local-dev-version";
|
|
|
3
3
|
export { findPluginEntry } from "./checker/plugin-entry";
|
|
4
4
|
export type { PluginEntryInfo } from "./checker/plugin-entry";
|
|
5
5
|
export { getCachedVersion } from "./checker/cached-version";
|
|
6
|
-
export { updatePinnedVersion } from "./checker/pinned-version-updater";
|
|
6
|
+
export { updatePinnedVersion, revertPinnedVersion } from "./checker/pinned-version-updater";
|
|
7
7
|
export { getLatestVersion } from "./checker/latest-version";
|
|
8
8
|
export { checkForUpdate } from "./checker/check-for-update";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isPrometheusAgent(agentName: string | undefined): boolean;
|
package/dist/index.js
CHANGED
|
@@ -12252,7 +12252,14 @@ function readBoulderState(directory) {
|
|
|
12252
12252
|
}
|
|
12253
12253
|
try {
|
|
12254
12254
|
const content = readFileSync(filePath, "utf-8");
|
|
12255
|
-
|
|
12255
|
+
const parsed = JSON.parse(content);
|
|
12256
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
12257
|
+
return null;
|
|
12258
|
+
}
|
|
12259
|
+
if (!Array.isArray(parsed.session_ids)) {
|
|
12260
|
+
parsed.session_ids = [];
|
|
12261
|
+
}
|
|
12262
|
+
return parsed;
|
|
12256
12263
|
} catch {
|
|
12257
12264
|
return null;
|
|
12258
12265
|
}
|
|
@@ -12274,7 +12281,10 @@ function appendSessionId(directory, sessionId) {
|
|
|
12274
12281
|
const state = readBoulderState(directory);
|
|
12275
12282
|
if (!state)
|
|
12276
12283
|
return null;
|
|
12277
|
-
if (!state.session_ids
|
|
12284
|
+
if (!state.session_ids?.includes(sessionId)) {
|
|
12285
|
+
if (!Array.isArray(state.session_ids)) {
|
|
12286
|
+
state.session_ids = [];
|
|
12287
|
+
}
|
|
12278
12288
|
state.session_ids.push(sessionId);
|
|
12279
12289
|
if (writeBoulderState(directory, state)) {
|
|
12280
12290
|
return state;
|
|
@@ -26785,7 +26795,7 @@ function createCommentCheckerHooks(config2) {
|
|
|
26785
26795
|
"tool.execute.after": async (input, output) => {
|
|
26786
26796
|
debugLog3("tool.execute.after:", { tool: input.tool, callID: input.callID });
|
|
26787
26797
|
const toolLower = input.tool.toLowerCase();
|
|
26788
|
-
const outputLower = output.output.toLowerCase();
|
|
26798
|
+
const outputLower = (output.output ?? "").toLowerCase();
|
|
26789
26799
|
const isToolFailure = outputLower.includes("error:") || outputLower.includes("failed to") || outputLower.includes("could not") || outputLower.startsWith("error");
|
|
26790
26800
|
if (isToolFailure) {
|
|
26791
26801
|
debugLog3("skipping due to tool failure in output");
|
|
@@ -34304,6 +34314,7 @@ async function promptSyncWithModelSuggestionRetry(client, args) {
|
|
|
34304
34314
|
}
|
|
34305
34315
|
}
|
|
34306
34316
|
// src/shared/opencode-server-auth.ts
|
|
34317
|
+
init_logger();
|
|
34307
34318
|
function getServerBasicAuthHeader() {
|
|
34308
34319
|
const password = process.env.OPENCODE_SERVER_PASSWORD;
|
|
34309
34320
|
if (!password) {
|
|
@@ -34313,27 +34324,128 @@ function getServerBasicAuthHeader() {
|
|
|
34313
34324
|
const token = Buffer.from(`${username}:${password}`, "utf8").toString("base64");
|
|
34314
34325
|
return `Basic ${token}`;
|
|
34315
34326
|
}
|
|
34327
|
+
function isRecord(value) {
|
|
34328
|
+
return typeof value === "object" && value !== null;
|
|
34329
|
+
}
|
|
34330
|
+
function isRequestFetch(value) {
|
|
34331
|
+
return typeof value === "function";
|
|
34332
|
+
}
|
|
34333
|
+
function wrapRequestFetch(baseFetch, auth) {
|
|
34334
|
+
return async (request) => {
|
|
34335
|
+
const headers = new Headers(request.headers);
|
|
34336
|
+
headers.set("Authorization", auth);
|
|
34337
|
+
return baseFetch(new Request(request, { headers }));
|
|
34338
|
+
};
|
|
34339
|
+
}
|
|
34340
|
+
function getInternalClient(client) {
|
|
34341
|
+
if (!isRecord(client)) {
|
|
34342
|
+
return null;
|
|
34343
|
+
}
|
|
34344
|
+
const internal = client["_client"];
|
|
34345
|
+
return isRecord(internal) ? internal : null;
|
|
34346
|
+
}
|
|
34347
|
+
function tryInjectViaSetConfigHeaders(internal, auth) {
|
|
34348
|
+
const setConfig = internal["setConfig"];
|
|
34349
|
+
if (typeof setConfig !== "function") {
|
|
34350
|
+
return false;
|
|
34351
|
+
}
|
|
34352
|
+
setConfig({
|
|
34353
|
+
headers: {
|
|
34354
|
+
Authorization: auth
|
|
34355
|
+
}
|
|
34356
|
+
});
|
|
34357
|
+
return true;
|
|
34358
|
+
}
|
|
34359
|
+
function tryInjectViaInterceptors(internal, auth) {
|
|
34360
|
+
const interceptors = internal["interceptors"];
|
|
34361
|
+
if (!isRecord(interceptors)) {
|
|
34362
|
+
return false;
|
|
34363
|
+
}
|
|
34364
|
+
const requestInterceptors = interceptors["request"];
|
|
34365
|
+
if (!isRecord(requestInterceptors)) {
|
|
34366
|
+
return false;
|
|
34367
|
+
}
|
|
34368
|
+
const use = requestInterceptors["use"];
|
|
34369
|
+
if (typeof use !== "function") {
|
|
34370
|
+
return false;
|
|
34371
|
+
}
|
|
34372
|
+
use((request) => {
|
|
34373
|
+
if (!request.headers.get("Authorization")) {
|
|
34374
|
+
request.headers.set("Authorization", auth);
|
|
34375
|
+
}
|
|
34376
|
+
return request;
|
|
34377
|
+
});
|
|
34378
|
+
return true;
|
|
34379
|
+
}
|
|
34380
|
+
function tryInjectViaFetchWrapper(internal, auth) {
|
|
34381
|
+
const getConfig = internal["getConfig"];
|
|
34382
|
+
const setConfig = internal["setConfig"];
|
|
34383
|
+
if (typeof getConfig !== "function" || typeof setConfig !== "function") {
|
|
34384
|
+
return false;
|
|
34385
|
+
}
|
|
34386
|
+
const config2 = getConfig();
|
|
34387
|
+
if (!isRecord(config2)) {
|
|
34388
|
+
return false;
|
|
34389
|
+
}
|
|
34390
|
+
const fetchValue = config2["fetch"];
|
|
34391
|
+
if (!isRequestFetch(fetchValue)) {
|
|
34392
|
+
return false;
|
|
34393
|
+
}
|
|
34394
|
+
setConfig({
|
|
34395
|
+
fetch: wrapRequestFetch(fetchValue, auth)
|
|
34396
|
+
});
|
|
34397
|
+
return true;
|
|
34398
|
+
}
|
|
34399
|
+
function tryInjectViaMutableInternalConfig(internal, auth) {
|
|
34400
|
+
const configValue = internal["_config"];
|
|
34401
|
+
if (!isRecord(configValue)) {
|
|
34402
|
+
return false;
|
|
34403
|
+
}
|
|
34404
|
+
const fetchValue = configValue["fetch"];
|
|
34405
|
+
if (!isRequestFetch(fetchValue)) {
|
|
34406
|
+
return false;
|
|
34407
|
+
}
|
|
34408
|
+
configValue["fetch"] = wrapRequestFetch(fetchValue, auth);
|
|
34409
|
+
return true;
|
|
34410
|
+
}
|
|
34411
|
+
function tryInjectViaTopLevelFetch(client, auth) {
|
|
34412
|
+
if (!isRecord(client)) {
|
|
34413
|
+
return false;
|
|
34414
|
+
}
|
|
34415
|
+
const fetchValue = client["fetch"];
|
|
34416
|
+
if (!isRequestFetch(fetchValue)) {
|
|
34417
|
+
return false;
|
|
34418
|
+
}
|
|
34419
|
+
client["fetch"] = wrapRequestFetch(fetchValue, auth);
|
|
34420
|
+
return true;
|
|
34421
|
+
}
|
|
34316
34422
|
function injectServerAuthIntoClient(client) {
|
|
34317
34423
|
const auth = getServerBasicAuthHeader();
|
|
34318
34424
|
if (!auth) {
|
|
34319
34425
|
return;
|
|
34320
34426
|
}
|
|
34321
34427
|
try {
|
|
34322
|
-
|
|
34323
|
-
|
|
34428
|
+
const internal = getInternalClient(client);
|
|
34429
|
+
if (internal) {
|
|
34430
|
+
const injectedHeaders = tryInjectViaSetConfigHeaders(internal, auth);
|
|
34431
|
+
const injectedInterceptors = tryInjectViaInterceptors(internal, auth);
|
|
34432
|
+
const injectedFetch = tryInjectViaFetchWrapper(internal, auth);
|
|
34433
|
+
const injectedMutable = tryInjectViaMutableInternalConfig(internal, auth);
|
|
34434
|
+
const injected2 = injectedHeaders || injectedInterceptors || injectedFetch || injectedMutable;
|
|
34435
|
+
if (!injected2) {
|
|
34436
|
+
log("[opencode-server-auth] OPENCODE_SERVER_PASSWORD is set but SDK client structure is incompatible", {
|
|
34437
|
+
keys: Object.keys(internal)
|
|
34438
|
+
});
|
|
34439
|
+
}
|
|
34440
|
+
return;
|
|
34324
34441
|
}
|
|
34325
|
-
const
|
|
34326
|
-
if (
|
|
34327
|
-
|
|
34442
|
+
const injected = tryInjectViaTopLevelFetch(client, auth);
|
|
34443
|
+
if (!injected) {
|
|
34444
|
+
log("[opencode-server-auth] OPENCODE_SERVER_PASSWORD is set but no compatible SDK client found");
|
|
34328
34445
|
}
|
|
34329
|
-
internal.setConfig({
|
|
34330
|
-
headers: {
|
|
34331
|
-
Authorization: auth
|
|
34332
|
-
}
|
|
34333
|
-
});
|
|
34334
34446
|
} catch (error45) {
|
|
34335
34447
|
const message = error45 instanceof Error ? error45.message : String(error45);
|
|
34336
|
-
|
|
34448
|
+
log("[opencode-server-auth] Failed to inject server auth", { message });
|
|
34337
34449
|
}
|
|
34338
34450
|
}
|
|
34339
34451
|
// src/shared/git-worktree/parse-status-porcelain.ts
|
|
@@ -36389,10 +36501,9 @@ function getCachedVersion() {
|
|
|
36389
36501
|
// src/hooks/auto-update-checker/checker/pinned-version-updater.ts
|
|
36390
36502
|
init_logger();
|
|
36391
36503
|
import * as fs12 from "fs";
|
|
36392
|
-
function
|
|
36504
|
+
function replacePluginEntry(configPath, oldEntry, newEntry) {
|
|
36393
36505
|
try {
|
|
36394
36506
|
const content = fs12.readFileSync(configPath, "utf-8");
|
|
36395
|
-
const newEntry = `${PACKAGE_NAME}@${newVersion}`;
|
|
36396
36507
|
const pluginMatch = content.match(/"plugin"\s*:\s*\[/);
|
|
36397
36508
|
if (!pluginMatch || pluginMatch.index === undefined) {
|
|
36398
36509
|
log(`[auto-update-checker] No "plugin" array found in ${configPath}`);
|
|
@@ -36431,6 +36542,10 @@ function updatePinnedVersion(configPath, oldEntry, newVersion) {
|
|
|
36431
36542
|
return false;
|
|
36432
36543
|
}
|
|
36433
36544
|
}
|
|
36545
|
+
function revertPinnedVersion(configPath, failedVersion, originalEntry) {
|
|
36546
|
+
const failedEntry = `${PACKAGE_NAME}@${failedVersion}`;
|
|
36547
|
+
return replacePluginEntry(configPath, failedEntry, originalEntry);
|
|
36548
|
+
}
|
|
36434
36549
|
// src/hooks/auto-update-checker/checker/latest-version.ts
|
|
36435
36550
|
async function getLatestVersion(channel = "latest") {
|
|
36436
36551
|
const controller = new AbortController;
|
|
@@ -36673,23 +36788,23 @@ async function runBackgroundUpdateCheck(ctx, autoUpdate, getToastMessage) {
|
|
|
36673
36788
|
return;
|
|
36674
36789
|
}
|
|
36675
36790
|
if (pluginInfo.isPinned) {
|
|
36676
|
-
|
|
36677
|
-
|
|
36678
|
-
|
|
36679
|
-
log("[auto-update-checker] Failed to update pinned version in config");
|
|
36680
|
-
return;
|
|
36681
|
-
}
|
|
36682
|
-
log(`[auto-update-checker] Config updated: ${pluginInfo.entry} \u2192 ${PACKAGE_NAME}@${latestVersion}`);
|
|
36791
|
+
await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
36792
|
+
log(`[auto-update-checker] User-pinned version detected (${pluginInfo.entry}), skipping auto-update. Notification only.`);
|
|
36793
|
+
return;
|
|
36683
36794
|
}
|
|
36684
36795
|
invalidatePackage(PACKAGE_NAME);
|
|
36685
36796
|
const installSuccess = await runBunInstallSafe();
|
|
36686
36797
|
if (installSuccess) {
|
|
36687
36798
|
await showAutoUpdatedToast(ctx, currentVersion, latestVersion);
|
|
36688
36799
|
log(`[auto-update-checker] Update installed: ${currentVersion} \u2192 ${latestVersion}`);
|
|
36689
|
-
|
|
36690
|
-
|
|
36691
|
-
|
|
36800
|
+
return;
|
|
36801
|
+
}
|
|
36802
|
+
if (pluginInfo.isPinned) {
|
|
36803
|
+
revertPinnedVersion(pluginInfo.configPath, latestVersion, pluginInfo.entry);
|
|
36804
|
+
log("[auto-update-checker] Config reverted due to install failure");
|
|
36692
36805
|
}
|
|
36806
|
+
await showUpdateAvailableToast(ctx, latestVersion, getToastMessage);
|
|
36807
|
+
log("[auto-update-checker] bun install failed; update not installed (falling back to notification-only)");
|
|
36693
36808
|
}
|
|
36694
36809
|
|
|
36695
36810
|
// src/hooks/auto-update-checker/hook/config-errors-toast.ts
|
|
@@ -42698,7 +42813,7 @@ async function executeSlashCommand(parsed, options) {
|
|
|
42698
42813
|
if (!command) {
|
|
42699
42814
|
return {
|
|
42700
42815
|
success: false,
|
|
42701
|
-
error: `Command "/${parsed.command}" not found. Use the slashcommand tool to list available commands.`
|
|
42816
|
+
error: parsed.command.includes(":") ? `Marketplace plugin commands like "/${parsed.command}" are not supported. Use .claude/commands/ for custom commands.` : `Command "/${parsed.command}" not found. Use the slashcommand tool to list available commands.`
|
|
42702
42817
|
};
|
|
42703
42818
|
}
|
|
42704
42819
|
try {
|
|
@@ -42832,7 +42947,7 @@ function createEditErrorRecoveryHook(_ctx) {
|
|
|
42832
42947
|
"tool.execute.after": async (input, output) => {
|
|
42833
42948
|
if (input.tool.toLowerCase() !== "edit")
|
|
42834
42949
|
return;
|
|
42835
|
-
const outputLower = output.output.toLowerCase();
|
|
42950
|
+
const outputLower = (output.output ?? "").toLowerCase();
|
|
42836
42951
|
const hasEditError = EDIT_ERROR_PATTERNS.some((pattern) => outputLower.includes(pattern.toLowerCase()));
|
|
42837
42952
|
if (hasEditError) {
|
|
42838
42953
|
output.output += `
|
|
@@ -42965,12 +43080,17 @@ function getAgentFromSession(sessionID, directory) {
|
|
|
42965
43080
|
if (memoryAgent)
|
|
42966
43081
|
return memoryAgent;
|
|
42967
43082
|
const boulderState = readBoulderState(directory);
|
|
42968
|
-
if (boulderState?.session_ids
|
|
43083
|
+
if (boulderState?.session_ids?.includes(sessionID) && boulderState.agent) {
|
|
42969
43084
|
return boulderState.agent;
|
|
42970
43085
|
}
|
|
42971
43086
|
return getAgentFromMessageFiles(sessionID);
|
|
42972
43087
|
}
|
|
42973
43088
|
|
|
43089
|
+
// src/hooks/prometheus-md-only/agent-matcher.ts
|
|
43090
|
+
function isPrometheusAgent(agentName) {
|
|
43091
|
+
return agentName?.toLowerCase().includes(PROMETHEUS_AGENT) ?? false;
|
|
43092
|
+
}
|
|
43093
|
+
|
|
42974
43094
|
// src/hooks/prometheus-md-only/path-policy.ts
|
|
42975
43095
|
import { relative as relative3, resolve as resolve7, isAbsolute as isAbsolute3 } from "path";
|
|
42976
43096
|
function isAllowedFile(filePath, workspaceRoot) {
|
|
@@ -42995,7 +43115,7 @@ function createPrometheusMdOnlyHook(ctx) {
|
|
|
42995
43115
|
return {
|
|
42996
43116
|
"tool.execute.before": async (input, output) => {
|
|
42997
43117
|
const agentName = getAgentFromSession(input.sessionID, ctx.directory);
|
|
42998
|
-
if (agentName
|
|
43118
|
+
if (!isPrometheusAgent(agentName)) {
|
|
42999
43119
|
return;
|
|
43000
43120
|
}
|
|
43001
43121
|
const toolName = input.tool;
|
|
@@ -43120,15 +43240,16 @@ function createTaskResumeInfoHook() {
|
|
|
43120
43240
|
const toolExecuteAfter = async (input, output) => {
|
|
43121
43241
|
if (!TARGET_TOOLS2.includes(input.tool))
|
|
43122
43242
|
return;
|
|
43123
|
-
|
|
43243
|
+
const outputText = output.output ?? "";
|
|
43244
|
+
if (outputText.startsWith("Error:") || outputText.startsWith("Failed"))
|
|
43124
43245
|
return;
|
|
43125
|
-
if (
|
|
43246
|
+
if (outputText.includes(`
|
|
43126
43247
|
to continue:`))
|
|
43127
43248
|
return;
|
|
43128
|
-
const sessionId = extractSessionId(
|
|
43249
|
+
const sessionId = extractSessionId(outputText);
|
|
43129
43250
|
if (!sessionId)
|
|
43130
43251
|
return;
|
|
43131
|
-
output.output =
|
|
43252
|
+
output.output = outputText.trimEnd() + `
|
|
43132
43253
|
|
|
43133
43254
|
to continue: task(session_id="${sessionId}", prompt="...")`;
|
|
43134
43255
|
};
|
|
@@ -43629,7 +43750,7 @@ function createAtlasEventHandler(input) {
|
|
|
43629
43750
|
return;
|
|
43630
43751
|
log(`[${HOOK_NAME7}] session.idle`, { sessionID });
|
|
43631
43752
|
const boulderState = readBoulderState(ctx.directory);
|
|
43632
|
-
const isBoulderSession = boulderState?.session_ids
|
|
43753
|
+
const isBoulderSession = boulderState?.session_ids?.includes(sessionID) ?? false;
|
|
43633
43754
|
const isBackgroundTaskSession = subagentSessions.has(sessionID);
|
|
43634
43755
|
if (!isBackgroundTaskSession && !isBoulderSession) {
|
|
43635
43756
|
log(`[${HOOK_NAME7}] Skipped: not boulder or background task session`, { sessionID });
|
|
@@ -43798,7 +43919,23 @@ function buildOrchestratorReminder(planName, progress, sessionId) {
|
|
|
43798
43919
|
|
|
43799
43920
|
${buildVerificationReminder(sessionId)}
|
|
43800
43921
|
|
|
43801
|
-
**STEP 5:
|
|
43922
|
+
**STEP 5: READ SUBAGENT NOTEPAD (LEARNINGS, ISSUES, PROBLEMS)**
|
|
43923
|
+
|
|
43924
|
+
The subagent was instructed to record findings in notepad files. Read them NOW:
|
|
43925
|
+
\`\`\`
|
|
43926
|
+
Glob(".sisyphus/notepads/${planName}/*.md")
|
|
43927
|
+
\`\`\`
|
|
43928
|
+
Then \`Read\` each file found \u2014 especially:
|
|
43929
|
+
- **learnings.md**: Patterns, conventions, successful approaches discovered
|
|
43930
|
+
- **issues.md**: Problems, blockers, gotchas encountered during work
|
|
43931
|
+
- **problems.md**: Unresolved issues, technical debt flagged
|
|
43932
|
+
|
|
43933
|
+
**USE this information to:**
|
|
43934
|
+
- Inform your next delegation (avoid known pitfalls)
|
|
43935
|
+
- Adjust your plan if blockers were discovered
|
|
43936
|
+
- Propagate learnings to subsequent subagents
|
|
43937
|
+
|
|
43938
|
+
**STEP 6: CHECK BOULDER STATE DIRECTLY (EVERY TIME \u2014 NO EXCEPTIONS)**
|
|
43802
43939
|
|
|
43803
43940
|
Do NOT rely on cached progress. Read the plan file NOW:
|
|
43804
43941
|
\`\`\`
|
|
@@ -43807,7 +43944,7 @@ Read(".sisyphus/plans/${planName}.md")
|
|
|
43807
43944
|
Count exactly: how many \`- [ ]\` remain? How many \`- [x]\` completed?
|
|
43808
43945
|
This is YOUR ground truth. Use it to decide what comes next.
|
|
43809
43946
|
|
|
43810
|
-
**STEP
|
|
43947
|
+
**STEP 7: MARK COMPLETION IN PLAN FILE (IMMEDIATELY)**
|
|
43811
43948
|
|
|
43812
43949
|
RIGHT NOW - Do not delay. Verification passed \u2192 Mark IMMEDIATELY.
|
|
43813
43950
|
|
|
@@ -43817,12 +43954,12 @@ Update the plan file \`.sisyphus/plans/${planName}.md\`:
|
|
|
43817
43954
|
|
|
43818
43955
|
**DO THIS BEFORE ANYTHING ELSE. Unmarked = Untracked = Lost progress.**
|
|
43819
43956
|
|
|
43820
|
-
**STEP
|
|
43957
|
+
**STEP 8: COMMIT ATOMIC UNIT**
|
|
43821
43958
|
|
|
43822
43959
|
- Stage ONLY the verified changes
|
|
43823
43960
|
- Commit with clear message describing what was done
|
|
43824
43961
|
|
|
43825
|
-
**STEP
|
|
43962
|
+
**STEP 9: PROCEED TO NEXT TASK**
|
|
43826
43963
|
|
|
43827
43964
|
- Read the plan file AGAIN to identify the next \`- [ ]\` task
|
|
43828
43965
|
- Start immediately - DO NOT STOP
|
|
@@ -43916,7 +44053,7 @@ function createToolExecuteAfterHandler2(input) {
|
|
|
43916
44053
|
const boulderState = readBoulderState(ctx.directory);
|
|
43917
44054
|
if (boulderState) {
|
|
43918
44055
|
const progress = getPlanProgress(boulderState.active_plan);
|
|
43919
|
-
if (toolInput.sessionID && !boulderState.session_ids
|
|
44056
|
+
if (toolInput.sessionID && !boulderState.session_ids?.includes(toolInput.sessionID)) {
|
|
43920
44057
|
appendSessionId(ctx.directory, toolInput.sessionID);
|
|
43921
44058
|
log(`[${HOOK_NAME7}] Appended session to boulder`, {
|
|
43922
44059
|
sessionID: toolInput.sessionID,
|
|
@@ -44380,16 +44517,16 @@ var THINKING_SUMMARY_MAX_CHARS = 500;
|
|
|
44380
44517
|
function hasData(value) {
|
|
44381
44518
|
return typeof value === "object" && value !== null && "data" in value;
|
|
44382
44519
|
}
|
|
44383
|
-
function
|
|
44520
|
+
function isRecord2(value) {
|
|
44384
44521
|
return typeof value === "object" && value !== null;
|
|
44385
44522
|
}
|
|
44386
44523
|
function getMessageInfo(value) {
|
|
44387
|
-
if (!
|
|
44524
|
+
if (!isRecord2(value))
|
|
44388
44525
|
return;
|
|
44389
|
-
if (!
|
|
44526
|
+
if (!isRecord2(value.info))
|
|
44390
44527
|
return;
|
|
44391
44528
|
const info = value.info;
|
|
44392
|
-
const modelValue =
|
|
44529
|
+
const modelValue = isRecord2(info.model) ? info.model : undefined;
|
|
44393
44530
|
const model = modelValue && typeof modelValue.providerID === "string" && typeof modelValue.modelID === "string" ? { providerID: modelValue.providerID, modelID: modelValue.modelID } : undefined;
|
|
44394
44531
|
return {
|
|
44395
44532
|
role: typeof info.role === "string" ? info.role : undefined,
|
|
@@ -44400,11 +44537,11 @@ function getMessageInfo(value) {
|
|
|
44400
44537
|
};
|
|
44401
44538
|
}
|
|
44402
44539
|
function getMessageParts(value) {
|
|
44403
|
-
if (!
|
|
44540
|
+
if (!isRecord2(value))
|
|
44404
44541
|
return [];
|
|
44405
44542
|
if (!Array.isArray(value.parts))
|
|
44406
44543
|
return [];
|
|
44407
|
-
return value.parts.filter(
|
|
44544
|
+
return value.parts.filter(isRecord2).map((part) => ({
|
|
44408
44545
|
type: typeof part.type === "string" ? part.type : undefined,
|
|
44409
44546
|
text: typeof part.text === "string" ? part.text : undefined,
|
|
44410
44547
|
thinking: typeof part.thinking === "string" ? part.thinking : undefined
|
|
@@ -47804,7 +47941,9 @@ Provide a command or skill name to execute.`;
|
|
|
47804
47941
|
|
|
47805
47942
|
${formatCommandList(allItems)}`;
|
|
47806
47943
|
}
|
|
47807
|
-
return `
|
|
47944
|
+
return commandName.includes(":") ? `Marketplace plugin commands like "/${commandName}" are not supported. Use .claude/commands/ for custom commands.
|
|
47945
|
+
|
|
47946
|
+
${formatCommandList(allItems)}` : `Command or skill "/${commandName}" not found.
|
|
47808
47947
|
|
|
47809
47948
|
${formatCommandList(allItems)}
|
|
47810
47949
|
|
|
@@ -49526,10 +49665,7 @@ async function createOrGetSession(args, toolContext, ctx) {
|
|
|
49526
49665
|
const createResult = await ctx.client.session.create({
|
|
49527
49666
|
body: {
|
|
49528
49667
|
parentID: toolContext.sessionID,
|
|
49529
|
-
title: `${args.description} (@${args.subagent_type} subagent)
|
|
49530
|
-
permission: [
|
|
49531
|
-
{ permission: "question", action: "deny", pattern: "*" }
|
|
49532
|
-
]
|
|
49668
|
+
title: `${args.description} (@${args.subagent_type} subagent)`
|
|
49533
49669
|
},
|
|
49534
49670
|
query: {
|
|
49535
49671
|
directory: parentDirectory
|
|
@@ -49552,6 +49688,7 @@ Original error: ${createResult.error}`);
|
|
|
49552
49688
|
}
|
|
49553
49689
|
const sessionID = createResult.data.id;
|
|
49554
49690
|
log(`[call_omo_agent] Created session: ${sessionID}`);
|
|
49691
|
+
subagentSessions.add(sessionID);
|
|
49555
49692
|
return { sessionID, isNew: true };
|
|
49556
49693
|
}
|
|
49557
49694
|
}
|
|
@@ -50027,6 +50164,15 @@ Original error: ${createResult.error}`;
|
|
|
50027
50164
|
}
|
|
50028
50165
|
// src/tools/delegate-task/tools.ts
|
|
50029
50166
|
init_constants();
|
|
50167
|
+
|
|
50168
|
+
// src/shared/merge-categories.ts
|
|
50169
|
+
init_constants();
|
|
50170
|
+
function mergeCategories(userCategories) {
|
|
50171
|
+
const merged = userCategories ? { ...DEFAULT_CATEGORIES, ...userCategories } : { ...DEFAULT_CATEGORIES };
|
|
50172
|
+
return Object.fromEntries(Object.entries(merged).filter(([, config3]) => !config3.disable));
|
|
50173
|
+
}
|
|
50174
|
+
|
|
50175
|
+
// src/tools/delegate-task/tools.ts
|
|
50030
50176
|
init_logger();
|
|
50031
50177
|
|
|
50032
50178
|
// src/tools/delegate-task/prompt-builder.ts
|
|
@@ -50176,7 +50322,8 @@ Use \`background_output\` with task_id="${task.id}" to check progress.
|
|
|
50176
50322
|
|
|
50177
50323
|
<task_metadata>
|
|
50178
50324
|
session_id: ${task.sessionID}
|
|
50179
|
-
|
|
50325
|
+
${task.agent ? `subagent: ${task.agent}
|
|
50326
|
+
` : ""}</task_metadata>`;
|
|
50180
50327
|
} catch (error45) {
|
|
50181
50328
|
return formatDetailedError(error45, {
|
|
50182
50329
|
operation: "Continue background task",
|
|
@@ -50629,7 +50776,8 @@ ${result.textContent || "(No text output)"}
|
|
|
50629
50776
|
|
|
50630
50777
|
<task_metadata>
|
|
50631
50778
|
session_id: ${args.session_id}
|
|
50632
|
-
|
|
50779
|
+
${resumeAgent ? `subagent: ${resumeAgent}
|
|
50780
|
+
` : ""}</task_metadata>`;
|
|
50633
50781
|
} finally {
|
|
50634
50782
|
if (toastManager) {
|
|
50635
50783
|
toastManager.removeTask(taskId);
|
|
@@ -50848,10 +50996,7 @@ async function createSyncSession(client2, input) {
|
|
|
50848
50996
|
const createResult = await client2.session.create({
|
|
50849
50997
|
body: {
|
|
50850
50998
|
parentID: input.parentSessionID,
|
|
50851
|
-
title: `${input.description} (@${input.agentToUse} subagent)
|
|
50852
|
-
permission: [
|
|
50853
|
-
{ permission: "question", action: "deny", pattern: "*" }
|
|
50854
|
-
]
|
|
50999
|
+
title: `${input.description} (@${input.agentToUse} subagent)`
|
|
50855
51000
|
},
|
|
50856
51001
|
query: {
|
|
50857
51002
|
directory: parentDirectory
|
|
@@ -51035,9 +51180,6 @@ session_id: ${sessionID}
|
|
|
51035
51180
|
}
|
|
51036
51181
|
}
|
|
51037
51182
|
}
|
|
51038
|
-
// src/tools/delegate-task/category-resolver.ts
|
|
51039
|
-
init_constants();
|
|
51040
|
-
|
|
51041
51183
|
// src/tools/delegate-task/sisyphus-junior-agent.ts
|
|
51042
51184
|
var SISYPHUS_JUNIOR_AGENT2 = "sisyphus-junior";
|
|
51043
51185
|
|
|
@@ -51049,6 +51191,9 @@ function resolveCategoryConfig(categoryName, options) {
|
|
|
51049
51191
|
const defaultConfig = DEFAULT_CATEGORIES[categoryName];
|
|
51050
51192
|
const userConfig = userCategories?.[categoryName];
|
|
51051
51193
|
const hasExplicitUserConfig = userConfig !== undefined;
|
|
51194
|
+
if (userConfig?.disable) {
|
|
51195
|
+
return null;
|
|
51196
|
+
}
|
|
51052
51197
|
const categoryReq = CATEGORY_MODEL_REQUIREMENTS[categoryName];
|
|
51053
51198
|
if (categoryReq?.requiresModel && availableModels && !hasExplicitUserConfig) {
|
|
51054
51199
|
if (!isModelAvailable(categoryReq.requiresModel, availableModels)) {
|
|
@@ -51198,7 +51343,8 @@ async function resolveCategoryExecution(args, executorCtx, inheritedModel, syste
|
|
|
51198
51343
|
const { client: client2, userCategories, sisyphusJuniorModel } = executorCtx;
|
|
51199
51344
|
const availableModels = await getAvailableModelsForDelegateTask(client2);
|
|
51200
51345
|
const categoryName = args.category;
|
|
51201
|
-
const
|
|
51346
|
+
const enabledCategories = mergeCategories(userCategories);
|
|
51347
|
+
const categoryExists = enabledCategories[categoryName] !== undefined;
|
|
51202
51348
|
const resolved = resolveCategoryConfig(categoryName, {
|
|
51203
51349
|
userCategories,
|
|
51204
51350
|
inheritedModel,
|
|
@@ -51207,7 +51353,7 @@ async function resolveCategoryExecution(args, executorCtx, inheritedModel, syste
|
|
|
51207
51353
|
});
|
|
51208
51354
|
if (!resolved) {
|
|
51209
51355
|
const requirement2 = CATEGORY_MODEL_REQUIREMENTS[categoryName];
|
|
51210
|
-
const allCategoryNames = Object.keys(
|
|
51356
|
+
const allCategoryNames = Object.keys(enabledCategories).join(", ");
|
|
51211
51357
|
if (categoryExists && requirement2?.requiresModel) {
|
|
51212
51358
|
return {
|
|
51213
51359
|
agentToUse: "",
|
|
@@ -51282,7 +51428,7 @@ Available categories: ${allCategoryNames}`
|
|
|
51282
51428
|
}
|
|
51283
51429
|
const categoryPromptAppend = resolved.promptAppend || undefined;
|
|
51284
51430
|
if (!categoryModel && !actualModel) {
|
|
51285
|
-
const categoryNames = Object.keys(
|
|
51431
|
+
const categoryNames = Object.keys(enabledCategories);
|
|
51286
51432
|
return {
|
|
51287
51433
|
agentToUse: "",
|
|
51288
51434
|
categoryModel: undefined,
|
|
@@ -51392,7 +51538,7 @@ Create the work plan directly - that's your job as the planning agent.`
|
|
|
51392
51538
|
// src/tools/delegate-task/tools.ts
|
|
51393
51539
|
function createDelegateTask(options) {
|
|
51394
51540
|
const { userCategories } = options;
|
|
51395
|
-
const allCategories =
|
|
51541
|
+
const allCategories = mergeCategories(userCategories);
|
|
51396
51542
|
const categoryNames = Object.keys(allCategories);
|
|
51397
51543
|
const categoryExamples = categoryNames.map((k) => `'${k}'`).join(", ");
|
|
51398
51544
|
const availableCategories = options.availableCategories ?? Object.entries(allCategories).map(([name, categoryConfig]) => {
|
|
@@ -52729,7 +52875,7 @@ class BackgroundManager {
|
|
|
52729
52875
|
while (queue && queue.length > 0) {
|
|
52730
52876
|
const item = queue[0];
|
|
52731
52877
|
await this.concurrencyManager.acquire(key);
|
|
52732
|
-
if (item.task.status === "cancelled") {
|
|
52878
|
+
if (item.task.status === "cancelled" || item.task.status === "error") {
|
|
52733
52879
|
this.concurrencyManager.release(key);
|
|
52734
52880
|
queue.shift();
|
|
52735
52881
|
continue;
|
|
@@ -52764,14 +52910,10 @@ class BackgroundManager {
|
|
|
52764
52910
|
});
|
|
52765
52911
|
const parentDirectory = parentSession?.data?.directory ?? this.directory;
|
|
52766
52912
|
log(`[background-agent] Parent dir: ${parentSession?.data?.directory}, using: ${parentDirectory}`);
|
|
52767
|
-
const inheritedPermission = parentSession?.data?.permission;
|
|
52768
|
-
const permissionRules = Array.isArray(inheritedPermission) ? inheritedPermission.filter((r) => r?.permission !== "question") : [];
|
|
52769
|
-
permissionRules.push({ permission: "question", action: "deny", pattern: "*" });
|
|
52770
52913
|
const createResult = await this.client.session.create({
|
|
52771
52914
|
body: {
|
|
52772
52915
|
parentID: input.parentSessionID,
|
|
52773
|
-
title: `${input.description} (@${input.agent} subagent)
|
|
52774
|
-
permission: permissionRules
|
|
52916
|
+
title: `${input.description} (@${input.agent} subagent)`
|
|
52775
52917
|
},
|
|
52776
52918
|
query: {
|
|
52777
52919
|
directory: parentDirectory
|
|
@@ -53157,6 +53299,38 @@ class BackgroundManager {
|
|
|
53157
53299
|
log("[background-agent] Error in session.idle handler:", err);
|
|
53158
53300
|
});
|
|
53159
53301
|
}
|
|
53302
|
+
if (event.type === "session.error") {
|
|
53303
|
+
const sessionID = typeof props?.sessionID === "string" ? props.sessionID : undefined;
|
|
53304
|
+
if (!sessionID)
|
|
53305
|
+
return;
|
|
53306
|
+
const task = this.findBySession(sessionID);
|
|
53307
|
+
if (!task || task.status !== "running")
|
|
53308
|
+
return;
|
|
53309
|
+
const errorMessage = props ? this.getSessionErrorMessage(props) : undefined;
|
|
53310
|
+
task.status = "error";
|
|
53311
|
+
task.error = errorMessage ?? "Session error";
|
|
53312
|
+
task.completedAt = new Date;
|
|
53313
|
+
if (task.concurrencyKey) {
|
|
53314
|
+
this.concurrencyManager.release(task.concurrencyKey);
|
|
53315
|
+
task.concurrencyKey = undefined;
|
|
53316
|
+
}
|
|
53317
|
+
const completionTimer = this.completionTimers.get(task.id);
|
|
53318
|
+
if (completionTimer) {
|
|
53319
|
+
clearTimeout(completionTimer);
|
|
53320
|
+
this.completionTimers.delete(task.id);
|
|
53321
|
+
}
|
|
53322
|
+
const idleTimer = this.idleDeferralTimers.get(task.id);
|
|
53323
|
+
if (idleTimer) {
|
|
53324
|
+
clearTimeout(idleTimer);
|
|
53325
|
+
this.idleDeferralTimers.delete(task.id);
|
|
53326
|
+
}
|
|
53327
|
+
this.cleanupPendingByParent(task);
|
|
53328
|
+
this.tasks.delete(task.id);
|
|
53329
|
+
this.clearNotificationsForTask(task.id);
|
|
53330
|
+
if (task.sessionID) {
|
|
53331
|
+
subagentSessions.delete(task.sessionID);
|
|
53332
|
+
}
|
|
53333
|
+
}
|
|
53160
53334
|
if (event.type === "session.deleted") {
|
|
53161
53335
|
const info = props?.info;
|
|
53162
53336
|
if (!info || typeof info.id !== "string")
|
|
@@ -53579,6 +53753,22 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
|
|
|
53579
53753
|
}
|
|
53580
53754
|
return "";
|
|
53581
53755
|
}
|
|
53756
|
+
isRecord(value) {
|
|
53757
|
+
return typeof value === "object" && value !== null;
|
|
53758
|
+
}
|
|
53759
|
+
getSessionErrorMessage(properties) {
|
|
53760
|
+
const errorRaw = properties["error"];
|
|
53761
|
+
if (!this.isRecord(errorRaw))
|
|
53762
|
+
return;
|
|
53763
|
+
const dataRaw = errorRaw["data"];
|
|
53764
|
+
if (this.isRecord(dataRaw)) {
|
|
53765
|
+
const message2 = dataRaw["message"];
|
|
53766
|
+
if (typeof message2 === "string")
|
|
53767
|
+
return message2;
|
|
53768
|
+
}
|
|
53769
|
+
const message = errorRaw["message"];
|
|
53770
|
+
return typeof message === "string" ? message : undefined;
|
|
53771
|
+
}
|
|
53582
53772
|
hasRunningTasks() {
|
|
53583
53773
|
for (const task of this.tasks.values()) {
|
|
53584
53774
|
if (task.status === "running")
|
|
@@ -53589,6 +53779,7 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
|
|
|
53589
53779
|
pruneStaleTasksAndNotifications() {
|
|
53590
53780
|
const now = Date.now();
|
|
53591
53781
|
for (const [taskId, task] of this.tasks.entries()) {
|
|
53782
|
+
const wasPending = task.status === "pending";
|
|
53592
53783
|
const timestamp2 = task.status === "pending" ? task.queuedAt?.getTime() : task.startedAt?.getTime();
|
|
53593
53784
|
if (!timestamp2) {
|
|
53594
53785
|
continue;
|
|
@@ -53605,6 +53796,19 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
|
|
|
53605
53796
|
task.concurrencyKey = undefined;
|
|
53606
53797
|
}
|
|
53607
53798
|
this.cleanupPendingByParent(task);
|
|
53799
|
+
if (wasPending) {
|
|
53800
|
+
const key = task.model ? `${task.model.providerID}/${task.model.modelID}` : task.agent;
|
|
53801
|
+
const queue = this.queuesByKey.get(key);
|
|
53802
|
+
if (queue) {
|
|
53803
|
+
const index = queue.findIndex((item) => item.task.id === taskId);
|
|
53804
|
+
if (index !== -1) {
|
|
53805
|
+
queue.splice(index, 1);
|
|
53806
|
+
if (queue.length === 0) {
|
|
53807
|
+
this.queuesByKey.delete(key);
|
|
53808
|
+
}
|
|
53809
|
+
}
|
|
53810
|
+
}
|
|
53811
|
+
}
|
|
53608
53812
|
this.clearNotificationsForTask(taskId);
|
|
53609
53813
|
this.tasks.delete(taskId);
|
|
53610
53814
|
if (task.sessionID) {
|
|
@@ -58051,7 +58255,7 @@ async function getOrRegisterClient(options) {
|
|
|
58051
58255
|
}
|
|
58052
58256
|
}
|
|
58053
58257
|
function parseRegistrationResponse(data) {
|
|
58054
|
-
if (!
|
|
58258
|
+
if (!isRecord3(data))
|
|
58055
58259
|
return null;
|
|
58056
58260
|
const clientId = data.client_id;
|
|
58057
58261
|
if (typeof clientId !== "string" || clientId.length === 0)
|
|
@@ -58062,7 +58266,7 @@ function parseRegistrationResponse(data) {
|
|
|
58062
58266
|
}
|
|
58063
58267
|
return { clientId };
|
|
58064
58268
|
}
|
|
58065
|
-
function
|
|
58269
|
+
function isRecord3(value) {
|
|
58066
58270
|
return typeof value === "object" && value !== null;
|
|
58067
58271
|
}
|
|
58068
58272
|
|
|
@@ -62230,7 +62434,7 @@ ${rows.join(`
|
|
|
62230
62434
|
`)}`;
|
|
62231
62435
|
}
|
|
62232
62436
|
function buildCategorySection(userCategories) {
|
|
62233
|
-
const allCategories =
|
|
62437
|
+
const allCategories = mergeCategories(userCategories);
|
|
62234
62438
|
const categoryRows = Object.entries(allCategories).map(([name, config3]) => {
|
|
62235
62439
|
const temp = config3.temperature ?? 0.5;
|
|
62236
62440
|
return `| \`${name}\` | ${temp} | ${getCategoryDescription(name, userCategories)} |`;
|
|
@@ -62306,7 +62510,7 @@ task(category="[category]", load_skills=["skill-1", "skill-2"], run_in_backgroun
|
|
|
62306
62510
|
- Missing a relevant skill = suboptimal output quality`;
|
|
62307
62511
|
}
|
|
62308
62512
|
function buildDecisionMatrix(agents, userCategories) {
|
|
62309
|
-
const allCategories =
|
|
62513
|
+
const allCategories = mergeCategories(userCategories);
|
|
62310
62514
|
const categoryRows = Object.entries(allCategories).map(([name]) => `| ${getCategoryDescription(name, userCategories)} | \`category="${name}", load_skills=[...]\` |`);
|
|
62311
62515
|
const agentRows = agents.map((a) => {
|
|
62312
62516
|
const shortDesc = truncateDescription(a.description);
|
|
@@ -62324,7 +62528,6 @@ ${agentRows.join(`
|
|
|
62324
62528
|
**NEVER provide both category AND agent - they are mutually exclusive.**`;
|
|
62325
62529
|
}
|
|
62326
62530
|
// src/agents/atlas/agent.ts
|
|
62327
|
-
init_constants();
|
|
62328
62531
|
var MODE7 = "primary";
|
|
62329
62532
|
function getAtlasPromptSource(model) {
|
|
62330
62533
|
if (model && isGptModel2(model)) {
|
|
@@ -62347,7 +62550,7 @@ function buildDynamicOrchestratorPrompt(ctx) {
|
|
|
62347
62550
|
const skills = ctx?.availableSkills ?? [];
|
|
62348
62551
|
const userCategories = ctx?.userCategories;
|
|
62349
62552
|
const model = ctx?.model;
|
|
62350
|
-
const allCategories =
|
|
62553
|
+
const allCategories = mergeCategories(userCategories);
|
|
62351
62554
|
const availableCategories = Object.entries(allCategories).map(([name]) => ({
|
|
62352
62555
|
name,
|
|
62353
62556
|
description: getCategoryDescription(name, userCategories)
|
|
@@ -63223,13 +63426,12 @@ function buildAvailableSkills(discoveredSkills, browserProvider, disabledSkills)
|
|
|
63223
63426
|
}
|
|
63224
63427
|
|
|
63225
63428
|
// src/agents/agent-builder.ts
|
|
63226
|
-
init_constants();
|
|
63227
63429
|
function isFactory(source) {
|
|
63228
63430
|
return typeof source === "function";
|
|
63229
63431
|
}
|
|
63230
63432
|
function buildAgent(source, model, categories, gitMasterConfig, browserProvider, disabledSkills) {
|
|
63231
63433
|
const base = isFactory(source) ? source(model) : { ...source };
|
|
63232
|
-
const categoryConfigs = categories
|
|
63434
|
+
const categoryConfigs = mergeCategories(categories);
|
|
63233
63435
|
const agentWithCategory = base;
|
|
63234
63436
|
if (agentWithCategory.category) {
|
|
63235
63437
|
const categoryConfig = categoryConfigs[agentWithCategory.category];
|
|
@@ -63569,7 +63771,7 @@ function maybeCreateAtlasConfig(input) {
|
|
|
63569
63771
|
function sanitizeMarkdownTableCell(value) {
|
|
63570
63772
|
return value.replace(/\r?\n/g, " ").replace(/\|/g, "\\|").replace(/\s+/g, " ").trim();
|
|
63571
63773
|
}
|
|
63572
|
-
function
|
|
63774
|
+
function isRecord4(value) {
|
|
63573
63775
|
return typeof value === "object" && value !== null;
|
|
63574
63776
|
}
|
|
63575
63777
|
function parseRegisteredAgentSummaries(input) {
|
|
@@ -63577,7 +63779,7 @@ function parseRegisteredAgentSummaries(input) {
|
|
|
63577
63779
|
return [];
|
|
63578
63780
|
const result = [];
|
|
63579
63781
|
for (const item of input) {
|
|
63580
|
-
if (!
|
|
63782
|
+
if (!isRecord4(item))
|
|
63581
63783
|
continue;
|
|
63582
63784
|
const name = typeof item.name === "string" ? item.name : undefined;
|
|
63583
63785
|
if (!name)
|
|
@@ -63639,7 +63841,7 @@ async function createBuiltinAgents(disabledAgents = [], agentOverrides = {}, dir
|
|
|
63639
63841
|
});
|
|
63640
63842
|
const isFirstRunNoCache = availableModels.size === 0 && (!connectedProviders || connectedProviders.length === 0);
|
|
63641
63843
|
const result = {};
|
|
63642
|
-
const mergedCategories = categories
|
|
63844
|
+
const mergedCategories = mergeCategories(categories);
|
|
63643
63845
|
const availableCategories = Object.entries(mergedCategories).map(([name]) => ({
|
|
63644
63846
|
name,
|
|
63645
63847
|
description: categories?.[name]?.description ?? CATEGORY_DESCRIPTIONS[name] ?? "General tasks"
|
|
@@ -66682,8 +66884,8 @@ function createManagers(args) {
|
|
|
66682
66884
|
// src/plugin/available-categories.ts
|
|
66683
66885
|
init_constants();
|
|
66684
66886
|
function createAvailableCategories(pluginConfig) {
|
|
66685
|
-
const
|
|
66686
|
-
return Object.entries(
|
|
66887
|
+
const categories = mergeCategories(pluginConfig.categories);
|
|
66888
|
+
return Object.entries(categories).map(([name, categoryConfig]) => {
|
|
66687
66889
|
const model = typeof categoryConfig.model === "string" ? categoryConfig.model : undefined;
|
|
66688
66890
|
return {
|
|
66689
66891
|
name,
|
|
@@ -66865,11 +67067,11 @@ async function createTools(args) {
|
|
|
66865
67067
|
}
|
|
66866
67068
|
|
|
66867
67069
|
// src/plugin/chat-params.ts
|
|
66868
|
-
function
|
|
67070
|
+
function isRecord5(value) {
|
|
66869
67071
|
return typeof value === "object" && value !== null;
|
|
66870
67072
|
}
|
|
66871
67073
|
function buildChatParamsInput(raw) {
|
|
66872
|
-
if (!
|
|
67074
|
+
if (!isRecord5(raw))
|
|
66873
67075
|
return null;
|
|
66874
67076
|
const sessionID = raw.sessionID;
|
|
66875
67077
|
const agent = raw.agent;
|
|
@@ -66880,11 +67082,11 @@ function buildChatParamsInput(raw) {
|
|
|
66880
67082
|
return null;
|
|
66881
67083
|
if (typeof agent !== "string")
|
|
66882
67084
|
return null;
|
|
66883
|
-
if (!
|
|
67085
|
+
if (!isRecord5(model))
|
|
66884
67086
|
return null;
|
|
66885
|
-
if (!
|
|
67087
|
+
if (!isRecord5(provider))
|
|
66886
67088
|
return null;
|
|
66887
|
-
if (!
|
|
67089
|
+
if (!isRecord5(message))
|
|
66888
67090
|
return null;
|
|
66889
67091
|
const providerID = model.providerID;
|
|
66890
67092
|
const modelID = model.modelID;
|
|
@@ -66905,12 +67107,12 @@ function buildChatParamsInput(raw) {
|
|
|
66905
67107
|
};
|
|
66906
67108
|
}
|
|
66907
67109
|
function isChatParamsOutput(raw) {
|
|
66908
|
-
if (!
|
|
67110
|
+
if (!isRecord5(raw))
|
|
66909
67111
|
return false;
|
|
66910
|
-
if (!
|
|
67112
|
+
if (!isRecord5(raw.options)) {
|
|
66911
67113
|
raw.options = {};
|
|
66912
67114
|
}
|
|
66913
|
-
return
|
|
67115
|
+
return isRecord5(raw.options);
|
|
66914
67116
|
}
|
|
66915
67117
|
function createChatParamsHandler(args) {
|
|
66916
67118
|
return async (input, output) => {
|
|
@@ -67431,7 +67633,8 @@ var CategoryConfigSchema = exports_external.object({
|
|
|
67431
67633
|
textVerbosity: exports_external.enum(["low", "medium", "high"]).optional(),
|
|
67432
67634
|
tools: exports_external.record(exports_external.string(), exports_external.boolean()).optional(),
|
|
67433
67635
|
prompt_append: exports_external.string().optional(),
|
|
67434
|
-
is_unstable_agent: exports_external.boolean().optional()
|
|
67636
|
+
is_unstable_agent: exports_external.boolean().optional(),
|
|
67637
|
+
disable: exports_external.boolean().optional()
|
|
67435
67638
|
});
|
|
67436
67639
|
var BuiltinCategoryNameSchema = exports_external.enum([
|
|
67437
67640
|
"visual-engineering",
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CategoriesConfig, CategoryConfig } from "../config/schema";
|
|
2
|
+
/**
|
|
3
|
+
* Merge default and user categories, filtering out disabled ones.
|
|
4
|
+
* Single source of truth for category merging across the codebase.
|
|
5
|
+
*/
|
|
6
|
+
export declare function mergeCategories(userCategories?: CategoriesConfig): Record<string, CategoryConfig>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oh-my-opencode",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.3",
|
|
4
4
|
"description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -74,13 +74,13 @@
|
|
|
74
74
|
"typescript": "^5.7.3"
|
|
75
75
|
},
|
|
76
76
|
"optionalDependencies": {
|
|
77
|
-
"oh-my-opencode-darwin-arm64": "3.5.
|
|
78
|
-
"oh-my-opencode-darwin-x64": "3.5.
|
|
79
|
-
"oh-my-opencode-linux-arm64": "3.5.
|
|
80
|
-
"oh-my-opencode-linux-arm64-musl": "3.5.
|
|
81
|
-
"oh-my-opencode-linux-x64": "3.5.
|
|
82
|
-
"oh-my-opencode-linux-x64-musl": "3.5.
|
|
83
|
-
"oh-my-opencode-windows-x64": "3.5.
|
|
77
|
+
"oh-my-opencode-darwin-arm64": "3.5.3",
|
|
78
|
+
"oh-my-opencode-darwin-x64": "3.5.3",
|
|
79
|
+
"oh-my-opencode-linux-arm64": "3.5.3",
|
|
80
|
+
"oh-my-opencode-linux-arm64-musl": "3.5.3",
|
|
81
|
+
"oh-my-opencode-linux-x64": "3.5.3",
|
|
82
|
+
"oh-my-opencode-linux-x64-musl": "3.5.3",
|
|
83
|
+
"oh-my-opencode-windows-x64": "3.5.3"
|
|
84
84
|
},
|
|
85
85
|
"trustedDependencies": [
|
|
86
86
|
"@ast-grep/cli",
|