@brainervirus/workit-opencode 1.3.0 → 1.3.1
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/plugin.js +157 -98
- package/package.json +2 -2
package/dist/plugin.js
CHANGED
|
@@ -8318,7 +8318,47 @@ function operationJsonSchema(family) {
|
|
|
8318
8318
|
return toJSONSchema(operationSchemas[family], { target: "draft-2020-12" });
|
|
8319
8319
|
}
|
|
8320
8320
|
var OPERATION_SCHEMA_DEPTH = 1;
|
|
8321
|
-
var
|
|
8321
|
+
var schemaShapeDescription = (value, depth = 0) => {
|
|
8322
|
+
if (!value || typeof value !== "object")
|
|
8323
|
+
return "value";
|
|
8324
|
+
const schema = value;
|
|
8325
|
+
if (Array.isArray(schema.oneOf) || Array.isArray(schema.anyOf)) {
|
|
8326
|
+
const options = Array.isArray(schema.oneOf) ? schema.oneOf : schema.anyOf;
|
|
8327
|
+
return `(${options.map((option) => schemaShapeDescription(option, depth)).join("|")})`;
|
|
8328
|
+
}
|
|
8329
|
+
if (schema.const !== undefined)
|
|
8330
|
+
return `=${JSON.stringify(schema.const)}`;
|
|
8331
|
+
if (Array.isArray(schema.enum))
|
|
8332
|
+
return `[${schema.enum.map(String).join("|")}]`;
|
|
8333
|
+
const type = Array.isArray(schema.type) ? schema.type.join("/") : schema.type;
|
|
8334
|
+
if (type === "array")
|
|
8335
|
+
return `arr<${schemaShapeDescription(schema.items, depth)}>`;
|
|
8336
|
+
if (type === "object" && schema.properties && typeof schema.properties === "object") {
|
|
8337
|
+
if (depth >= 2)
|
|
8338
|
+
return "obj";
|
|
8339
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
8340
|
+
const properties = schema.properties;
|
|
8341
|
+
const fields = Object.entries(properties).map(([name, child]) => `${name}${required.has(name) ? "!" : ""}:${schemaShapeDescription(child, depth + 1)}`);
|
|
8342
|
+
return `obj{${fields.join(",")}}`;
|
|
8343
|
+
}
|
|
8344
|
+
if (typeof type !== "string")
|
|
8345
|
+
return "?";
|
|
8346
|
+
return type.split("/").map((part) => ({ string: "str", boolean: "bool", number: "num", null: "null" })[part] ?? part).join("|");
|
|
8347
|
+
};
|
|
8348
|
+
var canonicalFieldsDescription = (value) => {
|
|
8349
|
+
if (Array.isArray(value))
|
|
8350
|
+
return `Canonical object fields: ${value.join(", ")}. Workit validates the complete nested value.`;
|
|
8351
|
+
const isZodType = (schema) => ("_zod" in schema) && typeof schema._zod === "object";
|
|
8352
|
+
const schema = isZodType(value) ? toJSONSchema(value, { target: "draft-2020-12" }) : value;
|
|
8353
|
+
if (!schema.properties || typeof schema.properties !== "object") {
|
|
8354
|
+
const variants = Array.isArray(schema.oneOf) ? schema.oneOf : Array.isArray(schema.anyOf) ? schema.anyOf : null;
|
|
8355
|
+
return variants ? `Canonical shapes: ${variants.map((variant) => schemaShapeDescription(variant)).join(" | ")}. Full nested value is validated.` : "Canonical nested value; Workit validates the complete value.";
|
|
8356
|
+
}
|
|
8357
|
+
const properties = schema.properties;
|
|
8358
|
+
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
|
|
8359
|
+
const fields = Object.entries(properties).map(([name, child]) => `${name}${required.has(name) ? "!" : ""}:${schemaShapeDescription(child)}`);
|
|
8360
|
+
return `Fields (! required): ${fields.join(", ")}. Full nested value is validated.`;
|
|
8361
|
+
};
|
|
8322
8362
|
function boundedOperationJsonSchema(family, maxDepth = OPERATION_SCHEMA_DEPTH, stringifiedObjects = false) {
|
|
8323
8363
|
const tolerate = (projected) => {
|
|
8324
8364
|
if (!stringifiedObjects)
|
|
@@ -8342,9 +8382,10 @@ function boundedOperationJsonSchema(family, maxDepth = OPERATION_SCHEMA_DEPTH, s
|
|
|
8342
8382
|
return node;
|
|
8343
8383
|
const record = node;
|
|
8344
8384
|
if (record.properties && typeof record.properties === "object") {
|
|
8345
|
-
const
|
|
8385
|
+
const properties = record.properties;
|
|
8386
|
+
const fields = Object.keys(properties);
|
|
8346
8387
|
if (currentDepth >= maxDepth || fields.length === 0) {
|
|
8347
|
-
const description = stringifiedObjects ? `${canonicalFieldsDescription(
|
|
8388
|
+
const description = stringifiedObjects ? `${canonicalFieldsDescription(record)} A JSON-encoded string is also accepted.` : canonicalFieldsDescription(record);
|
|
8348
8389
|
return tolerate({ type: "object", description });
|
|
8349
8390
|
}
|
|
8350
8391
|
return tolerate({
|
|
@@ -10650,6 +10691,28 @@ var canonicalGlob = (glob) => {
|
|
|
10650
10691
|
const real = realpathOf(prefix.replace(/\/+$/, "") || "/");
|
|
10651
10692
|
return real + (prefix.endsWith("/") ? "/" : "") + rest;
|
|
10652
10693
|
};
|
|
10694
|
+
var globSpecificity = (glob) => glob.replaceAll("\\", "/").split("/").filter((segment) => segment.length > 0 && !/[*?[\]{]/.test(segment)).length;
|
|
10695
|
+
var selectWorkspaceMatch = (matches, cwd, workspaceName) => {
|
|
10696
|
+
if (workspaceName !== undefined) {
|
|
10697
|
+
const named = matches.filter((entry) => entry.name === workspaceName);
|
|
10698
|
+
if (named.length === 1)
|
|
10699
|
+
return named[0];
|
|
10700
|
+
if (named.length > 1)
|
|
10701
|
+
throw new Error(`ambiguous workspace ${JSON.stringify(workspaceName)} for ${cwd}`);
|
|
10702
|
+
if (matches.length > 0) {
|
|
10703
|
+
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
10704
|
+
}
|
|
10705
|
+
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
10706
|
+
}
|
|
10707
|
+
if (matches.length < 2)
|
|
10708
|
+
return matches[0];
|
|
10709
|
+
const highestSpecificity = Math.max(...matches.map((entry) => globSpecificity(entry.glob)));
|
|
10710
|
+
const mostSpecific = matches.filter((entry) => globSpecificity(entry.glob) === highestSpecificity);
|
|
10711
|
+
if (mostSpecific.length > 1) {
|
|
10712
|
+
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${mostSpecific.map((entry) => entry.name).join(", ")}`);
|
|
10713
|
+
}
|
|
10714
|
+
return mostSpecific[0];
|
|
10715
|
+
};
|
|
10653
10716
|
var resolveWorkspaceFrom = (cwd, dir, workspaceName) => {
|
|
10654
10717
|
const result = readWorkspacesResult(dir);
|
|
10655
10718
|
if (result.status === "malformed" || result.status === "invalid")
|
|
@@ -10669,20 +10732,7 @@ var resolveWorkspaceFrom = (cwd, dir, workspaceName) => {
|
|
|
10669
10732
|
if (matched)
|
|
10670
10733
|
matches.push(ws);
|
|
10671
10734
|
}
|
|
10672
|
-
|
|
10673
|
-
const selected = matches.find((ws) => ws.name === workspaceName);
|
|
10674
|
-
if (!selected && matches.length > 0) {
|
|
10675
|
-
const matchingNames = matches.map((ws) => ws.name);
|
|
10676
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matchingNames.join(", ")}`);
|
|
10677
|
-
}
|
|
10678
|
-
if (selected)
|
|
10679
|
-
return selected;
|
|
10680
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
10681
|
-
}
|
|
10682
|
-
if (matches.length > 1) {
|
|
10683
|
-
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${matches.map((ws) => ws.name).join(", ")}`);
|
|
10684
|
-
}
|
|
10685
|
-
return matches[0] ?? null;
|
|
10735
|
+
return selectWorkspaceMatch(matches, cwd, workspaceName) ?? null;
|
|
10686
10736
|
};
|
|
10687
10737
|
var runtimeWorkspacePolicySchema = (kind) => {
|
|
10688
10738
|
const key = kind === "branch" ? "branchPolicy" : kind === "commit" ? "commitPolicy" : "vcs";
|
|
@@ -10739,21 +10789,7 @@ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
|
10739
10789
|
return targets.some((target) => matchWorkspace(glob, target) || canonical !== glob && matchWorkspace(canonical, target));
|
|
10740
10790
|
});
|
|
10741
10791
|
const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
|
|
10742
|
-
|
|
10743
|
-
if (workspaceName) {
|
|
10744
|
-
const named = matches.filter((entry) => entry.name === workspaceName);
|
|
10745
|
-
if (named.length === 1)
|
|
10746
|
-
selected = named[0];
|
|
10747
|
-
else if (named.length > 1)
|
|
10748
|
-
throw new Error(`ambiguous workspace ${JSON.stringify(workspaceName)} for ${cwd}`);
|
|
10749
|
-
else if (matches.length)
|
|
10750
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}; matching choices: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
10751
|
-
else
|
|
10752
|
-
throw new Error(`workspace ${JSON.stringify(workspaceName)} does not match ${cwd}`);
|
|
10753
|
-
} else if (matches.length > 1)
|
|
10754
|
-
throw new Error(`ambiguous workspace for ${cwd}; choose one of: ${matches.map((entry) => entry.name).join(", ")}`);
|
|
10755
|
-
else
|
|
10756
|
-
selected = matches[0];
|
|
10792
|
+
const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
|
|
10757
10793
|
if (!selected)
|
|
10758
10794
|
return null;
|
|
10759
10795
|
const policy = runtimeWorkspacePolicySchema(kind).safeParse(selected);
|
|
@@ -12941,6 +12977,15 @@ need zero Workit task, assessment, or writer calls. Use one compact tracked
|
|
|
12941
12977
|
record only when handoff, dependent steps, concurrent actors, or meaningful
|
|
12942
12978
|
decisions make continuity useful; similar titles alone never merge tasks.
|
|
12943
12979
|
|
|
12980
|
+
For a routine user-authorized branch or commit, prefer native host Git/shell
|
|
12981
|
+
tools from the outset when managed coordination or outcome reconciliation is
|
|
12982
|
+
not needed. Inspect the actual target checkout and its configured conventions;
|
|
12983
|
+
use Workit's read-only context/policy tools when needed. Do not start a task,
|
|
12984
|
+
acquire a writer, or mint a decision receipt solely for a native Git action.
|
|
12985
|
+
Native permissions still apply. Never switch execution paths to evade a denial
|
|
12986
|
+
or repeat an uncertain managed effect. A local-commit endpoint does not imply
|
|
12987
|
+
PR readiness, a fresh review, or post-commit assessment/closure paperwork.
|
|
12988
|
+
|
|
12944
12989
|
For tracked work, inspect its current state and use the shared operations for
|
|
12945
12990
|
task, policy, evidence, finding, decision, worker, writer, and state changes.
|
|
12946
12991
|
Start a record once for an explicit tracked objective; assess or reassess only
|
|
@@ -13222,6 +13267,10 @@ var externalActionSchema = discriminatedUnion("operation", [
|
|
|
13222
13267
|
}).strict()
|
|
13223
13268
|
}).strict()
|
|
13224
13269
|
]);
|
|
13270
|
+
var externalActionJsonSchema = () => ({
|
|
13271
|
+
type: "object",
|
|
13272
|
+
...toJSONSchema(externalActionSchema, { target: "draft-2020-12" })
|
|
13273
|
+
});
|
|
13225
13274
|
var externalActionRequest = (value) => {
|
|
13226
13275
|
const parsed = externalActionSchema.safeParse(value);
|
|
13227
13276
|
return parsed.success ? success(null, null, parsed.data) : failure("invalid_input", "external action payload is invalid", {
|
|
@@ -13977,6 +14026,7 @@ function resolveRequirements(input) {
|
|
|
13977
14026
|
dependentAction: null,
|
|
13978
14027
|
acceptanceAllowed: false
|
|
13979
14028
|
}));
|
|
14029
|
+
const independentBehaviorReview = input.preferences?.thorough === true || input.assessment.consequences.some((consequence) => ["security", "data", "public_contract", "operations"].includes(consequence.area));
|
|
13980
14030
|
if (signals.behaviorChange.value === true)
|
|
13981
14031
|
requirements.push(requirement({
|
|
13982
14032
|
ruleId: "behavioral-verification",
|
|
@@ -13988,14 +14038,14 @@ function resolveRequirements(input) {
|
|
|
13988
14038
|
dependentAction: null,
|
|
13989
14039
|
acceptanceAllowed: false
|
|
13990
14040
|
}), requirement({
|
|
13991
|
-
ruleId: "fresh-context-review",
|
|
14041
|
+
ruleId: independentBehaviorReview ? "fresh-context-review" : "self-review",
|
|
13992
14042
|
dimension: "review",
|
|
13993
14043
|
scope,
|
|
13994
|
-
reason: "
|
|
13995
|
-
satisfaction: "A separate review context examines the current candidate and records its result.",
|
|
14044
|
+
reason: independentBehaviorReview ? "Consequential behavior or the thorough preference requires fresh-context review." : "Bounded behavior changes use self-review unless consequential risks or trusted rules require more.",
|
|
14045
|
+
satisfaction: independentBehaviorReview ? "A separate review context examines the current candidate and records its result." : "The lead reviews the resulting diff and records the relevant scope and checks.",
|
|
13996
14046
|
before: "close",
|
|
13997
14047
|
dependentAction: null,
|
|
13998
|
-
acceptanceAllowed:
|
|
14048
|
+
acceptanceAllowed: !independentBehaviorReview
|
|
13999
14049
|
}));
|
|
14000
14050
|
else if (signals.mechanicalLowRisk.value === true)
|
|
14001
14051
|
requirements.push(requirement({
|
|
@@ -34040,14 +34090,33 @@ class NativeReceiptStore {
|
|
|
34040
34090
|
#observations = new WeakSet;
|
|
34041
34091
|
#reservations = new WeakMap;
|
|
34042
34092
|
#pending = new Map;
|
|
34093
|
+
#callSequences = new Map;
|
|
34094
|
+
#seenCalls = new Set;
|
|
34043
34095
|
#now;
|
|
34096
|
+
#sequence = 0;
|
|
34044
34097
|
constructor(options = {}) {
|
|
34045
34098
|
this.#now = options.now ?? Date.now;
|
|
34046
34099
|
}
|
|
34100
|
+
get sequence() {
|
|
34101
|
+
return this.#sequence;
|
|
34102
|
+
}
|
|
34103
|
+
callKey(sessionID, callID) {
|
|
34104
|
+
return `${sessionID.length}:${sessionID}${callID}`;
|
|
34105
|
+
}
|
|
34106
|
+
rememberSequence(key, sequence) {
|
|
34107
|
+
if (!this.#callSequences.has(key))
|
|
34108
|
+
this.#callSequences.set(key, sequence);
|
|
34109
|
+
}
|
|
34047
34110
|
recordRequest(requestID, sessionID, callID, questions) {
|
|
34048
34111
|
if (typeof requestID !== "string" || !requestID)
|
|
34049
34112
|
return;
|
|
34050
|
-
this
|
|
34113
|
+
const key = this.callKey(sessionID, callID);
|
|
34114
|
+
let sequence = this.#callSequences.get(key);
|
|
34115
|
+
if (sequence === undefined) {
|
|
34116
|
+
sequence = ++this.#sequence;
|
|
34117
|
+
this.rememberSequence(key, sequence);
|
|
34118
|
+
}
|
|
34119
|
+
this.#pending.set(requestID, { sessionID, callID, questions, sequence });
|
|
34051
34120
|
if (this.#pending.size > 16) {
|
|
34052
34121
|
const oldest = this.#pending.keys().next();
|
|
34053
34122
|
if (!oldest.done)
|
|
@@ -34064,9 +34133,9 @@ class NativeReceiptStore {
|
|
|
34064
34133
|
return false;
|
|
34065
34134
|
if (!Array.isArray(answers) || answers.length !== 1)
|
|
34066
34135
|
return false;
|
|
34067
|
-
return this.mint(pending.sessionID, pending.callID, pending.questions, answers);
|
|
34136
|
+
return this.mint(pending.sessionID, pending.callID, pending.questions, answers, pending.sequence);
|
|
34068
34137
|
}
|
|
34069
|
-
mint(sessionID, callID, questions, answers) {
|
|
34138
|
+
mint(sessionID, callID, questions, answers, sequence) {
|
|
34070
34139
|
const answer = Array.isArray(answers) && answers.length === 1 && Array.isArray(answers[0]) && answers[0].length === 1 && typeof answers[0][0] === "string" ? answers[0][0] : undefined;
|
|
34071
34140
|
if (typeof answer !== "string" || !answer.trim())
|
|
34072
34141
|
return false;
|
|
@@ -34087,6 +34156,12 @@ class NativeReceiptStore {
|
|
|
34087
34156
|
const decisionPurpose = typeof question.header === "string" ? question.header.match(/^Workit decision: (design|action|limitation|preference)$/)?.[1] : undefined;
|
|
34088
34157
|
if (!decisionPurpose)
|
|
34089
34158
|
return false;
|
|
34159
|
+
const key = this.callKey(sessionID, callID);
|
|
34160
|
+
if (this.#seenCalls.has(key))
|
|
34161
|
+
return true;
|
|
34162
|
+
const receiptSequence = sequence ?? this.#callSequences.get(key) ?? ++this.#sequence;
|
|
34163
|
+
this.rememberSequence(key, receiptSequence);
|
|
34164
|
+
this.#seenCalls.add(key);
|
|
34090
34165
|
const content = decisionContent(decisionPurpose, typeof question.question === "string" ? question.question : "", options[0].description);
|
|
34091
34166
|
const receipt = {
|
|
34092
34167
|
sessionID,
|
|
@@ -34097,7 +34172,8 @@ class NativeReceiptStore {
|
|
|
34097
34172
|
question: content.question,
|
|
34098
34173
|
purpose,
|
|
34099
34174
|
contentDigest: sha256(canonicalJson(content)),
|
|
34100
|
-
recordedAt: this.#now()
|
|
34175
|
+
recordedAt: this.#now(),
|
|
34176
|
+
sequence: receiptSequence
|
|
34101
34177
|
};
|
|
34102
34178
|
const queue = this.#receipts.get(sessionID) ?? [];
|
|
34103
34179
|
queue.push(receipt);
|
|
@@ -34201,7 +34277,7 @@ var boundedSchema = (schema, depth, field) => {
|
|
|
34201
34277
|
key,
|
|
34202
34278
|
depth >= MAX_OPERATION_OBJECT_DEPTH ? shallowSchema(child, `${field}.${key}`) : boundedSchema(child, depth + 1, `${field}.${key}`)
|
|
34203
34279
|
]));
|
|
34204
|
-
const description = depth >= MAX_OPERATION_OBJECT_DEPTH ? canonicalFieldsDescription(
|
|
34280
|
+
const description = depth >= MAX_OPERATION_OBJECT_DEPTH ? canonicalFieldsDescription(schema) : undefined;
|
|
34205
34281
|
const object = tool.schema.object(shape).strict();
|
|
34206
34282
|
return description ? object.describe(description) : object;
|
|
34207
34283
|
}
|
|
@@ -34493,27 +34569,39 @@ var createWorkitTools = ({
|
|
|
34493
34569
|
if (decision.purpose === "action" && decision.response === "approved") {
|
|
34494
34570
|
const queue = actionProposals.get(context.sessionID) ?? [];
|
|
34495
34571
|
const textMatches = queue.filter((pending) => pending.presented === decision.binding.presented && pending.approvedText === decision.binding.approvedContent);
|
|
34496
|
-
if (textMatches.length > 1 && new Set(textMatches.map((pending) => pending.descriptor)).size > 1)
|
|
34497
|
-
return output2(failure("invalid_input", "multiple action proposals match this approval; resolve the action again"));
|
|
34498
34572
|
let bound = false;
|
|
34499
|
-
const
|
|
34500
|
-
|
|
34573
|
+
const valid = [];
|
|
34574
|
+
const stale = new Set;
|
|
34575
|
+
let unresolved = false;
|
|
34576
|
+
for (const pending of textMatches) {
|
|
34501
34577
|
const fresh = resolveExternalActionRequest(context.directory, pending.request);
|
|
34502
34578
|
const freshDescriptor = fresh.ok ? externalActionDescriptor(pending.request.operation, fresh.data.descriptorPayload) : null;
|
|
34503
34579
|
if (freshDescriptor === pending.descriptor) {
|
|
34504
|
-
|
|
34505
|
-
|
|
34506
|
-
|
|
34507
|
-
binding: {
|
|
34508
|
-
...recordInput.binding,
|
|
34509
|
-
approvedContent: pending.descriptor,
|
|
34510
|
-
displayed: pending.approvedText
|
|
34511
|
-
}
|
|
34512
|
-
};
|
|
34513
|
-
bound = true;
|
|
34580
|
+
valid.push(pending);
|
|
34581
|
+
if (observed.receipt.sequence <= pending.receiptSequence)
|
|
34582
|
+
unresolved = true;
|
|
34514
34583
|
} else if (fresh.ok) {
|
|
34515
|
-
|
|
34516
|
-
}
|
|
34584
|
+
stale.add(pending);
|
|
34585
|
+
} else
|
|
34586
|
+
unresolved = true;
|
|
34587
|
+
}
|
|
34588
|
+
if (stale.size)
|
|
34589
|
+
actionProposals.set(context.sessionID, queue.filter((candidate) => !stale.has(candidate)));
|
|
34590
|
+
const validDescriptors = new Set(valid.map((pending) => pending.descriptor));
|
|
34591
|
+
if (unresolved || validDescriptors.size > 1)
|
|
34592
|
+
return output2(failure("invalid_input", "matching action proposals are ambiguous or this receipt predates a matching proposal; resolve and ask again"));
|
|
34593
|
+
if (validDescriptors.size === 1) {
|
|
34594
|
+
const pending = valid[0];
|
|
34595
|
+
proposalToCommit = pending;
|
|
34596
|
+
recordInput = {
|
|
34597
|
+
...recordInput,
|
|
34598
|
+
binding: {
|
|
34599
|
+
...recordInput.binding,
|
|
34600
|
+
approvedContent: pending.descriptor,
|
|
34601
|
+
displayed: pending.approvedText
|
|
34602
|
+
}
|
|
34603
|
+
};
|
|
34604
|
+
bound = true;
|
|
34517
34605
|
}
|
|
34518
34606
|
if (!bound && !isSelfAuthorizingActionContent(decision.binding.approvedContent)) {
|
|
34519
34607
|
return output2(failure("invalid_input", textMatches.length > 0 ? "repository state changed since the proposal; resolve the action again for a fresh proposal" : "no matching action proposal; resolve the action through the action tool first"));
|
|
@@ -34540,20 +34628,8 @@ var createWorkitTools = ({
|
|
|
34540
34628
|
workit_external_action: tool({
|
|
34541
34629
|
description: `Run one fixed optional action. ${externalActionHelp}`,
|
|
34542
34630
|
args: {
|
|
34543
|
-
operation: tool.schema.enum(
|
|
34544
|
-
|
|
34545
|
-
"git.commit",
|
|
34546
|
-
"git.push",
|
|
34547
|
-
"hosting.pull_request",
|
|
34548
|
-
"hosting.merge",
|
|
34549
|
-
"hosting.delete_branch",
|
|
34550
|
-
"youtrack.update",
|
|
34551
|
-
"youtrack.time",
|
|
34552
|
-
"youtrack.meeting",
|
|
34553
|
-
"changelog.apply",
|
|
34554
|
-
"context.read"
|
|
34555
|
-
]),
|
|
34556
|
-
payload: tool.schema.record(tool.schema.string(), tool.schema.any())
|
|
34631
|
+
operation: tool.schema.enum(externalActionSchema.options.map((variant) => variant.shape.operation.value)),
|
|
34632
|
+
payload: tool.schema.union(externalActionSchema.options.map((variant) => variant.shape.payload)).describe("Use the payload variant for the selected operation; Workit validates their exact pairing.")
|
|
34557
34633
|
},
|
|
34558
34634
|
execute: async (args, context) => {
|
|
34559
34635
|
const parsed = externalActionRequest(args);
|
|
@@ -34687,7 +34763,8 @@ var createWorkitTools = ({
|
|
|
34687
34763
|
descriptor,
|
|
34688
34764
|
presented: proposal.presented,
|
|
34689
34765
|
approvedText: proposal.approvedText,
|
|
34690
|
-
request: resolved.data.request
|
|
34766
|
+
request: resolved.data.request,
|
|
34767
|
+
receiptSequence: receipts.sequence
|
|
34691
34768
|
};
|
|
34692
34769
|
if (!existing) {
|
|
34693
34770
|
pending.push(open);
|
|
@@ -35259,19 +35336,6 @@ var objectSchema = (properties, required) => ({
|
|
|
35259
35336
|
required,
|
|
35260
35337
|
additionalProperties: false
|
|
35261
35338
|
});
|
|
35262
|
-
var WORKIT_EXTERNAL_ACTION_OPERATIONS = [
|
|
35263
|
-
"git.branch_setup",
|
|
35264
|
-
"git.commit",
|
|
35265
|
-
"git.push",
|
|
35266
|
-
"hosting.pull_request",
|
|
35267
|
-
"hosting.merge",
|
|
35268
|
-
"hosting.delete_branch",
|
|
35269
|
-
"youtrack.update",
|
|
35270
|
-
"youtrack.time",
|
|
35271
|
-
"youtrack.meeting",
|
|
35272
|
-
"changelog.apply",
|
|
35273
|
-
"context.read"
|
|
35274
|
-
];
|
|
35275
35339
|
var familyTools = OPERATION_FAMILIES.map((family) => ({
|
|
35276
35340
|
name: `workit_${family}`,
|
|
35277
35341
|
description: `Workit ${family} operations backed by the shared task contract.`,
|
|
@@ -35281,19 +35345,8 @@ var WORKIT_TOOL_CATALOG = [
|
|
|
35281
35345
|
...familyTools,
|
|
35282
35346
|
{
|
|
35283
35347
|
name: "workit_external_action",
|
|
35284
|
-
description:
|
|
35285
|
-
input:
|
|
35286
|
-
operation: {
|
|
35287
|
-
type: "string",
|
|
35288
|
-
enum: [...WORKIT_EXTERNAL_ACTION_OPERATIONS],
|
|
35289
|
-
description: "Fixed optional action to run."
|
|
35290
|
-
},
|
|
35291
|
-
payload: {
|
|
35292
|
-
type: "object",
|
|
35293
|
-
description: "Operation-specific payload; Workit validates it.",
|
|
35294
|
-
additionalProperties: true
|
|
35295
|
-
}
|
|
35296
|
-
}, ["operation", "payload"])
|
|
35348
|
+
description: "Run a Workit-managed external action. context.read is read-only. Mutations require an active coordinator task, checkout writer ownership, and host-native authorization. Routine Git work already permitted by the host can use native tools without a Workit task; never use another route to bypass a host denial or uncertain result.",
|
|
35349
|
+
input: externalActionJsonSchema()
|
|
35297
35350
|
},
|
|
35298
35351
|
{
|
|
35299
35352
|
name: "workit_init_apply",
|
|
@@ -36028,6 +36081,12 @@ var setup = async (ctx) => {
|
|
|
36028
36081
|
}
|
|
36029
36082
|
});
|
|
36030
36083
|
await ctx.tool.hook("execute.before", async (event) => {
|
|
36084
|
+
if (event.tool === "question") {
|
|
36085
|
+
const sessionID = String(event.sessionID);
|
|
36086
|
+
const callID = String(event.id);
|
|
36087
|
+
receipts.recordRequest(callID, sessionID, callID, event.input?.questions);
|
|
36088
|
+
return;
|
|
36089
|
+
}
|
|
36031
36090
|
if (event.tool !== "subagent")
|
|
36032
36091
|
return;
|
|
36033
36092
|
await lifecycle.executeBefore({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainervirus/workit-opencode",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Workit OpenCode plugin — native tools, adaptive policy, and fourteen method skills",
|
|
6
6
|
"keywords": [
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"typecheck": "tsc --noEmit"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@brainervirus/workit-core": "^1.3.
|
|
42
|
+
"@brainervirus/workit-core": "^1.3.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@opencode-ai/plugin": "1.18.30",
|