@prevalentware/opencode-goal-plugin 0.1.36 → 0.1.37
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/server.js +44 -15
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -1144,6 +1144,9 @@ var NON_PROGRESS_TOOLS = new Set(["get_goal", "get_goal_history"]);
|
|
|
1144
1144
|
var TASK_TERMINAL_STATES = new Set(["completed", "error", "cancelled"]);
|
|
1145
1145
|
var PLAN_MODE_CREATE_NOTICE = 'Goal recorded while the session is in Plan mode, so execution is paused. Do not start implementation work now. Ask the user to switch to Build mode and resume the goal (for example with "/goal resume") to begin execution.';
|
|
1146
1146
|
var LIMITED_GOAL_NOTICE = "Safety limit reached. Do not start or continue substantive work for this goal. Summarize useful progress, remaining work, and blockers, then wait for the user to resume or edit the goal.";
|
|
1147
|
+
var DUPLICATE_GOAL_NOTICE = "This non-closed goal already exists. Do not call create_goal or set_goal again. The existing objective and limits were preserved; repeated-call arguments were not applied. Use the returned goal state and continue only when its status permits execution.";
|
|
1148
|
+
var CONFLICTING_GOAL_NOTICE = "A different non-closed goal already exists. Do not call create_goal or set_goal again. Report the conflict instead of replacing the goal; edit, clear, complete, or mark it unmet only when explicitly requested.";
|
|
1149
|
+
var RESTRICTED_GOAL_NOTICE = "Goal execution is not allowed from the current restricted agent or while the goal is paused for Plan mode. Switch to Build mode and resume the goal before doing substantive work.";
|
|
1147
1150
|
var activeContinuations = new Set;
|
|
1148
1151
|
function restrictedAgentSet(options) {
|
|
1149
1152
|
if (options?.allow_goal_execution_from_plan === true)
|
|
@@ -1170,9 +1173,9 @@ Use the goal tools to handle this command:
|
|
|
1170
1173
|
- If the arguments start with "edit ", update the current goal objective by calling update_goal_objective with the remaining text.
|
|
1171
1174
|
- If the arguments start with "complete " or "done ", perform a completion audit against real artifacts and command output. Call update_goal with status "complete" only if the goal is achieved, using concise evidence from the audit.
|
|
1172
1175
|
- If the arguments start with "unmet ", "blocked ", or "blocker ", call update_goal with status "unmet" only when the goal cannot be achieved or needs external input, using the remaining arguments as the blocker.
|
|
1173
|
-
- Otherwise,
|
|
1176
|
+
- Otherwise, call get_goal first. If it returns a non-closed goal with the same objective, do not create it again; continue working from the returned state. If it returns a different non-closed goal, report that conflict instead of replacing it. Only when there is no non-closed goal, call create_goal once. Use the full arguments as the objective. If the user includes explicit budget instructions, pass token_budget, max_auto_turns, or max_duration_seconds to create_goal rather than leaving those words in the objective.
|
|
1174
1177
|
|
|
1175
|
-
Create a goal only from these explicit command arguments. Do not infer a goal from unrelated session context. After create_goal succeeds, continue working
|
|
1178
|
+
Create a goal only from these explicit command arguments. Do not infer a goal from unrelated session context. After create_goal succeeds or returns an existing matching goal, never call it again for this command; continue working from the returned goal state.`;
|
|
1176
1179
|
}
|
|
1177
1180
|
function commandNameFromOptions(options) {
|
|
1178
1181
|
const name = options?.command_name?.trim() || DEFAULT_COMMAND_NAME;
|
|
@@ -1773,18 +1776,44 @@ function getGoalToolResult(goal) {
|
|
|
1773
1776
|
}
|
|
1774
1777
|
async function createGoalFromTool(input, context, services) {
|
|
1775
1778
|
const planningOnly = services.isPlanAgent(context.agent);
|
|
1776
|
-
const
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1779
|
+
const objective = validateObjective(input.objective);
|
|
1780
|
+
const existing = await getGoal(context.sessionID);
|
|
1781
|
+
if (existing && !isClosedGoal(existing))
|
|
1782
|
+
return existingGoalResult(existing, objective, planningOnly);
|
|
1783
|
+
let goal;
|
|
1784
|
+
try {
|
|
1785
|
+
goal = await createGoal(context.sessionID, input.objective, {
|
|
1786
|
+
tokenBudget: input.token_budget ?? services.options.default_token_budget ?? null,
|
|
1787
|
+
maxAutoTurns: input.max_auto_turns ?? null,
|
|
1788
|
+
maxDurationSeconds: input.max_duration_seconds ?? services.options.max_goal_duration_seconds ?? null,
|
|
1789
|
+
noProgressTokenThreshold: services.options.no_progress_token_threshold ?? null,
|
|
1790
|
+
maxNoProgressTurns: services.options.max_no_progress_turns ?? null,
|
|
1791
|
+
agent: typeof context.agent === "string" ? context.agent : null,
|
|
1792
|
+
initialStatus: planningOnly ? "paused" : "active"
|
|
1793
|
+
});
|
|
1794
|
+
} catch (error) {
|
|
1795
|
+
if (!(error instanceof Error) || !error.message.includes("non-closed goal"))
|
|
1796
|
+
throw error;
|
|
1797
|
+
const raced = await getGoal(context.sessionID);
|
|
1798
|
+
if (raced && !isClosedGoal(raced))
|
|
1799
|
+
return existingGoalResult(raced, objective, planningOnly);
|
|
1800
|
+
throw error;
|
|
1801
|
+
}
|
|
1785
1802
|
await services.initializeUsage?.(context.sessionID);
|
|
1786
1803
|
return JSON.stringify(planningOnly ? { goal, plan_mode_notice: PLAN_MODE_CREATE_NOTICE } : { goal }, null, 2);
|
|
1787
1804
|
}
|
|
1805
|
+
function isClosedGoal(goal) {
|
|
1806
|
+
return goal.status === "complete" || goal.status === "unmet";
|
|
1807
|
+
}
|
|
1808
|
+
function existingGoalResult(goal, requestedObjective, planningOnly) {
|
|
1809
|
+
const reused = goal.objective === requestedObjective;
|
|
1810
|
+
return JSON.stringify({
|
|
1811
|
+
goal,
|
|
1812
|
+
...reused ? { goal_reused: true, duplicate_goal_notice: DUPLICATE_GOAL_NOTICE } : { goal_conflict: true, goal_conflict_notice: CONFLICTING_GOAL_NOTICE },
|
|
1813
|
+
...goal.status === "budgetLimited" || goal.status === "usageLimited" ? { goal_mode_notice: LIMITED_GOAL_NOTICE } : {},
|
|
1814
|
+
...planningOnly || goal.stopReason === PLAN_MODE_STOP_REASON ? { plan_mode_notice: RESTRICTED_GOAL_NOTICE } : {}
|
|
1815
|
+
}, null, 2);
|
|
1816
|
+
}
|
|
1788
1817
|
async function updateGoalObjectiveFromTool(input, context, services) {
|
|
1789
1818
|
const requested = input.status ?? "active";
|
|
1790
1819
|
const planningOnly = requested === "active" && services.isPlanAgent(context.agent);
|
|
@@ -2143,7 +2172,7 @@ var server = async ({ client }, options) => {
|
|
|
2143
2172
|
}
|
|
2144
2173
|
},
|
|
2145
2174
|
create_goal: {
|
|
2146
|
-
description: "Create a goal only when explicitly requested by the user or system/developer instructions; do not infer goals from ordinary tasks.
|
|
2175
|
+
description: "Create a goal only when explicitly requested by the user or system/developer instructions; do not infer goals from ordinary tasks. If any non-closed goal exists, this returns the existing goal as either reused or conflicting and must not be retried. While the session is in Plan mode, the goal is recorded as paused and execution requires the user to switch to Build mode.",
|
|
2147
2176
|
args: {
|
|
2148
2177
|
objective: z.string().min(1).max(4000).describe("The concrete objective to start pursuing."),
|
|
2149
2178
|
token_budget: z.number().int().positive().nullable().optional().describe("Optional positive token budget."),
|
|
@@ -2155,7 +2184,7 @@ var server = async ({ client }, options) => {
|
|
|
2155
2184
|
}
|
|
2156
2185
|
},
|
|
2157
2186
|
set_goal: {
|
|
2158
|
-
description: "Set a new goal when the user explicitly asks the agent to formulate and set its own goal. The model should write the objective itself based on the user's explicit request.
|
|
2187
|
+
description: "Set a new goal when the user explicitly asks the agent to formulate and set its own goal. The model should write the objective itself based on the user's explicit request. If any non-closed goal exists, this returns the existing goal as either reused or conflicting and must not be retried. While the session is in Plan mode, the goal is recorded as paused and execution requires the user to switch to Build mode.",
|
|
2159
2188
|
args: {
|
|
2160
2189
|
objective: z.string().min(1).max(4000).describe("The model-formulated concrete objective to start pursuing."),
|
|
2161
2190
|
token_budget: z.number().int().positive().nullable().optional().describe("Optional positive token budget."),
|
|
@@ -3019,7 +3048,7 @@ function goalToolsV2(services) {
|
|
|
3019
3048
|
},
|
|
3020
3049
|
{
|
|
3021
3050
|
name: "create_goal",
|
|
3022
|
-
description: "Create a goal only when explicitly requested by the user or system/developer instructions; do not infer goals from ordinary tasks.
|
|
3051
|
+
description: "Create a goal only when explicitly requested by the user or system/developer instructions; do not infer goals from ordinary tasks. If any non-closed goal exists, this returns the existing goal as either reused or conflicting and must not be retried. While the session is in Plan mode, the goal is recorded as paused and execution requires the user to switch to Build mode.",
|
|
3023
3052
|
input: v2ObjectSchema({
|
|
3024
3053
|
objective: { type: "string", minLength: 1, maxLength: 4000, description: "The concrete objective to start pursuing." },
|
|
3025
3054
|
token_budget: { type: ["integer", "null"], minimum: 1, description: "Optional positive token budget." },
|
|
@@ -3033,7 +3062,7 @@ function goalToolsV2(services) {
|
|
|
3033
3062
|
},
|
|
3034
3063
|
{
|
|
3035
3064
|
name: "set_goal",
|
|
3036
|
-
description: "Set a new goal when the user explicitly asks the agent to formulate and set its own goal. The model should write the objective itself based on the user's explicit request.
|
|
3065
|
+
description: "Set a new goal when the user explicitly asks the agent to formulate and set its own goal. The model should write the objective itself based on the user's explicit request. If any non-closed goal exists, this returns the existing goal as either reused or conflicting and must not be retried. While the session is in Plan mode, the goal is recorded as paused and execution requires the user to switch to Build mode.",
|
|
3037
3066
|
input: v2ObjectSchema({
|
|
3038
3067
|
objective: {
|
|
3039
3068
|
type: "string",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prevalentware/opencode-goal-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.37",
|
|
4
4
|
"description": "OpenCode goal plugin that adds Codex-style long-running goal mode, /goal commands, persistence, and TUI status for AI coding agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"opencode",
|