@nextclaw/service 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/agent/agent-runtime.utils.d.ts +1 -2
- package/dist/cli/commands/agent/agent-runtime.utils.js +6 -50
- package/dist/cli/commands/agent/cli-agent-runner.utils.d.ts +0 -2
- package/dist/cli/commands/agent/cli-agent-runner.utils.js +7 -9
- package/dist/cli/commands/agent/services/agent-commands.service.js +0 -1
- package/dist/cli/commands/cron/services/cron-local.service.d.ts +1 -2
- package/dist/cli/commands/skills/index.js +1 -1
- package/dist/cli/commands/skills/marketplace-client.d.ts +11 -1
- package/dist/cli/commands/skills/marketplace-client.js +39 -1
- package/dist/cli/commands/skills/marketplace-command-options.utils.d.ts +1 -1
- package/dist/cli/commands/skills/marketplace.metadata.d.ts +3 -12
- package/dist/cli/commands/skills/marketplace.metadata.js +1 -87
- package/dist/cli/commands/skills/{marketplace.service.d.ts → marketplace.utils.d.ts} +1 -1
- package/dist/cli/commands/skills/{marketplace.service.js → marketplace.utils.js} +11 -47
- package/dist/cli/commands/skills/skills-query.service.d.ts +4 -37
- package/dist/cli/commands/skills/skills-query.service.js +16 -98
- package/dist/cli/commands/usage/services/llm-usage-command.service.d.ts +3 -5
- package/dist/cli/commands/usage/services/llm-usage-command.service.js +16 -26
- package/dist/commands/channel/channel-list-view.service.d.ts +0 -1
- package/dist/commands/channel/channel-list-view.service.js +6 -23
- package/dist/commands/channel/index.js +0 -1
- package/dist/commands/plugin/index.d.ts +2 -4
- package/dist/commands/plugin/index.js +8 -20
- package/dist/commands/plugin/{plugin-command-utils.d.ts → plugin-command.utils.d.ts} +1 -2
- package/dist/commands/plugin/{plugin-command-utils.js → plugin-command.utils.js} +2 -4
- package/dist/commands/plugin/{plugin-mutation-actions.d.ts → plugin-mutation-actions.utils.d.ts} +1 -1
- package/dist/commands/plugin/{plugin-mutation-actions.js → plugin-mutation-actions.utils.js} +2 -2
- package/dist/commands/service/services/autostart/linux-systemd-autostart.service.js +1 -1
- package/dist/commands/service/services/autostart/macos-launch-agent-autostart.service.js +1 -1
- package/dist/commands/service/services/autostart/windows-task-autostart.service.js +1 -1
- package/dist/launcher/npm-runtime-launcher.service.js +1 -1
- package/dist/service-runtime.service.d.ts +1 -1
- package/dist/service-runtime.service.js +7 -15
- package/dist/shared/controllers/gateway.controller.d.ts +3 -11
- package/dist/shared/controllers/gateway.controller.js +24 -180
- package/dist/shared/services/gateway/managers/gateway-plugin.manager.d.ts +2 -9
- package/dist/shared/services/gateway/managers/gateway-plugin.manager.js +30 -88
- package/dist/shared/services/gateway/nextclaw-app.service.d.ts +2 -7
- package/dist/shared/services/gateway/nextclaw-app.service.js +6 -16
- package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.d.ts +4 -9
- package/dist/shared/services/gateway/nextclaw-gateway-runtime.service.js +12 -46
- package/dist/shared/services/gateway/{cron-job-handler.service.d.ts → utils/cron-job-handler.utils.d.ts} +3 -6
- package/dist/shared/services/gateway/utils/cron-job-handler.utils.js +57 -0
- package/dist/shared/services/marketplace/service-marketplace-installer.service.js +3 -3
- package/dist/shared/services/plugin/utils/plugin-runtime-bridge.utils.js +1 -1
- package/dist/shared/services/runtime/runtime-command.service.js +2 -2
- package/dist/shared/services/runtime/service-managed-startup.service.js +1 -1
- package/dist/shared/services/ui/companion-runtime.service.js +1 -1
- package/dist/shared/services/workspace/workspace-manager.service.js +8 -10
- package/dist/shared/utils/cli.utils.js +1 -1
- package/package.json +20 -20
- package/dist/cli/commands/usage/services/llm-usage-query.service.d.ts +0 -43
- package/dist/cli/commands/usage/services/llm-usage-query.service.js +0 -85
- package/dist/commands/plugin/development-source/dev-plugin-overrides.utils.d.ts +0 -18
- package/dist/commands/plugin/development-source/dev-plugin-overrides.utils.js +0 -111
- package/dist/commands/plugin/development-source/first-party-plugin-load-paths.utils.d.ts +0 -9
- package/dist/commands/plugin/development-source/first-party-plugin-load-paths.utils.js +0 -183
- package/dist/commands/plugin/plugin-extension-registry.d.ts +0 -10
- package/dist/commands/plugin/plugin-extension-registry.js +0 -35
- package/dist/commands/plugin/plugin-registry-loader.utils.d.ts +0 -14
- package/dist/commands/plugin/plugin-registry-loader.utils.js +0 -43
- package/dist/commands/plugin/plugin-reload.d.ts +0 -13
- package/dist/commands/plugin/plugin-reload.js +0 -42
- package/dist/shared/services/extensions/extension-lifecycle.service.d.ts +0 -63
- package/dist/shared/services/extensions/extension-lifecycle.service.js +0 -174
- package/dist/shared/services/extensions/service-extension-runtime.service.d.ts +0 -52
- package/dist/shared/services/extensions/service-extension-runtime.service.js +0 -325
- package/dist/shared/services/gateway/cron-job-handler.service.js +0 -100
- package/dist/shared/services/runtime/utils/skills-loader.utils.d.ts +0 -12
- package/dist/shared/services/runtime/utils/skills-loader.utils.js +0 -9
- package/dist/shared/services/session/service-deferred-ncp-agent.service.d.ts +0 -14
- package/dist/shared/services/session/service-deferred-ncp-agent.service.js +0 -85
|
@@ -3,8 +3,7 @@ import { AgentRuntimeSessionTypeDescribeParams, AgentRuntimeSessionTypeOption }
|
|
|
3
3
|
//#region src/cli/commands/agent/agent-runtime.utils.d.ts
|
|
4
4
|
type AgentRuntimeListEntry = AgentRuntimeSessionTypeOption & {
|
|
5
5
|
default: boolean;
|
|
6
|
-
source: "builtin"
|
|
7
|
-
pluginId?: string;
|
|
6
|
+
source: "builtin";
|
|
8
7
|
};
|
|
9
8
|
type AgentRuntimeListResult = {
|
|
10
9
|
defaultRuntime: string;
|
|
@@ -1,37 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { resolveDevPluginLoadingContext } from "../../../commands/plugin/development-source/dev-plugin-overrides.utils.js";
|
|
4
|
-
import { toExtensionRegistry } from "../../../commands/plugin/plugin-extension-registry.js";
|
|
5
|
-
import { logPluginDiagnostics } from "../../../commands/plugin/index.js";
|
|
6
|
-
import { getWorkspacePath, loadConfig } from "@nextclaw/core";
|
|
7
|
-
import { AgentRuntimeRegistry, BuiltinNarpRuntimeRegistrationService, DEFAULT_AGENT_RUNTIME_ENTRY_ID, NARP_HTTP_RUNTIME_KIND, NARP_STDIO_RUNTIME_KIND, resolveAgentRuntimeEntries } from "@nextclaw/kernel";
|
|
8
|
-
import { loadOpenClawPlugins } from "@nextclaw/openclaw-compat";
|
|
1
|
+
import { loadConfig } from "@nextclaw/core";
|
|
2
|
+
import { AgentRuntimeRegistry, BuiltinNarpRuntimeProviderService, DEFAULT_AGENT_RUNTIME_ENTRY_ID, resolveAgentRuntimeEntries } from "@nextclaw/kernel";
|
|
9
3
|
//#region src/cli/commands/agent/agent-runtime.utils.ts
|
|
10
4
|
function createUnusedRuntime(_params) {
|
|
11
5
|
throw new Error("runtime creation is not available during runtime listing");
|
|
12
6
|
}
|
|
13
|
-
function loadRuntimeOnlyPluginRegistry(config, workspaceDir) {
|
|
14
|
-
const { configWithDevPluginOverrides, excludedRoots } = resolveDevPluginLoadingContext(config, resolveDevFirstPartyPluginDir(process.env.NEXTCLAW_DEV_FIRST_PARTY_PLUGIN_DIR));
|
|
15
|
-
return loadOpenClawPlugins({
|
|
16
|
-
config: configWithDevPluginOverrides,
|
|
17
|
-
workspaceDir,
|
|
18
|
-
includeBundled: false,
|
|
19
|
-
kinds: ["agent-runtime"],
|
|
20
|
-
excludeRoots: excludedRoots,
|
|
21
|
-
...buildReservedPluginLoadOptions(),
|
|
22
|
-
logger: {
|
|
23
|
-
info: (message) => console.log(message),
|
|
24
|
-
warn: (message) => console.warn(message),
|
|
25
|
-
error: (message) => console.error(message),
|
|
26
|
-
debug: (message) => console.debug(message)
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
7
|
async function listAvailableAgentRuntimes(params) {
|
|
31
8
|
const config = loadConfig();
|
|
32
|
-
const pluginRegistry = loadRuntimeOnlyPluginRegistry(config, getWorkspacePath(config.agents.defaults.workspace));
|
|
33
|
-
logPluginDiagnostics(pluginRegistry);
|
|
34
|
-
const extensionRegistry = toExtensionRegistry(pluginRegistry);
|
|
35
9
|
const runtimeRegistry = new AgentRuntimeRegistry();
|
|
36
10
|
const runtimeSourceByKind = /* @__PURE__ */ new Map();
|
|
37
11
|
const runtimeSourceByEntryId = /* @__PURE__ */ new Map();
|
|
@@ -41,31 +15,14 @@ async function listAvailableAgentRuntimes(params) {
|
|
|
41
15
|
createRuntime: createUnusedRuntime
|
|
42
16
|
});
|
|
43
17
|
runtimeSourceByKind.set(DEFAULT_AGENT_RUNTIME_ENTRY_ID, { source: "builtin" });
|
|
44
|
-
new
|
|
18
|
+
for (const provider of new BuiltinNarpRuntimeProviderService(() => config).createProviders()) runtimeRegistry.register(provider);
|
|
45
19
|
runtimeSourceByKind.set("narp-http", { source: "builtin" });
|
|
46
20
|
runtimeSourceByKind.set("narp-stdio", { source: "builtin" });
|
|
47
|
-
|
|
48
|
-
const normalizedKind = registration.kind.trim().toLowerCase();
|
|
49
|
-
if (normalizedKind === NARP_HTTP_RUNTIME_KIND || normalizedKind === NARP_STDIO_RUNTIME_KIND) continue;
|
|
50
|
-
runtimeRegistry.register({
|
|
51
|
-
kind: registration.kind,
|
|
52
|
-
label: registration.label,
|
|
53
|
-
createRuntime: registration.createRuntime,
|
|
54
|
-
describeSessionType: registration.describeSessionType
|
|
55
|
-
});
|
|
56
|
-
runtimeSourceByKind.set(registration.kind, {
|
|
57
|
-
source: "plugin",
|
|
58
|
-
pluginId: registration.pluginId
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
const resolvedEntries = resolveAgentRuntimeEntries({
|
|
62
|
-
config,
|
|
63
|
-
providerKinds: runtimeRegistry.listProviderKinds()
|
|
64
|
-
});
|
|
21
|
+
const resolvedEntries = resolveAgentRuntimeEntries({ config });
|
|
65
22
|
runtimeRegistry.applyEntries(resolvedEntries);
|
|
66
23
|
for (const entry of resolvedEntries.entries) {
|
|
67
24
|
const source = runtimeSourceByKind.get(entry.type);
|
|
68
|
-
runtimeSourceByEntryId.set(entry.id, source ?? { source:
|
|
25
|
+
runtimeSourceByEntryId.set(entry.id, source ?? { source: "builtin" });
|
|
69
26
|
}
|
|
70
27
|
const listed = await runtimeRegistry.listSessionTypes(params);
|
|
71
28
|
return {
|
|
@@ -75,8 +32,7 @@ async function listAvailableAgentRuntimes(params) {
|
|
|
75
32
|
return {
|
|
76
33
|
...runtime,
|
|
77
34
|
default: runtime.value === listed.defaultType,
|
|
78
|
-
source: source?.source ?? "
|
|
79
|
-
...source?.pluginId ? { pluginId: source.pluginId } : {}
|
|
35
|
+
source: source?.source ?? "builtin"
|
|
80
36
|
};
|
|
81
37
|
})
|
|
82
38
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AgentCommandOptions } from "../../../shared/types/cli.types.js";
|
|
2
|
-
import { NextclawExtensionRegistry } from "../../../commands/plugin/plugin-extension-registry.js";
|
|
3
2
|
import { Config } from "@nextclaw/core";
|
|
4
3
|
import { LlmProviderRuntime, NextclawKernel } from "@nextclaw/kernel";
|
|
5
4
|
|
|
@@ -10,7 +9,6 @@ declare function runCliAgentCommand(params: {
|
|
|
10
9
|
config: Config;
|
|
11
10
|
kernel: NextclawKernel;
|
|
12
11
|
providerManager: LlmProviderRuntime;
|
|
13
|
-
extensionRegistry: NextclawExtensionRegistry;
|
|
14
12
|
}): Promise<void>;
|
|
15
13
|
//#endregion
|
|
16
14
|
export { runCliAgentCommand };
|
|
@@ -30,7 +30,7 @@ function createCliHistoryInterface() {
|
|
|
30
30
|
return rl;
|
|
31
31
|
}
|
|
32
32
|
async function runCliInteractiveLoop(params) {
|
|
33
|
-
const { config, logo, metadata,
|
|
33
|
+
const { agentRunRequests, config, logo, metadata, sessionKey, sessionManager } = params;
|
|
34
34
|
console.log(`${logo} Interactive mode (type exit or Ctrl+C to quit)\n`);
|
|
35
35
|
const rl = createCliHistoryInterface();
|
|
36
36
|
let running = true;
|
|
@@ -45,7 +45,7 @@ async function runCliInteractiveLoop(params) {
|
|
|
45
45
|
printAgentResponse(await dispatchPromptOverNcp({
|
|
46
46
|
config,
|
|
47
47
|
sessionManager,
|
|
48
|
-
|
|
48
|
+
agentRunRequests,
|
|
49
49
|
sessionKey,
|
|
50
50
|
content: trimmed,
|
|
51
51
|
metadata
|
|
@@ -53,12 +53,10 @@ async function runCliInteractiveLoop(params) {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
async function runCliAgentCommand(params) {
|
|
56
|
-
const { config,
|
|
56
|
+
const { config, kernel, logo, opts } = params;
|
|
57
57
|
const sessionManager = kernel.sessions;
|
|
58
|
-
kernel.extensions.
|
|
58
|
+
await kernel.extensions.load({ config });
|
|
59
59
|
await kernel.start();
|
|
60
|
-
const ncpAgent = kernel.agentRuntimeManager.currentHandle;
|
|
61
|
-
if (!ncpAgent) throw new Error("Kernel start completed without an agent runtime handle.");
|
|
62
60
|
try {
|
|
63
61
|
const sessionKey = opts.session ?? "cli:default";
|
|
64
62
|
const sharedMetadata = buildCliSharedMetadata(opts);
|
|
@@ -66,7 +64,7 @@ async function runCliAgentCommand(params) {
|
|
|
66
64
|
printAgentResponse(await dispatchPromptOverNcp({
|
|
67
65
|
config,
|
|
68
66
|
sessionManager,
|
|
69
|
-
|
|
67
|
+
agentRunRequests: kernel.agentRunRequestManager,
|
|
70
68
|
sessionKey,
|
|
71
69
|
content: opts.message,
|
|
72
70
|
metadata: sharedMetadata
|
|
@@ -77,12 +75,12 @@ async function runCliAgentCommand(params) {
|
|
|
77
75
|
logo,
|
|
78
76
|
config,
|
|
79
77
|
sessionManager,
|
|
80
|
-
|
|
78
|
+
agentRunRequests: kernel.agentRunRequestManager,
|
|
81
79
|
sessionKey,
|
|
82
80
|
metadata: sharedMetadata
|
|
83
81
|
});
|
|
84
82
|
} finally {
|
|
85
|
-
await
|
|
83
|
+
await kernel.dispose();
|
|
86
84
|
}
|
|
87
85
|
}
|
|
88
86
|
//#endregion
|
|
@@ -37,7 +37,6 @@ var AgentCommands = class {
|
|
|
37
37
|
console.log(head);
|
|
38
38
|
console.log(` label: ${runtime.label}`);
|
|
39
39
|
console.log(` source: ${runtime.source}`);
|
|
40
|
-
if (runtime.pluginId) console.log(` pluginId: ${runtime.pluginId}`);
|
|
41
40
|
console.log(` ready: ${runtime.ready === false ? "no" : "yes"}`);
|
|
42
41
|
console.log(` reason: ${runtime.reason ?? "-"}`);
|
|
43
42
|
console.log(` reasonMessage: ${runtime.reasonMessage ?? "-"}`);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { CronAddOptions } from "../../../../shared/types/cli.types.js";
|
|
2
2
|
import { CronJobView } from "../utils/cron-job.utils.js";
|
|
3
|
-
import { AutomationManager } from "@nextclaw/kernel";
|
|
4
3
|
import { CronCreateRequest } from "@nextclaw/server";
|
|
5
4
|
|
|
6
5
|
//#region src/cli/commands/cron/services/cron-local.service.d.ts
|
|
@@ -10,7 +9,7 @@ declare function createCronCreateRequest(opts: CronAddOptions): {
|
|
|
10
9
|
};
|
|
11
10
|
declare class CronLocalService {
|
|
12
11
|
private readonly automation;
|
|
13
|
-
constructor(automation?:
|
|
12
|
+
constructor(automation?: any);
|
|
14
13
|
readonly list: (all: boolean) => CronJobView[];
|
|
15
14
|
readonly addRequest: (request: CronCreateRequest) => CronJobView;
|
|
16
15
|
readonly add: (opts: CronAddOptions) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolveSkillsInstallWorkdir } from "../../../shared/utils/runtime-helpers.js";
|
|
2
2
|
import { buildMarketplacePublishOptions, buildMarketplaceUpdateOptions } from "./marketplace-command-options.utils.js";
|
|
3
|
-
import { installMarketplaceSkill, publishMarketplaceSkill } from "./marketplace.
|
|
3
|
+
import { installMarketplaceSkill, publishMarketplaceSkill } from "./marketplace.utils.js";
|
|
4
4
|
import { SkillsQueryService } from "./skills-query.service.js";
|
|
5
5
|
import { loadConfig } from "@nextclaw/core";
|
|
6
6
|
//#region src/cli/commands/skills/index.ts
|
|
@@ -26,6 +26,16 @@ declare function fetchMarketplaceSkillFiles(apiBase: string, slug: string): Prom
|
|
|
26
26
|
files: MarketplaceSkillFileManifestEntry[];
|
|
27
27
|
}>;
|
|
28
28
|
declare function fetchMarketplaceSkillFileBlob(apiBase: string, slug: string, file: MarketplaceSkillFileManifestEntry): Promise<Buffer>;
|
|
29
|
+
declare function collectMarketplaceSkillFiles(rootDir: string): Array<{
|
|
30
|
+
path: string;
|
|
31
|
+
contentBase64: string;
|
|
32
|
+
}>;
|
|
33
|
+
declare function writeMarketplaceSkillFiles(params: {
|
|
34
|
+
destinationDir: string;
|
|
35
|
+
files: MarketplaceSkillFileManifestEntry[];
|
|
36
|
+
apiBase: string;
|
|
37
|
+
slug: string;
|
|
38
|
+
}): Promise<void>;
|
|
29
39
|
declare function readMarketplaceEnvelope<T>(response: Response): Promise<MarketplaceEnvelope<T>>;
|
|
30
40
|
//#endregion
|
|
31
|
-
export { MarketplaceSkillFileManifestEntry, fetchMarketplaceSkillFileBlob, fetchMarketplaceSkillFiles, fetchMarketplaceSkillItem, readMarketplaceEnvelope, resolveMarketplaceAdminToken, resolveMarketplaceApiBase };
|
|
41
|
+
export { MarketplaceSkillFileManifestEntry, collectMarketplaceSkillFiles, fetchMarketplaceSkillFileBlob, fetchMarketplaceSkillFiles, fetchMarketplaceSkillItem, readMarketplaceEnvelope, resolveMarketplaceAdminToken, resolveMarketplaceApiBase, writeMarketplaceSkillFiles };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { runWithMarketplaceNetworkRetry } from "./marketplace-network-retry.js";
|
|
2
|
+
import { mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
2
4
|
//#region src/cli/commands/skills/marketplace-client.ts
|
|
3
5
|
const DEFAULT_MARKETPLACE_API_BASE = "https://marketplace-api.nextclaw.io";
|
|
4
6
|
function resolveMarketplaceApiBase(explicitBase) {
|
|
@@ -54,6 +56,37 @@ async function fetchMarketplaceSkillFileBlob(apiBase, slug, file) {
|
|
|
54
56
|
return Buffer.from(await response.arrayBuffer());
|
|
55
57
|
});
|
|
56
58
|
}
|
|
59
|
+
function collectMarketplaceSkillFiles(rootDir) {
|
|
60
|
+
const output = [];
|
|
61
|
+
const walk = (dir, prefix) => {
|
|
62
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
63
|
+
for (const entry of entries) {
|
|
64
|
+
const absolute = join(dir, entry.name);
|
|
65
|
+
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
66
|
+
if (entry.isDirectory()) {
|
|
67
|
+
walk(absolute, relativePath);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (!entry.isFile()) continue;
|
|
71
|
+
output.push({
|
|
72
|
+
path: relativePath,
|
|
73
|
+
contentBase64: readFileSync(absolute).toString("base64")
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
walk(rootDir, "");
|
|
78
|
+
return output;
|
|
79
|
+
}
|
|
80
|
+
async function writeMarketplaceSkillFiles(params) {
|
|
81
|
+
const { destinationDir, files, apiBase, slug } = params;
|
|
82
|
+
for (const file of files) {
|
|
83
|
+
const targetPath = resolve(destinationDir, ...file.path.split("/"));
|
|
84
|
+
const rel = relative(destinationDir, targetPath);
|
|
85
|
+
if (rel.startsWith("..") || isAbsolute(rel)) throw new Error(`Invalid marketplace file path: ${file.path}`);
|
|
86
|
+
mkdirSync(dirname(targetPath), { recursive: true });
|
|
87
|
+
writeFileSync(targetPath, file.contentBase64 ? decodeMarketplaceFileContent(file.path, file.contentBase64) : await fetchMarketplaceSkillFileBlob(apiBase, slug, file));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
57
90
|
async function readMarketplaceEnvelope(response) {
|
|
58
91
|
const raw = await response.text();
|
|
59
92
|
let payload;
|
|
@@ -77,8 +110,13 @@ function extractMarketplaceErrorMessage(raw, fallbackStatus) {
|
|
|
77
110
|
return raw || `Request failed (${fallbackStatus})`;
|
|
78
111
|
}
|
|
79
112
|
}
|
|
113
|
+
function decodeMarketplaceFileContent(path, contentBase64) {
|
|
114
|
+
const normalized = contentBase64.replace(/\s+/g, "");
|
|
115
|
+
if (!normalized || normalized.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(normalized)) throw new Error(`Invalid marketplace file contentBase64 for path: ${path}`);
|
|
116
|
+
return Buffer.from(normalized, "base64");
|
|
117
|
+
}
|
|
80
118
|
function isRecord(value) {
|
|
81
119
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
82
120
|
}
|
|
83
121
|
//#endregion
|
|
84
|
-
export { fetchMarketplaceSkillFileBlob, fetchMarketplaceSkillFiles, fetchMarketplaceSkillItem, readMarketplaceEnvelope, resolveMarketplaceAdminToken, resolveMarketplaceApiBase };
|
|
122
|
+
export { collectMarketplaceSkillFiles, fetchMarketplaceSkillFileBlob, fetchMarketplaceSkillFiles, fetchMarketplaceSkillItem, readMarketplaceEnvelope, resolveMarketplaceAdminToken, resolveMarketplaceApiBase, writeMarketplaceSkillFiles };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { LocalizedTextMap, buildLocalizedTextMap, parseSkillFrontmatter } from "@nextclaw/kernel";
|
|
2
|
+
|
|
1
3
|
//#region src/cli/commands/skills/marketplace.metadata.d.ts
|
|
2
|
-
type LocalizedTextMap = Record<string, string>;
|
|
3
4
|
type MarketplaceSkillPublishMetadata = {
|
|
4
5
|
slug?: string;
|
|
5
6
|
name?: string;
|
|
@@ -14,16 +15,6 @@ type MarketplaceSkillPublishMetadata = {
|
|
|
14
15
|
publishedAt?: string;
|
|
15
16
|
updatedAt?: string;
|
|
16
17
|
};
|
|
17
|
-
declare function parseSkillFrontmatter(raw: string): {
|
|
18
|
-
name?: string;
|
|
19
|
-
summary?: string;
|
|
20
|
-
summaryI18n?: LocalizedTextMap;
|
|
21
|
-
description?: string;
|
|
22
|
-
descriptionI18n?: LocalizedTextMap;
|
|
23
|
-
author?: string;
|
|
24
|
-
tags?: string[];
|
|
25
|
-
};
|
|
26
|
-
declare function buildLocalizedTextMap(englishText: string, ...maps: Array<LocalizedTextMap | Partial<LocalizedTextMap> | undefined>): LocalizedTextMap;
|
|
27
18
|
declare function readMarketplaceMetadataFile(skillDir: string, explicitMetaFile?: string): MarketplaceSkillPublishMetadata;
|
|
28
19
|
//#endregion
|
|
29
|
-
export { LocalizedTextMap, MarketplaceSkillPublishMetadata, buildLocalizedTextMap, parseSkillFrontmatter, readMarketplaceMetadataFile };
|
|
20
|
+
export { type LocalizedTextMap, MarketplaceSkillPublishMetadata, buildLocalizedTextMap, parseSkillFrontmatter, readMarketplaceMetadataFile };
|
|
@@ -1,39 +1,8 @@
|
|
|
1
|
+
import { buildLocalizedTextMap, parseSkillFrontmatter } from "@nextclaw/kernel";
|
|
1
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
3
|
import { resolve } from "node:path";
|
|
3
|
-
import { parse } from "yaml";
|
|
4
4
|
//#region src/cli/commands/skills/marketplace.metadata.ts
|
|
5
5
|
const DEFAULT_MARKETPLACE_META_FILENAME = "marketplace.json";
|
|
6
|
-
function parseSkillFrontmatter(raw) {
|
|
7
|
-
const match = raw.replace(/\r\n/g, "\n").match(/^---\n([\s\S]*?)\n---/);
|
|
8
|
-
if (!match || !match[1]) return {};
|
|
9
|
-
let parsed;
|
|
10
|
-
try {
|
|
11
|
-
parsed = parse(match[1]);
|
|
12
|
-
} catch (error) {
|
|
13
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
14
|
-
throw new Error(`Invalid SKILL.md frontmatter: ${message}`);
|
|
15
|
-
}
|
|
16
|
-
if (!isRecord(parsed)) return {};
|
|
17
|
-
const summaryI18n = readLocalizedTextMapField(parsed, [["summaryi18n"], ["summary_i18n"]]);
|
|
18
|
-
const descriptionI18n = readLocalizedTextMapField(parsed, [["descriptioni18n"], ["description_i18n"]]);
|
|
19
|
-
const summaryZh = readFrontmatterStringField(parsed, [["summaryzh"], ["summary_zh"]]);
|
|
20
|
-
const descriptionZh = readFrontmatterStringField(parsed, [["descriptionzh"], ["description_zh"]]);
|
|
21
|
-
return {
|
|
22
|
-
name: readFrontmatterStringField(parsed, [["name"]]),
|
|
23
|
-
summary: readFrontmatterStringField(parsed, [["summary"]]),
|
|
24
|
-
summaryI18n: mergeLocalizedTextMap(summaryI18n, { zh: summaryZh }),
|
|
25
|
-
description: readFrontmatterStringField(parsed, [["description"]]),
|
|
26
|
-
descriptionI18n: mergeLocalizedTextMap(descriptionI18n, { zh: descriptionZh }),
|
|
27
|
-
author: readFrontmatterStringField(parsed, [["author"]]),
|
|
28
|
-
tags: readFrontmatterTags(parsed)
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
function buildLocalizedTextMap(englishText, ...maps) {
|
|
32
|
-
return {
|
|
33
|
-
...mergeLocalizedTextMap(...maps) ?? {},
|
|
34
|
-
en: englishText
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
6
|
function readMarketplaceMetadataFile(skillDir, explicitMetaFile) {
|
|
38
7
|
const metadataPath = resolveMarketplaceMetadataPath(skillDir, explicitMetaFile);
|
|
39
8
|
if (!metadataPath) return {};
|
|
@@ -64,15 +33,6 @@ function resolveMarketplaceMetadataPath(skillDir, explicitMetaFile) {
|
|
|
64
33
|
const resolved = explicitMetaFile?.trim() ? resolve(explicitMetaFile) : resolve(skillDir, DEFAULT_MARKETPLACE_META_FILENAME);
|
|
65
34
|
return existsSync(resolved) ? resolved : void 0;
|
|
66
35
|
}
|
|
67
|
-
function mergeLocalizedTextMap(...maps) {
|
|
68
|
-
const localized = {};
|
|
69
|
-
for (const map of maps) for (const [locale, text] of Object.entries(map ?? {})) {
|
|
70
|
-
const normalizedText = typeof text === "string" ? text.trim() : "";
|
|
71
|
-
if (!normalizedText) continue;
|
|
72
|
-
localized[normalizeLocaleTag(locale)] = normalizedText;
|
|
73
|
-
}
|
|
74
|
-
return Object.keys(localized).length > 0 ? localized : void 0;
|
|
75
|
-
}
|
|
76
36
|
function readMetadataString(record, fieldName) {
|
|
77
37
|
const value = record[fieldName];
|
|
78
38
|
if (value == null) return;
|
|
@@ -102,52 +62,6 @@ function readMetadataLocalizedTextMap(record, fieldName) {
|
|
|
102
62
|
}
|
|
103
63
|
return Object.keys(localized).length > 0 ? localized : void 0;
|
|
104
64
|
}
|
|
105
|
-
function readFrontmatterStringField(record, keyPaths) {
|
|
106
|
-
for (const keyPath of keyPaths) {
|
|
107
|
-
const value = readNestedFrontmatterValue(record, keyPath);
|
|
108
|
-
if (typeof value !== "string") continue;
|
|
109
|
-
const normalized = value.trim();
|
|
110
|
-
if (normalized) return normalized;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
function readLocalizedTextMapField(record, keyPaths) {
|
|
114
|
-
for (const keyPath of keyPaths) {
|
|
115
|
-
const value = readNestedFrontmatterValue(record, keyPath);
|
|
116
|
-
if (!isRecord(value)) continue;
|
|
117
|
-
const normalized = {};
|
|
118
|
-
for (const [locale, text] of Object.entries(value)) {
|
|
119
|
-
if (typeof text !== "string") continue;
|
|
120
|
-
const trimmed = text.trim();
|
|
121
|
-
if (!trimmed) continue;
|
|
122
|
-
normalized[normalizeLocaleTag(locale)] = trimmed;
|
|
123
|
-
}
|
|
124
|
-
if (Object.keys(normalized).length > 0) return normalized;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
function readFrontmatterTags(record) {
|
|
128
|
-
const rawTags = readNestedFrontmatterValue(record, ["tags"]);
|
|
129
|
-
if (Array.isArray(rawTags)) {
|
|
130
|
-
const tags = rawTags.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean);
|
|
131
|
-
return tags.length > 0 ? tags : void 0;
|
|
132
|
-
}
|
|
133
|
-
if (typeof rawTags !== "string") return;
|
|
134
|
-
const tags = rawTags.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
135
|
-
return tags.length > 0 ? tags : void 0;
|
|
136
|
-
}
|
|
137
|
-
function readNestedFrontmatterValue(record, keyPath) {
|
|
138
|
-
let current = record;
|
|
139
|
-
for (const rawKey of keyPath) {
|
|
140
|
-
if (!isRecord(current)) return;
|
|
141
|
-
const normalizedKey = normalizeFrontmatterKey(rawKey);
|
|
142
|
-
const matchingKey = Object.keys(current).find((candidate) => normalizeFrontmatterKey(candidate) === normalizedKey);
|
|
143
|
-
if (!matchingKey) return;
|
|
144
|
-
current = current[matchingKey];
|
|
145
|
-
}
|
|
146
|
-
return current;
|
|
147
|
-
}
|
|
148
|
-
function normalizeFrontmatterKey(raw) {
|
|
149
|
-
return raw.replace(/[-_]/g, "").toLowerCase();
|
|
150
|
-
}
|
|
151
65
|
function normalizeLocaleTag(raw) {
|
|
152
66
|
return raw.trim().toLowerCase();
|
|
153
67
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LocalizedTextMap } from "./marketplace.metadata.js";
|
|
2
2
|
|
|
3
|
-
//#region src/cli/commands/skills/marketplace.
|
|
3
|
+
//#region src/cli/commands/skills/marketplace.utils.d.ts
|
|
4
4
|
type MarketplaceSkillInstallKind = "builtin" | "marketplace";
|
|
5
5
|
type MarketplaceSkillInstallOptions = {
|
|
6
6
|
slug: string;
|
|
@@ -2,12 +2,13 @@ import { PlatformAuthCommands } from "../../../commands/platform-auth/services/p
|
|
|
2
2
|
import "../../../commands/platform-auth/index.js";
|
|
3
3
|
import { buildLocalizedTextMap, parseSkillFrontmatter, readMarketplaceMetadataFile } from "./marketplace.metadata.js";
|
|
4
4
|
import { runWithMarketplaceNetworkRetry } from "./marketplace-network-retry.js";
|
|
5
|
-
import {
|
|
5
|
+
import { collectMarketplaceSkillFiles, fetchMarketplaceSkillFiles, fetchMarketplaceSkillItem, readMarketplaceEnvelope, resolveMarketplaceAdminToken, resolveMarketplaceApiBase, writeMarketplaceSkillFiles } from "./marketplace-client.js";
|
|
6
6
|
import { normalizeTags, resolvePublishPackageName, validateSkillSelector, validateSkillSlug } from "./marketplace-identity.utils.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
7
|
+
import { DEFAULT_SKILLS_DIR } from "@nextclaw/core";
|
|
8
|
+
import { SkillManager } from "@nextclaw/kernel";
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync } from "node:fs";
|
|
10
|
+
import { basename, isAbsolute, join, relative, resolve } from "node:path";
|
|
11
|
+
//#region src/cli/commands/skills/marketplace.utils.ts
|
|
11
12
|
async function installMarketplaceSkill(options) {
|
|
12
13
|
const { slug, workdir: rawWorkdir, dir, force, apiBaseUrl } = options;
|
|
13
14
|
const selector = validateSkillSelector(slug.trim(), "slug");
|
|
@@ -52,7 +53,7 @@ async function installMarketplaceSkill(options) {
|
|
|
52
53
|
}
|
|
53
54
|
function resolveMarketplaceSkillDestinationDir(params) {
|
|
54
55
|
const { workdir, slug, dir } = params;
|
|
55
|
-
const dirName = dir?.trim() ||
|
|
56
|
+
const dirName = dir?.trim() || DEFAULT_SKILLS_DIR;
|
|
56
57
|
return isAbsolute(dirName) ? resolve(dirName, slug) : resolve(workdir, dirName, slug);
|
|
57
58
|
}
|
|
58
59
|
function resolveBuiltinMarketplaceInstallResult(params) {
|
|
@@ -86,16 +87,6 @@ function prepareMarketplaceSkillDestinationDir(params) {
|
|
|
86
87
|
mkdirSync(destinationDir, { recursive: true });
|
|
87
88
|
return null;
|
|
88
89
|
}
|
|
89
|
-
async function writeMarketplaceSkillFiles(params) {
|
|
90
|
-
const { destinationDir, files, apiBase, slug } = params;
|
|
91
|
-
for (const file of files) {
|
|
92
|
-
const targetPath = resolve(destinationDir, ...file.path.split("/"));
|
|
93
|
-
const rel = relative(destinationDir, targetPath);
|
|
94
|
-
if (rel.startsWith("..") || isAbsolute(rel)) throw new Error(`Invalid marketplace file path: ${file.path}`);
|
|
95
|
-
mkdirSync(dirname(targetPath), { recursive: true });
|
|
96
|
-
writeFileSync(targetPath, file.contentBase64 ? decodeMarketplaceFileContent(file.path, file.contentBase64) : await fetchMarketplaceSkillFileBlob(apiBase, slug, file));
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
90
|
function ensureInstalledMarketplaceSkill(destinationDir, slug) {
|
|
100
91
|
if (!existsSync(join(destinationDir, "SKILL.md"))) throw new Error(`Marketplace skill ${slug} does not include SKILL.md`);
|
|
101
92
|
}
|
|
@@ -143,7 +134,7 @@ async function publishMarketplaceSkill(options) {
|
|
|
143
134
|
const { skillDir: rawSkillDir, slug: explicitSlug, metaFile, packageName: explicitPackageName, scope: explicitScope, name: explicitName, summary: explicitSummary, summaryI18n: explicitSummaryI18n, description: explicitDescription, descriptionI18n: explicitDescriptionI18n, tags: explicitTags, sourceRepo: explicitSourceRepo, homepage: explicitHomepage, publishedAt: explicitPublishedAt, updatedAt: explicitUpdatedAt, apiBaseUrl, token: explicitToken, requireExisting } = options;
|
|
144
135
|
const skillDir = resolve(rawSkillDir);
|
|
145
136
|
if (!existsSync(skillDir)) throw new Error(`Skill directory not found: ${skillDir}`);
|
|
146
|
-
const files =
|
|
137
|
+
const files = collectMarketplaceSkillFiles(skillDir);
|
|
147
138
|
if (!files.some((file) => file.path === "SKILL.md")) throw new Error(`Skill directory must include SKILL.md: ${skillDir}`);
|
|
148
139
|
const parsedFrontmatter = parseSkillFrontmatter(readFileSync(join(skillDir, "SKILL.md"), "utf8"));
|
|
149
140
|
const metadata = readMarketplaceMetadataFile(skillDir, metaFile);
|
|
@@ -202,37 +193,10 @@ async function publishMarketplaceSkill(options) {
|
|
|
202
193
|
fileCount: payload.data.fileCount
|
|
203
194
|
};
|
|
204
195
|
}
|
|
205
|
-
function collectFiles(rootDir) {
|
|
206
|
-
const output = [];
|
|
207
|
-
const walk = (dir, prefix) => {
|
|
208
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
209
|
-
for (const entry of entries) {
|
|
210
|
-
const absolute = join(dir, entry.name);
|
|
211
|
-
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
212
|
-
if (entry.isDirectory()) {
|
|
213
|
-
walk(absolute, relativePath);
|
|
214
|
-
continue;
|
|
215
|
-
}
|
|
216
|
-
if (!entry.isFile()) continue;
|
|
217
|
-
const content = readFileSync(absolute);
|
|
218
|
-
output.push({
|
|
219
|
-
path: relativePath,
|
|
220
|
-
contentBase64: content.toString("base64")
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
};
|
|
224
|
-
walk(rootDir, "");
|
|
225
|
-
return output;
|
|
226
|
-
}
|
|
227
196
|
function resolveBuiltinSkillDir(workdir, skillName) {
|
|
228
|
-
const
|
|
229
|
-
if (!
|
|
230
|
-
return
|
|
231
|
-
}
|
|
232
|
-
function decodeMarketplaceFileContent(path, contentBase64) {
|
|
233
|
-
const normalized = contentBase64.replace(/\s+/g, "");
|
|
234
|
-
if (!normalized || normalized.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(normalized)) throw new Error(`Invalid marketplace file contentBase64 for path: ${path}`);
|
|
235
|
-
return Buffer.from(normalized, "base64");
|
|
197
|
+
const skillDir = new SkillManager({ workspace: workdir }).resolveBuiltinSkillDir(skillName);
|
|
198
|
+
if (!skillDir) throw new Error(`Built-in skill not found in local installation: ${skillName}`);
|
|
199
|
+
return skillDir;
|
|
236
200
|
}
|
|
237
201
|
//#endregion
|
|
238
202
|
export { installMarketplaceSkill, publishMarketplaceSkill };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { LocalizedTextMap } from "
|
|
2
|
-
import { SkillScope } from "@nextclaw/core";
|
|
1
|
+
import { LocalizedTextMap } from "@nextclaw/kernel";
|
|
3
2
|
|
|
4
3
|
//#region src/cli/commands/skills/skills-query.service.d.ts
|
|
5
4
|
type MarketplaceSkillSort = "relevance" | "updated";
|
|
@@ -56,31 +55,6 @@ type MarketplaceSkillRecommendationView = {
|
|
|
56
55
|
total: number;
|
|
57
56
|
items: MarketplaceSkillItemSummary[];
|
|
58
57
|
};
|
|
59
|
-
type InstalledSkillSummaryView = {
|
|
60
|
-
ref: string;
|
|
61
|
-
name: string;
|
|
62
|
-
path: string;
|
|
63
|
-
relativePath: string | null;
|
|
64
|
-
scope: SkillScope;
|
|
65
|
-
source: SkillScope;
|
|
66
|
-
summary: string | null;
|
|
67
|
-
summaryI18n: LocalizedTextMap | null;
|
|
68
|
-
description: string | null;
|
|
69
|
-
descriptionI18n: LocalizedTextMap | null;
|
|
70
|
-
author: string | null;
|
|
71
|
-
tags: string[];
|
|
72
|
-
always: boolean;
|
|
73
|
-
};
|
|
74
|
-
type InstalledSkillDetailView = InstalledSkillSummaryView & {
|
|
75
|
-
metadata: Record<string, string> | null;
|
|
76
|
-
raw: string;
|
|
77
|
-
bodyRaw: string;
|
|
78
|
-
};
|
|
79
|
-
type InstalledSkillsListView = {
|
|
80
|
-
workspace: string;
|
|
81
|
-
total: number;
|
|
82
|
-
skills: InstalledSkillSummaryView[];
|
|
83
|
-
};
|
|
84
58
|
type MarketplaceSkillsSearchView = MarketplaceSkillListView & {
|
|
85
59
|
apiBaseUrl: string;
|
|
86
60
|
};
|
|
@@ -98,11 +72,11 @@ declare class SkillsQueryService {
|
|
|
98
72
|
workdir: string;
|
|
99
73
|
query?: string;
|
|
100
74
|
scope?: string;
|
|
101
|
-
}) =>
|
|
75
|
+
}) => any;
|
|
102
76
|
getInstalledInfo: (params: {
|
|
103
77
|
workdir: string;
|
|
104
78
|
selector: string;
|
|
105
|
-
}) =>
|
|
79
|
+
}) => any;
|
|
106
80
|
searchMarketplaceSkills: (params: {
|
|
107
81
|
apiBaseUrl?: string;
|
|
108
82
|
query?: string;
|
|
@@ -120,17 +94,10 @@ declare class SkillsQueryService {
|
|
|
120
94
|
scene?: string;
|
|
121
95
|
limit?: string | number;
|
|
122
96
|
}) => Promise<MarketplaceSkillsRecommendationResultView>;
|
|
123
|
-
private buildInstalledSkillSummary;
|
|
124
|
-
private buildInstalledSkillDetail;
|
|
125
|
-
private matchesInstalledSkillQuery;
|
|
126
|
-
private stripFrontmatter;
|
|
127
|
-
private readAlwaysFlag;
|
|
128
|
-
private buildRelativePath;
|
|
129
97
|
private normalizeMarketplaceSummary;
|
|
130
98
|
private normalizeMarketplaceItem;
|
|
131
99
|
private normalizeMarketplaceContent;
|
|
132
100
|
private normalizeMarketplaceInstallSpec;
|
|
133
|
-
private normalizeInstalledScope;
|
|
134
101
|
private normalizeMarketplaceSort;
|
|
135
102
|
private normalizePositiveInteger;
|
|
136
103
|
private normalizeRequiredString;
|
|
@@ -138,4 +105,4 @@ declare class SkillsQueryService {
|
|
|
138
105
|
private fetchMarketplaceView;
|
|
139
106
|
}
|
|
140
107
|
//#endregion
|
|
141
|
-
export {
|
|
108
|
+
export { MarketplaceSkillInfoView, MarketplaceSkillsRecommendationResultView, MarketplaceSkillsSearchView, SkillsQueryService };
|