@actiondock/cli 2.0.10 → 2.0.11
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/index.js +1204 -299
- package/package.json +7 -7
- package/src/commands/export.ts +138 -12
- package/src/commands/index.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -24271,6 +24271,10 @@ app.run(process.argv.slice(2)).catch((err: unknown) => {
|
|
|
24271
24271
|
});
|
|
24272
24272
|
`;
|
|
24273
24273
|
}
|
|
24274
|
+
// ../core/src/catalog/action-index.ts
|
|
24275
|
+
import { existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
|
|
24276
|
+
import { join as join3 } from "path";
|
|
24277
|
+
|
|
24274
24278
|
// ../core/src/project/manifest.ts
|
|
24275
24279
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
24276
24280
|
import { join as join2, relative } from "path";
|
|
@@ -24926,11 +24930,176 @@ async function syncManifest(projectRoot, options = {}) {
|
|
|
24926
24930
|
unchanged
|
|
24927
24931
|
};
|
|
24928
24932
|
}
|
|
24933
|
+
|
|
24934
|
+
// ../core/src/catalog/action-index.ts
|
|
24935
|
+
class ActionIndex {
|
|
24936
|
+
actions = new Map;
|
|
24937
|
+
constructor(snapshot) {
|
|
24938
|
+
this.indexSnapshot(snapshot);
|
|
24939
|
+
}
|
|
24940
|
+
indexSnapshot(snapshot) {
|
|
24941
|
+
for (const [packageId, pkg] of snapshot.packages) {
|
|
24942
|
+
const manifest = loadManifest(pkg.projectRoot);
|
|
24943
|
+
if (manifest && manifest.actions) {
|
|
24944
|
+
for (const [actionId, item] of Object.entries(manifest.actions)) {
|
|
24945
|
+
const indexed = {
|
|
24946
|
+
packageId,
|
|
24947
|
+
actionId,
|
|
24948
|
+
contract: {
|
|
24949
|
+
id: actionId,
|
|
24950
|
+
description: item.description,
|
|
24951
|
+
inputSchema: item.inputSchema,
|
|
24952
|
+
outputSchema: item.outputSchema,
|
|
24953
|
+
uses: item.uses,
|
|
24954
|
+
tags: item.tags,
|
|
24955
|
+
annotations: item.annotations
|
|
24956
|
+
},
|
|
24957
|
+
entry: item.entry,
|
|
24958
|
+
projectRoot: pkg.projectRoot
|
|
24959
|
+
};
|
|
24960
|
+
this.add(indexed);
|
|
24961
|
+
}
|
|
24962
|
+
} else {
|
|
24963
|
+
const actionsDir = join3(pkg.projectRoot, pkg.config.actionsDir || "actions");
|
|
24964
|
+
if (existsSync3(actionsDir)) {
|
|
24965
|
+
try {
|
|
24966
|
+
const files = readdirSync2(actionsDir);
|
|
24967
|
+
for (const file of files) {
|
|
24968
|
+
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
|
24969
|
+
const actionId = file.replace(/\.(ts|js)$/, "");
|
|
24970
|
+
const indexed = {
|
|
24971
|
+
packageId,
|
|
24972
|
+
actionId,
|
|
24973
|
+
contract: {
|
|
24974
|
+
id: actionId
|
|
24975
|
+
},
|
|
24976
|
+
entry: join3(pkg.config.actionsDir || "actions", file),
|
|
24977
|
+
projectRoot: pkg.projectRoot
|
|
24978
|
+
};
|
|
24979
|
+
this.add(indexed);
|
|
24980
|
+
}
|
|
24981
|
+
}
|
|
24982
|
+
} catch {}
|
|
24983
|
+
}
|
|
24984
|
+
}
|
|
24985
|
+
}
|
|
24986
|
+
}
|
|
24987
|
+
add(action) {
|
|
24988
|
+
let list = this.actions.get(action.actionId);
|
|
24989
|
+
if (!list) {
|
|
24990
|
+
list = [];
|
|
24991
|
+
this.actions.set(action.actionId, list);
|
|
24992
|
+
}
|
|
24993
|
+
list.push(action);
|
|
24994
|
+
}
|
|
24995
|
+
list(packageId) {
|
|
24996
|
+
const all = [];
|
|
24997
|
+
for (const [_, list] of this.actions) {
|
|
24998
|
+
for (const action of list) {
|
|
24999
|
+
if (!packageId || action.packageId === packageId) {
|
|
25000
|
+
all.push(action);
|
|
25001
|
+
}
|
|
25002
|
+
}
|
|
25003
|
+
}
|
|
25004
|
+
return all;
|
|
25005
|
+
}
|
|
25006
|
+
find(actionId, packageId) {
|
|
25007
|
+
const matches = this.actions.get(actionId) || [];
|
|
25008
|
+
if (packageId) {
|
|
25009
|
+
return matches.filter((a) => a.packageId === packageId);
|
|
25010
|
+
}
|
|
25011
|
+
return matches;
|
|
25012
|
+
}
|
|
25013
|
+
}
|
|
25014
|
+
// ../core/src/catalog/action-resolver.ts
|
|
25015
|
+
class ActionResolver {
|
|
25016
|
+
snapshot;
|
|
25017
|
+
index;
|
|
25018
|
+
constructor(snapshot, index) {
|
|
25019
|
+
this.snapshot = snapshot;
|
|
25020
|
+
this.index = index || new ActionIndex(snapshot);
|
|
25021
|
+
}
|
|
25022
|
+
static parseRef(refStringOrObj) {
|
|
25023
|
+
if (typeof refStringOrObj === "object") {
|
|
25024
|
+
return refStringOrObj;
|
|
25025
|
+
}
|
|
25026
|
+
const str = refStringOrObj.trim();
|
|
25027
|
+
if (str.includes("/")) {
|
|
25028
|
+
const lastSlashIndex = str.lastIndexOf("/");
|
|
25029
|
+
const packageId = str.slice(0, lastSlashIndex);
|
|
25030
|
+
const actionId = str.slice(lastSlashIndex + 1);
|
|
25031
|
+
if (actionId.includes(":") || actionId.includes("/") || actionId.includes("..")) {
|
|
25032
|
+
throw new Error(`Invalid action identifier: '${actionId}'`);
|
|
25033
|
+
}
|
|
25034
|
+
return { packageId, actionId };
|
|
25035
|
+
}
|
|
25036
|
+
if (str.includes(":")) {
|
|
25037
|
+
const parts = str.split(":");
|
|
25038
|
+
throw new Error(`Legacy syntax '${str}' is deprecated. Please use '${parts.join("/")}' instead.`);
|
|
25039
|
+
}
|
|
25040
|
+
return { actionId: str };
|
|
25041
|
+
}
|
|
25042
|
+
resolve(refStringOrObj, options = {}) {
|
|
25043
|
+
const ref = ActionResolver.parseRef(refStringOrObj);
|
|
25044
|
+
if (ref.packageId) {
|
|
25045
|
+
const matches = this.index.find(ref.actionId, ref.packageId);
|
|
25046
|
+
if (matches.length === 0) {
|
|
25047
|
+
throw new Error(`ACTION_NOT_FOUND: Action '${ref.actionId}' not found in package '${ref.packageId}'`);
|
|
25048
|
+
}
|
|
25049
|
+
const matched = matches[0];
|
|
25050
|
+
const pkg = this.snapshot.packages.get(matched.packageId);
|
|
25051
|
+
return {
|
|
25052
|
+
resolved: {
|
|
25053
|
+
packageId: matched.packageId,
|
|
25054
|
+
packageInstanceId: pkg?.packageInstanceId || matched.packageId,
|
|
25055
|
+
actionId: matched.actionId,
|
|
25056
|
+
generationId: this.snapshot.generationId
|
|
25057
|
+
},
|
|
25058
|
+
action: matched
|
|
25059
|
+
};
|
|
25060
|
+
}
|
|
25061
|
+
if (options.currentPackageId) {
|
|
25062
|
+
const inCurrent = this.index.find(ref.actionId, options.currentPackageId);
|
|
25063
|
+
if (inCurrent.length > 0) {
|
|
25064
|
+
const matched = inCurrent[0];
|
|
25065
|
+
const pkg = this.snapshot.packages.get(matched.packageId);
|
|
25066
|
+
return {
|
|
25067
|
+
resolved: {
|
|
25068
|
+
packageId: matched.packageId,
|
|
25069
|
+
packageInstanceId: pkg?.packageInstanceId || matched.packageId,
|
|
25070
|
+
actionId: matched.actionId,
|
|
25071
|
+
generationId: this.snapshot.generationId
|
|
25072
|
+
},
|
|
25073
|
+
action: matched
|
|
25074
|
+
};
|
|
25075
|
+
}
|
|
25076
|
+
}
|
|
25077
|
+
const allMatches = this.index.find(ref.actionId);
|
|
25078
|
+
if (allMatches.length === 0) {
|
|
25079
|
+
throw new Error(`ACTION_NOT_FOUND: Action '${ref.actionId}' not found in any linked package`);
|
|
25080
|
+
}
|
|
25081
|
+
if (allMatches.length > 1) {
|
|
25082
|
+
const candidates = allMatches.map((m) => `${m.packageId}/${m.actionId}`).join(", ");
|
|
25083
|
+
throw new Error(`AMBIGUOUS_ACTION_REF: Action '${ref.actionId}' is provided by multiple packages: ${candidates}. Please specify the package name.`);
|
|
25084
|
+
}
|
|
25085
|
+
const matched = allMatches[0];
|
|
25086
|
+
const pkg = this.snapshot.packages.get(matched.packageId);
|
|
25087
|
+
return {
|
|
25088
|
+
resolved: {
|
|
25089
|
+
packageId: matched.packageId,
|
|
25090
|
+
packageInstanceId: pkg?.packageInstanceId || matched.packageId,
|
|
25091
|
+
actionId: matched.actionId,
|
|
25092
|
+
generationId: this.snapshot.generationId
|
|
25093
|
+
},
|
|
25094
|
+
action: matched
|
|
25095
|
+
};
|
|
25096
|
+
}
|
|
25097
|
+
}
|
|
24929
25098
|
// ../core/src/utils/index.ts
|
|
24930
25099
|
import { homedir as homedir2 } from "os";
|
|
24931
25100
|
// ../sdk/src/cli.ts
|
|
24932
|
-
import { existsSync as
|
|
24933
|
-
import { delimiter, join as
|
|
25101
|
+
import { existsSync as existsSync4 } from "fs";
|
|
25102
|
+
import { delimiter, join as join4 } from "path";
|
|
24934
25103
|
function findExecutable(command) {
|
|
24935
25104
|
if (typeof globalThis.Bun !== "undefined" && typeof globalThis.Bun.which === "function") {
|
|
24936
25105
|
try {
|
|
@@ -24941,7 +25110,7 @@ function findExecutable(command) {
|
|
|
24941
25110
|
}
|
|
24942
25111
|
const hasPathSep = command.includes("/") || command.includes("\\");
|
|
24943
25112
|
if (hasPathSep) {
|
|
24944
|
-
return
|
|
25113
|
+
return existsSync4(command) ? command : null;
|
|
24945
25114
|
}
|
|
24946
25115
|
const pathEnv = process.env.PATH || "";
|
|
24947
25116
|
const dirs = pathEnv.split(delimiter);
|
|
@@ -24951,8 +25120,8 @@ function findExecutable(command) {
|
|
|
24951
25120
|
if (!dir)
|
|
24952
25121
|
continue;
|
|
24953
25122
|
for (const ext of pathext) {
|
|
24954
|
-
const candidate =
|
|
24955
|
-
if (
|
|
25123
|
+
const candidate = join4(dir, isWindows && !command.includes(".") ? command + ext : command);
|
|
25124
|
+
if (existsSync4(candidate)) {
|
|
24956
25125
|
return candidate;
|
|
24957
25126
|
}
|
|
24958
25127
|
}
|
|
@@ -25002,8 +25171,8 @@ function getActionDockHome(customHome) {
|
|
|
25002
25171
|
return customHome || process.env.ACTIONDOCK_HOME || homedir2();
|
|
25003
25172
|
}
|
|
25004
25173
|
// ../core/src/registry/registry.ts
|
|
25005
|
-
import { existsSync as
|
|
25006
|
-
import { basename as basename2, dirname as dirname2, join as
|
|
25174
|
+
import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
25175
|
+
import { basename as basename2, dirname as dirname2, join as join5, resolve as resolve3 } from "path";
|
|
25007
25176
|
var IGNORED_SCAN_DIRS = new Set([
|
|
25008
25177
|
"node_modules",
|
|
25009
25178
|
".git",
|
|
@@ -25022,7 +25191,7 @@ function discoverProjects(dir, maxDepth = 3) {
|
|
|
25022
25191
|
if (currentDepth > maxDepth)
|
|
25023
25192
|
return;
|
|
25024
25193
|
try {
|
|
25025
|
-
const entries =
|
|
25194
|
+
const entries = readdirSync3(currentDir, { withFileTypes: true });
|
|
25026
25195
|
const hasActiondock = entries.some((e) => e.isFile() && e.name === "actiondock.json");
|
|
25027
25196
|
if (hasActiondock && currentDir !== resolvedDir) {
|
|
25028
25197
|
results.push(currentDir);
|
|
@@ -25030,7 +25199,7 @@ function discoverProjects(dir, maxDepth = 3) {
|
|
|
25030
25199
|
}
|
|
25031
25200
|
for (const entry of entries) {
|
|
25032
25201
|
if (entry.isDirectory() && !IGNORED_SCAN_DIRS.has(entry.name)) {
|
|
25033
|
-
walk(
|
|
25202
|
+
walk(join5(currentDir, entry.name), currentDepth + 1);
|
|
25034
25203
|
}
|
|
25035
25204
|
}
|
|
25036
25205
|
} catch {}
|
|
@@ -25040,11 +25209,11 @@ function discoverProjects(dir, maxDepth = 3) {
|
|
|
25040
25209
|
}
|
|
25041
25210
|
function getRegistryFilePath(customHome) {
|
|
25042
25211
|
const baseDir = getActionDockHome(customHome);
|
|
25043
|
-
return
|
|
25212
|
+
return join5(baseDir, ".actiondock", "registry.json");
|
|
25044
25213
|
}
|
|
25045
25214
|
function loadRegistry(customHome) {
|
|
25046
25215
|
const filePath = getRegistryFilePath(customHome);
|
|
25047
|
-
if (!
|
|
25216
|
+
if (!existsSync5(filePath)) {
|
|
25048
25217
|
return { version: "2.0.0", packages: {}, workspaces: {} };
|
|
25049
25218
|
}
|
|
25050
25219
|
try {
|
|
@@ -25070,7 +25239,7 @@ function saveRegistry(data, customHome) {
|
|
|
25070
25239
|
}
|
|
25071
25240
|
function linkPackage(targetPath = process.cwd(), customHome, options) {
|
|
25072
25241
|
const absPath = resolve3(targetPath);
|
|
25073
|
-
const directHasConfig =
|
|
25242
|
+
const directHasConfig = existsSync5(join5(absPath, "actiondock.json"));
|
|
25074
25243
|
if (directHasConfig && !options?.recursive) {
|
|
25075
25244
|
const config = loadProjectConfig(absPath);
|
|
25076
25245
|
const registry = loadRegistry(customHome);
|
|
@@ -25231,7 +25400,7 @@ function listLinkedPackages(customHome) {
|
|
|
25231
25400
|
const result = { ...registry.packages };
|
|
25232
25401
|
if (registry.workspaces) {
|
|
25233
25402
|
for (const ws of Object.values(registry.workspaces)) {
|
|
25234
|
-
if (!
|
|
25403
|
+
if (!existsSync5(ws.path))
|
|
25235
25404
|
continue;
|
|
25236
25405
|
const discovered = discoverProjects(ws.path);
|
|
25237
25406
|
for (const root of discovered) {
|
|
@@ -25265,6 +25434,110 @@ async function projectHasAction(projectRoot, actionsDir, actionId) {
|
|
|
25265
25434
|
return false;
|
|
25266
25435
|
}
|
|
25267
25436
|
}
|
|
25437
|
+
function projectHasActionSync(projectRoot, actionsDir, actionId) {
|
|
25438
|
+
const manifest = loadManifest(projectRoot);
|
|
25439
|
+
if (manifest?.actions && actionId in manifest.actions) {
|
|
25440
|
+
return true;
|
|
25441
|
+
}
|
|
25442
|
+
const dir = join5(projectRoot, actionsDir || "actions");
|
|
25443
|
+
if (!existsSync5(dir)) {
|
|
25444
|
+
return false;
|
|
25445
|
+
}
|
|
25446
|
+
if (actionId.includes("..") || actionId.startsWith("/") || actionId.startsWith("\\")) {
|
|
25447
|
+
return false;
|
|
25448
|
+
}
|
|
25449
|
+
if (existsSync5(join5(dir, `${actionId}.ts`)) || existsSync5(join5(dir, `${actionId}.js`))) {
|
|
25450
|
+
return true;
|
|
25451
|
+
}
|
|
25452
|
+
const relFile = actionId.replace(/\./g, "/");
|
|
25453
|
+
if (existsSync5(join5(dir, `${relFile}.ts`)) || existsSync5(join5(dir, `${relFile}.js`))) {
|
|
25454
|
+
return true;
|
|
25455
|
+
}
|
|
25456
|
+
return false;
|
|
25457
|
+
}
|
|
25458
|
+
function resolveActionProjectSync(actionIdentifier, cwd = process.cwd(), customHome) {
|
|
25459
|
+
const currentRoot = findProjectRoot(cwd);
|
|
25460
|
+
if (currentRoot) {
|
|
25461
|
+
try {
|
|
25462
|
+
const config = loadProjectConfig(currentRoot);
|
|
25463
|
+
if (projectHasActionSync(currentRoot, config.actionsDir, actionIdentifier)) {
|
|
25464
|
+
return {
|
|
25465
|
+
projectRoot: currentRoot,
|
|
25466
|
+
packageId: config.id,
|
|
25467
|
+
actionId: actionIdentifier
|
|
25468
|
+
};
|
|
25469
|
+
}
|
|
25470
|
+
} catch {}
|
|
25471
|
+
}
|
|
25472
|
+
let targetPackage;
|
|
25473
|
+
let pureActionId = actionIdentifier;
|
|
25474
|
+
if (actionIdentifier.includes("/")) {
|
|
25475
|
+
const slashIdx = actionIdentifier.lastIndexOf("/");
|
|
25476
|
+
targetPackage = actionIdentifier.slice(0, slashIdx);
|
|
25477
|
+
pureActionId = actionIdentifier.slice(slashIdx + 1);
|
|
25478
|
+
} else if (actionIdentifier.includes(":")) {
|
|
25479
|
+
const colonIdx = actionIdentifier.lastIndexOf(":");
|
|
25480
|
+
targetPackage = actionIdentifier.slice(0, colonIdx);
|
|
25481
|
+
pureActionId = actionIdentifier.slice(colonIdx + 1);
|
|
25482
|
+
}
|
|
25483
|
+
const linkedList = listLinkedPackages(customHome);
|
|
25484
|
+
if (targetPackage) {
|
|
25485
|
+
let targetRoot;
|
|
25486
|
+
let targetPkgId = targetPackage;
|
|
25487
|
+
const pkg = linkedList.find((p) => p.id === targetPackage || getPackageSlug(p.id) === targetPackage);
|
|
25488
|
+
if (pkg && existsSync5(pkg.path)) {
|
|
25489
|
+
targetRoot = pkg.path;
|
|
25490
|
+
targetPkgId = pkg.id;
|
|
25491
|
+
} else if (currentRoot) {
|
|
25492
|
+
try {
|
|
25493
|
+
const config = loadProjectConfig(currentRoot);
|
|
25494
|
+
if (config.id === targetPackage || getPackageSlug(config.id) === targetPackage) {
|
|
25495
|
+
targetRoot = currentRoot;
|
|
25496
|
+
targetPkgId = config.id;
|
|
25497
|
+
}
|
|
25498
|
+
} catch {}
|
|
25499
|
+
}
|
|
25500
|
+
if (!targetRoot || !existsSync5(targetRoot)) {
|
|
25501
|
+
throw new Error(`Linked package '${targetPackage}' not found or path no longer exists (${pkg?.path || "unregistered"}). Run 'ad link' in the package directory.`);
|
|
25502
|
+
}
|
|
25503
|
+
const config = loadProjectConfig(targetRoot);
|
|
25504
|
+
if (!projectHasActionSync(targetRoot, config.actionsDir, pureActionId)) {
|
|
25505
|
+
throw new Error(`Action '${pureActionId}' not found in package '${targetPkgId}' (${targetRoot})`);
|
|
25506
|
+
}
|
|
25507
|
+
return {
|
|
25508
|
+
projectRoot: targetRoot,
|
|
25509
|
+
packageId: targetPkgId,
|
|
25510
|
+
actionId: pureActionId
|
|
25511
|
+
};
|
|
25512
|
+
}
|
|
25513
|
+
const matches = [];
|
|
25514
|
+
for (const pkg of linkedList) {
|
|
25515
|
+
if (!existsSync5(pkg.path))
|
|
25516
|
+
continue;
|
|
25517
|
+
try {
|
|
25518
|
+
const config = loadProjectConfig(pkg.path);
|
|
25519
|
+
if (projectHasActionSync(pkg.path, config.actionsDir, actionIdentifier)) {
|
|
25520
|
+
matches.push({ entry: pkg, actionId: actionIdentifier });
|
|
25521
|
+
}
|
|
25522
|
+
} catch {}
|
|
25523
|
+
}
|
|
25524
|
+
if (matches.length === 1) {
|
|
25525
|
+
return {
|
|
25526
|
+
projectRoot: matches[0].entry.path,
|
|
25527
|
+
packageId: matches[0].entry.id,
|
|
25528
|
+
actionId: matches[0].actionId
|
|
25529
|
+
};
|
|
25530
|
+
}
|
|
25531
|
+
if (matches.length > 1) {
|
|
25532
|
+
const pkgList = matches.map((m) => `'${m.entry.id}'`).join(", ");
|
|
25533
|
+
throw new Error(`Action '${actionIdentifier}' is provided by multiple linked packages: ${pkgList}. Please specify using '<package-id>/${actionIdentifier}'.`);
|
|
25534
|
+
}
|
|
25535
|
+
if (currentRoot) {
|
|
25536
|
+
throw new Error(`Action '${actionIdentifier}' not found in current project or any linked packages`);
|
|
25537
|
+
} else {
|
|
25538
|
+
throw new Error(`Action '${actionIdentifier}' not found. You are not in an ActionDock project, and no linked package provides '${actionIdentifier}'. Use 'ad link' to register your package.`);
|
|
25539
|
+
}
|
|
25540
|
+
}
|
|
25268
25541
|
async function resolveActionProject(actionIdentifier, cwd = process.cwd(), customHome) {
|
|
25269
25542
|
const currentRoot = findProjectRoot(cwd);
|
|
25270
25543
|
if (currentRoot) {
|
|
@@ -25282,11 +25555,11 @@ async function resolveActionProject(actionIdentifier, cwd = process.cwd(), custo
|
|
|
25282
25555
|
let targetPackage;
|
|
25283
25556
|
let pureActionId = actionIdentifier;
|
|
25284
25557
|
if (actionIdentifier.includes("/")) {
|
|
25285
|
-
const slashIdx = actionIdentifier.
|
|
25558
|
+
const slashIdx = actionIdentifier.lastIndexOf("/");
|
|
25286
25559
|
targetPackage = actionIdentifier.slice(0, slashIdx);
|
|
25287
25560
|
pureActionId = actionIdentifier.slice(slashIdx + 1);
|
|
25288
25561
|
} else if (actionIdentifier.includes(":")) {
|
|
25289
|
-
const colonIdx = actionIdentifier.
|
|
25562
|
+
const colonIdx = actionIdentifier.lastIndexOf(":");
|
|
25290
25563
|
targetPackage = actionIdentifier.slice(0, colonIdx);
|
|
25291
25564
|
pureActionId = actionIdentifier.slice(colonIdx + 1);
|
|
25292
25565
|
}
|
|
@@ -25295,7 +25568,7 @@ async function resolveActionProject(actionIdentifier, cwd = process.cwd(), custo
|
|
|
25295
25568
|
let targetRoot;
|
|
25296
25569
|
let targetPkgId = targetPackage;
|
|
25297
25570
|
const pkg = linkedList.find((p) => p.id === targetPackage || getPackageSlug(p.id) === targetPackage);
|
|
25298
|
-
if (pkg &&
|
|
25571
|
+
if (pkg && existsSync5(pkg.path)) {
|
|
25299
25572
|
targetRoot = pkg.path;
|
|
25300
25573
|
targetPkgId = pkg.id;
|
|
25301
25574
|
} else if (currentRoot) {
|
|
@@ -25307,7 +25580,7 @@ async function resolveActionProject(actionIdentifier, cwd = process.cwd(), custo
|
|
|
25307
25580
|
}
|
|
25308
25581
|
} catch {}
|
|
25309
25582
|
}
|
|
25310
|
-
if (!targetRoot || !
|
|
25583
|
+
if (!targetRoot || !existsSync5(targetRoot)) {
|
|
25311
25584
|
throw new Error(`Linked package '${targetPackage}' not found or path no longer exists (${pkg?.path || "unregistered"}). Run 'ad link' in the package directory.`);
|
|
25312
25585
|
}
|
|
25313
25586
|
const config = loadProjectConfig(targetRoot);
|
|
@@ -25322,7 +25595,7 @@ async function resolveActionProject(actionIdentifier, cwd = process.cwd(), custo
|
|
|
25322
25595
|
}
|
|
25323
25596
|
const matches = [];
|
|
25324
25597
|
for (const pkg of linkedList) {
|
|
25325
|
-
if (!
|
|
25598
|
+
if (!existsSync5(pkg.path))
|
|
25326
25599
|
continue;
|
|
25327
25600
|
try {
|
|
25328
25601
|
const config = loadProjectConfig(pkg.path);
|
|
@@ -25354,11 +25627,11 @@ function resolvePackageRoot(packageIdOrPath, cwd, customHome) {
|
|
|
25354
25627
|
}
|
|
25355
25628
|
const baseDir = cwd || process.cwd();
|
|
25356
25629
|
const resolvedPath = resolve3(baseDir, packageIdOrPath);
|
|
25357
|
-
if (
|
|
25630
|
+
if (existsSync5(resolvedPath)) {
|
|
25358
25631
|
try {
|
|
25359
25632
|
const stat = statSync2(resolvedPath);
|
|
25360
25633
|
const targetDir = stat.isDirectory() ? resolvedPath : dirname2(resolvedPath);
|
|
25361
|
-
if (
|
|
25634
|
+
if (existsSync5(join5(targetDir, "actiondock.json"))) {
|
|
25362
25635
|
return targetDir;
|
|
25363
25636
|
}
|
|
25364
25637
|
const parentRoot = findProjectRoot(targetDir);
|
|
@@ -25419,7 +25692,7 @@ function resolvePlaybookProject(playbookIdentifier, cwd = process.cwd(), customH
|
|
|
25419
25692
|
let targetRoot;
|
|
25420
25693
|
let targetPkgId = targetPackage;
|
|
25421
25694
|
const pkg = linkedList.find((p) => p.id === targetPackage || getPackageSlug(p.id) === targetPackage);
|
|
25422
|
-
if (pkg &&
|
|
25695
|
+
if (pkg && existsSync5(pkg.path)) {
|
|
25423
25696
|
targetRoot = pkg.path;
|
|
25424
25697
|
targetPkgId = pkg.id;
|
|
25425
25698
|
} else if (currentRoot) {
|
|
@@ -25431,7 +25704,7 @@ function resolvePlaybookProject(playbookIdentifier, cwd = process.cwd(), customH
|
|
|
25431
25704
|
}
|
|
25432
25705
|
} catch {}
|
|
25433
25706
|
}
|
|
25434
|
-
if (!targetRoot || !
|
|
25707
|
+
if (!targetRoot || !existsSync5(targetRoot)) {
|
|
25435
25708
|
throw new Error(`Linked package '${targetPackage}' not found or path no longer exists (${pkg?.path || "unregistered"}). Run 'ad link' in the package directory.`);
|
|
25436
25709
|
}
|
|
25437
25710
|
const config = loadProjectConfig(targetRoot);
|
|
@@ -25449,7 +25722,7 @@ function resolvePlaybookProject(playbookIdentifier, cwd = process.cwd(), customH
|
|
|
25449
25722
|
}
|
|
25450
25723
|
const matches = [];
|
|
25451
25724
|
for (const pkg of linkedList) {
|
|
25452
|
-
if (!
|
|
25725
|
+
if (!existsSync5(pkg.path))
|
|
25453
25726
|
continue;
|
|
25454
25727
|
try {
|
|
25455
25728
|
const config = loadProjectConfig(pkg.path);
|
|
@@ -25489,7 +25762,7 @@ function getRegistryStatus(customHome) {
|
|
|
25489
25762
|
const seenPackageIds = new Set;
|
|
25490
25763
|
if (registry.workspaces) {
|
|
25491
25764
|
for (const [wsPath, wsEntry] of Object.entries(registry.workspaces)) {
|
|
25492
|
-
const isWsActive =
|
|
25765
|
+
const isWsActive = existsSync5(wsPath);
|
|
25493
25766
|
if (!isWsActive) {
|
|
25494
25767
|
staleCount++;
|
|
25495
25768
|
workspaces.push({
|
|
@@ -25534,7 +25807,7 @@ function getRegistryStatus(customHome) {
|
|
|
25534
25807
|
if (seenPackageIds.has(pkgId)) {
|
|
25535
25808
|
continue;
|
|
25536
25809
|
}
|
|
25537
|
-
const isPkgActive =
|
|
25810
|
+
const isPkgActive = existsSync5(pkgEntry.path);
|
|
25538
25811
|
if (!isPkgActive) {
|
|
25539
25812
|
staleCount++;
|
|
25540
25813
|
packages.push({
|
|
@@ -25570,14 +25843,14 @@ function pruneRegistry(customHome) {
|
|
|
25570
25843
|
const prunedPackages = [];
|
|
25571
25844
|
if (registry.workspaces) {
|
|
25572
25845
|
for (const [wsPath, wsEntry] of Object.entries(registry.workspaces)) {
|
|
25573
|
-
if (!
|
|
25846
|
+
if (!existsSync5(wsPath)) {
|
|
25574
25847
|
prunedWorkspaces.push(wsEntry);
|
|
25575
25848
|
delete registry.workspaces[wsPath];
|
|
25576
25849
|
}
|
|
25577
25850
|
}
|
|
25578
25851
|
}
|
|
25579
25852
|
for (const [pkgId, pkgEntry] of Object.entries(registry.packages)) {
|
|
25580
|
-
if (!
|
|
25853
|
+
if (!existsSync5(pkgEntry.path)) {
|
|
25581
25854
|
prunedPackages.push(pkgEntry);
|
|
25582
25855
|
delete registry.packages[pkgId];
|
|
25583
25856
|
}
|
|
@@ -25591,14 +25864,14 @@ function pruneRegistry(customHome) {
|
|
|
25591
25864
|
};
|
|
25592
25865
|
}
|
|
25593
25866
|
// ../core/src/doctor/doctor.ts
|
|
25594
|
-
import { existsSync as
|
|
25595
|
-
import { join as
|
|
25867
|
+
import { existsSync as existsSync7, statSync as statSync3 } from "fs";
|
|
25868
|
+
import { join as join7, relative as relative2 } from "path";
|
|
25596
25869
|
|
|
25597
25870
|
// ../core/src/storage/index.ts
|
|
25598
|
-
import { join as
|
|
25871
|
+
import { join as join6 } from "path";
|
|
25599
25872
|
|
|
25600
25873
|
// ../core/src/storage/sqlite.ts
|
|
25601
|
-
import { chmodSync, existsSync as
|
|
25874
|
+
import { chmodSync, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
|
|
25602
25875
|
import { dirname as dirname3 } from "path";
|
|
25603
25876
|
|
|
25604
25877
|
// ../core/src/runtime/clock.ts
|
|
@@ -25742,7 +26015,7 @@ class SqliteRuntimeStorage {
|
|
|
25742
26015
|
const dbPath = options.dbPath || ":memory:";
|
|
25743
26016
|
if (dbPath !== ":memory:") {
|
|
25744
26017
|
const dir = dirname3(dbPath);
|
|
25745
|
-
if (!
|
|
26018
|
+
if (!existsSync6(dir)) {
|
|
25746
26019
|
try {
|
|
25747
26020
|
mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
25748
26021
|
chmodSync(dir, 448);
|
|
@@ -25750,7 +26023,7 @@ class SqliteRuntimeStorage {
|
|
|
25750
26023
|
}
|
|
25751
26024
|
}
|
|
25752
26025
|
this.driver = options.driver ?? createDefaultSqliteDriver(dbPath);
|
|
25753
|
-
if (dbPath !== ":memory:" &&
|
|
26026
|
+
if (dbPath !== ":memory:" && existsSync6(dbPath)) {
|
|
25754
26027
|
try {
|
|
25755
26028
|
chmodSync(dbPath, 384);
|
|
25756
26029
|
} catch {}
|
|
@@ -26254,12 +26527,12 @@ function resolveDatabasePath(packageId, options = {}) {
|
|
|
26254
26527
|
return ":memory:";
|
|
26255
26528
|
}
|
|
26256
26529
|
if (options.dataDir) {
|
|
26257
|
-
return
|
|
26530
|
+
return join6(options.dataDir, packageId, "runtime.db");
|
|
26258
26531
|
}
|
|
26259
26532
|
if (options.projectRoot) {
|
|
26260
|
-
return
|
|
26533
|
+
return join6(options.projectRoot, ".actiondock", "runtime.db");
|
|
26261
26534
|
}
|
|
26262
|
-
return
|
|
26535
|
+
return join6(getActionDockHome(), ".actiondock", "data", packageId, "runtime.db");
|
|
26263
26536
|
}
|
|
26264
26537
|
function createStorage(packageId, options = {}) {
|
|
26265
26538
|
const dbPath = resolveDatabasePath(packageId, options);
|
|
@@ -26275,7 +26548,7 @@ function createGlobalStorage(customHomeOrOptions, dataDirArg) {
|
|
|
26275
26548
|
customHome = customHomeOrOptions;
|
|
26276
26549
|
dataDir = dataDirArg;
|
|
26277
26550
|
}
|
|
26278
|
-
const dbPath = dataDir ?
|
|
26551
|
+
const dbPath = dataDir ? join6(dataDir, "global.db") : join6(getActionDockHome(customHome), ".actiondock", "global.db");
|
|
26279
26552
|
return new SqliteRuntimeStorage({ dbPath, packageId: "__global__" });
|
|
26280
26553
|
}
|
|
26281
26554
|
|
|
@@ -26415,7 +26688,7 @@ async function runDoctorChecks(options) {
|
|
|
26415
26688
|
status: "ok",
|
|
26416
26689
|
message: `Valid (${config.id} v${config.version})`
|
|
26417
26690
|
});
|
|
26418
|
-
const hasSdkInNodeModules =
|
|
26691
|
+
const hasSdkInNodeModules = existsSync7(join7(projectRoot, "node_modules", "@actiondock", "sdk")) || existsSync7(join7(projectRoot, "node_modules", "@actiondock", "sdk", "package.json"));
|
|
26419
26692
|
if (hasSdkInNodeModules) {
|
|
26420
26693
|
checks.push({
|
|
26421
26694
|
id: "project.sdk",
|
|
@@ -26444,7 +26717,7 @@ async function runDoctorChecks(options) {
|
|
|
26444
26717
|
category: "project",
|
|
26445
26718
|
name: "Project Database",
|
|
26446
26719
|
status: "ok",
|
|
26447
|
-
message: `Database writable at ${
|
|
26720
|
+
message: `Database writable at ${join7(projectRoot, ".actiondock", "runtime.db")}`
|
|
26448
26721
|
});
|
|
26449
26722
|
} catch (err) {
|
|
26450
26723
|
checks.push({
|
|
@@ -26453,7 +26726,7 @@ async function runDoctorChecks(options) {
|
|
|
26453
26726
|
name: "Project Database",
|
|
26454
26727
|
status: "error",
|
|
26455
26728
|
message: `Failed to write project runtime database: ${err.message}`,
|
|
26456
|
-
fix: `Check write permissions for '${
|
|
26729
|
+
fix: `Check write permissions for '${join7(projectRoot, ".actiondock")}'`
|
|
26457
26730
|
});
|
|
26458
26731
|
}
|
|
26459
26732
|
try {
|
|
@@ -26493,10 +26766,10 @@ async function runDoctorChecks(options) {
|
|
|
26493
26766
|
});
|
|
26494
26767
|
}
|
|
26495
26768
|
try {
|
|
26496
|
-
const manifestPath =
|
|
26769
|
+
const manifestPath = join7(projectRoot, MANIFEST_FILE_NAME);
|
|
26497
26770
|
const manifest = loadManifest(projectRoot);
|
|
26498
26771
|
const actionFiles = discoverActionFiles(projectRoot, config.actionsDir || "actions");
|
|
26499
|
-
if (!
|
|
26772
|
+
if (!existsSync7(manifestPath)) {
|
|
26500
26773
|
if (actionFiles.length > 0) {
|
|
26501
26774
|
checks.push({
|
|
26502
26775
|
id: "project.manifest",
|
|
@@ -26508,7 +26781,7 @@ async function runDoctorChecks(options) {
|
|
|
26508
26781
|
});
|
|
26509
26782
|
}
|
|
26510
26783
|
} else if (manifest && manifest.actions) {
|
|
26511
|
-
const missingFiles = Object.entries(manifest.actions).filter(([_, item]) => !
|
|
26784
|
+
const missingFiles = Object.entries(manifest.actions).filter(([_, item]) => !existsSync7(join7(projectRoot, item.entry))).map(([id, item]) => `${id} (${item.entry})`);
|
|
26512
26785
|
const manifestEntries = new Set(Object.values(manifest.actions).map((a) => a.entry.replace(/\\/g, "/")));
|
|
26513
26786
|
const untracked = actionFiles.map((f) => relative2(projectRoot, f).replace(/\\/g, "/")).filter((rel) => !manifestEntries.has(rel));
|
|
26514
26787
|
if (missingFiles.length > 0) {
|
|
@@ -26739,6 +27012,7 @@ class InMemoryEventSink {
|
|
|
26739
27012
|
var defaultEventSink = new InMemoryEventSink;
|
|
26740
27013
|
|
|
26741
27014
|
// ../core/src/runtime/runner.ts
|
|
27015
|
+
import { existsSync as existsSync8 } from "fs";
|
|
26742
27016
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
26743
27017
|
|
|
26744
27018
|
// ../core/src/schema/validator.ts
|
|
@@ -27241,12 +27515,14 @@ class ActionRunner {
|
|
|
27241
27515
|
projectConfig;
|
|
27242
27516
|
configOverrides;
|
|
27243
27517
|
actions;
|
|
27518
|
+
actionResolver;
|
|
27244
27519
|
constructor(options) {
|
|
27245
27520
|
this.packageId = options.packageId;
|
|
27246
27521
|
this.storage = options.storage;
|
|
27247
27522
|
this.projectConfig = options.projectConfig;
|
|
27248
27523
|
this.configOverrides = options.configOverrides || {};
|
|
27249
27524
|
this.actions = options.actions || new Map;
|
|
27525
|
+
this.actionResolver = options.actionResolver;
|
|
27250
27526
|
}
|
|
27251
27527
|
registerAction(action) {
|
|
27252
27528
|
this.actions.set(action.id, action);
|
|
@@ -27254,6 +27530,60 @@ class ActionRunner {
|
|
|
27254
27530
|
getAction(id) {
|
|
27255
27531
|
return this.actions.get(id);
|
|
27256
27532
|
}
|
|
27533
|
+
async resolveAction(actionOrRef) {
|
|
27534
|
+
if (typeof actionOrRef === "object" && "run" in actionOrRef && typeof actionOrRef.run === "function") {
|
|
27535
|
+
return actionOrRef;
|
|
27536
|
+
}
|
|
27537
|
+
const ref = actionOrRef;
|
|
27538
|
+
const parsed = ActionResolver.parseRef(ref);
|
|
27539
|
+
const targetActionId = parsed.actionId;
|
|
27540
|
+
const targetPackageId = parsed.packageId;
|
|
27541
|
+
if (targetPackageId && targetPackageId !== this.packageId) {
|
|
27542
|
+
if (this.actions.has(`${targetPackageId}/${targetActionId}`)) {
|
|
27543
|
+
return this.actions.get(`${targetPackageId}/${targetActionId}`);
|
|
27544
|
+
}
|
|
27545
|
+
} else {
|
|
27546
|
+
if (this.actions.has(targetActionId)) {
|
|
27547
|
+
return this.actions.get(targetActionId);
|
|
27548
|
+
}
|
|
27549
|
+
if (this.packageId && this.actions.has(`${this.packageId}/${targetActionId}`)) {
|
|
27550
|
+
return this.actions.get(`${this.packageId}/${targetActionId}`);
|
|
27551
|
+
}
|
|
27552
|
+
}
|
|
27553
|
+
if (this.actionResolver) {
|
|
27554
|
+
const customResolved = await this.actionResolver(ref, this.packageId);
|
|
27555
|
+
if (customResolved) {
|
|
27556
|
+
if (targetPackageId && targetPackageId !== this.packageId) {
|
|
27557
|
+
this.actions.set(`${targetPackageId}/${targetActionId}`, customResolved);
|
|
27558
|
+
} else {
|
|
27559
|
+
this.actions.set(targetActionId, customResolved);
|
|
27560
|
+
if (this.packageId) {
|
|
27561
|
+
this.actions.set(`${this.packageId}/${targetActionId}`, customResolved);
|
|
27562
|
+
}
|
|
27563
|
+
}
|
|
27564
|
+
return customResolved;
|
|
27565
|
+
}
|
|
27566
|
+
}
|
|
27567
|
+
try {
|
|
27568
|
+
const identifier = targetPackageId ? `${targetPackageId}/${targetActionId}` : targetActionId;
|
|
27569
|
+
const resolved = await resolveActionProject(identifier);
|
|
27570
|
+
if (resolved && existsSync8(resolved.projectRoot)) {
|
|
27571
|
+
const config = loadProjectConfig(resolved.projectRoot);
|
|
27572
|
+
const actionsMap = await loadActions(resolved.projectRoot, config.actionsDir, {
|
|
27573
|
+
autoInstall: false
|
|
27574
|
+
});
|
|
27575
|
+
const matched = actionsMap.get(resolved.actionId);
|
|
27576
|
+
if (matched) {
|
|
27577
|
+
this.actions.set(`${resolved.packageId}/${resolved.actionId}`, matched);
|
|
27578
|
+
if (!targetPackageId || resolved.packageId === this.packageId) {
|
|
27579
|
+
this.actions.set(resolved.actionId, matched);
|
|
27580
|
+
}
|
|
27581
|
+
return matched;
|
|
27582
|
+
}
|
|
27583
|
+
}
|
|
27584
|
+
} catch {}
|
|
27585
|
+
return;
|
|
27586
|
+
}
|
|
27257
27587
|
listActions() {
|
|
27258
27588
|
return Array.from(this.actions.values());
|
|
27259
27589
|
}
|
|
@@ -27262,27 +27592,30 @@ class ActionRunner {
|
|
|
27262
27592
|
const startedAt = new Date().toISOString();
|
|
27263
27593
|
const callStack = [...options.callStack || []];
|
|
27264
27594
|
let action;
|
|
27265
|
-
|
|
27266
|
-
|
|
27267
|
-
|
|
27268
|
-
const error = {
|
|
27269
|
-
code: "ACTION_NOT_FOUND",
|
|
27270
|
-
message: `Action '${actionOrId}' not found in registry`
|
|
27271
|
-
};
|
|
27272
|
-
return {
|
|
27273
|
-
runId,
|
|
27274
|
-
result: Promise.resolve({ ok: false, runId, error }),
|
|
27275
|
-
cancel: () => false
|
|
27276
|
-
};
|
|
27277
|
-
}
|
|
27278
|
-
action = found;
|
|
27279
|
-
} else {
|
|
27595
|
+
let targetActionId;
|
|
27596
|
+
let targetPackageId = this.packageId;
|
|
27597
|
+
if (typeof actionOrId === "object" && "run" in actionOrId && typeof actionOrId.run === "function") {
|
|
27280
27598
|
action = actionOrId;
|
|
27599
|
+
targetActionId = action.id;
|
|
27600
|
+
} else {
|
|
27601
|
+
const parsed = ActionResolver.parseRef(actionOrId);
|
|
27602
|
+
targetActionId = parsed.actionId;
|
|
27603
|
+
if (parsed.packageId) {
|
|
27604
|
+
targetPackageId = parsed.packageId;
|
|
27605
|
+
}
|
|
27606
|
+
if (parsed.packageId && parsed.packageId !== this.packageId) {
|
|
27607
|
+
action = this.actions.get(`${parsed.packageId}/${targetActionId}`);
|
|
27608
|
+
} else {
|
|
27609
|
+
action = this.actions.get(targetActionId) || (this.packageId ? this.actions.get(`${this.packageId}/${targetActionId}`) : undefined);
|
|
27610
|
+
}
|
|
27281
27611
|
}
|
|
27282
|
-
|
|
27612
|
+
const isExternal = Boolean(targetPackageId && targetPackageId !== this.packageId);
|
|
27613
|
+
const callKey = isExternal ? `${targetPackageId}/${targetActionId}` : targetActionId;
|
|
27614
|
+
const hasCycle = isExternal ? callStack.includes(callKey) : callStack.includes(callKey) || (this.packageId ? callStack.includes(`${this.packageId}/${targetActionId}`) : false);
|
|
27615
|
+
if (hasCycle) {
|
|
27283
27616
|
const error = {
|
|
27284
27617
|
code: "ACTION_CYCLE_DETECTED",
|
|
27285
|
-
message: `Cycle detected in action invocation: ${callStack.join(" -> ")} -> ${
|
|
27618
|
+
message: `Cycle detected in action invocation: ${callStack.join(" -> ")} -> ${callKey}`
|
|
27286
27619
|
};
|
|
27287
27620
|
return {
|
|
27288
27621
|
runId,
|
|
@@ -27290,8 +27623,8 @@ class ActionRunner {
|
|
|
27290
27623
|
cancel: () => false
|
|
27291
27624
|
};
|
|
27292
27625
|
}
|
|
27293
|
-
callStack.push(
|
|
27294
|
-
if (action
|
|
27626
|
+
callStack.push(callKey);
|
|
27627
|
+
if (action?.inputSchema) {
|
|
27295
27628
|
const val = validateSchema(action.inputSchema, input);
|
|
27296
27629
|
if (!val.valid) {
|
|
27297
27630
|
const error = {
|
|
@@ -27310,9 +27643,9 @@ class ActionRunner {
|
|
|
27310
27643
|
id: runId,
|
|
27311
27644
|
rootRunId: options.rootRunId || options.parentRunId || runId,
|
|
27312
27645
|
parentRunId: options.parentRunId,
|
|
27313
|
-
packageId:
|
|
27314
|
-
packageInstanceId: options.packageInstanceId ||
|
|
27315
|
-
actionId:
|
|
27646
|
+
packageId: targetPackageId,
|
|
27647
|
+
packageInstanceId: options.packageInstanceId || targetPackageId,
|
|
27648
|
+
actionId: targetActionId,
|
|
27316
27649
|
generationId: options.generationId || "1",
|
|
27317
27650
|
ownerId: options.ownerId || "local",
|
|
27318
27651
|
status: "running",
|
|
@@ -27357,7 +27690,7 @@ class ActionRunner {
|
|
|
27357
27690
|
signal: controller.signal,
|
|
27358
27691
|
process: options.process,
|
|
27359
27692
|
progress: options.progress,
|
|
27360
|
-
logger: options.logger || new StderrLogger(action
|
|
27693
|
+
logger: options.logger || new StderrLogger(action?.id || targetActionId),
|
|
27361
27694
|
onActionInvoke: async (childAction, childInput, parentRunId) => {
|
|
27362
27695
|
const childResult = await this.execute(childAction, childInput, {
|
|
27363
27696
|
rootRunId: initialRun.rootRunId,
|
|
@@ -27386,16 +27719,40 @@ class ActionRunner {
|
|
|
27386
27719
|
});
|
|
27387
27720
|
const executionPromise = (async () => {
|
|
27388
27721
|
try {
|
|
27722
|
+
let currentAction = action;
|
|
27723
|
+
if (!currentAction) {
|
|
27724
|
+
currentAction = await this.resolveAction(actionOrId);
|
|
27725
|
+
if (!currentAction) {
|
|
27726
|
+
const error = {
|
|
27727
|
+
code: "ACTION_NOT_FOUND",
|
|
27728
|
+
message: `Action '${targetActionId}' not found in registry or linked packages`
|
|
27729
|
+
};
|
|
27730
|
+
finalizeRun("failed", undefined, error);
|
|
27731
|
+
return { ok: false, runId, error };
|
|
27732
|
+
}
|
|
27733
|
+
if (currentAction.inputSchema) {
|
|
27734
|
+
const val = validateSchema(currentAction.inputSchema, input);
|
|
27735
|
+
if (!val.valid) {
|
|
27736
|
+
const error = {
|
|
27737
|
+
code: "INPUT_VALIDATION_FAILED",
|
|
27738
|
+
message: `Input schema validation failed for action '${currentAction.id}'`,
|
|
27739
|
+
details: val.errors
|
|
27740
|
+
};
|
|
27741
|
+
finalizeRun("failed", undefined, error);
|
|
27742
|
+
return { ok: false, runId, error };
|
|
27743
|
+
}
|
|
27744
|
+
}
|
|
27745
|
+
}
|
|
27389
27746
|
const rawOutput = await Promise.race([
|
|
27390
|
-
Promise.resolve().then(() =>
|
|
27747
|
+
Promise.resolve().then(() => currentAction.run(input, ctx)),
|
|
27391
27748
|
abortPromise
|
|
27392
27749
|
]);
|
|
27393
|
-
if (
|
|
27394
|
-
const outVal = validateSchema(
|
|
27750
|
+
if (currentAction.outputSchema) {
|
|
27751
|
+
const outVal = validateSchema(currentAction.outputSchema, rawOutput);
|
|
27395
27752
|
if (!outVal.valid) {
|
|
27396
27753
|
const error = {
|
|
27397
27754
|
code: "OUTPUT_VALIDATION_FAILED",
|
|
27398
|
-
message: `Output schema validation failed for action '${
|
|
27755
|
+
message: `Output schema validation failed for action '${currentAction.id}'`,
|
|
27399
27756
|
details: outVal.errors
|
|
27400
27757
|
};
|
|
27401
27758
|
finalizeRun("failed", undefined, error);
|
|
@@ -27568,6 +27925,14 @@ ad link "<skill_root>"
|
|
|
27568
27925
|
|
|
27569
27926
|
> \`ad link\` \u5929\u7136\u5177\u5907\u5E42\u7B49\u6027\uFF0C\u540C\u4E00 Package \u591A\u6B21\u6267\u884C\u4F1A\u76F4\u63A5\u66F4\u65B0\u8DEF\u5F84\uFF0C\u53EF\u5B89\u5168\u91CD\u590D\u8C03\u7528\u3002
|
|
27570
27927
|
|
|
27928
|
+
### \u52A8\u4F5C\u53C2\u6570\u5951\u7EA6\u6309\u9700\u8C03\u9605
|
|
27929
|
+
|
|
27930
|
+
\u5728\u8C03\u7528\u672A\u77E5\u53C2\u6570\u7684 Action \u524D\uFF0C\u53EF\u5728\u7EC8\u7AEF\u6267\u884C\u547D\u4EE4\u6309\u9700\u67E5\u9605\u8BE5 Action \u7684\u8F93\u5165\u8F93\u51FA\u6A21\u5F0F\u4E0E\u8BE6\u7EC6\u8BF4\u660E\uFF1A
|
|
27931
|
+
|
|
27932
|
+
\`\`\`bash
|
|
27933
|
+
ad action show ${pkgId}/${firstAction}
|
|
27934
|
+
\`\`\`
|
|
27935
|
+
|
|
27571
27936
|
### \u6267\u884C Action
|
|
27572
27937
|
|
|
27573
27938
|
\u4E3A\u907F\u514D\u591A\u6280\u80FD\u4E4B\u95F4\u7684 Action ID \u547D\u540D\u51B2\u7A81\uFF0C\u5EFA\u8BAE\u7EDF\u4E00\u4F7F\u7528\u5E26\u6709 Package \u524D\u7F00\u7684\u5B8C\u5168\u9650\u5B9A ID\u3002
|
|
@@ -27776,70 +28141,106 @@ ${binaryRelPath} state get KEY
|
|
|
27776
28141
|
\`\`\`
|
|
27777
28142
|
`;
|
|
27778
28143
|
}
|
|
27779
|
-
function
|
|
27780
|
-
|
|
27781
|
-
|
|
27782
|
-
|
|
27783
|
-
|
|
27784
|
-
|
|
27785
|
-
|
|
27786
|
-
|
|
27787
|
-
|
|
27788
|
-
|
|
27789
|
-
|
|
27790
|
-
|
|
27791
|
-
|
|
27792
|
-
|
|
27793
|
-
|
|
27794
|
-
|
|
27795
|
-
const
|
|
27796
|
-
|
|
27797
|
-
|
|
27798
|
-
|
|
27799
|
-
version: config.version,
|
|
27800
|
-
description: config.description,
|
|
27801
|
-
mode
|
|
27802
|
-
};
|
|
27803
|
-
if (mode === "standalone" && executable) {
|
|
27804
|
-
manifest.target = targetPlatform;
|
|
27805
|
-
manifest.executable = executable;
|
|
27806
|
-
}
|
|
27807
|
-
manifest.actions = actions.map((a) => {
|
|
27808
|
-
const item = {
|
|
27809
|
-
id: a.id
|
|
27810
|
-
};
|
|
27811
|
-
if (a.entry) {
|
|
27812
|
-
item.entry = a.entry;
|
|
27813
|
-
}
|
|
27814
|
-
if (a.description) {
|
|
27815
|
-
item.description = a.description;
|
|
27816
|
-
}
|
|
27817
|
-
if (a.inputSchema !== undefined) {
|
|
27818
|
-
item.inputSchema = a.inputSchema;
|
|
27819
|
-
}
|
|
27820
|
-
if (a.outputSchema !== undefined) {
|
|
27821
|
-
item.outputSchema = a.outputSchema;
|
|
27822
|
-
}
|
|
27823
|
-
if (a.uses) {
|
|
27824
|
-
item.uses = a.uses;
|
|
27825
|
-
}
|
|
27826
|
-
if (a.tags) {
|
|
27827
|
-
item.tags = a.tags;
|
|
27828
|
-
}
|
|
27829
|
-
if (a.annotations) {
|
|
27830
|
-
item.annotations = a.annotations;
|
|
28144
|
+
function generateCompositeSkillMd(bundleName, description, packages) {
|
|
28145
|
+
const cleanName = bundleName.replace(/[^a-zA-Z0-9-_]/g, "-").toLowerCase();
|
|
28146
|
+
const samplePkg = packages.find((p) => p.actions && p.actions.length > 0);
|
|
28147
|
+
const sampleActionId = samplePkg ? `${samplePkg.config.id}/${samplePkg.actions[0].id}` : "sample.greet";
|
|
28148
|
+
const actionSections = packages.map((pkg) => {
|
|
28149
|
+
const actList = pkg.actions.map((a) => {
|
|
28150
|
+
const desc = a.description ? `: ${a.description}` : "";
|
|
28151
|
+
return `- \`${pkg.config.id}/${a.id}\`${desc}`;
|
|
28152
|
+
}).join(`
|
|
28153
|
+
`);
|
|
28154
|
+
return `### ${pkg.config.name} (${pkg.config.id})
|
|
28155
|
+
${actList || "- \u65E0\u53EF\u7528 Action"}`;
|
|
28156
|
+
}).join(`
|
|
28157
|
+
|
|
28158
|
+
`);
|
|
28159
|
+
const playbookEntries = [];
|
|
28160
|
+
for (const pkg of packages) {
|
|
28161
|
+
for (const pb of pkg.playbooks) {
|
|
28162
|
+
const relPath = `packages/${pkg.packageDir}/playbooks/${basename3(pb.filePath)}`;
|
|
28163
|
+
playbookEntries.push(`- [${pb.name || pb.id}](${relPath}): ${pb.description || "\u6807\u51C6\u64CD\u4F5C\u89C4\u7A0B"}`);
|
|
27831
28164
|
}
|
|
27832
|
-
return item;
|
|
27833
|
-
});
|
|
27834
|
-
if (playbooks && playbooks.length > 0) {
|
|
27835
|
-
manifest.playbooks = playbooks.map((p) => ({
|
|
27836
|
-
id: p.id,
|
|
27837
|
-
description: p.description,
|
|
27838
|
-
entry: `playbooks/${basename3(p.filePath)}`
|
|
27839
|
-
}));
|
|
27840
28165
|
}
|
|
27841
|
-
|
|
27842
|
-
|
|
28166
|
+
const playbookSection = playbookEntries.length > 0 ? `## \u63A8\u8350\u64CD\u4F5C\u89C4\u7A0B
|
|
28167
|
+
|
|
28168
|
+
\u6D89\u53CA\u591A\u6B65\u9AA4\u6216\u4E1A\u52A1\u6D41\u7A0B\u65F6\uFF0C\u4F18\u5148\u9075\u5FAA\u4EE5\u4E0B\u539F\u4F4D\u89C4\u7A0B\uFF1A
|
|
28169
|
+
|
|
28170
|
+
${playbookEntries.join(`
|
|
28171
|
+
`)}
|
|
28172
|
+
|
|
28173
|
+
---
|
|
28174
|
+
` : "";
|
|
28175
|
+
return `---
|
|
28176
|
+
name: ${cleanName}
|
|
28177
|
+
description: ${description}
|
|
28178
|
+
---
|
|
28179
|
+
|
|
28180
|
+
# ${bundleName} \u590D\u5408\u6280\u80FD\u5957\u4EF6
|
|
28181
|
+
|
|
28182
|
+
${description}
|
|
28183
|
+
|
|
28184
|
+
## ActionDock \u8FD0\u884C\u65F6\u521D\u59CB\u5316
|
|
28185
|
+
|
|
28186
|
+
\u672C\u6280\u80FD\u4E3A **ActionDock \u590D\u5408\u5DE5\u4F5C\u533A\u6280\u80FD\u5305**\uFF0C\u805A\u5408\u4E86\u591A\u4E2A\u529F\u80FD\u5305\u3002\u667A\u80FD\u4F53\u5728\u521D\u6B21\u8C03\u7528\u6216\u521D\u59CB\u5316\u65F6\uFF0C\u5728\u5F53\u524D\u6280\u80FD\u6839\u76EE\u5F55\u6267\u884C\u6CE8\u518C\u547D\u4EE4\uFF1A
|
|
28187
|
+
|
|
28188
|
+
\`\`\`bash
|
|
28189
|
+
ad link "<skill_root>"
|
|
28190
|
+
\`\`\`
|
|
28191
|
+
|
|
28192
|
+
> \`ad link\` \u4F1A\u81EA\u52A8\u8BC6\u522B\u5E76\u6CE8\u518C\u5DE5\u4F5C\u533A\u4E0B\u7684\u6240\u6709\u5B50\u5305\uFF0C\u4F7F\u5176\u4E2D\u7684 Action \u968F\u65F6\u53EF\u4EE5\u901A\u8FC7\u5B8C\u5168\u9650\u5B9A\u6807\u8BC6\u8C03\u7528\u3002
|
|
28193
|
+
|
|
28194
|
+
## \u52A8\u4F5C\u53C2\u6570\u5951\u7EA6\u6309\u9700\u8C03\u9605
|
|
28195
|
+
|
|
28196
|
+
\u4E3A\u8282\u7701\u4E0A\u4E0B\u6587\u5F00\u9500\uFF0C\u5404 Action \u7684\u8BE6\u7EC6\u53C2\u6570\u7ED3\u6784\u4E0D\u9759\u6001\u5185\u5D4C\u5728\u8BF4\u660E\u4E66\u4E2D\u3002\u5728\u8C03\u7528\u672A\u77E5\u53C2\u6570\u7684 Action \u524D\uFF0C\u53EF\u5728\u7EC8\u7AEF\u6267\u884C\u547D\u4EE4\u67E5\u9605\u8F93\u5165\u8F93\u51FA\u7EA6\u675F\uFF1A
|
|
28197
|
+
|
|
28198
|
+
\`\`\`bash
|
|
28199
|
+
ad action show ${sampleActionId}
|
|
28200
|
+
\`\`\`
|
|
28201
|
+
|
|
28202
|
+
## \u53EF\u7528 Action \u5DE5\u5177\u6E05\u5355
|
|
28203
|
+
|
|
28204
|
+
${actionSections}
|
|
28205
|
+
|
|
28206
|
+
---
|
|
28207
|
+
|
|
28208
|
+
${playbookSection}
|
|
28209
|
+
## \u6807\u51C6\u8C03\u7528\u547D\u4EE4
|
|
28210
|
+
|
|
28211
|
+
\u63A8\u8350\u4F7F\u7528\u53C2\u6570\u6587\u4EF6\u4F20\u9012\u5185\u5BB9\uFF0C\u675C\u7EDD\u7EC8\u7AEF\u5F15\u53F7\u8F6C\u4E49\u95EE\u9898\uFF1A
|
|
28212
|
+
|
|
28213
|
+
\`\`\`bash
|
|
28214
|
+
cat << 'EOF' > /tmp/input.json
|
|
28215
|
+
{
|
|
28216
|
+
"param": "value"
|
|
28217
|
+
}
|
|
28218
|
+
EOF
|
|
28219
|
+
ad run ${sampleActionId} --input-file /tmp/input.json
|
|
28220
|
+
\`\`\`
|
|
28221
|
+
|
|
28222
|
+
### \u7ED3\u6784\u5316\u54CD\u5E94\u89E3\u6790
|
|
28223
|
+
|
|
28224
|
+
\u6240\u6709 Action \u6267\u884C\u7ED3\u679C\u5747\u5728 \`stdout\` \u8F93\u51FA\u6807\u51C6\u683C\u5F0F\u7684 JSON \u4FE1\u5C01\uFF1A
|
|
28225
|
+
|
|
28226
|
+
\`\`\`json
|
|
28227
|
+
// \u6267\u884C\u6210\u529F\u54CD\u5E94 (ok \u4E3A true)
|
|
28228
|
+
{
|
|
28229
|
+
"ok": true,
|
|
28230
|
+
"runId": "01J...",
|
|
28231
|
+
"data": { ... }
|
|
28232
|
+
}
|
|
28233
|
+
|
|
28234
|
+
// \u6267\u884C\u5931\u8D25\u54CD\u5E94 (ok \u4E3A false)
|
|
28235
|
+
{
|
|
28236
|
+
"ok": false,
|
|
28237
|
+
"runId": "01J...",
|
|
28238
|
+
"error": {
|
|
28239
|
+
"code": "ACTION_EXECUTION_FAILED",
|
|
28240
|
+
"message": "\u9519\u8BEF\u8BE6\u7EC6\u63CF\u8FF0\u4FE1\u606F"
|
|
28241
|
+
}
|
|
28242
|
+
}
|
|
28243
|
+
\`\`\`
|
|
27843
28244
|
`;
|
|
27844
28245
|
}
|
|
27845
28246
|
// ../core/src/filter/intent.ts
|
|
@@ -27939,8 +28340,8 @@ function filterByIntent(items, intent, extractors, fallback = true) {
|
|
|
27939
28340
|
return filterWithFallbackInfo(items, intent, extractors, fallback).items;
|
|
27940
28341
|
}
|
|
27941
28342
|
// ../core/src/profile/manager.ts
|
|
27942
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
27943
|
-
import { dirname as dirname4, join as
|
|
28343
|
+
import { chmodSync as chmodSync2, existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
28344
|
+
import { dirname as dirname4, join as join8 } from "path";
|
|
27944
28345
|
var PROFILE_NAME_REGEX = /^[a-zA-Z0-9_\-\.]+$/;
|
|
27945
28346
|
var DEFAULT_PROFILES_CONFIG = {
|
|
27946
28347
|
currentProfile: "local",
|
|
@@ -27960,11 +28361,11 @@ function normalizeServerUrl(url) {
|
|
|
27960
28361
|
}
|
|
27961
28362
|
function getProfilesFilePath(customHome) {
|
|
27962
28363
|
const baseDir = getActionDockHome(customHome);
|
|
27963
|
-
return
|
|
28364
|
+
return join8(baseDir, ".actiondock", "profiles.json");
|
|
27964
28365
|
}
|
|
27965
28366
|
function loadProfiles(customHome) {
|
|
27966
28367
|
const filePath = getProfilesFilePath(customHome);
|
|
27967
|
-
if (!
|
|
28368
|
+
if (!existsSync9(filePath)) {
|
|
27968
28369
|
return structuredClone(DEFAULT_PROFILES_CONFIG);
|
|
27969
28370
|
}
|
|
27970
28371
|
try {
|
|
@@ -28457,11 +28858,11 @@ async function deleteRemoteConfig(serverUrl, key, token, packageId) {
|
|
|
28457
28858
|
});
|
|
28458
28859
|
}
|
|
28459
28860
|
// ../core/src/project/init.ts
|
|
28460
|
-
import { existsSync as
|
|
28461
|
-
import { basename as basename4, join as
|
|
28861
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
28862
|
+
import { basename as basename4, join as join9, resolve as resolve4 } from "path";
|
|
28462
28863
|
function initProject(targetDir, options = {}) {
|
|
28463
28864
|
const root = resolve4(targetDir);
|
|
28464
|
-
if (!
|
|
28865
|
+
if (!existsSync10(root)) {
|
|
28465
28866
|
mkdirSync4(root, { recursive: true });
|
|
28466
28867
|
}
|
|
28467
28868
|
const dirName = basename4(root);
|
|
@@ -28482,7 +28883,7 @@ function initProject(targetDir, options = {}) {
|
|
|
28482
28883
|
}
|
|
28483
28884
|
}
|
|
28484
28885
|
};
|
|
28485
|
-
writeFileSync4(
|
|
28886
|
+
writeFileSync4(join9(root, "actiondock.json"), JSON.stringify(actiondockJson, null, 2) + `
|
|
28486
28887
|
`);
|
|
28487
28888
|
const manifestJson = {
|
|
28488
28889
|
schemaVersion: 1,
|
|
@@ -28514,7 +28915,7 @@ function initProject(targetDir, options = {}) {
|
|
|
28514
28915
|
},
|
|
28515
28916
|
assets: []
|
|
28516
28917
|
};
|
|
28517
|
-
writeFileSync4(
|
|
28918
|
+
writeFileSync4(join9(root, "actiondock.manifest.json"), JSON.stringify(manifestJson, null, 2) + `
|
|
28518
28919
|
`);
|
|
28519
28920
|
const packageJson = {
|
|
28520
28921
|
name: id,
|
|
@@ -28528,16 +28929,16 @@ function initProject(targetDir, options = {}) {
|
|
|
28528
28929
|
node: ">=22.12.0"
|
|
28529
28930
|
},
|
|
28530
28931
|
dependencies: {
|
|
28531
|
-
"@actiondock/sdk": "^2.0.
|
|
28932
|
+
"@actiondock/sdk": "^2.0.11"
|
|
28532
28933
|
},
|
|
28533
28934
|
devDependencies: {
|
|
28534
|
-
"@actiondock/testing": "^2.0.
|
|
28935
|
+
"@actiondock/testing": "^2.0.11",
|
|
28535
28936
|
"@types/node": "^22.12.0",
|
|
28536
28937
|
tsx: "^4.19.0",
|
|
28537
28938
|
typescript: "^5.7.0"
|
|
28538
28939
|
}
|
|
28539
28940
|
};
|
|
28540
|
-
writeFileSync4(
|
|
28941
|
+
writeFileSync4(join9(root, "package.json"), JSON.stringify(packageJson, null, 2) + `
|
|
28541
28942
|
`);
|
|
28542
28943
|
const tsconfigJson = {
|
|
28543
28944
|
compilerOptions: {
|
|
@@ -28549,7 +28950,7 @@ function initProject(targetDir, options = {}) {
|
|
|
28549
28950
|
types: ["node"]
|
|
28550
28951
|
}
|
|
28551
28952
|
};
|
|
28552
|
-
writeFileSync4(
|
|
28953
|
+
writeFileSync4(join9(root, "tsconfig.json"), JSON.stringify(tsconfigJson, null, 2) + `
|
|
28553
28954
|
`);
|
|
28554
28955
|
const gitignore = `.actiondock/
|
|
28555
28956
|
node_modules/
|
|
@@ -28558,8 +28959,8 @@ build/
|
|
|
28558
28959
|
*.log
|
|
28559
28960
|
.env
|
|
28560
28961
|
`;
|
|
28561
|
-
writeFileSync4(
|
|
28562
|
-
const actionsDir =
|
|
28962
|
+
writeFileSync4(join9(root, ".gitignore"), gitignore);
|
|
28963
|
+
const actionsDir = join9(root, "actions");
|
|
28563
28964
|
mkdirSync4(actionsDir, { recursive: true });
|
|
28564
28965
|
const sampleAction = `import { defineAction } from "@actiondock/sdk";
|
|
28565
28966
|
|
|
@@ -28602,8 +29003,8 @@ export default defineAction({
|
|
|
28602
29003
|
},
|
|
28603
29004
|
});
|
|
28604
29005
|
`;
|
|
28605
|
-
writeFileSync4(
|
|
28606
|
-
const playbooksDir =
|
|
29006
|
+
writeFileSync4(join9(actionsDir, "greet.ts"), sampleAction);
|
|
29007
|
+
const playbooksDir = join9(root, "playbooks");
|
|
28607
29008
|
mkdirSync4(playbooksDir, { recursive: true });
|
|
28608
29009
|
const samplePlaybook = `---
|
|
28609
29010
|
id: greet-user
|
|
@@ -28617,8 +29018,8 @@ actions:
|
|
|
28617
29018
|
- Call \`sample.greet\` with the user's name.
|
|
28618
29019
|
- Confirm the returned greeting message.
|
|
28619
29020
|
`;
|
|
28620
|
-
writeFileSync4(
|
|
28621
|
-
const testsDir =
|
|
29021
|
+
writeFileSync4(join9(playbooksDir, "greet-user.md"), samplePlaybook);
|
|
29022
|
+
const testsDir = join9(root, "tests");
|
|
28622
29023
|
mkdirSync4(testsDir, { recursive: true });
|
|
28623
29024
|
const sampleTest = `import { describe, it } from "node:test";
|
|
28624
29025
|
import assert from "node:assert/strict";
|
|
@@ -28641,7 +29042,7 @@ describe("greet action", () => {
|
|
|
28641
29042
|
});
|
|
28642
29043
|
});
|
|
28643
29044
|
`;
|
|
28644
|
-
writeFileSync4(
|
|
29045
|
+
writeFileSync4(join9(testsDir, "greet.test.ts"), sampleTest);
|
|
28645
29046
|
}
|
|
28646
29047
|
// ../core/src/runtime/execution-manager.ts
|
|
28647
29048
|
class ExecutionManager {
|
|
@@ -28865,7 +29266,7 @@ class ServerRuntimeRegistry {
|
|
|
28865
29266
|
}
|
|
28866
29267
|
}
|
|
28867
29268
|
// ../core/src/server/routes/common.ts
|
|
28868
|
-
import { existsSync as
|
|
29269
|
+
import { existsSync as existsSync11 } from "fs";
|
|
28869
29270
|
function jsonResponse(data, status = 200, corsHeaders = {}) {
|
|
28870
29271
|
return new Response(JSON.stringify(data, null, 2), {
|
|
28871
29272
|
status,
|
|
@@ -28929,7 +29330,7 @@ function findRunAcrossStorages(runId, runtimeRegistry, projectRoot, customHome)
|
|
|
28929
29330
|
try {
|
|
28930
29331
|
const linked = listLinkedPackages(customHome);
|
|
28931
29332
|
for (const pkg of linked) {
|
|
28932
|
-
if (!
|
|
29333
|
+
if (!existsSync11(pkg.path))
|
|
28933
29334
|
continue;
|
|
28934
29335
|
const storage = runtimeRegistry.getStorage(pkg.id, pkg.path);
|
|
28935
29336
|
const run = storage.getRun(runId);
|
|
@@ -28966,7 +29367,7 @@ async function handleHealthRoute(ctx) {
|
|
|
28966
29367
|
return jsonResponse(healthData, 200, corsHeaders);
|
|
28967
29368
|
}
|
|
28968
29369
|
// ../core/src/server/routes/info.ts
|
|
28969
|
-
import { existsSync as
|
|
29370
|
+
import { existsSync as existsSync12 } from "fs";
|
|
28970
29371
|
async function handleInfoRoute(ctx) {
|
|
28971
29372
|
const { req, url, pathname, corsHeaders, projectRoot, customHome, options } = ctx;
|
|
28972
29373
|
if (pathname !== "/api/v1/info" || req.method !== "GET") {
|
|
@@ -29011,7 +29412,7 @@ async function handleInfoRoute(ctx) {
|
|
|
29011
29412
|
} else {
|
|
29012
29413
|
const linked = listLinkedPackages(customHome);
|
|
29013
29414
|
for (const pkg of linked) {
|
|
29014
|
-
if (!
|
|
29415
|
+
if (!existsSync12(pkg.path))
|
|
29015
29416
|
continue;
|
|
29016
29417
|
try {
|
|
29017
29418
|
const config = loadProjectConfig(pkg.path);
|
|
@@ -29140,7 +29541,7 @@ async function handleDoctorRoute(ctx) {
|
|
|
29140
29541
|
}
|
|
29141
29542
|
// ../core/src/server/routes/actions.ts
|
|
29142
29543
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
29143
|
-
import { existsSync as
|
|
29544
|
+
import { existsSync as existsSync13 } from "fs";
|
|
29144
29545
|
async function handleActionsRoutes(ctx) {
|
|
29145
29546
|
const { req, url, pathname, corsHeaders, projectRoot, customHome, runtimeRegistry, options } = ctx;
|
|
29146
29547
|
if (pathname === "/api/v1/actions" && req.method === "GET") {
|
|
@@ -29161,7 +29562,7 @@ async function handleActionsRoutes(ctx) {
|
|
|
29161
29562
|
for (const pkg of linked) {
|
|
29162
29563
|
if (projectRoot && pkg.path === projectRoot)
|
|
29163
29564
|
continue;
|
|
29164
|
-
if (!
|
|
29565
|
+
if (!existsSync13(pkg.path))
|
|
29165
29566
|
continue;
|
|
29166
29567
|
try {
|
|
29167
29568
|
const config = loadProjectConfig(pkg.path);
|
|
@@ -29308,7 +29709,7 @@ async function handleActionsRoutes(ctx) {
|
|
|
29308
29709
|
return null;
|
|
29309
29710
|
}
|
|
29310
29711
|
// ../core/src/server/routes/playbooks.ts
|
|
29311
|
-
import { existsSync as
|
|
29712
|
+
import { existsSync as existsSync14 } from "fs";
|
|
29312
29713
|
async function handlePlaybooksRoutes(ctx) {
|
|
29313
29714
|
const { req, url, pathname, corsHeaders, projectRoot, customHome } = ctx;
|
|
29314
29715
|
if (pathname === "/api/v1/playbooks" && req.method === "GET") {
|
|
@@ -29325,7 +29726,7 @@ async function handlePlaybooksRoutes(ctx) {
|
|
|
29325
29726
|
for (const pkg of linked) {
|
|
29326
29727
|
if (projectRoot && pkg.path === projectRoot)
|
|
29327
29728
|
continue;
|
|
29328
|
-
if (!
|
|
29729
|
+
if (!existsSync14(pkg.path))
|
|
29329
29730
|
continue;
|
|
29330
29731
|
roots.push({ root: pkg.path, packageId: pkg.id });
|
|
29331
29732
|
}
|
|
@@ -29374,7 +29775,7 @@ async function handlePlaybooksRoutes(ctx) {
|
|
|
29374
29775
|
return null;
|
|
29375
29776
|
}
|
|
29376
29777
|
// ../core/src/server/routes/runs.ts
|
|
29377
|
-
import { existsSync as
|
|
29778
|
+
import { existsSync as existsSync15 } from "fs";
|
|
29378
29779
|
async function handleRunsRoutes(ctx) {
|
|
29379
29780
|
const { req, url, pathname, corsHeaders, projectRoot, customHome, runtimeRegistry, options } = ctx;
|
|
29380
29781
|
if (pathname === "/api/v1/runs" && req.method === "GET") {
|
|
@@ -29400,7 +29801,7 @@ async function handleRunsRoutes(ctx) {
|
|
|
29400
29801
|
for (const pkg of linked) {
|
|
29401
29802
|
if (projectRoot && pkg.path === projectRoot)
|
|
29402
29803
|
continue;
|
|
29403
|
-
if (!
|
|
29804
|
+
if (!existsSync15(pkg.path))
|
|
29404
29805
|
continue;
|
|
29405
29806
|
candidateStorages.push({
|
|
29406
29807
|
packageId: pkg.id,
|
|
@@ -29451,7 +29852,7 @@ async function handleRunsRoutes(ctx) {
|
|
|
29451
29852
|
for (const pkg of linked) {
|
|
29452
29853
|
if (projectRoot && pkg.path === projectRoot)
|
|
29453
29854
|
continue;
|
|
29454
|
-
if (!
|
|
29855
|
+
if (!existsSync15(pkg.path))
|
|
29455
29856
|
continue;
|
|
29456
29857
|
if (packageId && pkg.id !== packageId)
|
|
29457
29858
|
continue;
|
|
@@ -52305,7 +52706,7 @@ function toMcpSchema(schema) {
|
|
|
52305
52706
|
return fromJsonSchema2(schema);
|
|
52306
52707
|
}
|
|
52307
52708
|
// ../mcp/src/adapter.ts
|
|
52308
|
-
import { existsSync as
|
|
52709
|
+
import { existsSync as existsSync16 } from "fs";
|
|
52309
52710
|
import { resolve as resolve6 } from "path";
|
|
52310
52711
|
function isPlainObject3(value) {
|
|
52311
52712
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
@@ -52389,7 +52790,7 @@ async function createActionDockMcpServer(options = {}) {
|
|
|
52389
52790
|
if (options.all) {
|
|
52390
52791
|
const linked = listLinkedPackages(options.customHome);
|
|
52391
52792
|
for (const pkg of linked) {
|
|
52392
|
-
if (
|
|
52793
|
+
if (existsSync16(pkg.path)) {
|
|
52393
52794
|
resolvedRoots.add(resolve6(pkg.path));
|
|
52394
52795
|
}
|
|
52395
52796
|
}
|
|
@@ -52400,7 +52801,7 @@ async function createActionDockMcpServer(options = {}) {
|
|
|
52400
52801
|
}
|
|
52401
52802
|
for (const pkgId of targetPackages) {
|
|
52402
52803
|
const root = resolvePackageRoot(pkgId, undefined, options.customHome);
|
|
52403
|
-
if (!root || !
|
|
52804
|
+
if (!root || !existsSync16(root)) {
|
|
52404
52805
|
throw new Error(`Package '${pkgId}' not found in registry`);
|
|
52405
52806
|
}
|
|
52406
52807
|
resolvedRoots.add(resolve6(root));
|
|
@@ -53488,9 +53889,9 @@ class NodeHttpServer {
|
|
|
53488
53889
|
}
|
|
53489
53890
|
|
|
53490
53891
|
// ../runtime-node/src/module-loader.ts
|
|
53491
|
-
import { existsSync as
|
|
53892
|
+
import { existsSync as existsSync17, statSync as statSync4 } from "fs";
|
|
53492
53893
|
import { createRequire as createRequire2 } from "module";
|
|
53493
|
-
import { dirname as dirname5, isAbsolute, join as
|
|
53894
|
+
import { dirname as dirname5, isAbsolute, join as join10, resolve as resolve7 } from "path";
|
|
53494
53895
|
import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "url";
|
|
53495
53896
|
var cjsRequire2 = createRequire2(import.meta.url);
|
|
53496
53897
|
var CANDIDATE_EXTENSIONS = [
|
|
@@ -53533,7 +53934,7 @@ class TsxModuleLoader {
|
|
|
53533
53934
|
if (parentPath) {
|
|
53534
53935
|
try {
|
|
53535
53936
|
const p = parentPath.startsWith("file://") ? fileURLToPath(parentPath) : parentPath;
|
|
53536
|
-
if (
|
|
53937
|
+
if (existsSync17(p)) {
|
|
53537
53938
|
const stat = statSync4(p);
|
|
53538
53939
|
baseDir = stat.isDirectory() ? resolve7(p) : dirname5(resolve7(p));
|
|
53539
53940
|
} else {
|
|
@@ -53546,7 +53947,7 @@ class TsxModuleLoader {
|
|
|
53546
53947
|
const candidateBasePath = isAbsolute(target) ? target : resolve7(baseDir, target);
|
|
53547
53948
|
for (const ext of CANDIDATE_EXTENSIONS) {
|
|
53548
53949
|
const fullPath = ext ? `${candidateBasePath}${ext}` : candidateBasePath;
|
|
53549
|
-
if (
|
|
53950
|
+
if (existsSync17(fullPath)) {
|
|
53550
53951
|
try {
|
|
53551
53952
|
if (statSync4(fullPath).isFile()) {
|
|
53552
53953
|
return fullPath;
|
|
@@ -53554,12 +53955,12 @@ class TsxModuleLoader {
|
|
|
53554
53955
|
} catch {}
|
|
53555
53956
|
}
|
|
53556
53957
|
}
|
|
53557
|
-
if (
|
|
53958
|
+
if (existsSync17(candidateBasePath)) {
|
|
53558
53959
|
try {
|
|
53559
53960
|
if (statSync4(candidateBasePath).isDirectory()) {
|
|
53560
53961
|
for (const indexName of INDEX_CANDIDATES) {
|
|
53561
|
-
const indexFilePath =
|
|
53562
|
-
if (
|
|
53962
|
+
const indexFilePath = join10(candidateBasePath, indexName);
|
|
53963
|
+
if (existsSync17(indexFilePath) && statSync4(indexFilePath).isFile()) {
|
|
53563
53964
|
return indexFilePath;
|
|
53564
53965
|
}
|
|
53565
53966
|
}
|
|
@@ -53577,7 +53978,7 @@ class TsxModuleLoader {
|
|
|
53577
53978
|
}
|
|
53578
53979
|
async load(specifier, parentPath) {
|
|
53579
53980
|
const resolvedPath = this.resolve(specifier, parentPath);
|
|
53580
|
-
const parentUrl = parentPath ? parentPath.startsWith("file://") ? parentPath : pathToFileURL2(resolve7(parentPath)).href : pathToFileURL2(
|
|
53981
|
+
const parentUrl = parentPath ? parentPath.startsWith("file://") ? parentPath : pathToFileURL2(resolve7(parentPath)).href : pathToFileURL2(join10(process.cwd(), "index.js")).href;
|
|
53581
53982
|
const isBun = typeof globalThis.Bun !== "undefined";
|
|
53582
53983
|
if (isBun) {
|
|
53583
53984
|
try {
|
|
@@ -60617,8 +61018,8 @@ function setupNodeRuntime() {
|
|
|
60617
61018
|
}
|
|
60618
61019
|
|
|
60619
61020
|
// src/commands/action/create.ts
|
|
60620
|
-
import { existsSync as
|
|
60621
|
-
import { join as
|
|
61021
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync5, writeFileSync as writeFileSync6 } from "fs";
|
|
61022
|
+
import { join as join11, resolve as resolve8 } from "path";
|
|
60622
61023
|
function registerActionCreateCommand(actionCmd) {
|
|
60623
61024
|
actionCmd.command("create <id>").alias("new").description("Scaffold a new Action definition file").option("-d, --desc <description>", "Action description").option("-f, --file <filePath>", "Target file path relative to actions dir").action(async (id, options) => {
|
|
60624
61025
|
const root = findProjectRoot();
|
|
@@ -60628,13 +61029,13 @@ function registerActionCreateCommand(actionCmd) {
|
|
|
60628
61029
|
try {
|
|
60629
61030
|
const config = loadProjectConfig(root);
|
|
60630
61031
|
const actionsDir = resolve8(root, config.actionsDir || "actions");
|
|
60631
|
-
if (!
|
|
61032
|
+
if (!existsSync18(actionsDir)) {
|
|
60632
61033
|
mkdirSync5(actionsDir, { recursive: true });
|
|
60633
61034
|
}
|
|
60634
61035
|
const cleanName = getPackageSlug(id);
|
|
60635
61036
|
const targetRelFile = options.file || `${cleanName}.ts`;
|
|
60636
61037
|
const targetFullFile = resolve8(actionsDir, targetRelFile);
|
|
60637
|
-
if (
|
|
61038
|
+
if (existsSync18(targetFullFile)) {
|
|
60638
61039
|
throw new ExecutionError(`Target action file already exists at ${targetFullFile}`);
|
|
60639
61040
|
}
|
|
60640
61041
|
const desc = options.desc || `Action ${id}`;
|
|
@@ -60691,7 +61092,7 @@ export default defineAction<Input, Output>({
|
|
|
60691
61092
|
const manifest = loadManifest(root) || { schemaVersion: 1, actions: {}, assets: [] };
|
|
60692
61093
|
manifest.actions = manifest.actions || {};
|
|
60693
61094
|
manifest.actions[id] = {
|
|
60694
|
-
entry:
|
|
61095
|
+
entry: join11(config.actionsDir || "actions", targetRelFile),
|
|
60695
61096
|
description: desc,
|
|
60696
61097
|
inputSchema: {
|
|
60697
61098
|
type: "object",
|
|
@@ -60728,7 +61129,7 @@ To run this action:`);
|
|
|
60728
61129
|
}
|
|
60729
61130
|
|
|
60730
61131
|
// src/commands/action/list.ts
|
|
60731
|
-
import { existsSync as
|
|
61132
|
+
import { existsSync as existsSync19 } from "fs";
|
|
60732
61133
|
function registerActionListCommand(actionCmd) {
|
|
60733
61134
|
actionCmd.command("list [patterns...]").description("List actions in current project, linked packages, or remote profile").option("-i, --intent <pattern>", "Regex or fuzzy intent filter; falls back to full list when no match").option("-P, --package <id>", "Target package ID or path").option("-p, --profile <name>", "Execute or query against a specific profile").option("-s, --server <url>", "Remote server URL").option("-t, --token <token>", "Auth token for remote server").option("--fallback", "Enable fallback to full list when no items match intent").option("--no-fallback", "Disable fallback to full list when no items match intent").option("--json", "Output as JSON").option("--envelope", "Wrap JSON output in standard envelope").action(async (patterns, rawOptions, cmd) => {
|
|
60734
61135
|
try {
|
|
@@ -60827,7 +61228,7 @@ Run 'ad link' inside an Action package to register it.`
|
|
|
60827
61228
|
}
|
|
60828
61229
|
const aggregated = [];
|
|
60829
61230
|
for (const pkg of linkedList) {
|
|
60830
|
-
if (!
|
|
61231
|
+
if (!existsSync19(pkg.path))
|
|
60831
61232
|
continue;
|
|
60832
61233
|
try {
|
|
60833
61234
|
const config = loadProjectConfig(pkg.path);
|
|
@@ -61329,13 +61730,13 @@ class CompilerError extends BuilderError {
|
|
|
61329
61730
|
}
|
|
61330
61731
|
}
|
|
61331
61732
|
// ../builder/src/build.ts
|
|
61332
|
-
import { existsSync as
|
|
61333
|
-
import { join as
|
|
61733
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync7, rmSync, writeFileSync as writeFileSync8 } from "fs";
|
|
61734
|
+
import { join as join13, resolve as resolve11 } from "path";
|
|
61334
61735
|
|
|
61335
61736
|
// ../builder/src/compiler.ts
|
|
61336
61737
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
61337
61738
|
import { createHash } from "crypto";
|
|
61338
|
-
import { existsSync as
|
|
61739
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync6, readFileSync as readFileSync8, statSync as statSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
61339
61740
|
import { basename as basename5, dirname as dirname6, resolve as resolve9 } from "path";
|
|
61340
61741
|
var SUPPORTED_TARGETS = new Set([
|
|
61341
61742
|
"bun",
|
|
@@ -61400,7 +61801,7 @@ class BunCompiler {
|
|
|
61400
61801
|
});
|
|
61401
61802
|
}
|
|
61402
61803
|
const resolvedEntry = resolve9(options.entrypoint);
|
|
61403
|
-
if (!
|
|
61804
|
+
if (!existsSync20(resolvedEntry)) {
|
|
61404
61805
|
throw new CompilerValidationError(`Entrypoint file not found: ${options.entrypoint}`, { code: "ENTRYPOINT_NOT_FOUND" });
|
|
61405
61806
|
}
|
|
61406
61807
|
if (!options.outfile) {
|
|
@@ -61473,13 +61874,13 @@ class BunCompiler {
|
|
|
61473
61874
|
throw normalizeCompilerError(rawStderr, rawStdout, proc.status ?? 1, options.target);
|
|
61474
61875
|
}
|
|
61475
61876
|
let actualExecutablePath = resolvedOutfile;
|
|
61476
|
-
if (!
|
|
61877
|
+
if (!existsSync20(actualExecutablePath) && isWindowsTarget) {
|
|
61477
61878
|
const withExe = `${resolvedOutfile}.exe`;
|
|
61478
|
-
if (
|
|
61879
|
+
if (existsSync20(withExe)) {
|
|
61479
61880
|
actualExecutablePath = withExe;
|
|
61480
61881
|
}
|
|
61481
61882
|
}
|
|
61482
|
-
if (!
|
|
61883
|
+
if (!existsSync20(actualExecutablePath)) {
|
|
61483
61884
|
throw new CompilerError(`Compiler completed with exit code 0 but output executable not found at ${resolvedOutfile}`, {
|
|
61484
61885
|
code: "OUTPUT_NOT_FOUND",
|
|
61485
61886
|
exitCode: 0,
|
|
@@ -61541,15 +61942,15 @@ class BunCompiler {
|
|
|
61541
61942
|
}
|
|
61542
61943
|
|
|
61543
61944
|
// ../builder/src/planner.ts
|
|
61544
|
-
import { existsSync as
|
|
61545
|
-
import { basename as basename6, join as
|
|
61945
|
+
import { existsSync as existsSync21, readdirSync as readdirSync4, readFileSync as readFileSync9, statSync as statSync7 } from "fs";
|
|
61946
|
+
import { basename as basename6, dirname as dirname7, isAbsolute as isAbsolute2, join as join12, relative as relative3, resolve as resolve10 } from "path";
|
|
61546
61947
|
function walkDirectory(dir) {
|
|
61547
|
-
if (!
|
|
61948
|
+
if (!existsSync21(dir))
|
|
61548
61949
|
return [];
|
|
61549
61950
|
const results = [];
|
|
61550
|
-
const entries =
|
|
61951
|
+
const entries = readdirSync4(dir);
|
|
61551
61952
|
for (const entry of entries) {
|
|
61552
|
-
const fullPath =
|
|
61953
|
+
const fullPath = join12(dir, entry);
|
|
61553
61954
|
const stat = statSync7(fullPath);
|
|
61554
61955
|
if (stat.isDirectory()) {
|
|
61555
61956
|
results.push(...walkDirectory(fullPath));
|
|
@@ -61559,6 +61960,136 @@ function walkDirectory(dir) {
|
|
|
61559
61960
|
}
|
|
61560
61961
|
return results;
|
|
61561
61962
|
}
|
|
61963
|
+
function isIgnoredModulePath(relPath) {
|
|
61964
|
+
const normalized = relPath.replace(/\\/g, "/");
|
|
61965
|
+
return normalized.startsWith("node_modules/") || normalized.includes("/node_modules/") || normalized.startsWith(".git/") || normalized.startsWith("dist/") || normalized.startsWith(".actiondock/") || normalized.endsWith(".test.ts") || normalized.endsWith(".test.js") || normalized.endsWith(".test.tsx") || normalized.endsWith(".test.jsx") || normalized.endsWith(".spec.ts") || normalized.endsWith(".spec.js") || normalized.endsWith(".spec.tsx") || normalized.endsWith(".spec.jsx") || normalized.endsWith(".d.ts");
|
|
61966
|
+
}
|
|
61967
|
+
function extractRelativeImports(source) {
|
|
61968
|
+
const stripped = source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "");
|
|
61969
|
+
const specifiers = new Set;
|
|
61970
|
+
const fromRegex = /\bfrom\s*["'`]([^"'`]+)["'`]/g;
|
|
61971
|
+
let match;
|
|
61972
|
+
while ((match = fromRegex.exec(stripped)) !== null) {
|
|
61973
|
+
const spec = match[1].trim();
|
|
61974
|
+
if (spec.startsWith("./") || spec.startsWith("../")) {
|
|
61975
|
+
specifiers.add(spec);
|
|
61976
|
+
}
|
|
61977
|
+
}
|
|
61978
|
+
const importRegex = /\bimport\s*(?:\(\s*)?["'`]([^"'`]+)["'`]/g;
|
|
61979
|
+
while ((match = importRegex.exec(stripped)) !== null) {
|
|
61980
|
+
const spec = match[1].trim();
|
|
61981
|
+
if (spec.startsWith("./") || spec.startsWith("../")) {
|
|
61982
|
+
specifiers.add(spec);
|
|
61983
|
+
}
|
|
61984
|
+
}
|
|
61985
|
+
const requireRegex = /\brequire\s*\(\s*["'`]([^"'`]+)["'`]/g;
|
|
61986
|
+
while ((match = requireRegex.exec(stripped)) !== null) {
|
|
61987
|
+
const spec = match[1].trim();
|
|
61988
|
+
if (spec.startsWith("./") || spec.startsWith("../")) {
|
|
61989
|
+
specifiers.add(spec);
|
|
61990
|
+
}
|
|
61991
|
+
}
|
|
61992
|
+
return Array.from(specifiers);
|
|
61993
|
+
}
|
|
61994
|
+
var CANDIDATE_EXTENSIONS2 = [
|
|
61995
|
+
"",
|
|
61996
|
+
".ts",
|
|
61997
|
+
".tsx",
|
|
61998
|
+
".js",
|
|
61999
|
+
".jsx",
|
|
62000
|
+
".mjs",
|
|
62001
|
+
".cjs",
|
|
62002
|
+
".mts",
|
|
62003
|
+
".cts",
|
|
62004
|
+
".json"
|
|
62005
|
+
];
|
|
62006
|
+
function resolveLocalModulePath(baseDir, specifier) {
|
|
62007
|
+
const candidate = resolve10(baseDir, specifier);
|
|
62008
|
+
if (existsSync21(candidate)) {
|
|
62009
|
+
try {
|
|
62010
|
+
if (statSync7(candidate).isFile()) {
|
|
62011
|
+
return candidate;
|
|
62012
|
+
}
|
|
62013
|
+
} catch {}
|
|
62014
|
+
}
|
|
62015
|
+
if (candidate.endsWith(".js")) {
|
|
62016
|
+
const tsPath = candidate.slice(0, -3) + ".ts";
|
|
62017
|
+
if (existsSync21(tsPath))
|
|
62018
|
+
return tsPath;
|
|
62019
|
+
const tsxPath = candidate.slice(0, -3) + ".tsx";
|
|
62020
|
+
if (existsSync21(tsxPath))
|
|
62021
|
+
return tsxPath;
|
|
62022
|
+
} else if (candidate.endsWith(".mjs")) {
|
|
62023
|
+
const mtsPath = candidate.slice(0, -4) + ".mts";
|
|
62024
|
+
if (existsSync21(mtsPath))
|
|
62025
|
+
return mtsPath;
|
|
62026
|
+
} else if (candidate.endsWith(".cjs")) {
|
|
62027
|
+
const ctsPath = candidate.slice(0, -4) + ".cts";
|
|
62028
|
+
if (existsSync21(ctsPath))
|
|
62029
|
+
return ctsPath;
|
|
62030
|
+
}
|
|
62031
|
+
for (const ext of CANDIDATE_EXTENSIONS2) {
|
|
62032
|
+
if (!ext)
|
|
62033
|
+
continue;
|
|
62034
|
+
const withExt = candidate + ext;
|
|
62035
|
+
if (existsSync21(withExt)) {
|
|
62036
|
+
try {
|
|
62037
|
+
if (statSync7(withExt).isFile()) {
|
|
62038
|
+
return withExt;
|
|
62039
|
+
}
|
|
62040
|
+
} catch {}
|
|
62041
|
+
}
|
|
62042
|
+
}
|
|
62043
|
+
if (existsSync21(candidate)) {
|
|
62044
|
+
try {
|
|
62045
|
+
if (statSync7(candidate).isDirectory()) {
|
|
62046
|
+
for (const ext of [".ts", ".tsx", ".js", ".mjs", ".json"]) {
|
|
62047
|
+
const indexFile = join12(candidate, `index${ext}`);
|
|
62048
|
+
if (existsSync21(indexFile)) {
|
|
62049
|
+
return indexFile;
|
|
62050
|
+
}
|
|
62051
|
+
}
|
|
62052
|
+
}
|
|
62053
|
+
} catch {}
|
|
62054
|
+
}
|
|
62055
|
+
return null;
|
|
62056
|
+
}
|
|
62057
|
+
function traceLocalModuleDependencies(entryFiles, projectRoot) {
|
|
62058
|
+
const visited = new Set;
|
|
62059
|
+
const modules = new Set;
|
|
62060
|
+
const queue = [...entryFiles];
|
|
62061
|
+
while (queue.length > 0) {
|
|
62062
|
+
const current = queue.shift();
|
|
62063
|
+
if (visited.has(current))
|
|
62064
|
+
continue;
|
|
62065
|
+
visited.add(current);
|
|
62066
|
+
const relToRoot = relative3(projectRoot, current);
|
|
62067
|
+
if (relToRoot.startsWith("..") || isAbsolute2(relToRoot)) {
|
|
62068
|
+
continue;
|
|
62069
|
+
}
|
|
62070
|
+
let content = "";
|
|
62071
|
+
try {
|
|
62072
|
+
content = readFileSync9(current, "utf-8");
|
|
62073
|
+
} catch {
|
|
62074
|
+
continue;
|
|
62075
|
+
}
|
|
62076
|
+
const specifiers = extractRelativeImports(content);
|
|
62077
|
+
const dir = dirname7(current);
|
|
62078
|
+
for (const spec of specifiers) {
|
|
62079
|
+
const resolved = resolveLocalModulePath(dir, spec);
|
|
62080
|
+
if (resolved) {
|
|
62081
|
+
const rel = relative3(projectRoot, resolved);
|
|
62082
|
+
if (!rel.startsWith("..") && !isAbsolute2(rel) && !isIgnoredModulePath(rel)) {
|
|
62083
|
+
modules.add(resolved);
|
|
62084
|
+
if (!visited.has(resolved)) {
|
|
62085
|
+
queue.push(resolved);
|
|
62086
|
+
}
|
|
62087
|
+
}
|
|
62088
|
+
}
|
|
62089
|
+
}
|
|
62090
|
+
}
|
|
62091
|
+
return Array.from(modules);
|
|
62092
|
+
}
|
|
61562
62093
|
function parsePlaybookFile(filePath) {
|
|
61563
62094
|
try {
|
|
61564
62095
|
const content = readFileSync9(filePath, "utf-8");
|
|
@@ -61584,8 +62115,8 @@ function parsePlaybookFile(filePath) {
|
|
|
61584
62115
|
}
|
|
61585
62116
|
function loadProjectPlaybooks(projectRoot, playbooksDir = "playbooks") {
|
|
61586
62117
|
const map = new Map;
|
|
61587
|
-
const dir =
|
|
61588
|
-
if (!
|
|
62118
|
+
const dir = join12(projectRoot, playbooksDir);
|
|
62119
|
+
if (!existsSync21(dir))
|
|
61589
62120
|
return map;
|
|
61590
62121
|
const files = walkDirectory(dir).filter((f) => f.endsWith(".md"));
|
|
61591
62122
|
for (const file of files) {
|
|
@@ -61597,9 +62128,9 @@ function loadProjectPlaybooks(projectRoot, playbooksDir = "playbooks") {
|
|
|
61597
62128
|
return map;
|
|
61598
62129
|
}
|
|
61599
62130
|
function generateStaticManifest(projectRoot, actionsDir = "actions") {
|
|
61600
|
-
const dir =
|
|
62131
|
+
const dir = join12(projectRoot, actionsDir);
|
|
61601
62132
|
const actions = {};
|
|
61602
|
-
if (
|
|
62133
|
+
if (existsSync21(dir)) {
|
|
61603
62134
|
const files = walkDirectory(dir).filter((f) => (f.endsWith(".ts") || f.endsWith(".js")) && !f.endsWith(".d.ts") && !f.endsWith(".test.ts") && !f.endsWith(".spec.ts"));
|
|
61604
62135
|
for (const file of files) {
|
|
61605
62136
|
const relPath = relative3(projectRoot, file);
|
|
@@ -61637,8 +62168,8 @@ function generateStaticManifest(projectRoot, actionsDir = "actions") {
|
|
|
61637
62168
|
};
|
|
61638
62169
|
}
|
|
61639
62170
|
function extractExternalDependencies(projectRoot) {
|
|
61640
|
-
const pkgPath =
|
|
61641
|
-
if (!
|
|
62171
|
+
const pkgPath = join12(projectRoot, "package.json");
|
|
62172
|
+
if (!existsSync21(pkgPath))
|
|
61642
62173
|
return [];
|
|
61643
62174
|
try {
|
|
61644
62175
|
const raw = readFileSync9(pkgPath, "utf-8");
|
|
@@ -61730,14 +62261,34 @@ class BuildPlanner {
|
|
|
61730
62261
|
}
|
|
61731
62262
|
const resolvedActionIds = new Set;
|
|
61732
62263
|
const queue = Array.from(initialActionIds);
|
|
62264
|
+
const externalActionRoots = new Map;
|
|
62265
|
+
const externalActionEntries = new Map;
|
|
61733
62266
|
while (queue.length > 0) {
|
|
61734
62267
|
const currentId = queue.shift();
|
|
61735
62268
|
if (resolvedActionIds.has(currentId)) {
|
|
61736
62269
|
continue;
|
|
61737
62270
|
}
|
|
61738
|
-
|
|
62271
|
+
let entry = manifest.actions[currentId];
|
|
62272
|
+
let entryRoot = root;
|
|
61739
62273
|
if (!entry) {
|
|
61740
|
-
|
|
62274
|
+
try {
|
|
62275
|
+
const resolvedExternal = resolveActionProjectSync(currentId, root);
|
|
62276
|
+
if (resolvedExternal && existsSync21(resolvedExternal.projectRoot)) {
|
|
62277
|
+
const externalManifest = loadManifest(resolvedExternal.projectRoot);
|
|
62278
|
+
const externalEntry = externalManifest?.actions?.[resolvedExternal.actionId];
|
|
62279
|
+
if (externalEntry) {
|
|
62280
|
+
entry = externalEntry;
|
|
62281
|
+
entryRoot = resolvedExternal.projectRoot;
|
|
62282
|
+
}
|
|
62283
|
+
}
|
|
62284
|
+
} catch {}
|
|
62285
|
+
}
|
|
62286
|
+
if (!entry) {
|
|
62287
|
+
throw new PlannerError(`Action '${currentId}' referenced in dependency closure (uses) was not found in manifest or linked packages`, "MISSING_DEPENDENCY");
|
|
62288
|
+
}
|
|
62289
|
+
if (entryRoot !== root) {
|
|
62290
|
+
externalActionRoots.set(currentId, entryRoot);
|
|
62291
|
+
externalActionEntries.set(currentId, entry);
|
|
61741
62292
|
}
|
|
61742
62293
|
resolvedActionIds.add(currentId);
|
|
61743
62294
|
if (entry.uses && Array.isArray(entry.uses)) {
|
|
@@ -61757,9 +62308,13 @@ class BuildPlanner {
|
|
|
61757
62308
|
}
|
|
61758
62309
|
const actionDependencies = [];
|
|
61759
62310
|
for (const actId of resolvedActionIds) {
|
|
61760
|
-
const entry = manifest.actions[actId];
|
|
61761
|
-
const
|
|
61762
|
-
if (!
|
|
62311
|
+
const entry = manifest.actions[actId] || externalActionEntries.get(actId);
|
|
62312
|
+
const entryRoot = externalActionRoots.get(actId) || root;
|
|
62313
|
+
if (!entry) {
|
|
62314
|
+
throw new PlannerError(`Action '${actId}' entry not found`, "ENTRY_FILE_NOT_FOUND");
|
|
62315
|
+
}
|
|
62316
|
+
const resolvedPath = resolve10(entryRoot, entry.entry);
|
|
62317
|
+
if (!existsSync21(resolvedPath)) {
|
|
61763
62318
|
throw new PlannerError(`Action '${actId}' entry file not found on disk: ${entry.entry}`, "ENTRY_FILE_NOT_FOUND");
|
|
61764
62319
|
}
|
|
61765
62320
|
actionDependencies.push({
|
|
@@ -61776,6 +62331,50 @@ class BuildPlanner {
|
|
|
61776
62331
|
}
|
|
61777
62332
|
const modulesAndAssets = [];
|
|
61778
62333
|
const assetPathSet = new Set;
|
|
62334
|
+
const modulePathSet = new Set;
|
|
62335
|
+
const actionPathSet = new Set(actionDependencies.map((a) => a.resolvedPath));
|
|
62336
|
+
const rootActionsMap = new Map;
|
|
62337
|
+
for (const act of actionDependencies) {
|
|
62338
|
+
const actRoot = externalActionRoots.get(act.id) || root;
|
|
62339
|
+
if (!rootActionsMap.has(actRoot)) {
|
|
62340
|
+
rootActionsMap.set(actRoot, []);
|
|
62341
|
+
}
|
|
62342
|
+
rootActionsMap.get(actRoot).push(act.resolvedPath);
|
|
62343
|
+
}
|
|
62344
|
+
for (const [actRoot, files] of rootActionsMap) {
|
|
62345
|
+
const tracedModulePaths = traceLocalModuleDependencies(files, actRoot);
|
|
62346
|
+
for (const modPath of tracedModulePaths) {
|
|
62347
|
+
if (!actionPathSet.has(modPath)) {
|
|
62348
|
+
const rel = relative3(actRoot, modPath).replace(/\\/g, "/");
|
|
62349
|
+
if (!modulePathSet.has(rel) && !isIgnoredModulePath(rel)) {
|
|
62350
|
+
modulePathSet.add(rel);
|
|
62351
|
+
modulesAndAssets.push({
|
|
62352
|
+
path: rel,
|
|
62353
|
+
resolvedPath: modPath,
|
|
62354
|
+
type: "module"
|
|
62355
|
+
});
|
|
62356
|
+
}
|
|
62357
|
+
}
|
|
62358
|
+
}
|
|
62359
|
+
}
|
|
62360
|
+
const isSelective = Boolean(options?.actions && options.actions.length > 0) || Boolean(options?.playbooks && options.playbooks.length > 0);
|
|
62361
|
+
if (!isSelective) {
|
|
62362
|
+
const defaultLibDir = join12(root, "lib");
|
|
62363
|
+
if (existsSync21(defaultLibDir)) {
|
|
62364
|
+
const libFiles = walkDirectory(defaultLibDir);
|
|
62365
|
+
for (const file of libFiles) {
|
|
62366
|
+
const rel = relative3(root, file).replace(/\\/g, "/");
|
|
62367
|
+
if (!isIgnoredModulePath(rel) && !actionPathSet.has(file) && !modulePathSet.has(rel)) {
|
|
62368
|
+
modulePathSet.add(rel);
|
|
62369
|
+
modulesAndAssets.push({
|
|
62370
|
+
path: rel,
|
|
62371
|
+
resolvedPath: file,
|
|
62372
|
+
type: "module"
|
|
62373
|
+
});
|
|
62374
|
+
}
|
|
62375
|
+
}
|
|
62376
|
+
}
|
|
62377
|
+
}
|
|
61779
62378
|
if (manifest.assets && Array.isArray(manifest.assets)) {
|
|
61780
62379
|
for (const assetRel of manifest.assets) {
|
|
61781
62380
|
if (!assetPathSet.has(assetRel)) {
|
|
@@ -61788,8 +62387,8 @@ class BuildPlanner {
|
|
|
61788
62387
|
}
|
|
61789
62388
|
}
|
|
61790
62389
|
}
|
|
61791
|
-
const defaultAssetsDir =
|
|
61792
|
-
if (
|
|
62390
|
+
const defaultAssetsDir = join12(root, "assets");
|
|
62391
|
+
if (existsSync21(defaultAssetsDir)) {
|
|
61793
62392
|
const assetFiles = walkDirectory(defaultAssetsDir);
|
|
61794
62393
|
for (const file of assetFiles) {
|
|
61795
62394
|
const rel = relative3(root, file);
|
|
@@ -61811,16 +62410,16 @@ class BuildPlanner {
|
|
|
61811
62410
|
type: "playbook"
|
|
61812
62411
|
});
|
|
61813
62412
|
}
|
|
61814
|
-
const configPath =
|
|
61815
|
-
if (
|
|
62413
|
+
const configPath = join12(root, "actiondock.json");
|
|
62414
|
+
if (existsSync21(configPath)) {
|
|
61816
62415
|
modulesAndAssets.push({
|
|
61817
62416
|
path: "actiondock.json",
|
|
61818
62417
|
resolvedPath: configPath,
|
|
61819
62418
|
type: "config"
|
|
61820
62419
|
});
|
|
61821
62420
|
}
|
|
61822
|
-
const manifestPath =
|
|
61823
|
-
if (
|
|
62421
|
+
const manifestPath = join12(root, "actiondock.manifest.json");
|
|
62422
|
+
if (existsSync21(manifestPath)) {
|
|
61824
62423
|
modulesAndAssets.push({
|
|
61825
62424
|
path: "actiondock.manifest.json",
|
|
61826
62425
|
resolvedPath: manifestPath,
|
|
@@ -61868,14 +62467,14 @@ async function buildProject(options) {
|
|
|
61868
62467
|
if (plan.actions.length === 0) {
|
|
61869
62468
|
throw new BuilderError("No actions resolved for standalone compilation");
|
|
61870
62469
|
}
|
|
61871
|
-
const buildDir =
|
|
62470
|
+
const buildDir = join13(root, ".actiondock", ".build");
|
|
61872
62471
|
mkdirSync7(buildDir, { recursive: true });
|
|
61873
62472
|
const entryCode = generateStandaloneEntrypoint(plan.packageId, plan.version, plan.description, plan.actions.map((a) => ({ id: a.id, filePath: a.resolvedPath })), plan.configDefs);
|
|
61874
62473
|
const entryFileName = `entry-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.ts`;
|
|
61875
|
-
const entryPath =
|
|
62474
|
+
const entryPath = join13(buildDir, entryFileName);
|
|
61876
62475
|
writeFileSync8(entryPath, entryCode, "utf-8");
|
|
61877
62476
|
const binaryName = getPackageSlug(plan.packageId);
|
|
61878
|
-
const defaultOutfile =
|
|
62477
|
+
const defaultOutfile = join13(root, "dist", binaryName);
|
|
61879
62478
|
const outfile = resolve11(options.outfile || defaultOutfile);
|
|
61880
62479
|
try {
|
|
61881
62480
|
const result = await BunCompiler.compile({
|
|
@@ -61898,23 +62497,23 @@ async function buildProject(options) {
|
|
|
61898
62497
|
actions: plan.actions.map((a) => a.id)
|
|
61899
62498
|
};
|
|
61900
62499
|
} finally {
|
|
61901
|
-
if (
|
|
62500
|
+
if (existsSync22(entryPath)) {
|
|
61902
62501
|
rmSync(entryPath, { force: true });
|
|
61903
62502
|
}
|
|
61904
62503
|
}
|
|
61905
62504
|
}
|
|
61906
62505
|
// ../builder/src/exporter.ts
|
|
61907
|
-
import { copyFileSync, existsSync as
|
|
61908
|
-
import { basename as basename8, dirname as dirname9, join as
|
|
62506
|
+
import { copyFileSync, existsSync as existsSync23, mkdirSync as mkdirSync8, readFileSync as readFileSync11, readdirSync as readdirSync6, rmSync as rmSync2, statSync as statSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
62507
|
+
import { basename as basename8, dirname as dirname9, join as join15, relative as relative5, resolve as resolve12 } from "path";
|
|
61909
62508
|
|
|
61910
62509
|
// ../builder/src/archive.ts
|
|
61911
|
-
import { readdirSync as
|
|
62510
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync10, statSync as statSync8, writeFileSync as writeFileSync9 } from "fs";
|
|
61912
62511
|
import { deflateRawSync, gzipSync } from "zlib";
|
|
61913
|
-
import { basename as basename7, join as
|
|
62512
|
+
import { basename as basename7, join as join14, relative as relative4, sep } from "path";
|
|
61914
62513
|
function collectEntries(dir, baseDir = dir) {
|
|
61915
62514
|
const entries = [];
|
|
61916
|
-
for (const name of
|
|
61917
|
-
const fullPath =
|
|
62515
|
+
for (const name of readdirSync5(dir).sort()) {
|
|
62516
|
+
const fullPath = join14(dir, name);
|
|
61918
62517
|
const stat = statSync8(fullPath);
|
|
61919
62518
|
if (stat.isDirectory()) {
|
|
61920
62519
|
entries.push({ relPath: relative4(baseDir, fullPath).split(sep).join("/"), isDir: true });
|
|
@@ -61959,9 +62558,9 @@ function createZipArchive(dir, outPath) {
|
|
|
61959
62558
|
for (const entry of entries) {
|
|
61960
62559
|
const name = `${rootName}/${entry.relPath}${entry.isDir ? "/" : ""}`;
|
|
61961
62560
|
const nameBuf = Buffer.from(name, "utf8");
|
|
61962
|
-
const stat = statSync8(
|
|
62561
|
+
const stat = statSync8(join14(dir, entry.relPath));
|
|
61963
62562
|
const { date, time } = dosDateTime(stat.mtimeMs);
|
|
61964
|
-
const content = entry.isDir ? Buffer.alloc(0) : readFileSync10(
|
|
62563
|
+
const content = entry.isDir ? Buffer.alloc(0) : readFileSync10(join14(dir, entry.relPath));
|
|
61965
62564
|
let method = 0;
|
|
61966
62565
|
let payload = content;
|
|
61967
62566
|
if (!entry.isDir && content.length > 0) {
|
|
@@ -62067,7 +62666,7 @@ function createTarGzArchive(dir, outPath) {
|
|
|
62067
62666
|
const chunks = [];
|
|
62068
62667
|
for (const entry of entries) {
|
|
62069
62668
|
const path = `${rootName}/${entry.relPath}`;
|
|
62070
|
-
const fullPath =
|
|
62669
|
+
const fullPath = join14(dir, entry.relPath);
|
|
62071
62670
|
const stat = statSync8(fullPath);
|
|
62072
62671
|
const content = entry.isDir ? Buffer.alloc(0) : readFileSync10(fullPath);
|
|
62073
62672
|
chunks.push(tarHeader(path, content.length, Math.floor(stat.mtimeMs / 1000), entry.isDir));
|
|
@@ -62081,12 +62680,12 @@ function createTarGzArchive(dir, outPath) {
|
|
|
62081
62680
|
|
|
62082
62681
|
// ../builder/src/exporter.ts
|
|
62083
62682
|
function scanRelativeFiles(dir, baseDir = dir) {
|
|
62084
|
-
if (!
|
|
62683
|
+
if (!existsSync23(dir))
|
|
62085
62684
|
return [];
|
|
62086
62685
|
const results = [];
|
|
62087
|
-
const entries =
|
|
62686
|
+
const entries = readdirSync6(dir);
|
|
62088
62687
|
for (const entry of entries) {
|
|
62089
|
-
const fullPath =
|
|
62688
|
+
const fullPath = join15(dir, entry);
|
|
62090
62689
|
const stat = statSync9(fullPath);
|
|
62091
62690
|
if (stat.isDirectory()) {
|
|
62092
62691
|
results.push(...scanRelativeFiles(fullPath, baseDir));
|
|
@@ -62100,8 +62699,8 @@ function createArchive(skillDir, format) {
|
|
|
62100
62699
|
const parentDir = dirname9(skillDir);
|
|
62101
62700
|
const folderName = basename8(skillDir);
|
|
62102
62701
|
const archiveName = `${folderName}.${format === "tar.gz" ? "tar.gz" : "zip"}`;
|
|
62103
|
-
const archivePath =
|
|
62104
|
-
if (
|
|
62702
|
+
const archivePath = join15(parentDir, archiveName);
|
|
62703
|
+
if (existsSync23(archivePath)) {
|
|
62105
62704
|
rmSync2(archivePath, { force: true });
|
|
62106
62705
|
}
|
|
62107
62706
|
try {
|
|
@@ -62115,6 +62714,74 @@ function createArchive(skillDir, format) {
|
|
|
62115
62714
|
}
|
|
62116
62715
|
return archivePath;
|
|
62117
62716
|
}
|
|
62717
|
+
function findExistingSingleSkillMd(projectRoot, explicitPath, pkgSlug) {
|
|
62718
|
+
if (explicitPath && existsSync23(explicitPath)) {
|
|
62719
|
+
try {
|
|
62720
|
+
if (statSync9(explicitPath).isFile())
|
|
62721
|
+
return resolve12(explicitPath);
|
|
62722
|
+
} catch {}
|
|
62723
|
+
}
|
|
62724
|
+
const candidates = [
|
|
62725
|
+
join15(projectRoot, "SKILL.md"),
|
|
62726
|
+
join15(projectRoot, "skill.md"),
|
|
62727
|
+
join15(projectRoot, "skills", "SKILL.md"),
|
|
62728
|
+
join15(projectRoot, "skills", "skill.md")
|
|
62729
|
+
];
|
|
62730
|
+
if (pkgSlug) {
|
|
62731
|
+
candidates.push(join15(projectRoot, "skills", pkgSlug, "SKILL.md"), join15(projectRoot, "skills", pkgSlug, "skill.md"));
|
|
62732
|
+
}
|
|
62733
|
+
for (const candidate of candidates) {
|
|
62734
|
+
if (existsSync23(candidate)) {
|
|
62735
|
+
try {
|
|
62736
|
+
if (statSync9(candidate).isFile())
|
|
62737
|
+
return resolve12(candidate);
|
|
62738
|
+
} catch {}
|
|
62739
|
+
}
|
|
62740
|
+
}
|
|
62741
|
+
return;
|
|
62742
|
+
}
|
|
62743
|
+
function findExistingCompositeSkillMd(options) {
|
|
62744
|
+
if (options.skillMdPath && existsSync23(options.skillMdPath)) {
|
|
62745
|
+
try {
|
|
62746
|
+
if (statSync9(options.skillMdPath).isFile())
|
|
62747
|
+
return resolve12(options.skillMdPath);
|
|
62748
|
+
} catch {}
|
|
62749
|
+
}
|
|
62750
|
+
const bundleSlug = getPackageSlug(options.bundleName);
|
|
62751
|
+
const searchDirs = new Set;
|
|
62752
|
+
if (options.workspaceRoot && existsSync23(options.workspaceRoot)) {
|
|
62753
|
+
searchDirs.add(resolve12(options.workspaceRoot));
|
|
62754
|
+
}
|
|
62755
|
+
searchDirs.add(process.cwd());
|
|
62756
|
+
for (const root of options.projectRoots) {
|
|
62757
|
+
const absRoot = resolve12(root);
|
|
62758
|
+
const parentDir = dirname9(absRoot);
|
|
62759
|
+
searchDirs.add(parentDir);
|
|
62760
|
+
searchDirs.add(dirname9(parentDir));
|
|
62761
|
+
}
|
|
62762
|
+
const candidateRelativePaths = [
|
|
62763
|
+
join15("skills", options.bundleName, "SKILL.md"),
|
|
62764
|
+
join15("skills", bundleSlug, "SKILL.md"),
|
|
62765
|
+
join15("skills", "SKILL.md"),
|
|
62766
|
+
"SKILL.md",
|
|
62767
|
+
join15("skills", options.bundleName, "skill.md"),
|
|
62768
|
+
join15("skills", bundleSlug, "skill.md"),
|
|
62769
|
+
join15("skills", "skill.md"),
|
|
62770
|
+
"skill.md"
|
|
62771
|
+
];
|
|
62772
|
+
for (const dir of searchDirs) {
|
|
62773
|
+
for (const rel of candidateRelativePaths) {
|
|
62774
|
+
const fullPath = join15(dir, rel);
|
|
62775
|
+
if (existsSync23(fullPath)) {
|
|
62776
|
+
try {
|
|
62777
|
+
if (statSync9(fullPath).isFile())
|
|
62778
|
+
return fullPath;
|
|
62779
|
+
} catch {}
|
|
62780
|
+
}
|
|
62781
|
+
}
|
|
62782
|
+
}
|
|
62783
|
+
return;
|
|
62784
|
+
}
|
|
62118
62785
|
|
|
62119
62786
|
class SkillExporter {
|
|
62120
62787
|
async export(options) {
|
|
@@ -62132,10 +62799,10 @@ class SkillExporter {
|
|
|
62132
62799
|
const pkgSlug = getPackageSlug(plan.packageId);
|
|
62133
62800
|
const targetSuffix = mode === "standalone" && target !== "host" && target !== "bun" ? `-${target}` : "";
|
|
62134
62801
|
const defaultFolderName = `${pkgSlug}-skill${targetSuffix}`;
|
|
62135
|
-
const defaultSkillDir =
|
|
62802
|
+
const defaultSkillDir = join15(root, "dist", defaultFolderName);
|
|
62136
62803
|
const skillDir = resolve12(options.outDir || defaultSkillDir);
|
|
62137
62804
|
mkdirSync8(skillDir, { recursive: true });
|
|
62138
|
-
const playbooksDestDir =
|
|
62805
|
+
const playbooksDestDir = join15(skillDir, "playbooks");
|
|
62139
62806
|
if (plan.playbooks.length > 0) {
|
|
62140
62807
|
mkdirSync8(playbooksDestDir, { recursive: true });
|
|
62141
62808
|
}
|
|
@@ -62148,14 +62815,19 @@ class SkillExporter {
|
|
|
62148
62815
|
playbooksDir: "playbooks",
|
|
62149
62816
|
config: plan.configDefs
|
|
62150
62817
|
};
|
|
62818
|
+
let usedExistingSkillMd;
|
|
62151
62819
|
if (mode === "source") {
|
|
62152
|
-
const
|
|
62153
|
-
|
|
62154
|
-
|
|
62155
|
-
|
|
62156
|
-
|
|
62157
|
-
|
|
62158
|
-
|
|
62820
|
+
const existingSkill = !options.skipSkillMd ? findExistingSingleSkillMd(root, options.skillMdPath, pkgSlug) : undefined;
|
|
62821
|
+
if (existingSkill) {
|
|
62822
|
+
usedExistingSkillMd = existingSkill;
|
|
62823
|
+
const destSkillMd = join15(skillDir, "SKILL.md");
|
|
62824
|
+
if (resolve12(existingSkill) !== resolve12(destSkillMd)) {
|
|
62825
|
+
copyFileSync(existingSkill, destSkillMd);
|
|
62826
|
+
}
|
|
62827
|
+
} else if (!options.skipSkillMd) {
|
|
62828
|
+
const skillMd = generateSourceSkillMd(configForTemplates, plan.actions, plan.playbooks);
|
|
62829
|
+
writeFileSync10(join15(skillDir, "SKILL.md"), skillMd, "utf-8");
|
|
62830
|
+
}
|
|
62159
62831
|
const manifestActions = {};
|
|
62160
62832
|
for (const a of plan.actions) {
|
|
62161
62833
|
manifestActions[a.id] = {
|
|
@@ -62167,13 +62839,19 @@ class SkillExporter {
|
|
|
62167
62839
|
tags: a.tags,
|
|
62168
62840
|
annotations: a.annotations
|
|
62169
62841
|
};
|
|
62842
|
+
if (a.id.includes("/")) {
|
|
62843
|
+
const shortId = a.id.slice(a.id.lastIndexOf("/") + 1);
|
|
62844
|
+
if (!manifestActions[shortId]) {
|
|
62845
|
+
manifestActions[shortId] = manifestActions[a.id];
|
|
62846
|
+
}
|
|
62847
|
+
}
|
|
62170
62848
|
}
|
|
62171
62849
|
const exportedManifest = {
|
|
62172
62850
|
schemaVersion: 1,
|
|
62173
62851
|
actions: manifestActions,
|
|
62174
62852
|
assets: plan.assets
|
|
62175
62853
|
};
|
|
62176
|
-
writeFileSync10(
|
|
62854
|
+
writeFileSync10(join15(skillDir, "actiondock.manifest.json"), JSON.stringify(exportedManifest, null, 2) + `
|
|
62177
62855
|
`, "utf-8");
|
|
62178
62856
|
const exportedConfig = {
|
|
62179
62857
|
id: plan.packageId,
|
|
@@ -62184,11 +62862,11 @@ class SkillExporter {
|
|
|
62184
62862
|
playbooksDir: "playbooks",
|
|
62185
62863
|
config: plan.configDefs
|
|
62186
62864
|
};
|
|
62187
|
-
writeFileSync10(
|
|
62865
|
+
writeFileSync10(join15(skillDir, "actiondock.json"), JSON.stringify(exportedConfig, null, 2) + `
|
|
62188
62866
|
`, "utf-8");
|
|
62189
|
-
const projectPkgPath =
|
|
62867
|
+
const projectPkgPath = join15(root, "package.json");
|
|
62190
62868
|
let exportedPkg;
|
|
62191
|
-
if (
|
|
62869
|
+
if (existsSync23(projectPkgPath)) {
|
|
62192
62870
|
try {
|
|
62193
62871
|
const raw = readFileSync11(projectPkgPath, "utf-8");
|
|
62194
62872
|
const parsed = JSON.parse(raw);
|
|
@@ -62220,42 +62898,42 @@ class SkillExporter {
|
|
|
62220
62898
|
dependencies: { "@actiondock/sdk": "^2.0.0" }
|
|
62221
62899
|
};
|
|
62222
62900
|
}
|
|
62223
|
-
writeFileSync10(
|
|
62901
|
+
writeFileSync10(join15(skillDir, "package.json"), JSON.stringify(exportedPkg, null, 2) + `
|
|
62224
62902
|
`, "utf-8");
|
|
62225
|
-
const tsconfigPath =
|
|
62226
|
-
if (
|
|
62227
|
-
copyFileSync(tsconfigPath,
|
|
62903
|
+
const tsconfigPath = join15(root, "tsconfig.json");
|
|
62904
|
+
if (existsSync23(tsconfigPath)) {
|
|
62905
|
+
copyFileSync(tsconfigPath, join15(skillDir, "tsconfig.json"));
|
|
62228
62906
|
}
|
|
62229
62907
|
for (const act of plan.actions) {
|
|
62230
|
-
if (
|
|
62231
|
-
const destFile =
|
|
62908
|
+
if (existsSync23(act.resolvedPath)) {
|
|
62909
|
+
const destFile = join15(skillDir, act.entry);
|
|
62232
62910
|
mkdirSync8(dirname9(destFile), { recursive: true });
|
|
62233
62911
|
copyFileSync(act.resolvedPath, destFile);
|
|
62234
62912
|
}
|
|
62235
62913
|
}
|
|
62236
62914
|
for (const dep of plan.dependencies.modulesAndAssets) {
|
|
62237
|
-
if (dep.type === "asset" &&
|
|
62238
|
-
const destAsset =
|
|
62915
|
+
if ((dep.type === "asset" || dep.type === "module") && existsSync23(dep.resolvedPath)) {
|
|
62916
|
+
const destAsset = join15(skillDir, dep.path);
|
|
62239
62917
|
mkdirSync8(dirname9(destAsset), { recursive: true });
|
|
62240
62918
|
copyFileSync(dep.resolvedPath, destAsset);
|
|
62241
62919
|
}
|
|
62242
62920
|
}
|
|
62243
62921
|
for (const pb of plan.playbooks) {
|
|
62244
|
-
if (
|
|
62245
|
-
const destPb =
|
|
62922
|
+
if (existsSync23(pb.filePath)) {
|
|
62923
|
+
const destPb = join15(playbooksDestDir, basename8(pb.filePath));
|
|
62246
62924
|
copyFileSync(pb.filePath, destPb);
|
|
62247
62925
|
}
|
|
62248
62926
|
}
|
|
62249
62927
|
} else {
|
|
62250
|
-
const binDir =
|
|
62928
|
+
const binDir = join15(skillDir, "bin");
|
|
62251
62929
|
mkdirSync8(binDir, { recursive: true });
|
|
62252
62930
|
const binaryName = pkgSlug;
|
|
62253
|
-
const binaryPath =
|
|
62254
|
-
const buildDir =
|
|
62931
|
+
const binaryPath = join15(binDir, binaryName);
|
|
62932
|
+
const buildDir = join15(root, ".actiondock", ".build");
|
|
62255
62933
|
mkdirSync8(buildDir, { recursive: true });
|
|
62256
62934
|
const entryCode = generateStandaloneEntrypoint(plan.packageId, plan.version, plan.description, plan.actions.map((a) => ({ id: a.id, filePath: a.resolvedPath })), plan.configDefs);
|
|
62257
62935
|
const entryFileName = `entry-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.ts`;
|
|
62258
|
-
const entryPath =
|
|
62936
|
+
const entryPath = join15(buildDir, entryFileName);
|
|
62259
62937
|
writeFileSync10(entryPath, entryCode, "utf-8");
|
|
62260
62938
|
let compileRes;
|
|
62261
62939
|
try {
|
|
@@ -62271,29 +62949,31 @@ class SkillExporter {
|
|
|
62271
62949
|
actions: plan.actions.map((a) => a.id)
|
|
62272
62950
|
});
|
|
62273
62951
|
} finally {
|
|
62274
|
-
if (
|
|
62952
|
+
if (existsSync23(entryPath)) {
|
|
62275
62953
|
rmSync2(entryPath, { force: true });
|
|
62276
62954
|
}
|
|
62277
62955
|
}
|
|
62278
62956
|
const actualBinaryName = basename8(compileRes.executablePath);
|
|
62279
|
-
const
|
|
62280
|
-
|
|
62281
|
-
|
|
62282
|
-
|
|
62283
|
-
|
|
62284
|
-
|
|
62285
|
-
|
|
62286
|
-
})
|
|
62287
|
-
|
|
62957
|
+
const existingSkill = !options.skipSkillMd ? findExistingSingleSkillMd(root, options.skillMdPath, pkgSlug) : undefined;
|
|
62958
|
+
if (existingSkill) {
|
|
62959
|
+
usedExistingSkillMd = existingSkill;
|
|
62960
|
+
const destSkillMd = join15(skillDir, "SKILL.md");
|
|
62961
|
+
if (resolve12(existingSkill) !== resolve12(destSkillMd)) {
|
|
62962
|
+
copyFileSync(existingSkill, destSkillMd);
|
|
62963
|
+
}
|
|
62964
|
+
} else if (!options.skipSkillMd) {
|
|
62965
|
+
const skillMd = generateStandaloneSkillMd(configForTemplates, plan.actions, plan.playbooks, `./bin/${actualBinaryName}`);
|
|
62966
|
+
writeFileSync10(join15(skillDir, "SKILL.md"), skillMd, "utf-8");
|
|
62967
|
+
}
|
|
62288
62968
|
for (const pb of plan.playbooks) {
|
|
62289
|
-
if (
|
|
62290
|
-
const destPb =
|
|
62969
|
+
if (existsSync23(pb.filePath)) {
|
|
62970
|
+
const destPb = join15(playbooksDestDir, basename8(pb.filePath));
|
|
62291
62971
|
copyFileSync(pb.filePath, destPb);
|
|
62292
62972
|
}
|
|
62293
62973
|
}
|
|
62294
62974
|
for (const dep of plan.dependencies.modulesAndAssets) {
|
|
62295
|
-
if (dep.type === "asset" &&
|
|
62296
|
-
const destAsset =
|
|
62975
|
+
if (dep.type === "asset" && existsSync23(dep.resolvedPath)) {
|
|
62976
|
+
const destAsset = join15(skillDir, dep.path);
|
|
62297
62977
|
mkdirSync8(dirname9(destAsset), { recursive: true });
|
|
62298
62978
|
copyFileSync(dep.resolvedPath, destAsset);
|
|
62299
62979
|
}
|
|
@@ -62321,9 +63001,134 @@ class SkillExporter {
|
|
|
62321
63001
|
playbooksCount: plan.playbooks.length,
|
|
62322
63002
|
actions: plan.actions.map((a) => a.id),
|
|
62323
63003
|
playbooks: plan.playbooks.map((p) => p.id),
|
|
62324
|
-
files
|
|
63004
|
+
files,
|
|
63005
|
+
usedExistingSkillMd
|
|
63006
|
+
};
|
|
63007
|
+
}
|
|
63008
|
+
async exportBatch(options) {
|
|
63009
|
+
if (!options.projectRoots || options.projectRoots.length === 0) {
|
|
63010
|
+
throw new BuilderError("No project roots provided for batch skill export.");
|
|
63011
|
+
}
|
|
63012
|
+
const results = [];
|
|
63013
|
+
const baseOutDir = resolve12(options.outDir || join15(process.cwd(), "dist", "skills"));
|
|
63014
|
+
mkdirSync8(baseOutDir, { recursive: true });
|
|
63015
|
+
const usedDirNames = new Set;
|
|
63016
|
+
for (const projectRoot of options.projectRoots) {
|
|
63017
|
+
const config = loadProjectConfig(projectRoot);
|
|
63018
|
+
let pkgSlug = getPackageSlug(config.id);
|
|
63019
|
+
if (usedDirNames.has(pkgSlug)) {
|
|
63020
|
+
pkgSlug = config.id.replace(/[^a-zA-Z0-9-_]/g, "-").replace(/^-+|-+$/g, "");
|
|
63021
|
+
}
|
|
63022
|
+
usedDirNames.add(pkgSlug);
|
|
63023
|
+
const pkgOutDir = join15(baseOutDir, `${pkgSlug}-skill`);
|
|
63024
|
+
const res = await this.export({
|
|
63025
|
+
...options,
|
|
63026
|
+
projectRoot,
|
|
63027
|
+
outDir: pkgOutDir
|
|
63028
|
+
});
|
|
63029
|
+
results.push(res);
|
|
63030
|
+
}
|
|
63031
|
+
const totalActions = results.reduce((sum, r) => sum + r.actionsCount, 0);
|
|
63032
|
+
const totalPlaybooks = results.reduce((sum, r) => sum + r.playbooksCount, 0);
|
|
63033
|
+
return {
|
|
63034
|
+
results,
|
|
63035
|
+
outDir: baseOutDir,
|
|
63036
|
+
totalActions,
|
|
63037
|
+
totalPlaybooks
|
|
63038
|
+
};
|
|
63039
|
+
}
|
|
63040
|
+
static async exportBatch(options) {
|
|
63041
|
+
const exporter = new SkillExporter;
|
|
63042
|
+
return exporter.exportBatch(options);
|
|
63043
|
+
}
|
|
63044
|
+
async exportComposite(options) {
|
|
63045
|
+
if (!options.projectRoots || options.projectRoots.length === 0) {
|
|
63046
|
+
throw new BuilderError("No project roots provided for composite skill export.");
|
|
63047
|
+
}
|
|
63048
|
+
if (!options.bundleName || !options.bundleName.trim()) {
|
|
63049
|
+
throw new BuilderError("bundleName is required for composite skill export.");
|
|
63050
|
+
}
|
|
63051
|
+
const bundleSlug = getPackageSlug(options.bundleName);
|
|
63052
|
+
const defaultSkillDir = join15(process.cwd(), "dist", `${bundleSlug}-skill`);
|
|
63053
|
+
const skillDir = resolve12(options.outDir || defaultSkillDir);
|
|
63054
|
+
mkdirSync8(skillDir, { recursive: true });
|
|
63055
|
+
const packagesDestDir = join15(skillDir, "packages");
|
|
63056
|
+
mkdirSync8(packagesDestDir, { recursive: true });
|
|
63057
|
+
const packageInfos = [];
|
|
63058
|
+
const packageSummaries = [];
|
|
63059
|
+
const usedDirNames = new Set;
|
|
63060
|
+
for (const projectRoot of options.projectRoots) {
|
|
63061
|
+
const config = loadProjectConfig(projectRoot);
|
|
63062
|
+
let pkgSlug = getPackageSlug(config.id);
|
|
63063
|
+
if (usedDirNames.has(pkgSlug)) {
|
|
63064
|
+
pkgSlug = config.id.replace(/[^a-zA-Z0-9-_]/g, "-").replace(/^-+|-+$/g, "");
|
|
63065
|
+
}
|
|
63066
|
+
usedDirNames.add(pkgSlug);
|
|
63067
|
+
const destPkgDir = join15(packagesDestDir, pkgSlug);
|
|
63068
|
+
const singleExport = await this.export({
|
|
63069
|
+
projectRoot,
|
|
63070
|
+
outDir: destPkgDir,
|
|
63071
|
+
archive: false,
|
|
63072
|
+
skipSkillMd: true
|
|
63073
|
+
});
|
|
63074
|
+
const manifest = loadManifest(destPkgDir) || loadManifest(projectRoot);
|
|
63075
|
+
const playbooks = loadPlaybooks(projectRoot, config.playbooksDir);
|
|
63076
|
+
const actionEntries = singleExport.actions.map((actId) => ({
|
|
63077
|
+
id: actId,
|
|
63078
|
+
description: manifest?.actions?.[actId]?.description
|
|
63079
|
+
}));
|
|
63080
|
+
packageInfos.push({
|
|
63081
|
+
config,
|
|
63082
|
+
actions: actionEntries,
|
|
63083
|
+
playbooks: Array.from(playbooks.values()),
|
|
63084
|
+
packageDir: pkgSlug
|
|
63085
|
+
});
|
|
63086
|
+
packageSummaries.push({
|
|
63087
|
+
packageId: config.id,
|
|
63088
|
+
actions: singleExport.actions,
|
|
63089
|
+
playbooks: singleExport.playbooks
|
|
63090
|
+
});
|
|
63091
|
+
}
|
|
63092
|
+
const existingSkillPath = findExistingCompositeSkillMd(options);
|
|
63093
|
+
if (existingSkillPath) {
|
|
63094
|
+
const destSkillMdPath = join15(skillDir, "SKILL.md");
|
|
63095
|
+
if (resolve12(existingSkillPath) !== resolve12(destSkillMdPath)) {
|
|
63096
|
+
copyFileSync(existingSkillPath, destSkillMdPath);
|
|
63097
|
+
}
|
|
63098
|
+
} else {
|
|
63099
|
+
const description = options.description || `ActionDock \u590D\u5408\u6280\u80FD\u5957\u4EF6\uFF0C\u805A\u5408 ${packageInfos.map((p) => p.config.name).join("\u3001")}`;
|
|
63100
|
+
const compositeSkillMd = generateCompositeSkillMd(options.bundleName, description, packageInfos);
|
|
63101
|
+
writeFileSync10(join15(skillDir, "SKILL.md"), compositeSkillMd, "utf-8");
|
|
63102
|
+
}
|
|
63103
|
+
let archivePath;
|
|
63104
|
+
if (options.archive) {
|
|
63105
|
+
let format = "zip";
|
|
63106
|
+
if (options.archiveFormat === "tar.gz" || options.archive === "tar.gz") {
|
|
63107
|
+
format = "tar.gz";
|
|
63108
|
+
} else if (options.archiveFormat === "zip" || options.archive === "zip") {
|
|
63109
|
+
format = "zip";
|
|
63110
|
+
}
|
|
63111
|
+
archivePath = createArchive(skillDir, format);
|
|
63112
|
+
}
|
|
63113
|
+
const files = scanRelativeFiles(skillDir);
|
|
63114
|
+
const totalActions = packageSummaries.reduce((sum, p) => sum + p.actions.length, 0);
|
|
63115
|
+
const totalPlaybooks = packageSummaries.reduce((sum, p) => sum + p.playbooks.length, 0);
|
|
63116
|
+
return {
|
|
63117
|
+
bundleName: options.bundleName,
|
|
63118
|
+
skillDir,
|
|
63119
|
+
archivePath,
|
|
63120
|
+
packagesCount: packageInfos.length,
|
|
63121
|
+
actionsCount: totalActions,
|
|
63122
|
+
playbooksCount: totalPlaybooks,
|
|
63123
|
+
packages: packageSummaries,
|
|
63124
|
+
files,
|
|
63125
|
+
usedExistingSkillMd: existingSkillPath
|
|
62325
63126
|
};
|
|
62326
63127
|
}
|
|
63128
|
+
static async exportComposite(options) {
|
|
63129
|
+
const exporter = new SkillExporter;
|
|
63130
|
+
return exporter.exportComposite(options);
|
|
63131
|
+
}
|
|
62327
63132
|
static async export(options) {
|
|
62328
63133
|
const exporter = new SkillExporter;
|
|
62329
63134
|
return exporter.export(options);
|
|
@@ -62332,6 +63137,12 @@ class SkillExporter {
|
|
|
62332
63137
|
async function exportSkill(options) {
|
|
62333
63138
|
return SkillExporter.export(options);
|
|
62334
63139
|
}
|
|
63140
|
+
async function exportSkillBatch(options) {
|
|
63141
|
+
return SkillExporter.exportBatch(options);
|
|
63142
|
+
}
|
|
63143
|
+
async function exportCompositeSkill(options) {
|
|
63144
|
+
return SkillExporter.exportComposite(options);
|
|
63145
|
+
}
|
|
62335
63146
|
// src/commands/build.ts
|
|
62336
63147
|
function registerBuildCommand(program) {
|
|
62337
63148
|
program.command("build").description("Build project actions into a single standalone executable").option("-P, --package <id>", "Target package ID or path").option("-t, --target <target>", "Target compilation platform (e.g. bun, linux-x64, darwin-arm64, windows-x64)").option("-o, --out <path>", "Output executable path").option("-a, --actions <actions...>", "Only build specific action(s) into the standalone binary").option("-m, --minify", "Minify bundled JavaScript (default: true)", true).option("--no-minify", "Disable JavaScript minification").option("--bytecode", "Compile JavaScript to bytecode for faster startup (default: true)", true).option("--no-bytecode", "Disable bytecode compilation").action(async (options) => {
|
|
@@ -62847,19 +63658,109 @@ function registerDoctorCommand(program) {
|
|
|
62847
63658
|
}
|
|
62848
63659
|
|
|
62849
63660
|
// src/commands/export.ts
|
|
63661
|
+
import { existsSync as existsSync24 } from "fs";
|
|
63662
|
+
import { basename as basename9 } from "path";
|
|
63663
|
+
function parseListOption2(val, prev = []) {
|
|
63664
|
+
const parts = val.split(",").map((s) => s.trim()).filter(Boolean);
|
|
63665
|
+
return [...prev, ...parts];
|
|
63666
|
+
}
|
|
62850
63667
|
function registerExportCommand(program) {
|
|
62851
63668
|
const exportCmd = program.command("export").description("Export project artifacts");
|
|
62852
|
-
exportCmd.command("skill").description("Export Skill directory for AI Agents (default: source skill; use -s/--standalone for pre-built standalone binary)").option("-P, --package <id
|
|
62853
|
-
const
|
|
62854
|
-
if (
|
|
62855
|
-
|
|
62856
|
-
|
|
63669
|
+
exportCmd.command("skill").description("Export Skill directory for AI Agents (default: source skill; use -s/--standalone for pre-built standalone binary)").option("-P, --package <id...>", "Target package ID(s) or path(s) (can be specified multiple times or comma-separated)", parseListOption2, []).option("--workspace", "Export all packages discovered in current workspace").option("--all", "Export all linked packages from global registry").option("--bundle [name]", "Export multiple packages as a unified composite Skill bundle (defaults to workspace directory name if omitted)").option("-s, --standalone", "Export pre-compiled standalone binary skill (for environments without ActionDock runtime)").option("-t, --target <target>", "Target compilation platform for standalone mode (e.g. host, linux-x64, darwin-arm64, windows-x64)").option("-o, --out <path>", "Output skill directory").option("-p, --playbook <playbooks...>", "Only export specific playbook(s) and their dependent actions (Playbook-driven minimal export)").option("-a, --actions <actions...>", "Only export specific action(s)").option("-m, --minify", "Minify bundled JavaScript in standalone mode (default: true)", true).option("--no-minify", "Disable JavaScript minification in standalone mode").option("--bytecode", "Compile JavaScript to bytecode in standalone mode (default: true)", true).option("--no-bytecode", "Disable bytecode compilation in standalone mode").option("-z, --archive", "Create a .zip archive of the exported skill").option("--skill-md <path>", "Use specified existing SKILL.md file instead of auto-generating").action(async (options) => {
|
|
63670
|
+
const isStandalone = Boolean(options.standalone);
|
|
63671
|
+
if (options.bundle && isStandalone) {
|
|
63672
|
+
throw new ExecutionError("Composite Skill export (--bundle) currently only supports source mode. Please remove --standalone to export as a composite workspace Skill.");
|
|
63673
|
+
}
|
|
63674
|
+
const sourceCount = (options.all ? 1 : 0) + (options.workspace ? 1 : 0) + (options.package && options.package.length > 0 ? 1 : 0);
|
|
63675
|
+
if (sourceCount > 1) {
|
|
63676
|
+
throw new ExecutionError("Options -P/--package, --workspace, and --all are mutually exclusive. Please specify only one package selection mode.");
|
|
63677
|
+
}
|
|
63678
|
+
let roots = [];
|
|
63679
|
+
if (options.all) {
|
|
63680
|
+
const linked = listLinkedPackages();
|
|
63681
|
+
roots = linked.map((p) => p.path).filter((p) => existsSync24(p));
|
|
63682
|
+
if (roots.length === 0) {
|
|
63683
|
+
throw new ExecutionError("No linked packages found in global registry.");
|
|
63684
|
+
}
|
|
63685
|
+
} else if (options.workspace) {
|
|
63686
|
+
const cwd = process.cwd();
|
|
63687
|
+
const discovered = discoverProjects(cwd);
|
|
63688
|
+
roots = discovered.length > 0 ? discovered : findProjectRoot(cwd) ? [findProjectRoot(cwd)] : [];
|
|
63689
|
+
if (roots.length === 0) {
|
|
63690
|
+
throw new ExecutionError(`No ActionDock packages found in workspace '${cwd}'.
|
|
63691
|
+
Make sure child directories contain actiondock.json.`);
|
|
63692
|
+
}
|
|
63693
|
+
} else if (options.package && options.package.length > 0) {
|
|
63694
|
+
for (const pkgIdOrPath of options.package) {
|
|
63695
|
+
const root = resolvePackageRoot(pkgIdOrPath);
|
|
63696
|
+
if (!root) {
|
|
63697
|
+
throw new ExecutionError(`Package '${pkgIdOrPath}' not found in linked packages or path`);
|
|
63698
|
+
}
|
|
63699
|
+
if (!roots.includes(root)) {
|
|
63700
|
+
roots.push(root);
|
|
63701
|
+
}
|
|
63702
|
+
}
|
|
63703
|
+
} else {
|
|
63704
|
+
const root = findProjectRoot();
|
|
63705
|
+
if (root) {
|
|
63706
|
+
roots.push(root);
|
|
63707
|
+
} else {
|
|
63708
|
+
throw new ExecutionError(`Not in an ActionDock project (actiondock.json not found).
|
|
63709
|
+
Please specify -P, --package <id>, --workspace, --all, or cd into a project directory.`);
|
|
62857
63710
|
}
|
|
62858
|
-
throw new ExecutionError(`Not in an ActionDock project (actiondock.json not found).
|
|
62859
|
-
Please specify -P, --package <id> or cd into a project directory.`);
|
|
62860
63711
|
}
|
|
62861
|
-
|
|
63712
|
+
if (roots.length > 1 && (options.actions || options.playbook)) {
|
|
63713
|
+
throw new ExecutionError("Filtering options (--actions, --playbook) can only be used when exporting a single package.");
|
|
63714
|
+
}
|
|
62862
63715
|
try {
|
|
63716
|
+
if (options.bundle !== undefined) {
|
|
63717
|
+
const bundleName = typeof options.bundle === "string" && options.bundle.trim() ? options.bundle.trim() : basename9(process.cwd());
|
|
63718
|
+
console.log(`Exporting composite Skill bundle '${bundleName}' (${roots.length} package${roots.length > 1 ? "s" : ""})...`);
|
|
63719
|
+
const result = await exportCompositeSkill({
|
|
63720
|
+
bundleName,
|
|
63721
|
+
projectRoots: roots,
|
|
63722
|
+
outDir: options.out,
|
|
63723
|
+
archive: options.archive,
|
|
63724
|
+
workspaceRoot: options.workspace ? process.cwd() : undefined,
|
|
63725
|
+
skillMdPath: options.skillMd
|
|
63726
|
+
});
|
|
63727
|
+
console.log(`[OK] Successfully exported Composite Skill: ${result.bundleName}`);
|
|
63728
|
+
console.log(` Packages: ${result.packagesCount}`);
|
|
63729
|
+
console.log(` Actions: ${result.actionsCount}`);
|
|
63730
|
+
console.log(` Playbooks: ${result.playbooksCount}`);
|
|
63731
|
+
console.log(` Skill Dir: ${result.skillDir}`);
|
|
63732
|
+
if (result.usedExistingSkillMd) {
|
|
63733
|
+
console.log(` SKILL.md: Reused existing file from ${result.usedExistingSkillMd}`);
|
|
63734
|
+
}
|
|
63735
|
+
if (result.archivePath) {
|
|
63736
|
+
console.log(` Archive: ${result.archivePath}`);
|
|
63737
|
+
}
|
|
63738
|
+
return;
|
|
63739
|
+
}
|
|
63740
|
+
if (roots.length > 1) {
|
|
63741
|
+
console.log(`Batch exporting ${roots.length} Skill packages...`);
|
|
63742
|
+
const batchRes = await exportSkillBatch({
|
|
63743
|
+
projectRoots: roots,
|
|
63744
|
+
mode: isStandalone ? "standalone" : "source",
|
|
63745
|
+
standalone: isStandalone,
|
|
63746
|
+
target: options.target,
|
|
63747
|
+
outDir: options.out,
|
|
63748
|
+
archive: options.archive,
|
|
63749
|
+
playbooks: options.playbook,
|
|
63750
|
+
actions: options.actions,
|
|
63751
|
+
minify: options.minify,
|
|
63752
|
+
bytecode: options.bytecode,
|
|
63753
|
+
skillMdPath: options.skillMd
|
|
63754
|
+
});
|
|
63755
|
+
console.log(`[OK] Successfully batch exported ${batchRes.results.length} Skill packages to: ${batchRes.outDir}`);
|
|
63756
|
+
for (const res of batchRes.results) {
|
|
63757
|
+
console.log(` - ${res.packageId} (v${res.version}): ${res.actionsCount} actions, ${res.playbooksCount} playbooks -> ${res.skillDir}`);
|
|
63758
|
+
}
|
|
63759
|
+
console.log(` Total Actions: ${batchRes.totalActions}`);
|
|
63760
|
+
console.log(` Total Playbooks: ${batchRes.totalPlaybooks}`);
|
|
63761
|
+
return;
|
|
63762
|
+
}
|
|
63763
|
+
const root = roots[0];
|
|
62863
63764
|
console.log(`Exporting ${isStandalone ? "standalone binary" : "source"} Skill artifact...`);
|
|
62864
63765
|
const result = await exportSkill({
|
|
62865
63766
|
projectRoot: root,
|
|
@@ -62871,13 +63772,17 @@ Please specify -P, --package <id> or cd into a project directory.`);
|
|
|
62871
63772
|
playbooks: options.playbook,
|
|
62872
63773
|
actions: options.actions,
|
|
62873
63774
|
minify: options.minify,
|
|
62874
|
-
bytecode: options.bytecode
|
|
63775
|
+
bytecode: options.bytecode,
|
|
63776
|
+
skillMdPath: options.skillMd
|
|
62875
63777
|
});
|
|
62876
63778
|
console.log(`[OK] Successfully exported ${result.mode === "standalone" ? "Standalone" : "Source"} Skill: ${result.packageId} (v${result.version})`);
|
|
62877
63779
|
console.log(` Mode: ${result.mode}${result.mode === "standalone" ? ` (target: ${result.target})` : ""}`);
|
|
62878
63780
|
console.log(` Actions: ${result.actionsCount}`);
|
|
62879
63781
|
console.log(` Playbooks: ${result.playbooksCount}`);
|
|
62880
63782
|
console.log(` Skill Dir: ${result.skillDir}`);
|
|
63783
|
+
if (result.usedExistingSkillMd) {
|
|
63784
|
+
console.log(` SKILL.md: Reused existing file from ${result.usedExistingSkillMd}`);
|
|
63785
|
+
}
|
|
62881
63786
|
if (result.archivePath) {
|
|
62882
63787
|
console.log(` Archive: ${result.archivePath}`);
|
|
62883
63788
|
}
|
|
@@ -62888,7 +63793,7 @@ Please specify -P, --package <id> or cd into a project directory.`);
|
|
|
62888
63793
|
}
|
|
62889
63794
|
|
|
62890
63795
|
// src/commands/info.ts
|
|
62891
|
-
import { existsSync as
|
|
63796
|
+
import { existsSync as existsSync25 } from "fs";
|
|
62892
63797
|
async function getProjectDetailInfo(root) {
|
|
62893
63798
|
const config = loadProjectConfig(root);
|
|
62894
63799
|
const manifest = loadManifest(root);
|
|
@@ -63164,7 +64069,7 @@ Declared Config Keys:`);
|
|
|
63164
64069
|
} catch {}
|
|
63165
64070
|
}
|
|
63166
64071
|
for (const pkg of linkedList) {
|
|
63167
|
-
if (!
|
|
64072
|
+
if (!existsSync25(pkg.path))
|
|
63168
64073
|
continue;
|
|
63169
64074
|
if (seenPaths.has(pkg.path))
|
|
63170
64075
|
continue;
|
|
@@ -63354,12 +64259,12 @@ function registerLinkCommands(program) {
|
|
|
63354
64259
|
|
|
63355
64260
|
// src/commands/mcp.ts
|
|
63356
64261
|
import { resolve as resolve13 } from "path";
|
|
63357
|
-
function
|
|
64262
|
+
function parseListOption3(val, prev = []) {
|
|
63358
64263
|
const parts = val.split(",").map((s) => s.trim()).filter(Boolean);
|
|
63359
64264
|
return [...prev, ...parts];
|
|
63360
64265
|
}
|
|
63361
64266
|
function registerMcpCommands2(program) {
|
|
63362
|
-
const mcpCommand = program.command("mcp").description("Model Context Protocol (MCP) server for ActionDock Actions (STDIO default)").option("-d, --dir <path>", "Project root directory or directories (can be specified multiple times or comma-separated)",
|
|
64267
|
+
const mcpCommand = program.command("mcp").description("Model Context Protocol (MCP) server for ActionDock Actions (STDIO default)").option("-d, --dir <path>", "Project root directory or directories (can be specified multiple times or comma-separated)", parseListOption3, []).option("--package <package-id>", "Specific linked package ID(s) to serve (can be specified multiple times or comma-separated)", parseListOption3, []).option("--all", "Serve all linked packages from global registry").option("--timeout <duration>", "Execution timeout (e.g. 30s, 5m, 500ms)").action(async (options) => {
|
|
63363
64268
|
let timeoutMs;
|
|
63364
64269
|
if (options.timeout) {
|
|
63365
64270
|
try {
|
|
@@ -63382,7 +64287,7 @@ function registerMcpCommands2(program) {
|
|
|
63382
64287
|
throw new ExecutionError(`Failed to start MCP STDIO server: ${err.message}`);
|
|
63383
64288
|
}
|
|
63384
64289
|
});
|
|
63385
|
-
mcpCommand.command("serve").description("Start the ActionDock MCP server over HTTP transport").option("-p, --port <port>", "Port to listen on (default: 5178)", "5178").option("-H, --host <host>", "Host address to bind to (default: 127.0.0.1)", "127.0.0.1").option("-t, --token <token>", "Authentication token for securing the endpoint (or set ACTIONDOCK_TOKEN)").option("--token-env <env>", "Environment variable name containing the authentication token").option("--allow-insecure-no-auth", "Allow non-loopback host binding without authentication token (INSECURE)").option("--cors-origin <origin>", "Allowed CORS origin (can be specified multiple times)", (val, prev = []) => [...prev, val], []).option("--max-body <size>", "Maximum allowed JSON request body size (e.g. 1mb, 500kb)", "1mb").option("-d, --dir <path>", "Project root directory or directories (can be specified multiple times or comma-separated)",
|
|
64290
|
+
mcpCommand.command("serve").description("Start the ActionDock MCP server over HTTP transport").option("-p, --port <port>", "Port to listen on (default: 5178)", "5178").option("-H, --host <host>", "Host address to bind to (default: 127.0.0.1)", "127.0.0.1").option("-t, --token <token>", "Authentication token for securing the endpoint (or set ACTIONDOCK_TOKEN)").option("--token-env <env>", "Environment variable name containing the authentication token").option("--allow-insecure-no-auth", "Allow non-loopback host binding without authentication token (INSECURE)").option("--cors-origin <origin>", "Allowed CORS origin (can be specified multiple times)", (val, prev = []) => [...prev, val], []).option("--max-body <size>", "Maximum allowed JSON request body size (e.g. 1mb, 500kb)", "1mb").option("-d, --dir <path>", "Project root directory or directories (can be specified multiple times or comma-separated)", parseListOption3, []).option("--package <package-id>", "Specific linked package ID(s) to serve (can be specified multiple times or comma-separated)", parseListOption3, []).option("--all", "Serve all linked packages from global registry").option("--timeout <duration>", "Execution timeout (e.g. 30s, 5m, 500ms)").action(async (options) => {
|
|
63386
64291
|
const port = parseInt(options.port, 10) || 5178;
|
|
63387
64292
|
const host = options.host || "127.0.0.1";
|
|
63388
64293
|
const token = options.token || (options.tokenEnv ? process.env[options.tokenEnv] : undefined) || process.env.ACTIONDOCK_TOKEN;
|
|
@@ -63477,7 +64382,7 @@ Stopping MCP HTTP server...`);
|
|
|
63477
64382
|
}
|
|
63478
64383
|
|
|
63479
64384
|
// src/commands/playbook.ts
|
|
63480
|
-
import { existsSync as
|
|
64385
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync9, writeFileSync as writeFileSync11 } from "fs";
|
|
63481
64386
|
import { dirname as dirname10, resolve as resolve14 } from "path";
|
|
63482
64387
|
function registerPlaybookCommands2(program) {
|
|
63483
64388
|
const pbCmd = program.command("playbook").description("Manage task Playbooks (Task SOPs for AI Agents)");
|
|
@@ -63589,7 +64494,7 @@ Run 'ad link' inside an Action package to register it.`
|
|
|
63589
64494
|
}
|
|
63590
64495
|
const aggregated = [];
|
|
63591
64496
|
for (const pkg of linkedList) {
|
|
63592
|
-
if (!
|
|
64497
|
+
if (!existsSync26(pkg.path))
|
|
63593
64498
|
continue;
|
|
63594
64499
|
try {
|
|
63595
64500
|
const config = loadProjectConfig(pkg.path);
|
|
@@ -63670,13 +64575,13 @@ Run 'ad link' inside an Action package to register it.`
|
|
|
63670
64575
|
try {
|
|
63671
64576
|
const config = loadProjectConfig(root);
|
|
63672
64577
|
const pbDir = resolve14(root, config.playbooksDir || "playbooks");
|
|
63673
|
-
if (!
|
|
64578
|
+
if (!existsSync26(pbDir)) {
|
|
63674
64579
|
mkdirSync9(pbDir, { recursive: true });
|
|
63675
64580
|
}
|
|
63676
64581
|
const cleanName = id.replace(/[^a-zA-Z0-9-_]/g, "-");
|
|
63677
64582
|
const targetRelFile = options.file || `${cleanName}.md`;
|
|
63678
64583
|
const targetFullFile = resolve14(pbDir, targetRelFile);
|
|
63679
|
-
if (
|
|
64584
|
+
if (existsSync26(targetFullFile)) {
|
|
63680
64585
|
throw new ExecutionError(`File '${targetFullFile}' already exists`);
|
|
63681
64586
|
}
|
|
63682
64587
|
mkdirSync9(dirname10(targetFullFile), { recursive: true });
|
|
@@ -63824,7 +64729,7 @@ This playbook provides task execution guidance for AI Agents.
|
|
|
63824
64729
|
throw new ArgumentError("Not in an ActionDock project, and no packages linked.");
|
|
63825
64730
|
}
|
|
63826
64731
|
for (const pkg of linkedList) {
|
|
63827
|
-
if (!
|
|
64732
|
+
if (!existsSync26(pkg.path))
|
|
63828
64733
|
continue;
|
|
63829
64734
|
try {
|
|
63830
64735
|
const config = loadProjectConfig(pkg.path);
|
|
@@ -64113,7 +65018,7 @@ Use 'ad profile use <name>' to switch or 'ad run <action> --profile <name>' to e
|
|
|
64113
65018
|
}
|
|
64114
65019
|
|
|
64115
65020
|
// src/commands/runs.ts
|
|
64116
|
-
import { existsSync as
|
|
65021
|
+
import { existsSync as existsSync27 } from "fs";
|
|
64117
65022
|
function printRunRecord(run) {
|
|
64118
65023
|
console.log(`Run: ${run.id}`);
|
|
64119
65024
|
console.log(`Action: ${run.actionId}`);
|
|
@@ -64220,7 +65125,7 @@ function registerRunsCommands2(program) {
|
|
|
64220
65125
|
}
|
|
64221
65126
|
let allRecords = [];
|
|
64222
65127
|
for (const pkg of linkedList) {
|
|
64223
|
-
if (!
|
|
65128
|
+
if (!existsSync27(pkg.path))
|
|
64224
65129
|
continue;
|
|
64225
65130
|
try {
|
|
64226
65131
|
const projConfig = loadProjectConfig(pkg.path);
|
|
@@ -64326,7 +65231,7 @@ function registerRunsCommands2(program) {
|
|
|
64326
65231
|
if (!foundRun) {
|
|
64327
65232
|
const linkedList = listLinkedPackages();
|
|
64328
65233
|
for (const pkg of linkedList) {
|
|
64329
|
-
if (!
|
|
65234
|
+
if (!existsSync27(pkg.path))
|
|
64330
65235
|
continue;
|
|
64331
65236
|
try {
|
|
64332
65237
|
const projConfig = loadProjectConfig(pkg.path);
|
|
@@ -64533,7 +65438,7 @@ Stopping ActionDock server...`);
|
|
|
64533
65438
|
}
|
|
64534
65439
|
|
|
64535
65440
|
// src/commands/state.ts
|
|
64536
|
-
import { existsSync as
|
|
65441
|
+
import { existsSync as existsSync28 } from "fs";
|
|
64537
65442
|
function getTargetRoot2(packageOption, keyHint) {
|
|
64538
65443
|
let targetPackage = packageOption;
|
|
64539
65444
|
let effectiveKey = keyHint || "";
|
|
@@ -64641,7 +65546,7 @@ function registerStateCommands2(program) {
|
|
|
64641
65546
|
}
|
|
64642
65547
|
const aggregated = [];
|
|
64643
65548
|
for (const pkg of linkedList) {
|
|
64644
|
-
if (!
|
|
65549
|
+
if (!existsSync28(pkg.path))
|
|
64645
65550
|
continue;
|
|
64646
65551
|
try {
|
|
64647
65552
|
const projConfig = loadProjectConfig(pkg.path);
|
|
@@ -64940,16 +65845,16 @@ function registerStateCommands2(program) {
|
|
|
64940
65845
|
|
|
64941
65846
|
// src/commands/test.ts
|
|
64942
65847
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
64943
|
-
import { existsSync as
|
|
64944
|
-
import { join as
|
|
65848
|
+
import { existsSync as existsSync29, readFileSync as readFileSync12 } from "fs";
|
|
65849
|
+
import { join as join16 } from "path";
|
|
64945
65850
|
function registerTestCommand(program) {
|
|
64946
65851
|
program.command("test [pattern]").description("Run project tests using configured test runner (node:test or bun test)").action((pattern) => {
|
|
64947
65852
|
const root = findProjectRoot();
|
|
64948
65853
|
const cwd = root || process.cwd();
|
|
64949
|
-
const pkgJsonPath =
|
|
65854
|
+
const pkgJsonPath = join16(cwd, "package.json");
|
|
64950
65855
|
let testCmd = "npm";
|
|
64951
65856
|
let testArgs = ["test"];
|
|
64952
|
-
if (
|
|
65857
|
+
if (existsSync29(pkgJsonPath)) {
|
|
64953
65858
|
try {
|
|
64954
65859
|
const pkg = JSON.parse(readFileSync12(pkgJsonPath, "utf-8"));
|
|
64955
65860
|
if (pkg.scripts?.test?.includes("bun test") && typeof globalThis.Bun !== "undefined") {
|
|
@@ -64993,7 +65898,7 @@ function applyCommonOptions(cmd) {
|
|
|
64993
65898
|
}
|
|
64994
65899
|
function createCliProgram() {
|
|
64995
65900
|
const program = new Command2;
|
|
64996
|
-
program.name("ad").description("ActionDock (ad) 2.0 - Toolchain for building and shipping standalone AI Agent Actions & Skills").version("2.0.
|
|
65901
|
+
program.name("ad").description("ActionDock (ad) 2.0 - Toolchain for building and shipping standalone AI Agent Actions & Skills").version("2.0.11", "-v, --version");
|
|
64997
65902
|
program.option("-V", "output the version number");
|
|
64998
65903
|
program.on("option:V", () => {
|
|
64999
65904
|
program._outputConfiguration.writeOut(`${program.version()}
|