@osovv/vv-opencode 1.3.5 → 1.3.6-rc.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/CHANGELOG.md +26 -0
- package/README.md +61 -1
- package/dist/commands/analytics.js +2 -0
- package/dist/commands/analytics.js.map +1 -1
- package/dist/commands/upgrade.d.ts +13 -6
- package/dist/commands/upgrade.js +31 -25
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/lib/opencode.js +3 -2
- package/dist/lib/opencode.js.map +1 -1
- package/dist/lib/peak-hours.d.ts +53 -0
- package/dist/lib/peak-hours.js +389 -0
- package/dist/lib/peak-hours.js.map +1 -0
- package/dist/lib/plugin-toggle-config.d.ts +71 -1
- package/dist/lib/plugin-toggle-config.js +77 -3
- package/dist/lib/plugin-toggle-config.js.map +1 -1
- package/dist/lib/vvoc-config.d.ts +84 -0
- package/dist/lib/vvoc-config.js +42 -1
- package/dist/lib/vvoc-config.js.map +1 -1
- package/dist/plugins/peak-hours/index.d.ts +31 -0
- package/dist/plugins/peak-hours/index.js +299 -0
- package/dist/plugins/peak-hours/index.js.map +1 -0
- package/dist/tui/analytics/indicator.js.map +1 -1
- package/dist/tui/peak-hours/banner.d.ts +26 -0
- package/dist/tui/peak-hours/banner.js +126 -0
- package/dist/tui/peak-hours/banner.js.map +1 -0
- package/dist/tui.js +13 -6
- package/dist/tui.js.map +1 -1
- package/package.json +6 -2
- package/schemas/vvoc/v3.json +326 -57
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { JSX } from "@opentui/solid";
|
|
2
|
+
import type { RGBA } from "@opentui/core";
|
|
3
|
+
import type { TuiPluginApi } from "@opencode-ai/plugin/tui";
|
|
4
|
+
import { type ActivePeak, type PeakHoursClock, type PeakHoursEntryConfig } from "../../lib/peak-hours.js";
|
|
5
|
+
export type PeakBannerModelRef = {
|
|
6
|
+
providerID: string;
|
|
7
|
+
};
|
|
8
|
+
export type PeakHoursBannerDependencies = {
|
|
9
|
+
enabled: (api: TuiPluginApi) => Promise<boolean>;
|
|
10
|
+
now: PeakHoursClock;
|
|
11
|
+
entry: () => PeakHoursEntryConfig;
|
|
12
|
+
currentModel: (api: TuiPluginApi) => PeakBannerModelRef | undefined;
|
|
13
|
+
connectedProviders: (api: TuiPluginApi) => string[];
|
|
14
|
+
renderBanner: (text: string, color: RGBA) => JSX.Element;
|
|
15
|
+
};
|
|
16
|
+
export declare function buildPeakBannerText(providerID: string, peak: ActivePeak, suggestions: readonly string[]): string;
|
|
17
|
+
export declare function resolveBannerModelRef(api: TuiPluginApi): PeakBannerModelRef | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Registers the persistent peak-hours banner for the app_bottom host slot.
|
|
20
|
+
*
|
|
21
|
+
* The banner renders in warning colors only while the current model's provider
|
|
22
|
+
* is inside an active peak window, naming the provider, the window end, and
|
|
23
|
+
* connected providers that are currently outside peak. Disabled toggle or
|
|
24
|
+
* entry, missing slot API, or registration failure leave the TUI untouched.
|
|
25
|
+
*/
|
|
26
|
+
export declare function registerPeakHoursBanner(api: TuiPluginApi, dependencies?: Partial<PeakHoursBannerDependencies>): Promise<void>;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@opentui/solid/jsx-runtime";
|
|
2
|
+
import { loadVvocConfigForRead } from "../../lib/config-layers.js";
|
|
3
|
+
import { isVvocPluginEnabled } from "../../lib/plugin-toggle-config.js";
|
|
4
|
+
import { findActivePeak, formatPeakEndTime, normalizeProviderId, parsePeakHoursEntry, suggestOffPeakProviders, } from "../../lib/peak-hours.js";
|
|
5
|
+
// START_CONTRACT: buildPeakBannerText
|
|
6
|
+
// PURPOSE: Compose the one-line banner label with window end and suggestions.
|
|
7
|
+
// INPUTS: { providerID: string - peak provider id; peak: ActivePeak - active window hit; suggestions: readonly string[] - connected off-peak provider ids }
|
|
8
|
+
// OUTPUTS: { string - banner label text }
|
|
9
|
+
// SIDE_EFFECTS: none
|
|
10
|
+
// LINKS: formatPeakEndTime
|
|
11
|
+
// END_CONTRACT: buildPeakBannerText
|
|
12
|
+
export function buildPeakBannerText(providerID, peak, suggestions) {
|
|
13
|
+
const until = formatPeakEndTime(peak.endsAt);
|
|
14
|
+
const suffix = suggestions.length > 0
|
|
15
|
+
? ` · off-peak now: ${suggestions.join(", ")}`
|
|
16
|
+
: " · every connected provider is in peak or unscheduled";
|
|
17
|
+
return `⚠ PEAK ${providerID} until ${until} · elevated pricing${suffix}`;
|
|
18
|
+
}
|
|
19
|
+
// START_CONTRACT: resolveBannerModelRef
|
|
20
|
+
// PURPOSE: Resolve the current model reference from the open session's messages with a config default fallback.
|
|
21
|
+
// INPUTS: { api: TuiPluginApi - TUI plugin api }
|
|
22
|
+
// OUTPUTS: { PeakBannerModelRef | undefined - provider id of the most recent model-bearing message, the config default model, or undefined }
|
|
23
|
+
// SIDE_EFFECTS: none
|
|
24
|
+
// LINKS: currentSessionID
|
|
25
|
+
// END_CONTRACT: resolveBannerModelRef
|
|
26
|
+
export function resolveBannerModelRef(api) {
|
|
27
|
+
const sessionID = currentSessionID(api);
|
|
28
|
+
if (!sessionID)
|
|
29
|
+
return undefined;
|
|
30
|
+
const messages = api.state.session.messages(sessionID);
|
|
31
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
32
|
+
const message = messages[index];
|
|
33
|
+
if (!message)
|
|
34
|
+
continue;
|
|
35
|
+
if (message.role === "assistant" && typeof message.providerID === "string") {
|
|
36
|
+
return { providerID: message.providerID };
|
|
37
|
+
}
|
|
38
|
+
if (typeof message.model?.providerID === "string") {
|
|
39
|
+
return { providerID: message.model.providerID };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const configModel = api.state.config.model;
|
|
43
|
+
if (typeof configModel === "string" && configModel.includes("/")) {
|
|
44
|
+
const providerID = configModel.split("/")[0];
|
|
45
|
+
if (providerID)
|
|
46
|
+
return { providerID };
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
/** Reads the currently open sessionID from the TUI route, or "". */
|
|
51
|
+
function currentSessionID(api) {
|
|
52
|
+
const route = api.route.current;
|
|
53
|
+
if (route.name === "session" && "params" in route) {
|
|
54
|
+
const sessionID = route.params?.sessionID;
|
|
55
|
+
return typeof sessionID === "string" ? sessionID : "";
|
|
56
|
+
}
|
|
57
|
+
return "";
|
|
58
|
+
}
|
|
59
|
+
// START_BLOCK_REGISTER_BANNER
|
|
60
|
+
/**
|
|
61
|
+
* Registers the persistent peak-hours banner for the app_bottom host slot.
|
|
62
|
+
*
|
|
63
|
+
* The banner renders in warning colors only while the current model's provider
|
|
64
|
+
* is inside an active peak window, naming the provider, the window end, and
|
|
65
|
+
* connected providers that are currently outside peak. Disabled toggle or
|
|
66
|
+
* entry, missing slot API, or registration failure leave the TUI untouched.
|
|
67
|
+
*/
|
|
68
|
+
export async function registerPeakHoursBanner(api, dependencies = {}) {
|
|
69
|
+
if (typeof api.slots?.register !== "function")
|
|
70
|
+
return;
|
|
71
|
+
// Populated by the default enabled() config read; kept for the sync entry().
|
|
72
|
+
let cachedEntry;
|
|
73
|
+
const deps = {
|
|
74
|
+
enabled: async (apiInstance) => {
|
|
75
|
+
const vvoc = await loadVvocConfigForRead({
|
|
76
|
+
scope: "effective",
|
|
77
|
+
allowDefault: true,
|
|
78
|
+
cwd: apiInstance.state.path.directory,
|
|
79
|
+
});
|
|
80
|
+
if (!isVvocPluginEnabled(vvoc.config, "peak-hours"))
|
|
81
|
+
return false;
|
|
82
|
+
const parsed = parsePeakHoursEntry(vvoc.config.plugins?.["peak-hours"]);
|
|
83
|
+
cachedEntry = parsed.entry;
|
|
84
|
+
return parsed.entry.enabled;
|
|
85
|
+
},
|
|
86
|
+
now: () => new Date(),
|
|
87
|
+
entry: () => cachedEntry ?? parsePeakHoursEntry(undefined).entry,
|
|
88
|
+
currentModel: (apiInstance) => resolveBannerModelRef(apiInstance),
|
|
89
|
+
connectedProviders: (apiInstance) => apiInstance.state.provider
|
|
90
|
+
.map((provider) => provider.id)
|
|
91
|
+
.filter((id) => typeof id === "string"),
|
|
92
|
+
renderBanner: (text, color) => (_jsx("text", { children: _jsx("span", { style: { fg: color }, children: text }) })),
|
|
93
|
+
...dependencies,
|
|
94
|
+
};
|
|
95
|
+
if (!(await deps.enabled(api)))
|
|
96
|
+
return;
|
|
97
|
+
try {
|
|
98
|
+
// OpenCode's runtime requires a string plugin id on slot registrations, while
|
|
99
|
+
// the SDK's TuiSlotPlugin type still types id as never; cast bridges the two.
|
|
100
|
+
const plugin = {
|
|
101
|
+
id: "vvoc-peak-hours",
|
|
102
|
+
order: 100,
|
|
103
|
+
slots: {
|
|
104
|
+
app_bottom: (_ctx) => {
|
|
105
|
+
const entry = deps.entry();
|
|
106
|
+
if (!entry.enabled)
|
|
107
|
+
return undefined;
|
|
108
|
+
const modelRef = deps.currentModel(api);
|
|
109
|
+
if (!modelRef)
|
|
110
|
+
return undefined;
|
|
111
|
+
const now = deps.now();
|
|
112
|
+
const peak = findActivePeak(now, entry.schedules, modelRef.providerID);
|
|
113
|
+
if (!peak)
|
|
114
|
+
return undefined;
|
|
115
|
+
const suggestions = suggestOffPeakProviders(now, entry.schedules, deps.connectedProviders(api)).filter((candidate) => normalizeProviderId(candidate) !== normalizeProviderId(modelRef.providerID));
|
|
116
|
+
return deps.renderBanner(buildPeakBannerText(modelRef.providerID, peak, suggestions), api.theme.current.warning);
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
api.slots.register(plugin);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// Fail-soft: no banner for this session.
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=banner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"banner.js","sourceRoot":"","sources":["../../../src/tui/peak-hours/banner.tsx"],"names":[],"mappings":"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"}
|
package/dist/tui.js
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
// FILE: src/tui.tsx
|
|
2
|
-
// VERSION: 1.
|
|
2
|
+
// VERSION: 1.2.0
|
|
3
3
|
// START_MODULE_CONTRACT
|
|
4
|
-
// PURPOSE: Publish the default @osovv/vv-opencode/tui module containing the managed context inspector, analytics indicator, and
|
|
4
|
+
// PURPOSE: Publish the default @osovv/vv-opencode/tui module containing the managed context inspector, analytics indicator, branding footer, and peak-hours banner.
|
|
5
5
|
// SCOPE: Stable TUI package entrypoint and module identity only.
|
|
6
|
-
// DEPENDS: [@opencode-ai/plugin/tui, @opencode-ai/plugin, src/tui/context/plugin.ts, src/tui/analytics/indicator.tsx, src/tui/branding/footer.tsx]
|
|
7
|
-
// LINKS: [M-PLUGIN-CONTEXT-TUI, M-TUI-ANALYTICS-INDICATOR, M-TUI-BRANDING-FOOTER, V-M-PLUGIN-CONTEXT-TUI]
|
|
6
|
+
// DEPENDS: [@opencode-ai/plugin/tui, @opencode-ai/plugin, src/tui/context/plugin.ts, src/tui/analytics/indicator.tsx, src/tui/branding/footer.tsx, src/tui/peak-hours/banner.tsx]
|
|
7
|
+
// LINKS: [M-PLUGIN-CONTEXT-TUI, M-TUI-ANALYTICS-INDICATOR, M-TUI-BRANDING-FOOTER, M-TUI-PEAK-HOURS-BANNER, V-M-PLUGIN-CONTEXT-TUI]
|
|
8
8
|
// ROLE: BARREL
|
|
9
9
|
// MAP_MODE: SUMMARY
|
|
10
10
|
// END_MODULE_CONTRACT
|
|
11
11
|
//
|
|
12
12
|
// START_MODULE_MAP
|
|
13
|
-
// default - OpenCode TUI plugin module registering /context, the analytics indicator, and the
|
|
13
|
+
// default - OpenCode TUI plugin module registering /context, the analytics indicator, the branding footer, and the peak-hours banner.
|
|
14
14
|
// ContextTuiPlugin - Named TUI plugin factory for direct consumers and tests.
|
|
15
15
|
// END_MODULE_MAP
|
|
16
16
|
//
|
|
17
17
|
// START_CHANGE_SUMMARY
|
|
18
|
-
// LAST_CHANGE: [
|
|
18
|
+
// LAST_CHANGE: [C-PLUGIN-PEAK-HOURS - Registered the app_bottom peak-hours banner alongside the indicator and footer.]
|
|
19
19
|
// END_CHANGE_SUMMARY
|
|
20
20
|
import { ContextTuiPlugin } from "./tui/context/plugin.js";
|
|
21
21
|
import { registerAnalyticsIndicator } from "./tui/analytics/indicator.js";
|
|
22
22
|
import { registerBrandingFooter } from "./tui/branding/footer.js";
|
|
23
|
+
import { registerPeakHoursBanner } from "./tui/peak-hours/banner.js";
|
|
23
24
|
export { ContextTuiPlugin };
|
|
24
25
|
// START_BLOCK_TUI_MODULE
|
|
25
26
|
const plugin = {
|
|
@@ -38,6 +39,12 @@ const plugin = {
|
|
|
38
39
|
catch {
|
|
39
40
|
// Fail-soft: footer unavailable for this session.
|
|
40
41
|
}
|
|
42
|
+
try {
|
|
43
|
+
await registerPeakHoursBanner(api, options);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Fail-soft: banner unavailable for this session.
|
|
47
|
+
}
|
|
41
48
|
},
|
|
42
49
|
};
|
|
43
50
|
// END_BLOCK_TUI_MODULE
|
package/dist/tui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui.js","sourceRoot":"","sources":["../src/tui.tsx"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,iBAAiB;AACjB,wBAAwB;AACxB,
|
|
1
|
+
{"version":3,"file":"tui.js","sourceRoot":"","sources":["../src/tui.tsx"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,iBAAiB;AACjB,wBAAwB;AACxB,sKAAsK;AACtK,mEAAmE;AACnE,oLAAoL;AACpL,qIAAqI;AACrI,iBAAiB;AACjB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,wIAAwI;AACxI,gFAAgF;AAChF,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,yHAAyH;AACzH,qBAAqB;AAGrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAErE,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAE5B,yBAAyB;AACzB,MAAM,MAAM,GAAqC;IAC/C,EAAE,EAAE,cAAc;IAClB,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAChC,MAAM,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,0BAA0B,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;QACD,IAAI,CAAC;YACH,sBAAsB,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;QACD,IAAI,CAAC;YACH,MAAM,uBAAuB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;IACH,CAAC;CACF,CAAC;AACF,uBAAuB;AAEvB,eAAe,MAAM,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osovv/vv-opencode",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6-rc.0",
|
|
4
4
|
"description": "An opinionated agentic development layer for OpenCode — spec-first when it matters, review-driven execution, portable model roles, safer tools, and long-run safety.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -81,6 +81,10 @@
|
|
|
81
81
|
"./plugins/analytics": {
|
|
82
82
|
"types": "./dist/plugins/analytics/index.d.ts",
|
|
83
83
|
"import": "./dist/plugins/analytics/index.js"
|
|
84
|
+
},
|
|
85
|
+
"./plugins/peak-hours": {
|
|
86
|
+
"types": "./dist/plugins/peak-hours/index.d.ts",
|
|
87
|
+
"import": "./dist/plugins/peak-hours/index.js"
|
|
84
88
|
}
|
|
85
89
|
},
|
|
86
90
|
"scripts": {
|
|
@@ -93,7 +97,7 @@
|
|
|
93
97
|
"grace:check": "bun scripts/check-grace-markup.ts",
|
|
94
98
|
"test": "bun test",
|
|
95
99
|
"check": "bun run typecheck && bun run lint && bun run fmt:check && bun run grace:check && bun test",
|
|
96
|
-
"pack:check": "bun run build && bun -e \"const root = await import('./dist/index.js'); if (!('GuardianPlugin' in root)) throw new Error('dist root export missing GuardianPlugin'); if (!('HashlineEditPlugin' in root)) throw new Error('dist root export missing HashlineEditPlugin'); if (!('ModelRolesPlugin' in root)) throw new Error('dist root export missing ModelRolesPlugin'); if (!('SystemContextInjectionPlugin' in root)) throw new Error('dist root export missing SystemContextInjectionPlugin'); if (!('WorkflowPlugin' in root)) throw new Error('dist root export missing WorkflowPlugin'); if (!('SecretsRedactionPlugin' in root)) throw new Error('dist root export missing SecretsRedactionPlugin'); if (!('WebToolsPlugin' in root)) throw new Error('dist root export missing WebToolsPlugin'); if (!('AnalyticsPlugin' in root)) throw new Error('dist root export missing AnalyticsPlugin'); const tui = await import('./dist/tui.js'); if (!tui.default || typeof tui.default.tui !== 'function') throw new Error('dist TUI export missing default tui module'); await import('./dist/plugins/guardian/index.js'); await import('./dist/plugins/hashline-edit/index.js'); await import('./dist/plugins/model-roles/index.js'); await import('./dist/plugins/system-context-injection/index.js'); await import('./dist/plugins/workflow/index.js'); await import('./dist/plugins/secrets-redaction/index.js'); await import('./dist/plugins/web-tools/index.js'); await import('./dist/plugins/analytics/index.js')\" && npm pack --dry-run",
|
|
100
|
+
"pack:check": "bun run build && bun -e \"const root = await import('./dist/index.js'); if (!('GuardianPlugin' in root)) throw new Error('dist root export missing GuardianPlugin'); if (!('HashlineEditPlugin' in root)) throw new Error('dist root export missing HashlineEditPlugin'); if (!('ModelRolesPlugin' in root)) throw new Error('dist root export missing ModelRolesPlugin'); if (!('SystemContextInjectionPlugin' in root)) throw new Error('dist root export missing SystemContextInjectionPlugin'); if (!('WorkflowPlugin' in root)) throw new Error('dist root export missing WorkflowPlugin'); if (!('SecretsRedactionPlugin' in root)) throw new Error('dist root export missing SecretsRedactionPlugin'); if (!('WebToolsPlugin' in root)) throw new Error('dist root export missing WebToolsPlugin'); if (!('AnalyticsPlugin' in root)) throw new Error('dist root export missing AnalyticsPlugin'); if (!('PeakHoursPlugin' in root)) throw new Error('dist root export missing PeakHoursPlugin'); const tui = await import('./dist/tui.js'); if (!tui.default || typeof tui.default.tui !== 'function') throw new Error('dist TUI export missing default tui module'); await import('./dist/plugins/guardian/index.js'); await import('./dist/plugins/hashline-edit/index.js'); await import('./dist/plugins/model-roles/index.js'); await import('./dist/plugins/system-context-injection/index.js'); await import('./dist/plugins/workflow/index.js'); await import('./dist/plugins/secrets-redaction/index.js'); await import('./dist/plugins/web-tools/index.js'); await import('./dist/plugins/analytics/index.js'); await import('./dist/plugins/peak-hours/index.js')\" && npm pack --dry-run",
|
|
97
101
|
"tui:local": "bun scripts/tui-local.ts",
|
|
98
102
|
"release:check": "bun scripts/release-check.ts",
|
|
99
103
|
"release:bump": "bun scripts/release-bump.ts",
|