@fro.bot/systematic 3.15.0 → 3.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +350 -128
- package/dist/index-ae6mhwth.js +9014 -0
- package/dist/index.js +167 -151
- package/dist/lib/agent-resolver.d.ts +7 -1
- package/dist/lib/capability-snapshot.d.ts +1 -1
- package/dist/lib/config-schema.d.ts +63 -1
- package/dist/lib/config.d.ts +59 -1
- package/dist/lib/pi-delegate-session.d.ts +2 -0
- package/dist/lib/pi-delegate-tool.d.ts +33 -1
- package/dist/lib/routing-resolver.d.ts +151 -0
- package/dist/pi.js +7495 -235
- package/dist/schemas/systematic-config.schema.json +1027 -185
- package/package.json +7 -7
- package/skills/ce-review/references/review-summary-schema.json +1 -1
- package/dist/index-0stf3ag0.js +0 -17100
package/dist/index.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
+
parseFrontmatter,
|
|
4
|
+
string,
|
|
5
|
+
array,
|
|
6
|
+
object,
|
|
7
|
+
record,
|
|
8
|
+
_enum,
|
|
3
9
|
AgentOverlaySchema,
|
|
4
10
|
CategoryOverlaySchema,
|
|
5
|
-
__require,
|
|
6
|
-
discoverSkills,
|
|
7
|
-
exports_external,
|
|
8
|
-
extractAgentFrontmatter,
|
|
9
|
-
extractCommandFrontmatter,
|
|
10
|
-
findAgentsInDir,
|
|
11
|
-
findCommandsInDir,
|
|
12
|
-
findSkillsInDir,
|
|
13
|
-
isDiscoverableMarkdown,
|
|
14
11
|
isRecord,
|
|
12
|
+
resolveRouting,
|
|
15
13
|
loadConfig,
|
|
16
14
|
loadConfigWithSources,
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
isDiscoverableMarkdown,
|
|
16
|
+
findAgentsInDir,
|
|
17
|
+
extractAgentFrontmatter,
|
|
18
|
+
findCommandsInDir,
|
|
19
|
+
extractCommandFrontmatter,
|
|
20
|
+
findSkillsInDir,
|
|
21
|
+
discoverSkills
|
|
22
|
+
} from "./index-ae6mhwth.js";
|
|
19
23
|
|
|
20
24
|
// src/index.ts
|
|
21
25
|
import { createHash as createHash4 } from "crypto";
|
|
@@ -479,7 +483,7 @@ function loadSkillAsCommand(loaded) {
|
|
|
479
483
|
config.subtask = loaded.subtask;
|
|
480
484
|
return config;
|
|
481
485
|
}
|
|
482
|
-
function collectAgents(dir, disabledAgents, nativeAgents, overlays) {
|
|
486
|
+
function collectAgents(dir, disabledAgents, nativeAgents, overlays, rawOverlays) {
|
|
483
487
|
const agents = {};
|
|
484
488
|
const agentList = findAgentsInDir(dir);
|
|
485
489
|
const disabledSet = new Set(disabledAgents);
|
|
@@ -494,12 +498,16 @@ function collectAgents(dir, disabledAgents, nativeAgents, overlays) {
|
|
|
494
498
|
continue;
|
|
495
499
|
const config = loadAgentAsConfig(agentInfo);
|
|
496
500
|
if (config) {
|
|
497
|
-
agents[agentInfo.name] = applyAgentOverlays(config, agentInfo, overlays);
|
|
501
|
+
agents[agentInfo.name] = applyAgentOverlays(config, agentInfo, overlays, rawOverlays);
|
|
498
502
|
}
|
|
499
503
|
}
|
|
500
504
|
return agents;
|
|
501
505
|
}
|
|
502
|
-
|
|
506
|
+
var EMPTY_PI_SUBAGENTS_OVERLAYS = {
|
|
507
|
+
agents: {},
|
|
508
|
+
categories: {}
|
|
509
|
+
};
|
|
510
|
+
function applyAgentOverlays(config, agentInfo, overlays, rawOverlays) {
|
|
503
511
|
const id = agentInfo.category ? `${agentInfo.category}/${agentInfo.name}` : agentInfo.name;
|
|
504
512
|
const categoryOverlay = agentInfo.category ? overlays.categoriesByKey.get(agentInfo.category) : undefined;
|
|
505
513
|
const exactOverlay = overlays.agentsByTargetId.get(id);
|
|
@@ -509,15 +517,40 @@ function applyAgentOverlays(config, agentInfo, overlays) {
|
|
|
509
517
|
if (hasPermissionOverlay && isRecord(config.permission)) {
|
|
510
518
|
addPermissionRules(permissionRules, config.permission);
|
|
511
519
|
}
|
|
512
|
-
|
|
513
|
-
|
|
520
|
+
const routing = resolveRouting({
|
|
521
|
+
overlays: rawOverlays,
|
|
522
|
+
piSubagentsOverlays: EMPTY_PI_SUBAGENTS_OVERLAYS,
|
|
523
|
+
target: { agentKey: agentInfo.name, category: agentInfo.category ?? "" },
|
|
524
|
+
harness: "opencode"
|
|
525
|
+
});
|
|
526
|
+
applyAgentOverlayPass(result, categoryOverlay?.value, permissionRules, routing, "category");
|
|
527
|
+
applyAgentOverlayPass(result, exactOverlay?.value, permissionRules, routing, "agent");
|
|
514
528
|
applyPermissionOverlay(result, permissionRules, hasPermissionOverlay);
|
|
515
529
|
return result;
|
|
516
530
|
}
|
|
517
|
-
function
|
|
531
|
+
function applyAgentOverlayPass(target, overlay, permissionRules, routing, level) {
|
|
532
|
+
if (routing.source.model?.level === level) {
|
|
533
|
+
applyRoutingModel(target, routing.model);
|
|
534
|
+
}
|
|
535
|
+
if (routing.source.qualifier?.level === level) {
|
|
536
|
+
target.variant = routing.qualifier;
|
|
537
|
+
}
|
|
518
538
|
if (overlay === undefined)
|
|
519
539
|
return;
|
|
520
|
-
|
|
540
|
+
applyOverlayObjectFields(target, overlay);
|
|
541
|
+
if (isRecord(overlay.permission)) {
|
|
542
|
+
addPermissionRules(permissionRules, overlay.permission);
|
|
543
|
+
}
|
|
544
|
+
if (Array.isArray(overlay.skills)) {
|
|
545
|
+
addManagedSkillRules(permissionRules, overlay.skills);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
function applyRoutingModel(target, model) {
|
|
549
|
+
if (model === null) {
|
|
550
|
+
delete target.model;
|
|
551
|
+
} else if (model !== undefined) {
|
|
552
|
+
target.model = model;
|
|
553
|
+
}
|
|
521
554
|
}
|
|
522
555
|
function applyPermissionOverlay(target, permissionRules, hasPermissionOverlay) {
|
|
523
556
|
if (!hasPermissionOverlay)
|
|
@@ -533,8 +566,6 @@ function overlayControlsPermission(overlay) {
|
|
|
533
566
|
return overlay !== undefined && (Object.hasOwn(overlay, "permission") || Object.hasOwn(overlay, "skills"));
|
|
534
567
|
}
|
|
535
568
|
var OVERLAY_ASSIGN_FIELDS = [
|
|
536
|
-
"model",
|
|
537
|
-
"variant",
|
|
538
569
|
"temperature",
|
|
539
570
|
"top_p",
|
|
540
571
|
"mode",
|
|
@@ -542,27 +573,12 @@ var OVERLAY_ASSIGN_FIELDS = [
|
|
|
542
573
|
"steps",
|
|
543
574
|
"hidden"
|
|
544
575
|
];
|
|
545
|
-
function
|
|
546
|
-
const overlayHasModel = Object.hasOwn(overlay, "model");
|
|
547
|
-
const overlayHasVariant = Object.hasOwn(overlay, "variant");
|
|
548
|
-
if (overlayHasModel && !overlayHasVariant) {
|
|
549
|
-
delete target.variant;
|
|
550
|
-
}
|
|
576
|
+
function applyOverlayObjectFields(target, overlay) {
|
|
551
577
|
for (const field of OVERLAY_ASSIGN_FIELDS) {
|
|
552
578
|
if (Object.hasOwn(overlay, field)) {
|
|
553
|
-
|
|
554
|
-
delete target[field];
|
|
555
|
-
} else {
|
|
556
|
-
target[field] = overlay[field];
|
|
557
|
-
}
|
|
579
|
+
target[field] = overlay[field];
|
|
558
580
|
}
|
|
559
581
|
}
|
|
560
|
-
if (isRecord(overlay.permission)) {
|
|
561
|
-
addPermissionRules(permissionRules, overlay.permission);
|
|
562
|
-
}
|
|
563
|
-
if (Array.isArray(overlay.skills)) {
|
|
564
|
-
addManagedSkillRules(permissionRules, overlay.skills);
|
|
565
|
-
}
|
|
566
582
|
}
|
|
567
583
|
function createPermissionRuleAccumulator() {
|
|
568
584
|
return new Map;
|
|
@@ -705,7 +721,7 @@ function createConfigHandler(deps) {
|
|
|
705
721
|
enabledSkills: enabledSkillNames
|
|
706
722
|
});
|
|
707
723
|
const resolvedOverlays = resolveAgentOverlaySet(validatedOverlays);
|
|
708
|
-
const bundledAgents = collectAgents(bundledAgentsDir, systematicConfig.disabled_agents, nativeAgents, resolvedOverlays);
|
|
724
|
+
const bundledAgents = collectAgents(bundledAgentsDir, systematicConfig.disabled_agents, nativeAgents, resolvedOverlays, overlays);
|
|
709
725
|
const bundledCommands = collectCommands(bundledCommandsDir, systematicConfig.disabled_commands);
|
|
710
726
|
const discoveredSkillCommands = systematicConfig.skills_as_commands !== false ? collectDiscoveredSkillsAsCommands(directory, homeDir, opencodeConfigDir, opencodeConfigDirOverride, systematicConfig.disabled_commands) : {};
|
|
711
727
|
const bundledAgentKeys = new Set(Object.keys(bundledAgents));
|
|
@@ -731,14 +747,14 @@ function registerSkillsPaths(config, skillsDir) {
|
|
|
731
747
|
};
|
|
732
748
|
}
|
|
733
749
|
function removeSystematicSkillPaths(paths) {
|
|
734
|
-
return paths.filter((
|
|
750
|
+
return paths.filter((path) => !isSystematicSkillPath(path));
|
|
735
751
|
}
|
|
736
|
-
function isSystematicSkillPath(
|
|
737
|
-
const normalizedPath = normalizePath(
|
|
752
|
+
function isSystematicSkillPath(path) {
|
|
753
|
+
const normalizedPath = normalizePath(path);
|
|
738
754
|
return normalizedPath.endsWith("/.config/opencode/systematic/skills") || normalizedPath.endsWith("/.cache/opencode/systematic/skills") || normalizedPath.endsWith("/.local/share/opencode/systematic/skills") || normalizedPath.endsWith("/.opencode/systematic/skills") || /(?:^|\/)\.cache\/opencode\/packages\/@fro\.bot\/systematic@[^/]+\/node_modules\/@fro\.bot\/systematic\/skills(?:$|\/)/u.test(normalizedPath);
|
|
739
755
|
}
|
|
740
|
-
function normalizePath(
|
|
741
|
-
return
|
|
756
|
+
function normalizePath(path) {
|
|
757
|
+
return path.replaceAll("\\", "/").replace(/\/+$/u, "");
|
|
742
758
|
}
|
|
743
759
|
|
|
744
760
|
// src/lib/opencode-operation-observer.ts
|
|
@@ -1655,10 +1671,10 @@ function createQuestionAttestation(options = {}) {
|
|
|
1655
1671
|
const disabledSessions = new Set;
|
|
1656
1672
|
let challengeCounter = 0;
|
|
1657
1673
|
function expireChallenges(now) {
|
|
1658
|
-
for (const [challengeId,
|
|
1659
|
-
if ((
|
|
1660
|
-
|
|
1661
|
-
const key = bindingKey(
|
|
1674
|
+
for (const [challengeId, challenge] of challenges) {
|
|
1675
|
+
if ((challenge.state === "pending" || challenge.state === "bound") && now - challenge.createdAt > maxChallengeAgeMs) {
|
|
1676
|
+
challenge.state = "expired";
|
|
1677
|
+
const key = bindingKey(challenge, challenge.resourceDigest);
|
|
1662
1678
|
if (activeByBinding.get(key) === challengeId)
|
|
1663
1679
|
activeByBinding.delete(key);
|
|
1664
1680
|
}
|
|
@@ -1675,17 +1691,17 @@ function createQuestionAttestation(options = {}) {
|
|
|
1675
1691
|
function findBindChallenge(input) {
|
|
1676
1692
|
return "challengeId" in input ? findChallengeById(input.challengeId) : findChallengeByScope(input);
|
|
1677
1693
|
}
|
|
1678
|
-
function bindStateRejection(
|
|
1679
|
-
if (
|
|
1694
|
+
function bindStateRejection(challenge, input) {
|
|
1695
|
+
if (challenge.state === "expired")
|
|
1680
1696
|
return "challenge-expired";
|
|
1681
|
-
if (
|
|
1697
|
+
if (challenge.state === "denied" || challenge.state === "consumed") {
|
|
1682
1698
|
return "challenge-consumed";
|
|
1683
1699
|
}
|
|
1684
|
-
if ("sessionId" in input && input.sessionId !== undefined && input.sessionId !==
|
|
1700
|
+
if ("sessionId" in input && input.sessionId !== undefined && input.sessionId !== challenge.sessionId) {
|
|
1685
1701
|
return "call-session-mismatch";
|
|
1686
1702
|
}
|
|
1687
|
-
if (
|
|
1688
|
-
return
|
|
1703
|
+
if (challenge.state === "bound") {
|
|
1704
|
+
return challenge.requestId === input.requestId ? "already-bound" : "substitution";
|
|
1689
1705
|
}
|
|
1690
1706
|
return seenRequestIds.has(input.requestId) ? "replay" : null;
|
|
1691
1707
|
}
|
|
@@ -1693,23 +1709,23 @@ function createQuestionAttestation(options = {}) {
|
|
|
1693
1709
|
const challengeId = challengeByRequest.get(requestId);
|
|
1694
1710
|
return challengeId === undefined ? null : challenges.get(challengeId) ?? null;
|
|
1695
1711
|
}
|
|
1696
|
-
function replyStateRejection(
|
|
1697
|
-
if (
|
|
1712
|
+
function replyStateRejection(challenge, input) {
|
|
1713
|
+
if (challenge.sessionId !== input.sessionId)
|
|
1698
1714
|
return "substitution";
|
|
1699
|
-
if (
|
|
1715
|
+
if (challenge.state === "expired")
|
|
1700
1716
|
return "challenge-expired";
|
|
1701
|
-
if (
|
|
1717
|
+
if (challenge.state !== "bound" || challenge.requestId !== input.requestId) {
|
|
1702
1718
|
return "replay";
|
|
1703
1719
|
}
|
|
1704
1720
|
return null;
|
|
1705
1721
|
}
|
|
1706
|
-
function rejectStateRejection(
|
|
1707
|
-
if (
|
|
1722
|
+
function rejectStateRejection(challenge, input) {
|
|
1723
|
+
if (challenge.sessionId !== input.sessionId)
|
|
1708
1724
|
return "substitution";
|
|
1709
|
-
if (
|
|
1725
|
+
if (challenge.state === "denied" || challenge.state === "consumed") {
|
|
1710
1726
|
return "already-consumed";
|
|
1711
1727
|
}
|
|
1712
|
-
if (
|
|
1728
|
+
if (challenge.state === "expired")
|
|
1713
1729
|
return "challenge-expired";
|
|
1714
1730
|
return null;
|
|
1715
1731
|
}
|
|
@@ -1721,37 +1737,37 @@ function createQuestionAttestation(options = {}) {
|
|
|
1721
1737
|
const parsed = parseBinding(input);
|
|
1722
1738
|
return parsed === null ? null : findChallengeByScope(parsed);
|
|
1723
1739
|
}
|
|
1724
|
-
function projectionBase(
|
|
1740
|
+
function projectionBase(challenge, status) {
|
|
1725
1741
|
return {
|
|
1726
|
-
status
|
|
1727
|
-
challengeId:
|
|
1728
|
-
purpose:
|
|
1729
|
-
sessionId:
|
|
1730
|
-
resourceDigest:
|
|
1731
|
-
transitionKey:
|
|
1732
|
-
...
|
|
1742
|
+
status,
|
|
1743
|
+
challengeId: challenge.challengeId,
|
|
1744
|
+
purpose: challenge.purpose,
|
|
1745
|
+
sessionId: challenge.sessionId,
|
|
1746
|
+
resourceDigest: challenge.resourceDigest,
|
|
1747
|
+
transitionKey: challenge.transition,
|
|
1748
|
+
...challenge.requestId === undefined ? {} : { requestId: challenge.requestId }
|
|
1733
1749
|
};
|
|
1734
1750
|
}
|
|
1735
|
-
function projectChallenge(
|
|
1736
|
-
const attestation =
|
|
1751
|
+
function projectChallenge(challenge) {
|
|
1752
|
+
const attestation = challenge.requestId === undefined ? undefined : attestations.get(challenge.requestId);
|
|
1737
1753
|
if (attestation !== undefined) {
|
|
1738
|
-
const
|
|
1754
|
+
const status = attestation.purpose === "session-disablement" && attestation.consumption === "consumed" ? "disabled" : "attested";
|
|
1739
1755
|
return {
|
|
1740
|
-
...projectionBase(
|
|
1756
|
+
...projectionBase(challenge, status),
|
|
1741
1757
|
consumption: attestation.consumption
|
|
1742
1758
|
};
|
|
1743
1759
|
}
|
|
1744
|
-
if (
|
|
1745
|
-
return projectionBase(
|
|
1760
|
+
if (challenge.state === "pending" || challenge.state === "bound") {
|
|
1761
|
+
return projectionBase(challenge, challenge.state);
|
|
1746
1762
|
}
|
|
1747
|
-
if (
|
|
1748
|
-
return projectionBase(
|
|
1763
|
+
if (challenge.state === "denied") {
|
|
1764
|
+
return projectionBase(challenge, "denied");
|
|
1749
1765
|
}
|
|
1750
1766
|
return { status: "unknown", reasonCode: "challenge-expired" };
|
|
1751
1767
|
}
|
|
1752
|
-
function removeActiveChallenge(
|
|
1753
|
-
const key = bindingKey(
|
|
1754
|
-
if (activeByBinding.get(key) ===
|
|
1768
|
+
function removeActiveChallenge(challenge) {
|
|
1769
|
+
const key = bindingKey(challenge, challenge.resourceDigest);
|
|
1770
|
+
if (activeByBinding.get(key) === challenge.challengeId) {
|
|
1755
1771
|
activeByBinding.delete(key);
|
|
1756
1772
|
}
|
|
1757
1773
|
}
|
|
@@ -1800,20 +1816,20 @@ function createQuestionAttestation(options = {}) {
|
|
|
1800
1816
|
if (parsed === null)
|
|
1801
1817
|
return rejected("invalid-input");
|
|
1802
1818
|
expireChallenges(readNow(clock));
|
|
1803
|
-
const
|
|
1804
|
-
if (
|
|
1819
|
+
const challenge = findBindChallenge(parsed);
|
|
1820
|
+
if (challenge === null)
|
|
1805
1821
|
return rejected("unknown-challenge");
|
|
1806
|
-
const stateRejection = bindStateRejection(
|
|
1822
|
+
const stateRejection = bindStateRejection(challenge, parsed);
|
|
1807
1823
|
if (stateRejection !== null)
|
|
1808
1824
|
return rejected(stateRejection);
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
challengeByRequest.set(parsed.requestId,
|
|
1825
|
+
challenge.state = "bound";
|
|
1826
|
+
challenge.callId = parsed.callId;
|
|
1827
|
+
challenge.requestId = parsed.requestId;
|
|
1828
|
+
challengeByRequest.set(parsed.requestId, challenge.challengeId);
|
|
1813
1829
|
seenRequestIds.add(parsed.requestId);
|
|
1814
1830
|
return {
|
|
1815
1831
|
status: "bound",
|
|
1816
|
-
challengeId:
|
|
1832
|
+
challengeId: challenge.challengeId,
|
|
1817
1833
|
requestId: parsed.requestId
|
|
1818
1834
|
};
|
|
1819
1835
|
} catch {
|
|
@@ -1826,32 +1842,32 @@ function createQuestionAttestation(options = {}) {
|
|
|
1826
1842
|
if (parsed === null)
|
|
1827
1843
|
return rejected("invalid-input");
|
|
1828
1844
|
expireChallenges(readNow(clock));
|
|
1829
|
-
const
|
|
1830
|
-
if (
|
|
1845
|
+
const challenge = requestChallenge(parsed.requestId);
|
|
1846
|
+
if (challenge === null) {
|
|
1831
1847
|
const replay = seenRequestIds.has(parsed.requestId);
|
|
1832
1848
|
seenRequestIds.add(parsed.requestId);
|
|
1833
1849
|
return rejected(replay ? "replay" : "unknown-request");
|
|
1834
1850
|
}
|
|
1835
|
-
const stateRejection = replyStateRejection(
|
|
1851
|
+
const stateRejection = replyStateRejection(challenge, parsed);
|
|
1836
1852
|
if (stateRejection !== null)
|
|
1837
1853
|
return rejected(stateRejection);
|
|
1838
1854
|
if (classifyQuestionAnswer(parsed.answer) !== "affirmative") {
|
|
1839
|
-
|
|
1840
|
-
removeActiveChallenge(
|
|
1855
|
+
challenge.state = "denied";
|
|
1856
|
+
removeActiveChallenge(challenge);
|
|
1841
1857
|
return rejected("non-affirmative");
|
|
1842
1858
|
}
|
|
1843
1859
|
const attestation = {
|
|
1844
|
-
purpose:
|
|
1845
|
-
sessionId:
|
|
1846
|
-
resourceDigest:
|
|
1847
|
-
transitionKey:
|
|
1860
|
+
purpose: challenge.purpose,
|
|
1861
|
+
sessionId: challenge.sessionId,
|
|
1862
|
+
resourceDigest: challenge.resourceDigest,
|
|
1863
|
+
transitionKey: challenge.transition,
|
|
1848
1864
|
requestId: parsed.requestId,
|
|
1849
1865
|
answer: "affirmed",
|
|
1850
1866
|
timestamp: readNow(clock),
|
|
1851
1867
|
consumption: "available"
|
|
1852
1868
|
};
|
|
1853
|
-
|
|
1854
|
-
removeActiveChallenge(
|
|
1869
|
+
challenge.state = "consumed";
|
|
1870
|
+
removeActiveChallenge(challenge);
|
|
1855
1871
|
attestations.set(parsed.requestId, attestation);
|
|
1856
1872
|
return { status: "accepted", attestation: cloneAttestation(attestation) };
|
|
1857
1873
|
} catch {
|
|
@@ -1864,17 +1880,17 @@ function createQuestionAttestation(options = {}) {
|
|
|
1864
1880
|
if (parsed === null)
|
|
1865
1881
|
return rejected("invalid-input");
|
|
1866
1882
|
expireChallenges(readNow(clock));
|
|
1867
|
-
const
|
|
1868
|
-
if (
|
|
1883
|
+
const challenge = requestChallenge(parsed.requestId);
|
|
1884
|
+
if (challenge === null) {
|
|
1869
1885
|
const replay = seenRequestIds.has(parsed.requestId);
|
|
1870
1886
|
seenRequestIds.add(parsed.requestId);
|
|
1871
1887
|
return rejected(replay ? "replay" : "unknown-request");
|
|
1872
1888
|
}
|
|
1873
|
-
const stateRejection = rejectStateRejection(
|
|
1889
|
+
const stateRejection = rejectStateRejection(challenge, parsed);
|
|
1874
1890
|
if (stateRejection !== null)
|
|
1875
1891
|
return rejected(stateRejection);
|
|
1876
|
-
|
|
1877
|
-
removeActiveChallenge(
|
|
1892
|
+
challenge.state = "denied";
|
|
1893
|
+
removeActiveChallenge(challenge);
|
|
1878
1894
|
return { status: "rejected", reasonCode: "rejected" };
|
|
1879
1895
|
} catch {
|
|
1880
1896
|
return rejected("invalid-input");
|
|
@@ -1924,10 +1940,10 @@ function createQuestionAttestation(options = {}) {
|
|
|
1924
1940
|
])) {
|
|
1925
1941
|
return { status: "unknown", reasonCode: "invalid-input" };
|
|
1926
1942
|
}
|
|
1927
|
-
const
|
|
1928
|
-
if (
|
|
1943
|
+
const challenge = statusChallenge(input);
|
|
1944
|
+
if (challenge === null)
|
|
1929
1945
|
return { status: "unknown", reasonCode: "unknown-challenge" };
|
|
1930
|
-
return projectChallenge(
|
|
1946
|
+
return projectChallenge(challenge);
|
|
1931
1947
|
} catch {
|
|
1932
1948
|
return { status: "unknown", reasonCode: "invalid-input" };
|
|
1933
1949
|
}
|
|
@@ -1941,9 +1957,9 @@ function createQuestionAttestation(options = {}) {
|
|
|
1941
1957
|
const sessionId = input.sessionId;
|
|
1942
1958
|
if (disabledSessions.has(sessionId))
|
|
1943
1959
|
return { status: "disabled", sessionId };
|
|
1944
|
-
for (const
|
|
1945
|
-
if (
|
|
1946
|
-
return { status:
|
|
1960
|
+
for (const challenge of challenges.values()) {
|
|
1961
|
+
if (challenge.sessionId === sessionId && challenge.purpose === "session-disablement" && (challenge.state === "pending" || challenge.state === "bound")) {
|
|
1962
|
+
return { status: challenge.state, sessionId };
|
|
1947
1963
|
}
|
|
1948
1964
|
}
|
|
1949
1965
|
return { status: "enabled", sessionId };
|
|
@@ -3862,10 +3878,10 @@ function createReceiptLedger(options = {}) {
|
|
|
3862
3878
|
return { status: "consumed", receipt: cloneEnvelope2(stored.envelope) };
|
|
3863
3879
|
}
|
|
3864
3880
|
function recoverReceipt(input, operationTargetIdentity) {
|
|
3865
|
-
const
|
|
3866
|
-
if (
|
|
3867
|
-
return
|
|
3868
|
-
const marker =
|
|
3881
|
+
const markerResult = getMintMarker(input);
|
|
3882
|
+
if (markerResult.status !== "valid")
|
|
3883
|
+
return markerResult;
|
|
3884
|
+
const marker = markerResult.marker;
|
|
3869
3885
|
if (marker.sessionSalt !== sessionSalt)
|
|
3870
3886
|
return { status: "rejected", category: "salt-mismatch" };
|
|
3871
3887
|
if (marker.envelope.schemaVersion === 1 && operationTargetIdentity !== undefined) {
|
|
@@ -4990,8 +5006,8 @@ var Language = class _Language {
|
|
|
4990
5006
|
if (input instanceof Uint8Array) {
|
|
4991
5007
|
binary2 = input;
|
|
4992
5008
|
} else if (globalThis.process?.versions.node) {
|
|
4993
|
-
const
|
|
4994
|
-
binary2 = await
|
|
5009
|
+
const fs2 = await import("fs/promises");
|
|
5010
|
+
binary2 = await fs2.readFile(input);
|
|
4995
5011
|
} else {
|
|
4996
5012
|
const response = await fetch(input);
|
|
4997
5013
|
if (!response.ok) {
|
|
@@ -5042,11 +5058,11 @@ async function Module2(moduleArg = {}) {
|
|
|
5042
5058
|
}, "quit_");
|
|
5043
5059
|
var _scriptName = import.meta.url;
|
|
5044
5060
|
var scriptDirectory = "";
|
|
5045
|
-
function locateFile(
|
|
5061
|
+
function locateFile(path) {
|
|
5046
5062
|
if (Module["locateFile"]) {
|
|
5047
|
-
return Module["locateFile"](
|
|
5063
|
+
return Module["locateFile"](path, scriptDirectory);
|
|
5048
5064
|
}
|
|
5049
|
-
return scriptDirectory +
|
|
5065
|
+
return scriptDirectory + path;
|
|
5050
5066
|
}
|
|
5051
5067
|
__name(locateFile, "locateFile");
|
|
5052
5068
|
var readAsync, readBinary;
|
|
@@ -9744,23 +9760,23 @@ function createWorkflowGuard(options) {
|
|
|
9744
9760
|
return recoveryUnitProgressionReason(progression);
|
|
9745
9761
|
}
|
|
9746
9762
|
function recoveryUnitProgressionReason(progression) {
|
|
9747
|
-
const
|
|
9763
|
+
const epoch = progression.epoch;
|
|
9748
9764
|
const unit = progression.unit;
|
|
9749
|
-
if (!
|
|
9765
|
+
if (!epoch)
|
|
9750
9766
|
return "invalid-recovery";
|
|
9751
9767
|
if (!unit) {
|
|
9752
|
-
return
|
|
9768
|
+
return epoch.state === "completed" ? "invalid-recovery" : undefined;
|
|
9753
9769
|
}
|
|
9754
|
-
const declarationFailure = recoveryUnitDeclarationReason(
|
|
9770
|
+
const declarationFailure = recoveryUnitDeclarationReason(epoch, unit);
|
|
9755
9771
|
if (declarationFailure)
|
|
9756
9772
|
return declarationFailure;
|
|
9757
|
-
return unit.resourceScopes.some((scope) => !unit.requiredOperations.includes(scope.operation)) ? "invalid-recovery" : recoveryCompletedPairReason(
|
|
9773
|
+
return unit.resourceScopes.some((scope) => !unit.requiredOperations.includes(scope.operation)) ? "invalid-recovery" : recoveryCompletedPairReason(epoch, unit);
|
|
9758
9774
|
}
|
|
9759
|
-
function recoveryUnitDeclarationReason(
|
|
9760
|
-
return unit.epochId ===
|
|
9775
|
+
function recoveryUnitDeclarationReason(epoch, unit) {
|
|
9776
|
+
return unit.epochId === epoch.epochId && unit.epochDigest === epoch.epochDigest && unit.unitDigest === options.ledger.digestIdentity("unit", unit.unitId) && unit.family === epoch.family ? undefined : "invalid-recovery";
|
|
9761
9777
|
}
|
|
9762
|
-
function recoveryCompletedPairReason(
|
|
9763
|
-
return
|
|
9778
|
+
function recoveryCompletedPairReason(epoch, unit) {
|
|
9779
|
+
return epoch.state === "completed" && unit.state !== "completed" ? "invalid-recovery" : undefined;
|
|
9764
9780
|
}
|
|
9765
9781
|
function recoveryBoundaryReason(envelope) {
|
|
9766
9782
|
if (envelope.canonical.workspaceDigest !== options.ledger.digestIdentity("workspace", currentWorkspaceIdentity)) {
|
|
@@ -9857,8 +9873,8 @@ function createWorkflowGuard(options) {
|
|
|
9857
9873
|
}
|
|
9858
9874
|
return;
|
|
9859
9875
|
}
|
|
9860
|
-
function recoveryEpochCompletionReason(
|
|
9861
|
-
if (
|
|
9876
|
+
function recoveryEpochCompletionReason(epoch, matching) {
|
|
9877
|
+
if (epoch?.state !== "completed")
|
|
9862
9878
|
return;
|
|
9863
9879
|
return matching.length > 0 && matching.every((envelope) => envelope.canonical.consumption === "consumed") ? undefined : "invalid-recovery";
|
|
9864
9880
|
}
|
|
@@ -10291,18 +10307,18 @@ function isWorkflowGuardBlockedError(value) {
|
|
|
10291
10307
|
return typeof candidate.reasonCode === "string" && REASON_CODES.has(candidate.reasonCode);
|
|
10292
10308
|
}
|
|
10293
10309
|
var startToolShape = {
|
|
10294
|
-
expected_operations:
|
|
10295
|
-
resource_scopes:
|
|
10310
|
+
expected_operations: array(_enum(OPERATIONS)).optional(),
|
|
10311
|
+
resource_scopes: record(string(), string()).optional()
|
|
10296
10312
|
};
|
|
10297
|
-
var completeToolShape = { target:
|
|
10313
|
+
var completeToolShape = { target: _enum(["unit", "epoch"]) };
|
|
10298
10314
|
var controlToolShape = {
|
|
10299
|
-
mode:
|
|
10315
|
+
mode: _enum(["protected", "disabled", "unavailable"])
|
|
10300
10316
|
};
|
|
10301
10317
|
var statusToolShape = {};
|
|
10302
|
-
var startToolSchema =
|
|
10303
|
-
var completeToolSchema =
|
|
10304
|
-
var controlToolSchema =
|
|
10305
|
-
var statusToolSchema =
|
|
10318
|
+
var startToolSchema = object(startToolShape).strict();
|
|
10319
|
+
var completeToolSchema = object(completeToolShape).strict();
|
|
10320
|
+
var controlToolSchema = object(controlToolShape).strict();
|
|
10321
|
+
var statusToolSchema = object(statusToolShape).strict();
|
|
10306
10322
|
function isRecord7(value) {
|
|
10307
10323
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10308
10324
|
}
|
|
@@ -10453,13 +10469,13 @@ function validationForCandidate(candidatePath, options, targetPath = candidatePa
|
|
|
10453
10469
|
}
|
|
10454
10470
|
function deriveFileTarget(rawPath, baseDirectory, parentTargetRoot, options, realPath, allowParentFastPath = true) {
|
|
10455
10471
|
const resolvedPath = path6.resolve(baseDirectory, rawPath);
|
|
10456
|
-
const
|
|
10457
|
-
if (!
|
|
10472
|
+
const canonicalPath = canonicalFileTarget(resolvedPath, realPath);
|
|
10473
|
+
if (!canonicalPath)
|
|
10458
10474
|
return unavailableOperationTarget();
|
|
10459
|
-
const parentResult = allowParentFastPath && !path6.isAbsolute(rawPath) ? trustedParentTarget(parentTargetRoot,
|
|
10475
|
+
const parentResult = allowParentFastPath && !path6.isAbsolute(rawPath) ? trustedParentTarget(parentTargetRoot, canonicalPath) : undefined;
|
|
10460
10476
|
if (parentResult)
|
|
10461
10477
|
return parentResult;
|
|
10462
|
-
return validationForCandidate(path6.dirname(
|
|
10478
|
+
return validationForCandidate(path6.dirname(canonicalPath), options, canonicalPath);
|
|
10463
10479
|
}
|
|
10464
10480
|
function sharedTargetRoot(targets, extraRoots = []) {
|
|
10465
10481
|
const roots = [...extraRoots];
|
|
@@ -11057,7 +11073,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
|
|
|
11057
11073
|
return classifyQuestionAnswer(answer) === "affirmative" ? answer : "no";
|
|
11058
11074
|
}
|
|
11059
11075
|
function challengeForTransition(sessionID, target) {
|
|
11060
|
-
const existing = [...pendingQuestionChallenges.values()].find((
|
|
11076
|
+
const existing = [...pendingQuestionChallenges.values()].find((pending) => pending.purpose === "transition" && pending.transition === target);
|
|
11061
11077
|
if (existing)
|
|
11062
11078
|
return existing;
|
|
11063
11079
|
const resource = questionResource(target);
|
|
@@ -11079,7 +11095,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
|
|
|
11079
11095
|
return pending;
|
|
11080
11096
|
}
|
|
11081
11097
|
function challengeForDisablement(sessionID) {
|
|
11082
|
-
const existing = [...pendingQuestionChallenges.values()].find((
|
|
11098
|
+
const existing = [...pendingQuestionChallenges.values()].find((pending) => pending.purpose === "session-disablement");
|
|
11083
11099
|
if (existing)
|
|
11084
11100
|
return existing;
|
|
11085
11101
|
const resource = `session/${sessionID}`;
|
|
@@ -11253,14 +11269,14 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
|
|
|
11253
11269
|
}
|
|
11254
11270
|
return;
|
|
11255
11271
|
}
|
|
11256
|
-
function candidateAgreesWithOwnIdentity(salt,
|
|
11272
|
+
function candidateAgreesWithOwnIdentity(salt, digest) {
|
|
11257
11273
|
try {
|
|
11258
11274
|
const probe = createReceiptLedger({
|
|
11259
11275
|
capabilityFlags: ["workflow-guard"],
|
|
11260
11276
|
registrationIdentity: options.registrationIdentity,
|
|
11261
11277
|
sessionSalt: salt
|
|
11262
11278
|
});
|
|
11263
|
-
return probe.metadata.registrationDigest ===
|
|
11279
|
+
return probe.metadata.registrationDigest === digest;
|
|
11264
11280
|
} catch {
|
|
11265
11281
|
return false;
|
|
11266
11282
|
}
|
|
@@ -12465,7 +12481,7 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
|
|
|
12465
12481
|
return;
|
|
12466
12482
|
}
|
|
12467
12483
|
}
|
|
12468
|
-
function buildOperationObservation(host, pending,
|
|
12484
|
+
function buildOperationObservation(host, pending, after, current, output, operation = operationCandidate(host.tool), remoteAfter) {
|
|
12469
12485
|
if (!current.epoch || !current.unit || !isLocalOperationTool(host.tool)) {
|
|
12470
12486
|
return;
|
|
12471
12487
|
}
|
|
@@ -12489,10 +12505,10 @@ function createSessionRuntime(options, operationObservers, recoveredOperationCon
|
|
|
12489
12505
|
},
|
|
12490
12506
|
after: {
|
|
12491
12507
|
workspaceIdentity: options.workspaceIdentity,
|
|
12492
|
-
repositoryIdentity:
|
|
12493
|
-
worktreeIdentity:
|
|
12508
|
+
repositoryIdentity: after.repositoryRevisionDigest,
|
|
12509
|
+
worktreeIdentity: after.worktreeRevisionDigest,
|
|
12494
12510
|
...localOperation(operation) ? { operationTargetIdentity: pending.targetIdentity } : {},
|
|
12495
|
-
commitClosure:
|
|
12511
|
+
commitClosure: after.commitClosure,
|
|
12496
12512
|
...remoteAfter ? {
|
|
12497
12513
|
resourceIdentity: remoteAfter.resourceIdentity,
|
|
12498
12514
|
resourceRevisionIdentity: remoteAfter.resourceRevisionIdentity,
|
|
@@ -13093,7 +13109,7 @@ function createSkillTool(options) {
|
|
|
13093
13109
|
return cachedDescription;
|
|
13094
13110
|
},
|
|
13095
13111
|
args: {
|
|
13096
|
-
name:
|
|
13112
|
+
name: string().describe((() => {
|
|
13097
13113
|
if (cachedParameterHint == null) {
|
|
13098
13114
|
cachedParameterHint = buildParameterHint();
|
|
13099
13115
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Runtime persona catalog for `systematic_delegate`. Pi has no agent-discovery of its own, so category is dropped when flattening `agents/<category>/<name>.md` into this catalog. */
|
|
2
2
|
/** A single resolved persona entry in the flattened catalog. */
|
|
3
3
|
export interface AgentCatalogEntry {
|
|
4
|
-
/** Flat persona name (category dropped). */
|
|
4
|
+
/** Flat persona name (category dropped). Used for dispatch matching (`resolveAgent`); may differ from `key` if frontmatter `name` and the file stem diverge. */
|
|
5
5
|
name: string;
|
|
6
6
|
/** Human-readable description, used in tool description/parameter hints. */
|
|
7
7
|
description: string;
|
|
@@ -9,6 +9,12 @@ export interface AgentCatalogEntry {
|
|
|
9
9
|
body: string;
|
|
10
10
|
/** Raw comma-separated `tools:` frontmatter value, if declared. Undefined = not declared. */
|
|
11
11
|
toolsSource: string | undefined;
|
|
12
|
+
/** The agent's source file stem (filename without `.md`), used to key into `agents.<key>` overlays for routing (distinct from the display `name`). */
|
|
13
|
+
key: string;
|
|
14
|
+
/** The agent's category (source subdirectory name), used to key into `categories.<category>` overlays. `''` when the file has no category subdirectory -- the same no-category sentinel `config-handler.ts` and `pi-subagents-export.ts` use. */
|
|
15
|
+
category: string;
|
|
16
|
+
/** Qualified `category/key` id, mirroring `agent-overlays.ts`'s target-id convention, for callers that want a single stable identity. */
|
|
17
|
+
id: string;
|
|
12
18
|
}
|
|
13
19
|
/** Fails closed if the same persona name appears under more than one category. */
|
|
14
20
|
export declare function buildAgentCatalog(agentsDir: string): AgentCatalogEntry[];
|
|
@@ -3,7 +3,7 @@ declare const CAPABILITY_SNAPSHOT_COMMAND: 'systematic capabilities';
|
|
|
3
3
|
declare const CAPABILITY_SOURCE_IDS: readonly ['config:custom', 'config:global', 'config:project', 'config:user', 'discovery:agents', 'discovery:skills', 'host:runtime', 'package'];
|
|
4
4
|
declare const CONFIG_SOURCE_KINDS: readonly ['custom', 'project', 'user'];
|
|
5
5
|
declare const CONFIG_AUTHORITY_FIELD_PATHS: readonly ['bootstrap.enabled', 'bootstrap.file', 'skills_as_commands', 'workflow_guard.debug', 'workflow_guard.mode'];
|
|
6
|
-
declare const CONFIG_PROTECTED_FIELD_PATHS: readonly ['workflow_guard', 'agents.*.model', 'agents.*.permission', 'agents.*.skills', 'agents.*.variant', 'categories.*.model', 'categories.*.permission', 'categories.*.skills', 'categories.*.variant'];
|
|
6
|
+
declare const CONFIG_PROTECTED_FIELD_PATHS: readonly ['workflow_guard', 'profiles', 'agents.*.model', 'agents.*.permission', 'agents.*.skills', 'agents.*.variant', 'agents.*.opencode', 'agents.*.pi', 'categories.*.model', 'categories.*.permission', 'categories.*.skills', 'categories.*.variant', 'categories.*.opencode', 'categories.*.pi'];
|
|
7
7
|
declare const CONFIG_SOURCE_ERROR_CODES: readonly ['parse-failed', 'read-failed', 'schema-invalid', 'source-invalid'];
|
|
8
8
|
declare const CAPABILITY_SOURCE_PRESENCE: readonly ['absent', 'invalid', 'present'];
|
|
9
9
|
declare const CAPABILITY_STATUSES: readonly ['available', 'unknown', 'unavailable'];
|