umbrella-context 0.1.2 → 0.1.32
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/bin/um.js +2 -0
- package/dist/adapters/byterover-context-runtime-store.d.ts +15 -0
- package/dist/adapters/byterover-context-runtime-store.js +57 -0
- package/dist/adapters/byterover-runtime-bridge.d.ts +218 -0
- package/dist/adapters/byterover-runtime-bridge.js +343 -0
- package/dist/adapters/byterover-transport-task-store.d.ts +13 -0
- package/dist/adapters/byterover-transport-task-store.js +50 -0
- package/dist/adapters/umbrella-onboarding.d.ts +27 -0
- package/dist/adapters/umbrella-onboarding.js +79 -0
- package/dist/adapters/umbrella-provider-runtime.d.ts +38 -0
- package/dist/adapters/umbrella-provider-runtime.js +199 -0
- package/dist/adapters/vendor-byterover.d.ts +4 -0
- package/dist/adapters/vendor-byterover.js +19 -0
- package/dist/commands/activity.d.ts +2 -0
- package/dist/commands/activity.js +82 -0
- package/dist/commands/bridge.d.ts +2 -0
- package/dist/commands/bridge.js +40 -0
- package/dist/commands/catalog.d.ts +34 -0
- package/dist/commands/catalog.js +234 -0
- package/dist/commands/connect.js +14 -14
- package/dist/commands/connectors.d.ts +24 -0
- package/dist/commands/connectors.js +626 -0
- package/dist/commands/curate.d.ts +1 -0
- package/dist/commands/curate.js +48 -3
- package/dist/commands/debug.d.ts +2 -0
- package/dist/commands/debug.js +55 -0
- package/dist/commands/fix.js +54 -0
- package/dist/commands/hub.d.ts +22 -0
- package/dist/commands/hub.js +487 -0
- package/dist/commands/interactive.d.ts +2 -0
- package/dist/commands/interactive.js +970 -62
- package/dist/commands/locations.d.ts +1 -0
- package/dist/commands/locations.js +15 -12
- package/dist/commands/logout.d.ts +2 -0
- package/dist/commands/logout.js +34 -0
- package/dist/commands/model.d.ts +11 -0
- package/dist/commands/model.js +225 -0
- package/dist/commands/providers.d.ts +17 -0
- package/dist/commands/providers.js +379 -0
- package/dist/commands/pull.js +60 -1
- package/dist/commands/push.js +62 -2
- package/dist/commands/reset.d.ts +2 -0
- package/dist/commands/reset.js +35 -0
- package/dist/commands/restart.d.ts +2 -0
- package/dist/commands/restart.js +21 -0
- package/dist/commands/search.js +65 -1
- package/dist/commands/session.d.ts +2 -0
- package/dist/commands/session.js +241 -0
- package/dist/commands/setup.js +58 -56
- package/dist/commands/space.d.ts +12 -0
- package/dist/commands/space.js +138 -42
- package/dist/commands/status.d.ts +29 -0
- package/dist/commands/status.js +120 -19
- package/dist/commands/tasks.d.ts +2 -0
- package/dist/commands/tasks.js +95 -0
- package/dist/commands/transport.d.ts +2 -0
- package/dist/commands/transport.js +88 -0
- package/dist/commands/tree.d.ts +2 -0
- package/dist/commands/tree.js +98 -0
- package/dist/commands/tui.d.ts +2 -0
- package/dist/commands/tui.js +1273 -0
- package/dist/config.d.ts +23 -0
- package/dist/config.js +69 -0
- package/dist/index.js +41 -5
- package/dist/repo-state.d.ts +227 -1
- package/dist/repo-state.js +920 -4
- package/dist/umbrella.js +29 -5
- package/package.json +11 -3
package/dist/commands/space.js
CHANGED
|
@@ -1,52 +1,57 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import prompts from "prompts";
|
|
3
3
|
import { configManager } from "../config.js";
|
|
4
|
-
import { ensureRepoContext } from "../repo-state.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
4
|
+
import { ensureRepoContext, recordSessionEvent, setSessionPanel } from "../repo-state.js";
|
|
5
|
+
import { pullCommandAction } from "./pull.js";
|
|
6
|
+
import { createContextSpace, getCliSetup, getCompanyContextSummary, toContextSpaces } from "../umbrella.js";
|
|
7
|
+
export async function spaceCommandAction(action, spaceArg) {
|
|
8
|
+
const config = configManager.config;
|
|
9
|
+
if (!config) {
|
|
10
|
+
console.log(chalk.red("Not configured. Run: umbrella-context setup"));
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (!config.umbrellaUrl) {
|
|
14
|
+
console.log(chalk.red("No Umbrella URL saved for this device. Run umbrella-context setup to enable space commands."));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const normalizedAction = action.toLowerCase();
|
|
18
|
+
const summary = await getCompanyContextSummary(config.umbrellaUrl, config.companyId);
|
|
19
|
+
const spaces = toContextSpaces(summary);
|
|
20
|
+
if (normalizedAction === "list") {
|
|
21
|
+
await setSessionPanel("space", "list");
|
|
22
|
+
console.log(chalk.bold(`\n Spaces for ${config.companyName}\n`));
|
|
23
|
+
spaces.forEach((entry, index) => {
|
|
24
|
+
const active = entry.id === config.projectId ? " (active)" : "";
|
|
25
|
+
const primary = entry.isPrimary ? " [core]" : "";
|
|
26
|
+
console.log(` ${index + 1}. ${entry.name}${primary}${active}`);
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
action: "list",
|
|
30
|
+
changed: false,
|
|
31
|
+
companyName: config.companyName,
|
|
32
|
+
currentSpaceName: config.projectName,
|
|
33
|
+
spaces,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
if (normalizedAction === "create") {
|
|
37
|
+
let nextName = spaceArg?.trim() ?? "";
|
|
38
|
+
if (!nextName) {
|
|
37
39
|
const answer = await prompts({
|
|
38
|
-
type: "
|
|
40
|
+
type: "text",
|
|
39
41
|
name: "value",
|
|
40
|
-
message:
|
|
41
|
-
choices: spaces.map((entry) => ({
|
|
42
|
-
title: entry.isPrimary ? `${entry.name} (core)` : entry.name,
|
|
43
|
-
value: entry.id,
|
|
44
|
-
})),
|
|
42
|
+
message: `Name the new space for ${config.companyName}`,
|
|
45
43
|
});
|
|
46
|
-
|
|
44
|
+
nextName = answer.value?.trim() ?? "";
|
|
47
45
|
}
|
|
46
|
+
if (!nextName) {
|
|
47
|
+
console.log(chalk.yellow("\n No space name provided."));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const created = await createContextSpace(config.umbrellaUrl, config.companyId, nextName);
|
|
51
|
+
const createdSpaces = toContextSpaces(created);
|
|
52
|
+
const chosen = createdSpaces.find((entry) => entry.id === created.activeProjectId) ?? null;
|
|
48
53
|
if (!chosen) {
|
|
49
|
-
console.log(chalk.
|
|
54
|
+
console.log(chalk.red("\n The new space was created, but the CLI could not find it in the returned summary."));
|
|
50
55
|
return;
|
|
51
56
|
}
|
|
52
57
|
const setup = await getCliSetup(config.umbrellaUrl, config.companyId, chosen.id);
|
|
@@ -70,6 +75,97 @@ export function spaceCommand(cli) {
|
|
|
70
75
|
updatedAt: new Date().toISOString(),
|
|
71
76
|
});
|
|
72
77
|
await ensureRepoContext(configManager.config);
|
|
73
|
-
|
|
78
|
+
await setSessionPanel("space", setup.activeSpaceName);
|
|
79
|
+
await recordSessionEvent({
|
|
80
|
+
kind: "space",
|
|
81
|
+
title: `Created and switched to ${setup.activeSpaceName}`,
|
|
82
|
+
detail: `The repo is now linked to the new ${setup.companyName} space ${setup.activeSpaceName}.`,
|
|
83
|
+
panel: "space",
|
|
84
|
+
focus: setup.activeSpaceName,
|
|
85
|
+
status: "success",
|
|
86
|
+
});
|
|
87
|
+
console.log(chalk.green(`\n Created and switched to ${setup.companyName} / ${setup.activeSpaceName}`));
|
|
88
|
+
console.log(chalk.gray(" Pulling the latest shared Context snapshot for this space..."));
|
|
89
|
+
await pullCommandAction();
|
|
90
|
+
return {
|
|
91
|
+
action: "create",
|
|
92
|
+
changed: true,
|
|
93
|
+
companyName: setup.companyName,
|
|
94
|
+
currentSpaceName: setup.activeSpaceName,
|
|
95
|
+
spaces: createdSpaces,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (normalizedAction !== "switch") {
|
|
99
|
+
console.log(chalk.red("Use: umbrella-context space list | switch | create"));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
let chosen = spaces.find((entry) => entry.id === spaceArg || entry.name.toLowerCase() === (spaceArg ?? "").toLowerCase()) ?? null;
|
|
103
|
+
if (!chosen) {
|
|
104
|
+
const answer = await prompts({
|
|
105
|
+
type: "select",
|
|
106
|
+
name: "value",
|
|
107
|
+
message: "Choose a context space",
|
|
108
|
+
choices: spaces.map((entry) => ({
|
|
109
|
+
title: entry.isPrimary ? `${entry.name} (core)` : entry.name,
|
|
110
|
+
value: entry.id,
|
|
111
|
+
})),
|
|
112
|
+
});
|
|
113
|
+
chosen = spaces.find((entry) => entry.id === answer.value) ?? null;
|
|
114
|
+
}
|
|
115
|
+
if (!chosen) {
|
|
116
|
+
console.log(chalk.yellow("\n No space selected."));
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const setup = await getCliSetup(config.umbrellaUrl, config.companyId, chosen.id);
|
|
120
|
+
configManager.set({
|
|
121
|
+
umbrellaUrl: config.umbrellaUrl,
|
|
122
|
+
serverUrl: setup.baseUrl,
|
|
123
|
+
apiKey: setup.apiKey,
|
|
124
|
+
companyId: setup.companyId,
|
|
125
|
+
companyName: setup.companyName,
|
|
126
|
+
workspaceId: setup.workspaceId,
|
|
127
|
+
workspaceName: setup.workspaceName,
|
|
128
|
+
projectId: setup.activeSpaceId,
|
|
129
|
+
projectName: setup.activeSpaceName,
|
|
130
|
+
});
|
|
131
|
+
configManager.upsertLocation({
|
|
132
|
+
repoRoot: process.cwd(),
|
|
133
|
+
companyId: setup.companyId,
|
|
134
|
+
companyName: setup.companyName,
|
|
135
|
+
projectId: setup.activeSpaceId,
|
|
136
|
+
projectName: setup.activeSpaceName,
|
|
137
|
+
updatedAt: new Date().toISOString(),
|
|
138
|
+
});
|
|
139
|
+
await ensureRepoContext(configManager.config);
|
|
140
|
+
await setSessionPanel("space", setup.activeSpaceName);
|
|
141
|
+
await recordSessionEvent({
|
|
142
|
+
kind: "space",
|
|
143
|
+
title: `Switched repo to ${setup.activeSpaceName}`,
|
|
144
|
+
detail: `The active Context space for ${setup.companyName} is now ${setup.activeSpaceName}.`,
|
|
145
|
+
panel: "space",
|
|
146
|
+
focus: setup.activeSpaceName,
|
|
147
|
+
status: "success",
|
|
148
|
+
});
|
|
149
|
+
console.log(chalk.green(`\n Switched to ${setup.companyName} / ${setup.activeSpaceName}`));
|
|
150
|
+
console.log(chalk.gray(" Pulling the latest shared Context snapshot for this space..."));
|
|
151
|
+
await pullCommandAction();
|
|
152
|
+
return {
|
|
153
|
+
action: "switch",
|
|
154
|
+
changed: true,
|
|
155
|
+
companyName: setup.companyName,
|
|
156
|
+
currentSpaceName: setup.activeSpaceName,
|
|
157
|
+
spaces,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
export function spaceCommand(cli) {
|
|
161
|
+
cli
|
|
162
|
+
.command("space <action> [space]", "List, switch, or create context spaces for the current company")
|
|
163
|
+
.action(async (action, spaceArg) => {
|
|
164
|
+
try {
|
|
165
|
+
await spaceCommandAction(action, spaceArg);
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
console.log(chalk.red(`Could not load spaces: ${err.message}`));
|
|
169
|
+
}
|
|
74
170
|
});
|
|
75
171
|
}
|
|
@@ -1,2 +1,31 @@
|
|
|
1
|
+
export type StatusSnapshot = {
|
|
2
|
+
companyName: string;
|
|
3
|
+
spaceName: string;
|
|
4
|
+
umbrellaUrl: string | null;
|
|
5
|
+
serverUrl: string;
|
|
6
|
+
currentDirectory: string;
|
|
7
|
+
repoRoot: string;
|
|
8
|
+
umDir: string;
|
|
9
|
+
pendingCount: number;
|
|
10
|
+
pulledContextCount: number;
|
|
11
|
+
pulledFixCount: number;
|
|
12
|
+
lastPushAt: string;
|
|
13
|
+
lastPullAt: string;
|
|
14
|
+
hubEntriesCount: number;
|
|
15
|
+
connectorsCount: number;
|
|
16
|
+
mcpConfigured: boolean;
|
|
17
|
+
latestConnectorRun: string;
|
|
18
|
+
providerLabel: string;
|
|
19
|
+
modelLabel: string;
|
|
20
|
+
currentPanel: string;
|
|
21
|
+
currentFocus: string;
|
|
22
|
+
latestEvent: string;
|
|
23
|
+
transportStatus: string;
|
|
24
|
+
transportQueue: number;
|
|
25
|
+
transportActiveTask: string;
|
|
26
|
+
contextTreeSummary: string;
|
|
27
|
+
nextSteps: string[];
|
|
28
|
+
};
|
|
29
|
+
export declare function getStatusSnapshot(): Promise<StatusSnapshot>;
|
|
1
30
|
export declare function statusCommandAction(): Promise<void>;
|
|
2
31
|
export declare function statusCommand(cli: any): void;
|
package/dist/commands/status.js
CHANGED
|
@@ -1,29 +1,130 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
+
import { promises as fs } from "fs";
|
|
3
|
+
import path from "path";
|
|
2
4
|
import { configManager } from "../config.js";
|
|
3
|
-
import { getPendingMemories, getPulledFixes, getPulledMemories, getRepoContext } from "../repo-state.js";
|
|
4
|
-
export async function
|
|
5
|
+
import { getConnectorRuns, getContextTreeState, getInstalledConnectors, getInstalledHubEntries, getPendingMemories, getPulledFixes, getPulledMemories, getRepoContext, ensureSessionState, getTransportState, } from "../repo-state.js";
|
|
6
|
+
export async function getStatusSnapshot() {
|
|
5
7
|
const config = configManager.config;
|
|
6
8
|
if (!config) {
|
|
7
|
-
|
|
8
|
-
return;
|
|
9
|
+
throw new Error("Not configured. Run: umbrella-context setup");
|
|
9
10
|
}
|
|
10
11
|
const { repoRoot, state, umDir } = await getRepoContext();
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const pulledFixes = await
|
|
12
|
+
const session = await ensureSessionState();
|
|
13
|
+
const latestEvent = session.events?.[0] ?? null;
|
|
14
|
+
const [pending, pulledMemories, pulledFixes, connectors, hubEntries, connectorRuns, transport, contextTree] = await Promise.all([
|
|
15
|
+
getPendingMemories(),
|
|
16
|
+
getPulledMemories(),
|
|
17
|
+
getPulledFixes(),
|
|
18
|
+
getInstalledConnectors(),
|
|
19
|
+
getInstalledHubEntries(),
|
|
20
|
+
getConnectorRuns(),
|
|
21
|
+
getTransportState(),
|
|
22
|
+
getContextTreeState(),
|
|
23
|
+
]);
|
|
24
|
+
const activeProvider = configManager.providers.find((entry) => entry.id === config.activeProvider) ?? null;
|
|
25
|
+
const latestConnectorRun = connectorRuns[0] ?? null;
|
|
26
|
+
let mcpConfigured = false;
|
|
27
|
+
try {
|
|
28
|
+
const repoMcp = JSON.parse(await fs.readFile(path.join(repoRoot, ".mcp.json"), "utf8"));
|
|
29
|
+
mcpConfigured = Boolean(repoMcp?.mcpServers?.["umbrella-context"]);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
mcpConfigured = false;
|
|
33
|
+
}
|
|
34
|
+
const nextSteps = [];
|
|
35
|
+
if (pending.length > 0)
|
|
36
|
+
nextSteps.push(`Run "umbrella-context push" to share ${pending.length} local draft${pending.length === 1 ? "" : "s"}.`);
|
|
37
|
+
if (!activeProvider || !config.activeModel) {
|
|
38
|
+
nextSteps.push('Finish runtime setup with "umbrella-context providers setup".');
|
|
39
|
+
}
|
|
40
|
+
if (!mcpConfigured)
|
|
41
|
+
nextSteps.push('Install the MCP bridge with "umbrella-context connectors install codex-mcp".');
|
|
42
|
+
if (connectors.length === 0)
|
|
43
|
+
nextSteps.push('Add a first repo connector with "umbrella-context connectors install".');
|
|
44
|
+
if (hubEntries.length === 0)
|
|
45
|
+
nextSteps.push('Browse reusable bundles with "umbrella-context hub list".');
|
|
46
|
+
return {
|
|
47
|
+
companyName: config.companyName,
|
|
48
|
+
spaceName: config.projectName,
|
|
49
|
+
umbrellaUrl: config.umbrellaUrl ?? null,
|
|
50
|
+
serverUrl: config.serverUrl,
|
|
51
|
+
currentDirectory: process.cwd(),
|
|
52
|
+
repoRoot,
|
|
53
|
+
umDir,
|
|
54
|
+
pendingCount: pending.length,
|
|
55
|
+
pulledContextCount: pulledMemories.length,
|
|
56
|
+
pulledFixCount: pulledFixes.length,
|
|
57
|
+
lastPushAt: state?.lastPushAt ?? "Never",
|
|
58
|
+
lastPullAt: state?.lastPullAt ?? "Never",
|
|
59
|
+
hubEntriesCount: hubEntries.length,
|
|
60
|
+
connectorsCount: connectors.length,
|
|
61
|
+
mcpConfigured,
|
|
62
|
+
latestConnectorRun: latestConnectorRun
|
|
63
|
+
? `${latestConnectorRun.connectorName} (${latestConnectorRun.status}) at ${latestConnectorRun.ranAt}`
|
|
64
|
+
: "Never",
|
|
65
|
+
providerLabel: activeProvider ? `${activeProvider.name} (${activeProvider.kind})` : "Not connected",
|
|
66
|
+
modelLabel: config.activeModel ?? "Not selected",
|
|
67
|
+
currentPanel: session.currentPanel ?? "Home",
|
|
68
|
+
currentFocus: session.currentFocus ?? "None",
|
|
69
|
+
latestEvent: latestEvent ? `${latestEvent.title} (${latestEvent.status})` : "No session events yet",
|
|
70
|
+
transportStatus: transport?.status ?? "unknown",
|
|
71
|
+
transportQueue: transport?.queue.length ?? 0,
|
|
72
|
+
transportActiveTask: transport?.activeTaskId ?? "None",
|
|
73
|
+
contextTreeSummary: contextTree?.summaryHandle ?? "No context tree summary yet",
|
|
74
|
+
nextSteps,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export async function statusCommandAction() {
|
|
78
|
+
let snapshot;
|
|
79
|
+
try {
|
|
80
|
+
snapshot = await getStatusSnapshot();
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
console.log(chalk.red(err.message));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
14
86
|
console.log(chalk.bold("\n Umbrella Context Status\n"));
|
|
15
|
-
console.log(
|
|
16
|
-
console.log(`
|
|
17
|
-
console.log(`
|
|
18
|
-
console.log(`
|
|
19
|
-
console.log(`
|
|
20
|
-
console.log(
|
|
21
|
-
console.log(
|
|
22
|
-
console.log(`
|
|
23
|
-
console.log(`
|
|
24
|
-
console.log(`
|
|
25
|
-
console.log(`
|
|
26
|
-
console.log(`
|
|
87
|
+
console.log(chalk.cyan(" Connection"));
|
|
88
|
+
console.log(` Company: ${snapshot.companyName}`);
|
|
89
|
+
console.log(` Space: ${snapshot.spaceName}`);
|
|
90
|
+
console.log(` Umbrella: ${snapshot.umbrellaUrl ?? "Not saved"}`);
|
|
91
|
+
console.log(` Context Backend: ${snapshot.serverUrl}`);
|
|
92
|
+
console.log("");
|
|
93
|
+
console.log(chalk.cyan(" Local Repo"));
|
|
94
|
+
console.log(` Current Directory: ${snapshot.currentDirectory}`);
|
|
95
|
+
console.log(` Repo Root: ${snapshot.repoRoot}`);
|
|
96
|
+
console.log(` Local Context Folder: ${snapshot.umDir}`);
|
|
97
|
+
console.log(` Pending Local Context: ${snapshot.pendingCount}`);
|
|
98
|
+
console.log(` Pulled Context Snapshot: ${snapshot.pulledContextCount}`);
|
|
99
|
+
console.log(` Pulled Known Fixes: ${snapshot.pulledFixCount}`);
|
|
100
|
+
console.log(` Last Push: ${snapshot.lastPushAt}`);
|
|
101
|
+
console.log(` Last Pull: ${snapshot.lastPullAt}`);
|
|
102
|
+
console.log("");
|
|
103
|
+
console.log(chalk.cyan(" Repo Ecosystem"));
|
|
104
|
+
console.log(` Hub Entries Installed: ${snapshot.hubEntriesCount}`);
|
|
105
|
+
console.log(` Connectors Installed: ${snapshot.connectorsCount}`);
|
|
106
|
+
console.log(` Repo MCP Wired: ${snapshot.mcpConfigured ? "Yes" : "No"}`);
|
|
107
|
+
console.log(` Last Connector Run: ${snapshot.latestConnectorRun}`);
|
|
108
|
+
console.log("");
|
|
109
|
+
console.log(chalk.cyan(" Model Runtime"));
|
|
110
|
+
console.log(` Provider: ${snapshot.providerLabel}`);
|
|
111
|
+
console.log(` Model: ${snapshot.modelLabel}`);
|
|
112
|
+
console.log(` Session Panel: ${snapshot.currentPanel}`);
|
|
113
|
+
console.log(` Session Focus: ${snapshot.currentFocus}`);
|
|
114
|
+
console.log(` Latest Session Event: ${snapshot.latestEvent}`);
|
|
115
|
+
console.log(` Transport Status: ${snapshot.transportStatus}`);
|
|
116
|
+
console.log(` Transport Queue: ${snapshot.transportQueue}`);
|
|
117
|
+
console.log(` Active Task: ${snapshot.transportActiveTask}`);
|
|
118
|
+
console.log("");
|
|
119
|
+
console.log(chalk.cyan(" Context Tree"));
|
|
120
|
+
console.log(` Summary: ${snapshot.contextTreeSummary}`);
|
|
121
|
+
if (snapshot.nextSteps.length > 0) {
|
|
122
|
+
console.log("");
|
|
123
|
+
console.log(chalk.cyan(" Suggested Next Steps"));
|
|
124
|
+
snapshot.nextSteps.forEach((step) => {
|
|
125
|
+
console.log(` - ${step}`);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
27
128
|
}
|
|
28
129
|
export function statusCommand(cli) {
|
|
29
130
|
cli.command("status", "Show the current repo, company, space, and local sync state").action(async () => {
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { getTaskById, getTasks, getTransportState, setSessionPanel } from "../repo-state.js";
|
|
3
|
+
export async function tasksCommandAction(action, target) {
|
|
4
|
+
await setSessionPanel("tasks", action === "inspect" ? target ?? "inspect" : "list");
|
|
5
|
+
const [tasks, transport] = await Promise.all([getTasks(), getTransportState()]);
|
|
6
|
+
if ((action ?? "list") === "inspect") {
|
|
7
|
+
const defaultTask = (transport?.activeTaskId ? await getTaskById(transport.activeTaskId) : null) ??
|
|
8
|
+
tasks[0] ??
|
|
9
|
+
null;
|
|
10
|
+
const task = target ? await getTaskById(target) : defaultTask;
|
|
11
|
+
if (!task) {
|
|
12
|
+
console.log(chalk.yellow("\n No task found to inspect."));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
console.log(chalk.bold(`\n Task ${task.id}\n`));
|
|
16
|
+
console.log(` Kind: ${task.kind}`);
|
|
17
|
+
console.log(` Title: ${task.title}`);
|
|
18
|
+
console.log(` Status: ${task.status}`);
|
|
19
|
+
console.log(` Created: ${new Date(task.createdAt).toLocaleString()}`);
|
|
20
|
+
console.log(` Started: ${task.startedAt ? new Date(task.startedAt).toLocaleString() : "Not started"}`);
|
|
21
|
+
console.log(` Finished: ${task.finishedAt ? new Date(task.finishedAt).toLocaleString() : "Not finished"}`);
|
|
22
|
+
console.log(` Focus: ${task.focus ?? "None"}`);
|
|
23
|
+
console.log(` Panel: ${task.panel ?? "None"}`);
|
|
24
|
+
console.log(` Session: ${task.sessionId ?? "None"}`);
|
|
25
|
+
console.log(` Result: ${task.result ?? "No final result yet"}`);
|
|
26
|
+
console.log(` Reasoning items: ${task.reasoningContents?.length ?? 0}`);
|
|
27
|
+
console.log(` Tool calls: ${task.toolCalls?.length ?? 0}`);
|
|
28
|
+
if (task.detail) {
|
|
29
|
+
console.log("");
|
|
30
|
+
console.log(chalk.cyan(" Detail"));
|
|
31
|
+
console.log(` ${task.detail}`);
|
|
32
|
+
}
|
|
33
|
+
if (task.streamingContent) {
|
|
34
|
+
console.log("");
|
|
35
|
+
console.log(chalk.cyan(" Streaming"));
|
|
36
|
+
console.log(` ${task.streamingContent}`);
|
|
37
|
+
}
|
|
38
|
+
if ((task.reasoningContents?.length ?? 0) > 0) {
|
|
39
|
+
console.log("");
|
|
40
|
+
console.log(chalk.cyan(" Reasoning"));
|
|
41
|
+
task.reasoningContents?.forEach((item, index) => {
|
|
42
|
+
console.log(` ${index + 1}. ${item.content}`);
|
|
43
|
+
console.log(chalk.gray(` ${new Date(item.timestamp).toLocaleString()}${item.isThinking ? " | thinking" : ""}`));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if ((task.toolCalls?.length ?? 0) > 0) {
|
|
47
|
+
console.log("");
|
|
48
|
+
console.log(chalk.cyan(" Tool Calls"));
|
|
49
|
+
task.toolCalls?.forEach((call, index) => {
|
|
50
|
+
console.log(` ${index + 1}. ${call.toolName} (${call.status})`);
|
|
51
|
+
console.log(chalk.gray(` ${new Date(call.timestamp).toLocaleString()}`));
|
|
52
|
+
console.log(chalk.gray(` args: ${JSON.stringify(call.args)}`));
|
|
53
|
+
if (call.result !== undefined) {
|
|
54
|
+
console.log(chalk.gray(` result: ${JSON.stringify(call.result)}`));
|
|
55
|
+
}
|
|
56
|
+
if (call.error) {
|
|
57
|
+
console.log(chalk.red(` error: ${call.error}`));
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
console.log(chalk.bold("\n Local Context Tasks\n"));
|
|
64
|
+
if (transport) {
|
|
65
|
+
console.log(chalk.cyan(" Transport"));
|
|
66
|
+
console.log(` Status: ${transport.status}`);
|
|
67
|
+
console.log(` Active task: ${transport.activeTaskId ?? "None"}`);
|
|
68
|
+
console.log(` Queue: ${transport.queue.length}`);
|
|
69
|
+
console.log(` Stats: queued=${transport.stats.queued} running=${transport.stats.running} completed=${transport.stats.completed} failed=${transport.stats.failed}`);
|
|
70
|
+
console.log("");
|
|
71
|
+
}
|
|
72
|
+
if (tasks.length === 0) {
|
|
73
|
+
console.log(chalk.yellow(" No local tasks yet."));
|
|
74
|
+
console.log(chalk.gray(" Ask a question, save a local note, or run push/pull to create task history."));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
tasks.slice(0, 20).forEach((task, index) => {
|
|
78
|
+
console.log(` ${index + 1}. [${task.kind}] ${task.title}`);
|
|
79
|
+
console.log(chalk.gray(` Status: ${task.status} | Updated: ${new Date(task.updatedAt).toLocaleString()}`));
|
|
80
|
+
if (task.detail) {
|
|
81
|
+
console.log(chalk.gray(` ${task.detail}`));
|
|
82
|
+
}
|
|
83
|
+
if (task.result) {
|
|
84
|
+
console.log(chalk.gray(` Result: ${task.result}`));
|
|
85
|
+
}
|
|
86
|
+
if (task.toolCalls?.length) {
|
|
87
|
+
console.log(chalk.gray(` Tool calls: ${task.toolCalls.length}`));
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
export function tasksCommand(cli) {
|
|
92
|
+
cli.command("tasks [action] [target]", "Show or inspect the local .um task history for this repo").action(async (action, target) => {
|
|
93
|
+
await tasksCommandAction(action, target);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { getTaskById, getTransportState, setSessionPanel } from "../repo-state.js";
|
|
3
|
+
export async function transportCommandAction(action, target) {
|
|
4
|
+
const transport = await getTransportState();
|
|
5
|
+
const mode = (action ?? "status").toLowerCase();
|
|
6
|
+
await setSessionPanel("transport", mode === "inspect" ? target ?? "inspect" : mode);
|
|
7
|
+
if (mode === "events" || mode === "timeline") {
|
|
8
|
+
console.log(chalk.bold("\n Transport Timeline\n"));
|
|
9
|
+
if (transport.events.length === 0) {
|
|
10
|
+
console.log(chalk.yellow(" No transport events recorded yet."));
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
transport.events.slice(0, 20).forEach((event, index) => {
|
|
14
|
+
console.log(` ${index + 1}. [${event.kind}] ${event.title}`);
|
|
15
|
+
console.log(chalk.gray(` ${new Date(event.at).toLocaleString()} | ${event.status}`));
|
|
16
|
+
if (event.detail) {
|
|
17
|
+
console.log(chalk.gray(` ${event.detail}`));
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (mode === "inspect") {
|
|
23
|
+
const taskId = target ?? transport.activeTaskId ?? transport.queue[0]?.id ?? null;
|
|
24
|
+
if (!taskId) {
|
|
25
|
+
console.log(chalk.yellow("\n No transport-linked task is available to inspect."));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const task = await getTaskById(taskId);
|
|
29
|
+
if (!task) {
|
|
30
|
+
console.log(chalk.yellow(`\n Task ${taskId} is no longer available in local task history.`));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const relatedEvents = transport.events.filter((event) => event.taskId === taskId);
|
|
34
|
+
console.log(chalk.bold(`\n Transport Inspect for ${task.title}\n`));
|
|
35
|
+
console.log(` Task ID: ${task.id}`);
|
|
36
|
+
console.log(` Status: ${task.status}`);
|
|
37
|
+
console.log(` Kind: ${task.kind}`);
|
|
38
|
+
console.log(` Queue position: ${Math.max(transport.queue.findIndex((item) => item.id === taskId), 0) + 1}`);
|
|
39
|
+
console.log(` Related events: ${relatedEvents.length}`);
|
|
40
|
+
if (relatedEvents.length > 0) {
|
|
41
|
+
console.log("");
|
|
42
|
+
console.log(chalk.cyan(" Event Timeline"));
|
|
43
|
+
relatedEvents.forEach((event, index) => {
|
|
44
|
+
console.log(` ${index + 1}. [${event.kind}] ${event.title}`);
|
|
45
|
+
console.log(chalk.gray(` ${new Date(event.at).toLocaleString()} | ${event.status}`));
|
|
46
|
+
if (event.detail) {
|
|
47
|
+
console.log(chalk.gray(` ${event.detail}`));
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
console.log(chalk.bold("\n Transport Engine\n"));
|
|
54
|
+
console.log(` Status: ${transport.status}`);
|
|
55
|
+
console.log(` Active task: ${transport.activeTaskId ?? "None"}`);
|
|
56
|
+
console.log(` Queue: ${transport.queue.length}`);
|
|
57
|
+
console.log(` Stats: queued=${transport.stats.queued} running=${transport.stats.running} completed=${transport.stats.completed} failed=${transport.stats.failed}`);
|
|
58
|
+
console.log(` Subscriptions: ${transport.subscriptions.join(", ")}`);
|
|
59
|
+
console.log(` Last push: ${transport.lastPushAt ?? "Never"}`);
|
|
60
|
+
console.log(` Last pull: ${transport.lastPullAt ?? "Never"}`);
|
|
61
|
+
console.log(` Last runtime check: ${transport.lastRuntimeCheckAt ?? "Never"}`);
|
|
62
|
+
if (Object.keys(transport.taskKinds ?? {}).length > 0) {
|
|
63
|
+
console.log(` Task kinds: ${Object.entries(transport.taskKinds)
|
|
64
|
+
.map(([kind, count]) => `${kind}=${count}`)
|
|
65
|
+
.join(", ")}`);
|
|
66
|
+
}
|
|
67
|
+
console.log("");
|
|
68
|
+
if (transport.queue.length > 0) {
|
|
69
|
+
console.log(chalk.cyan(" Queue"));
|
|
70
|
+
transport.queue.forEach((task, index) => {
|
|
71
|
+
console.log(` ${index + 1}. [${task.kind}] ${task.title} (${task.status})`);
|
|
72
|
+
});
|
|
73
|
+
console.log("");
|
|
74
|
+
}
|
|
75
|
+
if (transport.events.length > 0) {
|
|
76
|
+
console.log(chalk.cyan(" Recent events"));
|
|
77
|
+
transport.events.slice(0, 8).forEach((event, index) => {
|
|
78
|
+
console.log(` ${index + 1}. [${event.kind}] ${event.title}`);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export function transportCommand(cli) {
|
|
83
|
+
cli
|
|
84
|
+
.command("transport [action] [target]", "Show the live local transport engine and timeline")
|
|
85
|
+
.action(async (action, target) => {
|
|
86
|
+
await transportCommandAction(action, target);
|
|
87
|
+
});
|
|
88
|
+
}
|