@treeseed/cli 0.8.6 → 0.8.8
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/handlers/capacity.d.ts +2 -0
- package/dist/cli/handlers/capacity.js +145 -0
- package/dist/cli/handlers/config-ui.d.ts +1 -0
- package/dist/cli/handlers/config-ui.js +21 -10
- package/dist/cli/handlers/config.js +8 -4
- package/dist/cli/operations-registry.js +41 -0
- package/dist/cli/registry.d.ts +1 -0
- package/dist/cli/registry.js +2 -0
- package/package.json +2 -2
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { guidedResult } from "./utils.js";
|
|
2
|
+
import { createMarketClientForInvocation } from "./market-utils.js";
|
|
3
|
+
function required(value, message) {
|
|
4
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
5
|
+
throw new Error(message);
|
|
6
|
+
}
|
|
7
|
+
const handleCapacity = async (invocation, context) => {
|
|
8
|
+
const action = invocation.positionals[0] ?? "status";
|
|
9
|
+
const { profile, client } = createMarketClientForInvocation(invocation, context, { requireAuth: true });
|
|
10
|
+
const teamId = typeof invocation.args.team === "string" ? invocation.args.team : typeof profile.teamId === "string" ? profile.teamId : null;
|
|
11
|
+
if (action === "status") {
|
|
12
|
+
const team = required(teamId, "Usage: treeseed capacity status --team <team-id>");
|
|
13
|
+
const response = await client.teamCapacity(team);
|
|
14
|
+
const summary = response.payload.summary;
|
|
15
|
+
return guidedResult({
|
|
16
|
+
command: "capacity",
|
|
17
|
+
summary: "Team helper capacity status",
|
|
18
|
+
facts: [
|
|
19
|
+
{ label: "Market", value: profile.id },
|
|
20
|
+
{ label: "Team", value: team },
|
|
21
|
+
{ label: "Monthly remaining", value: summary?.monthlyRemainingCredits },
|
|
22
|
+
{ label: "Daily remaining", value: summary?.dailyRemainingCredits },
|
|
23
|
+
{ label: "Active providers", value: summary?.activeProviderCount }
|
|
24
|
+
],
|
|
25
|
+
report: { marketId: profile.id, teamId: team, capacity: response.payload }
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
if (action === "providers") {
|
|
29
|
+
const subcommand = invocation.positionals[1] ?? "list";
|
|
30
|
+
const team = required(teamId, "Usage: treeseed capacity providers list --team <team-id>");
|
|
31
|
+
if (subcommand === "list") {
|
|
32
|
+
const response = await client.teamCapacity(team);
|
|
33
|
+
const providers = response.payload.providers ?? [];
|
|
34
|
+
return guidedResult({
|
|
35
|
+
command: "capacity",
|
|
36
|
+
summary: `Found ${providers.length} helper capacity provider${providers.length === 1 ? "" : "s"}.`,
|
|
37
|
+
sections: [{
|
|
38
|
+
title: "Providers",
|
|
39
|
+
lines: providers.map((provider) => `${provider.id} ${provider.name} ${provider.status} workers=${provider.maxConcurrentWorkers ?? 0}`)
|
|
40
|
+
}],
|
|
41
|
+
report: { marketId: profile.id, teamId: team, providers }
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (subcommand === "connect") {
|
|
45
|
+
const response = await client.launchManagedCapacityProvider(team, { launchSource: "cli" });
|
|
46
|
+
return guidedResult({
|
|
47
|
+
command: "capacity",
|
|
48
|
+
summary: "TreeSeed-managed helper capacity is connected.",
|
|
49
|
+
facts: [
|
|
50
|
+
{ label: "Provider", value: response.payload.provider?.id },
|
|
51
|
+
{ label: "Security code prefix", value: response.payload.apiKey?.keyPrefix }
|
|
52
|
+
],
|
|
53
|
+
report: { marketId: profile.id, teamId: team, result: response.payload }
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (subcommand === "keys") {
|
|
57
|
+
const keyAction = invocation.positionals[2] ?? "reset";
|
|
58
|
+
const providerId = required(invocation.args.provider, "Usage: treeseed capacity providers keys reset --provider <provider-id>");
|
|
59
|
+
if (keyAction === "reset") {
|
|
60
|
+
const response = await client.resetCapacityProviderApiKey(providerId, { name: "Provider security code" });
|
|
61
|
+
return guidedResult({
|
|
62
|
+
command: "capacity",
|
|
63
|
+
summary: "Provider security code was reset.",
|
|
64
|
+
facts: [
|
|
65
|
+
{ label: "Provider", value: providerId },
|
|
66
|
+
{ label: "Prefix", value: response.payload.key?.keyPrefix },
|
|
67
|
+
{ label: "Security access code", value: response.payload.plaintextKey }
|
|
68
|
+
],
|
|
69
|
+
report: { marketId: profile.id, providerId, result: response.payload }
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (keyAction === "revoke") {
|
|
73
|
+
const keyId = required(invocation.args.key, "Usage: treeseed capacity providers keys revoke --provider <provider-id> --key <key-id>");
|
|
74
|
+
const response = await client.revokeCapacityProviderApiKey(providerId, keyId);
|
|
75
|
+
return guidedResult({
|
|
76
|
+
command: "capacity",
|
|
77
|
+
summary: "Provider security code was revoked.",
|
|
78
|
+
facts: [
|
|
79
|
+
{ label: "Provider", value: providerId },
|
|
80
|
+
{ label: "Key", value: keyId }
|
|
81
|
+
],
|
|
82
|
+
report: { marketId: profile.id, providerId, keyId, result: response.payload }
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { exitCode: 1, stderr: [`Unknown capacity providers action: ${subcommand}`] };
|
|
87
|
+
}
|
|
88
|
+
if (action === "grants") {
|
|
89
|
+
const subcommand = invocation.positionals[1] ?? "list";
|
|
90
|
+
const team = required(teamId, "Usage: treeseed capacity grants list --team <team-id>");
|
|
91
|
+
if (subcommand === "list") {
|
|
92
|
+
const response = await client.capacityGrants(team);
|
|
93
|
+
return guidedResult({
|
|
94
|
+
command: "capacity",
|
|
95
|
+
summary: `Found ${response.payload.length} capacity grant${response.payload.length === 1 ? "" : "s"}.`,
|
|
96
|
+
sections: [{
|
|
97
|
+
title: "Grants",
|
|
98
|
+
lines: response.payload.map((grant) => `${grant.id} ${grant.grantScope} daily=${grant.dailyCreditLimit ?? "policy"} monthly=${grant.monthlyCreditLimit ?? "policy"}`)
|
|
99
|
+
}],
|
|
100
|
+
report: { marketId: profile.id, teamId: team, grants: response.payload }
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (subcommand === "create") {
|
|
104
|
+
const providerId = required(invocation.args.provider, "Usage: treeseed capacity grants create --team <team-id> --provider <provider-id>");
|
|
105
|
+
const response = await client.createCapacityGrant(team, {
|
|
106
|
+
capacityProviderId: providerId,
|
|
107
|
+
projectId: typeof invocation.args.project === "string" ? invocation.args.project : null,
|
|
108
|
+
environment: typeof invocation.args.environment === "string" ? invocation.args.environment : null,
|
|
109
|
+
dailyCreditLimit: Number(invocation.args.daily ?? 25),
|
|
110
|
+
monthlyCreditLimit: Number(invocation.args.monthly ?? 500),
|
|
111
|
+
overflowPolicy: typeof invocation.args.overflow === "string" ? invocation.args.overflow : "approval_required"
|
|
112
|
+
});
|
|
113
|
+
return guidedResult({
|
|
114
|
+
command: "capacity",
|
|
115
|
+
summary: "Capacity grant created.",
|
|
116
|
+
facts: [
|
|
117
|
+
{ label: "Grant", value: response.payload.id },
|
|
118
|
+
{ label: "Provider", value: providerId }
|
|
119
|
+
],
|
|
120
|
+
report: { marketId: profile.id, teamId: team, grant: response.payload }
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return { exitCode: 1, stderr: [`Unknown capacity grants action: ${subcommand}`] };
|
|
124
|
+
}
|
|
125
|
+
if (action === "enqueue") {
|
|
126
|
+
const projectId = required(invocation.args.project, "Usage: treeseed capacity enqueue --project <project-id> --task-kind <kind>");
|
|
127
|
+
const response = await client.enqueueAgentTask(projectId, {
|
|
128
|
+
taskKind: typeof invocation.args.taskKind === "string" ? invocation.args.taskKind : typeof invocation.args.task === "string" ? invocation.args.task : "proposal.draft",
|
|
129
|
+
environment: typeof invocation.args.environment === "string" ? invocation.args.environment : "staging"
|
|
130
|
+
});
|
|
131
|
+
return guidedResult({
|
|
132
|
+
command: "capacity",
|
|
133
|
+
summary: "Budgeted agent task enqueued.",
|
|
134
|
+
facts: [
|
|
135
|
+
{ label: "Task", value: response.payload.task?.id },
|
|
136
|
+
{ label: "Reserved credits", value: response.payload.reservation?.reservedCredits }
|
|
137
|
+
],
|
|
138
|
+
report: { marketId: profile.id, projectId, result: response.payload }
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return { exitCode: 1, stderr: [`Unknown capacity action: ${action}`] };
|
|
142
|
+
};
|
|
143
|
+
export {
|
|
144
|
+
handleCapacity
|
|
145
|
+
};
|
|
@@ -88,6 +88,7 @@ export type ConfigViewportLayout = UiViewportLayout & {
|
|
|
88
88
|
inputHeight: number;
|
|
89
89
|
actionRowHeight: number;
|
|
90
90
|
};
|
|
91
|
+
export declare function resolveCurrentConfigValue(context: ConfigContextSnapshot, overrides: Record<string, string>, entryId: string, scope?: ConfigScope): string;
|
|
91
92
|
export declare function filterCliConfigPages(pages: ConfigPage[], query: string): ConfigPage[];
|
|
92
93
|
export declare function computeConfigViewportLayout(rows: number, columns: number): ConfigViewportLayout;
|
|
93
94
|
export declare function buildCliConfigPages(context: ConfigContextSnapshot, selectedFilter: ConfigScope, overrides?: Record<string, string>, viewMode?: ConfigViewMode): ConfigPage[];
|
|
@@ -21,6 +21,12 @@ import {
|
|
|
21
21
|
} from "../ui/framework.js";
|
|
22
22
|
import { useTerminalMouse } from "../ui/mouse.js";
|
|
23
23
|
const FULL_CONFIG_FILTERS = ["local", "staging", "prod"];
|
|
24
|
+
function firstAvailableScope(context, preferred = "local") {
|
|
25
|
+
if (context.scopes.includes(preferred)) {
|
|
26
|
+
return preferred;
|
|
27
|
+
}
|
|
28
|
+
return context.scopes[0] ?? preferred;
|
|
29
|
+
}
|
|
24
30
|
function maskValue(value) {
|
|
25
31
|
if (!value) {
|
|
26
32
|
return "(unset)";
|
|
@@ -111,7 +117,7 @@ function resolveCurrentConfigValue(context, overrides, entryId, scope = "local")
|
|
|
111
117
|
return overrides[scopedOverrideKey] ?? "";
|
|
112
118
|
}
|
|
113
119
|
for (const candidateScope of [scope, ...context.scopes.filter((candidate) => candidate !== scope)]) {
|
|
114
|
-
const entry = context.entriesByScope[candidateScope]
|
|
120
|
+
const entry = context.entriesByScope[candidateScope]?.find((candidate) => candidate.id === entryId);
|
|
115
121
|
if (entry?.storage === "shared") {
|
|
116
122
|
const overrideKey = `shared:${entryId}`;
|
|
117
123
|
if (overrideKey in overrides) {
|
|
@@ -236,15 +242,15 @@ function buildCliConfigPages(context, selectedFilter, overrides = {}, viewMode =
|
|
|
236
242
|
const sharedEntries = /* @__PURE__ */ new Set();
|
|
237
243
|
const pages = [];
|
|
238
244
|
for (const scope of selectedScopes) {
|
|
239
|
-
for (const entry of context.entriesByScope[scope]) {
|
|
245
|
+
for (const entry of context.entriesByScope[scope] ?? []) {
|
|
240
246
|
if (entry.storage === "shared") {
|
|
241
247
|
if (sharedEntries.has(entry.id)) {
|
|
242
248
|
continue;
|
|
243
249
|
}
|
|
244
|
-
const relevantScopes = selectedScopes.filter((candidateScope) => context.entriesByScope[candidateScope]
|
|
250
|
+
const relevantScopes = selectedScopes.filter((candidateScope) => context.entriesByScope[candidateScope]?.some((candidate) => candidate.id === entry.id));
|
|
245
251
|
const key2 = `shared:${entry.id}`;
|
|
246
252
|
sharedEntries.add(entry.id);
|
|
247
|
-
const requiredScopes = relevantScopes.filter((candidateScope) => context.entriesByScope[candidateScope]
|
|
253
|
+
const requiredScopes = relevantScopes.filter((candidateScope) => context.entriesByScope[candidateScope]?.some((candidate) => candidate.id === entry.id && candidate.required));
|
|
248
254
|
const currentValue = resolveSharedEntryValue(relevantScopes, requiredScopes, context.entriesByScope, entry.id, "currentValue");
|
|
249
255
|
const suggestedValue = resolveSharedEntryValue(relevantScopes, requiredScopes, context.entriesByScope, entry.id, "suggestedValue", {
|
|
250
256
|
fallbackToRelevant: requiredScopes.length === 0
|
|
@@ -465,7 +471,10 @@ async function runCliConfigEditor(context, options = {}) {
|
|
|
465
471
|
function App() {
|
|
466
472
|
const sidebarFilterHeight = 4;
|
|
467
473
|
const [currentContext, setCurrentContext] = React.useState(context);
|
|
468
|
-
const [filterIndex, setFilterIndex] = React.useState(
|
|
474
|
+
const [filterIndex, setFilterIndex] = React.useState(() => {
|
|
475
|
+
const initialScope = firstAvailableScope(context);
|
|
476
|
+
return Math.max(0, FULL_CONFIG_FILTERS.indexOf(initialScope));
|
|
477
|
+
});
|
|
469
478
|
const [viewMode, setViewMode] = React.useState(options.initialViewMode ?? "startup");
|
|
470
479
|
const [pageIndex, setPageIndex] = React.useState(0);
|
|
471
480
|
const [sidebarOffset, setSidebarOffset] = React.useState(0);
|
|
@@ -484,7 +493,8 @@ async function runCliConfigEditor(context, options = {}) {
|
|
|
484
493
|
const { exit } = useApp();
|
|
485
494
|
const windowSize = useWindowSize();
|
|
486
495
|
const layout = computeConfigViewportLayout(windowSize?.rows ?? 24, windowSize?.columns ?? 100);
|
|
487
|
-
const selectedFilter = FULL_CONFIG_FILTERS[filterIndex] ??
|
|
496
|
+
const selectedFilter = FULL_CONFIG_FILTERS[filterIndex] ?? firstAvailableScope(currentContext);
|
|
497
|
+
const readinessScope = firstAvailableScope(currentContext, selectedFilter);
|
|
488
498
|
const allPages = buildCliConfigPages(currentContext, selectedFilter, overrides, viewMode);
|
|
489
499
|
const pages = viewMode === "full" ? filterCliConfigPages(allPages, filterQuery) : allPages;
|
|
490
500
|
const safePageIndex = pages.length === 0 ? 0 : Math.min(pageIndex, pages.length - 1);
|
|
@@ -510,10 +520,10 @@ async function runCliConfigEditor(context, options = {}) {
|
|
|
510
520
|
const detailWidth = viewMode === "full" ? layout.contentWidth : layout.columns;
|
|
511
521
|
const detailPanel = detailViewportLines(detailSourceLines, detailWidth, layout.detailHeight, detailOffset);
|
|
512
522
|
const configReadiness = {
|
|
513
|
-
github: { configured: hasUsableValue(resolveCurrentConfigValue(currentContext, overrides, "GH_TOKEN",
|
|
514
|
-
cloudflare: { configured: hasUsableValue(resolveCurrentConfigValue(currentContext, overrides, "CLOUDFLARE_API_TOKEN",
|
|
515
|
-
railway: { configured: hasUsableValue(resolveCurrentConfigValue(currentContext, overrides, "RAILWAY_API_TOKEN",
|
|
516
|
-
localDevelopment: currentContext.configReadinessByScope
|
|
523
|
+
github: { configured: hasUsableValue(resolveCurrentConfigValue(currentContext, overrides, "GH_TOKEN", readinessScope)) },
|
|
524
|
+
cloudflare: { configured: hasUsableValue(resolveCurrentConfigValue(currentContext, overrides, "CLOUDFLARE_API_TOKEN", readinessScope)) },
|
|
525
|
+
railway: { configured: hasUsableValue(resolveCurrentConfigValue(currentContext, overrides, "RAILWAY_API_TOKEN", readinessScope)) },
|
|
526
|
+
localDevelopment: currentContext.configReadinessByScope[readinessScope]?.localDevelopment ?? { configured: true }
|
|
517
527
|
};
|
|
518
528
|
const sidebarHeight = Math.max(4, layout.bodyHeight - sidebarFilterHeight);
|
|
519
529
|
const sidebarViewportSize = Math.max(1, sidebarHeight - 4);
|
|
@@ -1171,5 +1181,6 @@ export {
|
|
|
1171
1181
|
filterCliConfigPages,
|
|
1172
1182
|
normalizeConfigInputChunk,
|
|
1173
1183
|
readLinuxClipboardText,
|
|
1184
|
+
resolveCurrentConfigValue,
|
|
1174
1185
|
runCliConfigEditor
|
|
1175
1186
|
};
|
|
@@ -117,8 +117,12 @@ function renderConfigResult(commandName, result) {
|
|
|
117
117
|
const payload = result.payload;
|
|
118
118
|
const toolHealth = payload.toolHealth;
|
|
119
119
|
const configContext = payload.context;
|
|
120
|
-
const configReadiness = configContext?.configReadinessByScope?.local ?? {};
|
|
121
120
|
const readinessByScope = payload.result?.readinessByScope ?? {};
|
|
121
|
+
const configReadinessByScope = configContext?.configReadinessByScope ?? {};
|
|
122
|
+
const providerConfigStatus = (provider) => {
|
|
123
|
+
const selectedScopes = Array.isArray(payload.scopes) && payload.scopes.length > 0 ? payload.scopes : Object.keys(configReadinessByScope);
|
|
124
|
+
return selectedScopes.some((scope) => configReadinessByScope?.[scope]?.[provider]?.configured) ? "configured" : "missing";
|
|
125
|
+
};
|
|
122
126
|
const bootstrapSystemsByScope = payload.result?.bootstrapSystemsByScope ?? payload.bootstrapSystemsByScope ?? {};
|
|
123
127
|
const skippedSystems = Object.values(bootstrapSystemsByScope).flatMap((entry) => Array.isArray(entry?.skipped) ? entry.skipped : []);
|
|
124
128
|
const resourceInventoryByScope = payload.result?.resourceInventoryByScope ?? payload.resourceInventoryByScope ?? {};
|
|
@@ -149,9 +153,9 @@ function renderConfigResult(commandName, result) {
|
|
|
149
153
|
{ label: "Prod readiness", value: configReadinessLabel(readinessByScope.prod) },
|
|
150
154
|
{ label: "Pages project", value: resourceInventoryByScope.staging?.resources?.pagesProject ?? resourceInventoryByScope.prod?.resources?.pagesProject ?? "(unset)" },
|
|
151
155
|
{ label: "R2 bucket", value: resourceInventoryByScope.staging?.resources?.contentBucket ?? resourceInventoryByScope.prod?.resources?.contentBucket ?? "(unset)" },
|
|
152
|
-
{ label: "GitHub token/config", value:
|
|
153
|
-
{ label: "Cloudflare token/config", value:
|
|
154
|
-
{ label: "Railway token/config", value:
|
|
156
|
+
{ label: "GitHub token/config", value: providerConfigStatus("github") },
|
|
157
|
+
{ label: "Cloudflare token/config", value: providerConfigStatus("cloudflare") },
|
|
158
|
+
{ label: "Railway token/config", value: providerConfigStatus("railway") },
|
|
155
159
|
{ label: "GitHub CLI", value: toolHealth?.githubCli?.available ? "ready" : "missing" },
|
|
156
160
|
{ label: "Wrangler CLI", value: toolHealth?.wranglerCli?.available ? "ready" : "missing" },
|
|
157
161
|
{ label: "Railway CLI", value: toolHealth?.railwayCli?.available ? "ready" : "missing" },
|
|
@@ -1460,6 +1460,47 @@ const CLI_ONLY_OPERATION_SPECS = [
|
|
|
1460
1460
|
executionMode: "handler",
|
|
1461
1461
|
handlerName: "projects"
|
|
1462
1462
|
},
|
|
1463
|
+
{
|
|
1464
|
+
id: "market.capacity",
|
|
1465
|
+
name: "capacity",
|
|
1466
|
+
aliases: [],
|
|
1467
|
+
group: "Utilities",
|
|
1468
|
+
summary: "Manage team helper capacity from the selected market.",
|
|
1469
|
+
description: "Inspect team helper credits, connect managed providers, rotate provider security codes, manage grants, and enqueue budgeted agent tasks.",
|
|
1470
|
+
provider: "default",
|
|
1471
|
+
related: ["teams", "projects", "agents"],
|
|
1472
|
+
usage: "treeseed capacity [status|providers|grants|enqueue]",
|
|
1473
|
+
arguments: [{ name: "action", description: "Capacity action.", required: false }],
|
|
1474
|
+
options: [
|
|
1475
|
+
{ name: "market", flags: "--market <id-or-url>", description: "Select a configured market id or direct market API URL.", kind: "string" },
|
|
1476
|
+
{ name: "team", flags: "--team <team-id>", description: "Team id for capacity status and grants.", kind: "string" },
|
|
1477
|
+
{ name: "provider", flags: "--provider <provider-id>", description: "Capacity provider id for grant or key actions.", kind: "string" },
|
|
1478
|
+
{ name: "project", flags: "--project <project-id>", description: "Project id for grant allocation or agent enqueue.", kind: "string" },
|
|
1479
|
+
{ name: "key", flags: "--key <key-id>", description: "Provider security code id to revoke.", kind: "string" },
|
|
1480
|
+
{ name: "taskKind", flags: "--task-kind <kind>", description: "Agent task signature for budgeted enqueue.", kind: "string" },
|
|
1481
|
+
{ name: "environment", flags: "--environment <environment>", description: "Project environment for grants or enqueue.", kind: "enum", values: ["local", "staging", "prod"] },
|
|
1482
|
+
{ name: "daily", flags: "--daily <credits>", description: "Daily credit limit for a created grant.", kind: "string" },
|
|
1483
|
+
{ name: "monthly", flags: "--monthly <credits>", description: "Monthly credit limit for a created grant.", kind: "string" },
|
|
1484
|
+
{ name: "json", flags: "--json", description: "Emit machine-readable JSON instead of human-readable text.", kind: "boolean" }
|
|
1485
|
+
],
|
|
1486
|
+
examples: [
|
|
1487
|
+
"treeseed capacity status --team team_123",
|
|
1488
|
+
"treeseed capacity providers connect --team team_123",
|
|
1489
|
+
"treeseed capacity providers keys reset --provider provider_123",
|
|
1490
|
+
"treeseed capacity grants create --team team_123 --provider provider_123 --daily 25",
|
|
1491
|
+
"treeseed capacity enqueue --project project_123 --task-kind proposal.draft"
|
|
1492
|
+
],
|
|
1493
|
+
help: {
|
|
1494
|
+
longSummary: ["Capacity talks to the market control plane so technical stewards can inspect helper credits, provider security codes, and budgeted agent task routing without opening the browser."],
|
|
1495
|
+
whenToUse: ["Use this after connecting to a market when provider health, budget allocation, or budgeted agent enqueue needs to be checked from a terminal."],
|
|
1496
|
+
beforeYouRun: ["Authenticate to the selected market and know the team, project, or provider id for the action you are taking."],
|
|
1497
|
+
automationNotes: ["Use `--json` when capturing provider keys, grant ids, task ids, or dashboard summaries in automation."]
|
|
1498
|
+
},
|
|
1499
|
+
helpVisible: true,
|
|
1500
|
+
helpFeatured: false,
|
|
1501
|
+
executionMode: "handler",
|
|
1502
|
+
handlerName: "capacity"
|
|
1503
|
+
},
|
|
1463
1504
|
{
|
|
1464
1505
|
id: "market.packs",
|
|
1465
1506
|
name: "packs",
|
package/dist/cli/registry.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ export declare const COMMAND_HANDLERS: {
|
|
|
28
28
|
readonly market: import("./operations-types.js").TreeseedCommandHandler;
|
|
29
29
|
readonly teams: import("./operations-types.js").TreeseedCommandHandler;
|
|
30
30
|
readonly projects: import("./operations-types.js").TreeseedCommandHandler;
|
|
31
|
+
readonly capacity: import("./operations-types.js").TreeseedCommandHandler;
|
|
31
32
|
readonly packs: import("./operations-types.js").TreeseedCommandHandler;
|
|
32
33
|
readonly gh: import("./operations-types.js").TreeseedCommandHandler;
|
|
33
34
|
readonly railway: import("./operations-types.js").TreeseedCommandHandler;
|
package/dist/cli/registry.js
CHANGED
|
@@ -22,6 +22,7 @@ import { handleAuthWhoAmI } from "./handlers/auth-whoami.js";
|
|
|
22
22
|
import { handleMarket } from "./handlers/market.js";
|
|
23
23
|
import { handleTeams } from "./handlers/teams.js";
|
|
24
24
|
import { handleProjects } from "./handlers/projects.js";
|
|
25
|
+
import { handleCapacity } from "./handlers/capacity.js";
|
|
25
26
|
import { handlePacks } from "./handlers/packs.js";
|
|
26
27
|
import { handleToolWrapper } from "./handlers/tool-wrapper.js";
|
|
27
28
|
import {
|
|
@@ -73,6 +74,7 @@ const COMMAND_HANDLERS = {
|
|
|
73
74
|
market: handleMarket,
|
|
74
75
|
teams: handleTeams,
|
|
75
76
|
projects: handleProjects,
|
|
77
|
+
capacity: handleCapacity,
|
|
76
78
|
packs: handlePacks,
|
|
77
79
|
gh: handleToolWrapper,
|
|
78
80
|
railway: handleToolWrapper,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@treeseed/cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.8",
|
|
4
4
|
"description": "Operator-facing Treeseed CLI package.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"release:publish": "node ./scripts/run-ts.mjs ./scripts/publish-package.ts"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@treeseed/sdk": "0.8.
|
|
48
|
+
"@treeseed/sdk": "0.8.8",
|
|
49
49
|
"ink": "^7.0.0",
|
|
50
50
|
"react": "^19.2.5"
|
|
51
51
|
},
|