@intent-systems/nexus 2026.1.5-3 ā 2026.1.5-5
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/agents/agent-id.js +41 -0
- package/dist/agents/auth-profiles.js +114 -25
- package/dist/agents/identity-state.js +79 -0
- package/dist/agents/model-auth.js +1 -0
- package/dist/agents/model-fallback.js +15 -9
- package/dist/agents/model-selection.js +1 -1
- package/dist/agents/models-config.js +17 -11
- package/dist/agents/pi-embedded-runner.js +101 -9
- package/dist/agents/sandbox.js +12 -3
- package/dist/agents/skill-runner.js +29 -4
- package/dist/agents/skill-usage.js +114 -11
- package/dist/agents/skills-status.js +4 -4
- package/dist/agents/skills.js +18 -7
- package/dist/agents/subagent-registry.js +25 -11
- package/dist/agents/system-prompt.js +16 -0
- package/dist/agents/tool-policy.js +19 -3
- package/dist/agents/tools/browser-tool.js +5 -2
- package/dist/agents/tools/image-tool.js +93 -8
- package/dist/agents/tools/sessions-announce-target.js +5 -1
- package/dist/agents/workspace.js +55 -46
- package/dist/auto-reply/command-detection.js +2 -1
- package/dist/auto-reply/reply/directive-handling.js +153 -28
- package/dist/auto-reply/reply/directives.js +17 -2
- package/dist/auto-reply/reply/model-selection.js +8 -3
- package/dist/auto-reply/reply/queue.js +2 -2
- package/dist/auto-reply/reply.js +1 -1
- package/dist/auto-reply/thinking.js +15 -0
- package/dist/browser/chrome.js +1 -1
- package/dist/browser/client.js +2 -0
- package/dist/browser/config.js +6 -2
- package/dist/browser/pw-tools-core.js +3 -0
- package/dist/browser/routes/agent.js +14 -0
- package/dist/canvas-host/server.js +1 -1
- package/dist/capabilities/detector.js +245 -0
- package/dist/capabilities/registry.js +99 -0
- package/dist/channels/location.js +44 -0
- package/dist/channels/web/index.js +2 -0
- package/dist/cli/cloud-cli.js +12 -7
- package/dist/cli/credential-cli.js +139 -17
- package/dist/cli/gateway-cli.js +1 -1
- package/dist/cli/log-cli.js +25 -0
- package/dist/cli/pairing-cli.js +1 -1
- package/dist/cli/program.js +58 -6
- package/dist/cli/run-main.js +1 -1
- package/dist/cli/skills-cli.js +144 -21
- package/dist/cli/skills-hub-cli.js +59 -29
- package/dist/cli/tool-connector-cli.js +99 -24
- package/dist/cli/upstream-sync-cli.js +253 -96
- package/dist/cli/usage-cli.js +14 -0
- package/dist/commands/auth-choice-options.js +6 -1
- package/dist/commands/auth-choice.js +157 -5
- package/dist/commands/bootstrap-preset.js +10 -6
- package/dist/commands/capabilities.js +33 -6
- package/dist/commands/claude-md.js +3 -2
- package/dist/commands/config-view.js +1 -1
- package/dist/commands/configure.js +4 -4
- package/dist/commands/credential.js +497 -36
- package/dist/commands/cursor-rules.js +39 -19
- package/dist/commands/doctor.js +5 -4
- package/dist/commands/identity.js +28 -31
- package/dist/commands/init.js +15 -18
- package/dist/commands/log.js +134 -0
- package/dist/commands/models/fallbacks.js +1 -1
- package/dist/commands/models/image-fallbacks.js +1 -1
- package/dist/commands/models/list.js +1 -1
- package/dist/commands/models/scan.js +1 -1
- package/dist/commands/onboard-auth.js +27 -2
- package/dist/commands/onboard-eve-identity.js +7 -8
- package/dist/commands/onboard-non-interactive.js +4 -2
- package/dist/commands/onboard-quickstart.js +18 -11
- package/dist/commands/quest-state.js +271 -0
- package/dist/commands/quest.js +53 -13
- package/dist/commands/reset.js +1 -1
- package/dist/commands/sessions-ingest.js +5 -4
- package/dist/commands/setup.js +4 -2
- package/dist/commands/skills-manifest.js +2 -2
- package/dist/commands/status.js +179 -61
- package/dist/commands/suggestions.js +1 -1
- package/dist/commands/usage-tracking.js +32 -0
- package/dist/commands/usage-upload.js +6 -1
- package/dist/config/defaults.js +1 -3
- package/dist/config/includes.js +5 -7
- package/dist/config/io.js +88 -16
- package/dist/config/legacy.js +4 -2
- package/dist/config/paths.js +16 -0
- package/dist/config/sessions.js +9 -5
- package/dist/config/zod-schema.js +4 -3
- package/dist/control-plane/broker/broker.js +1022 -0
- package/dist/control-plane/compaction.js +282 -0
- package/dist/control-plane/factory.js +31 -0
- package/dist/control-plane/index.js +10 -0
- package/dist/control-plane/odu/agents.js +192 -0
- package/dist/control-plane/odu/interaction-tools.js +208 -0
- package/dist/control-plane/odu/prompt-loader.js +95 -0
- package/dist/control-plane/odu/runtime.js +479 -0
- package/dist/control-plane/odu/types.js +6 -0
- package/dist/control-plane/odu-control-plane.js +316 -0
- package/dist/control-plane/single-agent.js +249 -0
- package/dist/control-plane/types.js +11 -0
- package/dist/credentials/store.js +449 -0
- package/dist/gateway/server-browser.js +5 -4
- package/dist/gateway/server-methods/cron.js +11 -1
- package/dist/gateway/server.js +14 -7
- package/dist/infra/bonjour.js +1 -1
- package/dist/infra/event-log.js +8 -2
- package/dist/infra/path-env.js +1 -2
- package/dist/infra/provider-usage.auth.js +5 -3
- package/dist/infra/provider-usage.fetch.claude.js +16 -6
- package/dist/infra/provider-usage.fetch.minimax.js +8 -3
- package/dist/infra/provider-usage.js +9 -5
- package/dist/infra/restart.js +2 -2
- package/dist/infra/usage-settings.js +78 -0
- package/dist/infra/usage-suggestions.js +17 -5
- package/dist/infra/usage-upload.js +38 -1
- package/dist/infra/voicewake.js +2 -2
- package/dist/logging/redact.js +109 -0
- package/dist/markdown/fences.js +58 -0
- package/dist/media/image-ops.js +3 -1
- package/dist/memory/embeddings.js +146 -0
- package/dist/memory/index.js +3 -0
- package/dist/memory/internal.js +163 -0
- package/dist/pairing/pairing-store.js +218 -0
- package/dist/plugins/cli.js +42 -0
- package/dist/plugins/discovery.js +253 -0
- package/dist/plugins/install.js +181 -0
- package/dist/plugins/loader.js +290 -0
- package/dist/plugins/registry.js +105 -0
- package/dist/plugins/status.js +29 -0
- package/dist/plugins/tools.js +39 -0
- package/dist/plugins/types.js +1 -0
- package/dist/providers/github-copilot-auth.js +1 -1
- package/dist/routing/resolve-route.js +144 -0
- package/dist/routing/session-key.js +65 -0
- package/dist/sessions/send-policy.js +5 -5
- package/dist/slack/monitor.js +22 -1
- package/dist/telegram/reaction-level.js +2 -1
- package/dist/utils/provider-utils.js +28 -0
- package/dist/utils.js +4 -3
- package/dist/wizard/onboarding.js +29 -7
- package/package.json +4 -29
- package/patches/@mariozechner__pi-ai.patch +215 -0
- package/patches/playwright-core@1.57.0.patch +13 -0
- package/patches/qrcode-terminal.patch +12 -0
- package/scripts/postinstall.js +202 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cancel, confirm, isCancel } from "@clack/prompts";
|
|
2
|
-
import { addCredential, flagCredential, getCredential, getCredentialPaths, listCredentials, removeCredential, scanCredentialEnv, } from "../commands/credential.js";
|
|
2
|
+
import { addCredential, flagCredential, getCredential, getCredentialPaths, getCredentialValue, importCliCredential, listCredentials, removeCredential, scanCredentialEnv, verifyCredentials, } from "../commands/credential.js";
|
|
3
3
|
function parseFields(raw, fieldsArgs) {
|
|
4
4
|
const out = {};
|
|
5
5
|
if (raw) {
|
|
@@ -25,7 +25,9 @@ function parseFields(raw, fieldsArgs) {
|
|
|
25
25
|
return out;
|
|
26
26
|
}
|
|
27
27
|
export function registerCredentialCli(program) {
|
|
28
|
-
const credential = program
|
|
28
|
+
const credential = program
|
|
29
|
+
.command("credential")
|
|
30
|
+
.description("Manage credentials");
|
|
29
31
|
credential
|
|
30
32
|
.command("list")
|
|
31
33
|
.description("List credentials from the index")
|
|
@@ -54,29 +56,72 @@ export function registerCredentialCli(program) {
|
|
|
54
56
|
const paths = getCredentialPaths();
|
|
55
57
|
console.log(`\nIndex: ${paths.indexPath}`);
|
|
56
58
|
});
|
|
59
|
+
credential
|
|
60
|
+
.command("verify <service>")
|
|
61
|
+
.description("Verify credential status for a service")
|
|
62
|
+
.option("--json", "Output as JSON")
|
|
63
|
+
.action(async (service, opts) => {
|
|
64
|
+
const result = await verifyCredentials({ service });
|
|
65
|
+
if (!result) {
|
|
66
|
+
console.error("Credential service not found.");
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
if (opts.json) {
|
|
70
|
+
console.log(JSON.stringify(result, null, 2));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const iconFor = (status) => status === "ok" ? "ā
" : status === "skipped" ? "ā ļø" : "ā";
|
|
74
|
+
console.log(`${result.ok ? "ā
" : "ā"} ${result.service}: ${result.accounts} account(s) checked`);
|
|
75
|
+
for (const entry of result.checked) {
|
|
76
|
+
const err = entry.error ? ` - ${entry.error}` : "";
|
|
77
|
+
console.log(` ${iconFor(entry.status)} ${entry.account} (${entry.authId})${err}`);
|
|
78
|
+
}
|
|
79
|
+
if (!result.ok) {
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
57
83
|
credential
|
|
58
84
|
.command("get")
|
|
59
|
-
.description("Get a credential
|
|
85
|
+
.description("Get a credential value")
|
|
60
86
|
.requiredOption("--service <id>", "Service id")
|
|
61
87
|
.requiredOption("--account <id>", "Account id")
|
|
62
88
|
.requiredOption("--auth <id>", "Auth id")
|
|
63
89
|
.option("--json", "Output as JSON")
|
|
90
|
+
.option("--record", "Show credential record instead of value")
|
|
64
91
|
.action(async (opts) => {
|
|
65
|
-
const
|
|
92
|
+
const params = {
|
|
66
93
|
service: opts.service,
|
|
67
94
|
account: opts.account,
|
|
68
95
|
authId: opts.auth,
|
|
69
|
-
}
|
|
70
|
-
if (
|
|
71
|
-
|
|
96
|
+
};
|
|
97
|
+
if (opts.record) {
|
|
98
|
+
const result = await getCredential(params);
|
|
99
|
+
if (!result) {
|
|
100
|
+
console.error("Credential not found.");
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
if (opts.json) {
|
|
104
|
+
console.log(JSON.stringify(result, null, 2));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
console.log(`\n${result.filePath}`);
|
|
108
|
+
console.log(JSON.stringify(result.record, null, 2));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const valueResult = await getCredentialValue(params);
|
|
112
|
+
if (!valueResult) {
|
|
113
|
+
console.error("Credential value not found.");
|
|
72
114
|
process.exit(1);
|
|
73
115
|
}
|
|
74
116
|
if (opts.json) {
|
|
75
|
-
console.log(JSON.stringify(
|
|
117
|
+
console.log(JSON.stringify({
|
|
118
|
+
filePath: valueResult.filePath,
|
|
119
|
+
field: valueResult.field,
|
|
120
|
+
value: valueResult.value,
|
|
121
|
+
}, null, 2));
|
|
76
122
|
return;
|
|
77
123
|
}
|
|
78
|
-
console.log(
|
|
79
|
-
console.log(JSON.stringify(result.record, null, 2));
|
|
124
|
+
console.log(valueResult.value);
|
|
80
125
|
});
|
|
81
126
|
credential
|
|
82
127
|
.command("add")
|
|
@@ -86,23 +131,55 @@ export function registerCredentialCli(program) {
|
|
|
86
131
|
.requiredOption("--type <type>", "api_key | token | oauth | config")
|
|
87
132
|
.option("--auth <id>", "Auth id (defaults to type)")
|
|
88
133
|
.option("--owner <owner>", "shared | user | agent:<id>", "user")
|
|
89
|
-
.option("--storage <provider>", "
|
|
90
|
-
.option("--value <value>", "Secret value for
|
|
134
|
+
.option("--storage <provider>", "keychain | 1password | env | external")
|
|
135
|
+
.option("--value <value>", "Secret value for keychain")
|
|
91
136
|
.option("--refresh-token <token>", "OAuth refresh token")
|
|
92
137
|
.option("--expires-at <ts>", "Expiration (unix ms or ISO string)")
|
|
93
138
|
.option("--vault <name>", "1Password vault")
|
|
94
139
|
.option("--item <name>", "1Password item")
|
|
95
140
|
.option("--fields <json>", "1Password field map as JSON")
|
|
96
141
|
.option("--field <pair...>", "1Password field map: key=value")
|
|
97
|
-
.option("--
|
|
142
|
+
.option("--env-var <name>", "Env var name for env storage")
|
|
143
|
+
.option("--command <cmd>", "External command to fetch secret")
|
|
144
|
+
.option("--sync-command <cmd>", "External sync command (deprecated)")
|
|
145
|
+
.option("--format <format>", "External command output format: raw|json")
|
|
146
|
+
.option("--json-path <path>", "JSON path for external output")
|
|
98
147
|
.action(async (opts) => {
|
|
99
148
|
const type = String(opts.type).trim();
|
|
100
149
|
if (!["api_key", "token", "oauth", "config"].includes(type)) {
|
|
101
150
|
console.error("Invalid --type");
|
|
102
151
|
process.exit(1);
|
|
103
152
|
}
|
|
104
|
-
const
|
|
153
|
+
const storageRaw = opts.storage ? String(opts.storage).trim() : "";
|
|
154
|
+
const storage = storageRaw || (process.platform === "darwin" ? "keychain" : "");
|
|
155
|
+
if (!storage) {
|
|
156
|
+
console.error("Missing --storage. Use keychain (macOS), 1password, env, or external.");
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
if (storage === "keychain" && !opts.value) {
|
|
160
|
+
console.error("Missing --value for keychain storage.");
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
if (storage === "env" && !opts.envVar) {
|
|
164
|
+
console.error("Missing --env-var for env storage.");
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
if (storage === "external" && !opts.command && !opts.syncCommand) {
|
|
168
|
+
console.error("Missing --command for external storage.");
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
if (opts.format && !["raw", "json"].includes(String(opts.format))) {
|
|
172
|
+
console.error("Invalid --format. Use raw or json.");
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
if (!["keychain", "1password", "env", "external"].includes(storage)) {
|
|
176
|
+
console.error("Invalid --storage. Use keychain, 1password, env, external.");
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
105
179
|
const fields = parseFields(opts.fields, opts.field);
|
|
180
|
+
const format = opts.format === "raw" || opts.format === "json"
|
|
181
|
+
? opts.format
|
|
182
|
+
: undefined;
|
|
106
183
|
const expiresAt = opts.expiresAt && /^\d+$/.test(String(opts.expiresAt).trim())
|
|
107
184
|
? Number.parseInt(String(opts.expiresAt).trim(), 10)
|
|
108
185
|
: opts.expiresAt;
|
|
@@ -121,14 +198,59 @@ export function registerCredentialCli(program) {
|
|
|
121
198
|
item: String(opts.item ?? ""),
|
|
122
199
|
fields,
|
|
123
200
|
}
|
|
124
|
-
: storage === "
|
|
125
|
-
? { provider: "
|
|
126
|
-
:
|
|
201
|
+
: storage === "env"
|
|
202
|
+
? { provider: "env", var: String(opts.envVar ?? "") }
|
|
203
|
+
: storage === "external"
|
|
204
|
+
? {
|
|
205
|
+
provider: "external",
|
|
206
|
+
command: opts.command ? String(opts.command) : undefined,
|
|
207
|
+
syncCommand: opts.syncCommand
|
|
208
|
+
? String(opts.syncCommand)
|
|
209
|
+
: undefined,
|
|
210
|
+
...(format ? { format } : {}),
|
|
211
|
+
jsonPath: opts.jsonPath
|
|
212
|
+
? String(opts.jsonPath)
|
|
213
|
+
: undefined,
|
|
214
|
+
}
|
|
215
|
+
: { provider: "env", var: String(opts.envVar ?? "") },
|
|
127
216
|
refreshToken: opts.refreshToken,
|
|
128
217
|
expiresAt,
|
|
129
218
|
});
|
|
130
219
|
console.log(`Added credential at ${record.filePath}`);
|
|
131
220
|
});
|
|
221
|
+
credential
|
|
222
|
+
.command("import <source>")
|
|
223
|
+
.description("Import external CLI credentials")
|
|
224
|
+
.option("--account <id>", "Account id override")
|
|
225
|
+
.option("--owner <owner>", "shared | user | agent:<id>", "user")
|
|
226
|
+
.option("--force", "Overwrite existing record")
|
|
227
|
+
.option("--json", "Output as JSON")
|
|
228
|
+
.option("--no-keychain-prompt", "Skip keychain prompts")
|
|
229
|
+
.action(async (source, opts) => {
|
|
230
|
+
const normalized = String(source ?? "").trim();
|
|
231
|
+
if (!["claude-cli", "codex-cli"].includes(normalized)) {
|
|
232
|
+
console.error("Invalid source. Use claude-cli or codex-cli.");
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
const result = await importCliCredential({
|
|
237
|
+
source: normalized,
|
|
238
|
+
account: opts.account,
|
|
239
|
+
owner: opts.owner,
|
|
240
|
+
force: Boolean(opts.force),
|
|
241
|
+
allowKeychainPrompt: opts.keychainPrompt !== false,
|
|
242
|
+
});
|
|
243
|
+
if (opts.json) {
|
|
244
|
+
console.log(JSON.stringify(result, null, 2));
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
console.log(`Imported ${result.source} credentials into ${result.profileId} (${result.filePath})`);
|
|
248
|
+
}
|
|
249
|
+
catch (err) {
|
|
250
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
132
254
|
credential
|
|
133
255
|
.command("remove")
|
|
134
256
|
.description("Remove a credential record")
|
package/dist/cli/gateway-cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import { CONFIG_PATH_NEXUS, loadConfig, resolveGatewayPort } from "../config/config.js";
|
|
2
|
+
import { CONFIG_PATH_NEXUS, loadConfig, resolveGatewayPort, } from "../config/config.js";
|
|
3
3
|
import { GATEWAY_LAUNCH_AGENT_LABEL, GATEWAY_SYSTEMD_SERVICE_NAME, GATEWAY_WINDOWS_TASK_NAME, } from "../daemon/constants.js";
|
|
4
4
|
import { resolveGatewayService } from "../daemon/service.js";
|
|
5
5
|
import { callGateway, randomIdempotencyKey } from "../gateway/call.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { logCommand } from "../commands/log.js";
|
|
2
|
+
import { defaultRuntime } from "../runtime.js";
|
|
3
|
+
export function registerLogCli(program) {
|
|
4
|
+
program
|
|
5
|
+
.command("log")
|
|
6
|
+
.description("Show Nexus event or skill usage logs")
|
|
7
|
+
.option("--json", "Output as JSON")
|
|
8
|
+
.option("--errors", "Only include error events")
|
|
9
|
+
.option("--since <time>", "Only include events after time (e.g. 24h)")
|
|
10
|
+
.option("--limit <n>", "Limit entries", (value) => Number.parseInt(value, 10))
|
|
11
|
+
.option("--skill <name>", "Show usage log for a skill")
|
|
12
|
+
.option("--source <source>", "Filter by event source")
|
|
13
|
+
.option("--command <path>", "Filter by command path")
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
await logCommand({
|
|
16
|
+
json: Boolean(opts.json),
|
|
17
|
+
errors: Boolean(opts.errors),
|
|
18
|
+
since: typeof opts.since === "string" ? opts.since : undefined,
|
|
19
|
+
limit: Number.isFinite(opts.limit) ? opts.limit : undefined,
|
|
20
|
+
skill: typeof opts.skill === "string" ? opts.skill : undefined,
|
|
21
|
+
source: typeof opts.source === "string" ? opts.source : undefined,
|
|
22
|
+
command: typeof opts.command === "string" ? opts.command : undefined,
|
|
23
|
+
}, defaultRuntime);
|
|
24
|
+
});
|
|
25
|
+
}
|
package/dist/cli/pairing-cli.js
CHANGED
|
@@ -15,7 +15,7 @@ const PROVIDERS = [
|
|
|
15
15
|
"whatsapp",
|
|
16
16
|
];
|
|
17
17
|
function parseProvider(raw) {
|
|
18
|
-
const value = String(raw
|
|
18
|
+
const value = (typeof raw === "string" || typeof raw === "number" ? String(raw) : "")
|
|
19
19
|
.trim()
|
|
20
20
|
.toLowerCase();
|
|
21
21
|
if (PROVIDERS.includes(value))
|
package/dist/cli/program.js
CHANGED
|
@@ -4,22 +4,24 @@ import { configViewCommand } from "../commands/config-view.js";
|
|
|
4
4
|
import { identityCommand } from "../commands/identity.js";
|
|
5
5
|
import { initCommand } from "../commands/init.js";
|
|
6
6
|
import { questCommand } from "../commands/quest.js";
|
|
7
|
-
import { suggestionsCommand } from "../commands/suggestions.js";
|
|
8
7
|
import { statusCommand } from "../commands/status.js";
|
|
8
|
+
import { suggestionsCommand } from "../commands/suggestions.js";
|
|
9
9
|
import { updateCommand } from "../commands/update.js";
|
|
10
10
|
import { isNixMode, migrateLegacyConfig, readConfigFileSnapshot, writeConfigFile, } from "../config/config.js";
|
|
11
11
|
import { danger } from "../globals.js";
|
|
12
|
+
import { recordCliCommandFinish, recordCliCommandStart, } from "../infra/event-log.js";
|
|
12
13
|
import { defaultRuntime } from "../runtime.js";
|
|
13
14
|
import { VERSION } from "../version.js";
|
|
14
|
-
import { recordCliCommandFinish, recordCliCommandStart } from "../infra/event-log.js";
|
|
15
15
|
import { registerCloudCommand } from "./cloud-cli.js";
|
|
16
16
|
import { registerCredentialCli } from "./credential-cli.js";
|
|
17
17
|
import { registerDnsCli } from "./dns-cli.js";
|
|
18
18
|
import { registerGatewayCli } from "./gateway-cli.js";
|
|
19
|
+
import { registerLogCli } from "./log-cli.js";
|
|
19
20
|
import { registerSkillsCommand } from "./skills-cli.js";
|
|
20
21
|
import { registerSkillsHubCommand } from "./skills-hub-cli.js";
|
|
21
22
|
import { registerToolConnectorCli } from "./tool-connector-cli.js";
|
|
22
23
|
import { registerUsageCli } from "./usage-cli.js";
|
|
24
|
+
import { resolveIdentitySnapshot } from "../agents/identity-state.js";
|
|
23
25
|
function buildCommandPath(cmd) {
|
|
24
26
|
const parts = [];
|
|
25
27
|
let current = cmd;
|
|
@@ -51,6 +53,19 @@ export function buildProgram() {
|
|
|
51
53
|
});
|
|
52
54
|
if (actionCommand.name() === "init")
|
|
53
55
|
return;
|
|
56
|
+
const skipIdentityCheck = process.env.NODE_ENV === "test" || Boolean(process.env.VITEST);
|
|
57
|
+
if (!skipIdentityCheck && actionCommand.name() !== "status") {
|
|
58
|
+
const identity = resolveIdentitySnapshot();
|
|
59
|
+
if (!identity.ok) {
|
|
60
|
+
defaultRuntime.error("Multiple agents detected in state/agents.");
|
|
61
|
+
defaultRuntime.error(`Set NEXUS_AGENT_ID to one of: ${identity.agentOptions.join(", ")}`);
|
|
62
|
+
process.exit(2);
|
|
63
|
+
}
|
|
64
|
+
if (!identity.snapshot.hasIdentity) {
|
|
65
|
+
await statusCommand({ brief: true }, defaultRuntime);
|
|
66
|
+
process.exit(2);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
54
69
|
const snapshot = await readConfigFileSnapshot();
|
|
55
70
|
if (snapshot.legacyIssues.length === 0)
|
|
56
71
|
return;
|
|
@@ -79,41 +94,77 @@ export function buildProgram() {
|
|
|
79
94
|
.option("--brief", "Compact output")
|
|
80
95
|
.option("--capabilities", "Focus on capabilities")
|
|
81
96
|
.option("--credentials", "Focus on credentials")
|
|
97
|
+
.option("--usage", "Focus on usage statistics")
|
|
98
|
+
.option("--quiet", "Minimal output, exit codes only")
|
|
82
99
|
.action(async (opts) => {
|
|
83
100
|
await statusCommand({
|
|
84
101
|
json: Boolean(opts.json),
|
|
85
102
|
brief: Boolean(opts.brief),
|
|
86
103
|
capabilities: Boolean(opts.capabilities),
|
|
87
104
|
credentials: Boolean(opts.credentials),
|
|
105
|
+
usage: Boolean(opts.usage),
|
|
106
|
+
quiet: Boolean(opts.quiet),
|
|
88
107
|
}, defaultRuntime);
|
|
89
108
|
});
|
|
90
109
|
program
|
|
91
110
|
.command("capabilities")
|
|
92
111
|
.description("Show full capabilities map")
|
|
93
112
|
.option("--json", "Output as JSON")
|
|
113
|
+
.option("--category <name>", "Filter to a category")
|
|
114
|
+
.option("--status <status>", "Filter by status")
|
|
115
|
+
.option("--compact", "Compact output")
|
|
94
116
|
.action(async (opts) => {
|
|
95
|
-
await capabilitiesCommand({
|
|
117
|
+
await capabilitiesCommand({
|
|
118
|
+
json: Boolean(opts.json),
|
|
119
|
+
category: opts.category ? String(opts.category) : undefined,
|
|
120
|
+
status: opts.status ? String(opts.status) : undefined,
|
|
121
|
+
compact: Boolean(opts.compact),
|
|
122
|
+
}, defaultRuntime);
|
|
96
123
|
});
|
|
97
124
|
program
|
|
98
125
|
.command("map")
|
|
99
126
|
.description("Alias for capabilities")
|
|
100
127
|
.option("--json", "Output as JSON")
|
|
128
|
+
.option("--category <name>", "Filter to a category")
|
|
129
|
+
.option("--status <status>", "Filter by status")
|
|
130
|
+
.option("--compact", "Compact output")
|
|
101
131
|
.action(async (opts) => {
|
|
102
|
-
await capabilitiesCommand({
|
|
132
|
+
await capabilitiesCommand({
|
|
133
|
+
json: Boolean(opts.json),
|
|
134
|
+
category: opts.category ? String(opts.category) : undefined,
|
|
135
|
+
status: opts.status ? String(opts.status) : undefined,
|
|
136
|
+
compact: Boolean(opts.compact),
|
|
137
|
+
}, defaultRuntime);
|
|
103
138
|
});
|
|
104
139
|
program
|
|
105
140
|
.command("quest")
|
|
106
141
|
.description("Show onboarding quests")
|
|
107
142
|
.option("--json", "Output as JSON")
|
|
143
|
+
.option("--list", "List all quests")
|
|
144
|
+
.option("--progress", "Show quest progress summary")
|
|
145
|
+
.option("--start <quest>", "Mark a quest as started")
|
|
146
|
+
.option("--secrets", "Include secret quests")
|
|
147
|
+
.option("--power-path", "Only show power-path quests")
|
|
148
|
+
.option("--quick-wins", "Only show quick wins")
|
|
108
149
|
.action(async (opts) => {
|
|
109
|
-
await questCommand({
|
|
150
|
+
await questCommand({
|
|
151
|
+
json: Boolean(opts.json),
|
|
152
|
+
list: Boolean(opts.list),
|
|
153
|
+
progress: Boolean(opts.progress),
|
|
154
|
+
start: opts.start ? String(opts.start) : undefined,
|
|
155
|
+
secrets: Boolean(opts.secrets),
|
|
156
|
+
powerPath: Boolean(opts.powerPath),
|
|
157
|
+
quickWins: Boolean(opts.quickWins),
|
|
158
|
+
}, defaultRuntime);
|
|
110
159
|
});
|
|
111
160
|
program
|
|
112
161
|
.command("identity [target]")
|
|
113
162
|
.description("Show identity files")
|
|
114
163
|
.option("--json", "Output as JSON")
|
|
115
164
|
.action(async (target, opts) => {
|
|
116
|
-
const normalized = target && (target === "user" || target === "agent")
|
|
165
|
+
const normalized = target && (target === "user" || target === "agent")
|
|
166
|
+
? target
|
|
167
|
+
: undefined;
|
|
117
168
|
await identityCommand({ target: normalized, json: Boolean(opts.json) }, defaultRuntime);
|
|
118
169
|
});
|
|
119
170
|
program
|
|
@@ -156,6 +207,7 @@ export function buildProgram() {
|
|
|
156
207
|
registerCredentialCli(program);
|
|
157
208
|
registerDnsCli(program);
|
|
158
209
|
registerGatewayCli(program);
|
|
210
|
+
registerLogCli(program);
|
|
159
211
|
registerToolConnectorCli(program);
|
|
160
212
|
registerUsageCli(program);
|
|
161
213
|
return program;
|
package/dist/cli/run-main.js
CHANGED
|
@@ -2,10 +2,10 @@ import process from "node:process";
|
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import { loadDotEnv } from "../infra/dotenv.js";
|
|
4
4
|
import { normalizeEnv } from "../infra/env.js";
|
|
5
|
+
import { initCliEventLogSession, recordCliCommandFailure, recordCliSessionEnd, registerAgentEventLogListener, } from "../infra/event-log.js";
|
|
5
6
|
import { isMainModule } from "../infra/is-main.js";
|
|
6
7
|
import { ensureNexusCliOnPath } from "../infra/path-env.js";
|
|
7
8
|
import { assertSupportedRuntime } from "../infra/runtime-guard.js";
|
|
8
|
-
import { initCliEventLogSession, recordCliCommandFailure, recordCliSessionEnd, registerAgentEventLogListener, } from "../infra/event-log.js";
|
|
9
9
|
import { enableConsoleCapture } from "../logging.js";
|
|
10
10
|
export async function runCli(argv = process.argv) {
|
|
11
11
|
loadDotEnv({ quiet: true });
|
package/dist/cli/skills-cli.js
CHANGED
|
@@ -1,36 +1,129 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { getSkillInfo, runSkill, verifySkill } from "../agents/skill-runner.js";
|
|
4
|
-
import { getAggregateStats, getSkillStats } from "../agents/skill-usage.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { getAggregateStats, getSkillStats, hasSkillUsage, recordSkillUsage, } from "../agents/skill-usage.js";
|
|
5
|
+
import { getSkillMetadata, loadWorkspaceSkillEntries } from "../agents/skills.js";
|
|
6
|
+
import { buildWorkspaceSkillStatus } from "../agents/skills-status.js";
|
|
7
|
+
import { DEFAULT_AGENT_WORKSPACE_DIR } from "../agents/workspace.js";
|
|
8
|
+
import { loadConfig } from "../config/config.js";
|
|
9
|
+
import { MANAGED_SKILLS_DIR, NEXUS_ROOT, resolveUserPath } from "../utils.js";
|
|
10
|
+
const STATUS_ICON = {
|
|
11
|
+
active: "ā
",
|
|
12
|
+
ready: "ā",
|
|
13
|
+
needs_setup: "š§",
|
|
14
|
+
needs_install: "š„",
|
|
15
|
+
unavailable: "ā",
|
|
16
|
+
};
|
|
17
|
+
function resolveSkillType(entry) {
|
|
18
|
+
const metadata = getSkillMetadata(entry);
|
|
19
|
+
if (metadata?.type)
|
|
20
|
+
return metadata.type;
|
|
21
|
+
const requires = metadata?.requires;
|
|
22
|
+
if (requires?.env?.length || requires?.config?.length)
|
|
23
|
+
return "connector";
|
|
24
|
+
if (requires?.bins?.length || requires?.anyBins?.length)
|
|
25
|
+
return "tool";
|
|
26
|
+
return "guide";
|
|
27
|
+
}
|
|
28
|
+
function resolveSkillStatus(statusEntry) {
|
|
29
|
+
if (statusEntry.disabled || statusEntry.blockedByAllowlist) {
|
|
30
|
+
return "unavailable";
|
|
31
|
+
}
|
|
32
|
+
if (statusEntry.missing.os.length > 0)
|
|
33
|
+
return "unavailable";
|
|
34
|
+
if (statusEntry.missing.bins.length > 0)
|
|
35
|
+
return "needs_install";
|
|
36
|
+
if (statusEntry.missing.env.length > 0 || statusEntry.missing.config.length > 0) {
|
|
37
|
+
return "needs_setup";
|
|
38
|
+
}
|
|
39
|
+
if (hasSkillUsage(statusEntry.name))
|
|
40
|
+
return "active";
|
|
41
|
+
return "ready";
|
|
42
|
+
}
|
|
7
43
|
export function registerSkillsCommand(program) {
|
|
8
44
|
const skill = program.command("skill").description("Use and inspect skills");
|
|
9
45
|
skill
|
|
10
46
|
.command("list")
|
|
11
47
|
.description("List all available skills")
|
|
12
48
|
.option("--json", "Output as JSON")
|
|
49
|
+
.option("--type <type>", "Filter by type (guide|tool|connector)")
|
|
50
|
+
.option("--active", "Only show active skills")
|
|
51
|
+
.option("--ready", "Only show ready skills")
|
|
52
|
+
.option("--needs-setup", "Only show skills needing setup")
|
|
53
|
+
.option("--needs-install", "Only show skills needing install")
|
|
54
|
+
.option("--unavailable", "Only show unavailable skills")
|
|
55
|
+
.option("--all", "Include unavailable skills")
|
|
13
56
|
.action(async (opts) => {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
57
|
+
const config = loadConfig();
|
|
58
|
+
const workspaceDir = resolveUserPath(config.agent?.workspace ?? DEFAULT_AGENT_WORKSPACE_DIR);
|
|
59
|
+
const entries = loadWorkspaceSkillEntries(workspaceDir, {
|
|
60
|
+
config,
|
|
61
|
+
managedSkillsDir: MANAGED_SKILLS_DIR,
|
|
62
|
+
});
|
|
63
|
+
const status = buildWorkspaceSkillStatus(workspaceDir, {
|
|
64
|
+
config,
|
|
65
|
+
managedSkillsDir: MANAGED_SKILLS_DIR,
|
|
66
|
+
entries,
|
|
67
|
+
});
|
|
68
|
+
const statusMap = new Map(status.skills.map((item) => [item.name.toLowerCase(), item]));
|
|
69
|
+
const items = entries.map((entry) => {
|
|
70
|
+
const statusEntry = statusMap.get(entry.skill.name.toLowerCase());
|
|
71
|
+
const statusValue = statusEntry
|
|
72
|
+
? resolveSkillStatus(statusEntry)
|
|
73
|
+
: "unavailable";
|
|
74
|
+
return {
|
|
75
|
+
name: entry.skill.name,
|
|
76
|
+
description: entry.skill.description,
|
|
77
|
+
type: resolveSkillType(entry),
|
|
78
|
+
status: statusValue,
|
|
79
|
+
source: entry.skill.source,
|
|
80
|
+
filePath: entry.skill.filePath,
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
const typeFilter = opts.type
|
|
84
|
+
? String(opts.type).toLowerCase()
|
|
85
|
+
: undefined;
|
|
86
|
+
const statusFilters = new Set();
|
|
87
|
+
if (opts.active)
|
|
88
|
+
statusFilters.add("active");
|
|
89
|
+
if (opts.ready)
|
|
90
|
+
statusFilters.add("ready");
|
|
91
|
+
if (opts.needsSetup)
|
|
92
|
+
statusFilters.add("needs_setup");
|
|
93
|
+
if (opts.needsInstall)
|
|
94
|
+
statusFilters.add("needs_install");
|
|
95
|
+
if (opts.unavailable)
|
|
96
|
+
statusFilters.add("unavailable");
|
|
97
|
+
const hasStatusFilter = statusFilters.size > 0;
|
|
98
|
+
const filtered = items.filter((item) => {
|
|
99
|
+
if (typeFilter && item.type !== typeFilter)
|
|
100
|
+
return false;
|
|
101
|
+
if (hasStatusFilter && !statusFilters.has(item.status))
|
|
102
|
+
return false;
|
|
103
|
+
if (!hasStatusFilter && !opts.all && item.status === "unavailable")
|
|
104
|
+
return false;
|
|
105
|
+
return true;
|
|
106
|
+
});
|
|
19
107
|
if (opts.json) {
|
|
20
|
-
console.log(JSON.stringify(
|
|
108
|
+
console.log(JSON.stringify({
|
|
109
|
+
workspace: workspaceDir,
|
|
110
|
+
total: items.length,
|
|
111
|
+
filtered: filtered.length,
|
|
112
|
+
skills: filtered,
|
|
113
|
+
}, null, 2));
|
|
21
114
|
return;
|
|
22
115
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
console.log("No skills installed.");
|
|
116
|
+
if (filtered.length === 0) {
|
|
117
|
+
console.log("No skills matched.");
|
|
26
118
|
return;
|
|
27
119
|
}
|
|
28
|
-
console.log(`\nš Nexus Skills (${
|
|
29
|
-
for (const
|
|
30
|
-
const desc =
|
|
31
|
-
? ` - ${
|
|
120
|
+
console.log(`\nš Nexus Skills (${filtered.length} shown)\n`);
|
|
121
|
+
for (const item of filtered) {
|
|
122
|
+
const desc = item.description
|
|
123
|
+
? ` - ${item.description.slice(0, 60)}${item.description.length > 60 ? "..." : ""}`
|
|
32
124
|
: "";
|
|
33
|
-
|
|
125
|
+
const icon = STATUS_ICON[item.status] ?? "ā¢";
|
|
126
|
+
console.log(` ${icon} ${item.name}${desc}`);
|
|
34
127
|
}
|
|
35
128
|
console.log(`\nSkills directory: ${MANAGED_SKILLS_DIR}`);
|
|
36
129
|
console.log(`User skills: ${path.join(NEXUS_ROOT, "home", "skills")}\n`);
|
|
@@ -42,6 +135,7 @@ export function registerSkillsCommand(program) {
|
|
|
42
135
|
.option("--prompt", "Include the full SKILL.md prompt")
|
|
43
136
|
.action(async (name, opts) => {
|
|
44
137
|
const info = getSkillInfo(name);
|
|
138
|
+
const stats = await getSkillStats(name);
|
|
45
139
|
if (!info.exists) {
|
|
46
140
|
console.error(`Skill not found: ${name}`);
|
|
47
141
|
console.error(`\nRun 'nexus skill list' to see available skills.`);
|
|
@@ -49,7 +143,8 @@ export function registerSkillsCommand(program) {
|
|
|
49
143
|
}
|
|
50
144
|
if (opts.json) {
|
|
51
145
|
const output = opts.prompt ? info : { ...info, prompt: undefined };
|
|
52
|
-
|
|
146
|
+
const payload = stats ? { ...output, usage: stats } : output;
|
|
147
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
53
148
|
return;
|
|
54
149
|
}
|
|
55
150
|
console.log(`\n${chalk.bold.cyan("Skill:")} ${info.name}`);
|
|
@@ -63,12 +158,16 @@ export function registerSkillsCommand(program) {
|
|
|
63
158
|
const statusColor = info.configured ? chalk.green : chalk.yellow;
|
|
64
159
|
const statusIcon = info.configured ? "ā" : "ā";
|
|
65
160
|
console.log(`${chalk.bold("Status:")} ${statusColor(`${statusIcon} ${info.configured ? "Configured" : "Not configured"}`)}`);
|
|
66
|
-
if (info.lastUsed) {
|
|
67
|
-
console.log(`${chalk.bold("Last used:")} ${info.lastUsed}`);
|
|
161
|
+
if (stats?.lastUsed ?? info.lastUsed) {
|
|
162
|
+
console.log(`${chalk.bold("Last used:")} ${stats?.lastUsed ?? info.lastUsed}`);
|
|
68
163
|
}
|
|
69
164
|
if (info.lastError) {
|
|
70
165
|
console.log(`${chalk.bold("Last error:")} ${chalk.red(info.lastError)}`);
|
|
71
166
|
}
|
|
167
|
+
if (stats) {
|
|
168
|
+
console.log(`${chalk.bold("Runs:")} ${stats.runs}`);
|
|
169
|
+
console.log(`${chalk.bold("Errors:")} ${stats.errors}`);
|
|
170
|
+
}
|
|
72
171
|
if (opts.prompt && info.prompt) {
|
|
73
172
|
console.log(`\n${chalk.bold.cyan("--- SKILL.md ---")}\n`);
|
|
74
173
|
console.log(info.prompt);
|
|
@@ -76,6 +175,23 @@ export function registerSkillsCommand(program) {
|
|
|
76
175
|
});
|
|
77
176
|
skill
|
|
78
177
|
.command("use <name>")
|
|
178
|
+
.description("Show the SKILL.md guide for a skill")
|
|
179
|
+
.action(async (name) => {
|
|
180
|
+
const info = getSkillInfo(name);
|
|
181
|
+
if (!info.exists) {
|
|
182
|
+
console.error(`Skill not found: ${name}`);
|
|
183
|
+
console.error(`\nRun 'nexus skill list' to see available skills.`);
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
if (!info.prompt) {
|
|
187
|
+
console.error(`No SKILL.md found for ${name}.`);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
console.log(info.prompt.trimEnd());
|
|
191
|
+
recordSkillUsage(name, { ts: Date.now(), event: "use", ok: true });
|
|
192
|
+
});
|
|
193
|
+
skill
|
|
194
|
+
.command("run <name>")
|
|
79
195
|
.description("Run a skill command with arguments")
|
|
80
196
|
.allowUnknownOption()
|
|
81
197
|
.action(async (name, _opts, command) => {
|
|
@@ -126,7 +242,14 @@ export function registerSkillsCommand(program) {
|
|
|
126
242
|
}
|
|
127
243
|
console.log(`Total skill runs: ${stats.totalRuns}`);
|
|
128
244
|
console.log(`Active skills: ${stats.activeSkills}`);
|
|
129
|
-
|
|
245
|
+
if (stats.topUsed && stats.topUsed.length > 0) {
|
|
246
|
+
console.log(`Most used: ${stats.topUsed
|
|
247
|
+
.map((item) => `${item.name} (${item.runs})`)
|
|
248
|
+
.join(", ")}`);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
console.log("Most used: none");
|
|
252
|
+
}
|
|
130
253
|
console.log(`Ready but unused: ${stats.readyButUnused?.join(", ") || "none"}`);
|
|
131
254
|
});
|
|
132
255
|
}
|