opencode-hive 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +206 -0
- package/dist/agents/architect.d.ts +1 -1
- package/dist/agents/hive.d.ts +1 -1
- package/dist/agents/swarm.d.ts +1 -1
- package/dist/background/types.d.ts +7 -0
- package/dist/hooks/variant-hook.d.ts +50 -0
- package/dist/index.js +1220 -355
- package/dist/skills/builtin.d.ts +12 -0
- package/dist/skills/index.d.ts +1 -1
- package/dist/skills/registry.generated.d.ts +1 -1
- package/dist/tools/background-tools.d.ts +20 -7
- package/dist/utils/format.d.ts +16 -0
- package/dist/utils/prompt-budgeting.d.ts +112 -0
- package/dist/utils/prompt-file.d.ts +58 -0
- package/dist/utils/prompt-observability.d.ts +93 -0
- package/dist/utils/worker-prompt.d.ts +5 -4
- package/package.json +1 -1
- package/skills/onboarding/SKILL.md +61 -0
- package/skills/parallel-exploration/SKILL.md +286 -0
package/dist/index.js
CHANGED
|
@@ -12,10 +12,10 @@ var __export = (target, all) => {
|
|
|
12
12
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
13
13
|
|
|
14
14
|
// src/index.ts
|
|
15
|
-
import * as
|
|
16
|
-
import * as
|
|
15
|
+
import * as path7 from "path";
|
|
16
|
+
import * as fs9 from "fs";
|
|
17
17
|
|
|
18
|
-
// ../../node_modules
|
|
18
|
+
// ../../node_modules/zod/v4/classic/external.js
|
|
19
19
|
var exports_external = {};
|
|
20
20
|
__export(exports_external, {
|
|
21
21
|
xid: () => xid2,
|
|
@@ -245,7 +245,7 @@ __export(exports_external, {
|
|
|
245
245
|
$brand: () => $brand
|
|
246
246
|
});
|
|
247
247
|
|
|
248
|
-
// ../../node_modules
|
|
248
|
+
// ../../node_modules/zod/v4/core/index.js
|
|
249
249
|
var exports_core2 = {};
|
|
250
250
|
__export(exports_core2, {
|
|
251
251
|
version: () => version,
|
|
@@ -509,7 +509,7 @@ __export(exports_core2, {
|
|
|
509
509
|
$ZodAny: () => $ZodAny
|
|
510
510
|
});
|
|
511
511
|
|
|
512
|
-
// ../../node_modules
|
|
512
|
+
// ../../node_modules/zod/v4/core/core.js
|
|
513
513
|
var NEVER = Object.freeze({
|
|
514
514
|
status: "aborted"
|
|
515
515
|
});
|
|
@@ -576,7 +576,7 @@ function config(newConfig) {
|
|
|
576
576
|
Object.assign(globalConfig, newConfig);
|
|
577
577
|
return globalConfig;
|
|
578
578
|
}
|
|
579
|
-
// ../../node_modules
|
|
579
|
+
// ../../node_modules/zod/v4/core/util.js
|
|
580
580
|
var exports_util = {};
|
|
581
581
|
__export(exports_util, {
|
|
582
582
|
unwrapMessage: () => unwrapMessage,
|
|
@@ -1205,7 +1205,7 @@ class Class {
|
|
|
1205
1205
|
constructor(..._args) {}
|
|
1206
1206
|
}
|
|
1207
1207
|
|
|
1208
|
-
// ../../node_modules
|
|
1208
|
+
// ../../node_modules/zod/v4/core/errors.js
|
|
1209
1209
|
var initializer = (inst, def) => {
|
|
1210
1210
|
inst.name = "$ZodError";
|
|
1211
1211
|
Object.defineProperty(inst, "_zod", {
|
|
@@ -1348,7 +1348,7 @@ function prettifyError(error) {
|
|
|
1348
1348
|
`);
|
|
1349
1349
|
}
|
|
1350
1350
|
|
|
1351
|
-
// ../../node_modules
|
|
1351
|
+
// ../../node_modules/zod/v4/core/parse.js
|
|
1352
1352
|
var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
1353
1353
|
const ctx = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
|
|
1354
1354
|
const result = schema._zod.run({ value, issues: [] }, ctx);
|
|
@@ -1435,7 +1435,7 @@ var _safeDecodeAsync = (_Err) => async (schema, value, _ctx) => {
|
|
|
1435
1435
|
return _safeParseAsync(_Err)(schema, value, _ctx);
|
|
1436
1436
|
};
|
|
1437
1437
|
var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync($ZodRealError);
|
|
1438
|
-
// ../../node_modules
|
|
1438
|
+
// ../../node_modules/zod/v4/core/regexes.js
|
|
1439
1439
|
var exports_regexes = {};
|
|
1440
1440
|
__export(exports_regexes, {
|
|
1441
1441
|
xid: () => xid,
|
|
@@ -1587,7 +1587,7 @@ var sha512_hex = /^[0-9a-fA-F]{128}$/;
|
|
|
1587
1587
|
var sha512_base64 = /* @__PURE__ */ fixedBase64(86, "==");
|
|
1588
1588
|
var sha512_base64url = /* @__PURE__ */ fixedBase64url(86);
|
|
1589
1589
|
|
|
1590
|
-
// ../../node_modules
|
|
1590
|
+
// ../../node_modules/zod/v4/core/checks.js
|
|
1591
1591
|
var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
|
|
1592
1592
|
var _a;
|
|
1593
1593
|
inst._zod ?? (inst._zod = {});
|
|
@@ -2128,7 +2128,7 @@ var $ZodCheckOverwrite = /* @__PURE__ */ $constructor("$ZodCheckOverwrite", (ins
|
|
|
2128
2128
|
};
|
|
2129
2129
|
});
|
|
2130
2130
|
|
|
2131
|
-
// ../../node_modules
|
|
2131
|
+
// ../../node_modules/zod/v4/core/doc.js
|
|
2132
2132
|
class Doc {
|
|
2133
2133
|
constructor(args = []) {
|
|
2134
2134
|
this.content = [];
|
|
@@ -2166,14 +2166,14 @@ class Doc {
|
|
|
2166
2166
|
}
|
|
2167
2167
|
}
|
|
2168
2168
|
|
|
2169
|
-
// ../../node_modules
|
|
2169
|
+
// ../../node_modules/zod/v4/core/versions.js
|
|
2170
2170
|
var version = {
|
|
2171
2171
|
major: 4,
|
|
2172
2172
|
minor: 1,
|
|
2173
2173
|
patch: 8
|
|
2174
2174
|
};
|
|
2175
2175
|
|
|
2176
|
-
// ../../node_modules
|
|
2176
|
+
// ../../node_modules/zod/v4/core/schemas.js
|
|
2177
2177
|
var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
2178
2178
|
var _a;
|
|
2179
2179
|
inst ?? (inst = {});
|
|
@@ -3996,7 +3996,7 @@ function handleRefineResult(result, payload, input, inst) {
|
|
|
3996
3996
|
payload.issues.push(issue(_iss));
|
|
3997
3997
|
}
|
|
3998
3998
|
}
|
|
3999
|
-
// ../../node_modules
|
|
3999
|
+
// ../../node_modules/zod/v4/locales/index.js
|
|
4000
4000
|
var exports_locales = {};
|
|
4001
4001
|
__export(exports_locales, {
|
|
4002
4002
|
zhTW: () => zh_TW_default,
|
|
@@ -4047,7 +4047,7 @@ __export(exports_locales, {
|
|
|
4047
4047
|
ar: () => ar_default
|
|
4048
4048
|
});
|
|
4049
4049
|
|
|
4050
|
-
// ../../node_modules
|
|
4050
|
+
// ../../node_modules/zod/v4/locales/ar.js
|
|
4051
4051
|
var error = () => {
|
|
4052
4052
|
const Sizable = {
|
|
4053
4053
|
string: { unit: "حرف", verb: "أن يحوي" },
|
|
@@ -4163,7 +4163,7 @@ function ar_default() {
|
|
|
4163
4163
|
localeError: error()
|
|
4164
4164
|
};
|
|
4165
4165
|
}
|
|
4166
|
-
// ../../node_modules
|
|
4166
|
+
// ../../node_modules/zod/v4/locales/az.js
|
|
4167
4167
|
var error2 = () => {
|
|
4168
4168
|
const Sizable = {
|
|
4169
4169
|
string: { unit: "simvol", verb: "olmalıdır" },
|
|
@@ -4278,7 +4278,7 @@ function az_default() {
|
|
|
4278
4278
|
localeError: error2()
|
|
4279
4279
|
};
|
|
4280
4280
|
}
|
|
4281
|
-
// ../../node_modules
|
|
4281
|
+
// ../../node_modules/zod/v4/locales/be.js
|
|
4282
4282
|
function getBelarusianPlural(count, one, few, many) {
|
|
4283
4283
|
const absCount = Math.abs(count);
|
|
4284
4284
|
const lastDigit = absCount % 10;
|
|
@@ -4442,7 +4442,7 @@ function be_default() {
|
|
|
4442
4442
|
localeError: error3()
|
|
4443
4443
|
};
|
|
4444
4444
|
}
|
|
4445
|
-
// ../../node_modules
|
|
4445
|
+
// ../../node_modules/zod/v4/locales/ca.js
|
|
4446
4446
|
var error4 = () => {
|
|
4447
4447
|
const Sizable = {
|
|
4448
4448
|
string: { unit: "caràcters", verb: "contenir" },
|
|
@@ -4559,7 +4559,7 @@ function ca_default() {
|
|
|
4559
4559
|
localeError: error4()
|
|
4560
4560
|
};
|
|
4561
4561
|
}
|
|
4562
|
-
// ../../node_modules
|
|
4562
|
+
// ../../node_modules/zod/v4/locales/cs.js
|
|
4563
4563
|
var error5 = () => {
|
|
4564
4564
|
const Sizable = {
|
|
4565
4565
|
string: { unit: "znaků", verb: "mít" },
|
|
@@ -4694,7 +4694,7 @@ function cs_default() {
|
|
|
4694
4694
|
localeError: error5()
|
|
4695
4695
|
};
|
|
4696
4696
|
}
|
|
4697
|
-
// ../../node_modules
|
|
4697
|
+
// ../../node_modules/zod/v4/locales/da.js
|
|
4698
4698
|
var error6 = () => {
|
|
4699
4699
|
const Sizable = {
|
|
4700
4700
|
string: { unit: "tegn", verb: "havde" },
|
|
@@ -4825,7 +4825,7 @@ function da_default() {
|
|
|
4825
4825
|
localeError: error6()
|
|
4826
4826
|
};
|
|
4827
4827
|
}
|
|
4828
|
-
// ../../node_modules
|
|
4828
|
+
// ../../node_modules/zod/v4/locales/de.js
|
|
4829
4829
|
var error7 = () => {
|
|
4830
4830
|
const Sizable = {
|
|
4831
4831
|
string: { unit: "Zeichen", verb: "zu haben" },
|
|
@@ -4941,7 +4941,7 @@ function de_default() {
|
|
|
4941
4941
|
localeError: error7()
|
|
4942
4942
|
};
|
|
4943
4943
|
}
|
|
4944
|
-
// ../../node_modules
|
|
4944
|
+
// ../../node_modules/zod/v4/locales/en.js
|
|
4945
4945
|
var parsedType = (data) => {
|
|
4946
4946
|
const t = typeof data;
|
|
4947
4947
|
switch (t) {
|
|
@@ -5058,7 +5058,7 @@ function en_default() {
|
|
|
5058
5058
|
localeError: error8()
|
|
5059
5059
|
};
|
|
5060
5060
|
}
|
|
5061
|
-
// ../../node_modules
|
|
5061
|
+
// ../../node_modules/zod/v4/locales/eo.js
|
|
5062
5062
|
var parsedType2 = (data) => {
|
|
5063
5063
|
const t = typeof data;
|
|
5064
5064
|
switch (t) {
|
|
@@ -5174,7 +5174,7 @@ function eo_default() {
|
|
|
5174
5174
|
localeError: error9()
|
|
5175
5175
|
};
|
|
5176
5176
|
}
|
|
5177
|
-
// ../../node_modules
|
|
5177
|
+
// ../../node_modules/zod/v4/locales/es.js
|
|
5178
5178
|
var error10 = () => {
|
|
5179
5179
|
const Sizable = {
|
|
5180
5180
|
string: { unit: "caracteres", verb: "tener" },
|
|
@@ -5322,7 +5322,7 @@ function es_default() {
|
|
|
5322
5322
|
localeError: error10()
|
|
5323
5323
|
};
|
|
5324
5324
|
}
|
|
5325
|
-
// ../../node_modules
|
|
5325
|
+
// ../../node_modules/zod/v4/locales/fa.js
|
|
5326
5326
|
var error11 = () => {
|
|
5327
5327
|
const Sizable = {
|
|
5328
5328
|
string: { unit: "کاراکتر", verb: "داشته باشد" },
|
|
@@ -5444,7 +5444,7 @@ function fa_default() {
|
|
|
5444
5444
|
localeError: error11()
|
|
5445
5445
|
};
|
|
5446
5446
|
}
|
|
5447
|
-
// ../../node_modules
|
|
5447
|
+
// ../../node_modules/zod/v4/locales/fi.js
|
|
5448
5448
|
var error12 = () => {
|
|
5449
5449
|
const Sizable = {
|
|
5450
5450
|
string: { unit: "merkkiä", subject: "merkkijonon" },
|
|
@@ -5566,7 +5566,7 @@ function fi_default() {
|
|
|
5566
5566
|
localeError: error12()
|
|
5567
5567
|
};
|
|
5568
5568
|
}
|
|
5569
|
-
// ../../node_modules
|
|
5569
|
+
// ../../node_modules/zod/v4/locales/fr.js
|
|
5570
5570
|
var error13 = () => {
|
|
5571
5571
|
const Sizable = {
|
|
5572
5572
|
string: { unit: "caractères", verb: "avoir" },
|
|
@@ -5682,7 +5682,7 @@ function fr_default() {
|
|
|
5682
5682
|
localeError: error13()
|
|
5683
5683
|
};
|
|
5684
5684
|
}
|
|
5685
|
-
// ../../node_modules
|
|
5685
|
+
// ../../node_modules/zod/v4/locales/fr-CA.js
|
|
5686
5686
|
var error14 = () => {
|
|
5687
5687
|
const Sizable = {
|
|
5688
5688
|
string: { unit: "caractères", verb: "avoir" },
|
|
@@ -5799,7 +5799,7 @@ function fr_CA_default() {
|
|
|
5799
5799
|
localeError: error14()
|
|
5800
5800
|
};
|
|
5801
5801
|
}
|
|
5802
|
-
// ../../node_modules
|
|
5802
|
+
// ../../node_modules/zod/v4/locales/he.js
|
|
5803
5803
|
var error15 = () => {
|
|
5804
5804
|
const Sizable = {
|
|
5805
5805
|
string: { unit: "אותיות", verb: "לכלול" },
|
|
@@ -5915,7 +5915,7 @@ function he_default() {
|
|
|
5915
5915
|
localeError: error15()
|
|
5916
5916
|
};
|
|
5917
5917
|
}
|
|
5918
|
-
// ../../node_modules
|
|
5918
|
+
// ../../node_modules/zod/v4/locales/hu.js
|
|
5919
5919
|
var error16 = () => {
|
|
5920
5920
|
const Sizable = {
|
|
5921
5921
|
string: { unit: "karakter", verb: "legyen" },
|
|
@@ -6031,7 +6031,7 @@ function hu_default() {
|
|
|
6031
6031
|
localeError: error16()
|
|
6032
6032
|
};
|
|
6033
6033
|
}
|
|
6034
|
-
// ../../node_modules
|
|
6034
|
+
// ../../node_modules/zod/v4/locales/id.js
|
|
6035
6035
|
var error17 = () => {
|
|
6036
6036
|
const Sizable = {
|
|
6037
6037
|
string: { unit: "karakter", verb: "memiliki" },
|
|
@@ -6147,7 +6147,7 @@ function id_default() {
|
|
|
6147
6147
|
localeError: error17()
|
|
6148
6148
|
};
|
|
6149
6149
|
}
|
|
6150
|
-
// ../../node_modules
|
|
6150
|
+
// ../../node_modules/zod/v4/locales/is.js
|
|
6151
6151
|
var parsedType3 = (data) => {
|
|
6152
6152
|
const t = typeof data;
|
|
6153
6153
|
switch (t) {
|
|
@@ -6264,7 +6264,7 @@ function is_default() {
|
|
|
6264
6264
|
localeError: error18()
|
|
6265
6265
|
};
|
|
6266
6266
|
}
|
|
6267
|
-
// ../../node_modules
|
|
6267
|
+
// ../../node_modules/zod/v4/locales/it.js
|
|
6268
6268
|
var error19 = () => {
|
|
6269
6269
|
const Sizable = {
|
|
6270
6270
|
string: { unit: "caratteri", verb: "avere" },
|
|
@@ -6380,7 +6380,7 @@ function it_default() {
|
|
|
6380
6380
|
localeError: error19()
|
|
6381
6381
|
};
|
|
6382
6382
|
}
|
|
6383
|
-
// ../../node_modules
|
|
6383
|
+
// ../../node_modules/zod/v4/locales/ja.js
|
|
6384
6384
|
var error20 = () => {
|
|
6385
6385
|
const Sizable = {
|
|
6386
6386
|
string: { unit: "文字", verb: "である" },
|
|
@@ -6495,7 +6495,7 @@ function ja_default() {
|
|
|
6495
6495
|
localeError: error20()
|
|
6496
6496
|
};
|
|
6497
6497
|
}
|
|
6498
|
-
// ../../node_modules
|
|
6498
|
+
// ../../node_modules/zod/v4/locales/ka.js
|
|
6499
6499
|
var parsedType4 = (data) => {
|
|
6500
6500
|
const t = typeof data;
|
|
6501
6501
|
switch (t) {
|
|
@@ -6620,7 +6620,7 @@ function ka_default() {
|
|
|
6620
6620
|
localeError: error21()
|
|
6621
6621
|
};
|
|
6622
6622
|
}
|
|
6623
|
-
// ../../node_modules
|
|
6623
|
+
// ../../node_modules/zod/v4/locales/km.js
|
|
6624
6624
|
var error22 = () => {
|
|
6625
6625
|
const Sizable = {
|
|
6626
6626
|
string: { unit: "តួអក្សរ", verb: "គួរមាន" },
|
|
@@ -6738,11 +6738,11 @@ function km_default() {
|
|
|
6738
6738
|
};
|
|
6739
6739
|
}
|
|
6740
6740
|
|
|
6741
|
-
// ../../node_modules
|
|
6741
|
+
// ../../node_modules/zod/v4/locales/kh.js
|
|
6742
6742
|
function kh_default() {
|
|
6743
6743
|
return km_default();
|
|
6744
6744
|
}
|
|
6745
|
-
// ../../node_modules
|
|
6745
|
+
// ../../node_modules/zod/v4/locales/ko.js
|
|
6746
6746
|
var error23 = () => {
|
|
6747
6747
|
const Sizable = {
|
|
6748
6748
|
string: { unit: "문자", verb: "to have" },
|
|
@@ -6863,7 +6863,7 @@ function ko_default() {
|
|
|
6863
6863
|
localeError: error23()
|
|
6864
6864
|
};
|
|
6865
6865
|
}
|
|
6866
|
-
// ../../node_modules
|
|
6866
|
+
// ../../node_modules/zod/v4/locales/lt.js
|
|
6867
6867
|
var parsedType5 = (data) => {
|
|
6868
6868
|
const t = typeof data;
|
|
6869
6869
|
return parsedTypeFromType(t, data);
|
|
@@ -7092,7 +7092,7 @@ function lt_default() {
|
|
|
7092
7092
|
localeError: error24()
|
|
7093
7093
|
};
|
|
7094
7094
|
}
|
|
7095
|
-
// ../../node_modules
|
|
7095
|
+
// ../../node_modules/zod/v4/locales/mk.js
|
|
7096
7096
|
var error25 = () => {
|
|
7097
7097
|
const Sizable = {
|
|
7098
7098
|
string: { unit: "знаци", verb: "да имаат" },
|
|
@@ -7209,7 +7209,7 @@ function mk_default() {
|
|
|
7209
7209
|
localeError: error25()
|
|
7210
7210
|
};
|
|
7211
7211
|
}
|
|
7212
|
-
// ../../node_modules
|
|
7212
|
+
// ../../node_modules/zod/v4/locales/ms.js
|
|
7213
7213
|
var error26 = () => {
|
|
7214
7214
|
const Sizable = {
|
|
7215
7215
|
string: { unit: "aksara", verb: "mempunyai" },
|
|
@@ -7325,7 +7325,7 @@ function ms_default() {
|
|
|
7325
7325
|
localeError: error26()
|
|
7326
7326
|
};
|
|
7327
7327
|
}
|
|
7328
|
-
// ../../node_modules
|
|
7328
|
+
// ../../node_modules/zod/v4/locales/nl.js
|
|
7329
7329
|
var error27 = () => {
|
|
7330
7330
|
const Sizable = {
|
|
7331
7331
|
string: { unit: "tekens" },
|
|
@@ -7442,7 +7442,7 @@ function nl_default() {
|
|
|
7442
7442
|
localeError: error27()
|
|
7443
7443
|
};
|
|
7444
7444
|
}
|
|
7445
|
-
// ../../node_modules
|
|
7445
|
+
// ../../node_modules/zod/v4/locales/no.js
|
|
7446
7446
|
var error28 = () => {
|
|
7447
7447
|
const Sizable = {
|
|
7448
7448
|
string: { unit: "tegn", verb: "å ha" },
|
|
@@ -7558,7 +7558,7 @@ function no_default() {
|
|
|
7558
7558
|
localeError: error28()
|
|
7559
7559
|
};
|
|
7560
7560
|
}
|
|
7561
|
-
// ../../node_modules
|
|
7561
|
+
// ../../node_modules/zod/v4/locales/ota.js
|
|
7562
7562
|
var error29 = () => {
|
|
7563
7563
|
const Sizable = {
|
|
7564
7564
|
string: { unit: "harf", verb: "olmalıdır" },
|
|
@@ -7674,7 +7674,7 @@ function ota_default() {
|
|
|
7674
7674
|
localeError: error29()
|
|
7675
7675
|
};
|
|
7676
7676
|
}
|
|
7677
|
-
// ../../node_modules
|
|
7677
|
+
// ../../node_modules/zod/v4/locales/ps.js
|
|
7678
7678
|
var error30 = () => {
|
|
7679
7679
|
const Sizable = {
|
|
7680
7680
|
string: { unit: "توکي", verb: "ولري" },
|
|
@@ -7796,7 +7796,7 @@ function ps_default() {
|
|
|
7796
7796
|
localeError: error30()
|
|
7797
7797
|
};
|
|
7798
7798
|
}
|
|
7799
|
-
// ../../node_modules
|
|
7799
|
+
// ../../node_modules/zod/v4/locales/pl.js
|
|
7800
7800
|
var error31 = () => {
|
|
7801
7801
|
const Sizable = {
|
|
7802
7802
|
string: { unit: "znaków", verb: "mieć" },
|
|
@@ -7913,7 +7913,7 @@ function pl_default() {
|
|
|
7913
7913
|
localeError: error31()
|
|
7914
7914
|
};
|
|
7915
7915
|
}
|
|
7916
|
-
// ../../node_modules
|
|
7916
|
+
// ../../node_modules/zod/v4/locales/pt.js
|
|
7917
7917
|
var error32 = () => {
|
|
7918
7918
|
const Sizable = {
|
|
7919
7919
|
string: { unit: "caracteres", verb: "ter" },
|
|
@@ -8029,7 +8029,7 @@ function pt_default() {
|
|
|
8029
8029
|
localeError: error32()
|
|
8030
8030
|
};
|
|
8031
8031
|
}
|
|
8032
|
-
// ../../node_modules
|
|
8032
|
+
// ../../node_modules/zod/v4/locales/ru.js
|
|
8033
8033
|
function getRussianPlural(count, one, few, many) {
|
|
8034
8034
|
const absCount = Math.abs(count);
|
|
8035
8035
|
const lastDigit = absCount % 10;
|
|
@@ -8193,7 +8193,7 @@ function ru_default() {
|
|
|
8193
8193
|
localeError: error33()
|
|
8194
8194
|
};
|
|
8195
8195
|
}
|
|
8196
|
-
// ../../node_modules
|
|
8196
|
+
// ../../node_modules/zod/v4/locales/sl.js
|
|
8197
8197
|
var error34 = () => {
|
|
8198
8198
|
const Sizable = {
|
|
8199
8199
|
string: { unit: "znakov", verb: "imeti" },
|
|
@@ -8310,7 +8310,7 @@ function sl_default() {
|
|
|
8310
8310
|
localeError: error34()
|
|
8311
8311
|
};
|
|
8312
8312
|
}
|
|
8313
|
-
// ../../node_modules
|
|
8313
|
+
// ../../node_modules/zod/v4/locales/sv.js
|
|
8314
8314
|
var error35 = () => {
|
|
8315
8315
|
const Sizable = {
|
|
8316
8316
|
string: { unit: "tecken", verb: "att ha" },
|
|
@@ -8428,7 +8428,7 @@ function sv_default() {
|
|
|
8428
8428
|
localeError: error35()
|
|
8429
8429
|
};
|
|
8430
8430
|
}
|
|
8431
|
-
// ../../node_modules
|
|
8431
|
+
// ../../node_modules/zod/v4/locales/ta.js
|
|
8432
8432
|
var error36 = () => {
|
|
8433
8433
|
const Sizable = {
|
|
8434
8434
|
string: { unit: "எழுத்துக்கள்", verb: "கொண்டிருக்க வேண்டும்" },
|
|
@@ -8545,7 +8545,7 @@ function ta_default() {
|
|
|
8545
8545
|
localeError: error36()
|
|
8546
8546
|
};
|
|
8547
8547
|
}
|
|
8548
|
-
// ../../node_modules
|
|
8548
|
+
// ../../node_modules/zod/v4/locales/th.js
|
|
8549
8549
|
var error37 = () => {
|
|
8550
8550
|
const Sizable = {
|
|
8551
8551
|
string: { unit: "ตัวอักษร", verb: "ควรมี" },
|
|
@@ -8662,7 +8662,7 @@ function th_default() {
|
|
|
8662
8662
|
localeError: error37()
|
|
8663
8663
|
};
|
|
8664
8664
|
}
|
|
8665
|
-
// ../../node_modules
|
|
8665
|
+
// ../../node_modules/zod/v4/locales/tr.js
|
|
8666
8666
|
var parsedType6 = (data) => {
|
|
8667
8667
|
const t = typeof data;
|
|
8668
8668
|
switch (t) {
|
|
@@ -8777,7 +8777,7 @@ function tr_default() {
|
|
|
8777
8777
|
localeError: error38()
|
|
8778
8778
|
};
|
|
8779
8779
|
}
|
|
8780
|
-
// ../../node_modules
|
|
8780
|
+
// ../../node_modules/zod/v4/locales/uk.js
|
|
8781
8781
|
var error39 = () => {
|
|
8782
8782
|
const Sizable = {
|
|
8783
8783
|
string: { unit: "символів", verb: "матиме" },
|
|
@@ -8894,11 +8894,11 @@ function uk_default() {
|
|
|
8894
8894
|
};
|
|
8895
8895
|
}
|
|
8896
8896
|
|
|
8897
|
-
// ../../node_modules
|
|
8897
|
+
// ../../node_modules/zod/v4/locales/ua.js
|
|
8898
8898
|
function ua_default() {
|
|
8899
8899
|
return uk_default();
|
|
8900
8900
|
}
|
|
8901
|
-
// ../../node_modules
|
|
8901
|
+
// ../../node_modules/zod/v4/locales/ur.js
|
|
8902
8902
|
var error40 = () => {
|
|
8903
8903
|
const Sizable = {
|
|
8904
8904
|
string: { unit: "حروف", verb: "ہونا" },
|
|
@@ -9015,7 +9015,7 @@ function ur_default() {
|
|
|
9015
9015
|
localeError: error40()
|
|
9016
9016
|
};
|
|
9017
9017
|
}
|
|
9018
|
-
// ../../node_modules
|
|
9018
|
+
// ../../node_modules/zod/v4/locales/vi.js
|
|
9019
9019
|
var error41 = () => {
|
|
9020
9020
|
const Sizable = {
|
|
9021
9021
|
string: { unit: "ký tự", verb: "có" },
|
|
@@ -9131,7 +9131,7 @@ function vi_default() {
|
|
|
9131
9131
|
localeError: error41()
|
|
9132
9132
|
};
|
|
9133
9133
|
}
|
|
9134
|
-
// ../../node_modules
|
|
9134
|
+
// ../../node_modules/zod/v4/locales/zh-CN.js
|
|
9135
9135
|
var error42 = () => {
|
|
9136
9136
|
const Sizable = {
|
|
9137
9137
|
string: { unit: "字符", verb: "包含" },
|
|
@@ -9247,7 +9247,7 @@ function zh_CN_default() {
|
|
|
9247
9247
|
localeError: error42()
|
|
9248
9248
|
};
|
|
9249
9249
|
}
|
|
9250
|
-
// ../../node_modules
|
|
9250
|
+
// ../../node_modules/zod/v4/locales/zh-TW.js
|
|
9251
9251
|
var error43 = () => {
|
|
9252
9252
|
const Sizable = {
|
|
9253
9253
|
string: { unit: "字元", verb: "擁有" },
|
|
@@ -9364,7 +9364,7 @@ function zh_TW_default() {
|
|
|
9364
9364
|
localeError: error43()
|
|
9365
9365
|
};
|
|
9366
9366
|
}
|
|
9367
|
-
// ../../node_modules
|
|
9367
|
+
// ../../node_modules/zod/v4/locales/yo.js
|
|
9368
9368
|
var error44 = () => {
|
|
9369
9369
|
const Sizable = {
|
|
9370
9370
|
string: { unit: "àmi", verb: "ní" },
|
|
@@ -9479,7 +9479,7 @@ function yo_default() {
|
|
|
9479
9479
|
localeError: error44()
|
|
9480
9480
|
};
|
|
9481
9481
|
}
|
|
9482
|
-
// ../../node_modules
|
|
9482
|
+
// ../../node_modules/zod/v4/core/registries.js
|
|
9483
9483
|
var $output = Symbol("ZodOutput");
|
|
9484
9484
|
var $input = Symbol("ZodInput");
|
|
9485
9485
|
|
|
@@ -9530,7 +9530,7 @@ function registry() {
|
|
|
9530
9530
|
return new $ZodRegistry;
|
|
9531
9531
|
}
|
|
9532
9532
|
var globalRegistry = /* @__PURE__ */ registry();
|
|
9533
|
-
// ../../node_modules
|
|
9533
|
+
// ../../node_modules/zod/v4/core/api.js
|
|
9534
9534
|
function _string(Class2, params) {
|
|
9535
9535
|
return new Class2({
|
|
9536
9536
|
type: "string",
|
|
@@ -10408,7 +10408,7 @@ function _stringFormat(Class2, format, fnOrRegex, _params = {}) {
|
|
|
10408
10408
|
const inst = new Class2(def);
|
|
10409
10409
|
return inst;
|
|
10410
10410
|
}
|
|
10411
|
-
// ../../node_modules
|
|
10411
|
+
// ../../node_modules/zod/v4/core/to-json-schema.js
|
|
10412
10412
|
class JSONSchemaGenerator {
|
|
10413
10413
|
constructor(params) {
|
|
10414
10414
|
this.counter = 0;
|
|
@@ -11212,9 +11212,9 @@ function isTransforming(_schema, _ctx) {
|
|
|
11212
11212
|
}
|
|
11213
11213
|
throw new Error(`Unknown schema type: ${def.type}`);
|
|
11214
11214
|
}
|
|
11215
|
-
// ../../node_modules
|
|
11215
|
+
// ../../node_modules/zod/v4/core/json-schema.js
|
|
11216
11216
|
var exports_json_schema = {};
|
|
11217
|
-
// ../../node_modules
|
|
11217
|
+
// ../../node_modules/zod/v4/classic/iso.js
|
|
11218
11218
|
var exports_iso = {};
|
|
11219
11219
|
__export(exports_iso, {
|
|
11220
11220
|
time: () => time2,
|
|
@@ -11255,7 +11255,7 @@ function duration2(params) {
|
|
|
11255
11255
|
return _isoDuration(ZodISODuration, params);
|
|
11256
11256
|
}
|
|
11257
11257
|
|
|
11258
|
-
// ../../node_modules
|
|
11258
|
+
// ../../node_modules/zod/v4/classic/errors.js
|
|
11259
11259
|
var initializer2 = (inst, issues) => {
|
|
11260
11260
|
$ZodError.init(inst, issues);
|
|
11261
11261
|
inst.name = "ZodError";
|
|
@@ -11290,7 +11290,7 @@ var ZodRealError = $constructor("ZodError", initializer2, {
|
|
|
11290
11290
|
Parent: Error
|
|
11291
11291
|
});
|
|
11292
11292
|
|
|
11293
|
-
// ../../node_modules
|
|
11293
|
+
// ../../node_modules/zod/v4/classic/parse.js
|
|
11294
11294
|
var parse3 = /* @__PURE__ */ _parse(ZodRealError);
|
|
11295
11295
|
var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
11296
11296
|
var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
@@ -11304,7 +11304,7 @@ var safeDecode2 = /* @__PURE__ */ _safeDecode(ZodRealError);
|
|
|
11304
11304
|
var safeEncodeAsync2 = /* @__PURE__ */ _safeEncodeAsync(ZodRealError);
|
|
11305
11305
|
var safeDecodeAsync2 = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
|
|
11306
11306
|
|
|
11307
|
-
// ../../node_modules
|
|
11307
|
+
// ../../node_modules/zod/v4/classic/schemas.js
|
|
11308
11308
|
var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
11309
11309
|
$ZodType.init(inst, def);
|
|
11310
11310
|
inst.def = def;
|
|
@@ -12279,7 +12279,7 @@ function json(params) {
|
|
|
12279
12279
|
function preprocess(fn, schema) {
|
|
12280
12280
|
return pipe(transform(fn), schema);
|
|
12281
12281
|
}
|
|
12282
|
-
// ../../node_modules
|
|
12282
|
+
// ../../node_modules/zod/v4/classic/compat.js
|
|
12283
12283
|
var ZodIssueCode = {
|
|
12284
12284
|
invalid_type: "invalid_type",
|
|
12285
12285
|
too_big: "too_big",
|
|
@@ -12303,7 +12303,7 @@ function getErrorMap() {
|
|
|
12303
12303
|
}
|
|
12304
12304
|
var ZodFirstPartyTypeKind;
|
|
12305
12305
|
(function(ZodFirstPartyTypeKind2) {})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
|
|
12306
|
-
// ../../node_modules
|
|
12306
|
+
// ../../node_modules/zod/v4/classic/coerce.js
|
|
12307
12307
|
var exports_coerce = {};
|
|
12308
12308
|
__export(exports_coerce, {
|
|
12309
12309
|
string: () => string3,
|
|
@@ -12328,19 +12328,19 @@ function date4(params) {
|
|
|
12328
12328
|
return _coercedDate(ZodDate, params);
|
|
12329
12329
|
}
|
|
12330
12330
|
|
|
12331
|
-
// ../../node_modules
|
|
12331
|
+
// ../../node_modules/zod/v4/classic/external.js
|
|
12332
12332
|
config(en_default());
|
|
12333
|
-
// ../../node_modules
|
|
12333
|
+
// ../../node_modules/@opencode-ai/plugin/dist/tool.js
|
|
12334
12334
|
function tool(input) {
|
|
12335
12335
|
return input;
|
|
12336
12336
|
}
|
|
12337
12337
|
tool.schema = exports_external;
|
|
12338
12338
|
// src/skills/registry.generated.ts
|
|
12339
|
-
var BUILTIN_SKILL_NAMES = ["brainstorming", "dispatching-parallel-agents", "executing-plans", "systematic-debugging", "test-driven-development", "verification-before-completion", "writing-plans"];
|
|
12339
|
+
var BUILTIN_SKILL_NAMES = ["brainstorming", "dispatching-parallel-agents", "executing-plans", "onboarding", "parallel-exploration", "systematic-debugging", "test-driven-development", "verification-before-completion", "writing-plans"];
|
|
12340
12340
|
var BUILTIN_SKILLS = [
|
|
12341
12341
|
{
|
|
12342
12342
|
name: "brainstorming",
|
|
12343
|
-
description:
|
|
12343
|
+
description: "Use before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation.",
|
|
12344
12344
|
template: `# Brainstorming Ideas Into Designs
|
|
12345
12345
|
|
|
12346
12346
|
## Overview
|
|
@@ -12642,6 +12642,351 @@ After all tasks complete and verified:
|
|
|
12642
12642
|
- Reference skills when plan says to
|
|
12643
12643
|
- Between batches: just report and wait
|
|
12644
12644
|
- Stop when blocked, don't guess`
|
|
12645
|
+
},
|
|
12646
|
+
{
|
|
12647
|
+
name: "onboarding",
|
|
12648
|
+
description: "Ask about workflow preferences and store them in .hive/contexts/preferences.md before proceeding.",
|
|
12649
|
+
template: `# Onboarding Preferences
|
|
12650
|
+
|
|
12651
|
+
## Overview
|
|
12652
|
+
|
|
12653
|
+
Gather workflow preferences so the assistant can match the user's desired working style.
|
|
12654
|
+
|
|
12655
|
+
## When to Ask
|
|
12656
|
+
|
|
12657
|
+
- **Immediately when the skill is loaded**, before any other work.
|
|
12658
|
+
- If \`.hive/contexts/preferences.md\` does not exist, start onboarding.
|
|
12659
|
+
- If later a decision is ambiguous and preferences are missing, ask again.
|
|
12660
|
+
|
|
12661
|
+
## Preference Storage
|
|
12662
|
+
|
|
12663
|
+
Use \`hive_context_write\` to write \`.hive/contexts/preferences.md\` with this exact template:
|
|
12664
|
+
|
|
12665
|
+
\`\`\`
|
|
12666
|
+
# Preferences
|
|
12667
|
+
|
|
12668
|
+
## Exploration Style
|
|
12669
|
+
sync
|
|
12670
|
+
|
|
12671
|
+
## Research Depth
|
|
12672
|
+
medium
|
|
12673
|
+
|
|
12674
|
+
## Confirmation Level
|
|
12675
|
+
standard
|
|
12676
|
+
|
|
12677
|
+
## Commit Behavior
|
|
12678
|
+
ask-before-commit
|
|
12679
|
+
\`\`\`
|
|
12680
|
+
|
|
12681
|
+
## If Preferences Already Exist
|
|
12682
|
+
|
|
12683
|
+
Follow the same pattern used in \`packages/vscode-hive/src/tools/plan.ts\`:
|
|
12684
|
+
|
|
12685
|
+
1. Use \`contextService.list(feature)\` to detect existing contexts.
|
|
12686
|
+
2. Ask **"Preferences already exist. Keep or overwrite?"** using the \`question()\` tool.
|
|
12687
|
+
3. If keep → continue using existing preferences.
|
|
12688
|
+
4. If overwrite → collect new answers and write them with \`hive_context_write\`.
|
|
12689
|
+
|
|
12690
|
+
## Questions to Ask (Always use \`question()\`)
|
|
12691
|
+
|
|
12692
|
+
Ask one at a time, with the provided options. Store the answers in \`.hive/contexts/preferences.md\`.
|
|
12693
|
+
|
|
12694
|
+
1. **Exploration Style:** sync | async
|
|
12695
|
+
2. **Research Depth:** shallow | medium | deep
|
|
12696
|
+
3. **Confirmation Level:** minimal | standard | high
|
|
12697
|
+
4. **Commit Behavior:** ask-before-commit | auto-commit | never-commit
|
|
12698
|
+
|
|
12699
|
+
## Requirements
|
|
12700
|
+
|
|
12701
|
+
- Use the \`question()\` tool (no plain text questions).
|
|
12702
|
+
- Ask immediately when the skill loads if preferences are missing.
|
|
12703
|
+
- If later a decision is ambiguous and preferences are missing, ask again.
|
|
12704
|
+
- Always store answers using \`hive_context_write\` with the template above.`
|
|
12705
|
+
},
|
|
12706
|
+
{
|
|
12707
|
+
name: "parallel-exploration",
|
|
12708
|
+
description: "Use when you need parallel, read-only exploration via hive_hive_background_task (Scout fan-out)",
|
|
12709
|
+
template: `# Parallel Exploration (Background Scout Fan-Out)
|
|
12710
|
+
|
|
12711
|
+
## Overview
|
|
12712
|
+
|
|
12713
|
+
When you need to answer "where/how does X work?" across multiple domains (codebase, tests, docs, OSS), investigating sequentially wastes time. Each investigation is independent and can happen in parallel.
|
|
12714
|
+
|
|
12715
|
+
**Core principle:** Decompose into independent sub-questions, spawn one \`hive_hive_background_task\` per sub-question, collect results asynchronously.
|
|
12716
|
+
|
|
12717
|
+
**Safe in Planning mode:** This is read-only exploration. It is OK to use during exploratory research even when there is no feature, no plan, and no approved tasks.
|
|
12718
|
+
|
|
12719
|
+
**This skill is for read-only research.** For parallel implementation work, use \`hive_skill("dispatching-parallel-agents")\` with \`hive_exec_start\`.
|
|
12720
|
+
|
|
12721
|
+
## When to Use
|
|
12722
|
+
|
|
12723
|
+
**Default to this skill when:**
|
|
12724
|
+
**Use when:**
|
|
12725
|
+
- Investigation spans multiple domains (code + tests + docs)
|
|
12726
|
+
- User asks **2+ questions across different domains** (e.g., code + tests, code + docs/OSS, code + config/runtime)
|
|
12727
|
+
- Questions are independent (answer to A doesn't affect B)
|
|
12728
|
+
- User asks **3+ independent questions** (often as a numbered list or separate bullets)
|
|
12729
|
+
- No edits needed (read-only exploration)
|
|
12730
|
+
- User asks for an explorationthat likely spans multiple files/packages
|
|
12731
|
+
- The work is read-only and the questions can be investigated independently
|
|
12732
|
+
|
|
12733
|
+
**Only skip this skill when:**
|
|
12734
|
+
- Investigation requires shared state or context between questions
|
|
12735
|
+
- It's a single focused question that is genuinely answerable with **one quick grep + one file read**
|
|
12736
|
+
- Questions are dependent (answer A materially changes what to ask for B)
|
|
12737
|
+
- Work involves file edits (use Hive tasks / Forager instead)
|
|
12738
|
+
|
|
12739
|
+
**Important:** Do not treat "this is exploratory" as a reason to avoid delegation. This skill is specifically for exploratory research when fan-out makes it faster and cleaner.
|
|
12740
|
+
|
|
12741
|
+
## The Pattern
|
|
12742
|
+
|
|
12743
|
+
### 1. Decompose Into Independent Questions
|
|
12744
|
+
|
|
12745
|
+
Split your investigation into 2-4 independent sub-questions. Good decomposition:
|
|
12746
|
+
|
|
12747
|
+
| Domain | Question Example |
|
|
12748
|
+
|--------|------------------|
|
|
12749
|
+
| Codebase | "Where is X implemented? What files define it?" |
|
|
12750
|
+
| Tests | "How is X tested? What test patterns exist?" |
|
|
12751
|
+
| Docs/OSS | "How do other projects implement X? What's the recommended pattern?" |
|
|
12752
|
+
| Config | "How is X configured? What environment variables affect it?" |
|
|
12753
|
+
|
|
12754
|
+
**Bad decomposition (dependent questions):**
|
|
12755
|
+
- "What is X?" then "How is X used?" (second depends on first)
|
|
12756
|
+
- "Find the bug" then "Fix the bug" (not read-only)
|
|
12757
|
+
|
|
12758
|
+
### 2. Spawn Background Tasks (Fan-Out)
|
|
12759
|
+
|
|
12760
|
+
Launch all tasks before waiting for any results:
|
|
12761
|
+
|
|
12762
|
+
\`\`\`typescript
|
|
12763
|
+
// Fan-out: spawn all tasks first
|
|
12764
|
+
hive_background_task({
|
|
12765
|
+
agent: "scout-researcher",
|
|
12766
|
+
description: "Find hive_background_task implementation",
|
|
12767
|
+
prompt: \`Where is hive_background_task implemented and registered?
|
|
12768
|
+
- Find the tool definition
|
|
12769
|
+
- Find the plugin registration
|
|
12770
|
+
- Return file paths with line numbers\`,
|
|
12771
|
+
sync: false
|
|
12772
|
+
})
|
|
12773
|
+
|
|
12774
|
+
hive_background_task({
|
|
12775
|
+
agent: "scout-researcher",
|
|
12776
|
+
description: "Analyze background task concurrency",
|
|
12777
|
+
prompt: \`How does background task concurrency/queueing work?
|
|
12778
|
+
- Find the manager/scheduler code
|
|
12779
|
+
- Document the concurrency model
|
|
12780
|
+
- Return file paths with evidence\`,
|
|
12781
|
+
sync: false
|
|
12782
|
+
})
|
|
12783
|
+
|
|
12784
|
+
hive_background_task({
|
|
12785
|
+
agent: "scout-researcher",
|
|
12786
|
+
description: "Find parent notification mechanism",
|
|
12787
|
+
prompt: \`How does parent notification work for background tasks?
|
|
12788
|
+
- Where is the notification built?
|
|
12789
|
+
- How is it sent to the parent session?
|
|
12790
|
+
- Return file paths with evidence\`,
|
|
12791
|
+
sync: false
|
|
12792
|
+
})
|
|
12793
|
+
\`\`\`
|
|
12794
|
+
|
|
12795
|
+
**Key points:**
|
|
12796
|
+
- Use \`agent: "scout-researcher"\` for read-only exploration
|
|
12797
|
+
- Use \`sync: false\` to return immediately (non-blocking)
|
|
12798
|
+
- Give each task a clear, focused \`description\`
|
|
12799
|
+
- Make prompts specific about what evidence to return
|
|
12800
|
+
|
|
12801
|
+
### 3. Continue Working (Optional)
|
|
12802
|
+
|
|
12803
|
+
While tasks run, you can:
|
|
12804
|
+
- Work on other aspects of the problem
|
|
12805
|
+
- Prepare synthesis structure
|
|
12806
|
+
- Start drafting based on what you already know
|
|
12807
|
+
|
|
12808
|
+
You'll receive a \`<system-reminder>\` notification when each task completes.
|
|
12809
|
+
|
|
12810
|
+
### 4. Collect Results
|
|
12811
|
+
|
|
12812
|
+
When notified of completion, retrieve results:
|
|
12813
|
+
|
|
12814
|
+
\`\`\`typescript
|
|
12815
|
+
// Get output from completed task
|
|
12816
|
+
hive_background_output({
|
|
12817
|
+
task_id: "task-abc123",
|
|
12818
|
+
block: false // Don't wait, task already done
|
|
12819
|
+
})
|
|
12820
|
+
\`\`\`
|
|
12821
|
+
|
|
12822
|
+
**For incremental output (long-running tasks):**
|
|
12823
|
+
|
|
12824
|
+
\`\`\`typescript
|
|
12825
|
+
// First call - get initial output
|
|
12826
|
+
hive_background_output({
|
|
12827
|
+
task_id: "task-abc123",
|
|
12828
|
+
block: true, // Wait for output
|
|
12829
|
+
timeout: 30000 // 30 second timeout
|
|
12830
|
+
})
|
|
12831
|
+
// Returns: { output: "...", cursor: "5" }
|
|
12832
|
+
|
|
12833
|
+
// Later call - get new output since cursor
|
|
12834
|
+
hive_background_output({
|
|
12835
|
+
task_id: "task-abc123",
|
|
12836
|
+
cursor: "5", // Resume from message 5
|
|
12837
|
+
block: true
|
|
12838
|
+
})
|
|
12839
|
+
\`\`\`
|
|
12840
|
+
|
|
12841
|
+
### 5. Synthesize Findings
|
|
12842
|
+
|
|
12843
|
+
Combine results from all tasks:
|
|
12844
|
+
- Cross-reference findings (file X mentioned by tasks A and B)
|
|
12845
|
+
- Identify gaps (task C found nothing, need different approach)
|
|
12846
|
+
- Build coherent answer from parallel evidence
|
|
12847
|
+
|
|
12848
|
+
### 6. Cleanup (If Needed)
|
|
12849
|
+
|
|
12850
|
+
Cancel tasks that are no longer needed:
|
|
12851
|
+
|
|
12852
|
+
\`\`\`typescript
|
|
12853
|
+
// Cancel specific task
|
|
12854
|
+
hive_background_cancel({ task_id: "task-abc123" })
|
|
12855
|
+
|
|
12856
|
+
// Cancel all your background tasks
|
|
12857
|
+
hive_background_cancel({ all: true })
|
|
12858
|
+
\`\`\`
|
|
12859
|
+
|
|
12860
|
+
## Prompt Templates
|
|
12861
|
+
|
|
12862
|
+
### Codebase Slice
|
|
12863
|
+
|
|
12864
|
+
\`\`\`
|
|
12865
|
+
Investigate [TOPIC] in the codebase:
|
|
12866
|
+
- Where is [X] defined/implemented?
|
|
12867
|
+
- What files contain [X]?
|
|
12868
|
+
- How does [X] interact with [Y]?
|
|
12869
|
+
|
|
12870
|
+
Return:
|
|
12871
|
+
- File paths with line numbers
|
|
12872
|
+
- Brief code snippets as evidence
|
|
12873
|
+
- Key patterns observed
|
|
12874
|
+
\`\`\`
|
|
12875
|
+
|
|
12876
|
+
### Tests Slice
|
|
12877
|
+
|
|
12878
|
+
\`\`\`
|
|
12879
|
+
Investigate how [TOPIC] is tested:
|
|
12880
|
+
- What test files cover [X]?
|
|
12881
|
+
- What testing patterns are used?
|
|
12882
|
+
- What edge cases are tested?
|
|
12883
|
+
|
|
12884
|
+
Return:
|
|
12885
|
+
- Test file paths
|
|
12886
|
+
- Example test patterns
|
|
12887
|
+
- Coverage gaps if obvious
|
|
12888
|
+
\`\`\`
|
|
12889
|
+
|
|
12890
|
+
### Docs/OSS Slice
|
|
12891
|
+
|
|
12892
|
+
\`\`\`
|
|
12893
|
+
Research [TOPIC] in external sources:
|
|
12894
|
+
- How do other projects implement [X]?
|
|
12895
|
+
- What does the official documentation say?
|
|
12896
|
+
- What are common patterns/anti-patterns?
|
|
12897
|
+
|
|
12898
|
+
Return:
|
|
12899
|
+
- Links to relevant docs/repos
|
|
12900
|
+
- Key recommendations
|
|
12901
|
+
- Patterns that apply to our codebase
|
|
12902
|
+
\`\`\`
|
|
12903
|
+
|
|
12904
|
+
## Real Example
|
|
12905
|
+
|
|
12906
|
+
**Investigation:** "How does the background task system work?"
|
|
12907
|
+
|
|
12908
|
+
**Decomposition:**
|
|
12909
|
+
1. Implementation: Where is \`hive_background_task\` tool defined?
|
|
12910
|
+
2. Concurrency: How does task scheduling/queueing work?
|
|
12911
|
+
3. Notifications: How does parent session get notified?
|
|
12912
|
+
|
|
12913
|
+
**Fan-out:**
|
|
12914
|
+
\`\`\`typescript
|
|
12915
|
+
// Task 1: Implementation
|
|
12916
|
+
hive_background_task({
|
|
12917
|
+
agent: "scout-researcher",
|
|
12918
|
+
description: "Find hive_background_task implementation",
|
|
12919
|
+
prompt: "Where is hive_background_task implemented? Find tool definition and registration.",
|
|
12920
|
+
sync: false
|
|
12921
|
+
})
|
|
12922
|
+
|
|
12923
|
+
// Task 2: Concurrency
|
|
12924
|
+
hive_background_task({
|
|
12925
|
+
agent: "scout-researcher",
|
|
12926
|
+
description: "Analyze concurrency model",
|
|
12927
|
+
prompt: "How does background task concurrency work? Find the manager/scheduler.",
|
|
12928
|
+
sync: false
|
|
12929
|
+
})
|
|
12930
|
+
|
|
12931
|
+
// Task 3: Notifications
|
|
12932
|
+
hive_background_task({
|
|
12933
|
+
agent: "scout-researcher",
|
|
12934
|
+
description: "Find notification mechanism",
|
|
12935
|
+
prompt: "How are parent sessions notified of task completion?",
|
|
12936
|
+
sync: false
|
|
12937
|
+
})
|
|
12938
|
+
\`\`\`
|
|
12939
|
+
|
|
12940
|
+
**Results:**
|
|
12941
|
+
- Task 1: Found \`background-tools.ts\` (tool definition), \`index.ts\` (registration)
|
|
12942
|
+
- Task 2: Found \`manager.ts\` with concurrency=3 default, queue-based scheduling
|
|
12943
|
+
- Task 3: Found \`session.prompt()\` call in manager for parent notification
|
|
12944
|
+
|
|
12945
|
+
**Synthesis:** Complete picture of background task lifecycle in ~1/3 the time of sequential investigation.
|
|
12946
|
+
|
|
12947
|
+
## Common Mistakes
|
|
12948
|
+
|
|
12949
|
+
**Spawning sequentially (defeats the purpose):**
|
|
12950
|
+
\`\`\`typescript
|
|
12951
|
+
// BAD: Wait for each before spawning next
|
|
12952
|
+
const result1 = await hive_background_task({ ..., sync: true })
|
|
12953
|
+
const result2 = await hive_background_task({ ..., sync: true })
|
|
12954
|
+
\`\`\`
|
|
12955
|
+
|
|
12956
|
+
\`\`\`typescript
|
|
12957
|
+
// GOOD: Spawn all, then collect
|
|
12958
|
+
hive_background_task({ ..., sync: false }) // Returns immediately
|
|
12959
|
+
hive_background_task({ ..., sync: false }) // Returns immediately
|
|
12960
|
+
hive_background_task({ ..., sync: false }) // Returns immediately
|
|
12961
|
+
// ... later, collect results with hive_background_output
|
|
12962
|
+
\`\`\`
|
|
12963
|
+
|
|
12964
|
+
**Too many tasks (diminishing returns):**
|
|
12965
|
+
- 2-4 tasks: Good parallelization
|
|
12966
|
+
- 5+ tasks: Overhead exceeds benefit, harder to synthesize
|
|
12967
|
+
|
|
12968
|
+
**Dependent questions:**
|
|
12969
|
+
- Don't spawn task B if it needs task A's answer
|
|
12970
|
+
- Either make them independent or run sequentially
|
|
12971
|
+
|
|
12972
|
+
**Using for edits:**
|
|
12973
|
+
- Scout is read-only; use Forager for implementation
|
|
12974
|
+
- This skill is for exploration, not execution
|
|
12975
|
+
|
|
12976
|
+
## Key Benefits
|
|
12977
|
+
|
|
12978
|
+
1. **Speed** - 3 investigations in time of 1
|
|
12979
|
+
2. **Focus** - Each Scout has narrow scope
|
|
12980
|
+
3. **Independence** - No interference between tasks
|
|
12981
|
+
4. **Flexibility** - Cancel unneeded tasks, add new ones
|
|
12982
|
+
|
|
12983
|
+
## Verification
|
|
12984
|
+
|
|
12985
|
+
After using this pattern, verify:
|
|
12986
|
+
- [ ] All tasks spawned before collecting any results (true fan-out)
|
|
12987
|
+
- [ ] Received notifications for completed tasks
|
|
12988
|
+
- [ ] Successfully retrieved output with \`hive_background_output\`
|
|
12989
|
+
- [ ] Synthesized findings into coherent answer`
|
|
12645
12990
|
},
|
|
12646
12991
|
{
|
|
12647
12992
|
name: "systematic-debugging",
|
|
@@ -13578,8 +13923,14 @@ function loadBuiltinSkill(name) {
|
|
|
13578
13923
|
source: "builtin"
|
|
13579
13924
|
};
|
|
13580
13925
|
}
|
|
13581
|
-
function
|
|
13582
|
-
|
|
13926
|
+
function getFilteredSkills(disabledSkills = [], agentSkills) {
|
|
13927
|
+
const disabled = new Set(disabledSkills);
|
|
13928
|
+
let filtered = BUILTIN_SKILLS.filter((s) => !disabled.has(s.name));
|
|
13929
|
+
if (agentSkills && agentSkills.length > 0) {
|
|
13930
|
+
const enabled = new Set(agentSkills);
|
|
13931
|
+
filtered = filtered.filter((s) => enabled.has(s.name));
|
|
13932
|
+
}
|
|
13933
|
+
return filtered;
|
|
13583
13934
|
}
|
|
13584
13935
|
|
|
13585
13936
|
// src/agents/hive.ts
|
|
@@ -13610,13 +13961,22 @@ Run \`hive_status()\` or \`hive_feature_list()\` to detect phase:
|
|
|
13610
13961
|
| Trivial | Single file, <10 lines | Do directly |
|
|
13611
13962
|
| Simple | 1-2 files, <30 min | Light discovery → act |
|
|
13612
13963
|
| Complex | 3+ files, multi-step | Full discovery → plan/delegate |
|
|
13613
|
-
| Research |
|
|
13964
|
+
| Research | Internal codebase exploration OR external data | Delegate to Scout (Explorer/Researcher/Retrieval) |
|
|
13965
|
+
|
|
13966
|
+
### Canonical Delegation Threshold
|
|
13967
|
+
|
|
13968
|
+
- Delegate to Scout when you cannot name the file path upfront, expect to inspect 2+ files, or the question is open-ended ("how/where does X work?").
|
|
13969
|
+
- Prefer \`hive_background_task(agent: "scout-researcher", sync: true, ...)\` for single investigations; use \`sync: false\` only for multi-scout fan-out.
|
|
13970
|
+
- Local \`read/grep/glob\` is acceptable only for a single known file and a bounded question.
|
|
13614
13971
|
|
|
13615
13972
|
### Delegation
|
|
13616
13973
|
|
|
13617
|
-
-
|
|
13974
|
+
- Single-scout research → \`hive_background_task(agent: "scout-researcher", sync: true, ...)\` (blocks until complete, simpler flow)
|
|
13975
|
+
- Parallel exploration → Load \`hive_skill("parallel-exploration")\` and use \`hive_background_task(agent: "scout-researcher", sync: false, ...)\`
|
|
13618
13976
|
- Implementation → \`hive_exec_start(task)\` (spawns Forager)
|
|
13619
13977
|
|
|
13978
|
+
During Planning, default to synchronous exploration (\`sync: true\`). If async/parallel exploration would help, ask the user via \`question()\`.
|
|
13979
|
+
|
|
13620
13980
|
### Context Persistence
|
|
13621
13981
|
|
|
13622
13982
|
Save discoveries with \`hive_context_write\`:
|
|
@@ -13637,6 +13997,7 @@ Load when detailed guidance needed:
|
|
|
13637
13997
|
- \`hive_skill("brainstorming")\` - exploring ideas and requirements
|
|
13638
13998
|
- \`hive_skill("writing-plans")\` - structuring implementation plans
|
|
13639
13999
|
- \`hive_skill("dispatching-parallel-agents")\` - parallel task delegation
|
|
14000
|
+
- \`hive_skill("parallel-exploration")\` - parallel read-only research via hive_background_task (Scout fan-out)
|
|
13640
14001
|
- \`hive_skill("executing-plans")\` - step-by-step plan execution
|
|
13641
14002
|
|
|
13642
14003
|
Load ONE skill at a time. Only when you need guidance beyond this prompt.
|
|
@@ -13685,9 +14046,9 @@ If yes → \`task({ subagent_type: "hygienic", prompt: "Review plan..." })\`
|
|
|
13685
14046
|
|
|
13686
14047
|
### Planning Iron Laws
|
|
13687
14048
|
|
|
13688
|
-
- Research BEFORE asking (
|
|
14049
|
+
- Research BEFORE asking (use \`hive_skill("parallel-exploration")\` for multi-domain research)
|
|
13689
14050
|
- Save draft as working memory
|
|
13690
|
-
- Don't
|
|
14051
|
+
- Don't implement (no edits/worktrees). Read-only exploration is allowed (local tools + Scout via hive_background_task).
|
|
13691
14052
|
|
|
13692
14053
|
---
|
|
13693
14054
|
|
|
@@ -13714,9 +14075,19 @@ hive_exec_start({ task: "01-task-name" }) // Creates worktree + Forager
|
|
|
13714
14075
|
|
|
13715
14076
|
### After Delegation
|
|
13716
14077
|
|
|
13717
|
-
1.
|
|
13718
|
-
2.
|
|
13719
|
-
3.
|
|
14078
|
+
1. Wait for the completion notification (no polling required)
|
|
14079
|
+
2. Use \`hive_worker_status()\` for spot checks or if you suspect notifications did not deliver
|
|
14080
|
+
3. Use \`hive_background_output\` only if interim output is explicitly needed, or after completion
|
|
14081
|
+
4. When calling \`hive_background_output\`, choose a timeout (30-120s) based on task size
|
|
14082
|
+
5. If blocked: \`question()\` → user decision → \`continueFrom: "blocked"\`
|
|
14083
|
+
|
|
14084
|
+
### Observation Polling (Recommended)
|
|
14085
|
+
|
|
14086
|
+
- Prefer completion notifications over polling
|
|
14087
|
+
- Use \`hive_worker_status()\` for observation-based spot checks
|
|
14088
|
+
- Avoid tight loops with \`hive_background_output\`; if needed, wait 30-60s between checks
|
|
14089
|
+
- If you suspect notifications did not deliver, do a single \`hive_worker_status()\` check first
|
|
14090
|
+
- If you need to fetch final results, call \`hive_background_output({ task_id, block: false })\` after the completion notice
|
|
13720
14091
|
|
|
13721
14092
|
### Failure Recovery
|
|
13722
14093
|
|
|
@@ -13747,6 +14118,8 @@ hive_exec_start({ task: "01-task-name" }) // Creates worktree + Forager
|
|
|
13747
14118
|
- Skip phase detection
|
|
13748
14119
|
- Mix planning and orchestration in same action
|
|
13749
14120
|
- Auto-load all skills at start
|
|
14121
|
+
|
|
14122
|
+
**User Input:** ALWAYS use \`question()\` tool for any user input - NEVER ask questions via plain text. This ensures structured responses.
|
|
13750
14123
|
`;
|
|
13751
14124
|
|
|
13752
14125
|
// src/agents/architect.ts
|
|
@@ -13762,7 +14135,9 @@ PLANNER, NOT IMPLEMENTER. "Do X" means "create plan for X".
|
|
|
13762
14135
|
| Simple | 1-2 files, <30 min | Light interview → quick plan |
|
|
13763
14136
|
| Complex | 3+ files, review needed | Full discovery → detailed plan |
|
|
13764
14137
|
| Refactor | Existing code changes | Safety: tests, rollback, blast radius |
|
|
13765
|
-
| Greenfield | New feature | Research patterns BEFORE asking
|
|
14138
|
+
| Greenfield | New feature | Research patterns BEFORE asking. Delegate to Scout via \`hive_background_task(agent: "scout-researcher", sync: true, ...)\` for single investigations. |
|
|
14139
|
+
|
|
14140
|
+
During Planning, default to synchronous exploration (\`sync: true\`). If async/parallel exploration would help, ask the user via \`question()\`.
|
|
13766
14141
|
|
|
13767
14142
|
## Self-Clearance Check (After Every Exchange)
|
|
13768
14143
|
|
|
@@ -13815,7 +14190,7 @@ Plan MUST include:
|
|
|
13815
14190
|
|
|
13816
14191
|
**Never:**
|
|
13817
14192
|
- Execute code (you plan, not implement)
|
|
13818
|
-
-
|
|
14193
|
+
- Spawn implementation/coding workers (Swarm (Orchestrator) does this); read-only research delegation to Scout is allowed
|
|
13819
14194
|
- Use the task tool
|
|
13820
14195
|
- Skip discovery for complex tasks
|
|
13821
14196
|
- Assume when uncertain - ASK
|
|
@@ -13824,8 +14199,15 @@ Plan MUST include:
|
|
|
13824
14199
|
- Classify intent FIRST
|
|
13825
14200
|
- Run Self-Clearance after every exchange
|
|
13826
14201
|
- Flag AI-Slop patterns
|
|
13827
|
-
- Research BEFORE asking (greenfield); delegate external
|
|
14202
|
+
- Research BEFORE asking (greenfield); delegate internal codebase exploration or external data collection to Scout
|
|
13828
14203
|
- Save draft as working memory
|
|
14204
|
+
|
|
14205
|
+
### Canonical Delegation Threshold
|
|
14206
|
+
|
|
14207
|
+
- Delegate to Scout when you cannot name the file path upfront, expect to inspect 2+ files, or the question is open-ended ("how/where does X work?").
|
|
14208
|
+
- Prefer \`hive_background_task(agent: "scout-researcher", sync: true, ...)\` for single investigations; use \`sync: false\` only for multi-scout fan-out.
|
|
14209
|
+
- Local \`read/grep/glob\` is acceptable only for a single known file and a bounded question.
|
|
14210
|
+
- When calling \`hive_background_output\`, choose a timeout (30-120s) based on task size.
|
|
13829
14211
|
`;
|
|
13830
14212
|
|
|
13831
14213
|
// src/agents/swarm.ts
|
|
@@ -13839,7 +14221,7 @@ Delegate by default. Work yourself only when trivial.
|
|
|
13839
14221
|
|------|--------|--------|
|
|
13840
14222
|
| Trivial | Single file, known location | Direct tools only |
|
|
13841
14223
|
| Explicit | Specific file/line, clear command | Execute directly |
|
|
13842
|
-
| Exploratory | "How does X work?" | Delegate to Scout (
|
|
14224
|
+
| Exploratory | "How does X work?" | Delegate to Scout via hive_background_task(agent: "scout-researcher", sync: false, …). |
|
|
13843
14225
|
| Open-ended | "Improve", "Refactor" | Assess first, then delegate |
|
|
13844
14226
|
| Ambiguous | Unclear scope | Ask ONE clarifying question |
|
|
13845
14227
|
|
|
@@ -13848,7 +14230,8 @@ Delegate by default. Work yourself only when trivial.
|
|
|
13848
14230
|
1. Is there a specialized agent that matches?
|
|
13849
14231
|
2. Can I do it myself FOR SURE? REALLY?
|
|
13850
14232
|
3. Does this require external system data (DBs/APIs/3rd-party tools)?
|
|
13851
|
-
→ If external data needed:
|
|
14233
|
+
→ If external data needed: Load \`hive_skill("parallel-exploration")\` for parallel Scout fan-out
|
|
14234
|
+
During Planning, default to synchronous exploration. If async exploration would help, ask the user via \`question()\` and follow the onboarding preferences.
|
|
13852
14235
|
→ Default: DELEGATE
|
|
13853
14236
|
|
|
13854
14237
|
## Delegation Prompt Structure (All 6 Sections)
|
|
@@ -13867,11 +14250,16 @@ Delegate by default. Work yourself only when trivial.
|
|
|
13867
14250
|
\`\`\`
|
|
13868
14251
|
hive_exec_start({ task: "01-task-name" })
|
|
13869
14252
|
// If delegationRequired returned:
|
|
13870
|
-
|
|
13871
|
-
// If external system data is needed:
|
|
13872
|
-
|
|
14253
|
+
hive_background_task({ agent: "forager-worker", prompt: "...", sync: false })
|
|
14254
|
+
// If external system data is needed (parallel exploration):
|
|
14255
|
+
// Load hive_skill("parallel-exploration") for the full playbook, then:
|
|
14256
|
+
hive_background_task({ agent: "scout-researcher", prompt: "...", sync: false })
|
|
13873
14257
|
\`\`\`
|
|
13874
14258
|
|
|
14259
|
+
**Sync Mode Guidance:**
|
|
14260
|
+
- \`sync: true\` — Use for single-scout research when you need the result before continuing
|
|
14261
|
+
- \`sync: false\` — Use for parallel fan-out (multiple scouts) or when you can proceed without waiting
|
|
14262
|
+
|
|
13875
14263
|
## After Delegation - ALWAYS VERIFY
|
|
13876
14264
|
|
|
13877
14265
|
- Does it work as expected?
|
|
@@ -13914,7 +14302,9 @@ Merge only after verification passes.
|
|
|
13914
14302
|
- Delegate by default
|
|
13915
14303
|
- Verify delegate work
|
|
13916
14304
|
- Use question() for user input (NEVER plain text)
|
|
13917
|
-
- Cancel background tasks
|
|
14305
|
+
- Cancel background tasks only when stale or no longer needed
|
|
14306
|
+
|
|
14307
|
+
**User Input:** ALWAYS use \`question()\` tool for any user input - NEVER ask questions via plain text. This ensures structured responses.
|
|
13918
14308
|
`;
|
|
13919
14309
|
|
|
13920
14310
|
// src/agents/scout.ts
|
|
@@ -15113,70 +15503,6 @@ var require_dist2 = __commonJS((exports) => {
|
|
|
15113
15503
|
exports.createDeferred = deferred;
|
|
15114
15504
|
exports.default = deferred;
|
|
15115
15505
|
});
|
|
15116
|
-
var require_strip_json_comments = __commonJS((exports, module) => {
|
|
15117
|
-
var singleComment = 1;
|
|
15118
|
-
var multiComment = 2;
|
|
15119
|
-
function stripWithoutWhitespace() {
|
|
15120
|
-
return "";
|
|
15121
|
-
}
|
|
15122
|
-
function stripWithWhitespace(str, start, end) {
|
|
15123
|
-
return str.slice(start, end).replace(/\S/g, " ");
|
|
15124
|
-
}
|
|
15125
|
-
module.exports = function(str, opts) {
|
|
15126
|
-
opts = opts || {};
|
|
15127
|
-
var currentChar;
|
|
15128
|
-
var nextChar;
|
|
15129
|
-
var insideString = false;
|
|
15130
|
-
var insideComment = false;
|
|
15131
|
-
var offset = 0;
|
|
15132
|
-
var ret = "";
|
|
15133
|
-
var strip = opts.whitespace === false ? stripWithoutWhitespace : stripWithWhitespace;
|
|
15134
|
-
for (var i = 0;i < str.length; i++) {
|
|
15135
|
-
currentChar = str[i];
|
|
15136
|
-
nextChar = str[i + 1];
|
|
15137
|
-
if (!insideComment && currentChar === '"') {
|
|
15138
|
-
var escaped = str[i - 1] === "\\" && str[i - 2] !== "\\";
|
|
15139
|
-
if (!escaped) {
|
|
15140
|
-
insideString = !insideString;
|
|
15141
|
-
}
|
|
15142
|
-
}
|
|
15143
|
-
if (insideString) {
|
|
15144
|
-
continue;
|
|
15145
|
-
}
|
|
15146
|
-
if (!insideComment && currentChar + nextChar === "//") {
|
|
15147
|
-
ret += str.slice(offset, i);
|
|
15148
|
-
offset = i;
|
|
15149
|
-
insideComment = singleComment;
|
|
15150
|
-
i++;
|
|
15151
|
-
} else if (insideComment === singleComment && currentChar + nextChar === `\r
|
|
15152
|
-
`) {
|
|
15153
|
-
i++;
|
|
15154
|
-
insideComment = false;
|
|
15155
|
-
ret += strip(str, offset, i);
|
|
15156
|
-
offset = i;
|
|
15157
|
-
continue;
|
|
15158
|
-
} else if (insideComment === singleComment && currentChar === `
|
|
15159
|
-
`) {
|
|
15160
|
-
insideComment = false;
|
|
15161
|
-
ret += strip(str, offset, i);
|
|
15162
|
-
offset = i;
|
|
15163
|
-
} else if (!insideComment && currentChar + nextChar === "/*") {
|
|
15164
|
-
ret += str.slice(offset, i);
|
|
15165
|
-
offset = i;
|
|
15166
|
-
insideComment = multiComment;
|
|
15167
|
-
i++;
|
|
15168
|
-
continue;
|
|
15169
|
-
} else if (insideComment === multiComment && currentChar + nextChar === "*/") {
|
|
15170
|
-
i++;
|
|
15171
|
-
insideComment = false;
|
|
15172
|
-
ret += strip(str, offset, i + 1);
|
|
15173
|
-
offset = i + 1;
|
|
15174
|
-
continue;
|
|
15175
|
-
}
|
|
15176
|
-
}
|
|
15177
|
-
return ret + (insideComment ? strip(str.substr(offset)) : str.substr(offset));
|
|
15178
|
-
};
|
|
15179
|
-
});
|
|
15180
15506
|
var DEFAULT_AGENT_MODELS = {
|
|
15181
15507
|
"hive-master": "github-copilot/claude-opus-4.5",
|
|
15182
15508
|
"architect-planner": "github-copilot/gpt-5.2-codex",
|
|
@@ -15188,6 +15514,10 @@ var DEFAULT_AGENT_MODELS = {
|
|
|
15188
15514
|
var DEFAULT_HIVE_CONFIG = {
|
|
15189
15515
|
$schema: "https://raw.githubusercontent.com/tctinh/agent-hive/main/packages/opencode-hive/schema/agent_hive.schema.json",
|
|
15190
15516
|
enableToolsFor: [],
|
|
15517
|
+
disableSkills: [],
|
|
15518
|
+
disableMcps: [],
|
|
15519
|
+
agentMode: "unified",
|
|
15520
|
+
delegateMode: "task",
|
|
15191
15521
|
agents: {
|
|
15192
15522
|
"hive-master": {
|
|
15193
15523
|
model: DEFAULT_AGENT_MODELS["hive-master"],
|
|
@@ -15197,32 +15527,37 @@ var DEFAULT_HIVE_CONFIG = {
|
|
|
15197
15527
|
"writing-plans",
|
|
15198
15528
|
"dispatching-parallel-agents",
|
|
15199
15529
|
"executing-plans"
|
|
15200
|
-
]
|
|
15530
|
+
],
|
|
15531
|
+
autoLoadSkills: ["parallel-exploration"]
|
|
15201
15532
|
},
|
|
15202
15533
|
"architect-planner": {
|
|
15203
15534
|
model: DEFAULT_AGENT_MODELS["architect-planner"],
|
|
15204
15535
|
temperature: 0.7,
|
|
15205
|
-
skills: ["brainstorming", "writing-plans"]
|
|
15536
|
+
skills: ["brainstorming", "writing-plans"],
|
|
15537
|
+
autoLoadSkills: ["parallel-exploration"]
|
|
15206
15538
|
},
|
|
15207
15539
|
"swarm-orchestrator": {
|
|
15208
15540
|
model: DEFAULT_AGENT_MODELS["swarm-orchestrator"],
|
|
15209
15541
|
temperature: 0.5,
|
|
15210
|
-
skills: ["dispatching-parallel-agents", "executing-plans"]
|
|
15542
|
+
skills: ["dispatching-parallel-agents", "executing-plans"],
|
|
15543
|
+
autoLoadSkills: []
|
|
15211
15544
|
},
|
|
15212
15545
|
"scout-researcher": {
|
|
15213
15546
|
model: DEFAULT_AGENT_MODELS["scout-researcher"],
|
|
15214
15547
|
temperature: 0.5,
|
|
15215
|
-
skills: []
|
|
15548
|
+
skills: [],
|
|
15549
|
+
autoLoadSkills: ["parallel-exploration"]
|
|
15216
15550
|
},
|
|
15217
15551
|
"forager-worker": {
|
|
15218
15552
|
model: DEFAULT_AGENT_MODELS["forager-worker"],
|
|
15219
15553
|
temperature: 0.3,
|
|
15220
|
-
|
|
15554
|
+
autoLoadSkills: ["test-driven-development", "verification-before-completion"]
|
|
15221
15555
|
},
|
|
15222
15556
|
"hygienic-reviewer": {
|
|
15223
15557
|
model: DEFAULT_AGENT_MODELS["hygienic-reviewer"],
|
|
15224
15558
|
temperature: 0.3,
|
|
15225
|
-
skills: ["systematic-debugging"]
|
|
15559
|
+
skills: ["systematic-debugging"],
|
|
15560
|
+
autoLoadSkills: []
|
|
15226
15561
|
}
|
|
15227
15562
|
}
|
|
15228
15563
|
};
|
|
@@ -16095,7 +16430,7 @@ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
|
16095
16430
|
var __esm = (fn, res) => function __init() {
|
|
16096
16431
|
return fn && (res = (0, fn[__getOwnPropNames2(fn)[0]])(fn = 0)), res;
|
|
16097
16432
|
};
|
|
16098
|
-
var __commonJS2 = (cb, mod) => function
|
|
16433
|
+
var __commonJS2 = (cb, mod) => function __require22() {
|
|
16099
16434
|
return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
16100
16435
|
};
|
|
16101
16436
|
var __export2 = (target, all) => {
|
|
@@ -20586,8 +20921,6 @@ ${f.content}`);
|
|
|
20586
20921
|
return `${normalized}.md`;
|
|
20587
20922
|
}
|
|
20588
20923
|
}
|
|
20589
|
-
var import_strip_json_comments = __toESM(require_strip_json_comments(), 1);
|
|
20590
|
-
|
|
20591
20924
|
class ConfigService {
|
|
20592
20925
|
configPath;
|
|
20593
20926
|
constructor() {
|
|
@@ -20667,42 +21000,42 @@ class ConfigService {
|
|
|
20667
21000
|
}
|
|
20668
21001
|
return this.get();
|
|
20669
21002
|
}
|
|
20670
|
-
registerAgentsInOpenCode(agents) {
|
|
20671
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
20672
|
-
const opencodePath = path6.join(homeDir, ".config", "opencode", "opencode.json");
|
|
20673
|
-
try {
|
|
20674
|
-
if (!fs10.existsSync(opencodePath)) {
|
|
20675
|
-
return;
|
|
20676
|
-
}
|
|
20677
|
-
const raw = fs10.readFileSync(opencodePath, "utf-8");
|
|
20678
|
-
const config2 = JSON.parse(import_strip_json_comments.default(raw));
|
|
20679
|
-
if (!config2.agent) {
|
|
20680
|
-
config2.agent = {};
|
|
20681
|
-
}
|
|
20682
|
-
for (const [name, agentConfig] of Object.entries(agents)) {
|
|
20683
|
-
if (!config2.agent[name]) {
|
|
20684
|
-
config2.agent[name] = agentConfig;
|
|
20685
|
-
} else {
|
|
20686
|
-
config2.agent[name] = {
|
|
20687
|
-
...agentConfig,
|
|
20688
|
-
model: config2.agent[name].model || agentConfig.model,
|
|
20689
|
-
temperature: config2.agent[name].temperature ?? agentConfig.temperature
|
|
20690
|
-
};
|
|
20691
|
-
}
|
|
20692
|
-
}
|
|
20693
|
-
fs10.writeFileSync(opencodePath, JSON.stringify(config2, null, 2));
|
|
20694
|
-
} catch (err) {
|
|
20695
|
-
console.error("[Hive] Failed to register agents in opencode.json:", err);
|
|
20696
|
-
}
|
|
20697
|
-
}
|
|
20698
21003
|
getAgentConfig(agent) {
|
|
20699
21004
|
const config2 = this.get();
|
|
20700
|
-
|
|
21005
|
+
const agentConfig = config2.agents?.[agent] ?? {};
|
|
21006
|
+
const defaultAutoLoadSkills = DEFAULT_HIVE_CONFIG.agents?.[agent]?.autoLoadSkills ?? [];
|
|
21007
|
+
const userAutoLoadSkills = agentConfig.autoLoadSkills ?? [];
|
|
21008
|
+
const isPlannerAgent = agent === "hive-master" || agent === "architect-planner";
|
|
21009
|
+
const effectiveUserAutoLoadSkills = isPlannerAgent ? userAutoLoadSkills : userAutoLoadSkills.filter((skill) => skill !== "onboarding");
|
|
21010
|
+
const effectiveDefaultAutoLoadSkills = isPlannerAgent ? defaultAutoLoadSkills : defaultAutoLoadSkills.filter((skill) => skill !== "onboarding");
|
|
21011
|
+
const combinedAutoLoadSkills = [...effectiveDefaultAutoLoadSkills, ...effectiveUserAutoLoadSkills];
|
|
21012
|
+
const uniqueAutoLoadSkills = Array.from(new Set(combinedAutoLoadSkills));
|
|
21013
|
+
const disabledSkills = config2.disableSkills ?? [];
|
|
21014
|
+
const effectiveAutoLoadSkills = uniqueAutoLoadSkills.filter((skill) => !disabledSkills.includes(skill));
|
|
21015
|
+
return {
|
|
21016
|
+
...agentConfig,
|
|
21017
|
+
autoLoadSkills: effectiveAutoLoadSkills
|
|
21018
|
+
};
|
|
20701
21019
|
}
|
|
20702
21020
|
isOmoSlimEnabled() {
|
|
20703
21021
|
const config2 = this.get();
|
|
20704
21022
|
return config2.omoSlimEnabled === true;
|
|
20705
21023
|
}
|
|
21024
|
+
getDisabledSkills() {
|
|
21025
|
+
const config2 = this.get();
|
|
21026
|
+
return config2.disableSkills ?? [];
|
|
21027
|
+
}
|
|
21028
|
+
getDisabledMcps() {
|
|
21029
|
+
const config2 = this.get();
|
|
21030
|
+
return config2.disableMcps ?? [];
|
|
21031
|
+
}
|
|
21032
|
+
getDelegateMode() {
|
|
21033
|
+
const config2 = this.get();
|
|
21034
|
+
return config2.delegateMode ?? "task";
|
|
21035
|
+
}
|
|
21036
|
+
isHiveBackgroundEnabled() {
|
|
21037
|
+
return this.getDelegateMode() === "hive";
|
|
21038
|
+
}
|
|
20706
21039
|
}
|
|
20707
21040
|
|
|
20708
21041
|
// src/utils/worker-prompt.ts
|
|
@@ -20713,18 +21046,9 @@ function buildWorkerPrompt(params) {
|
|
|
20713
21046
|
taskOrder,
|
|
20714
21047
|
worktreePath,
|
|
20715
21048
|
branch,
|
|
20716
|
-
plan,
|
|
20717
|
-
contextFiles,
|
|
20718
21049
|
spec,
|
|
20719
|
-
previousTasks,
|
|
20720
21050
|
continueFrom
|
|
20721
21051
|
} = params;
|
|
20722
|
-
const contextSection = contextFiles.length > 0 ? contextFiles.map((f) => `### ${f.name}
|
|
20723
|
-
${f.content}`).join(`
|
|
20724
|
-
|
|
20725
|
-
`) : "_No context files available._";
|
|
20726
|
-
const previousSection = previousTasks?.length ? previousTasks.map((t) => `- **${t.name}**: ${t.summary}`).join(`
|
|
20727
|
-
`) : "_This is the first task._";
|
|
20728
21052
|
const continuationSection = continueFrom ? `
|
|
20729
21053
|
## Continuation from Blocked State
|
|
20730
21054
|
|
|
@@ -20758,24 +21082,6 @@ Do NOT modify files outside this directory.
|
|
|
20758
21082
|
${continuationSection}
|
|
20759
21083
|
---
|
|
20760
21084
|
|
|
20761
|
-
## Plan Context
|
|
20762
|
-
|
|
20763
|
-
${plan}
|
|
20764
|
-
|
|
20765
|
-
---
|
|
20766
|
-
|
|
20767
|
-
## Context Files (Royal Jelly)
|
|
20768
|
-
|
|
20769
|
-
${contextSection}
|
|
20770
|
-
|
|
20771
|
-
---
|
|
20772
|
-
|
|
20773
|
-
## Previous Tasks Completed
|
|
20774
|
-
|
|
20775
|
-
${previousSection}
|
|
20776
|
-
|
|
20777
|
-
---
|
|
20778
|
-
|
|
20779
21085
|
## Your Mission
|
|
20780
21086
|
|
|
20781
21087
|
${spec}
|
|
@@ -20890,7 +21196,7 @@ After 3 failed attempts at same fix: STOP and report blocker.
|
|
|
20890
21196
|
- \`question\` - Escalate via blocker protocol instead
|
|
20891
21197
|
- \`hive_exec_start\` - No spawning sub-workers
|
|
20892
21198
|
- \`hive_merge\` - Only Hive Master merges
|
|
20893
|
-
- \`
|
|
21199
|
+
- \`hive_background_task\` / \`task\` - No recursive delegation
|
|
20894
21200
|
|
|
20895
21201
|
---
|
|
20896
21202
|
|
|
@@ -20904,10 +21210,305 @@ After 3 failed attempts at same fix: STOP and report blocker.
|
|
|
20904
21210
|
|
|
20905
21211
|
---
|
|
20906
21212
|
|
|
21213
|
+
**User Input:** ALWAYS use \`question()\` tool for any user input - NEVER ask questions via plain text. This ensures structured responses.
|
|
21214
|
+
|
|
21215
|
+
---
|
|
21216
|
+
|
|
20907
21217
|
Begin your task now.
|
|
20908
21218
|
`;
|
|
20909
21219
|
}
|
|
20910
21220
|
|
|
21221
|
+
// src/utils/prompt-observability.ts
|
|
21222
|
+
var DEFAULT_THRESHOLDS = {
|
|
21223
|
+
workerPromptMaxChars: 1e5,
|
|
21224
|
+
jsonPayloadMaxChars: 150000,
|
|
21225
|
+
contextMaxChars: 50000,
|
|
21226
|
+
previousTasksMaxChars: 20000,
|
|
21227
|
+
planMaxChars: 30000
|
|
21228
|
+
};
|
|
21229
|
+
function calculatePromptMeta(inputs) {
|
|
21230
|
+
return {
|
|
21231
|
+
planChars: safeLength(inputs.plan),
|
|
21232
|
+
contextChars: safeLength(inputs.context),
|
|
21233
|
+
previousTasksChars: safeLength(inputs.previousTasks),
|
|
21234
|
+
specChars: safeLength(inputs.spec),
|
|
21235
|
+
workerPromptChars: safeLength(inputs.workerPrompt)
|
|
21236
|
+
};
|
|
21237
|
+
}
|
|
21238
|
+
function calculatePayloadMeta(inputs) {
|
|
21239
|
+
return {
|
|
21240
|
+
jsonPayloadChars: safeLength(inputs.jsonPayload),
|
|
21241
|
+
promptInlined: inputs.promptInlined,
|
|
21242
|
+
promptReferencedByFile: inputs.promptReferencedByFile ?? !inputs.promptInlined
|
|
21243
|
+
};
|
|
21244
|
+
}
|
|
21245
|
+
function checkWarnings(promptMeta, payloadMeta, thresholds = {}) {
|
|
21246
|
+
const t = { ...DEFAULT_THRESHOLDS, ...thresholds };
|
|
21247
|
+
const warnings = [];
|
|
21248
|
+
if (promptMeta.workerPromptChars > t.workerPromptMaxChars) {
|
|
21249
|
+
const severity = getSeverity(promptMeta.workerPromptChars, t.workerPromptMaxChars);
|
|
21250
|
+
warnings.push({
|
|
21251
|
+
type: "workerPromptSize",
|
|
21252
|
+
severity,
|
|
21253
|
+
message: `Worker prompt size (${formatBytes(promptMeta.workerPromptChars)}) exceeds threshold (${formatBytes(t.workerPromptMaxChars)})`,
|
|
21254
|
+
currentValue: promptMeta.workerPromptChars,
|
|
21255
|
+
threshold: t.workerPromptMaxChars
|
|
21256
|
+
});
|
|
21257
|
+
}
|
|
21258
|
+
if (payloadMeta.jsonPayloadChars > t.jsonPayloadMaxChars) {
|
|
21259
|
+
const severity = getSeverity(payloadMeta.jsonPayloadChars, t.jsonPayloadMaxChars);
|
|
21260
|
+
warnings.push({
|
|
21261
|
+
type: "jsonPayloadSize",
|
|
21262
|
+
severity,
|
|
21263
|
+
message: `JSON payload size (${formatBytes(payloadMeta.jsonPayloadChars)}) exceeds threshold (${formatBytes(t.jsonPayloadMaxChars)})`,
|
|
21264
|
+
currentValue: payloadMeta.jsonPayloadChars,
|
|
21265
|
+
threshold: t.jsonPayloadMaxChars
|
|
21266
|
+
});
|
|
21267
|
+
}
|
|
21268
|
+
if (promptMeta.contextChars > t.contextMaxChars) {
|
|
21269
|
+
const severity = getSeverity(promptMeta.contextChars, t.contextMaxChars);
|
|
21270
|
+
warnings.push({
|
|
21271
|
+
type: "contextSize",
|
|
21272
|
+
severity,
|
|
21273
|
+
message: `Context size (${formatBytes(promptMeta.contextChars)}) exceeds threshold (${formatBytes(t.contextMaxChars)})`,
|
|
21274
|
+
currentValue: promptMeta.contextChars,
|
|
21275
|
+
threshold: t.contextMaxChars
|
|
21276
|
+
});
|
|
21277
|
+
}
|
|
21278
|
+
if (promptMeta.previousTasksChars > t.previousTasksMaxChars) {
|
|
21279
|
+
const severity = getSeverity(promptMeta.previousTasksChars, t.previousTasksMaxChars);
|
|
21280
|
+
warnings.push({
|
|
21281
|
+
type: "previousTasksSize",
|
|
21282
|
+
severity,
|
|
21283
|
+
message: `Previous tasks size (${formatBytes(promptMeta.previousTasksChars)}) exceeds threshold (${formatBytes(t.previousTasksMaxChars)})`,
|
|
21284
|
+
currentValue: promptMeta.previousTasksChars,
|
|
21285
|
+
threshold: t.previousTasksMaxChars
|
|
21286
|
+
});
|
|
21287
|
+
}
|
|
21288
|
+
if (t.planMaxChars && promptMeta.planChars > t.planMaxChars) {
|
|
21289
|
+
const severity = getSeverity(promptMeta.planChars, t.planMaxChars);
|
|
21290
|
+
warnings.push({
|
|
21291
|
+
type: "planSize",
|
|
21292
|
+
severity,
|
|
21293
|
+
message: `Plan size (${formatBytes(promptMeta.planChars)}) exceeds threshold (${formatBytes(t.planMaxChars)})`,
|
|
21294
|
+
currentValue: promptMeta.planChars,
|
|
21295
|
+
threshold: t.planMaxChars
|
|
21296
|
+
});
|
|
21297
|
+
}
|
|
21298
|
+
return warnings;
|
|
21299
|
+
}
|
|
21300
|
+
function safeLength(str) {
|
|
21301
|
+
if (str == null)
|
|
21302
|
+
return 0;
|
|
21303
|
+
return str.length;
|
|
21304
|
+
}
|
|
21305
|
+
function getSeverity(value, threshold) {
|
|
21306
|
+
const ratio = value / threshold;
|
|
21307
|
+
if (ratio > 2)
|
|
21308
|
+
return "critical";
|
|
21309
|
+
if (ratio > 1.5)
|
|
21310
|
+
return "warning";
|
|
21311
|
+
return "info";
|
|
21312
|
+
}
|
|
21313
|
+
function formatBytes(chars) {
|
|
21314
|
+
if (chars < 1000)
|
|
21315
|
+
return `${chars} chars`;
|
|
21316
|
+
if (chars < 1e6)
|
|
21317
|
+
return `${(chars / 1000).toFixed(1)}K chars`;
|
|
21318
|
+
return `${(chars / 1e6).toFixed(2)}M chars`;
|
|
21319
|
+
}
|
|
21320
|
+
|
|
21321
|
+
// src/utils/prompt-budgeting.ts
|
|
21322
|
+
var DEFAULT_BUDGET = {
|
|
21323
|
+
maxTasks: 10,
|
|
21324
|
+
maxSummaryChars: 2000,
|
|
21325
|
+
maxContextChars: 20000,
|
|
21326
|
+
maxTotalContextChars: 60000
|
|
21327
|
+
};
|
|
21328
|
+
var TRUNCATION_MARKER = "...[truncated]";
|
|
21329
|
+
function truncateWithMarker(str, maxLength) {
|
|
21330
|
+
if (str.length <= maxLength) {
|
|
21331
|
+
return { result: str, truncated: false };
|
|
21332
|
+
}
|
|
21333
|
+
const cutoff = maxLength - TRUNCATION_MARKER.length;
|
|
21334
|
+
if (cutoff <= 0) {
|
|
21335
|
+
return { result: TRUNCATION_MARKER, truncated: true };
|
|
21336
|
+
}
|
|
21337
|
+
return {
|
|
21338
|
+
result: str.slice(0, cutoff) + TRUNCATION_MARKER,
|
|
21339
|
+
truncated: true
|
|
21340
|
+
};
|
|
21341
|
+
}
|
|
21342
|
+
function applyTaskBudget(tasks, config2 = {}) {
|
|
21343
|
+
const maxTasks = config2.maxTasks ?? DEFAULT_BUDGET.maxTasks;
|
|
21344
|
+
const maxSummaryChars = config2.maxSummaryChars ?? DEFAULT_BUDGET.maxSummaryChars;
|
|
21345
|
+
const feature = config2.feature;
|
|
21346
|
+
const truncationEvents = [];
|
|
21347
|
+
let droppedTasksHint;
|
|
21348
|
+
if (tasks.length === 0) {
|
|
21349
|
+
return { tasks: [], truncationEvents: [] };
|
|
21350
|
+
}
|
|
21351
|
+
let selectedTasks = tasks;
|
|
21352
|
+
const droppedTasks = [];
|
|
21353
|
+
if (tasks.length > maxTasks) {
|
|
21354
|
+
const dropCount = tasks.length - maxTasks;
|
|
21355
|
+
droppedTasks.push(...tasks.slice(0, dropCount).map((t) => t.name));
|
|
21356
|
+
selectedTasks = tasks.slice(dropCount);
|
|
21357
|
+
truncationEvents.push({
|
|
21358
|
+
type: "tasks_dropped",
|
|
21359
|
+
message: `Dropped ${dropCount} older task(s) to stay within budget of ${maxTasks}`,
|
|
21360
|
+
count: dropCount,
|
|
21361
|
+
affected: droppedTasks
|
|
21362
|
+
});
|
|
21363
|
+
if (feature) {
|
|
21364
|
+
droppedTasksHint = `Dropped tasks: ${droppedTasks.join(", ")}. Full reports available at .hive/features/${feature}/tasks/<task>/report.md`;
|
|
21365
|
+
} else {
|
|
21366
|
+
droppedTasksHint = `Dropped tasks: ${droppedTasks.join(", ")}. Full reports available in task directories.`;
|
|
21367
|
+
}
|
|
21368
|
+
}
|
|
21369
|
+
const budgetedTasks = selectedTasks.map((task) => {
|
|
21370
|
+
const { result, truncated } = truncateWithMarker(task.summary, maxSummaryChars);
|
|
21371
|
+
if (truncated) {
|
|
21372
|
+
truncationEvents.push({
|
|
21373
|
+
type: "summary_truncated",
|
|
21374
|
+
message: `Truncated summary for task "${task.name}" from ${task.summary.length} to ${result.length} chars`,
|
|
21375
|
+
affected: [task.name]
|
|
21376
|
+
});
|
|
21377
|
+
}
|
|
21378
|
+
return {
|
|
21379
|
+
name: task.name,
|
|
21380
|
+
summary: result,
|
|
21381
|
+
truncated,
|
|
21382
|
+
originalLength: truncated ? task.summary.length : undefined
|
|
21383
|
+
};
|
|
21384
|
+
});
|
|
21385
|
+
return {
|
|
21386
|
+
tasks: budgetedTasks,
|
|
21387
|
+
truncationEvents,
|
|
21388
|
+
droppedTasksHint
|
|
21389
|
+
};
|
|
21390
|
+
}
|
|
21391
|
+
function applyContextBudget(files, config2 = {}) {
|
|
21392
|
+
const maxContextChars = config2.maxContextChars ?? DEFAULT_BUDGET.maxContextChars;
|
|
21393
|
+
const maxTotalContextChars = config2.maxTotalContextChars ?? DEFAULT_BUDGET.maxTotalContextChars;
|
|
21394
|
+
const feature = config2.feature;
|
|
21395
|
+
const truncationEvents = [];
|
|
21396
|
+
const namesOnlyFiles = [];
|
|
21397
|
+
if (files.length === 0) {
|
|
21398
|
+
return { files: [], truncationEvents: [] };
|
|
21399
|
+
}
|
|
21400
|
+
const budgetedFiles = [];
|
|
21401
|
+
let totalChars = 0;
|
|
21402
|
+
let switchedToNamesOnly = false;
|
|
21403
|
+
for (const file2 of files) {
|
|
21404
|
+
const pathHint = feature ? `.hive/features/${feature}/context/${file2.name}.md` : `context/${file2.name}.md`;
|
|
21405
|
+
if (totalChars >= maxTotalContextChars && !switchedToNamesOnly) {
|
|
21406
|
+
switchedToNamesOnly = true;
|
|
21407
|
+
truncationEvents.push({
|
|
21408
|
+
type: "context_names_only",
|
|
21409
|
+
message: `Switched to name-only listing after ${totalChars} chars (budget: ${maxTotalContextChars})`,
|
|
21410
|
+
affected: files.slice(files.indexOf(file2)).map((f) => f.name)
|
|
21411
|
+
});
|
|
21412
|
+
}
|
|
21413
|
+
if (switchedToNamesOnly) {
|
|
21414
|
+
namesOnlyFiles.push(file2.name);
|
|
21415
|
+
budgetedFiles.push({
|
|
21416
|
+
name: file2.name,
|
|
21417
|
+
content: `[Content available at: ${pathHint}]`,
|
|
21418
|
+
truncated: true,
|
|
21419
|
+
originalLength: file2.content.length,
|
|
21420
|
+
pathHint
|
|
21421
|
+
});
|
|
21422
|
+
continue;
|
|
21423
|
+
}
|
|
21424
|
+
const { result, truncated } = truncateWithMarker(file2.content, maxContextChars);
|
|
21425
|
+
if (truncated) {
|
|
21426
|
+
truncationEvents.push({
|
|
21427
|
+
type: "context_truncated",
|
|
21428
|
+
message: `Truncated context file "${file2.name}" from ${file2.content.length} to ${result.length} chars. Full content at: ${pathHint}`,
|
|
21429
|
+
affected: [file2.name]
|
|
21430
|
+
});
|
|
21431
|
+
}
|
|
21432
|
+
budgetedFiles.push({
|
|
21433
|
+
name: file2.name,
|
|
21434
|
+
content: result,
|
|
21435
|
+
truncated,
|
|
21436
|
+
originalLength: truncated ? file2.content.length : undefined,
|
|
21437
|
+
pathHint: truncated ? pathHint : undefined
|
|
21438
|
+
});
|
|
21439
|
+
totalChars += result.length;
|
|
21440
|
+
}
|
|
21441
|
+
return {
|
|
21442
|
+
files: budgetedFiles,
|
|
21443
|
+
truncationEvents,
|
|
21444
|
+
namesOnlyFiles: namesOnlyFiles.length > 0 ? namesOnlyFiles : undefined
|
|
21445
|
+
};
|
|
21446
|
+
}
|
|
21447
|
+
|
|
21448
|
+
// src/utils/prompt-file.ts
|
|
21449
|
+
import * as fs6 from "fs";
|
|
21450
|
+
import * as path5 from "path";
|
|
21451
|
+
function findWorkspaceRoot(startDir) {
|
|
21452
|
+
try {
|
|
21453
|
+
let current = path5.resolve(startDir);
|
|
21454
|
+
while (true) {
|
|
21455
|
+
const hivePath = path5.join(current, ".hive");
|
|
21456
|
+
if (fs6.existsSync(hivePath) && fs6.statSync(hivePath).isDirectory()) {
|
|
21457
|
+
return current;
|
|
21458
|
+
}
|
|
21459
|
+
const parent = path5.dirname(current);
|
|
21460
|
+
if (parent === current) {
|
|
21461
|
+
return null;
|
|
21462
|
+
}
|
|
21463
|
+
current = parent;
|
|
21464
|
+
}
|
|
21465
|
+
} catch {
|
|
21466
|
+
return null;
|
|
21467
|
+
}
|
|
21468
|
+
}
|
|
21469
|
+
function isValidPromptFilePath(filePath, workspaceRoot) {
|
|
21470
|
+
try {
|
|
21471
|
+
const normalizedFilePath = path5.resolve(filePath);
|
|
21472
|
+
const normalizedWorkspace = path5.resolve(workspaceRoot);
|
|
21473
|
+
if (!normalizedFilePath.startsWith(normalizedWorkspace + path5.sep) && normalizedFilePath !== normalizedWorkspace) {
|
|
21474
|
+
return false;
|
|
21475
|
+
}
|
|
21476
|
+
return true;
|
|
21477
|
+
} catch {
|
|
21478
|
+
return false;
|
|
21479
|
+
}
|
|
21480
|
+
}
|
|
21481
|
+
async function resolvePromptFromFile(promptFilePath, workspaceRoot) {
|
|
21482
|
+
if (!isValidPromptFilePath(promptFilePath, workspaceRoot)) {
|
|
21483
|
+
return {
|
|
21484
|
+
error: `Prompt file path "${promptFilePath}" is outside the workspace. ` + `Only files within "${workspaceRoot}" are allowed.`
|
|
21485
|
+
};
|
|
21486
|
+
}
|
|
21487
|
+
const resolvedPath = path5.resolve(promptFilePath);
|
|
21488
|
+
if (!fs6.existsSync(resolvedPath)) {
|
|
21489
|
+
return {
|
|
21490
|
+
error: `Prompt file not found: "${resolvedPath}"`
|
|
21491
|
+
};
|
|
21492
|
+
}
|
|
21493
|
+
try {
|
|
21494
|
+
const content = fs6.readFileSync(resolvedPath, "utf-8");
|
|
21495
|
+
return { content };
|
|
21496
|
+
} catch (err) {
|
|
21497
|
+
return {
|
|
21498
|
+
error: `Failed to read prompt file: ${err instanceof Error ? err.message : "Unknown error"}`
|
|
21499
|
+
};
|
|
21500
|
+
}
|
|
21501
|
+
}
|
|
21502
|
+
function writeWorkerPromptFile(feature, task, prompt, hiveDir) {
|
|
21503
|
+
const promptDir = path5.join(hiveDir, "features", feature, "tasks", task);
|
|
21504
|
+
const promptPath = path5.join(promptDir, "worker-prompt.md");
|
|
21505
|
+
if (!fs6.existsSync(promptDir)) {
|
|
21506
|
+
fs6.mkdirSync(promptDir, { recursive: true });
|
|
21507
|
+
}
|
|
21508
|
+
fs6.writeFileSync(promptPath, prompt, "utf-8");
|
|
21509
|
+
return promptPath;
|
|
21510
|
+
}
|
|
21511
|
+
|
|
20911
21512
|
// src/background/types.ts
|
|
20912
21513
|
var VALID_TRANSITIONS = {
|
|
20913
21514
|
spawned: ["pending", "running", "error", "cancelled"],
|
|
@@ -21232,7 +21833,7 @@ class ConcurrencyManager {
|
|
|
21232
21833
|
this.lastStartTimes.set(key, Date.now());
|
|
21233
21834
|
return;
|
|
21234
21835
|
}
|
|
21235
|
-
return new Promise((
|
|
21836
|
+
return new Promise((resolve2, reject) => {
|
|
21236
21837
|
const queue = this.queues.get(key) ?? [];
|
|
21237
21838
|
const entry = {
|
|
21238
21839
|
resolve: () => {
|
|
@@ -21241,7 +21842,7 @@ class ConcurrencyManager {
|
|
|
21241
21842
|
entry.settled = true;
|
|
21242
21843
|
clearTimeout(entry.timeoutId);
|
|
21243
21844
|
this.lastStartTimes.set(key, Date.now());
|
|
21244
|
-
|
|
21845
|
+
resolve2();
|
|
21245
21846
|
},
|
|
21246
21847
|
reject: (error45) => {
|
|
21247
21848
|
if (entry.settled)
|
|
@@ -21372,7 +21973,7 @@ class ConcurrencyManager {
|
|
|
21372
21973
|
const elapsed = Date.now() - lastStart;
|
|
21373
21974
|
const delay2 = this.config.minDelayBetweenStartsMs - elapsed;
|
|
21374
21975
|
if (delay2 > 0) {
|
|
21375
|
-
await new Promise((
|
|
21976
|
+
await new Promise((resolve2) => setTimeout(resolve2, delay2));
|
|
21376
21977
|
}
|
|
21377
21978
|
}
|
|
21378
21979
|
}
|
|
@@ -21700,6 +22301,7 @@ class BackgroundManager {
|
|
|
21700
22301
|
}
|
|
21701
22302
|
this.store.updateStatus(task.taskId, "running");
|
|
21702
22303
|
this.poller.start();
|
|
22304
|
+
const normalizedVariant = options.variant?.trim() || undefined;
|
|
21703
22305
|
this.client.session.prompt({
|
|
21704
22306
|
path: { id: sessionId },
|
|
21705
22307
|
body: {
|
|
@@ -21708,7 +22310,8 @@ class BackgroundManager {
|
|
|
21708
22310
|
tools: {
|
|
21709
22311
|
background_task: false,
|
|
21710
22312
|
delegate: false
|
|
21711
|
-
}
|
|
22313
|
+
},
|
|
22314
|
+
...normalizedVariant !== undefined && { variant: normalizedVariant }
|
|
21712
22315
|
}
|
|
21713
22316
|
}).catch((error45) => {
|
|
21714
22317
|
this.updateStatus(task.taskId, "error", { errorMessage: error45.message });
|
|
@@ -21883,8 +22486,58 @@ Use \`background_output({ task_id: "${task.taskId}" })\` to retrieve the result.
|
|
|
21883
22486
|
function createBackgroundManager(options) {
|
|
21884
22487
|
return new BackgroundManager(options);
|
|
21885
22488
|
}
|
|
22489
|
+
// src/utils/format.ts
|
|
22490
|
+
function formatElapsed(ms) {
|
|
22491
|
+
const totalSeconds = Math.max(0, Math.floor(ms / 1000));
|
|
22492
|
+
if (totalSeconds < 60) {
|
|
22493
|
+
return `${totalSeconds}s`;
|
|
22494
|
+
}
|
|
22495
|
+
const totalMinutes = Math.floor(totalSeconds / 60);
|
|
22496
|
+
const seconds = totalSeconds % 60;
|
|
22497
|
+
if (totalMinutes < 60) {
|
|
22498
|
+
return `${totalMinutes}m ${seconds}s`;
|
|
22499
|
+
}
|
|
22500
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
22501
|
+
const minutes = totalMinutes % 60;
|
|
22502
|
+
return `${hours}h ${minutes}m`;
|
|
22503
|
+
}
|
|
22504
|
+
function formatRelativeTime(isoDate) {
|
|
22505
|
+
const timestamp = new Date(isoDate).getTime();
|
|
22506
|
+
const now = Date.now();
|
|
22507
|
+
const elapsedMs = Math.max(0, now - timestamp);
|
|
22508
|
+
const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1000));
|
|
22509
|
+
if (totalSeconds < 60) {
|
|
22510
|
+
return `${totalSeconds}s ago`;
|
|
22511
|
+
}
|
|
22512
|
+
const totalMinutes = Math.floor(totalSeconds / 60);
|
|
22513
|
+
if (totalMinutes < 60) {
|
|
22514
|
+
return `${totalMinutes}m ago`;
|
|
22515
|
+
}
|
|
22516
|
+
const totalHours = Math.floor(totalMinutes / 60);
|
|
22517
|
+
return `${totalHours}h ago`;
|
|
22518
|
+
}
|
|
22519
|
+
|
|
22520
|
+
// src/hooks/variant-hook.ts
|
|
22521
|
+
var HIVE_AGENT_NAMES = [
|
|
22522
|
+
"hive-master",
|
|
22523
|
+
"architect-planner",
|
|
22524
|
+
"swarm-orchestrator",
|
|
22525
|
+
"scout-researcher",
|
|
22526
|
+
"forager-worker",
|
|
22527
|
+
"hygienic-reviewer"
|
|
22528
|
+
];
|
|
22529
|
+
function isHiveAgent(agent) {
|
|
22530
|
+
return agent !== undefined && HIVE_AGENT_NAMES.includes(agent);
|
|
22531
|
+
}
|
|
22532
|
+
function normalizeVariant(variant) {
|
|
22533
|
+
if (variant === undefined)
|
|
22534
|
+
return;
|
|
22535
|
+
const trimmed2 = variant.trim();
|
|
22536
|
+
return trimmed2.length > 0 ? trimmed2 : undefined;
|
|
22537
|
+
}
|
|
22538
|
+
|
|
21886
22539
|
// src/tools/background-tools.ts
|
|
21887
|
-
function createBackgroundTools(manager, client) {
|
|
22540
|
+
function createBackgroundTools(manager, client, configService) {
|
|
21888
22541
|
async function maybeFinalizeIfIdle(sessionId) {
|
|
21889
22542
|
try {
|
|
21890
22543
|
const statusFn = client.session.status;
|
|
@@ -21908,11 +22561,12 @@ function createBackgroundTools(manager, client) {
|
|
|
21908
22561
|
} catch {}
|
|
21909
22562
|
}
|
|
21910
22563
|
return {
|
|
21911
|
-
|
|
21912
|
-
description: "Spawn a background agent task.
|
|
22564
|
+
hive_background_task: tool({
|
|
22565
|
+
description: "Spawn a background agent task. Use sync=true to wait for completion (returns output). If sync=false (default), the parent session receives a completion <system-reminder> and you can call hive_background_output to fetch the result.",
|
|
21913
22566
|
args: {
|
|
21914
22567
|
agent: tool.schema.string().describe('Agent to use (e.g., "forager-worker", "scout-researcher")'),
|
|
21915
|
-
prompt: tool.schema.string().describe("Task instructions/prompt"),
|
|
22568
|
+
prompt: tool.schema.string().optional().describe("Task instructions/prompt (required if promptFile not provided)"),
|
|
22569
|
+
promptFile: tool.schema.string().optional().describe("Path to file containing prompt (alternative to inline prompt)"),
|
|
21916
22570
|
description: tool.schema.string().describe("Human-readable task description"),
|
|
21917
22571
|
sync: tool.schema.boolean().optional().describe("Wait for completion (default: false)"),
|
|
21918
22572
|
idempotencyKey: tool.schema.string().optional().describe("Key for safe retries"),
|
|
@@ -21924,6 +22578,7 @@ function createBackgroundTools(manager, client) {
|
|
|
21924
22578
|
async execute({
|
|
21925
22579
|
agent,
|
|
21926
22580
|
prompt,
|
|
22581
|
+
promptFile,
|
|
21927
22582
|
description,
|
|
21928
22583
|
sync = false,
|
|
21929
22584
|
idempotencyKey,
|
|
@@ -21933,9 +22588,41 @@ function createBackgroundTools(manager, client) {
|
|
|
21933
22588
|
attempt
|
|
21934
22589
|
}, toolContext) {
|
|
21935
22590
|
const ctx = toolContext;
|
|
22591
|
+
let resolvedPrompt = prompt;
|
|
22592
|
+
if (promptFile) {
|
|
22593
|
+
const baseDir = workdir || process.cwd();
|
|
22594
|
+
const workspaceRoot = findWorkspaceRoot(baseDir) ?? baseDir;
|
|
22595
|
+
const fileResult = await resolvePromptFromFile(promptFile, workspaceRoot);
|
|
22596
|
+
if (fileResult.error) {
|
|
22597
|
+
const output = {
|
|
22598
|
+
provider: "hive",
|
|
22599
|
+
task_id: "",
|
|
22600
|
+
session_id: "",
|
|
22601
|
+
status: "error",
|
|
22602
|
+
error: `Failed to read prompt file: ${fileResult.error}`
|
|
22603
|
+
};
|
|
22604
|
+
return JSON.stringify(output, null, 2);
|
|
22605
|
+
}
|
|
22606
|
+
resolvedPrompt = fileResult.content;
|
|
22607
|
+
}
|
|
22608
|
+
if (!resolvedPrompt) {
|
|
22609
|
+
const output = {
|
|
22610
|
+
provider: "hive",
|
|
22611
|
+
task_id: "",
|
|
22612
|
+
session_id: "",
|
|
22613
|
+
status: "error",
|
|
22614
|
+
error: "Either prompt or promptFile is required"
|
|
22615
|
+
};
|
|
22616
|
+
return JSON.stringify(output, null, 2);
|
|
22617
|
+
}
|
|
22618
|
+
let variant;
|
|
22619
|
+
if (configService && isHiveAgent(agent)) {
|
|
22620
|
+
const agentConfig = configService.getAgentConfig(agent);
|
|
22621
|
+
variant = normalizeVariant(agentConfig.variant);
|
|
22622
|
+
}
|
|
21936
22623
|
const result = await manager.spawn({
|
|
21937
22624
|
agent,
|
|
21938
|
-
prompt,
|
|
22625
|
+
prompt: resolvedPrompt,
|
|
21939
22626
|
description,
|
|
21940
22627
|
idempotencyKey,
|
|
21941
22628
|
workdir,
|
|
@@ -21946,7 +22633,8 @@ function createBackgroundTools(manager, client) {
|
|
|
21946
22633
|
hiveFeature: feature,
|
|
21947
22634
|
hiveTaskFolder: hiveTask,
|
|
21948
22635
|
sync,
|
|
21949
|
-
attempt
|
|
22636
|
+
attempt,
|
|
22637
|
+
variant
|
|
21950
22638
|
});
|
|
21951
22639
|
if (result.error) {
|
|
21952
22640
|
const output = {
|
|
@@ -22011,19 +22699,19 @@ function createBackgroundTools(manager, client) {
|
|
|
22011
22699
|
done: false
|
|
22012
22700
|
}, null, 2);
|
|
22013
22701
|
}
|
|
22014
|
-
await new Promise((
|
|
22702
|
+
await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
|
|
22015
22703
|
}
|
|
22016
22704
|
}
|
|
22017
22705
|
}),
|
|
22018
|
-
|
|
22019
|
-
description: "Get output from background task.
|
|
22706
|
+
hive_background_output: tool({
|
|
22707
|
+
description: "Get output from a background task. For sync=false tasks, wait for the completion <system-reminder> and then call with block=false to fetch the result; use block=true only when you need interim output. When blocking, pick a timeout based on task complexity (typically 30-120s).",
|
|
22020
22708
|
args: {
|
|
22021
22709
|
task_id: tool.schema.string().describe("Task ID to get output from"),
|
|
22022
22710
|
block: tool.schema.boolean().optional().describe("Block waiting for new output (default: false)"),
|
|
22023
|
-
timeout: tool.schema.number().optional().describe("Timeout in ms when blocking (default:
|
|
22711
|
+
timeout: tool.schema.number().optional().describe("Timeout in ms when blocking (default: 60000)"),
|
|
22024
22712
|
cursor: tool.schema.string().optional().describe("Cursor for incremental output (message count)")
|
|
22025
22713
|
},
|
|
22026
|
-
async execute({ task_id, block = false, timeout =
|
|
22714
|
+
async execute({ task_id, block = false, timeout = 60000, cursor }) {
|
|
22027
22715
|
const task = manager.getTask(task_id);
|
|
22028
22716
|
if (!task) {
|
|
22029
22717
|
return JSON.stringify({
|
|
@@ -22048,7 +22736,7 @@ function createBackgroundTools(manager, client) {
|
|
|
22048
22736
|
if (afterFinalize && isTerminalStatus(afterFinalize.status)) {
|
|
22049
22737
|
break;
|
|
22050
22738
|
}
|
|
22051
|
-
await new Promise((
|
|
22739
|
+
await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
|
|
22052
22740
|
}
|
|
22053
22741
|
}
|
|
22054
22742
|
const current = manager.getTask(task_id);
|
|
@@ -22070,6 +22758,21 @@ function createBackgroundTools(manager, client) {
|
|
|
22070
22758
|
}
|
|
22071
22759
|
const output = await getTaskOutput(client, finalized.sessionId, cursorCount);
|
|
22072
22760
|
const messageCount = finalized.progress?.messageCount ?? 0;
|
|
22761
|
+
const observationSnapshot = manager.getTaskObservation(task_id);
|
|
22762
|
+
const lastActivityAt = observationSnapshot?.lastActivityAt ?? null;
|
|
22763
|
+
const startedAt = finalized.startedAt ? new Date(finalized.startedAt).getTime() : Date.now();
|
|
22764
|
+
const elapsedMs = Date.now() - startedAt;
|
|
22765
|
+
const lastMessage = finalized.progress?.lastMessage;
|
|
22766
|
+
const lastMessagePreview = lastMessage ? `${lastMessage.slice(0, 200)}${lastMessage.length > 200 ? "..." : ""}` : null;
|
|
22767
|
+
const observation = {
|
|
22768
|
+
elapsedMs,
|
|
22769
|
+
elapsedFormatted: formatElapsed(elapsedMs),
|
|
22770
|
+
messageCount: observationSnapshot?.messageCount ?? 0,
|
|
22771
|
+
lastActivityAgo: lastActivityAt ? formatRelativeTime(lastActivityAt) : "never",
|
|
22772
|
+
lastActivityAt,
|
|
22773
|
+
lastMessagePreview,
|
|
22774
|
+
maybeStuck: observationSnapshot?.maybeStuck ?? false
|
|
22775
|
+
};
|
|
22073
22776
|
return JSON.stringify({
|
|
22074
22777
|
task_id: finalized.taskId,
|
|
22075
22778
|
session_id: finalized.sessionId,
|
|
@@ -22077,11 +22780,12 @@ function createBackgroundTools(manager, client) {
|
|
|
22077
22780
|
done: isTerminalStatus(finalized.status),
|
|
22078
22781
|
output,
|
|
22079
22782
|
cursor: messageCount.toString(),
|
|
22080
|
-
progress: finalized.progress
|
|
22783
|
+
progress: finalized.progress,
|
|
22784
|
+
observation
|
|
22081
22785
|
}, null, 2);
|
|
22082
22786
|
}
|
|
22083
22787
|
}),
|
|
22084
|
-
|
|
22788
|
+
hive_background_cancel: tool({
|
|
22085
22789
|
description: "Cancel running background task(s). Use all=true to cancel all tasks for current session.",
|
|
22086
22790
|
args: {
|
|
22087
22791
|
task_id: tool.schema.string().optional().describe("Specific task ID to cancel"),
|
|
@@ -22168,8 +22872,7 @@ async function getTaskOutput(client, sessionId, afterCount = 0) {
|
|
|
22168
22872
|
}
|
|
22169
22873
|
|
|
22170
22874
|
// src/index.ts
|
|
22171
|
-
function formatSkillsXml() {
|
|
22172
|
-
const skills = getBuiltinSkills();
|
|
22875
|
+
function formatSkillsXml(skills) {
|
|
22173
22876
|
if (skills.length === 0)
|
|
22174
22877
|
return "";
|
|
22175
22878
|
const skillsXml = skills.map((skill) => {
|
|
@@ -22188,21 +22891,27 @@ function formatSkillsXml() {
|
|
|
22188
22891
|
${skillsXml}
|
|
22189
22892
|
</available_skills>`;
|
|
22190
22893
|
}
|
|
22191
|
-
function createHiveSkillTool() {
|
|
22192
|
-
const base =
|
|
22193
|
-
const skills = getBuiltinSkills();
|
|
22194
|
-
const description = skills.length === 0 ? base + `
|
|
22894
|
+
function createHiveSkillTool(filteredSkills) {
|
|
22895
|
+
const base = `Load a Hive skill to get detailed instructions for a specific workflow.
|
|
22195
22896
|
|
|
22196
|
-
|
|
22897
|
+
Use this when a task matches an available skill's description. The descriptions below ("Use when...", "Use before...") are triggers; when one applies, you MUST load that skill before proceeding.`;
|
|
22898
|
+
const description = filteredSkills.length === 0 ? base + `
|
|
22899
|
+
|
|
22900
|
+
No Hive skills available.` : base + formatSkillsXml(filteredSkills);
|
|
22901
|
+
const availableNames = new Set(filteredSkills.map((s) => s.name));
|
|
22197
22902
|
return tool({
|
|
22198
22903
|
description,
|
|
22199
22904
|
args: {
|
|
22200
22905
|
name: tool.schema.string().describe("The skill name from available_skills")
|
|
22201
22906
|
},
|
|
22202
22907
|
async execute({ name }) {
|
|
22908
|
+
if (!availableNames.has(name)) {
|
|
22909
|
+
const available = filteredSkills.map((s) => s.name).join(", ");
|
|
22910
|
+
throw new Error(`Skill "${name}" not available. Available Hive skills: ${available || "none"}`);
|
|
22911
|
+
}
|
|
22203
22912
|
const result = loadBuiltinSkill(name);
|
|
22204
22913
|
if (!result.found || !result.skill) {
|
|
22205
|
-
const available =
|
|
22914
|
+
const available = filteredSkills.map((s) => s.name).join(", ");
|
|
22206
22915
|
throw new Error(`Skill "${name}" not found. Available Hive skills: ${available || "none"}`);
|
|
22207
22916
|
}
|
|
22208
22917
|
const skill = result.skill;
|
|
@@ -22266,12 +22975,19 @@ Use \`hive_merge\` to explicitly integrate changes. Worktrees persist until manu
|
|
|
22266
22975
|
**CRITICAL**: When resuming, a NEW worker spawns in the SAME worktree.
|
|
22267
22976
|
The previous worker's progress is preserved. Include the user's decision in the \`decision\` parameter.
|
|
22268
22977
|
|
|
22269
|
-
**
|
|
22978
|
+
**Observation Polling (Recommended):**
|
|
22979
|
+
- Prefer completion notifications over polling
|
|
22980
|
+
- Use \`hive_worker_status()\` for observation-based spot checks
|
|
22981
|
+
- Avoid tight loops with \`hive_background_output\`; if needed, wait 30-60s between checks
|
|
22982
|
+
- If you suspect notifications did not deliver, do a single \`hive_worker_status()\` check first
|
|
22983
|
+
- If you need final results, call \`hive_background_output({ task_id, block: false })\` after the completion notice
|
|
22984
|
+
|
|
22985
|
+
**For research**, use MCP tools or parallel exploration:
|
|
22270
22986
|
- \`grep_app_searchGitHub\` - Find code in OSS
|
|
22271
22987
|
- \`context7_query-docs\` - Library documentation
|
|
22272
22988
|
- \`websearch_web_search_exa\` - Web search via Exa
|
|
22273
22989
|
- \`ast_grep_search\` - AST-based search
|
|
22274
|
-
- \`
|
|
22990
|
+
- For exploratory fan-out, load \`hive_skill("parallel-exploration")\` and use \`hive_background_task(agent: "scout-researcher", sync: false, ...)\`
|
|
22275
22991
|
|
|
22276
22992
|
### Planning Phase - Context Management REQUIRED
|
|
22277
22993
|
|
|
@@ -22300,16 +23016,22 @@ var plugin = async (ctx) => {
|
|
|
22300
23016
|
const taskService = new TaskService(directory);
|
|
22301
23017
|
const contextService = new ContextService(directory);
|
|
22302
23018
|
const configService = new ConfigService;
|
|
22303
|
-
const
|
|
23019
|
+
const disabledMcps = configService.getDisabledMcps();
|
|
23020
|
+
const disabledSkills = configService.getDisabledSkills();
|
|
23021
|
+
const builtinMcps = createBuiltinMcps(disabledMcps);
|
|
23022
|
+
const filteredSkills = getFilteredSkills(disabledSkills);
|
|
23023
|
+
const effectiveAutoLoadSkills = configService.getAgentConfig("hive-master").autoLoadSkills ?? [];
|
|
22304
23024
|
const worktreeService = new WorktreeService({
|
|
22305
23025
|
baseDir: directory,
|
|
22306
|
-
hiveDir:
|
|
23026
|
+
hiveDir: path7.join(directory, ".hive")
|
|
22307
23027
|
});
|
|
22308
23028
|
const backgroundManager = createBackgroundManager({
|
|
22309
23029
|
client,
|
|
22310
23030
|
projectRoot: directory
|
|
22311
23031
|
});
|
|
22312
|
-
const
|
|
23032
|
+
const delegateMode = configService.getDelegateMode();
|
|
23033
|
+
const useHiveBackground = delegateMode === "hive";
|
|
23034
|
+
const backgroundTools = createBackgroundTools(backgroundManager, client, configService);
|
|
22313
23035
|
const isOmoSlimEnabled = () => {
|
|
22314
23036
|
return configService.isOmoSlimEnabled();
|
|
22315
23037
|
};
|
|
@@ -22334,10 +23056,10 @@ var plugin = async (ctx) => {
|
|
|
22334
23056
|
}
|
|
22335
23057
|
};
|
|
22336
23058
|
const checkBlocked = (feature) => {
|
|
22337
|
-
const
|
|
22338
|
-
const blockedPath =
|
|
22339
|
-
if (
|
|
22340
|
-
const reason =
|
|
23059
|
+
const fs11 = __require("fs");
|
|
23060
|
+
const blockedPath = path7.join(directory, ".hive", "features", feature, "BLOCKED");
|
|
23061
|
+
if (fs11.existsSync(blockedPath)) {
|
|
23062
|
+
const reason = fs11.readFileSync(blockedPath, "utf-8").trim();
|
|
22341
23063
|
return `⛔ BLOCKED by Beekeeper
|
|
22342
23064
|
|
|
22343
23065
|
${reason || "(No reason provided)"}
|
|
@@ -22348,8 +23070,24 @@ To unblock: Remove .hive/features/${feature}/BLOCKED`;
|
|
|
22348
23070
|
return null;
|
|
22349
23071
|
};
|
|
22350
23072
|
return {
|
|
22351
|
-
"experimental.chat.system.transform": async (
|
|
23073
|
+
"experimental.chat.system.transform": async (input, output) => {
|
|
22352
23074
|
output.system.push(HIVE_SYSTEM_PROMPT);
|
|
23075
|
+
const agentInput = input;
|
|
23076
|
+
const agentName = agentInput?.agent;
|
|
23077
|
+
if (agentName && isHiveAgent(agentName)) {
|
|
23078
|
+
const agentConfig = configService.getAgentConfig(agentName);
|
|
23079
|
+
const autoLoadSkills = agentConfig.autoLoadSkills ?? [];
|
|
23080
|
+
if (autoLoadSkills.length > 0) {
|
|
23081
|
+
for (const skillId of autoLoadSkills) {
|
|
23082
|
+
const skill = BUILTIN_SKILLS.find((entry) => entry.name === skillId);
|
|
23083
|
+
if (!skill) {
|
|
23084
|
+
console.warn("Unknown skill id", skillId);
|
|
23085
|
+
continue;
|
|
23086
|
+
}
|
|
23087
|
+
output.system.push(skill.template);
|
|
23088
|
+
}
|
|
23089
|
+
}
|
|
23090
|
+
}
|
|
22353
23091
|
const activeFeature = resolveFeature();
|
|
22354
23092
|
if (activeFeature) {
|
|
22355
23093
|
const info = featureService.getInfo(activeFeature);
|
|
@@ -22369,12 +23107,28 @@ To unblock: Remove .hive/features/${feature}/BLOCKED`;
|
|
|
22369
23107
|
}
|
|
22370
23108
|
}
|
|
22371
23109
|
},
|
|
23110
|
+
"chat.message": async (input, output) => {
|
|
23111
|
+
const { agent } = input;
|
|
23112
|
+
if (!agent)
|
|
23113
|
+
return;
|
|
23114
|
+
if (!isHiveAgent(agent))
|
|
23115
|
+
return;
|
|
23116
|
+
if (output.message.variant !== undefined)
|
|
23117
|
+
return;
|
|
23118
|
+
const agentConfig = configService.getAgentConfig(agent);
|
|
23119
|
+
const configuredVariant = normalizeVariant(agentConfig.variant);
|
|
23120
|
+
if (configuredVariant !== undefined) {
|
|
23121
|
+
output.message.variant = configuredVariant;
|
|
23122
|
+
}
|
|
23123
|
+
},
|
|
22372
23124
|
mcp: builtinMcps,
|
|
22373
23125
|
tool: {
|
|
22374
|
-
hive_skill: createHiveSkillTool(),
|
|
22375
|
-
|
|
22376
|
-
|
|
22377
|
-
|
|
23126
|
+
hive_skill: createHiveSkillTool(filteredSkills),
|
|
23127
|
+
...useHiveBackground && {
|
|
23128
|
+
hive_background_task: backgroundTools.hive_background_task,
|
|
23129
|
+
hive_background_output: backgroundTools.hive_background_output,
|
|
23130
|
+
hive_background_cancel: backgroundTools.hive_background_cancel
|
|
23131
|
+
},
|
|
22378
23132
|
hive_feature_create: tool({
|
|
22379
23133
|
description: "Create a new feature and set it as active",
|
|
22380
23134
|
args: {
|
|
@@ -22455,8 +23209,8 @@ NEXT: Ask your first clarifying question about this feature.`;
|
|
|
22455
23209
|
constraint: tool.schema.string().optional().describe("Never/Always rule derived")
|
|
22456
23210
|
},
|
|
22457
23211
|
async execute({ feature, trouble, resolution, constraint }) {
|
|
22458
|
-
const journalPath =
|
|
22459
|
-
if (!
|
|
23212
|
+
const journalPath = path7.join(directory, ".hive", "journal.md");
|
|
23213
|
+
if (!fs9.existsSync(journalPath)) {
|
|
22460
23214
|
return `Error: journal.md not found. Create a feature first to initialize the journal.`;
|
|
22461
23215
|
}
|
|
22462
23216
|
const date5 = new Date().toISOString().split("T")[0];
|
|
@@ -22470,7 +23224,7 @@ ${constraint ? `**Constraint**: ${constraint}` : ""}
|
|
|
22470
23224
|
|
|
22471
23225
|
---
|
|
22472
23226
|
`;
|
|
22473
|
-
|
|
23227
|
+
fs9.appendFileSync(journalPath, entry);
|
|
22474
23228
|
return `Journal entry added for ${feature}. ${constraint ? `Constraint: "${constraint}"` : ""}`;
|
|
22475
23229
|
}
|
|
22476
23230
|
}),
|
|
@@ -22625,9 +23379,29 @@ Reminder: start work with hive_exec_start to use its worktree, and ensure any su
|
|
|
22625
23379
|
baseCommit: worktree.commit
|
|
22626
23380
|
});
|
|
22627
23381
|
const planResult = planService.read(feature);
|
|
22628
|
-
const contextCompiled = contextService.compile(feature);
|
|
22629
23382
|
const allTasks = taskService.list(feature);
|
|
22630
|
-
const
|
|
23383
|
+
const rawContextFiles = contextService.list(feature).map((f) => ({
|
|
23384
|
+
name: f.name,
|
|
23385
|
+
content: f.content
|
|
23386
|
+
}));
|
|
23387
|
+
const rawPreviousTasks = allTasks.filter((t) => t.status === "done" && t.summary).map((t) => ({ name: t.folder, summary: t.summary }));
|
|
23388
|
+
const taskBudgetResult = applyTaskBudget(rawPreviousTasks, { ...DEFAULT_BUDGET, feature });
|
|
23389
|
+
const contextBudgetResult = applyContextBudget(rawContextFiles, { ...DEFAULT_BUDGET, feature });
|
|
23390
|
+
const contextFiles = contextBudgetResult.files.map((f) => ({
|
|
23391
|
+
name: f.name,
|
|
23392
|
+
content: f.content
|
|
23393
|
+
}));
|
|
23394
|
+
const previousTasks = taskBudgetResult.tasks.map((t) => ({
|
|
23395
|
+
name: t.name,
|
|
23396
|
+
summary: t.summary
|
|
23397
|
+
}));
|
|
23398
|
+
const truncationEvents = [
|
|
23399
|
+
...taskBudgetResult.truncationEvents,
|
|
23400
|
+
...contextBudgetResult.truncationEvents
|
|
23401
|
+
];
|
|
23402
|
+
const priorTasksFormatted = previousTasks.map((t) => `- ${t.name}: ${t.summary}`).join(`
|
|
23403
|
+
`);
|
|
23404
|
+
const droppedTasksHint = taskBudgetResult.droppedTasksHint;
|
|
22631
23405
|
let specContent = `# Task: ${task}
|
|
22632
23406
|
|
|
22633
23407
|
`;
|
|
@@ -22654,32 +23428,28 @@ ${taskMatch[0].trim()}
|
|
|
22654
23428
|
`;
|
|
22655
23429
|
}
|
|
22656
23430
|
}
|
|
22657
|
-
if (
|
|
23431
|
+
if (contextFiles.length > 0) {
|
|
23432
|
+
const contextCompiled = contextFiles.map((f) => `## ${f.name}
|
|
23433
|
+
|
|
23434
|
+
${f.content}`).join(`
|
|
23435
|
+
|
|
23436
|
+
---
|
|
23437
|
+
|
|
23438
|
+
`);
|
|
22658
23439
|
specContent += `## Context
|
|
22659
23440
|
|
|
22660
23441
|
${contextCompiled}
|
|
22661
23442
|
|
|
22662
23443
|
`;
|
|
22663
23444
|
}
|
|
22664
|
-
if (
|
|
23445
|
+
if (priorTasksFormatted) {
|
|
22665
23446
|
specContent += `## Completed Tasks
|
|
22666
23447
|
|
|
22667
|
-
${
|
|
22668
|
-
`)}
|
|
23448
|
+
${priorTasksFormatted}
|
|
22669
23449
|
|
|
22670
23450
|
`;
|
|
22671
23451
|
}
|
|
22672
23452
|
taskService.writeSpec(feature, task, specContent);
|
|
22673
|
-
const contextFiles = [];
|
|
22674
|
-
const contextDir = path5.join(directory, ".hive", "features", feature, "context");
|
|
22675
|
-
if (fs6.existsSync(contextDir)) {
|
|
22676
|
-
const files = fs6.readdirSync(contextDir).filter((f) => f.endsWith(".md"));
|
|
22677
|
-
for (const file2 of files) {
|
|
22678
|
-
const content = fs6.readFileSync(path5.join(contextDir, file2), "utf-8");
|
|
22679
|
-
contextFiles.push({ name: file2, content });
|
|
22680
|
-
}
|
|
22681
|
-
}
|
|
22682
|
-
const previousTasks = allTasks.filter((t) => t.status === "done" && t.summary).map((t) => ({ name: t.folder, summary: t.summary }));
|
|
22683
23453
|
const workerPrompt = buildWorkerPrompt({
|
|
22684
23454
|
feature,
|
|
22685
23455
|
task,
|
|
@@ -22701,59 +23471,107 @@ ${priorTasks.join(`
|
|
|
22701
23471
|
const attempt = (rawStatus?.workerSession?.attempt || 0) + 1;
|
|
22702
23472
|
const idempotencyKey = `hive-${feature}-${task}-${attempt}`;
|
|
22703
23473
|
taskService.patchBackgroundFields(feature, task, { idempotencyKey });
|
|
22704
|
-
|
|
22705
|
-
worktreePath: worktree.path,
|
|
22706
|
-
branch: worktree.branch,
|
|
22707
|
-
mode: "delegate",
|
|
22708
|
-
agent,
|
|
22709
|
-
delegationRequired: true,
|
|
22710
|
-
backgroundTaskCall: {
|
|
22711
|
-
agent,
|
|
22712
|
-
prompt: workerPrompt,
|
|
22713
|
-
description: `Hive: ${task}`,
|
|
22714
|
-
sync: false,
|
|
22715
|
-
workdir: worktree.path,
|
|
22716
|
-
idempotencyKey,
|
|
22717
|
-
feature,
|
|
22718
|
-
task,
|
|
22719
|
-
attempt
|
|
22720
|
-
},
|
|
22721
|
-
instructions: `## Delegation Required
|
|
23474
|
+
const contextContent = contextFiles.map((f) => f.content).join(`
|
|
22722
23475
|
|
|
22723
|
-
|
|
23476
|
+
`);
|
|
23477
|
+
const previousTasksContent = previousTasks.map((t) => `- **${t.name}**: ${t.summary}`).join(`
|
|
23478
|
+
`);
|
|
23479
|
+
const promptMeta = calculatePromptMeta({
|
|
23480
|
+
plan: planResult?.content || "",
|
|
23481
|
+
context: contextContent,
|
|
23482
|
+
previousTasks: previousTasksContent,
|
|
23483
|
+
spec: specContent,
|
|
23484
|
+
workerPrompt
|
|
23485
|
+
});
|
|
23486
|
+
const hiveDir = path7.join(directory, ".hive");
|
|
23487
|
+
const workerPromptPath = writeWorkerPromptFile(feature, task, workerPrompt, hiveDir);
|
|
23488
|
+
const relativePromptPath = path7.relative(directory, workerPromptPath);
|
|
23489
|
+
const PREVIEW_MAX_LENGTH = 200;
|
|
23490
|
+
const workerPromptPreview = workerPrompt.length > PREVIEW_MAX_LENGTH ? workerPrompt.slice(0, PREVIEW_MAX_LENGTH) + "..." : workerPrompt;
|
|
23491
|
+
const hiveBackgroundInstructions = `## Delegation Required
|
|
23492
|
+
|
|
23493
|
+
Call the hive_background_task tool to spawn a Forager (Worker/Coder) worker.
|
|
23494
|
+
|
|
23495
|
+
\`backgroundTaskCall\` contains the canonical tool arguments.
|
|
23496
|
+
|
|
23497
|
+
- Add \`sync: true\` if you need the result in this session.
|
|
23498
|
+
- Otherwise omit \`sync\`. Wait for the completion notification (no polling required). After the <system-reminder> arrives, call \`hive_background_output({ task_id: "<id>", block: false })\` once to fetch the final result.
|
|
23499
|
+
|
|
23500
|
+
Troubleshooting: if you see "Unknown parameter: workdir", your hive_background_task tool is not Hive's provider. Ensure agent-hive loads after other background_* tool providers, then re-run hive_exec_start.`;
|
|
23501
|
+
const taskToolInstructions = `## Delegation Required
|
|
23502
|
+
|
|
23503
|
+
Use OpenCode's built-in \`task\` tool to spawn a Forager (Worker/Coder) worker.
|
|
22724
23504
|
|
|
22725
23505
|
\`\`\`
|
|
22726
|
-
|
|
22727
|
-
|
|
22728
|
-
prompt: <the workerPrompt below>,
|
|
23506
|
+
task({
|
|
23507
|
+
subagent_type: "${agent}",
|
|
22729
23508
|
description: "Hive: ${task}",
|
|
22730
|
-
|
|
22731
|
-
workdir: "${worktree.path}",
|
|
22732
|
-
idempotencyKey: "${idempotencyKey}",
|
|
22733
|
-
feature: "${feature}",
|
|
22734
|
-
task: "${task}",
|
|
22735
|
-
attempt: ${attempt}
|
|
23509
|
+
prompt: <read the file at ${relativePromptPath}>
|
|
22736
23510
|
})
|
|
22737
23511
|
\`\`\`
|
|
22738
23512
|
|
|
22739
|
-
|
|
22740
|
-
- Monitor with hive_worker_status
|
|
22741
|
-
- Handle blockers when worker exits
|
|
22742
|
-
- Merge completed work with hive_merge
|
|
22743
|
-
|
|
22744
|
-
DO NOT do the work yourself. Delegate it.
|
|
22745
|
-
|
|
22746
|
-
## Troubleshooting
|
|
23513
|
+
Read the prompt file at \`${relativePromptPath}\` and pass its content to the task tool.
|
|
22747
23514
|
|
|
22748
|
-
|
|
22749
|
-
|
|
22750
|
-
|
|
22751
|
-
|
|
22752
|
-
|
|
22753
|
-
|
|
22754
|
-
|
|
22755
|
-
|
|
22756
|
-
|
|
23515
|
+
Note: delegateMode is set to 'task' in agent_hive.json. To use Hive's background tools instead, set delegateMode to 'hive'.`;
|
|
23516
|
+
const delegationInstructions = useHiveBackground ? hiveBackgroundInstructions : taskToolInstructions;
|
|
23517
|
+
const responseBase = {
|
|
23518
|
+
worktreePath: worktree.path,
|
|
23519
|
+
branch: worktree.branch,
|
|
23520
|
+
mode: "delegate",
|
|
23521
|
+
delegateMode,
|
|
23522
|
+
agent,
|
|
23523
|
+
delegationRequired: true,
|
|
23524
|
+
workerPromptPath: relativePromptPath,
|
|
23525
|
+
workerPromptPreview,
|
|
23526
|
+
...useHiveBackground && {
|
|
23527
|
+
backgroundTaskCall: {
|
|
23528
|
+
promptFile: workerPromptPath,
|
|
23529
|
+
description: `Hive: ${task}`,
|
|
23530
|
+
workdir: worktree.path,
|
|
23531
|
+
idempotencyKey,
|
|
23532
|
+
feature,
|
|
23533
|
+
task,
|
|
23534
|
+
attempt
|
|
23535
|
+
}
|
|
23536
|
+
},
|
|
23537
|
+
...!useHiveBackground && {
|
|
23538
|
+
taskToolCall: {
|
|
23539
|
+
subagent_type: agent,
|
|
23540
|
+
description: `Hive: ${task}`,
|
|
23541
|
+
promptFile: relativePromptPath
|
|
23542
|
+
}
|
|
23543
|
+
},
|
|
23544
|
+
instructions: delegationInstructions
|
|
23545
|
+
};
|
|
23546
|
+
const jsonPayload = JSON.stringify(responseBase, null, 2);
|
|
23547
|
+
const payloadMeta = calculatePayloadMeta({
|
|
23548
|
+
jsonPayload,
|
|
23549
|
+
promptInlined: false,
|
|
23550
|
+
promptReferencedByFile: true
|
|
23551
|
+
});
|
|
23552
|
+
const sizeWarnings = checkWarnings(promptMeta, payloadMeta);
|
|
23553
|
+
const budgetWarnings = truncationEvents.map((event) => ({
|
|
23554
|
+
type: event.type,
|
|
23555
|
+
severity: "info",
|
|
23556
|
+
message: event.message,
|
|
23557
|
+
affected: event.affected,
|
|
23558
|
+
count: event.count
|
|
23559
|
+
}));
|
|
23560
|
+
const allWarnings = [...sizeWarnings, ...budgetWarnings];
|
|
23561
|
+
return JSON.stringify({
|
|
23562
|
+
...responseBase,
|
|
23563
|
+
promptMeta,
|
|
23564
|
+
payloadMeta,
|
|
23565
|
+
budgetApplied: {
|
|
23566
|
+
maxTasks: DEFAULT_BUDGET.maxTasks,
|
|
23567
|
+
maxSummaryChars: DEFAULT_BUDGET.maxSummaryChars,
|
|
23568
|
+
maxContextChars: DEFAULT_BUDGET.maxContextChars,
|
|
23569
|
+
maxTotalContextChars: DEFAULT_BUDGET.maxTotalContextChars,
|
|
23570
|
+
tasksIncluded: previousTasks.length,
|
|
23571
|
+
tasksDropped: rawPreviousTasks.length - previousTasks.length,
|
|
23572
|
+
droppedTasksHint
|
|
23573
|
+
},
|
|
23574
|
+
warnings: allWarnings.length > 0 ? allWarnings : undefined
|
|
22757
23575
|
}, null, 2);
|
|
22758
23576
|
}
|
|
22759
23577
|
}),
|
|
@@ -22880,6 +23698,7 @@ Use hive_merge to integrate changes. Worktree preserved at ${worktree?.path || "
|
|
|
22880
23698
|
const STUCK_THRESHOLD = 10 * 60 * 1000;
|
|
22881
23699
|
const HEARTBEAT_STALE_THRESHOLD = 5 * 60 * 1000;
|
|
22882
23700
|
const now = Date.now();
|
|
23701
|
+
const PREVIEW_MAX_LENGTH = 200;
|
|
22883
23702
|
const tasks = taskService.list(feature);
|
|
22884
23703
|
const inProgressTasks = tasks.filter((t) => (t.status === "in_progress" || t.status === "blocked") && (!specificTask || t.folder === specificTask));
|
|
22885
23704
|
if (inProgressTasks.length === 0) {
|
|
@@ -22889,9 +23708,13 @@ Use hive_merge to integrate changes. Worktree preserved at ${worktree?.path || "
|
|
|
22889
23708
|
const worktree = await worktreeService.get(feature, t.folder);
|
|
22890
23709
|
const rawStatus = taskService.getRawStatus(feature, t.folder);
|
|
22891
23710
|
const workerSession = rawStatus?.workerSession;
|
|
23711
|
+
const backgroundRecord = backgroundManager.getTaskByHiveTask(feature, t.folder);
|
|
23712
|
+
const observation = backgroundRecord ? backgroundManager.getTaskObservation(backgroundRecord.taskId) : null;
|
|
22892
23713
|
let maybeStuck = false;
|
|
22893
23714
|
let lastActivityAt = null;
|
|
22894
|
-
if (
|
|
23715
|
+
if (observation?.lastActivityAt) {
|
|
23716
|
+
lastActivityAt = new Date(observation.lastActivityAt).getTime();
|
|
23717
|
+
} else if (workerSession?.lastHeartbeatAt) {
|
|
22895
23718
|
lastActivityAt = new Date(workerSession.lastHeartbeatAt).getTime();
|
|
22896
23719
|
const heartbeatStale = now - lastActivityAt > HEARTBEAT_STALE_THRESHOLD;
|
|
22897
23720
|
const noRecentMessages = !workerSession.messageCount || workerSession.messageCount === 0;
|
|
@@ -22900,10 +23723,23 @@ Use hive_merge to integrate changes. Worktree preserved at ${worktree?.path || "
|
|
|
22900
23723
|
lastActivityAt = new Date(rawStatus.startedAt).getTime();
|
|
22901
23724
|
maybeStuck = now - lastActivityAt > STUCK_THRESHOLD && t.status === "in_progress";
|
|
22902
23725
|
}
|
|
23726
|
+
if (typeof observation?.maybeStuck === "boolean") {
|
|
23727
|
+
maybeStuck = observation.maybeStuck;
|
|
23728
|
+
}
|
|
23729
|
+
const startedAtIso = backgroundRecord?.startedAt || rawStatus?.startedAt || null;
|
|
23730
|
+
const startedAtMs = startedAtIso ? new Date(startedAtIso).getTime() : null;
|
|
23731
|
+
const elapsedMs = startedAtMs ? Math.max(0, now - startedAtMs) : 0;
|
|
23732
|
+
const lastActivityIso = observation?.lastActivityAt || workerSession?.lastHeartbeatAt || rawStatus?.startedAt || null;
|
|
23733
|
+
const lastActivityAgo = lastActivityIso ? formatRelativeTime(lastActivityIso) : "never";
|
|
23734
|
+
const messageCount = observation?.messageCount ?? backgroundRecord?.progress?.messageCount ?? workerSession?.messageCount ?? 0;
|
|
23735
|
+
const lastMessagePreview = backgroundRecord?.progress?.lastMessage ? backgroundRecord.progress.lastMessage.slice(0, PREVIEW_MAX_LENGTH) : null;
|
|
22903
23736
|
return {
|
|
22904
23737
|
task: t.folder,
|
|
22905
23738
|
name: t.name,
|
|
22906
23739
|
status: t.status,
|
|
23740
|
+
taskId: backgroundRecord?.taskId || workerSession?.taskId || null,
|
|
23741
|
+
description: backgroundRecord?.description || null,
|
|
23742
|
+
startedAt: startedAtIso,
|
|
22907
23743
|
workerSession: workerSession || null,
|
|
22908
23744
|
sessionId: workerSession?.sessionId || null,
|
|
22909
23745
|
agent: workerSession?.agent || "inline",
|
|
@@ -22915,16 +23751,33 @@ Use hive_merge to integrate changes. Worktree preserved at ${worktree?.path || "
|
|
|
22915
23751
|
worktreePath: worktree?.path || null,
|
|
22916
23752
|
branch: worktree?.branch || null,
|
|
22917
23753
|
maybeStuck,
|
|
23754
|
+
activity: {
|
|
23755
|
+
elapsedMs,
|
|
23756
|
+
elapsedFormatted: formatElapsed(elapsedMs),
|
|
23757
|
+
messageCount,
|
|
23758
|
+
lastActivityAgo,
|
|
23759
|
+
lastMessagePreview,
|
|
23760
|
+
maybeStuck
|
|
23761
|
+
},
|
|
22918
23762
|
blocker: rawStatus?.blocker || null,
|
|
22919
23763
|
summary: t.summary || null
|
|
22920
23764
|
};
|
|
22921
23765
|
}));
|
|
23766
|
+
const stuckWorkers = workers.filter((worker) => worker.activity?.maybeStuck).length;
|
|
23767
|
+
const hint = workers.some((w) => w.status === "blocked") ? 'Use hive_exec_start(task, continueFrom: "blocked", decision: answer) to resume blocked workers' : workers.some((w) => w.maybeStuck) ? "Some workers may be stuck. Use hive_background_output({ task_id }) to check output, or abort with hive_exec_abort." : "Workers in progress. Wait for the completion notification (no polling required). Use hive_worker_status for spot checks; use hive_background_output only if interim output is explicitly needed.";
|
|
23768
|
+
const guidance = stuckWorkers > 0 ? `
|
|
23769
|
+
|
|
23770
|
+
⚠️ ${stuckWorkers} worker(s) may be stuck (no activity for 10+ minutes). Consider cancelling or investigating.` : "";
|
|
22922
23771
|
return JSON.stringify({
|
|
22923
23772
|
feature,
|
|
23773
|
+
delegateMode,
|
|
22924
23774
|
omoSlimEnabled: isOmoSlimEnabled(),
|
|
22925
|
-
backgroundTaskProvider: "hive",
|
|
23775
|
+
backgroundTaskProvider: useHiveBackground ? "hive" : "task",
|
|
22926
23776
|
workers,
|
|
22927
|
-
|
|
23777
|
+
summary: {
|
|
23778
|
+
stuckWorkers
|
|
23779
|
+
},
|
|
23780
|
+
hint: hint + guidance
|
|
22928
23781
|
}, null, 2);
|
|
22929
23782
|
}
|
|
22930
23783
|
}),
|
|
@@ -23095,12 +23948,12 @@ Files changed: ${result.filesChanged?.length || 0}`;
|
|
|
23095
23948
|
const feature = resolveFeature(explicitFeature);
|
|
23096
23949
|
if (!feature)
|
|
23097
23950
|
return "Error: No feature specified.";
|
|
23098
|
-
const taskDir =
|
|
23099
|
-
if (!
|
|
23951
|
+
const taskDir = path7.join(directory, ".hive", "features", feature, "tasks", task);
|
|
23952
|
+
if (!fs9.existsSync(taskDir)) {
|
|
23100
23953
|
return `Error: Task '${task}' not found in feature '${feature}'`;
|
|
23101
23954
|
}
|
|
23102
|
-
const reportPath =
|
|
23103
|
-
const existingReport =
|
|
23955
|
+
const reportPath = path7.join(taskDir, "report.md");
|
|
23956
|
+
const existingReport = fs9.existsSync(reportPath) ? fs9.readFileSync(reportPath, "utf-8") : `# Task Report
|
|
23104
23957
|
`;
|
|
23105
23958
|
const attemptCount = (existingReport.match(/## Attempt \d+/g) || []).length + 1;
|
|
23106
23959
|
const timestamp = new Date().toISOString();
|
|
@@ -23114,9 +23967,9 @@ Files changed: ${result.filesChanged?.length || 0}`;
|
|
|
23114
23967
|
${summary}
|
|
23115
23968
|
|
|
23116
23969
|
`;
|
|
23117
|
-
|
|
23118
|
-
const pendingPath =
|
|
23119
|
-
|
|
23970
|
+
fs9.writeFileSync(reportPath, newContent);
|
|
23971
|
+
const pendingPath = path7.join(taskDir, "PENDING_REVIEW");
|
|
23972
|
+
fs9.writeFileSync(pendingPath, JSON.stringify({
|
|
23120
23973
|
attempt: attemptCount,
|
|
23121
23974
|
requestedAt: timestamp,
|
|
23122
23975
|
summary: summary.substring(0, 200) + (summary.length > 200 ? "..." : "")
|
|
@@ -23124,18 +23977,18 @@ ${summary}
|
|
|
23124
23977
|
const pollInterval = 2000;
|
|
23125
23978
|
const maxWait = 30 * 60 * 1000;
|
|
23126
23979
|
const startTime = Date.now();
|
|
23127
|
-
while (
|
|
23980
|
+
while (fs9.existsSync(pendingPath)) {
|
|
23128
23981
|
if (Date.now() - startTime > maxWait) {
|
|
23129
23982
|
return "Review timed out after 30 minutes. Human did not respond.";
|
|
23130
23983
|
}
|
|
23131
|
-
await new Promise((
|
|
23984
|
+
await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
|
|
23132
23985
|
}
|
|
23133
|
-
const resultPath =
|
|
23134
|
-
if (!
|
|
23986
|
+
const resultPath = path7.join(taskDir, "REVIEW_RESULT");
|
|
23987
|
+
if (!fs9.existsSync(resultPath)) {
|
|
23135
23988
|
return "Review cancelled (PENDING_REVIEW removed but no REVIEW_RESULT).";
|
|
23136
23989
|
}
|
|
23137
|
-
const result =
|
|
23138
|
-
|
|
23990
|
+
const result = fs9.readFileSync(resultPath, "utf-8").trim();
|
|
23991
|
+
fs9.appendFileSync(reportPath, `### Review Result
|
|
23139
23992
|
|
|
23140
23993
|
${result}
|
|
23141
23994
|
|
|
@@ -23198,7 +24051,10 @@ Make the requested changes, then call hive_request_review again.`;
|
|
|
23198
24051
|
question: "allow",
|
|
23199
24052
|
skill: "allow",
|
|
23200
24053
|
todowrite: "allow",
|
|
23201
|
-
todoread: "allow"
|
|
24054
|
+
todoread: "allow",
|
|
24055
|
+
hive_background_task: "allow",
|
|
24056
|
+
hive_background_output: "allow",
|
|
24057
|
+
hive_background_cancel: "allow"
|
|
23202
24058
|
}
|
|
23203
24059
|
};
|
|
23204
24060
|
const architectUserConfig = configService.getAgentConfig("architect-planner");
|
|
@@ -23214,7 +24070,10 @@ Make the requested changes, then call hive_request_review again.`;
|
|
|
23214
24070
|
skill: "allow",
|
|
23215
24071
|
todowrite: "allow",
|
|
23216
24072
|
todoread: "allow",
|
|
23217
|
-
webfetch: "allow"
|
|
24073
|
+
webfetch: "allow",
|
|
24074
|
+
hive_background_task: "allow",
|
|
24075
|
+
hive_background_output: "allow",
|
|
24076
|
+
hive_background_cancel: "allow"
|
|
23218
24077
|
}
|
|
23219
24078
|
};
|
|
23220
24079
|
const swarmUserConfig = configService.getAgentConfig("swarm-orchestrator");
|
|
@@ -23227,7 +24086,10 @@ Make the requested changes, then call hive_request_review again.`;
|
|
|
23227
24086
|
question: "allow",
|
|
23228
24087
|
skill: "allow",
|
|
23229
24088
|
todowrite: "allow",
|
|
23230
|
-
todoread: "allow"
|
|
24089
|
+
todoread: "allow",
|
|
24090
|
+
hive_background_task: "allow",
|
|
24091
|
+
hive_background_output: "allow",
|
|
24092
|
+
hive_background_cancel: "allow"
|
|
23231
24093
|
}
|
|
23232
24094
|
};
|
|
23233
24095
|
const scoutUserConfig = configService.getAgentConfig("scout-researcher");
|
|
@@ -23266,15 +24128,18 @@ Make the requested changes, then call hive_request_review again.`;
|
|
|
23266
24128
|
skill: "allow"
|
|
23267
24129
|
}
|
|
23268
24130
|
};
|
|
23269
|
-
const
|
|
23270
|
-
|
|
23271
|
-
|
|
23272
|
-
|
|
23273
|
-
"
|
|
23274
|
-
|
|
23275
|
-
"
|
|
23276
|
-
|
|
23277
|
-
|
|
24131
|
+
const hiveConfigData = configService.get();
|
|
24132
|
+
const agentMode = hiveConfigData.agentMode ?? "unified";
|
|
24133
|
+
const allAgents = {};
|
|
24134
|
+
if (agentMode === "unified") {
|
|
24135
|
+
allAgents["hive-master"] = hiveConfig;
|
|
24136
|
+
} else {
|
|
24137
|
+
allAgents["architect-planner"] = architectConfig;
|
|
24138
|
+
allAgents["swarm-orchestrator"] = swarmConfig;
|
|
24139
|
+
allAgents["scout-researcher"] = scoutConfig;
|
|
24140
|
+
allAgents["forager-worker"] = foragerConfig;
|
|
24141
|
+
allAgents["hygienic-reviewer"] = hygienicConfig;
|
|
24142
|
+
}
|
|
23278
24143
|
const configAgent = opencodeConfig.agent;
|
|
23279
24144
|
if (!configAgent) {
|
|
23280
24145
|
opencodeConfig.agent = allAgents;
|
|
@@ -23294,7 +24159,7 @@ Make the requested changes, then call hive_request_review again.`;
|
|
|
23294
24159
|
delete configAgent["hygienic-reviewer"];
|
|
23295
24160
|
Object.assign(configAgent, allAgents);
|
|
23296
24161
|
}
|
|
23297
|
-
opencodeConfig.default_agent = "hive-master";
|
|
24162
|
+
opencodeConfig.default_agent = agentMode === "unified" ? "hive-master" : "architect-planner";
|
|
23298
24163
|
const configMcp = opencodeConfig.mcp;
|
|
23299
24164
|
if (!configMcp) {
|
|
23300
24165
|
opencodeConfig.mcp = builtinMcps;
|