@pellux/goodvibes-agent 1.8.0 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +1 -1
- package/dist/package/{ast-grep-napi.linux-x64-gnu-mkk8xwww.node → ast-grep-napi.linux-x64-gnu-44ar68xs.node} +0 -0
- package/dist/package/{ast-grep-napi.linux-x64-musl-ryqtgdv6.node → ast-grep-napi.linux-x64-musl-asvc2tv1.node} +0 -0
- package/dist/package/main.js +135434 -118764
- package/dist/package/{web-tree-sitter-vmqc5d26.wasm → web-tree-sitter-jbz042ba.wasm} +0 -0
- package/docs/tools-and-commands.md +9 -0
- package/package.json +3 -2
- package/src/agent/capability-registry.ts +300 -0
- package/src/agent/email/style-reply-lane.ts +13 -4
- package/src/agent/memory-consolidation-receipts.ts +79 -0
- package/src/agent/memory-prompt.ts +3 -1
- package/src/agent/operator-gateway-call.ts +134 -0
- package/src/agent/principal-attribution.ts +97 -0
- package/src/agent/prompt-context-receipts.ts +5 -1
- package/src/agent/unified-inbox.ts +17 -1
- package/src/cli/bundle-command.ts +2 -1
- package/src/cli/channel-profiles-command.ts +168 -0
- package/src/cli/ci-command.ts +214 -0
- package/src/cli/completion.ts +5 -0
- package/src/cli/connected-host-metrics.ts +165 -0
- package/src/cli/entrypoint.ts +25 -1
- package/src/cli/fleet-command.ts +178 -0
- package/src/cli/help.ts +115 -0
- package/src/cli/import-command.ts +208 -0
- package/src/cli/index.ts +1 -0
- package/src/cli/management-commands.ts +9 -8
- package/src/cli/management.ts +42 -0
- package/src/cli/memory-command.ts +4 -3
- package/src/cli/openclaw-import.ts +382 -0
- package/src/cli/operator-command-args.ts +88 -0
- package/src/cli/parser.ts +12 -0
- package/src/cli/personas-command.ts +3 -2
- package/src/cli/principals-command.ts +230 -0
- package/src/cli/profiles-command.ts +2 -1
- package/src/cli/relay-command.ts +100 -0
- package/src/cli/routines-command.ts +4 -3
- package/src/cli/skill-bundle-command.ts +3 -2
- package/src/cli/skills-command.ts +3 -2
- package/src/cli/status.ts +114 -2
- package/src/cli/temporal-label.ts +89 -0
- package/src/cli/types.ts +7 -0
- package/src/cli/workspaces-command.ts +135 -0
- package/src/config/agent-settings-policy.ts +8 -0
- package/src/config/checkpoint-settings.ts +113 -0
- package/src/config/workspace-registration.ts +299 -0
- package/src/core/rewind-turn-anchors.ts +82 -0
- package/src/input/agent-workspace-categories.ts +1 -0
- package/src/input/agent-workspace-channel-triage.ts +27 -8
- package/src/input/agent-workspace-local-library-snapshot.ts +5 -1
- package/src/input/agent-workspace-onboarding-categories.ts +17 -1
- package/src/input/agent-workspace-snapshot.ts +25 -3
- package/src/input/agent-workspace-types.ts +5 -5
- package/src/input/commands/connected-host-admin-runtime.ts +75 -0
- package/src/input/commands.ts +2 -0
- package/src/input/settings-modal-types.ts +16 -5
- package/src/main.ts +17 -12
- package/src/permissions/approval-posture.ts +40 -5
- package/src/permissions/prompt.ts +35 -1
- package/src/renderer/settings-modal-helpers.ts +11 -0
- package/src/renderer/settings-modal.ts +21 -0
- package/src/renderer/terminal-escapes.ts +65 -12
- package/src/runtime/agent-runtime-events.ts +102 -3
- package/src/runtime/bootstrap-core.ts +111 -10
- package/src/runtime/bootstrap-external-services.ts +156 -0
- package/src/runtime/bootstrap.ts +73 -69
- package/src/runtime/context-accounting-source.ts +114 -0
- package/src/runtime/conversation-rewind-port.ts +133 -0
- package/src/runtime/index.ts +8 -28
- package/src/runtime/memory-consolidation-scheduler.ts +67 -0
- package/src/runtime/memory-consolidation-wiring.ts +56 -0
- package/src/runtime/memory-usage-wiring.ts +75 -0
- package/src/runtime/services.ts +257 -6
- package/src/runtime/tool-permission-safety.ts +18 -1
- package/src/shell/blocking-input.ts +38 -8
- package/src/shell/startup-wiring.ts +26 -1
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-harness-cli-command-policy.ts +29 -3
- package/src/tools/agent-harness-learning-auto-promote.ts +7 -3
- package/src/tools/agent-harness-memory-posture.ts +57 -2
- package/src/tools/agent-harness-metadata.ts +12 -0
- package/src/tools/agent-harness-mode-catalog.ts +1 -1
- package/src/tools/agent-harness-personal-ops-lanes.ts +8 -6
- package/src/tools/agent-harness-prompt-context.ts +3 -1
- package/src/tools/agent-harness-tool.ts +3 -2
- package/src/tools/agent-policy-explanation.ts +40 -0
- package/src/tools/tool-definition-compaction.ts +2 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { isAbsolute, resolve } from 'node:path';
|
|
2
|
+
import {
|
|
3
|
+
MemoryEmbeddingProviderRegistry,
|
|
4
|
+
MemoryRegistry,
|
|
5
|
+
MemoryStore,
|
|
6
|
+
resolveCanonicalMemoryDbPath,
|
|
7
|
+
} from '@pellux/goodvibes-sdk/platform/state';
|
|
8
|
+
import { assertNoSecretLikeMemoryText } from '../agent/memory-safety.ts';
|
|
9
|
+
import { buildAgentSkillRequirements } from '../agent/skill-registry.ts';
|
|
10
|
+
import type { CliCommandOutput } from './types.ts';
|
|
11
|
+
import type { CliCommandRuntime } from './management.ts';
|
|
12
|
+
import { failure, personaRegistry, skillRegistry, success } from './local-library-command-shared.ts';
|
|
13
|
+
import {
|
|
14
|
+
OPENCLAW_LAYOUT_VERSION,
|
|
15
|
+
scanOpenClawWorkspace,
|
|
16
|
+
type OpenClawImportPlan,
|
|
17
|
+
} from './openclaw-import.ts';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* `goodvibes-agent import openclaw [path]` — migrate an OpenClaw workspace into
|
|
21
|
+
* the Agent's existing registries. Dry-run is the DEFAULT (prints what would be
|
|
22
|
+
* created); --apply performs the writes through the persona registry, the
|
|
23
|
+
* canonical memory store, the skill registry, and the permission settings. No
|
|
24
|
+
* parallel storage is invented. See openclaw-import.ts for the targeted layout.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
interface ApplyCounts {
|
|
28
|
+
created: number;
|
|
29
|
+
skipped: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resolveSourcePath(runtime: CliCommandRuntime, arg: string | undefined): string {
|
|
33
|
+
// Home is taken from the runtime's owned home root (the composition root passes
|
|
34
|
+
// it in), never discovered implicitly. Default workspace is <home>/.openclaw.
|
|
35
|
+
if (!arg) return resolve(runtime.homeDirectory, '.openclaw');
|
|
36
|
+
if (arg.startsWith('~')) return resolve(runtime.homeDirectory, arg.slice(1).replace(/^[/\\]/, ''));
|
|
37
|
+
if (isAbsolute(arg)) return arg;
|
|
38
|
+
return resolve(runtime.workingDirectory, arg);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function planSummaryLines(plan: OpenClawImportPlan): string[] {
|
|
42
|
+
const lines: string[] = [];
|
|
43
|
+
lines.push(` personas: ${plan.personas.length}`);
|
|
44
|
+
for (const persona of plan.personas) lines.push(` - ${persona.name} (${persona.sourcePath})`);
|
|
45
|
+
lines.push(` memory records: ${plan.memories.length}`);
|
|
46
|
+
for (const memory of plan.memories) lines.push(` - ${memory.scope}/${memory.cls} ${memory.summary}`);
|
|
47
|
+
lines.push(` skills: ${plan.skills.length}`);
|
|
48
|
+
for (const skill of plan.skills) lines.push(` - ${skill.name} (${skill.sourcePath})`);
|
|
49
|
+
const perm = plan.permissions;
|
|
50
|
+
lines.push(` permission allowlist: ${perm.categories.length} categor${perm.categories.length === 1 ? 'y' : 'ies'}${perm.sourcePath ? ` (${perm.sourcePath})` : ''}`);
|
|
51
|
+
if (perm.categories.length > 0) lines.push(` - allow: ${perm.categories.join(', ')} (mode -> custom)`);
|
|
52
|
+
lines.push(` skipped: ${plan.skipped.length}`);
|
|
53
|
+
for (const entry of plan.skipped) lines.push(` - ${entry.path}: ${entry.reason}`);
|
|
54
|
+
return lines;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function renderDryRun(plan: OpenClawImportPlan): string {
|
|
58
|
+
return [
|
|
59
|
+
`OpenClaw import (dry run) — layout ${OPENCLAW_LAYOUT_VERSION}`,
|
|
60
|
+
` source ${plan.sourcePath}`,
|
|
61
|
+
...planSummaryLines(plan),
|
|
62
|
+
'',
|
|
63
|
+
' This is a preview. Re-run with --apply to write these into the Agent registries.',
|
|
64
|
+
].join('\n');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function applyMemories(
|
|
68
|
+
runtime: CliCommandRuntime,
|
|
69
|
+
plan: OpenClawImportPlan,
|
|
70
|
+
notes: string[],
|
|
71
|
+
): Promise<ApplyCounts> {
|
|
72
|
+
const counts: ApplyCounts = { created: 0, skipped: 0 };
|
|
73
|
+
if (plan.memories.length === 0) return counts;
|
|
74
|
+
const path = resolveCanonicalMemoryDbPath(runtime.homeDirectory);
|
|
75
|
+
const embeddingRegistry = new MemoryEmbeddingProviderRegistry({ configManager: runtime.configManager });
|
|
76
|
+
const store = new MemoryStore(path, { embeddingRegistry });
|
|
77
|
+
await store.init();
|
|
78
|
+
const registry = new MemoryRegistry(store);
|
|
79
|
+
try {
|
|
80
|
+
for (const memory of plan.memories) {
|
|
81
|
+
try {
|
|
82
|
+
assertNoSecretLikeMemoryText([memory.summary, memory.detail ?? '', ...memory.tags]);
|
|
83
|
+
await registry.add({
|
|
84
|
+
scope: memory.scope as 'session' | 'project' | 'team',
|
|
85
|
+
cls: memory.cls as 'fact',
|
|
86
|
+
summary: memory.summary,
|
|
87
|
+
detail: memory.detail,
|
|
88
|
+
tags: [...memory.tags],
|
|
89
|
+
provenance: [{ kind: 'event', ref: `openclaw-import:${memory.sourcePath}` }],
|
|
90
|
+
});
|
|
91
|
+
counts.created += 1;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
counts.skipped += 1;
|
|
94
|
+
notes.push(` memory skipped (${memory.summary}): ${error instanceof Error ? error.message : String(error)}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
} finally {
|
|
98
|
+
await store.save();
|
|
99
|
+
store.close();
|
|
100
|
+
}
|
|
101
|
+
return counts;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function applyPersonas(runtime: CliCommandRuntime, plan: OpenClawImportPlan, notes: string[]): ApplyCounts {
|
|
105
|
+
const counts: ApplyCounts = { created: 0, skipped: 0 };
|
|
106
|
+
const registry = personaRegistry(runtime);
|
|
107
|
+
for (const persona of plan.personas) {
|
|
108
|
+
try {
|
|
109
|
+
registry.create({
|
|
110
|
+
name: persona.name,
|
|
111
|
+
description: persona.description,
|
|
112
|
+
body: persona.body,
|
|
113
|
+
tags: [...persona.tags],
|
|
114
|
+
source: 'imported',
|
|
115
|
+
provenance: `openclaw-import:${persona.sourcePath}`,
|
|
116
|
+
});
|
|
117
|
+
counts.created += 1;
|
|
118
|
+
} catch (error) {
|
|
119
|
+
counts.skipped += 1;
|
|
120
|
+
notes.push(` persona skipped (${persona.name}): ${error instanceof Error ? error.message : String(error)}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return counts;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function applySkills(runtime: CliCommandRuntime, plan: OpenClawImportPlan, notes: string[]): ApplyCounts {
|
|
127
|
+
const counts: ApplyCounts = { created: 0, skipped: 0 };
|
|
128
|
+
const registry = skillRegistry(runtime);
|
|
129
|
+
for (const skill of plan.skills) {
|
|
130
|
+
try {
|
|
131
|
+
registry.create({
|
|
132
|
+
name: skill.name,
|
|
133
|
+
description: skill.description,
|
|
134
|
+
procedure: skill.procedure,
|
|
135
|
+
tags: [...skill.tags],
|
|
136
|
+
requirements: buildAgentSkillRequirements({ env: skill.requiresEnv, commands: skill.requiresCommand }),
|
|
137
|
+
source: 'imported',
|
|
138
|
+
provenance: `openclaw-import:${skill.sourcePath}`,
|
|
139
|
+
});
|
|
140
|
+
counts.created += 1;
|
|
141
|
+
} catch (error) {
|
|
142
|
+
counts.skipped += 1;
|
|
143
|
+
notes.push(` skill skipped (${skill.name}): ${error instanceof Error ? error.message : String(error)}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return counts;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function applyPermissions(runtime: CliCommandRuntime, plan: OpenClawImportPlan): number {
|
|
150
|
+
const categories = plan.permissions.categories;
|
|
151
|
+
if (categories.length === 0) return 0;
|
|
152
|
+
runtime.configManager.setDynamic('permissions.mode', 'custom');
|
|
153
|
+
for (const category of categories) {
|
|
154
|
+
runtime.configManager.setDynamic(`permissions.tools.${category}` as never, 'allow');
|
|
155
|
+
}
|
|
156
|
+
return categories.length;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function renderApply(runtime: CliCommandRuntime, plan: OpenClawImportPlan): Promise<string> {
|
|
160
|
+
const notes: string[] = [];
|
|
161
|
+
const personas = applyPersonas(runtime, plan, notes);
|
|
162
|
+
const memories = await applyMemories(runtime, plan, notes);
|
|
163
|
+
const skills = applySkills(runtime, plan, notes);
|
|
164
|
+
const permissionCategories = applyPermissions(runtime, plan);
|
|
165
|
+
return [
|
|
166
|
+
`OpenClaw import (applied) — layout ${OPENCLAW_LAYOUT_VERSION}`,
|
|
167
|
+
` source ${plan.sourcePath}`,
|
|
168
|
+
` personas created ${personas.created}${personas.skipped ? ` (skipped ${personas.skipped})` : ''}`,
|
|
169
|
+
` memory records created ${memories.created}${memories.skipped ? ` (skipped ${memories.skipped})` : ''}`,
|
|
170
|
+
` skills created ${skills.created}${skills.skipped ? ` (skipped ${skills.skipped})` : ''}`,
|
|
171
|
+
` permission categories allowed ${permissionCategories}${permissionCategories ? ` (${plan.permissions.categories.join(', ')}; mode -> custom)` : ''}`,
|
|
172
|
+
` input files skipped ${plan.skipped.length}`,
|
|
173
|
+
...notes,
|
|
174
|
+
].join('\n');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function usageImport(): string {
|
|
178
|
+
return 'Usage: goodvibes-agent import openclaw [path] [--apply]';
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export async function handleImportCommand(runtime: CliCommandRuntime): Promise<CliCommandOutput> {
|
|
182
|
+
try {
|
|
183
|
+
const [sourceRaw, ...rest] = runtime.cli.commandArgs;
|
|
184
|
+
const source = (sourceRaw ?? '').toLowerCase();
|
|
185
|
+
if (!source) return failure(runtime, 'invalid_import_command', usageImport(), 2);
|
|
186
|
+
if (source !== 'openclaw') {
|
|
187
|
+
return failure(runtime, 'unknown_import_source', `Unknown import source "${sourceRaw}". Supported sources: openclaw.\n${usageImport()}`, 2);
|
|
188
|
+
}
|
|
189
|
+
const apply = rest.includes('--apply');
|
|
190
|
+
const pathArg = rest.find((arg) => !arg.startsWith('--'));
|
|
191
|
+
const sourcePath = resolveSourcePath(runtime, pathArg);
|
|
192
|
+
const plan = scanOpenClawWorkspace(sourcePath);
|
|
193
|
+
if (!plan.exists) {
|
|
194
|
+
const message = pathArg
|
|
195
|
+
? `OpenClaw workspace not found at ${sourcePath}.`
|
|
196
|
+
: `No OpenClaw workspace found at the default location ${sourcePath}. Pass a path: goodvibes-agent import openclaw <path>.`;
|
|
197
|
+
return failure(runtime, 'openclaw_workspace_missing', message, 1);
|
|
198
|
+
}
|
|
199
|
+
if (apply) {
|
|
200
|
+
const output = await renderApply(runtime, plan);
|
|
201
|
+
return success(runtime, 'agent.import.openclaw.apply', plan, output);
|
|
202
|
+
}
|
|
203
|
+
return success(runtime, 'agent.import.openclaw.dryRun', plan, renderDryRun(plan));
|
|
204
|
+
} catch (error) {
|
|
205
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
206
|
+
return failure(runtime, 'agent.import.error', message, 1);
|
|
207
|
+
}
|
|
208
|
+
}
|
package/src/cli/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { extractAuthorizationCode, formatJsonOrText, hasCommandFlag, openBrowser
|
|
|
14
14
|
import { GOODVIBES_AGENT_PAIRING_SURFACE } from '../config/surface.ts';
|
|
15
15
|
import { connectedHostTokenRequiredMessage, readConnectedHostOperatorToken } from '../runtime/connected-host-auth.ts';
|
|
16
16
|
import { formatAgentRecordSource } from '../agent/record-labels.ts';
|
|
17
|
+
import { appendTemporalLabel } from './temporal-label.ts';
|
|
17
18
|
|
|
18
19
|
function resolveManualSubscriptionConfig(config: OAuthProviderConfig): OAuthProviderConfig {
|
|
19
20
|
return config.manualRedirectUri
|
|
@@ -58,7 +59,7 @@ export async function renderSubscriptions(runtime: CliCommandRuntime): Promise<s
|
|
|
58
59
|
] : []),
|
|
59
60
|
...(stored ? [
|
|
60
61
|
` token type ${stored.tokenType}`,
|
|
61
|
-
` expires ${stored.expiresAt ? new Date(stored.expiresAt).toISOString() : 'n/a'}`,
|
|
62
|
+
` expires ${stored.expiresAt ? appendTemporalLabel(new Date(stored.expiresAt).toISOString(), stored.expiresAt) : 'n/a'}`,
|
|
62
63
|
` refresh token ${stored.refreshToken ? 'present' : 'absent'}`,
|
|
63
64
|
` override ambient ${yesNo(stored.overrideAmbientApiKeys)}`,
|
|
64
65
|
] : [' stored no']),
|
|
@@ -136,7 +137,7 @@ export async function renderSubscriptions(runtime: CliCommandRuntime): Promise<s
|
|
|
136
137
|
return [
|
|
137
138
|
`Subscription stored ${provider}`,
|
|
138
139
|
` token type ${record.tokenType}`,
|
|
139
|
-
` expires ${record.expiresAt ? new Date(record.expiresAt).toISOString() : 'n/a'}`,
|
|
140
|
+
` expires ${record.expiresAt ? appendTemporalLabel(new Date(record.expiresAt).toISOString(), record.expiresAt) : 'n/a'}`,
|
|
140
141
|
].join('\n');
|
|
141
142
|
}
|
|
142
143
|
const activeConfig = resolveManualSubscriptionConfig(resolved.oauth);
|
|
@@ -144,7 +145,7 @@ export async function renderSubscriptions(runtime: CliCommandRuntime): Promise<s
|
|
|
144
145
|
return [
|
|
145
146
|
`Subscription stored ${provider}`,
|
|
146
147
|
` token type ${record.tokenType}`,
|
|
147
|
-
` expires ${record.expiresAt ? new Date(record.expiresAt).toISOString() : 'n/a'}`,
|
|
148
|
+
` expires ${record.expiresAt ? appendTemporalLabel(new Date(record.expiresAt).toISOString(), record.expiresAt) : 'n/a'}`,
|
|
148
149
|
].join('\n');
|
|
149
150
|
}
|
|
150
151
|
if (sub === 'refresh') {
|
|
@@ -155,7 +156,7 @@ export async function renderSubscriptions(runtime: CliCommandRuntime): Promise<s
|
|
|
155
156
|
const record = await services.subscriptionManager.refreshOAuthToken(provider, resolved.oauth);
|
|
156
157
|
return [
|
|
157
158
|
`Subscription refreshed ${provider}`,
|
|
158
|
-
` expires ${record.expiresAt ? new Date(record.expiresAt).toISOString() : 'n/a'}`,
|
|
159
|
+
` expires ${record.expiresAt ? appendTemporalLabel(new Date(record.expiresAt).toISOString(), record.expiresAt) : 'n/a'}`,
|
|
159
160
|
].join('\n');
|
|
160
161
|
}
|
|
161
162
|
if (sub === 'logout' || sub === 'remove') {
|
|
@@ -179,9 +180,9 @@ export async function renderSubscriptions(runtime: CliCommandRuntime): Promise<s
|
|
|
179
180
|
return formatJsonOrText(runtime.cli)(value, [
|
|
180
181
|
'GoodVibes subscriptions',
|
|
181
182
|
subscriptions.length === 0 ? ' active none' : ' active',
|
|
182
|
-
...subscriptions.map((sub) => ` ${sub.provider} token ${sub.tokenType} expires ${sub.expiresAt ? new Date(sub.expiresAt).toISOString() : 'n/a'} override ambient ${yesNo(sub.overrideAmbientApiKeys)}`),
|
|
183
|
+
...subscriptions.map((sub) => ` ${sub.provider} token ${sub.tokenType} expires ${sub.expiresAt ? appendTemporalLabel(new Date(sub.expiresAt).toISOString(), sub.expiresAt) : 'n/a'} override ambient ${yesNo(sub.overrideAmbientApiKeys)}`),
|
|
183
184
|
pending.length === 0 ? ' pending none' : ' pending',
|
|
184
|
-
...pending.map((sub) => ` ${sub.provider} created ${new Date(sub.createdAt).toISOString()}`),
|
|
185
|
+
...pending.map((sub) => ` ${sub.provider} created ${appendTemporalLabel(new Date(sub.createdAt).toISOString(), sub.createdAt)}`),
|
|
185
186
|
].join('\n'));
|
|
186
187
|
});
|
|
187
188
|
}
|
|
@@ -268,7 +269,7 @@ export async function handleSessions(runtime: CliCommandRuntime): Promise<string
|
|
|
268
269
|
const value = sessions;
|
|
269
270
|
return formatJsonOrText(runtime.cli)(value, [
|
|
270
271
|
`GoodVibes sessions (${sessions.length})`,
|
|
271
|
-
...sessions.slice(0, 50).map((session) => ` ${session.name} messages ${session.messageCount} ${new Date(session.timestamp).toISOString()} ${session.title || '(untitled)'}`),
|
|
272
|
+
...sessions.slice(0, 50).map((session) => ` ${session.name} messages ${session.messageCount} ${appendTemporalLabel(new Date(session.timestamp).toISOString(), session.timestamp)} ${session.title || '(untitled)'}`),
|
|
272
273
|
].join('\n'));
|
|
273
274
|
}
|
|
274
275
|
if (sub === 'show' || sub === 'info') {
|
|
@@ -281,7 +282,7 @@ export async function handleSessions(runtime: CliCommandRuntime): Promise<string
|
|
|
281
282
|
` title ${found.title || '(untitled)'}`,
|
|
282
283
|
` messages ${found.messageCount}`,
|
|
283
284
|
` provider/model ${found.provider}/${found.model}`,
|
|
284
|
-
` updated ${new Date(found.timestamp).toISOString()}`,
|
|
285
|
+
` updated ${appendTemporalLabel(new Date(found.timestamp).toISOString(), found.timestamp)}`,
|
|
285
286
|
` file ${found.filePath}`,
|
|
286
287
|
].join('\n'));
|
|
287
288
|
}
|
package/src/cli/management.ts
CHANGED
|
@@ -27,6 +27,7 @@ import type { GoodVibesCliParseResult } from './types.ts';
|
|
|
27
27
|
import { formatProviderAuthRoute, summarizeProviderAuthRoutes } from './provider-auth-routes.ts';
|
|
28
28
|
import { classifyProviderSetup } from './provider-classification.ts';
|
|
29
29
|
import { handleBundleCommand } from './bundle-command.ts';
|
|
30
|
+
import { handleImportCommand } from './import-command.ts';
|
|
30
31
|
import { handleSecrets, handleSessions, handleTasks, renderPairing, renderSubscriptions } from './management-commands.ts';
|
|
31
32
|
import { handleAgentKnowledgeCommand, handleAgentKnowledgeShortcutCommand, handleCompatCommand, handleDelegateCommand } from './agent-knowledge-command.ts';
|
|
32
33
|
import { handlePersonasCommand } from './personas-command.ts';
|
|
@@ -34,6 +35,12 @@ import { handleSkillsCommand } from './skills-command.ts';
|
|
|
34
35
|
import { handleMemoryCommand } from './memory-command.ts';
|
|
35
36
|
import { handleProfilesCommand } from './profiles-command.ts';
|
|
36
37
|
import { handleRoutinesCommand } from './routines-command.ts';
|
|
38
|
+
import { handleCiCommand } from './ci-command.ts';
|
|
39
|
+
import { handlePrincipalsCommand } from './principals-command.ts';
|
|
40
|
+
import { handleChannelProfilesCommand } from './channel-profiles-command.ts';
|
|
41
|
+
import { handleWorkspacesCommand } from './workspaces-command.ts';
|
|
42
|
+
import { handleRelayCommand } from './relay-command.ts';
|
|
43
|
+
import { handleFleetCommand } from './fleet-command.ts';
|
|
37
44
|
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
38
45
|
|
|
39
46
|
export interface CliCommandRuntime {
|
|
@@ -620,6 +627,36 @@ export async function handleGoodVibesCliCommand(runtime: CliCommandRuntime): Pro
|
|
|
620
627
|
console.log(result.output);
|
|
621
628
|
return { handled: true, exitCode: result.exitCode };
|
|
622
629
|
}
|
|
630
|
+
case 'ci': {
|
|
631
|
+
const result = await handleCiCommand(runtime);
|
|
632
|
+
console.log(result.output);
|
|
633
|
+
return { handled: true, exitCode: result.exitCode };
|
|
634
|
+
}
|
|
635
|
+
case 'principals': {
|
|
636
|
+
const result = await handlePrincipalsCommand(runtime);
|
|
637
|
+
console.log(result.output);
|
|
638
|
+
return { handled: true, exitCode: result.exitCode };
|
|
639
|
+
}
|
|
640
|
+
case 'channel-profiles': {
|
|
641
|
+
const result = await handleChannelProfilesCommand(runtime);
|
|
642
|
+
console.log(result.output);
|
|
643
|
+
return { handled: true, exitCode: result.exitCode };
|
|
644
|
+
}
|
|
645
|
+
case 'workspaces': {
|
|
646
|
+
const result = await handleWorkspacesCommand(runtime);
|
|
647
|
+
console.log(result.output);
|
|
648
|
+
return { handled: true, exitCode: result.exitCode };
|
|
649
|
+
}
|
|
650
|
+
case 'relay': {
|
|
651
|
+
const result = handleRelayCommand(runtime);
|
|
652
|
+
console.log(result.output);
|
|
653
|
+
return { handled: true, exitCode: result.exitCode };
|
|
654
|
+
}
|
|
655
|
+
case 'fleet': {
|
|
656
|
+
const result = await handleFleetCommand(runtime);
|
|
657
|
+
console.log(result.output);
|
|
658
|
+
return { handled: true, exitCode: result.exitCode };
|
|
659
|
+
}
|
|
623
660
|
case 'knowledge': {
|
|
624
661
|
const result = await handleAgentKnowledgeCommand(runtime);
|
|
625
662
|
console.log(result.output);
|
|
@@ -665,6 +702,11 @@ export async function handleGoodVibesCliCommand(runtime: CliCommandRuntime): Pro
|
|
|
665
702
|
console.log(result.output);
|
|
666
703
|
return { handled: true, exitCode: result.exitCode };
|
|
667
704
|
}
|
|
705
|
+
case 'import': {
|
|
706
|
+
const result = await handleImportCommand(runtime);
|
|
707
|
+
console.log(result.output);
|
|
708
|
+
return { handled: true, exitCode: result.exitCode };
|
|
709
|
+
}
|
|
668
710
|
default:
|
|
669
711
|
return { handled: false, exitCode: 0 };
|
|
670
712
|
}
|
|
@@ -23,6 +23,7 @@ import type { CliCommandRuntime } from './management.ts';
|
|
|
23
23
|
// Split out to stay under the architecture line cap; see its file header for the
|
|
24
24
|
// CLI ruling on when a memory subcommand goes over the wire vs local-direct.
|
|
25
25
|
import { tryWireMemoryCommand } from './memory-command-wire.ts';
|
|
26
|
+
import { appendTemporalLabel } from './temporal-label.ts';
|
|
26
27
|
|
|
27
28
|
const VALID_CLASSES: readonly MemoryClass[] = ['decision', 'constraint', 'incident', 'pattern', 'fact', 'risk', 'runbook', 'architecture', 'ownership'];
|
|
28
29
|
const VALID_SCOPES: readonly MemoryScope[] = ['session', 'project', 'team'];
|
|
@@ -253,9 +254,9 @@ export function renderRecord(record: MemoryRecord, links: readonly MemoryLink[])
|
|
|
253
254
|
` review: ${formatAgentRecordReviewState(record.reviewState)}`,
|
|
254
255
|
` confidence: ${record.confidence}`,
|
|
255
256
|
` tags: ${record.tags.join(', ') || '(none)'}`,
|
|
256
|
-
` created: ${timestamp(record.createdAt)}`,
|
|
257
|
-
` updated: ${timestamp(record.updatedAt)}`,
|
|
258
|
-
record.reviewedAt ? ` reviewed: ${timestamp(record.reviewedAt)}${record.reviewedBy ? ` by ${record.reviewedBy}` : ''}` : '',
|
|
257
|
+
` created: ${appendTemporalLabel(timestamp(record.createdAt), record.createdAt)}`,
|
|
258
|
+
` updated: ${appendTemporalLabel(timestamp(record.updatedAt), record.updatedAt)}`,
|
|
259
|
+
record.reviewedAt ? ` reviewed: ${appendTemporalLabel(timestamp(record.reviewedAt), record.reviewedAt)}${record.reviewedBy ? ` by ${record.reviewedBy}` : ''}` : '',
|
|
259
260
|
record.staleReason ? ` stale reason: ${record.staleReason}` : '',
|
|
260
261
|
'',
|
|
261
262
|
record.summary,
|