@elevasis/sdk 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +784 -3192
- package/dist/index.d.ts +483 -331
- package/dist/types/worker/index.d.ts +2 -2
- package/package.json +3 -9
- package/reference/_navigation.md +2 -2
- package/reference/cli.mdx +2 -113
- package/reference/deployment/command-center.mdx +6 -6
- package/reference/deployment/index.mdx +1 -1
- package/reference/framework/index.mdx +10 -0
- package/reference/framework/project-structure.mdx +6 -7
- package/reference/framework/tutorial-system.mdx +2 -2
- package/reference/getting-started.mdx +1 -11
- package/reference/index.mdx +16 -1
- package/reference/platform-tools/index.mdx +3 -3
- package/reference/platform-tools/type-safety.mdx +2 -2
- package/reference/resources/index.mdx +6 -6
- package/reference/resources/patterns.mdx +2 -2
- package/reference/resources/types.mdx +1 -1
- package/reference/runtime.mdx +1 -1
- package/reference/templates/index.mdx +3 -3
- package/reference/troubleshooting.mdx +4 -4
- package/dist/templates.js +0 -2253
- package/dist/types/templates.d.ts +0 -2
package/dist/cli.cjs
CHANGED
|
@@ -6,6 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
9
12
|
var __commonJS = (cb, mod) => function __require() {
|
|
10
13
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
14
|
};
|
|
@@ -225,8 +228,8 @@ var require_main = __commonJS({
|
|
|
225
228
|
}
|
|
226
229
|
return null;
|
|
227
230
|
}
|
|
228
|
-
function _resolveHome(
|
|
229
|
-
return
|
|
231
|
+
function _resolveHome(envPath2) {
|
|
232
|
+
return envPath2[0] === "~" ? path.join(os2.homedir(), envPath2.slice(1)) : envPath2;
|
|
230
233
|
}
|
|
231
234
|
function _configVault(options2) {
|
|
232
235
|
const debug = Boolean(options2 && options2.debug);
|
|
@@ -6622,14 +6625,14 @@ var require_async_iterator = __commonJS({
|
|
|
6622
6625
|
};
|
|
6623
6626
|
}
|
|
6624
6627
|
function readAndResolve(iter) {
|
|
6625
|
-
var
|
|
6626
|
-
if (
|
|
6628
|
+
var resolve4 = iter[kLastResolve];
|
|
6629
|
+
if (resolve4 !== null) {
|
|
6627
6630
|
var data = iter[kStream].read();
|
|
6628
6631
|
if (data !== null) {
|
|
6629
6632
|
iter[kLastPromise] = null;
|
|
6630
6633
|
iter[kLastResolve] = null;
|
|
6631
6634
|
iter[kLastReject] = null;
|
|
6632
|
-
|
|
6635
|
+
resolve4(createIterResult(data, false));
|
|
6633
6636
|
}
|
|
6634
6637
|
}
|
|
6635
6638
|
}
|
|
@@ -6637,13 +6640,13 @@ var require_async_iterator = __commonJS({
|
|
|
6637
6640
|
process.nextTick(readAndResolve, iter);
|
|
6638
6641
|
}
|
|
6639
6642
|
function wrapForNext(lastPromise, iter) {
|
|
6640
|
-
return function(
|
|
6643
|
+
return function(resolve4, reject) {
|
|
6641
6644
|
lastPromise.then(function() {
|
|
6642
6645
|
if (iter[kEnded]) {
|
|
6643
|
-
|
|
6646
|
+
resolve4(createIterResult(void 0, true));
|
|
6644
6647
|
return;
|
|
6645
6648
|
}
|
|
6646
|
-
iter[kHandlePromise](
|
|
6649
|
+
iter[kHandlePromise](resolve4, reject);
|
|
6647
6650
|
}, reject);
|
|
6648
6651
|
};
|
|
6649
6652
|
}
|
|
@@ -6663,12 +6666,12 @@ var require_async_iterator = __commonJS({
|
|
|
6663
6666
|
return Promise.resolve(createIterResult(void 0, true));
|
|
6664
6667
|
}
|
|
6665
6668
|
if (this[kStream].destroyed) {
|
|
6666
|
-
return new Promise(function(
|
|
6669
|
+
return new Promise(function(resolve4, reject) {
|
|
6667
6670
|
process.nextTick(function() {
|
|
6668
6671
|
if (_this[kError]) {
|
|
6669
6672
|
reject(_this[kError]);
|
|
6670
6673
|
} else {
|
|
6671
|
-
|
|
6674
|
+
resolve4(createIterResult(void 0, true));
|
|
6672
6675
|
}
|
|
6673
6676
|
});
|
|
6674
6677
|
});
|
|
@@ -6691,13 +6694,13 @@ var require_async_iterator = __commonJS({
|
|
|
6691
6694
|
return this;
|
|
6692
6695
|
}), _defineProperty(_Object$setPrototypeO, "return", function _return() {
|
|
6693
6696
|
var _this2 = this;
|
|
6694
|
-
return new Promise(function(
|
|
6697
|
+
return new Promise(function(resolve4, reject) {
|
|
6695
6698
|
_this2[kStream].destroy(null, function(err) {
|
|
6696
6699
|
if (err) {
|
|
6697
6700
|
reject(err);
|
|
6698
6701
|
return;
|
|
6699
6702
|
}
|
|
6700
|
-
|
|
6703
|
+
resolve4(createIterResult(void 0, true));
|
|
6701
6704
|
});
|
|
6702
6705
|
});
|
|
6703
6706
|
}), _Object$setPrototypeO), AsyncIteratorPrototype);
|
|
@@ -6719,15 +6722,15 @@ var require_async_iterator = __commonJS({
|
|
|
6719
6722
|
value: stream._readableState.endEmitted,
|
|
6720
6723
|
writable: true
|
|
6721
6724
|
}), _defineProperty(_Object$create, kHandlePromise, {
|
|
6722
|
-
value: function value(
|
|
6725
|
+
value: function value(resolve4, reject) {
|
|
6723
6726
|
var data = iterator[kStream].read();
|
|
6724
6727
|
if (data) {
|
|
6725
6728
|
iterator[kLastPromise] = null;
|
|
6726
6729
|
iterator[kLastResolve] = null;
|
|
6727
6730
|
iterator[kLastReject] = null;
|
|
6728
|
-
|
|
6731
|
+
resolve4(createIterResult(data, false));
|
|
6729
6732
|
} else {
|
|
6730
|
-
iterator[kLastResolve] =
|
|
6733
|
+
iterator[kLastResolve] = resolve4;
|
|
6731
6734
|
iterator[kLastReject] = reject;
|
|
6732
6735
|
}
|
|
6733
6736
|
},
|
|
@@ -6746,12 +6749,12 @@ var require_async_iterator = __commonJS({
|
|
|
6746
6749
|
iterator[kError] = err;
|
|
6747
6750
|
return;
|
|
6748
6751
|
}
|
|
6749
|
-
var
|
|
6750
|
-
if (
|
|
6752
|
+
var resolve4 = iterator[kLastResolve];
|
|
6753
|
+
if (resolve4 !== null) {
|
|
6751
6754
|
iterator[kLastPromise] = null;
|
|
6752
6755
|
iterator[kLastResolve] = null;
|
|
6753
6756
|
iterator[kLastReject] = null;
|
|
6754
|
-
|
|
6757
|
+
resolve4(createIterResult(void 0, true));
|
|
6755
6758
|
}
|
|
6756
6759
|
iterator[kEnded] = true;
|
|
6757
6760
|
});
|
|
@@ -6766,7 +6769,7 @@ var require_async_iterator = __commonJS({
|
|
|
6766
6769
|
var require_from = __commonJS({
|
|
6767
6770
|
"../../node_modules/.pnpm/readable-stream@3.6.2/node_modules/readable-stream/lib/internal/streams/from.js"(exports2, module2) {
|
|
6768
6771
|
"use strict";
|
|
6769
|
-
function asyncGeneratorStep(gen,
|
|
6772
|
+
function asyncGeneratorStep(gen, resolve4, reject, _next, _throw, key, arg) {
|
|
6770
6773
|
try {
|
|
6771
6774
|
var info = gen[key](arg);
|
|
6772
6775
|
var value = info.value;
|
|
@@ -6775,7 +6778,7 @@ var require_from = __commonJS({
|
|
|
6775
6778
|
return;
|
|
6776
6779
|
}
|
|
6777
6780
|
if (info.done) {
|
|
6778
|
-
|
|
6781
|
+
resolve4(value);
|
|
6779
6782
|
} else {
|
|
6780
6783
|
Promise.resolve(value).then(_next, _throw);
|
|
6781
6784
|
}
|
|
@@ -6783,13 +6786,13 @@ var require_from = __commonJS({
|
|
|
6783
6786
|
function _asyncToGenerator(fn) {
|
|
6784
6787
|
return function() {
|
|
6785
6788
|
var self2 = this, args = arguments;
|
|
6786
|
-
return new Promise(function(
|
|
6789
|
+
return new Promise(function(resolve4, reject) {
|
|
6787
6790
|
var gen = fn.apply(self2, args);
|
|
6788
6791
|
function _next(value) {
|
|
6789
|
-
asyncGeneratorStep(gen,
|
|
6792
|
+
asyncGeneratorStep(gen, resolve4, reject, _next, _throw, "next", value);
|
|
6790
6793
|
}
|
|
6791
6794
|
function _throw(err) {
|
|
6792
|
-
asyncGeneratorStep(gen,
|
|
6795
|
+
asyncGeneratorStep(gen, resolve4, reject, _next, _throw, "throw", err);
|
|
6793
6796
|
}
|
|
6794
6797
|
_next(void 0);
|
|
6795
6798
|
});
|
|
@@ -26487,9 +26490,67 @@ var require_zod = __commonJS({
|
|
|
26487
26490
|
}
|
|
26488
26491
|
});
|
|
26489
26492
|
|
|
26493
|
+
// src/cli/config.ts
|
|
26494
|
+
var config_exports = {};
|
|
26495
|
+
__export(config_exports, {
|
|
26496
|
+
findEnvFile: () => findEnvFile,
|
|
26497
|
+
resolveApiKey: () => resolveApiKey,
|
|
26498
|
+
resolveApiUrl: () => resolveApiUrl,
|
|
26499
|
+
resolveEnvironment: () => resolveEnvironment
|
|
26500
|
+
});
|
|
26501
|
+
function resolveApiUrl(cliOverride, prod) {
|
|
26502
|
+
if (cliOverride) return cliOverride;
|
|
26503
|
+
if (prod) return PROD_API_URL;
|
|
26504
|
+
if (process.env.ELEVASIS_API_URL) return process.env.ELEVASIS_API_URL;
|
|
26505
|
+
if (process.env.NODE_ENV === "development") return DEV_API_URL;
|
|
26506
|
+
return PROD_API_URL;
|
|
26507
|
+
}
|
|
26508
|
+
function resolveEnvironment(prod) {
|
|
26509
|
+
if (prod) return "production";
|
|
26510
|
+
return process.env.NODE_ENV === "development" ? "development" : "production";
|
|
26511
|
+
}
|
|
26512
|
+
function resolveApiKey(prod) {
|
|
26513
|
+
if (!prod && process.env.NODE_ENV === "development") {
|
|
26514
|
+
return process.env.ELEVASIS_PLATFORM_KEY_DEV ?? process.env.ELEVASIS_PLATFORM_KEY ?? "";
|
|
26515
|
+
}
|
|
26516
|
+
return process.env.ELEVASIS_PLATFORM_KEY ?? "";
|
|
26517
|
+
}
|
|
26518
|
+
function findEnvFile(startDir) {
|
|
26519
|
+
const cwd = (0, import_path.resolve)(startDir ?? process.cwd());
|
|
26520
|
+
let dir = cwd;
|
|
26521
|
+
while (true) {
|
|
26522
|
+
const candidate = (0, import_path.resolve)(dir, ".env");
|
|
26523
|
+
if ((0, import_fs.existsSync)(candidate)) return candidate;
|
|
26524
|
+
const parent = (0, import_path.dirname)(dir);
|
|
26525
|
+
if (parent === dir) break;
|
|
26526
|
+
dir = parent;
|
|
26527
|
+
}
|
|
26528
|
+
dir = cwd;
|
|
26529
|
+
while (true) {
|
|
26530
|
+
if ((0, import_fs.existsSync)((0, import_path.resolve)(dir, "pnpm-workspace.yaml"))) {
|
|
26531
|
+
const candidate = (0, import_path.resolve)(dir, ".env");
|
|
26532
|
+
if ((0, import_fs.existsSync)(candidate)) return candidate;
|
|
26533
|
+
break;
|
|
26534
|
+
}
|
|
26535
|
+
const parent = (0, import_path.dirname)(dir);
|
|
26536
|
+
if (parent === dir) break;
|
|
26537
|
+
dir = parent;
|
|
26538
|
+
}
|
|
26539
|
+
return void 0;
|
|
26540
|
+
}
|
|
26541
|
+
var import_fs, import_path, DEV_API_URL, PROD_API_URL;
|
|
26542
|
+
var init_config = __esm({
|
|
26543
|
+
"src/cli/config.ts"() {
|
|
26544
|
+
"use strict";
|
|
26545
|
+
import_fs = require("fs");
|
|
26546
|
+
import_path = require("path");
|
|
26547
|
+
DEV_API_URL = "http://localhost:5170";
|
|
26548
|
+
PROD_API_URL = "https://api.elevasis.io";
|
|
26549
|
+
}
|
|
26550
|
+
});
|
|
26551
|
+
|
|
26490
26552
|
// src/cli/index.ts
|
|
26491
26553
|
var import_dotenv = __toESM(require_main(), 1);
|
|
26492
|
-
var import_path5 = require("path");
|
|
26493
26554
|
|
|
26494
26555
|
// ../../node_modules/.pnpm/commander@11.1.0/node_modules/commander/esm.mjs
|
|
26495
26556
|
var import_index = __toESM(require_commander(), 1);
|
|
@@ -27004,7 +27065,7 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
|
27004
27065
|
var source_default = chalk;
|
|
27005
27066
|
|
|
27006
27067
|
// src/cli/commands/check.ts
|
|
27007
|
-
var
|
|
27068
|
+
var import_path3 = require("path");
|
|
27008
27069
|
|
|
27009
27070
|
// ../../node_modules/.pnpm/ora@7.0.1/node_modules/ora/index.js
|
|
27010
27071
|
var import_node_process6 = __toESM(require("node:process"), 1);
|
|
@@ -27516,7 +27577,7 @@ function ora(options2) {
|
|
|
27516
27577
|
}
|
|
27517
27578
|
|
|
27518
27579
|
// src/cli/commands/deploy.ts
|
|
27519
|
-
var
|
|
27580
|
+
var import_path2 = require("path");
|
|
27520
27581
|
var import_promises = require("fs/promises");
|
|
27521
27582
|
var import_gray_matter = __toESM(require_gray_matter(), 1);
|
|
27522
27583
|
|
|
@@ -43774,28 +43835,11 @@ var ResourceRegistry = class {
|
|
|
43774
43835
|
}
|
|
43775
43836
|
};
|
|
43776
43837
|
|
|
43777
|
-
// src/cli/
|
|
43778
|
-
|
|
43779
|
-
var PROD_API_URL = "https://api.elevasis.io";
|
|
43780
|
-
function resolveApiUrl(cliOverride, prod) {
|
|
43781
|
-
if (cliOverride) return cliOverride;
|
|
43782
|
-
if (prod) return PROD_API_URL;
|
|
43783
|
-
if (process.env.ELEVASIS_API_URL) return process.env.ELEVASIS_API_URL;
|
|
43784
|
-
if (process.env.NODE_ENV === "development") return DEV_API_URL;
|
|
43785
|
-
return PROD_API_URL;
|
|
43786
|
-
}
|
|
43787
|
-
function resolveEnvironment(prod) {
|
|
43788
|
-
if (prod) return "production";
|
|
43789
|
-
return process.env.NODE_ENV === "development" ? "development" : "production";
|
|
43790
|
-
}
|
|
43791
|
-
function resolveApiKey(prod) {
|
|
43792
|
-
if (!prod && process.env.NODE_ENV === "development") {
|
|
43793
|
-
return process.env.ELEVASIS_PLATFORM_KEY_DEV ?? process.env.ELEVASIS_PLATFORM_KEY ?? "";
|
|
43794
|
-
}
|
|
43795
|
-
return process.env.ELEVASIS_PLATFORM_KEY ?? "";
|
|
43796
|
-
}
|
|
43838
|
+
// src/cli/commands/deploy.ts
|
|
43839
|
+
init_config();
|
|
43797
43840
|
|
|
43798
43841
|
// src/cli/api-client.ts
|
|
43842
|
+
init_config();
|
|
43799
43843
|
function getApiKey(apiUrl) {
|
|
43800
43844
|
const isProd = !apiUrl.includes("localhost");
|
|
43801
43845
|
const key = resolveApiKey(isProd);
|
|
@@ -43893,7 +43937,7 @@ function wrapAction(commandName, fn) {
|
|
|
43893
43937
|
// package.json
|
|
43894
43938
|
var package_default = {
|
|
43895
43939
|
name: "@elevasis/sdk",
|
|
43896
|
-
version: "1.0
|
|
43940
|
+
version: "1.1.0",
|
|
43897
43941
|
description: "SDK for building Elevasis organization resources",
|
|
43898
43942
|
type: "module",
|
|
43899
43943
|
bin: {
|
|
@@ -43907,10 +43951,6 @@ var package_default = {
|
|
|
43907
43951
|
"./worker": {
|
|
43908
43952
|
types: "./dist/types/worker/index.d.ts",
|
|
43909
43953
|
import: "./dist/worker/index.js"
|
|
43910
|
-
},
|
|
43911
|
-
"./templates": {
|
|
43912
|
-
types: "./dist/types/templates.d.ts",
|
|
43913
|
-
import: "./dist/templates.js"
|
|
43914
43954
|
}
|
|
43915
43955
|
},
|
|
43916
43956
|
files: [
|
|
@@ -43921,8 +43961,6 @@ var package_default = {
|
|
|
43921
43961
|
"dist/types/worker/platform.d.ts",
|
|
43922
43962
|
"dist/types/worker/adapters/",
|
|
43923
43963
|
"dist/cli.cjs",
|
|
43924
|
-
"dist/templates.js",
|
|
43925
|
-
"dist/types/templates.d.ts",
|
|
43926
43964
|
"reference/"
|
|
43927
43965
|
],
|
|
43928
43966
|
scripts: {
|
|
@@ -43958,13 +43996,13 @@ var SDK_VERSION = package_default.version;
|
|
|
43958
43996
|
|
|
43959
43997
|
// src/cli/commands/deploy.ts
|
|
43960
43998
|
function getEsbuild() {
|
|
43961
|
-
const consumerRequire = (0, import_module.createRequire)((0,
|
|
43999
|
+
const consumerRequire = (0, import_module.createRequire)((0, import_path2.resolve)(process.cwd(), "package.json"));
|
|
43962
44000
|
return consumerRequire("esbuild");
|
|
43963
44001
|
}
|
|
43964
44002
|
async function loadTsModule(filePath) {
|
|
43965
44003
|
const esbuild = getEsbuild();
|
|
43966
|
-
const absPath = (0,
|
|
43967
|
-
const tmpOut = (0,
|
|
44004
|
+
const absPath = (0, import_path2.resolve)(filePath);
|
|
44005
|
+
const tmpOut = (0, import_path2.resolve)(`.elevasis-tmp-${Date.now()}.mjs`);
|
|
43968
44006
|
try {
|
|
43969
44007
|
await esbuild.build({
|
|
43970
44008
|
entryPoints: [absPath],
|
|
@@ -44023,7 +44061,7 @@ function bumpVersion(current, type) {
|
|
|
44023
44061
|
}
|
|
44024
44062
|
var IGNORED_DOC_DIRS = /* @__PURE__ */ new Set([".archive"]);
|
|
44025
44063
|
async function scanDocumentation() {
|
|
44026
|
-
const docsDir = (0,
|
|
44064
|
+
const docsDir = (0, import_path2.resolve)("docs");
|
|
44027
44065
|
const files = [];
|
|
44028
44066
|
let totalSize = 0;
|
|
44029
44067
|
async function scan(dir, relPrefix) {
|
|
@@ -44034,7 +44072,7 @@ async function scanDocumentation() {
|
|
|
44034
44072
|
return;
|
|
44035
44073
|
}
|
|
44036
44074
|
for (const entry of entries) {
|
|
44037
|
-
const fullPath = (0,
|
|
44075
|
+
const fullPath = (0, import_path2.resolve)(dir, entry.name);
|
|
44038
44076
|
const relPath = relPrefix ? `${relPrefix}/${entry.name}` : entry.name;
|
|
44039
44077
|
if (entry.isDirectory()) {
|
|
44040
44078
|
if (IGNORED_DOC_DIRS.has(entry.name)) continue;
|
|
@@ -44121,21 +44159,12 @@ async function generateResourceMap(org) {
|
|
|
44121
44159
|
`**Total:** ${workflows.length + agents.length} resources (${workflows.length} workflows, ${agents.length} agents)`,
|
|
44122
44160
|
""
|
|
44123
44161
|
);
|
|
44124
|
-
await (0, import_promises.mkdir)((0,
|
|
44125
|
-
await (0, import_promises.writeFile)((0,
|
|
44162
|
+
await (0, import_promises.mkdir)((0, import_path2.resolve)("docs"), { recursive: true });
|
|
44163
|
+
await (0, import_promises.writeFile)((0, import_path2.resolve)("docs/resource-map.mdx"), lines.join("\n"), "utf-8");
|
|
44126
44164
|
}
|
|
44127
44165
|
async function generateProjectMap(org) {
|
|
44128
44166
|
const workflows = org.workflows ?? [];
|
|
44129
44167
|
const agents = org.agents ?? [];
|
|
44130
|
-
let templateVersion = "unknown";
|
|
44131
|
-
try {
|
|
44132
|
-
const cfg = await loadTsModule("elevasis.config.ts");
|
|
44133
|
-
const cfgObj = cfg.default ?? cfg;
|
|
44134
|
-
if (cfgObj?.templateVersion != null) {
|
|
44135
|
-
templateVersion = String(cfgObj.templateVersion);
|
|
44136
|
-
}
|
|
44137
|
-
} catch {
|
|
44138
|
-
}
|
|
44139
44168
|
const lastDeploy = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
44140
44169
|
const lines = [
|
|
44141
44170
|
"---",
|
|
@@ -44153,7 +44182,6 @@ async function generateProjectMap(org) {
|
|
|
44153
44182
|
"| Field | Value |",
|
|
44154
44183
|
"| --- | --- |",
|
|
44155
44184
|
`| SDK Version | ${SDK_VERSION} |`,
|
|
44156
|
-
`| Template Version | ${templateVersion} |`,
|
|
44157
44185
|
`| Last Deploy | ${lastDeploy} |`,
|
|
44158
44186
|
`| Resources | ${workflows.length} workflows, ${agents.length} agents |`,
|
|
44159
44187
|
""
|
|
@@ -44167,7 +44195,7 @@ async function generateProjectMap(org) {
|
|
|
44167
44195
|
"| --- | --- | --- | --- |"
|
|
44168
44196
|
);
|
|
44169
44197
|
try {
|
|
44170
|
-
const srcEntries = await (0, import_promises.readdir)((0,
|
|
44198
|
+
const srcEntries = await (0, import_promises.readdir)((0, import_path2.resolve)("src"), { withFileTypes: true });
|
|
44171
44199
|
const domainDirs = srcEntries.filter((e) => e.isDirectory());
|
|
44172
44200
|
if (domainDirs.length === 0) {
|
|
44173
44201
|
lines.push("| (none) | src/ | 0 | \u2014 |");
|
|
@@ -44233,10 +44261,10 @@ async function generateProjectMap(org) {
|
|
|
44233
44261
|
const relPath = relPrefix ? `${relPrefix}/${entry.name}` : entry.name;
|
|
44234
44262
|
if (entry.isDirectory()) {
|
|
44235
44263
|
if (IGNORED_DOC_DIRS.has(entry.name)) continue;
|
|
44236
|
-
await scanDocsDir((0,
|
|
44264
|
+
await scanDocsDir((0, import_path2.resolve)(dir, entry.name), relPath);
|
|
44237
44265
|
} else if (entry.isFile() && entry.name.endsWith(".mdx") && relPath !== "project-map.mdx" && relPath !== "resource-map.mdx") {
|
|
44238
44266
|
try {
|
|
44239
|
-
const raw = await (0, import_promises.readFile)((0,
|
|
44267
|
+
const raw = await (0, import_promises.readFile)((0, import_path2.resolve)(dir, entry.name), "utf-8");
|
|
44240
44268
|
const fmMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
44241
44269
|
let title = relPath;
|
|
44242
44270
|
let description = "";
|
|
@@ -44256,7 +44284,7 @@ async function generateProjectMap(org) {
|
|
|
44256
44284
|
}
|
|
44257
44285
|
}
|
|
44258
44286
|
}
|
|
44259
|
-
await scanDocsDir((0,
|
|
44287
|
+
await scanDocsDir((0, import_path2.resolve)("docs"), "");
|
|
44260
44288
|
docEntries.sort((a, b) => {
|
|
44261
44289
|
if (a.order !== b.order) return a.order - b.order;
|
|
44262
44290
|
return a.title.localeCompare(b.title);
|
|
@@ -44274,7 +44302,7 @@ async function generateProjectMap(org) {
|
|
|
44274
44302
|
lines.push("");
|
|
44275
44303
|
lines.push("## SDK Reference", "");
|
|
44276
44304
|
try {
|
|
44277
|
-
const navPath = (0,
|
|
44305
|
+
const navPath = (0, import_path2.resolve)("node_modules/@elevasis/sdk/reference/_navigation.md");
|
|
44278
44306
|
const navContent = await (0, import_promises.readFile)(navPath, "utf-8");
|
|
44279
44307
|
const navLines = navContent.split(/\r?\n/);
|
|
44280
44308
|
const categories = [];
|
|
@@ -44314,7 +44342,7 @@ async function generateProjectMap(org) {
|
|
|
44314
44342
|
}
|
|
44315
44343
|
lines.push("## Command and Rules System", "", "### Commands", "");
|
|
44316
44344
|
try {
|
|
44317
|
-
const cmdEntries = await (0, import_promises.readdir)((0,
|
|
44345
|
+
const cmdEntries = await (0, import_promises.readdir)((0, import_path2.resolve)(".claude/commands"), { withFileTypes: true });
|
|
44318
44346
|
const cmdFiles = cmdEntries.filter((e) => e.isFile() && e.name.endsWith(".md"));
|
|
44319
44347
|
if (cmdFiles.length === 0) {
|
|
44320
44348
|
lines.push("No commands found.", "");
|
|
@@ -44324,7 +44352,7 @@ async function generateProjectMap(org) {
|
|
|
44324
44352
|
const cmdName = f.name.replace(/\.md$/, "");
|
|
44325
44353
|
let purpose = "";
|
|
44326
44354
|
try {
|
|
44327
|
-
const raw = await (0, import_promises.readFile)((0,
|
|
44355
|
+
const raw = await (0, import_promises.readFile)((0, import_path2.resolve)(".claude/commands", f.name), "utf-8");
|
|
44328
44356
|
const goalMatch = raw.match(/\*\*Goal:\*\*\s*(.+)/);
|
|
44329
44357
|
if (goalMatch) {
|
|
44330
44358
|
purpose = goalMatch[1].trim();
|
|
@@ -44343,7 +44371,7 @@ async function generateProjectMap(org) {
|
|
|
44343
44371
|
}
|
|
44344
44372
|
lines.push("### Rules (auto-injected)", "");
|
|
44345
44373
|
try {
|
|
44346
|
-
const ruleEntries = await (0, import_promises.readdir)((0,
|
|
44374
|
+
const ruleEntries = await (0, import_promises.readdir)((0, import_path2.resolve)(".claude/rules"), { withFileTypes: true });
|
|
44347
44375
|
const ruleFiles = ruleEntries.filter((e) => e.isFile() && e.name.endsWith(".md"));
|
|
44348
44376
|
if (ruleFiles.length === 0) {
|
|
44349
44377
|
lines.push("No rules found.", "");
|
|
@@ -44353,7 +44381,7 @@ async function generateProjectMap(org) {
|
|
|
44353
44381
|
const ruleName = f.name.replace(/\.md$/, "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
44354
44382
|
let scope = "";
|
|
44355
44383
|
try {
|
|
44356
|
-
const raw = await (0, import_promises.readFile)((0,
|
|
44384
|
+
const raw = await (0, import_promises.readFile)((0, import_path2.resolve)(".claude/rules", f.name), "utf-8");
|
|
44357
44385
|
const fmMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
44358
44386
|
if (fmMatch) {
|
|
44359
44387
|
const descMatch = fmMatch[1].match(/^description:\s*(.+)$/m);
|
|
@@ -44374,14 +44402,14 @@ async function generateProjectMap(org) {
|
|
|
44374
44402
|
}
|
|
44375
44403
|
lines.push("### Skills", "");
|
|
44376
44404
|
try {
|
|
44377
|
-
const skillEntries = await (0, import_promises.readdir)((0,
|
|
44405
|
+
const skillEntries = await (0, import_promises.readdir)((0, import_path2.resolve)(".claude/skills"), { withFileTypes: true });
|
|
44378
44406
|
const skillDirs = skillEntries.filter((e) => e.isDirectory());
|
|
44379
44407
|
if (skillDirs.length === 0) {
|
|
44380
44408
|
lines.push("No skills found.", "");
|
|
44381
44409
|
} else {
|
|
44382
44410
|
lines.push("| Skill | File | Trigger |", "| --- | --- | --- |");
|
|
44383
44411
|
for (const d of skillDirs) {
|
|
44384
|
-
const skillFile = (0,
|
|
44412
|
+
const skillFile = (0, import_path2.resolve)(".claude/skills", d.name, "SKILL.md");
|
|
44385
44413
|
let trigger = "";
|
|
44386
44414
|
try {
|
|
44387
44415
|
const raw = await (0, import_promises.readFile)(skillFile, "utf-8");
|
|
@@ -44414,7 +44442,7 @@ async function generateProjectMap(org) {
|
|
|
44414
44442
|
return;
|
|
44415
44443
|
}
|
|
44416
44444
|
for (const entry of entries) {
|
|
44417
|
-
const fullPath = (0,
|
|
44445
|
+
const fullPath = (0, import_path2.resolve)(dir, entry.name);
|
|
44418
44446
|
const relPath = relPrefix ? `${relPrefix}/${entry.name}` : entry.name;
|
|
44419
44447
|
if (entry.isDirectory()) {
|
|
44420
44448
|
await scanMemory(fullPath, relPath);
|
|
@@ -44431,7 +44459,7 @@ async function generateProjectMap(org) {
|
|
|
44431
44459
|
}
|
|
44432
44460
|
}
|
|
44433
44461
|
}
|
|
44434
|
-
await scanMemory((0,
|
|
44462
|
+
await scanMemory((0, import_path2.resolve)(".claude/memory"), "");
|
|
44435
44463
|
if (memoryFiles.length === 0) {
|
|
44436
44464
|
lines.push("No memory files found.", "");
|
|
44437
44465
|
} else {
|
|
@@ -44448,7 +44476,8 @@ async function generateProjectMap(org) {
|
|
|
44448
44476
|
let apiKeySet = "no";
|
|
44449
44477
|
let nodeEnv = "not set";
|
|
44450
44478
|
try {
|
|
44451
|
-
const
|
|
44479
|
+
const { findEnvFile: findEnvFile2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
44480
|
+
const envContent = await (0, import_promises.readFile)(findEnvFile2() ?? (0, import_path2.resolve)(".env"), "utf-8");
|
|
44452
44481
|
const apiKeyMatch = envContent.match(/^ELEVASIS_PLATFORM_KEY=(.+)$/m);
|
|
44453
44482
|
if (apiKeyMatch && apiKeyMatch[1].trim()) apiKeySet = "yes";
|
|
44454
44483
|
const nodeEnvMatch = envContent.match(/^NODE_ENV=(.+)$/m);
|
|
@@ -44458,14 +44487,13 @@ async function generateProjectMap(org) {
|
|
|
44458
44487
|
lines.push(
|
|
44459
44488
|
"| Setting | Source | Value |",
|
|
44460
44489
|
"| --- | --- | --- |",
|
|
44461
|
-
`| Template Version | elevasis.config.ts | ${templateVersion} |`,
|
|
44462
44490
|
`| SDK Version | package.json | ${SDK_VERSION} |`,
|
|
44463
44491
|
`| API Key Set | .env | ${apiKeySet} |`,
|
|
44464
44492
|
`| Node Env | .env | ${nodeEnv} |`,
|
|
44465
44493
|
""
|
|
44466
44494
|
);
|
|
44467
|
-
await (0, import_promises.mkdir)((0,
|
|
44468
|
-
await (0, import_promises.writeFile)((0,
|
|
44495
|
+
await (0, import_promises.mkdir)((0, import_path2.resolve)("docs"), { recursive: true });
|
|
44496
|
+
await (0, import_promises.writeFile)((0, import_path2.resolve)("docs/project-map.mdx"), lines.join("\n"), "utf-8");
|
|
44469
44497
|
}
|
|
44470
44498
|
async function generateNavigationMap(docs) {
|
|
44471
44499
|
const excludedFiles = /* @__PURE__ */ new Set(["docs/navigation-map.mdx", "docs/project-map.mdx", "docs/resource-map.mdx"]);
|
|
@@ -44493,8 +44521,8 @@ async function generateNavigationMap(docs) {
|
|
|
44493
44521
|
lines.push(`| ${escapeMdx(doc.frontmatter.title)} | ${escapeMdx(doc.frontmatter.description)} | ${doc.path} |`);
|
|
44494
44522
|
}
|
|
44495
44523
|
lines.push("");
|
|
44496
|
-
await (0, import_promises.mkdir)((0,
|
|
44497
|
-
await (0, import_promises.writeFile)((0,
|
|
44524
|
+
await (0, import_promises.mkdir)((0, import_path2.resolve)("docs"), { recursive: true });
|
|
44525
|
+
await (0, import_promises.writeFile)((0, import_path2.resolve)("docs/navigation-map.mdx"), lines.join("\n"), "utf-8");
|
|
44498
44526
|
}
|
|
44499
44527
|
function registerDeployCommand(program3) {
|
|
44500
44528
|
program3.command("deploy").description(
|
|
@@ -44537,7 +44565,7 @@ function registerDeployCommand(program3) {
|
|
|
44537
44565
|
org = entryModule.default;
|
|
44538
44566
|
if (!org) {
|
|
44539
44567
|
validateSpinner.fail("Invalid entry: no default export found");
|
|
44540
|
-
console.error(source_default.gray(` Entry file: ${(0,
|
|
44568
|
+
console.error(source_default.gray(` Entry file: ${(0, import_path2.resolve)(entryPath)}`));
|
|
44541
44569
|
throw new Error("Invalid entry: no default export found");
|
|
44542
44570
|
}
|
|
44543
44571
|
new ResourceRegistry({ [orgName]: org });
|
|
@@ -44551,21 +44579,25 @@ function registerDeployCommand(program3) {
|
|
|
44551
44579
|
if (archivedCount > 0) {
|
|
44552
44580
|
console.log(source_default.gray(` Skipping ${archivedCount} archived resource${archivedCount !== 1 ? "s" : ""}`));
|
|
44553
44581
|
}
|
|
44554
|
-
const bumpType = options2.major ? "major" : options2.minor ? "minor" : "patch";
|
|
44582
|
+
const bumpType = options2.major ? "major" : options2.minor ? "minor" : options2.patch ? "patch" : null;
|
|
44555
44583
|
const currentVersion = org.version;
|
|
44556
|
-
|
|
44557
|
-
|
|
44558
|
-
|
|
44559
|
-
|
|
44560
|
-
|
|
44561
|
-
|
|
44562
|
-
|
|
44563
|
-
|
|
44564
|
-
|
|
44584
|
+
if (bumpType !== null) {
|
|
44585
|
+
const newVersion = bumpVersion(currentVersion, bumpType);
|
|
44586
|
+
const absEntryPath = (0, import_path2.resolve)(entryPath);
|
|
44587
|
+
const entryContent = await (0, import_promises.readFile)(absEntryPath, "utf-8");
|
|
44588
|
+
const updatedContent = entryContent.replace(
|
|
44589
|
+
/version:\s*['"][\d]+\.[\d]+\.[\d]+['"]/,
|
|
44590
|
+
`version: '${newVersion}'`
|
|
44591
|
+
);
|
|
44592
|
+
await (0, import_promises.writeFile)(absEntryPath, updatedContent, "utf-8");
|
|
44593
|
+
org.version = newVersion;
|
|
44594
|
+
}
|
|
44565
44595
|
console.log("");
|
|
44566
44596
|
console.log(source_default.gray(` Org: ${orgName}`));
|
|
44567
44597
|
console.log(source_default.gray(` Target: ${apiUrl} (${env2})`));
|
|
44568
|
-
console.log(
|
|
44598
|
+
console.log(
|
|
44599
|
+
source_default.gray(` Version: ${source_default.white(org.version)}${bumpType !== null ? ` (${bumpType} bump)` : ""}`)
|
|
44600
|
+
);
|
|
44569
44601
|
console.log("");
|
|
44570
44602
|
for (const w of activeWorkflows) {
|
|
44571
44603
|
console.log(source_default.gray(` workflow ${source_default.white(w.config.resourceId)} v${w.config.version}`));
|
|
@@ -44624,8 +44656,8 @@ function registerDeployCommand(program3) {
|
|
|
44624
44656
|
console.log("");
|
|
44625
44657
|
}
|
|
44626
44658
|
const bundleSpinner = ora("Bundling...").start();
|
|
44627
|
-
const wrapperPath = (0,
|
|
44628
|
-
const bundleOutfile = (0,
|
|
44659
|
+
const wrapperPath = (0, import_path2.resolve)("__elevasis_worker.ts");
|
|
44660
|
+
const bundleOutfile = (0, import_path2.resolve)("dist/bundle.js");
|
|
44629
44661
|
try {
|
|
44630
44662
|
const entryImport = entryPath.replace(/\.ts$/, ".js");
|
|
44631
44663
|
const wrapperContent = `import org from ${JSON.stringify(entryImport)}
|
|
@@ -44633,7 +44665,7 @@ import { startWorker } from '@elevasis/sdk/worker'
|
|
|
44633
44665
|
startWorker(org)
|
|
44634
44666
|
`;
|
|
44635
44667
|
await (0, import_promises.writeFile)(wrapperPath, wrapperContent, "utf-8");
|
|
44636
|
-
await (0, import_promises.mkdir)((0,
|
|
44668
|
+
await (0, import_promises.mkdir)((0, import_path2.resolve)("dist"), { recursive: true });
|
|
44637
44669
|
const esbuild = getEsbuild();
|
|
44638
44670
|
await esbuild.build({
|
|
44639
44671
|
entryPoints: [wrapperPath],
|
|
@@ -44743,7 +44775,7 @@ function registerCheckCommand(program3) {
|
|
|
44743
44775
|
const org = entryModule.default;
|
|
44744
44776
|
if (!org) {
|
|
44745
44777
|
spinner.fail("Invalid entry: no default export found");
|
|
44746
|
-
console.error(source_default.gray(` Entry file: ${(0,
|
|
44778
|
+
console.error(source_default.gray(` Entry file: ${(0, import_path3.resolve)(entryPath)}`));
|
|
44747
44779
|
console.error(source_default.gray(" Expected: export default { workflows: [...], agents: [...] }"));
|
|
44748
44780
|
throw new Error("Invalid entry");
|
|
44749
44781
|
}
|
|
@@ -44812,6 +44844,7 @@ function registerCheckCommand(program3) {
|
|
|
44812
44844
|
|
|
44813
44845
|
// src/cli/commands/exec.ts
|
|
44814
44846
|
var import_node_fs = require("node:fs");
|
|
44847
|
+
init_config();
|
|
44815
44848
|
var POLL_INTERVAL_MS = 3e3;
|
|
44816
44849
|
async function pollForCompletion(resourceId, executionId, apiUrl) {
|
|
44817
44850
|
const pollSpinner = ora("Waiting for completion...").start();
|
|
@@ -44826,7 +44859,7 @@ async function pollForCompletion(resourceId, executionId, apiUrl) {
|
|
|
44826
44859
|
};
|
|
44827
44860
|
process.on("SIGINT", cleanup);
|
|
44828
44861
|
while (true) {
|
|
44829
|
-
await new Promise((
|
|
44862
|
+
await new Promise((resolve4) => setTimeout(resolve4, POLL_INTERVAL_MS));
|
|
44830
44863
|
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
44831
44864
|
pollSpinner.text = `Waiting for completion... (${elapsed}s)`;
|
|
44832
44865
|
try {
|
|
@@ -44931,6 +44964,7 @@ function registerExecCommand(program3) {
|
|
|
44931
44964
|
}
|
|
44932
44965
|
|
|
44933
44966
|
// src/cli/commands/resources.ts
|
|
44967
|
+
init_config();
|
|
44934
44968
|
function registerResourcesCommand(program3) {
|
|
44935
44969
|
program3.command("resources").description("List deployed resources for your organization").option("--api-url <url>", "API URL").option("--json", "Output as JSON").action(wrapAction("resources", async (options2) => {
|
|
44936
44970
|
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
@@ -44976,6 +45010,7 @@ function registerResourcesCommand(program3) {
|
|
|
44976
45010
|
}
|
|
44977
45011
|
|
|
44978
45012
|
// src/cli/commands/executions.ts
|
|
45013
|
+
init_config();
|
|
44979
45014
|
function registerExecutionsCommand(program3) {
|
|
44980
45015
|
program3.command("executions <resourceId>").description("List execution history for a resource\n Example: elevasis-sdk executions my-workflow --limit 10").option("--api-url <url>", "API URL").option("--json", "Output as JSON").option("--limit <number>", "Limit number of results (default: 50)").option("--status <status>", "Filter by status (running|completed|failed)").action(wrapAction("executions", async (resourceId, options2) => {
|
|
44981
45016
|
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
@@ -45034,6 +45069,7 @@ function registerExecutionsCommand(program3) {
|
|
|
45034
45069
|
}
|
|
45035
45070
|
|
|
45036
45071
|
// src/cli/commands/execution.ts
|
|
45072
|
+
init_config();
|
|
45037
45073
|
function registerExecutionCommand(program3) {
|
|
45038
45074
|
program3.command("execution <resourceId> <executionId>").description("Get detailed information about a specific execution\n Example: elevasis-sdk execution my-workflow abc-123-uuid --logs-only").option("--api-url <url>", "API URL").option("--json", "Output raw JSON response").option("--logs-only", "Show only execution logs").option("--input", "Include input data in output").option("--result", "Include result data in output").action(wrapAction("execution", async (resourceId, executionId, options2) => {
|
|
45039
45075
|
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
@@ -45136,6 +45172,7 @@ function displayLog(log) {
|
|
|
45136
45172
|
}
|
|
45137
45173
|
|
|
45138
45174
|
// src/cli/commands/deployments.ts
|
|
45175
|
+
init_config();
|
|
45139
45176
|
function registerDeploymentsCommand(program3) {
|
|
45140
45177
|
program3.command("deployments").description("List deployments for your organization").option("--api-url <url>", "API URL").option("--json", "Output as JSON").action(wrapAction("deployments", async (options2) => {
|
|
45141
45178
|
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
@@ -45196,6 +45233,7 @@ function registerDeploymentsCommand(program3) {
|
|
|
45196
45233
|
}
|
|
45197
45234
|
|
|
45198
45235
|
// src/cli/commands/describe.ts
|
|
45236
|
+
init_config();
|
|
45199
45237
|
function hasSchemaContent(schema) {
|
|
45200
45238
|
return Object.keys(schema).some((k) => k !== "$schema");
|
|
45201
45239
|
}
|
|
@@ -45265,3085 +45303,8 @@ function registerDescribeCommand(program3) {
|
|
|
45265
45303
|
);
|
|
45266
45304
|
}
|
|
45267
45305
|
|
|
45268
|
-
// src/cli/commands/
|
|
45269
|
-
|
|
45270
|
-
var import_promises2 = require("fs/promises");
|
|
45271
|
-
|
|
45272
|
-
// src/cli/commands/templates/core/workspace.ts
|
|
45273
|
-
var TEMPLATE_VERSION = 34;
|
|
45274
|
-
function configTemplate() {
|
|
45275
|
-
return `import type { ElevasConfig } from '@elevasis/sdk'
|
|
45276
|
-
|
|
45277
|
-
export default {
|
|
45278
|
-
templateVersion: ${TEMPLATE_VERSION},
|
|
45279
|
-
// defaultStatus: 'dev', // Default status for new resources ('dev' | 'prod')
|
|
45280
|
-
// dev: { port: 5170 }, // Local API port (internal development only)
|
|
45281
|
-
} satisfies ElevasConfig
|
|
45282
|
-
`;
|
|
45283
|
-
}
|
|
45284
|
-
function packageJsonTemplate(organization) {
|
|
45285
|
-
return JSON.stringify(
|
|
45286
|
-
{
|
|
45287
|
-
name: organization,
|
|
45288
|
-
private: true,
|
|
45289
|
-
type: "module",
|
|
45290
|
-
scripts: {
|
|
45291
|
-
"check-types": "tsc --noEmit",
|
|
45292
|
-
check: "elevasis-sdk check",
|
|
45293
|
-
deploy: "elevasis-sdk deploy"
|
|
45294
|
-
},
|
|
45295
|
-
dependencies: {
|
|
45296
|
-
"@elevasis/sdk": `^${SDK_VERSION}`
|
|
45297
|
-
},
|
|
45298
|
-
devDependencies: {
|
|
45299
|
-
typescript: "5.9.2",
|
|
45300
|
-
zod: "4.1.12"
|
|
45301
|
-
}
|
|
45302
|
-
},
|
|
45303
|
-
null,
|
|
45304
|
-
2
|
|
45305
|
-
) + "\n";
|
|
45306
|
-
}
|
|
45307
|
-
function pnpmWorkspaceTemplate() {
|
|
45308
|
-
return `packages: []
|
|
45309
|
-
`;
|
|
45310
|
-
}
|
|
45311
|
-
function tsconfigTemplate() {
|
|
45312
|
-
return JSON.stringify(
|
|
45313
|
-
{
|
|
45314
|
-
compilerOptions: {
|
|
45315
|
-
target: "ES2022",
|
|
45316
|
-
module: "ESNext",
|
|
45317
|
-
moduleResolution: "Bundler",
|
|
45318
|
-
strict: true,
|
|
45319
|
-
esModuleInterop: true,
|
|
45320
|
-
skipLibCheck: true,
|
|
45321
|
-
forceConsistentCasingInFileNames: true,
|
|
45322
|
-
isolatedModules: true,
|
|
45323
|
-
outDir: "./dist"
|
|
45324
|
-
},
|
|
45325
|
-
include: ["src"],
|
|
45326
|
-
exclude: ["node_modules", "dist"]
|
|
45327
|
-
},
|
|
45328
|
-
null,
|
|
45329
|
-
2
|
|
45330
|
-
) + "\n";
|
|
45331
|
-
}
|
|
45332
|
-
function envTemplate() {
|
|
45333
|
-
return `ELEVASIS_PLATFORM_KEY=
|
|
45334
|
-
`;
|
|
45335
|
-
}
|
|
45336
|
-
function npmrcTemplate() {
|
|
45337
|
-
return `auto-install-peers = true
|
|
45338
|
-
`;
|
|
45339
|
-
}
|
|
45340
|
-
function gitignoreTemplate(ctx = {}) {
|
|
45341
|
-
let content = `node_modules/
|
|
45342
|
-
.env
|
|
45343
|
-
dist/
|
|
45344
|
-
__elevasis_worker.ts
|
|
45345
|
-
.claude/settings.local.json
|
|
45346
|
-
.claude/memory/
|
|
45347
|
-
package-lock.json
|
|
45348
|
-
`;
|
|
45349
|
-
if (ctx.hasUI) {
|
|
45350
|
-
content += `ui/node_modules/
|
|
45351
|
-
ui/dist/
|
|
45352
|
-
`;
|
|
45353
|
-
}
|
|
45354
|
-
return content;
|
|
45355
|
-
}
|
|
45356
|
-
function docsIndexTemplate(organization) {
|
|
45357
|
-
return `---
|
|
45358
|
-
title: ${organization}
|
|
45359
|
-
description: Documentation for the ${organization} Elevasis workspace
|
|
45360
|
-
order: 1
|
|
45361
|
-
---
|
|
45362
|
-
|
|
45363
|
-
# ${organization}
|
|
45364
|
-
|
|
45365
|
-
An [Elevasis](https://elevasis.io) workspace built with the \`@elevasis/sdk\`.
|
|
45366
|
-
|
|
45367
|
-
## Setup
|
|
45368
|
-
|
|
45369
|
-
\`\`\`bash
|
|
45370
|
-
pnpm install
|
|
45371
|
-
\`\`\`
|
|
45372
|
-
|
|
45373
|
-
Add your API key to \`.env\`:
|
|
45374
|
-
|
|
45375
|
-
\`\`\`
|
|
45376
|
-
ELEVASIS_PLATFORM_KEY=sk_...
|
|
45377
|
-
\`\`\`
|
|
45378
|
-
|
|
45379
|
-
## Development
|
|
45380
|
-
|
|
45381
|
-
\`\`\`bash
|
|
45382
|
-
pnpm run check # Validate resource definitions
|
|
45383
|
-
pnpm run deploy # Bundle and deploy to platform
|
|
45384
|
-
pnpm exec elevasis-sdk exec <resourceId> --input '...' # Execute a resource
|
|
45385
|
-
pnpm exec elevasis-sdk resources # List deployed resources
|
|
45386
|
-
pnpm exec elevasis-sdk describe <resourceId> # Show resource definition + schemas
|
|
45387
|
-
pnpm exec elevasis-sdk executions <resourceId> # View execution history
|
|
45388
|
-
\`\`\`
|
|
45389
|
-
|
|
45390
|
-
## Project Structure
|
|
45391
|
-
|
|
45392
|
-
- \`elevasis.config.ts\` -- Workspace config (optional settings)
|
|
45393
|
-
- \`src/index.ts\` -- Resource registry (aggregates from domain barrels)
|
|
45394
|
-
- \`src/operations/\` -- Operations domain (platform-status workflow)
|
|
45395
|
-
- \`src/example/\` -- Example domain (echo workflow -- replace with your own)
|
|
45396
|
-
- \`src/shared/\` -- Cross-domain shared types and utilities
|
|
45397
|
-
- \`docs/\` -- Documentation (.mdx files, deployed alongside code)
|
|
45398
|
-
- \`.env\` -- API key for CLI authentication
|
|
45399
|
-
|
|
45400
|
-
## Resources
|
|
45401
|
-
|
|
45402
|
-
### Platform Status Workflow (\`src/operations/\`)
|
|
45403
|
-
|
|
45404
|
-
A multi-step workflow that queries platform status and compiles a natural language
|
|
45405
|
-
summary using an LLM. Demonstrates platform API usage with the \`llm\` typed adapter and \`platform.call()\`.
|
|
45406
|
-
|
|
45407
|
-
\`\`\`bash
|
|
45408
|
-
pnpm exec elevasis-sdk exec platform-status --input '{"timeRange": "24h"}'
|
|
45409
|
-
\`\`\`
|
|
45410
|
-
|
|
45411
|
-
**Input:** \`{ "timeRange": "1h" | "24h" | "7d" }\`
|
|
45412
|
-
**Output:** \`{ "raw": object, "summary": string }\`
|
|
45413
|
-
|
|
45414
|
-
### Echo Workflow (\`src/example/\`)
|
|
45415
|
-
|
|
45416
|
-
A simple workflow that echoes the input message back. Use it as a starter pattern
|
|
45417
|
-
for new workflows:
|
|
45418
|
-
|
|
45419
|
-
\`\`\`bash
|
|
45420
|
-
pnpm exec elevasis-sdk exec echo --input '{"message": "hello"}'
|
|
45421
|
-
\`\`\`
|
|
45422
|
-
|
|
45423
|
-
**Input:** \`{ "message": string }\`
|
|
45424
|
-
**Output:** \`{ "echo": string }\`
|
|
45425
|
-
`;
|
|
45426
|
-
}
|
|
45427
|
-
|
|
45428
|
-
// src/cli/commands/templates/core/claude.ts
|
|
45429
|
-
function claudeSettingsTemplate() {
|
|
45430
|
-
return JSON.stringify(
|
|
45431
|
-
{
|
|
45432
|
-
autoCompact: false,
|
|
45433
|
-
statusLine: {
|
|
45434
|
-
type: "command",
|
|
45435
|
-
command: "node .claude/scripts/statusline-command.js"
|
|
45436
|
-
},
|
|
45437
|
-
hooks: {
|
|
45438
|
-
PreToolUse: [
|
|
45439
|
-
{
|
|
45440
|
-
matcher: "Write|Edit|MultiEdit|Bash",
|
|
45441
|
-
hooks: [
|
|
45442
|
-
{
|
|
45443
|
-
type: "command",
|
|
45444
|
-
command: "node .claude/hooks/enforce-sdk-boundary.mjs"
|
|
45445
|
-
}
|
|
45446
|
-
]
|
|
45447
|
-
}
|
|
45448
|
-
],
|
|
45449
|
-
PostToolUse: [
|
|
45450
|
-
{
|
|
45451
|
-
matcher: "Write|Edit|MultiEdit",
|
|
45452
|
-
hooks: [
|
|
45453
|
-
{
|
|
45454
|
-
type: "command",
|
|
45455
|
-
command: "node .claude/hooks/post-edit-validate.mjs"
|
|
45456
|
-
}
|
|
45457
|
-
]
|
|
45458
|
-
}
|
|
45459
|
-
],
|
|
45460
|
-
PostToolUseFailure: [
|
|
45461
|
-
{
|
|
45462
|
-
matcher: "Bash",
|
|
45463
|
-
hooks: [
|
|
45464
|
-
{
|
|
45465
|
-
type: "command",
|
|
45466
|
-
command: "node .claude/hooks/tool-failure-recovery.mjs"
|
|
45467
|
-
}
|
|
45468
|
-
]
|
|
45469
|
-
}
|
|
45470
|
-
]
|
|
45471
|
-
}
|
|
45472
|
-
},
|
|
45473
|
-
null,
|
|
45474
|
-
2
|
|
45475
|
-
) + "\n";
|
|
45476
|
-
}
|
|
45477
|
-
function claudeStatuslineScriptTemplate() {
|
|
45478
|
-
return `#!/usr/bin/env node
|
|
45479
|
-
let input = '';
|
|
45480
|
-
process.stdin.on('data', chunk => input += chunk);
|
|
45481
|
-
process.stdin.on('end', () => {
|
|
45482
|
-
const data = JSON.parse(input);
|
|
45483
|
-
const model = data.model?.display_name || '?';
|
|
45484
|
-
const pct = Math.floor(data.context_window?.used_percentage || 0);
|
|
45485
|
-
|
|
45486
|
-
const DIM = '\\x1b[90m', RESET = '\\x1b[0m';
|
|
45487
|
-
const GREEN = '\\x1b[32m', YELLOW = '\\x1b[33m', RED = '\\x1b[31m';
|
|
45488
|
-
|
|
45489
|
-
const color = pct >= 90 ? RED : pct >= 70 ? YELLOW : GREEN;
|
|
45490
|
-
|
|
45491
|
-
const width = 20;
|
|
45492
|
-
const filled = Math.floor(pct * width / 100);
|
|
45493
|
-
const empty = width - filled;
|
|
45494
|
-
const bar = '#'.repeat(filled) + '-'.repeat(empty);
|
|
45495
|
-
|
|
45496
|
-
console.log(\`\${DIM}[\${RESET}\${model}\${DIM}]\${RESET} \${color}\${bar}\${RESET} \${pct}%\`);
|
|
45497
|
-
});
|
|
45498
|
-
`;
|
|
45499
|
-
}
|
|
45500
|
-
function claudeSdkBoundaryHookTemplate() {
|
|
45501
|
-
return String.raw`#!/usr/bin/env node
|
|
45502
|
-
// enforce-sdk-boundary.mjs
|
|
45503
|
-
// Blocks file modifications (Write, Edit, MultiEdit, destructive Bash) outside the project root.
|
|
45504
|
-
// Git, gh, and other CLI tools are NOT blocked -- the agent can use them freely.
|
|
45505
|
-
|
|
45506
|
-
import { resolve, normalize } from "node:path";
|
|
45507
|
-
import { appendFileSync, mkdirSync } from "node:fs";
|
|
45508
|
-
|
|
45509
|
-
const LOG_DIR = (process.env.CLAUDE_PROJECT_DIR ?? process.cwd()) + "/.claude/logs";
|
|
45510
|
-
const LOG_FILE = LOG_DIR + "/boundary-hook.log";
|
|
45511
|
-
|
|
45512
|
-
function log(msg) {
|
|
45513
|
-
try {
|
|
45514
|
-
mkdirSync(LOG_DIR, { recursive: true });
|
|
45515
|
-
appendFileSync(LOG_FILE, "[" + new Date().toISOString() + "] " + msg + "\n");
|
|
45516
|
-
} catch {}
|
|
45517
|
-
}
|
|
45518
|
-
|
|
45519
|
-
function deny(reason) {
|
|
45520
|
-
log("DENY -- " + reason);
|
|
45521
|
-
process.stdout.write(
|
|
45522
|
-
JSON.stringify({
|
|
45523
|
-
hookSpecificOutput: {
|
|
45524
|
-
hookEventName: "PreToolUse",
|
|
45525
|
-
permissionDecision: "deny",
|
|
45526
|
-
permissionDecisionReason: reason,
|
|
45527
|
-
},
|
|
45528
|
-
})
|
|
45529
|
-
);
|
|
45530
|
-
}
|
|
45531
|
-
|
|
45532
|
-
try {
|
|
45533
|
-
const chunks = [];
|
|
45534
|
-
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
45535
|
-
const input = JSON.parse(Buffer.concat(chunks).toString());
|
|
45536
|
-
|
|
45537
|
-
const projectDir = normalize(process.env.CLAUDE_PROJECT_DIR ?? process.cwd());
|
|
45538
|
-
const sep = process.platform === "win32" ? "\\" : "/";
|
|
45539
|
-
const prefix = projectDir.endsWith("\\") || projectDir.endsWith("/") ? projectDir : projectDir + sep;
|
|
45540
|
-
|
|
45541
|
-
function isOutside(filePath) {
|
|
45542
|
-
const target = normalize(resolve(filePath));
|
|
45543
|
-
return !target.startsWith(prefix) && target !== projectDir;
|
|
45544
|
-
}
|
|
45545
|
-
|
|
45546
|
-
if (input.tool_name === "Bash") {
|
|
45547
|
-
const cmd = input.tool_input?.command ?? "";
|
|
45548
|
-
|
|
45549
|
-
// Path-scoped blocks -- destructive commands or redirects outside project root
|
|
45550
|
-
const winPaths = cmd.match(/(?<![A-Za-z])[A-Za-z]:[/\\][^\s"'|;&)]+/g) || [];
|
|
45551
|
-
const unixPaths = cmd.match(/(?<=\s|^|"|')\/[^\s"'|;&)]+/g) || [];
|
|
45552
|
-
const allPaths = [...winPaths, ...unixPaths]
|
|
45553
|
-
.map((p) => p.trim())
|
|
45554
|
-
.filter((p) => !p.startsWith("/dev/"));
|
|
45555
|
-
|
|
45556
|
-
const outsidePaths = allPaths.filter((p) => isOutside(p));
|
|
45557
|
-
|
|
45558
|
-
if (outsidePaths.length > 0) {
|
|
45559
|
-
const hasDestructiveCmd = /(?<![-])\b(rm|rmdir|del|unlink|mv|cp|touch|mkdir|chmod|chown|truncate|tee|dd|install)\b/.test(cmd);
|
|
45560
|
-
const hasInPlaceEdit = /\bsed\b.*\s-i/.test(cmd);
|
|
45561
|
-
const hasRedirect = />{1,2}\s*[^\s&>]/.test(cmd);
|
|
45562
|
-
|
|
45563
|
-
const hasTempPath = outsidePaths.some(
|
|
45564
|
-
(p) => /[/\\]tmp[/\\]/i.test(p) || /[/\\]Temp[/\\]/i.test(p)
|
|
45565
|
-
);
|
|
45566
|
-
|
|
45567
|
-
if (hasDestructiveCmd || hasInPlaceEdit || hasRedirect) {
|
|
45568
|
-
const instead = hasTempPath
|
|
45569
|
-
? "INSTEAD: Use pipes instead of temp files: cmd 2>&1 | grep pattern not cmd > /tmp/out.txt. All file writes must target paths inside the project."
|
|
45570
|
-
: "INSTEAD: Only files within the project directory may be modified. Ask the user to run this command manually if external paths are needed.";
|
|
45571
|
-
|
|
45572
|
-
deny(
|
|
45573
|
-
"BLOCKED: destructive command references path(s) outside the project: " + outsidePaths.join(", ") + ".\n" +
|
|
45574
|
-
"WHY: File modifications outside the project boundary are not allowed.\n" +
|
|
45575
|
-
instead
|
|
45576
|
-
);
|
|
45577
|
-
}
|
|
45578
|
-
}
|
|
45579
|
-
} else {
|
|
45580
|
-
// Write, Edit, MultiEdit: check file_path
|
|
45581
|
-
const filePath = input.tool_input?.file_path;
|
|
45582
|
-
if (filePath && isOutside(filePath)) {
|
|
45583
|
-
deny(
|
|
45584
|
-
"BLOCKED: " + filePath + " is outside the project.\n" +
|
|
45585
|
-
"WHY: [" + (input.tool_name ?? "Unknown") + "] file operations outside the project boundary are not allowed.\n" +
|
|
45586
|
-
"INSTEAD: Only files within the project directory may be modified."
|
|
45587
|
-
);
|
|
45588
|
-
}
|
|
45589
|
-
}
|
|
45590
|
-
} catch (err) {
|
|
45591
|
-
log("ERROR: " + err.message + "\n" + err.stack);
|
|
45592
|
-
}
|
|
45593
|
-
|
|
45594
|
-
process.exit(0);
|
|
45595
|
-
`;
|
|
45596
|
-
}
|
|
45597
|
-
function claudeMdTemplate(ctx = {}) {
|
|
45598
|
-
return `<!-- initialized: false -->
|
|
45599
|
-
|
|
45600
|
-
# CLAUDE.md
|
|
45601
|
-
|
|
45602
|
-
## Session Initialization
|
|
45603
|
-
|
|
45604
|
-
At the start of every session:
|
|
45605
|
-
|
|
45606
|
-
0. Check the \`<!-- initialized: ... -->\` flag at the top of this file.
|
|
45607
|
-
If \`false\`, read \`.claude/commands/init.md\` and run the \`/init\` flow.
|
|
45608
|
-
After initialization completes, change the flag to \`<!-- initialized: true -->\`.
|
|
45609
|
-
If \`true\`, proceed with steps below.
|
|
45610
|
-
1. Read \`.claude/memory/profile/skills.md\` -- adapt all responses to the user's
|
|
45611
|
-
assessed skill levels (see Interaction Guidance below).
|
|
45612
|
-
2. Read \`.claude/memory/index.md\` -- drill into relevant topic files as needed.
|
|
45613
|
-
Balance context relevance against token usage.
|
|
45614
|
-
3. Check installed \`@elevasis/sdk\` template version against \`templateVersion\`
|
|
45615
|
-
in \`elevasis.config.ts\`. If newer, notify and suggest \`/fix\`.
|
|
45616
|
-
4. If \`.claude/memory/\` does not exist, suggest \`/init\`.
|
|
45617
|
-
5. If user Platform Navigation level is none (from skills.md) and
|
|
45618
|
-
\`.claude/memory/tutorial-progress.md\` does not exist, suggest \`/tutorial\`.
|
|
45619
|
-
If tutorial-progress.md exists and Phase is not complete, mention that the
|
|
45620
|
-
tutorial has more to explore.
|
|
45621
|
-
|
|
45622
|
-
Do this silently. Do not narrate the steps to the user.
|
|
45623
|
-
|
|
45624
|
-
## Identity
|
|
45625
|
-
|
|
45626
|
-
You are the development agent for an Elevasis workspace. You help the user
|
|
45627
|
-
design, build, and deploy business automation workflows on the Elevasis
|
|
45628
|
-
platform. You are not just a code assistant -- you are a guide who translates
|
|
45629
|
-
business intent into working automation.
|
|
45630
|
-
|
|
45631
|
-
Your users range from experienced developers to business operators who have
|
|
45632
|
-
never written code. Read the user's skill profile at session start and adapt
|
|
45633
|
-
every interaction -- vocabulary, code completeness, explanation depth, and
|
|
45634
|
-
proactivity -- to their assessed levels.
|
|
45635
|
-
|
|
45636
|
-
## Navigation
|
|
45637
|
-
|
|
45638
|
-
| Resource | Location | When to Load |
|
|
45639
|
-
| --- | --- | --- |
|
|
45640
|
-
| Workspace concepts | \`reference/concepts.mdx\` | User asks "what is...?" or needs conceptual grounding |
|
|
45641
|
-
| SDK patterns and examples | \`reference/resources/patterns.mdx\` | Building or modifying a workflow |
|
|
45642
|
-
| Platform tool catalog | \`reference/platform-tools/index.mdx\` | Connecting to external services |
|
|
45643
|
-
| CLI reference | \`reference/cli.mdx\` | Running execution/platform operations |
|
|
45644
|
-
| Credential model | \`reference/platform-tools/index.mdx\` | Setting up integrations or credential security |
|
|
45645
|
-
| Interaction guidance | \`reference/framework/interaction-guidance.mdx\` | Unsure how to adapt for a skill combination |
|
|
45646
|
-
| Error history | \`.claude/memory/errors/index.md\` | Debugging errors, checking past fixes |
|
|
45647
|
-
| Command View model | \`reference/deployment/command-center.mdx\` | Deploying or building resources that invoke other resources |
|
|
45648
|
-
| Command Center UI reference | \`reference/deployment/command-center.mdx\` | User asks about post-deployment UI or Command Center navigation |
|
|
45649
|
-
| SDK error reference | \`reference/troubleshooting.mdx\` | Unknown error not in workspace memory |
|
|
45650
|
-
| Project map | \`docs/project-map.mdx\` | Session start, project orientation |
|
|
45651
|
-
| Resource inventory | \`docs/resource-map.mdx\` | Finding a specific resource by name or ID |
|
|
45652
|
-
| Project priorities | \`docs/priorities.mdx\` | Deciding what to work on next |
|
|
45653
|
-
| User profile and skills | \`.claude/memory/profile/skills.md\` | Session start (mandatory) |
|
|
45654
|
-
| Cross-session memory | \`.claude/memory/index.md\` | Session start, recalling past context |${ctx.hasUI ? `
|
|
45655
|
-
| UI app source | \`ui/src/\` | Modifying the frontend, adding routes or components |` : ""}
|
|
45656
|
-
|
|
45657
|
-
All \`reference/\` paths resolve to \`node_modules/@elevasis/sdk/reference/\`.
|
|
45658
|
-
|
|
45659
|
-
## Elevasis CLI
|
|
45660
|
-
|
|
45661
|
-
**MANDATORY:** Use the \`elevasis-sdk\` CLI for all execution/platform operations -- never \`curl\` or any other tool.
|
|
45662
|
-
|
|
45663
|
-
Use pnpm scripts for check and deploy (they resolve the local binary automatically):
|
|
45664
|
-
|
|
45665
|
-
- \`pnpm run check\` -- validate resource definitions without deploying
|
|
45666
|
-
- \`pnpm run deploy\` -- deploy to the platform
|
|
45667
|
-
|
|
45668
|
-
Use \`pnpm exec elevasis-sdk\` for runtime commands (resolves the locally installed binary):
|
|
45669
|
-
|
|
45670
|
-
- \`pnpm exec elevasis-sdk exec <resource-id> --input '{...}'\` -- run a resource synchronously
|
|
45671
|
-
- \`pnpm exec elevasis-sdk exec <resource-id> --input '{...}' --async\` -- run async, returns execution ID
|
|
45672
|
-
- \`pnpm exec elevasis-sdk execution <resource-id> <execution-id>\` -- inspect execution detail
|
|
45673
|
-
- \`pnpm exec elevasis-sdk rename <old-id> --to <new-id> [--execute] [--prod]\` -- rename a resource ID across platform tables (dry run by default)
|
|
45674
|
-
|
|
45675
|
-
Organization is derived from your API key -- no org prefix needed in the resource ID.
|
|
45676
|
-
For full CLI reference: \`reference/cli.mdx\`
|
|
45677
|
-
|
|
45678
|
-
## Rules
|
|
45679
|
-
|
|
45680
|
-
SDK patterns (imports, source structure, platform tools) are auto-loaded from
|
|
45681
|
-
\`.claude/rules/sdk-patterns.md\`. Project-specific patterns live in
|
|
45682
|
-
\`.claude/rules/workspace-patterns.md\`.
|
|
45683
|
-
|
|
45684
|
-
- Documentation goes in \`docs/\` as \`.mdx\` files
|
|
45685
|
-
- Resources are not visible in the Command Center until deployed. Always deploy before directing users to verify in the UI.
|
|
45686
|
-
|
|
45687
|
-
### Error Handling
|
|
45688
|
-
|
|
45689
|
-
When an error occurs:
|
|
45690
|
-
1. Check \`.claude/memory/errors/\` first for past fixes
|
|
45691
|
-
2. If new, check \`reference/troubleshooting.mdx\`
|
|
45692
|
-
3. After resolving, record in \`.claude/memory/errors/\` with context and fix
|
|
45693
|
-
4. If an error recurs 3+ times, add a rule to \`.claude/rules/workspace-patterns.md\`${ctx.hasUI ? `
|
|
45694
|
-
|
|
45695
|
-
### UI App (\`ui/\`)
|
|
45696
|
-
|
|
45697
|
-
- \`ui/\` is a standalone Vite + React app with its own \`package.json\` -- not part of the pnpm workspace
|
|
45698
|
-
- Import from \`@elevasis/sdk-ui\`, never from \`@elevasis/sdk\` or \`@repo/ui\`
|
|
45699
|
-
- Dev server runs on port 5100: \`cd ui && pnpm dev\`
|
|
45700
|
-
- Set \`VITE_WORKOS_CLIENT_ID\` in \`ui/.env\` before running
|
|
45701
|
-
- \`ElevasisCoreProvider\` (headless, no Mantine dependency) is pre-configured in \`ui/src/App.tsx\` with \`auth={{ mode: 'oauth', clientId, redirectUri }}\`, \`apiUrl="http://localhost:5170"\`, and \`theme={{ colorScheme: 'dark', preset: 'default' }}\`
|
|
45702
|
-
- To use pre-built Mantine components from \`@elevasis/sdk-ui\`, switch to \`ElevasisUIProvider\` and install \`@mantine/core\` and \`@mantine/hooks\`
|
|
45703
|
-
- OAuth redirect is handled by the \`AuthRedirect\` component at \`/auth-redirect\` -- it uses \`useAuthContext()\` from \`@elevasis/sdk-ui/auth\` and navigates home once \`user\` is set
|
|
45704
|
-
- API must be running on port 5170 for the UI to work (\`pnpm --filter api dev\` from the platform monorepo)` : ""}
|
|
45705
|
-
|
|
45706
|
-
## Interaction Guidance
|
|
45707
|
-
|
|
45708
|
-
Adapt your communication based on \`.claude/memory/profile/skills.md\`.
|
|
45709
|
-
Read the profile at session start (Step 1). Adjust every response --
|
|
45710
|
-
vocabulary, code completeness, explanation depth, and proactivity --
|
|
45711
|
-
based on what you find.
|
|
45712
|
-
|
|
45713
|
-
- Match vocabulary to the user's level. Avoid jargon for beginners;
|
|
45714
|
-
be precise for experts. Define technical terms in parentheses the first time.
|
|
45715
|
-
- Provide step-by-step UI navigation for users with Platform Navigation below comfortable.
|
|
45716
|
-
Reference exact page names and paths until they are oriented.
|
|
45717
|
-
- Explain "why" before "how" for users new to automation.
|
|
45718
|
-
- For users comfortable with the platform, focus on SDK-specific patterns and advanced operations.
|
|
45719
|
-
- Leverage domain expertise -- if the user knows sales but not code,
|
|
45720
|
-
ask for business process descriptions and translate.
|
|
45721
|
-
- When growth is observed, note it in the skills.md Growth Log.
|
|
45722
|
-
|
|
45723
|
-
For detailed per-dimension adaptation rules, read
|
|
45724
|
-
\`reference/framework/interaction-guidance.mdx\`.
|
|
45725
|
-
|
|
45726
|
-
## Commands
|
|
45727
|
-
|
|
45728
|
-
| Command | Purpose |
|
|
45729
|
-
| --- | --- |
|
|
45730
|
-
| \`/init\` | First-run workspace setup and competency assessment |
|
|
45731
|
-
| \`/status\` | Project health dashboard |
|
|
45732
|
-
| \`/fix\` | Maintenance, drift repair, and SDK upgrade |
|
|
45733
|
-
| \`/deploy\` | Full deploy pipeline (validate \u2192 deploy \u2192 verify) |
|
|
45734
|
-
| \`/docs\` | Browse, create, and verify permanent documentation |
|
|
45735
|
-
| \`/tutorial\` | Progressive learning path (21 items across 4 sections) |
|
|
45736
|
-
|
|
45737
|
-
## Skills
|
|
45738
|
-
|
|
45739
|
-
Skills auto-trigger based on conversation context. You do not need to invoke them manually.
|
|
45740
|
-
|
|
45741
|
-
| Skill | Triggers When |
|
|
45742
|
-
| --- | --- |
|
|
45743
|
-
| \`work\` | You say /work, ask to track or save progress across sessions, ask what you were working on, want to create/resume/complete a task doc, or say you are done for today. Also proactively save when conversation is heavy or 2+ steps completed |
|
|
45744
|
-
| \`creds\` | You mention credentials, API keys, secrets, webhook secrets, or setting up integrations |
|
|
45745
|
-
| \`diagnostics\` | An execution fails, user asks why something failed, user mentions runtime errors, or agent observes a failed execution |
|
|
45746
|
-
|
|
45747
|
-
## Maintaining Memory
|
|
45748
|
-
|
|
45749
|
-
### What Memory Is
|
|
45750
|
-
|
|
45751
|
-
Memory stores persistent state and observations that inform future sessions.
|
|
45752
|
-
Every file must contain data the agent writes and later reads to make better
|
|
45753
|
-
decisions. File names must clearly indicate they contain state or data
|
|
45754
|
-
(e.g., \`deployment-state.md\`, \`tutorial-progress.md\`, \`skills.md\`).
|
|
45755
|
-
|
|
45756
|
-
Priorities live in \`docs/priorities.mdx\`, not in memory. Memory is for internal
|
|
45757
|
-
agent state; priorities are project documentation the user may also read.
|
|
45758
|
-
|
|
45759
|
-
### What Memory Is NOT
|
|
45760
|
-
|
|
45761
|
-
Do not store in \`.claude/memory/\`:
|
|
45762
|
-
- Instructions, commands, or procedures (belong in \`.claude/commands/\`)
|
|
45763
|
-
- Reference documentation or teaching material (belong in \`docs/\` or SDK reference)
|
|
45764
|
-
- Templates or boilerplate code
|
|
45765
|
-
- Conversation transcripts or chat history
|
|
45766
|
-
- Anything the agent reads but never updates
|
|
45767
|
-
|
|
45768
|
-
### Structure
|
|
45769
|
-
|
|
45770
|
-
- \`.claude/memory/index.md\` is the root -- maps to topic files and subdirectories
|
|
45771
|
-
- Every subdirectory has its own \`index.md\` mapping to children
|
|
45772
|
-
- Start at the root index and drill down
|
|
45773
|
-
- When a file outgrows a single document, split into a subdirectory
|
|
45774
|
-
|
|
45775
|
-
### Pruning
|
|
45776
|
-
|
|
45777
|
-
- Keep ~20 recent entries per table; drop stale patterns (30+ days, no recurrence)
|
|
45778
|
-
- If a file/index references a missing child, remove the row
|
|
45779
|
-
- If a child exists without an index entry, add it
|
|
45780
|
-
- If an error pattern recurs 3+ times, promote to Rules above
|
|
45781
|
-
`;
|
|
45782
|
-
}
|
|
45783
|
-
function claudeTutorialCommandTemplate() {
|
|
45784
|
-
return `# /tutorial command
|
|
45785
|
-
|
|
45786
|
-
You are a tutorial guide for this Elevasis workspace.
|
|
45787
|
-
|
|
45788
|
-
## Context
|
|
45789
|
-
|
|
45790
|
-
Read \`.claude/memory/profile/skills.md\` first. The \`automation\` skill level
|
|
45791
|
-
controls which docs you load and which lesson variant you deliver.
|
|
45792
|
-
|
|
45793
|
-
**automation: none**
|
|
45794
|
-
- Load from \`reference/concepts.mdx\`: Glossary, What is a Workflow,
|
|
45795
|
-
Platform Tools Overview only. Skip Zod, Execution Model, Design Decisions.
|
|
45796
|
-
- Load \`reference/deployment/command-center.mdx\` for UI-first teaching.
|
|
45797
|
-
- Do NOT load \`reference/resources/patterns.mdx\` or
|
|
45798
|
-
\`reference/platform-tools/adapters.mdx\` during core lessons.
|
|
45799
|
-
|
|
45800
|
-
**automation: low-code**
|
|
45801
|
-
- Load all sections of \`reference/concepts.mdx\`.
|
|
45802
|
-
- Load \`reference/resources/patterns.mdx\` with Zapier/Make mapping in mind.
|
|
45803
|
-
- Load \`reference/platform-tools/adapters.mdx\` on-demand (when tools are used).
|
|
45804
|
-
|
|
45805
|
-
**automation: custom**
|
|
45806
|
-
- Load all docs listed per-lesson and per-module as specified below.
|
|
45807
|
-
|
|
45808
|
-
Read \`.claude/memory/tutorial-progress.md\` to check current lesson progress.
|
|
45809
|
-
|
|
45810
|
-
## Invocation
|
|
45811
|
-
|
|
45812
|
-
\`/tutorial\` -- ALWAYS shows the main menu first. Never silently auto-resumes without giving the user a choice. See ## Menu section for the exact menu format.
|
|
45813
|
-
|
|
45814
|
-
## Menu
|
|
45815
|
-
|
|
45816
|
-
When \`/tutorial\` is invoked:
|
|
45817
|
-
|
|
45818
|
-
1. Read \`.claude/memory/tutorial-progress.md\` (if it exists)
|
|
45819
|
-
2. Display the full menu table. Fill in progress indicators from the progress file.
|
|
45820
|
-
3. User picks a number -> start or resume that item directly. No track gating.
|
|
45821
|
-
|
|
45822
|
-
Progress indicators: \`[ ]\` not started, \`[>]\` in progress, \`[x] YYYY-MM-DD\` complete.
|
|
45823
|
-
|
|
45824
|
-
Example (first time, no progress):
|
|
45825
|
-
|
|
45826
|
-
\`\`\`
|
|
45827
|
-
Elevasis Tutorial
|
|
45828
|
-
==================
|
|
45829
|
-
|
|
45830
|
-
INTRODUCTION 0/4
|
|
45831
|
-
1 Welcome & Orientation [ ]
|
|
45832
|
-
2 How This Workspace Works [ ]
|
|
45833
|
-
3 Project Commands (/init, /status, /fix, /deploy) [ ]
|
|
45834
|
-
4 /work and /docs [ ]
|
|
45835
|
-
|
|
45836
|
-
CORE CONCEPTS 0/6
|
|
45837
|
-
5 Your First Custom Workflow [ ]
|
|
45838
|
-
6 Understanding Data (Schemas) [ ]
|
|
45839
|
-
7 Using Platform Tools [ ]
|
|
45840
|
-
8 Multi-Step Workflows [ ]
|
|
45841
|
-
9 Decision Points [ ]
|
|
45842
|
-
10 Going to Production [ ]
|
|
45843
|
-
|
|
45844
|
-
ADVANCED MODULES 0/9
|
|
45845
|
-
11 Human-in-the-Loop [ ]
|
|
45846
|
-
12 Task Scheduling [ ]
|
|
45847
|
-
13 Notification System [ ]
|
|
45848
|
-
14 Real-World Integrations [ ]
|
|
45849
|
-
15 Error Handling Mastery [ ]
|
|
45850
|
-
16 Advanced Workflows [ ]
|
|
45851
|
-
17 Resource Composition [ ]
|
|
45852
|
-
18 LLM Integration [ ]
|
|
45853
|
-
19 AI Agents [ ]
|
|
45854
|
-
|
|
45855
|
-
ADVANCED WORKSPACE 0/2
|
|
45856
|
-
20 Rules, Memory, and Customization [ ]
|
|
45857
|
-
21 Template Lifecycle [ ]
|
|
45858
|
-
|
|
45859
|
-
Pick a number to start.
|
|
45860
|
-
\`\`\`
|
|
45861
|
-
|
|
45862
|
-
Always show this full table when \`/tutorial\` is invoked. Populate progress
|
|
45863
|
-
indicators from completed/current state. \`"status"\` -> show the same table.
|
|
45864
|
-
|
|
45865
|
-
## Progress Logic
|
|
45866
|
-
|
|
45867
|
-
1. Read \`.claude/memory/tutorial-progress.md\`
|
|
45868
|
-
2. Show the full menu table (## Menu) with progress filled in
|
|
45869
|
-
3. User picks a number -> start or resume that lesson or module directly
|
|
45870
|
-
4. After user confirms readiness: mark done in progress file, show updated menu table
|
|
45871
|
-
5. All 21 items complete -> congratulate, suggest exploring docs/ or /work
|
|
45872
|
-
|
|
45873
|
-
## Lesson Flow
|
|
45874
|
-
|
|
45875
|
-
Each lesson follows this flow:
|
|
45876
|
-
1. Announce lesson title and what they'll learn (1-2 sentences)
|
|
45877
|
-
2. Explain the concept (read docs per skill level, adapt to user)
|
|
45878
|
-
3. Guide user to build or modify something (agent writes all code for automation: none)
|
|
45879
|
-
4. Verify it works (CLI primary for all levels; Command Center for visual review -- Command View, Execution Logs)
|
|
45880
|
-
5. Celebrate success and ask: "Any questions, or ready to continue?"
|
|
45881
|
-
6. Once the user confirms, record observations in \`.claude/memory/tutorial-progress.md\`
|
|
45882
|
-
|
|
45883
|
-
## Lessons
|
|
45884
|
-
|
|
45885
|
-
**Item 1: Welcome & Orientation**
|
|
45886
|
-
|
|
45887
|
-
When automation is none:
|
|
45888
|
-
Skip the file tour. Start with what Elevasis does for their business -- use analogies
|
|
45889
|
-
from \`reference/framework/interaction-guidance.mdx\` (recipe, assembly line, kitchen
|
|
45890
|
-
appliance). Explain deployment plainly: "You write the recipe here, then deploy it so
|
|
45891
|
-
it's live." Deploy the starter echo workflow (\`elevasis-sdk check\` + \`elevasis-sdk deploy\`),
|
|
45892
|
-
THEN tour the Command Center so the user sees populated pages, not empty ones. Tour:
|
|
45893
|
-
Command View (echo node), Execution Logs (result).
|
|
45894
|
-
Observation focus: automation value understanding, Command Center comfort.
|
|
45895
|
-
|
|
45896
|
-
When automation is low-code or custom:
|
|
45897
|
-
Tour project files: src/index.ts (registry), src/example/echo.ts (starter
|
|
45898
|
-
workflow), src/operations/platform-status.ts (platform API example),
|
|
45899
|
-
elevasis.config.ts, .env, docs/. Explain the execution model.
|
|
45900
|
-
Verify: run \`elevasis-sdk resources\`. Then open the Command Center and tour the
|
|
45901
|
-
main pages: Command View (resource graph), Execution Logs.
|
|
45902
|
-
Point out the echo workflow node in Command View.
|
|
45903
|
-
Observation focus: cloud deployment model, UI navigation comfort.
|
|
45904
|
-
|
|
45905
|
-
**Item 2: How This Workspace Works**
|
|
45906
|
-
|
|
45907
|
-
When automation is none:
|
|
45908
|
-
"This workspace comes with a built-in assistant that knows your project, your tools,
|
|
45909
|
-
and your goals. Let me show you how it's set up." Open CLAUDE.md and explain in
|
|
45910
|
-
plain terms: it's the agent's instruction sheet. Point out the commands in the
|
|
45911
|
-
Commands table. Show /status, /tutorial. Explain the work and creds skills as
|
|
45912
|
-
"the assistant automatically helps when you mention tasks or API keys." Tour the memory folder
|
|
45913
|
-
at a high level -- "this is where the agent stores what it learns about your project."
|
|
45914
|
-
Verify: Ask the user a question about their business goal and show how the agent
|
|
45915
|
-
references their profile in the answer.
|
|
45916
|
-
Observation focus: agent-as-assistant concept, CLAUDE.md as instruction sheet.
|
|
45917
|
-
|
|
45918
|
-
When automation is low-code:
|
|
45919
|
-
Read CLAUDE.md and walk through each section. Explain: what the agent reads on
|
|
45920
|
-
session start, how the navigation table works, what the Skills section means.
|
|
45921
|
-
Explain the three commands briefly and the two auto-triggering skills (work, creds). Show that the agent has memory: open
|
|
45922
|
-
\`.claude/memory/profile/skills.md\` and show their own profile -- "every session,
|
|
45923
|
-
the agent reads this and adapts." Explain the initialized flag.
|
|
45924
|
-
Verify: Run /status to see project status.
|
|
45925
|
-
Observation focus: memory system concept, session initialization flow.
|
|
45926
|
-
|
|
45927
|
-
When automation is custom:
|
|
45928
|
-
Read CLAUDE.md in full. Explain the session initialization sequence: CLAUDE.md ->
|
|
45929
|
-
navigation table -> memory files -> context loading. Walk through: Commands section
|
|
45930
|
-
(3 commands + work and creds skills), Rules section (auto-loaded based on file paths), Skills
|
|
45931
|
-
section (auto-triggered by content patterns). Point out the initialized flag and
|
|
45932
|
-
explain how /init set it.
|
|
45933
|
-
Verify: Run /status to see project status; observe which fields it reports.
|
|
45934
|
-
Observation focus: initialization model, command-vs-rule-vs-skill distinction.
|
|
45935
|
-
|
|
45936
|
-
**Item 3: Project Commands (/init, /status, /fix, /deploy)**
|
|
45937
|
-
|
|
45938
|
-
When automation is none:
|
|
45939
|
-
"Think of /status as your project dashboard -- it shows what's healthy and what needs
|
|
45940
|
-
attention." Run /status and narrate the output in plain language: what each field means.
|
|
45941
|
-
Explain /fix as "the agent tidies up and applies updates."
|
|
45942
|
-
Explain /deploy as "the agent publishes your changes in one step." Mention the
|
|
45943
|
-
diagnostics skill: "If something goes wrong, the assistant automatically investigates."
|
|
45944
|
-
Verify: Run /status. Narrate the output together.
|
|
45945
|
-
Observation focus: project lifecycle concept, dashboard reading.
|
|
45946
|
-
|
|
45947
|
-
When automation is low-code:
|
|
45948
|
-
Show all project commands with their purpose. Map to familiar concepts: /fix is
|
|
45949
|
-
like "repair this Zap" in Zapier; /deploy is a one-command publish pipeline.
|
|
45950
|
-
Walk through /status output: template version (SDK template your workspace
|
|
45951
|
-
uses), SDK version (installed package), profile summary, drift check. Mention the
|
|
45952
|
-
diagnostics skill auto-triggers on execution failures.
|
|
45953
|
-
Verify: Run /status and interpret each field together.
|
|
45954
|
-
Observation focus: deploy pipeline understanding, version tracking.
|
|
45955
|
-
|
|
45956
|
-
When automation is custom:
|
|
45957
|
-
Read each command file in \`.claude/commands/\`: init.md (/init -- first-run setup
|
|
45958
|
-
with assessment), status.md (/status -- health dashboard), fix.md (/fix -- drift
|
|
45959
|
-
repair + SDK upgrade + rules health), deploy.md (/deploy -- 9-step pipeline: check,
|
|
45960
|
-
typecheck, docs, git, deploy, project-map, verify, state, push). Explain the
|
|
45961
|
-
diagnostics skill (auto-triggered on execution failures for runtime debugging).
|
|
45962
|
-
Explain the merge strategy for CLAUDE.md and commands. Note the template access
|
|
45963
|
-
model: templates read from @elevasis/sdk/templates subpath.
|
|
45964
|
-
Verify: Run /status to see project status. Identify what a version mismatch looks like.
|
|
45965
|
-
Observation focus: full lifecycle coverage, pipeline internals.
|
|
45966
|
-
|
|
45967
|
-
**Item 4: /work and /docs**
|
|
45968
|
-
|
|
45969
|
-
When automation is none:
|
|
45970
|
-
"You can ask the assistant to track work across conversations. Just say /work and tell it
|
|
45971
|
-
what you're working on -- it figures out the rest. It'll save your progress automatically,
|
|
45972
|
-
and next session you just say /work to pick up where you left off." Walk through the
|
|
45973
|
-
concept without deep command details. Then introduce /docs:
|
|
45974
|
-
"When a task is done, the assistant will ask if you want to finalize it -- that moves it
|
|
45975
|
-
to docs/ permanently. /docs helps you find and read what's there -- like a notebook for
|
|
45976
|
-
your project." Run /docs (no args) to show the docs/ overview together.
|
|
45977
|
-
Verify: Run \`/work\` and describe "practice task", see it created automatically.
|
|
45978
|
-
Then run /docs to see the docs/ structure.
|
|
45979
|
-
Observation focus: persistence concept, cross-session continuity, docs as permanent notes.
|
|
45980
|
-
|
|
45981
|
-
When automation is low-code:
|
|
45982
|
-
Show /work as intent-driven: the agent detects whether to create, resume, or save based
|
|
45983
|
-
on context. Create happens when you describe new work, resume when you pick an existing
|
|
45984
|
-
task, save happens automatically when progress is made. Complete is the only action that
|
|
45985
|
-
asks permission first.
|
|
45986
|
-
Then introduce /docs: "/docs is for permanent knowledge -- things that don't expire. Use
|
|
45987
|
-
/docs create to document a workflow or integration. Use /docs verify to check if your
|
|
45988
|
-
docs match the current code." Explain the boundary: /work manages in-progress/, /docs
|
|
45989
|
-
manages permanent docs/.
|
|
45990
|
-
Verify: Run \`/work\` and describe "practice task", see auto-create. Make some changes,
|
|
45991
|
-
then notice auto-save. Then run /docs to browse docs/.
|
|
45992
|
-
Observation focus: intent-driven task tracking, /work vs /docs separation.
|
|
45993
|
-
|
|
45994
|
-
When automation is custom:
|
|
45995
|
-
Read \`.claude/skills/work/SKILL.md\`. Full /work coverage:
|
|
45996
|
-
Intent detection table (list, create, resume, save auto-invoked; complete always suggests).
|
|
45997
|
-
Task doc anatomy: kebab-case filename, frontmatter with status, Objective/Plan/Progress/
|
|
45998
|
-
Resume Context sections. Auto-save behavior: triggers on heavy context, wrap-up signals,
|
|
45999
|
-
2+ steps completed. Resolution order for resume: number, keyword match, single in-progress.
|
|
46000
|
-
Then read \`.claude/commands/docs.md\`. Cover /docs operations:
|
|
46001
|
-
/docs (default): browse permanent docs/, categorized with read-only auto-generated files
|
|
46002
|
-
separate; /docs create: interview-driven, resource-aware doc creation from src/ code
|
|
46003
|
-
analysis; /docs verify: cross-references resource IDs, schema fields, platform tools in
|
|
46004
|
-
docs against src/ -- standalone analog of /fix step 5.
|
|
46005
|
-
Explain the relationship: /work owns docs/in-progress/ (task lifecycle), completing a task
|
|
46006
|
-
moves docs to permanent location, /docs browses and verifies what's there.
|
|
46007
|
-
Verify: Create a task via /work, make progress, observe auto-save, then run /work complete
|
|
46008
|
-
to move it. Run /docs to see it in the permanent docs/ listing.
|
|
46009
|
-
Observation focus: intent detection, auto-save behavior, /work-to-/docs handoff, docs verification.
|
|
46010
|
-
|
|
46011
|
-
**Item 5: Your First Custom Workflow**
|
|
46012
|
-
|
|
46013
|
-
When automation is none:
|
|
46014
|
-
Frame the workflow as "a recipe." Use plain language: "settings" not "config",
|
|
46015
|
-
"what data it needs" not "contract", "instructions" not "steps", "where it starts"
|
|
46016
|
-
not "entryPoint." Agent writes all code changes. Agent runs \`elevasis-sdk exec\` to verify
|
|
46017
|
-
and narrates the result in plain terms.
|
|
46018
|
-
Observation focus: recipe-to-result connection.
|
|
46019
|
-
|
|
46020
|
-
When automation is low-code or custom:
|
|
46021
|
-
Modify the echo workflow. Walk through each part: config, contract, steps,
|
|
46022
|
-
entryPoint. Deploy: \`elevasis-sdk check\` then \`elevasis-sdk deploy\`. Test with
|
|
46023
|
-
\`elevasis-sdk exec echo --input '{"message":"hello"}'\`. Then open the Execution
|
|
46024
|
-
Runner in the Command Center, find the echo workflow, fill out the form, and
|
|
46025
|
-
run it from the UI. Compare the result to the CLI output.
|
|
46026
|
-
Observation focus: deployment-to-execution loop, TypeScript syntax comfort.
|
|
46027
|
-
|
|
46028
|
-
**Item 6: Understanding Data (Schemas)**
|
|
46029
|
-
|
|
46030
|
-
When automation is none:
|
|
46031
|
-
Frame as "What information does your automation need?" Describe types in plain English:
|
|
46032
|
-
text, number, yes/no, a choice from a list. NO Zod, no z.string(), no z.infer(), no
|
|
46033
|
-
code shown. Agent reads identity.md goals and writes the workflow schema. Agent runs
|
|
46034
|
-
\`elevasis-sdk exec\` with sample input and narrates the result.
|
|
46035
|
-
Observation focus: data-to-input connection, required vs optional understanding.
|
|
46036
|
-
|
|
46037
|
-
When automation is low-code:
|
|
46038
|
-
"Field mapping like Zapier, but with validation." Show Zod types briefly. Demonstrate
|
|
46039
|
-
how \`.describe()\` documents each field. Build schema based on identity.md goals.
|
|
46040
|
-
After deploy, run with \`elevasis-sdk exec --input '{...}'\` to verify each field.
|
|
46041
|
-
Observation focus: schema-to-input mapping, optional fields, types.
|
|
46042
|
-
|
|
46043
|
-
When automation is custom:
|
|
46044
|
-
Explain schemas in plain English (concepts page). Show common Zod types.
|
|
46045
|
-
Explain \`z.infer\`. Build a new workflow with real-world input schema based
|
|
46046
|
-
on the user's goals (read .claude/memory/profile/identity.md). After deploy,
|
|
46047
|
-
run with \`elevasis-sdk exec --input '{...}'\` to verify the schema and inspect
|
|
46048
|
-
the execution output.
|
|
46049
|
-
Observation focus: schema-to-input mapping, optional fields, types.
|
|
46050
|
-
|
|
46051
|
-
**Item 7: Using Platform Tools**
|
|
46052
|
-
|
|
46053
|
-
When automation is none:
|
|
46054
|
-
Frame as "Connecting your automation to a service you already use." Pick ONE
|
|
46055
|
-
service from identity.md tools. Agent makes the code edit -- no adapter or
|
|
46056
|
-
singleton explanation, no imports shown. Guide credential creation step-by-step
|
|
46057
|
-
via Command Center UI (Settings > Credentials). Show where the connection appears
|
|
46058
|
-
in Command View after deploy.
|
|
46059
|
-
Observation focus: service-connection concept, credential comfort.
|
|
46060
|
-
|
|
46061
|
-
When automation is low-code or custom:
|
|
46062
|
-
Explain platform tools (concepts page). Browse available tools via
|
|
46063
|
-
reference/platform-tools/index.mdx. Pick a tool based on user's goals.
|
|
46064
|
-
Build: add a tool step using typed adapters (preferred) or platform.call().
|
|
46065
|
-
Show adapter pattern: \`const attio = createAttioAdapter('cred')\`.
|
|
46066
|
-
Show singleton pattern: \`import { scheduler, llm } from '@elevasis/sdk/worker'\`.
|
|
46067
|
-
Guide credential creation: for API keys, use the \`creds\` skill or Settings >
|
|
46068
|
-
Credentials in the Command Center. For OAuth credentials, the UI is required.
|
|
46069
|
-
If using the approval tool, note that pending requests surface in Command Queue.
|
|
46070
|
-
See reference/platform-tools/adapters.mdx for full API.
|
|
46071
|
-
Observation focus: credential setup (CLI + UI), async/await.
|
|
46072
|
-
|
|
46073
|
-
**Item 8: Multi-Step Workflows**
|
|
46074
|
-
|
|
46075
|
-
When automation is none:
|
|
46076
|
-
Frame as "Step 1 passes its result to Step 2, like a relay race." Command View is
|
|
46077
|
-
PRIMARY teaching tool -- show the visual graph before explaining code. Agent builds
|
|
46078
|
-
the 2-step workflow. Agent runs \`elevasis-sdk exec\` to verify and shows output flow.
|
|
46079
|
-
User opens Command View to see the two nodes + arrow. Code is secondary.
|
|
46080
|
-
Observation focus: relay-race concept, visual graph comprehension.
|
|
46081
|
-
|
|
46082
|
-
When automation is low-code or custom:
|
|
46083
|
-
Chain steps with StepType.LINEAR. Build a 2-step workflow. Explain data
|
|
46084
|
-
flow between steps. Deploy and test. Then open the Command View and show the
|
|
46085
|
-
relationship edges between resources. Explain how declared relationships map
|
|
46086
|
-
to the visual graph.
|
|
46087
|
-
Observation focus: data flow reasoning, relationship visualization.
|
|
46088
|
-
|
|
46089
|
-
**Item 9: Decision Points**
|
|
46090
|
-
|
|
46091
|
-
When automation is none:
|
|
46092
|
-
Frame as "If the customer is VIP, do this -- otherwise, do that." No StepType.CONDITIONAL
|
|
46093
|
-
jargon -- focus on the concept, not the implementation. Agent adds the condition.
|
|
46094
|
-
Agent runs \`elevasis-sdk exec\` for both paths. Open Execution Logs to see which
|
|
46095
|
-
path ran. Guide log navigation step-by-step.
|
|
46096
|
-
Observation focus: branching concept understanding, log navigation.
|
|
46097
|
-
|
|
46098
|
-
When automation is low-code or custom:
|
|
46099
|
-
Conditional routing with StepType.CONDITIONAL. Add a condition to the
|
|
46100
|
-
multi-step workflow from Lesson 5. Test both paths. After testing, open
|
|
46101
|
-
Execution Logs in the Command Center, filter by the resource, and show how
|
|
46102
|
-
each path appears in the log detail (step trace, input/output).
|
|
46103
|
-
Observation focus: branching logic reasoning, execution log interpretation.
|
|
46104
|
-
|
|
46105
|
-
**Item 10: Going to Production**
|
|
46106
|
-
|
|
46107
|
-
When automation is none:
|
|
46108
|
-
Frame as "draft vs live" not "dev vs production." Error handling: "when something
|
|
46109
|
-
goes wrong with your data" / "when a connected service fails" -- no type names.
|
|
46110
|
-
Task Scheduler and Knowledge Base stay as-is (UI-friendly already). Open Deployments
|
|
46111
|
-
page to show version is active.
|
|
46112
|
-
Observation focus: draft/live concept, readiness for independent Command Center use.
|
|
46113
|
-
|
|
46114
|
-
When automation is low-code or custom:
|
|
46115
|
-
Change status from dev to production. Cover error handling: try/catch,
|
|
46116
|
-
ExecutionError, PlatformToolError. Create a schedule in Task Scheduler (use
|
|
46117
|
-
Recurring type for a cron schedule). If docs/ has pages, show Knowledge Base.
|
|
46118
|
-
Open Deployments page to confirm the latest version is active. Show CLI
|
|
46119
|
-
monitoring: elevasis-sdk executions, elevasis-sdk execution. Suggest next steps.
|
|
46120
|
-
Observation focus: readiness for independent operation (CLI + UI).
|
|
46121
|
-
|
|
46122
|
-
## Module Menu
|
|
46123
|
-
|
|
46124
|
-
Module order (items 11-19 in the main menu): hitl, schedules, notifications,
|
|
46125
|
-
integrations, error-handling, workflows, composition, llm, agents.
|
|
46126
|
-
|
|
46127
|
-
After completing a module, show the updated full menu table (## Menu).
|
|
46128
|
-
|
|
46129
|
-
## Module Flow
|
|
46130
|
-
|
|
46131
|
-
Each module follows this flow:
|
|
46132
|
-
1. Announce module title and what they'll build (1-2 sentences)
|
|
46133
|
-
2. Read the listed SDK reference docs for teaching context
|
|
46134
|
-
3. Guide user to build a resource exercising the module's concepts
|
|
46135
|
-
4. Verify it works (CLI + Command Center where applicable)
|
|
46136
|
-
5. Record observations in \`.claude/memory/tutorial-progress.md\`
|
|
46137
|
-
6. Show updated full menu table (## Menu)
|
|
46138
|
-
|
|
46139
|
-
## Modules
|
|
46140
|
-
|
|
46141
|
-
**Module: hitl -- Human-in-the-Loop**
|
|
46142
|
-
Read: \`reference/deployment/command-center.mdx\` (Command Queue section).
|
|
46143
|
-
Build: Add an approval gate using \`approval.requestApproval()\`. Test full lifecycle:
|
|
46144
|
-
trigger, see pending in Command Queue, approve/reject, observe resume.
|
|
46145
|
-
Key concepts: approval adapter, pending state, Command Queue UI, resume on decision.
|
|
46146
|
-
Verify: Trigger workflow, open Command Queue, approve, confirm completion.
|
|
46147
|
-
|
|
46148
|
-
**Module: schedules -- Task Scheduling**
|
|
46149
|
-
Read: \`reference/deployment/command-center.mdx\` (Task Scheduler section).
|
|
46150
|
-
Build: Create all three schedule types (Recurring cron, Relative delay, Absolute
|
|
46151
|
-
datetime). Use \`scheduler\` adapter for in-workflow scheduling.
|
|
46152
|
-
Key concepts: schedule types, cron syntax, scheduler adapter, Task Scheduler UI.
|
|
46153
|
-
Verify: Create each type in Task Scheduler, confirm scheduled execution in Execution Logs.
|
|
46154
|
-
|
|
46155
|
-
**Module: notifications -- Notification System**
|
|
46156
|
-
Read: \`reference/platform-tools/adapters.mdx\` (notifications, email singletons).
|
|
46157
|
-
Build: Add notification and email steps to a workflow. Send alerts on completion.
|
|
46158
|
-
Key concepts: notifications singleton, email singleton, alert patterns.
|
|
46159
|
-
Verify: Run workflow, check notification in Command Center, confirm email received.
|
|
46160
|
-
|
|
46161
|
-
**Module: integrations -- Real-World Integrations**
|
|
46162
|
-
Read: \`reference/platform-tools/index.mdx\`, \`reference/platform-tools/adapters.mdx\`,
|
|
46163
|
-
\`reference/platform-tools/index.mdx\`.
|
|
46164
|
-
Build: Pick a real integration adapter based on user's goals (read \`identity.md\`).
|
|
46165
|
-
Set up credential (OAuth via UI, API key via CLI). Build end-to-end integration workflow.
|
|
46166
|
-
Key concepts: adapter pattern, credential scoping, error handling for external calls.
|
|
46167
|
-
Verify: Run workflow with real credential, confirm external service call, test error
|
|
46168
|
-
handling with invalid credential.
|
|
46169
|
-
|
|
46170
|
-
**Module: error-handling -- Error Handling Mastery**
|
|
46171
|
-
Read: \`reference/resources/patterns.mdx\` (error handling),
|
|
46172
|
-
\`reference/troubleshooting.mdx\`.
|
|
46173
|
-
Build: Create a workflow demonstrating all three error types. Add try/catch,
|
|
46174
|
-
\`context.logger\`, and error recovery.
|
|
46175
|
-
Key concepts: ExecutionError, PlatformToolError, ToolingError, recovery patterns.
|
|
46176
|
-
Verify: Trigger each error type, confirm messages in Execution Logs with correct
|
|
46177
|
-
categorization.
|
|
46178
|
-
|
|
46179
|
-
**Module: workflows -- Advanced Workflows**
|
|
46180
|
-
Read: \`reference/resources/patterns.mdx\` (execution store, logging, organizing).
|
|
46181
|
-
Build: Refactor an existing workflow to use \`context.store\` for cross-step data,
|
|
46182
|
-
\`context.logger\` for structured logging, and organize into a domain directory.
|
|
46183
|
-
Add advanced schema patterns (nested objects, arrays, optional fields).
|
|
46184
|
-
Key concepts: context.store, context.logger, domain organization, schema depth.
|
|
46185
|
-
Verify: Run workflow, confirm store values in step output, check logs in Execution Logs.
|
|
46186
|
-
|
|
46187
|
-
**Module: composition -- Resource Composition**
|
|
46188
|
-
Read: \`reference/deployment/command-center.mdx\`, \`reference/resources/patterns.mdx\`.
|
|
46189
|
-
Build: Create two workflows where the first triggers the second using
|
|
46190
|
-
\`execution.trigger()\`. Declare the relationship.
|
|
46191
|
-
Key concepts: execution.trigger, relationship declarations, Command View graph edges.
|
|
46192
|
-
Verify: Deploy, see relationship edge in Command View, trigger parent and confirm
|
|
46193
|
-
child executes.
|
|
46194
|
-
|
|
46195
|
-
**Module: llm -- LLM Integration**
|
|
46196
|
-
Read: \`reference/platform-tools/adapters.mdx\` (llm singleton).
|
|
46197
|
-
Build: Create a workflow step using \`llm.generate()\` with structured output.
|
|
46198
|
-
Experiment with model selection and temperature.
|
|
46199
|
-
Key concepts: llm singleton, structured output, model selection, temperature.
|
|
46200
|
-
Verify: Run workflow, compare outputs with different settings, confirm structured output.
|
|
46201
|
-
|
|
46202
|
-
**Module: agents -- AI Agents**
|
|
46203
|
-
Read: \`reference/framework/agent.mdx\`.
|
|
46204
|
-
Build: Create an agent definition with tools. Configure LLM tool calling.
|
|
46205
|
-
Compare agent vs workflow for a task.
|
|
46206
|
-
Key concepts: agent definition, tool registration, LLM tool calling, execution trace.
|
|
46207
|
-
Verify: Run agent with \`elevasis-sdk exec\`, review tool call trace in Execution Logs.
|
|
46208
|
-
|
|
46209
|
-
## Advanced Workspace Track
|
|
46210
|
-
|
|
46211
|
-
The Advanced Workspace track teaches power-user workspace customization and maintenance --
|
|
46212
|
-
rules, memory, and the template lifecycle. Independent of the core path; can be taken at any time.
|
|
46213
|
-
|
|
46214
|
-
Each item follows the same flow as core lessons: announce, explain per skill level, verify, record observations.
|
|
46215
|
-
|
|
46216
|
-
**Item 20: Rules, Memory, and Customization**
|
|
46217
|
-
|
|
46218
|
-
When automation is none:
|
|
46219
|
-
"The assistant has a set of reminders specific to your project. Over time, when it
|
|
46220
|
-
makes the same mistake 3 times, you can tell it to always remember that rule -- it
|
|
46221
|
-
lives in a file so the rule sticks across conversations."
|
|
46222
|
-
Show \`.claude/rules/workspace-patterns.md\` without technical detail. Explain: "This
|
|
46223
|
-
is where YOUR project's rules go. The other rule files are updated automatically by
|
|
46224
|
-
SDK releases."
|
|
46225
|
-
Verify: Open \`.claude/rules/workspace-patterns.md\` and read the current content together.
|
|
46226
|
-
Observation focus: customization concept, owned vs managed files.
|
|
46227
|
-
|
|
46228
|
-
When automation is low-code:
|
|
46229
|
-
Show the \`.claude/rules/\` directory. Explain the two types: sdk-patterns.md (MANAGED --
|
|
46230
|
-
updated by elevasis-sdk update) and workspace-patterns.md (INIT_ONLY -- yours to edit).
|
|
46231
|
-
Explain path-scoping briefly: "These rules only activate when the agent is working on
|
|
46232
|
-
certain file types." Show an example rule with WRONG/RIGHT pattern. Explain error
|
|
46233
|
-
promotion: if something goes wrong 3+ times, add it here.
|
|
46234
|
-
Verify: Read \`.claude/rules/workspace-patterns.md\`. Note the "When to Add a Rule" section.
|
|
46235
|
-
Observation focus: two-tier ownership model, rule format.
|
|
46236
|
-
|
|
46237
|
-
When automation is custom:
|
|
46238
|
-
Read \`.claude/rules/sdk-patterns.md\` and \`.claude/rules/workspace-patterns.md\`.
|
|
46239
|
-
Explain MANAGED vs INIT_ONLY lifecycle. Show rule frontmatter structure (paths: for
|
|
46240
|
-
auto-loading by the agent). Explain the memory system layout: \`.claude/memory/\`
|
|
46241
|
-
(index.md root, profile/ subdirectory, errors/ for promoted issues,
|
|
46242
|
-
tutorial-progress.md). Explain error promotion: 3+ recurrences -> rule in
|
|
46243
|
-
workspace-patterns.md. Walk through how to add a new rule.
|
|
46244
|
-
Verify: Read \`.claude/rules/workspace-patterns.md\`. Add a sample rule entry together.
|
|
46245
|
-
Observation focus: MANAGED vs INIT_ONLY lifecycle, rule authoring, memory layout.
|
|
46246
|
-
|
|
46247
|
-
**Item 21: Template Lifecycle**
|
|
46248
|
-
|
|
46249
|
-
When automation is none:
|
|
46250
|
-
"When Elevasis SDK releases updates, the assistant can apply them to your workspace
|
|
46251
|
-
automatically. You don't have to redo your customizations." Explain /fix as
|
|
46252
|
-
the command that applies updates. Skip technical file classification details.
|
|
46253
|
-
Show \`docs/project-map.mdx\` briefly: "This is an auto-generated map of everything
|
|
46254
|
-
in your project -- the agent uses it for navigation."
|
|
46255
|
-
Verify: Run /fix (or explain what it would do). Check \`docs/project-map.mdx\`.
|
|
46256
|
-
Next steps: point to reference docs in docs/, encourage using /work for new tasks.
|
|
46257
|
-
Observation focus: update model concept, project map as navigation aid.
|
|
46258
|
-
|
|
46259
|
-
When automation is low-code:
|
|
46260
|
-
Explain MANAGED (auto-updated by elevasis-sdk update) vs INIT_ONLY (set once, yours).
|
|
46261
|
-
Show how /fix applies SDK updates with conflict handling: "If a file changed,
|
|
46262
|
-
it shows you both versions and lets you decide."
|
|
46263
|
-
Show \`docs/project-map.mdx\` and explain what it contains: resources, commands,
|
|
46264
|
-
rules, memory index. Note that deploy auto-regenerates it.
|
|
46265
|
-
Verify: Read \`elevasis.config.ts\` templateVersion. Compare to the running SDK version from /status.
|
|
46266
|
-
Observation focus: update workflow, project map freshness.
|
|
46267
|
-
|
|
46268
|
-
When automation is custom:
|
|
46269
|
-
Read \`elevasis.config.ts\` for the current templateVersion. Read \`docs/project-map.mdx\`.
|
|
46270
|
-
Explain the full template lifecycle: init (writes all files with classification),
|
|
46271
|
-
update (applies MANAGED changes, flags conflicts, preserves INIT_ONLY), fix (detects
|
|
46272
|
-
drift, offers SDK upgrade, runs full repair). Explain conflict handling: read current
|
|
46273
|
-
file, read template from @elevasis/sdk/templates, merge preserving customizations.
|
|
46274
|
-
Explain the project map: auto-generated by deploy, contains resource inventory,
|
|
46275
|
-
command list, rule list, memory index.
|
|
46276
|
-
Next steps: explore reference docs, use /work for complex tasks, build custom rules.
|
|
46277
|
-
Verify: Compare elevasis.config.ts templateVersion with output of /status. Identify any drift.
|
|
46278
|
-
Observation focus: full template lifecycle, conflict resolution pattern.
|
|
46279
|
-
|
|
46280
|
-
## Adaptation Rules
|
|
46281
|
-
|
|
46282
|
-
**automation: none**
|
|
46283
|
-
Use the non-technical variant for each lesson. Agent writes all code -- user
|
|
46284
|
-
never types code. Agent runs \`elevasis-sdk exec\` for verification and narrates results.
|
|
46285
|
-
Avoid all jargon; use analogies. CLI is the primary verification tool.
|
|
46286
|
-
Always deploy before directing the user to the Command Center.
|
|
46287
|
-
|
|
46288
|
-
**automation: low-code**
|
|
46289
|
-
Map concepts to Zapier/Make equivalents. Show code with plain-English explanations.
|
|
46290
|
-
CLI is the primary verification tool. Show Zod types with labels.
|
|
46291
|
-
|
|
46292
|
-
**automation: custom**
|
|
46293
|
-
Full technical content. Code-first. CLI and UI are equal. Condense explanations
|
|
46294
|
-
for intermediate/advanced users.
|
|
46295
|
-
|
|
46296
|
-
**General rules (all levels)**
|
|
46297
|
-
- If user is fast, acknowledge and offer to skip ahead within a lesson
|
|
46298
|
-
- After the user confirms readiness at the end of a lesson, update \`.claude/memory/tutorial-progress.md\`
|
|
46299
|
-
- If user demonstrates a level change, promote to skills.md Growth Log
|
|
46300
|
-
- After completing a module, show the updated full menu table
|
|
46301
|
-
- Adapt module depth to skill level as with lessons
|
|
46302
|
-
|
|
46303
|
-
## Progress Format
|
|
46304
|
-
|
|
46305
|
-
On first \`/tutorial\` invocation, if \`.claude/memory/tutorial-progress.md\` does not exist,
|
|
46306
|
-
create it with this exact format:
|
|
46307
|
-
|
|
46308
|
-
\`\`\`markdown
|
|
46309
|
-
# Tutorial Progress
|
|
46310
|
-
|
|
46311
|
-
Current: Not started
|
|
46312
|
-
Started: {today's date}
|
|
46313
|
-
Last Session: {today's date}
|
|
46314
|
-
|
|
46315
|
-
## Completed Lessons
|
|
46316
|
-
|
|
46317
|
-
| Item | Title | Completed | Duration |
|
|
46318
|
-
| --- | --- | --- | --- |
|
|
46319
|
-
|
|
46320
|
-
## Completed Modules
|
|
46321
|
-
|
|
46322
|
-
| Module | Title | Completed | Duration |
|
|
46323
|
-
| --- | --- | --- | --- |
|
|
46324
|
-
|
|
46325
|
-
## Capability Observations
|
|
46326
|
-
|
|
46327
|
-
| Source | Observation |
|
|
46328
|
-
| --- | --- |
|
|
46329
|
-
|
|
46330
|
-
## Assessment Notes
|
|
46331
|
-
|
|
46332
|
-
(none yet)
|
|
46333
|
-
\`\`\`
|
|
46334
|
-
|
|
46335
|
-
Update rules:
|
|
46336
|
-
- \`Current\`: free-form, e.g. "7: Using Platform Tools" or "M:integrations" or "20: Rules, Memory, and Customization"
|
|
46337
|
-
- \`Last Session\`: update to today's date on each \`/tutorial\` invocation
|
|
46338
|
-
- Completed Lessons: add a row when any numbered item (1-10, 20-21) finishes
|
|
46339
|
-
- Completed Modules: add a row when any module (items 11-19) finishes
|
|
46340
|
-
- Capability Observations: prefix source with item number for lessons (#), M:<id> for modules
|
|
46341
|
-
- Assessment Notes: bullet points of general skill observations
|
|
46342
|
-
|
|
46343
|
-
Backward-compatible: missing Completed Modules treated as empty. Old files with Completed MF Lessons: map entries to items 2-4 and 20-21 by lesson title match.
|
|
46344
|
-
`;
|
|
46345
|
-
}
|
|
46346
|
-
function claudeInitCommandTemplate() {
|
|
46347
|
-
return `# /init command
|
|
46348
|
-
|
|
46349
|
-
You are a project management assistant for this Elevasis workspace.
|
|
46350
|
-
|
|
46351
|
-
## Context
|
|
46352
|
-
|
|
46353
|
-
Read \`elevasis.config.ts\` to get the current \`templateVersion\`.
|
|
46354
|
-
Read \`package.json\` to get the installed \`@elevasis/sdk\` version.
|
|
46355
|
-
Read \`.claude/memory/index.md\` if it exists for project state.
|
|
46356
|
-
|
|
46357
|
-
## Operation
|
|
46358
|
-
|
|
46359
|
-
Guided setup for a freshly scaffolded workspace. Triggered automatically
|
|
46360
|
-
by the \`<!-- initialized: false -->\` flag in CLAUDE.md, or run manually.
|
|
46361
|
-
|
|
46362
|
-
1. **Install dependencies**
|
|
46363
|
-
Run \`pnpm install\`. Wait for completion. Report any errors.
|
|
46364
|
-
|
|
46365
|
-
2. **Setup environment**
|
|
46366
|
-
Read \`.env\`. It should contain only a single line: \`ELEVASIS_PLATFORM_KEY=\`.
|
|
46367
|
-
If \`ELEVASIS_PLATFORM_KEY\` is empty or missing, ask the user: "What is your
|
|
46368
|
-
Elevasis API key?" When the user provides it, write \`.env\` with exactly:
|
|
46369
|
-
\`\`\`
|
|
46370
|
-
ELEVASIS_PLATFORM_KEY=<value they provided>
|
|
46371
|
-
\`\`\`
|
|
46372
|
-
No other keys (no \`NODE_ENV\`, no extras). The \`.env\` file must contain
|
|
46373
|
-
only \`ELEVASIS_PLATFORM_KEY\`.
|
|
46374
|
-
Validate the key works: run \`elevasis-sdk resources\` (should return an empty
|
|
46375
|
-
list, not an auth error). If auth fails, tell the user their key appears
|
|
46376
|
-
invalid and ask them to check it in the Elevasis dashboard.
|
|
46377
|
-
|
|
46378
|
-
3. **Competency Assessment**
|
|
46379
|
-
Ask these questions to build the user's profile:
|
|
46380
|
-
|
|
46381
|
-
Identity & Goals (3 questions):
|
|
46382
|
-
- "What does your business or team do?"
|
|
46383
|
-
- "What do you want to automate with Elevasis?"
|
|
46384
|
-
- "Which tools does your team already use?" (email, CRM, spreadsheets, etc.)
|
|
46385
|
-
|
|
46386
|
-
Competency (2 questions):
|
|
46387
|
-
- "Have you used the Elevasis Command Center before?"
|
|
46388
|
-
Never used it -> platformNavigation: none
|
|
46389
|
-
Explored it / know the main sections -> platformNavigation: oriented
|
|
46390
|
-
Use it regularly -> platformNavigation: comfortable
|
|
46391
|
-
- "Have you used automation tools? (Zapier, Make, cron jobs, scripts)"
|
|
46392
|
-
No -> automation: none
|
|
46393
|
-
Zapier/Make flows -> automation: low-code
|
|
46394
|
-
Custom scripts -> automation: custom
|
|
46395
|
-
|
|
46396
|
-
Inferred dimensions (do NOT ask, derive from answers above):
|
|
46397
|
-
- apiIntegration: automation: none -> none, low-code -> basic, custom -> proficient.
|
|
46398
|
-
Override: if tools answer includes API services (Stripe API, webhook, REST), upgrade one level.
|
|
46399
|
-
- domainExpertise: if goals are specific (names processes, metrics, edge cases) -> high.
|
|
46400
|
-
If goals are vague -> low.
|
|
46401
|
-
|
|
46402
|
-
Communication (1 question):
|
|
46403
|
-
- "Step-by-step explanations or concise answers?"
|
|
46404
|
-
|
|
46405
|
-
Write responses to memory:
|
|
46406
|
-
- Create \`.claude/memory/index.md\` (root index)
|
|
46407
|
-
- Create \`.claude/memory/profile/index.md\` (profile index)
|
|
46408
|
-
- Create \`.claude/memory/profile/identity.md\` (org, goals, tools)
|
|
46409
|
-
- Create \`.claude/memory/profile/skills.md\` using this exact format:
|
|
46410
|
-
|
|
46411
|
-
\`\`\`markdown
|
|
46412
|
-
# Skills
|
|
46413
|
-
|
|
46414
|
-
| Dimension | Level | Since |
|
|
46415
|
-
| --- | --- | --- |
|
|
46416
|
-
| platformNavigation | {level} | {date} |
|
|
46417
|
-
| apiIntegration | {level} | {date} |
|
|
46418
|
-
| automation | {level} | {date} |
|
|
46419
|
-
| domainExpertise | {level} | {date} |
|
|
46420
|
-
|
|
46421
|
-
## Growth Log
|
|
46422
|
-
|
|
46423
|
-
| Date | Observation | Dimension | Change |
|
|
46424
|
-
| --- | --- | --- | --- |
|
|
46425
|
-
\`\`\`
|
|
46426
|
-
|
|
46427
|
-
- Create \`.claude/memory/profile/preferences.md\` (verbosity, guidance)
|
|
46428
|
-
|
|
46429
|
-
4. **Git check**
|
|
46430
|
-
- If \`.git/\` exists: note git is configured in .claude/memory/profile/preferences.md
|
|
46431
|
-
- If \`.git/\` does not exist: suggest \`git init\` and optionally GitHub
|
|
46432
|
-
- If git remote exists: note remote URL in .claude/memory/profile/preferences.md
|
|
46433
|
-
|
|
46434
|
-
5. **Verify project**
|
|
46435
|
-
Run \`elevasis-sdk check\` to confirm the starter resource is valid.
|
|
46436
|
-
Optionally deploy the echo workflow.
|
|
46437
|
-
|
|
46438
|
-
6. **Report**
|
|
46439
|
-
Summary of what was set up. Suggest next steps based on goals.
|
|
46440
|
-
|
|
46441
|
-
If the user's Platform Navigation level is none or automation level is none,
|
|
46442
|
-
suggest /tutorial: "I recommend starting with /tutorial -- it walks
|
|
46443
|
-
you through building workflows step by step, at your own pace."
|
|
46444
|
-
|
|
46445
|
-
7. **Update flag**
|
|
46446
|
-
Change \`<!-- initialized: false -->\` to \`<!-- initialized: true -->\`
|
|
46447
|
-
in CLAUDE.md.
|
|
46448
|
-
`;
|
|
46449
|
-
}
|
|
46450
|
-
function claudeStatusCommandTemplate() {
|
|
46451
|
-
return `# /status command
|
|
46452
|
-
|
|
46453
|
-
You are a project management assistant for this Elevasis workspace.
|
|
46454
|
-
|
|
46455
|
-
## Context
|
|
46456
|
-
|
|
46457
|
-
Read \`elevasis.config.ts\` to get the current \`templateVersion\`.
|
|
46458
|
-
Read \`package.json\` to get the installed \`@elevasis/sdk\` version.
|
|
46459
|
-
Read \`.claude/memory/index.md\` if it exists for project state.
|
|
46460
|
-
|
|
46461
|
-
## Operation
|
|
46462
|
-
|
|
46463
|
-
Display a project health summary:
|
|
46464
|
-
1. Template version (from elevasis.config.ts) and installed SDK version (from package.json). Suggest \`elevasis-sdk update\` to check for updates
|
|
46465
|
-
2. Profile summary (from .claude/memory/profile/skills.md)
|
|
46466
|
-
3. Quick drift check: count of missing managed files, missing gitignore entries
|
|
46467
|
-
4. Last deployment status (from .claude/memory/deployment-state.md if it exists)
|
|
46468
|
-
`;
|
|
46469
|
-
}
|
|
46470
|
-
function claudeFixCommandTemplate() {
|
|
46471
|
-
return `# /fix command
|
|
46472
|
-
|
|
46473
|
-
You are a project management assistant for this Elevasis workspace.
|
|
46474
|
-
|
|
46475
|
-
## Context
|
|
46476
|
-
|
|
46477
|
-
Read \`elevasis.config.ts\` to get the current \`templateVersion\`.
|
|
46478
|
-
Read \`package.json\` to get the installed \`@elevasis/sdk\` version.
|
|
46479
|
-
Read \`.claude/memory/index.md\` if it exists for project state.
|
|
46480
|
-
|
|
46481
|
-
## Operation
|
|
46482
|
-
|
|
46483
|
-
Detect and repair all drift. Optionally upgrades the SDK first.
|
|
46484
|
-
|
|
46485
|
-
0. **SDK version check** -- Compare installed \`@elevasis/sdk\` against the latest
|
|
46486
|
-
available. If behind, offer to run \`pnpm update @elevasis/sdk\` before
|
|
46487
|
-
continuing. If the user accepts, run it, then run \`elevasis-sdk update\` to add
|
|
46488
|
-
any new managed files and flag conflicts. For each flagged file:
|
|
46489
|
-
- Read the current project file and the new template from \`@elevasis/sdk/templates\`
|
|
46490
|
-
- Add new sections that don't exist; preserve user customizations
|
|
46491
|
-
- If a section differs, show both versions and let the user choose
|
|
46492
|
-
1. **Missing managed files:** Regenerate from templates
|
|
46493
|
-
2. **Gitignore drift:** Append missing entries
|
|
46494
|
-
3. **CLAUDE.md sections:** Add missing sections in correct position
|
|
46495
|
-
4. **Memory structure:** Create base structure if missing, then verify index consistency.
|
|
46496
|
-
If \`.claude/memory/\` does not exist or is empty:
|
|
46497
|
-
- Create \`.claude/memory/index.md\` (root index with placeholder entries)
|
|
46498
|
-
- Create \`.claude/memory/errors/index.md\` (error category summary, empty tables)
|
|
46499
|
-
- Create \`.claude/memory/errors/deploy.md\`, \`.claude/memory/errors/runtime.md\`, \`.claude/memory/errors/typescript.md\`
|
|
46500
|
-
If memory exists, verify: every file referenced in an index exists; every file
|
|
46501
|
-
without an index entry gets one added; broken references are removed.
|
|
46502
|
-
5. **Documentation verification:** For each file in docs/:
|
|
46503
|
-
a. Cross-reference claims against src/ code (resource IDs, schema fields, platform tools used)
|
|
46504
|
-
b. Verify file path references point to real files
|
|
46505
|
-
c. Flag mismatches between documented schemas and actual resource definitions
|
|
46506
|
-
d. Check for undocumented resources (resources in src/ without docs coverage)
|
|
46507
|
-
e. Report discrepancies with suggested fixes
|
|
46508
|
-
Note: \`/docs verify\` is available for standalone interactive verification outside this pipeline.
|
|
46509
|
-
6. **Settings consistency:** Verify expected fields
|
|
46510
|
-
7. **Rules health:** Scan \`.claude/memory/errors/\` -- flag any entry that has recurred
|
|
46511
|
-
3+ times and is not yet in \`.claude/rules/workspace-patterns.md\`.
|
|
46512
|
-
If \`workspace-patterns.md\` has no rules yet and 5+ resources exist in \`src/\`,
|
|
46513
|
-
suggest adding patterns. Surface suggestions only -- do not auto-generate.
|
|
46514
|
-
8. **Project map freshness:** Check whether \`docs/project-map.mdx\` reflects the
|
|
46515
|
-
current project state (resources, commands, rules, skills, memory files).
|
|
46516
|
-
Compare filesystem state against the map. If stale, run \`elevasis-sdk deploy\`
|
|
46517
|
-
to regenerate, or patch inline for minor drift.
|
|
46518
|
-
|
|
46519
|
-
Each step reports its result. Steps 1-8 run even if step 0 is skipped.
|
|
46520
|
-
|
|
46521
|
-
## Merge Strategy
|
|
46522
|
-
|
|
46523
|
-
- **CLAUDE.md:** Add new sections in correct position. Preserve customizations.
|
|
46524
|
-
- **Commands:** Usually additive. Show diff for changes.
|
|
46525
|
-
- **.gitignore:** Append-only -- never remove existing entries.
|
|
46526
|
-
|
|
46527
|
-
## Template Access
|
|
46528
|
-
|
|
46529
|
-
The agent reads current templates from the installed SDK:
|
|
46530
|
-
\`@elevasis/sdk/templates\` subpath exports all template functions.
|
|
46531
|
-
`;
|
|
46532
|
-
}
|
|
46533
|
-
function claudeDeployCommandTemplate() {
|
|
46534
|
-
return `# /deploy command
|
|
46535
|
-
|
|
46536
|
-
You are a project management assistant for this Elevasis workspace.
|
|
46537
|
-
|
|
46538
|
-
## Context
|
|
46539
|
-
|
|
46540
|
-
Read \`elevasis.config.ts\` to get the current \`templateVersion\`.
|
|
46541
|
-
Read \`package.json\` to get the installed \`@elevasis/sdk\` version.
|
|
46542
|
-
Read \`.claude/memory/index.md\` if it exists for project state.
|
|
46543
|
-
|
|
46544
|
-
## Operation
|
|
46545
|
-
|
|
46546
|
-
0. Read \`reference/deployment/command-center.mdx\` -- understand the Command View
|
|
46547
|
-
model, relationship declarations, and what deploy-time validation checks.
|
|
46548
|
-
This context is essential for diagnosing validation failures in steps 1-2.
|
|
46549
|
-
1. Run \`elevasis-sdk check\` (validation)
|
|
46550
|
-
2. Type check if \`tsconfig.json\` exists
|
|
46551
|
-
3. Verify docs reflect current resources
|
|
46552
|
-
4. If git configured: stage changes, commit with deploy message
|
|
46553
|
-
5. Run \`elevasis-sdk deploy\`
|
|
46554
|
-
6. \`docs/project-map.mdx\` is auto-regenerated by deploy (no manual bump needed)
|
|
46555
|
-
7. Verify deployment via platform
|
|
46556
|
-
8. Update \`.claude/memory/deployment-state.md\` with count, timestamp, inventory
|
|
46557
|
-
9. If git configured and remote exists: optionally push
|
|
46558
|
-
|
|
46559
|
-
Each step reports its result. Pipeline stops on failure with suggested fix.
|
|
46560
|
-
If validation fails with relationship errors, re-read \`reference/deployment/command-center.mdx\`
|
|
46561
|
-
for the enforcement model and common fixes.
|
|
46562
|
-
`;
|
|
46563
|
-
}
|
|
46564
|
-
function claudeDiagnosticsSkillTemplate() {
|
|
46565
|
-
return `---
|
|
46566
|
-
name: diagnostics
|
|
46567
|
-
description: "Execution diagnostics and runtime debugging. TRIGGER when: an execution fails, user asks why something failed or errored, user mentions runtime errors or unexpected behavior, or agent observes a failed execution result. DO NOT TRIGGER when: user is discussing errors in code (type errors, lint errors) or build failures -- those are development issues, not runtime diagnostics."
|
|
46568
|
-
---
|
|
46569
|
-
|
|
46570
|
-
# Execution Diagnostics
|
|
46571
|
-
|
|
46572
|
-
You are a runtime diagnostics assistant for this Elevasis workspace.
|
|
46573
|
-
|
|
46574
|
-
## Context
|
|
46575
|
-
|
|
46576
|
-
Read \`.claude/memory/errors/index.md\` if it exists for past error patterns.
|
|
46577
|
-
Read \`.claude/memory/deployment-state.md\` if it exists for deployment context.
|
|
46578
|
-
|
|
46579
|
-
## When Triggered
|
|
46580
|
-
|
|
46581
|
-
Diagnose runtime failures and environment issues:
|
|
46582
|
-
|
|
46583
|
-
1. **Identify the failure** -- get the execution ID and resource ID from the error or conversation context
|
|
46584
|
-
2. **Pull execution details** -- run \`elevasis-sdk execution <resource-id> <execution-id>\` to get logs
|
|
46585
|
-
3. **Cross-reference** -- check \`.claude/memory/errors/\` for known patterns
|
|
46586
|
-
4. **Check deployment status** -- is the resource deployed? Is it the latest version?
|
|
46587
|
-
5. **Verify environment** -- API key valid, required credentials accessible
|
|
46588
|
-
6. **Diagnose root cause** -- analyze logs, identify the failing step, trace the error
|
|
46589
|
-
7. **Record** -- save new error patterns to \`.claude/memory/errors/\` with context and fix
|
|
46590
|
-
8. **Suggest fix** -- propose a concrete fix or next step
|
|
46591
|
-
|
|
46592
|
-
If the error has occurred before (found in memory/errors/), apply the known fix directly.
|
|
46593
|
-
If it recurs 3+ times, suggest adding a rule to \`.claude/rules/workspace-patterns.md\`.
|
|
46594
|
-
`;
|
|
46595
|
-
}
|
|
46596
|
-
function claudeWorkSkillTemplate() {
|
|
46597
|
-
return `---
|
|
46598
|
-
name: work
|
|
46599
|
-
description: "Task tracking and progress persistence. TRIGGER when: user says /work, asks to track or save progress across sessions, asks what they were working on, wants to create/resume/complete a task doc, or says they are done for today. DO NOT TRIGGER when: user is just doing work without wanting to track it in docs/in-progress/."
|
|
46600
|
-
---
|
|
46601
|
-
|
|
46602
|
-
# Task Tracking
|
|
46603
|
-
|
|
46604
|
-
You are a task tracking assistant for this Elevasis workspace. \`/work\` is the primary interface for managing all work and projects.
|
|
46605
|
-
|
|
46606
|
-
Your job is to **intelligently manage tasks without requiring the user to know subcommands**. Detect what the user needs from context and act accordingly.
|
|
46607
|
-
|
|
46608
|
-
## Context
|
|
46609
|
-
|
|
46610
|
-
Read \`docs/priorities.mdx\` if it exists for current priorities.
|
|
46611
|
-
Scan \`docs/in-progress/\` recursively for \`.mdx\` files with \`status\` frontmatter.
|
|
46612
|
-
|
|
46613
|
-
## Directory Structure
|
|
46614
|
-
|
|
46615
|
-
Task docs live in \`docs/in-progress/\`. Organize intelligently:
|
|
46616
|
-
|
|
46617
|
-
- **Small standalone tasks**: \`docs/in-progress/<slug>.mdx\`
|
|
46618
|
-
- **Multi-file tasks**: \`docs/in-progress/<slug>/index.mdx\` (+ supporting docs)
|
|
46619
|
-
- **Related tasks**: group under the same directory
|
|
46620
|
-
|
|
46621
|
-
When scanning, treat \`index.mdx\` as the primary task doc for a directory.
|
|
46622
|
-
|
|
46623
|
-
## Status Values
|
|
46624
|
-
|
|
46625
|
-
Enforce exactly three values in frontmatter: \`planned\`, \`in-progress\`, \`complete\`.
|
|
46626
|
-
|
|
46627
|
-
## Intent Detection
|
|
46628
|
-
|
|
46629
|
-
When \`/work\` is invoked (with or without arguments), detect intent from context:
|
|
46630
|
-
|
|
46631
|
-
| Signal | Action |
|
|
46632
|
-
|--------|--------|
|
|
46633
|
-
| No arguments, no active conversation context | **List** tasks, then let user pick |
|
|
46634
|
-
| User picks a number or names a task | **Resume** that task automatically |
|
|
46635
|
-
| User describes new work (not matching existing tasks) | **Create** a task doc automatically |
|
|
46636
|
-
| \`/work\` with a description that matches no existing task | **Create** automatically |
|
|
46637
|
-
| \`/work\` with a keyword/name matching an existing task | **Resume** automatically |
|
|
46638
|
-
| Conversation is getting heavy, user wrapping up, or 2+ steps completed | **Save** automatically |
|
|
46639
|
-
| All plan steps are COMPLETE | **Suggest** \`/work complete\` (never auto-invoke) |
|
|
46640
|
-
|
|
46641
|
-
**Key principle:** Create, save, and resume are auto-invoked. Complete always asks permission first.
|
|
46642
|
-
|
|
46643
|
-
## Behaviors
|
|
46644
|
-
|
|
46645
|
-
### List and Pick (default when no context)
|
|
46646
|
-
|
|
46647
|
-
1. Scan \`docs/in-progress/\` recursively for \`.mdx\` files with \`status\` frontmatter
|
|
46648
|
-
2. For directories, read \`index.mdx\` as the primary task doc
|
|
46649
|
-
3. Display a numbered list sorted by status (\`in-progress\` first, then \`planned\`, then \`complete\`):
|
|
46650
|
-
|
|
46651
|
-
\`\`\`
|
|
46652
|
-
Active Tasks
|
|
46653
|
-
============
|
|
46654
|
-
|
|
46655
|
-
1. [in-progress] SDK Adapter Migration
|
|
46656
|
-
Last saved: 2026-03-02 | Step 3/5: Building factory adapters
|
|
46657
|
-
|
|
46658
|
-
2. [planned] Email Template System
|
|
46659
|
-
Created: 2026-03-01 | Not started
|
|
46660
|
-
|
|
46661
|
-
3. [complete] CRM Integration
|
|
46662
|
-
Completed: 2026-03-03
|
|
46663
|
-
|
|
46664
|
-
Pick a task by number or name, or describe new work to start.
|
|
46665
|
-
\`\`\`
|
|
46666
|
-
|
|
46667
|
-
4. Cross-reference with \`docs/priorities.mdx\` if it exists
|
|
46668
|
-
5. When the user picks a number or describes a task, auto-invoke the appropriate flow (resume or create)
|
|
46669
|
-
6. If no tasks found, ask: "What are you trying to accomplish?"
|
|
46670
|
-
|
|
46671
|
-
### Create (auto-invoked when new work detected)
|
|
46672
|
-
|
|
46673
|
-
1. If the user's intent is clear, skip the interview and create directly
|
|
46674
|
-
2. If ambiguous, ask 1-2 focused questions:
|
|
46675
|
-
- "What does success look like?" (acceptance criteria)
|
|
46676
|
-
- "Do we need to investigate anything first, or is the path clear?"
|
|
46677
|
-
3. Scan \`docs/in-progress/\` for existing directories related to the topic
|
|
46678
|
-
4. Determine directory placement:
|
|
46679
|
-
- If related to existing directory, create as a file within it
|
|
46680
|
-
- If new concept that may grow, create \`docs/in-progress/<slug>/index.mdx\`
|
|
46681
|
-
- If small/standalone, create \`docs/in-progress/<slug>.mdx\`
|
|
46682
|
-
5. Create the doc with \`status: planned\` and structured sections:
|
|
46683
|
-
|
|
46684
|
-
\`\`\`yaml
|
|
46685
|
-
---
|
|
46686
|
-
title: {Task Title}
|
|
46687
|
-
description: {Concise description}
|
|
46688
|
-
status: planned
|
|
46689
|
-
---
|
|
46690
|
-
\`\`\`
|
|
46691
|
-
|
|
46692
|
-
Sections: Objective (what and why), Plan (numbered steps), Progress (per-step tracking with PENDING markers), Resume Context (current state, key docs, "To continue" prompt).
|
|
46693
|
-
|
|
46694
|
-
6. Update \`docs/priorities.mdx\` if it exists
|
|
46695
|
-
7. Report what was created with location and step count
|
|
46696
|
-
|
|
46697
|
-
### Save (auto-invoked when progress detected)
|
|
46698
|
-
|
|
46699
|
-
Auto-save triggers (do NOT ask, just save):
|
|
46700
|
-
- The conversation context is getting heavy (many tool calls, large file reads)
|
|
46701
|
-
- The user appears to be wrapping up (thanks, goodbye, switching topics)
|
|
46702
|
-
- Significant progress has been made (2+ steps completed without saving)
|
|
46703
|
-
- Before a context reset
|
|
46704
|
-
|
|
46705
|
-
Save flow:
|
|
46706
|
-
1. Identify the current task from conversation context
|
|
46707
|
-
2. If not working on a tracked task, offer to create a new one
|
|
46708
|
-
3. Update Progress section:
|
|
46709
|
-
- Mark completed steps as \`COMPLETE\` with: what was done, key decisions, files changed
|
|
46710
|
-
- Mark current step as \`IN PROGRESS\` with current state
|
|
46711
|
-
- Leave future steps as \`PENDING\`
|
|
46712
|
-
4. Update Resume Context section with:
|
|
46713
|
-
- Current State ({today's date}): summary of accomplishments and next steps
|
|
46714
|
-
- Files Modified: table of file paths and descriptions of changes
|
|
46715
|
-
- Key docs to read on resume: file paths with why they matter
|
|
46716
|
-
- To continue: copy-pasteable prompt for the next session
|
|
46717
|
-
5. Set \`status\` appropriately (\`in-progress\` if ongoing)
|
|
46718
|
-
6. Briefly confirm: "Progress saved to {path}."
|
|
46719
|
-
|
|
46720
|
-
### Resume (auto-invoked when existing task detected)
|
|
46721
|
-
|
|
46722
|
-
**Resolution order:**
|
|
46723
|
-
1. If a number is given, map to the numbered list from the task list
|
|
46724
|
-
2. If a name/keyword is given, substring match against task titles and filenames in \`docs/in-progress/\`
|
|
46725
|
-
3. If no argument, scan for \`status: in-progress\` docs -- if one found, use it; if multiple, list and ask
|
|
46726
|
-
4. If multiple matches, list them and ask which to resume
|
|
46727
|
-
|
|
46728
|
-
**Resume flow:**
|
|
46729
|
-
1. Read the target task doc
|
|
46730
|
-
2. Parse the Resume Context section
|
|
46731
|
-
3. Load key docs listed in "Key docs to read on resume" in parallel
|
|
46732
|
-
4. Quick verify: check that referenced files exist (Glob), report warnings for missing files
|
|
46733
|
-
5. Present resume summary:
|
|
46734
|
-
|
|
46735
|
-
\`\`\`
|
|
46736
|
-
Resuming: {task title}
|
|
46737
|
-
========================
|
|
46738
|
-
|
|
46739
|
-
Last completed: Step {N}: {title}
|
|
46740
|
-
Next: Step {M}: {title}
|
|
46741
|
-
|
|
46742
|
-
Key context loaded:
|
|
46743
|
-
- {doc 1}
|
|
46744
|
-
- {doc 2}
|
|
46745
|
-
|
|
46746
|
-
Ready to continue. {Copy of "To continue" prompt}
|
|
46747
|
-
\`\`\`
|
|
46748
|
-
|
|
46749
|
-
### Complete (NEVER auto-invoked -- always suggest)
|
|
46750
|
-
|
|
46751
|
-
When all plan steps are COMPLETE, suggest: "All steps for '{task}' look done. Want me to finalize it?"
|
|
46752
|
-
|
|
46753
|
-
Only proceed after explicit user confirmation. Then:
|
|
46754
|
-
|
|
46755
|
-
1. **Validate readiness:** Check that all plan steps are marked COMPLETE. If not, warn and ask for confirmation.
|
|
46756
|
-
2. **Clean up the doc:**
|
|
46757
|
-
- Strip \`## Resume Context\` section entirely (header through next \`##\` or EOF)
|
|
46758
|
-
- Strip progress markers: \`COMPLETE\`, \`IN PROGRESS\`, \`PENDING\` from step headings
|
|
46759
|
-
- Remove steps still marked PENDING entirely (header + body) -- they were never done
|
|
46760
|
-
- Remove \`status\` from frontmatter (keep \`title\` and \`description\`)
|
|
46761
|
-
- Target 200-400 lines; flag if result exceeds 500 lines
|
|
46762
|
-
3. **Determine destination:**
|
|
46763
|
-
- Scan \`docs/\` (excluding \`docs/in-progress/\`) for existing directories related to this work
|
|
46764
|
-
- If a related directory exists, propose merging into it
|
|
46765
|
-
- If no related directory, propose \`docs/<slug>/\` or \`docs/<slug>.mdx\`
|
|
46766
|
-
- Present the proposed destination and ask user to confirm
|
|
46767
|
-
4. **Move the doc(s):**
|
|
46768
|
-
- Single file: move from \`docs/in-progress/\` to destination
|
|
46769
|
-
- Directory: move entire directory
|
|
46770
|
-
5. **Verify and report:**
|
|
46771
|
-
- Confirm destination exists, source removed
|
|
46772
|
-
- Check no leftover \`status:\` or \`## Resume Context\` in moved files
|
|
46773
|
-
- Update \`docs/priorities.mdx\` if it exists
|
|
46774
|
-
- Report: task title, cleanup stats (lines before/after), destination path
|
|
46775
|
-
`;
|
|
46776
|
-
}
|
|
46777
|
-
function claudeDocsCommandTemplate() {
|
|
46778
|
-
return `# /docs command
|
|
46779
|
-
|
|
46780
|
-
You are a documentation assistant for this Elevasis workspace. \`/docs\` manages the
|
|
46781
|
-
permanent \`docs/\` tree -- browsing, creating reference content, and verifying accuracy
|
|
46782
|
-
against code.
|
|
46783
|
-
|
|
46784
|
-
**Scope:** Everything in \`docs/\` EXCEPT:
|
|
46785
|
-
- \`docs/in-progress/\` -- \`/work\`'s territory
|
|
46786
|
-
- \`docs/project-map.mdx\` and \`docs/resource-map.mdx\` -- auto-generated, read-only
|
|
46787
|
-
|
|
46788
|
-
## Context
|
|
46789
|
-
|
|
46790
|
-
Read \`.claude/memory/profile/skills.md\` first. The \`automation\` skill level controls
|
|
46791
|
-
how results are presented.
|
|
46792
|
-
|
|
46793
|
-
## Operations
|
|
46794
|
-
|
|
46795
|
-
### \`/docs\` (no arguments) -- Browse
|
|
46796
|
-
|
|
46797
|
-
Scan \`docs/\` recursively. Display:
|
|
46798
|
-
|
|
46799
|
-
\`\`\`
|
|
46800
|
-
Your Docs
|
|
46801
|
-
=========
|
|
46802
|
-
|
|
46803
|
-
Auto-generated (read-only):
|
|
46804
|
-
project-map.mdx Updated 2026-03-03
|
|
46805
|
-
resource-map.mdx Updated 2026-03-03
|
|
46806
|
-
|
|
46807
|
-
Reference (3):
|
|
46808
|
-
1. index.mdx Workspace overview
|
|
46809
|
-
2. priorities.mdx Current priorities
|
|
46810
|
-
3. crm-integration/ CRM integration guide (2 files)
|
|
46811
|
-
|
|
46812
|
-
Pick a number to read and discuss, or say:
|
|
46813
|
-
"create" to write a new doc
|
|
46814
|
-
"verify" to check docs against current code
|
|
46815
|
-
\`\`\`
|
|
46816
|
-
|
|
46817
|
-
Steps:
|
|
46818
|
-
1. Scan \`docs/\` recursively for \`.mdx\` files, excluding \`in-progress/\`
|
|
46819
|
-
2. Separate auto-generated files (\`project-map.mdx\`, \`resource-map.mdx\`) into a
|
|
46820
|
-
read-only group -- show modification date, no number
|
|
46821
|
-
3. Number all user-maintained docs. For directories, show \`index.mdx\` as primary
|
|
46822
|
-
with file count
|
|
46823
|
-
4. Sort: \`index.mdx\` first, \`priorities.mdx\` second, then alphabetical
|
|
46824
|
-
5. When user picks a number: read the file and present a summary. Ask what they
|
|
46825
|
-
want -- discuss, update, or go back
|
|
46826
|
-
6. If only auto-generated files and \`index.mdx\` exist, suggest: "Your docs/ is
|
|
46827
|
-
mostly empty. Run \`/docs create\` to add reference documentation."
|
|
46828
|
-
|
|
46829
|
-
**automation: none** -- Frame as "your project's knowledge base." Plain language:
|
|
46830
|
-
"These are your project's permanent notes. Pick one to read or discuss."
|
|
46831
|
-
|
|
46832
|
-
**automation: low-code** -- Standard presentation. Map to "like a wiki for your automations."
|
|
46833
|
-
|
|
46834
|
-
**automation: custom** -- Compact. Show file sizes and last-modified dates.
|
|
46835
|
-
|
|
46836
|
-
---
|
|
46837
|
-
|
|
46838
|
-
### \`create [description]\` -- Reference Doc Creation
|
|
46839
|
-
|
|
46840
|
-
Interview-driven creation for permanent documentation. Task docs go through \`/work\`.
|
|
46841
|
-
|
|
46842
|
-
1. If no description given, ask: "What do you want to document?"
|
|
46843
|
-
2. Determine doc type (infer or ask):
|
|
46844
|
-
- **Resource guide** -- documents a specific workflow or agent
|
|
46845
|
-
- **Integration guide** -- how a specific external tool is used
|
|
46846
|
-
- **Architecture notes** -- design decisions, system diagrams
|
|
46847
|
-
- **Process doc** -- operational procedures, runbooks
|
|
46848
|
-
- **General reference** -- glossaries, onboarding, anything else
|
|
46849
|
-
3. If the doc is about a specific resource: scan \`src/\` for matching resource IDs.
|
|
46850
|
-
If found, pre-populate with resource config, schemas, step names, and platform
|
|
46851
|
-
tools used. The user does not need to describe what the resource does.
|
|
46852
|
-
4. Determine placement:
|
|
46853
|
-
- Scan \`docs/\` for existing directories related to the topic
|
|
46854
|
-
- If related to an existing directory, propose adding to it
|
|
46855
|
-
- If the topic may grow into multiple files, create \`docs/<slug>/index.mdx\`
|
|
46856
|
-
- If small and standalone, create \`docs/<slug>.mdx\`
|
|
46857
|
-
5. Create with proper frontmatter:
|
|
46858
|
-
\`\`\`yaml
|
|
46859
|
-
---
|
|
46860
|
-
title: Guide Title
|
|
46861
|
-
description: What this covers
|
|
46862
|
-
---
|
|
46863
|
-
\`\`\`
|
|
46864
|
-
Sections by doc type:
|
|
46865
|
-
- **Resource guide:** Overview, Input/Output, How It Works, Platform Tools Used, Configuration
|
|
46866
|
-
- **Integration guide:** Overview, Setup (credentials), Data Model, Usage Patterns, Troubleshooting
|
|
46867
|
-
- **Architecture notes:** Context, Decision, Consequences, Alternatives Considered
|
|
46868
|
-
- **Process doc:** Purpose, Prerequisites, Steps, Recovery
|
|
46869
|
-
- **General reference:** determined by content
|
|
46870
|
-
6. Report what was created and suggest next steps.
|
|
46871
|
-
|
|
46872
|
-
**automation: none** -- Agent writes the full doc from code analysis. User reviews and
|
|
46873
|
-
approves. "I've written a guide for your CRM integration based on the code. Take a look
|
|
46874
|
-
and tell me if anything is missing."
|
|
46875
|
-
|
|
46876
|
-
**automation: low-code** -- Agent drafts, highlights sections the user should customize.
|
|
46877
|
-
Shows what was auto-detected vs what needs human input.
|
|
46878
|
-
|
|
46879
|
-
**automation: custom** -- Agent scaffolds structure and fills in code-derived content.
|
|
46880
|
-
Leaves technical prose to the user. Concise.
|
|
46881
|
-
|
|
46882
|
-
---
|
|
46883
|
-
|
|
46884
|
-
### \`verify [file?]\` -- Interactive Documentation Verification
|
|
46885
|
-
|
|
46886
|
-
Standalone interactive version of \`/fix\` step 5. Checks docs against current code.
|
|
46887
|
-
|
|
46888
|
-
**Without argument -- verify all:**
|
|
46889
|
-
|
|
46890
|
-
1. Scan \`docs/\` for user-maintained \`.mdx\` files (skip \`in-progress/\`,
|
|
46891
|
-
\`project-map.mdx\`, \`resource-map.mdx\`)
|
|
46892
|
-
2. For each file: cross-reference resource IDs, schema fields, and platform tools
|
|
46893
|
-
mentioned against \`src/\`
|
|
46894
|
-
3. Check for undocumented resources: resources in \`src/\` without docs coverage
|
|
46895
|
-
4. Present results interactively:
|
|
46896
|
-
|
|
46897
|
-
\`\`\`
|
|
46898
|
-
Docs Verification
|
|
46899
|
-
=================
|
|
46900
|
-
|
|
46901
|
-
crm-integration/index.mdx:
|
|
46902
|
-
- Line 23: references resourceId "attio-sync" but src/ has "attio-sync-v2"
|
|
46903
|
-
- Line 45: schema field "companyName" no longer exists in input schema
|
|
46904
|
-
|
|
46905
|
-
onboarding-guide.mdx:
|
|
46906
|
-
- No issues found
|
|
46907
|
-
|
|
46908
|
-
Undocumented resources (2):
|
|
46909
|
-
- email-sender (src/communications/email-sender.ts)
|
|
46910
|
-
- lead-scorer (src/scoring/lead-scorer.ts)
|
|
46911
|
-
|
|
46912
|
-
Fix crm-integration issues now? (yes/no/skip)
|
|
46913
|
-
\`\`\`
|
|
46914
|
-
|
|
46915
|
-
5. When user says yes: read source code, apply fixes to doc, show the diff
|
|
46916
|
-
6. For undocumented resources: offer to create a doc for each one (invokes \`create\` flow)
|
|
46917
|
-
|
|
46918
|
-
**With argument -- verify one file:**
|
|
46919
|
-
|
|
46920
|
-
Same but scoped to a single file. Resolves by substring match against \`docs/\` file names.
|
|
46921
|
-
|
|
46922
|
-
\`\`\`
|
|
46923
|
-
/docs verify crm-integration
|
|
46924
|
-
\`\`\`
|
|
46925
|
-
|
|
46926
|
-
**automation: none** -- Plain language: "Your CRM guide mentions a field called
|
|
46927
|
-
'companyName' but that field was renamed to 'company'. Want me to fix it?"
|
|
46928
|
-
|
|
46929
|
-
**automation: low-code** -- Standard presentation with suggested fixes.
|
|
46930
|
-
|
|
46931
|
-
**automation: custom** -- Compact diff-style. Auto-fix obvious issues, ask only for
|
|
46932
|
-
ambiguous ones.
|
|
46933
|
-
|
|
46934
|
-
---
|
|
46935
|
-
|
|
46936
|
-
## What /docs Does NOT Do
|
|
46937
|
-
|
|
46938
|
-
- Touch \`docs/in-progress/\` -- \`/work\`'s territory
|
|
46939
|
-
- Handle task lifecycle (planned / in-progress / complete)
|
|
46940
|
-
- Edit \`project-map.mdx\` or \`resource-map.mdx\` -- auto-generated, read-only
|
|
46941
|
-
- Replace \`/fix\` step 5 -- it supplements it with interactivity
|
|
46942
|
-
`;
|
|
46943
|
-
}
|
|
46944
|
-
function claudeCredsSkillTemplate() {
|
|
46945
|
-
return `---
|
|
46946
|
-
name: creds
|
|
46947
|
-
description: "Credential management assistant. TRIGGER when: user mentions credentials, API keys, secrets, webhook secrets, or asks to set up integrations that need authentication. DO NOT TRIGGER when: user is discussing code that references credentials without needing to manage them."
|
|
46948
|
-
---
|
|
46949
|
-
|
|
46950
|
-
# Credential Management
|
|
46951
|
-
|
|
46952
|
-
You are a credential management assistant for this Elevasis workspace.
|
|
46953
|
-
|
|
46954
|
-
## Context
|
|
46955
|
-
|
|
46956
|
-
Credentials are stored encrypted (AES-256-GCM) on the Elevasis platform and scoped to your
|
|
46957
|
-
organization. They are used by workflows and agents at runtime via \`platform.getCredential()\`
|
|
46958
|
-
or the \`credential:\` field on tool steps.
|
|
46959
|
-
|
|
46960
|
-
The SDK CLI (\`elevasis-sdk creds\`) manages credentials via API key authentication.
|
|
46961
|
-
Your \`ELEVASIS_PLATFORM_KEY\` in \`.env\` determines the organization.
|
|
46962
|
-
|
|
46963
|
-
## Credential Types
|
|
46964
|
-
|
|
46965
|
-
| Type | Value Format | Example Providers |
|
|
46966
|
-
| --- | --- | --- |
|
|
46967
|
-
| \`api-key\` | \`{"apiKey": "sk-..."}\` | Stripe, Resend, Apify, Attio, Instantly |
|
|
46968
|
-
| \`webhook-secret\` | \`{"signingSecret": "whsec_..."}\` | Cal.com, Stripe webhooks |
|
|
46969
|
-
| \`oauth\` | N/A (browser flow only) | Notion, Google Sheets, Dropbox |
|
|
46970
|
-
|
|
46971
|
-
OAuth credentials **cannot** be created via CLI. Redirect the user to the Command Center UI.
|
|
46972
|
-
|
|
46973
|
-
## Naming Rules
|
|
46974
|
-
|
|
46975
|
-
- Lowercase letters, digits, and hyphens only (\`[a-z0-9-]\`)
|
|
46976
|
-
- No consecutive hyphens (\`--\`)
|
|
46977
|
-
- 1-100 characters
|
|
46978
|
-
- Convention: \`{org}-{provider}\` (e.g., \`tester-stripe-key\`, \`my-project-resend\`)
|
|
46979
|
-
|
|
46980
|
-
## Operations
|
|
46981
|
-
|
|
46982
|
-
**No arguments (default):** Show this reference and list credentials.
|
|
46983
|
-
|
|
46984
|
-
**\`list\`:** List all credentials for the organization.
|
|
46985
|
-
\`\`\`bash
|
|
46986
|
-
elevasis-sdk creds list
|
|
46987
|
-
\`\`\`
|
|
46988
|
-
Display the output. Note which are \`oauth\` (not modifiable via CLI).
|
|
46989
|
-
|
|
46990
|
-
**\`create\`:** Guided credential creation flow:
|
|
46991
|
-
1. Ask credential type (\`api-key\` or \`webhook-secret\`). Not \`oauth\`.
|
|
46992
|
-
2. Ask credential name. Validate naming rules before proceeding.
|
|
46993
|
-
3. Ask the user to paste the credential value directly in chat.
|
|
46994
|
-
- For \`api-key\`: ask for the API key, construct \`{"apiKey": "..."}\`
|
|
46995
|
-
- For \`webhook-secret\`: ask for the signing secret, construct \`{"signingSecret": "..."}\`
|
|
46996
|
-
4. Pipe to CLI: \`echo '{"apiKey":"..."}' | elevasis-sdk creds create --name {name} --type {type}\`
|
|
46997
|
-
5. Confirm success. **NEVER echo the credential value back.**
|
|
46998
|
-
|
|
46999
|
-
**\`update\`:** Update credential value:
|
|
47000
|
-
1. Run \`elevasis-sdk creds list\` to confirm the credential exists.
|
|
47001
|
-
2. Ask the user to paste the new value.
|
|
47002
|
-
3. Pipe to CLI: \`echo '{"apiKey":"..."}' | elevasis-sdk creds update {name}\`
|
|
47003
|
-
4. Confirm success. **NEVER echo the value.**
|
|
47004
|
-
|
|
47005
|
-
**\`rename\`:** Rename a credential:
|
|
47006
|
-
1. Run \`elevasis-sdk creds list\` to confirm it exists.
|
|
47007
|
-
2. Ask for the new name. Validate naming rules.
|
|
47008
|
-
3. Run: \`elevasis-sdk creds rename {name} --to {newName}\`
|
|
47009
|
-
|
|
47010
|
-
**\`delete\`:** Delete a credential:
|
|
47011
|
-
1. Run \`elevasis-sdk creds list\` to confirm it exists.
|
|
47012
|
-
2. Confirm with user before proceeding.
|
|
47013
|
-
3. Run: \`elevasis-sdk creds delete {name} --force\`
|
|
47014
|
-
|
|
47015
|
-
**\`webhook-url\`:** Generate a webhook URL:
|
|
47016
|
-
Ask for provider, org UUID, resource ID, and credential name. Construct:
|
|
47017
|
-
\`POST https://api.elevasis.io/api/webhooks/{provider}?org={uuid}&resource={resourceId}&credential={credentialName}\`
|
|
47018
|
-
|
|
47019
|
-
**\`audit\`:** Scan project for credential references:
|
|
47020
|
-
1. Search \`src/**/*.ts\` for \`credential:\` patterns and \`platform.getCredential()\` calls.
|
|
47021
|
-
2. Extract all credential names referenced.
|
|
47022
|
-
3. Run \`elevasis-sdk creds list\` to get the actual credential list.
|
|
47023
|
-
4. Report: missing credentials (referenced but not created), unused credentials (created but not referenced).
|
|
47024
|
-
|
|
47025
|
-
## Security Rules (MANDATORY)
|
|
47026
|
-
|
|
47027
|
-
- **NEVER** log, repeat, or display credential values after the user provides them
|
|
47028
|
-
- **NEVER** store credential values in files, memory, or command history
|
|
47029
|
-
- If an API call fails, ask the user to **re-paste** rather than retrying with a cached value
|
|
47030
|
-
- Always confirm name and type **before** asking for the value
|
|
47031
|
-
- OAuth credentials cannot be created via CLI -- redirect to Command Center UI
|
|
47032
|
-
`;
|
|
47033
|
-
}
|
|
47034
|
-
function claudeSdkPatternsRuleTemplate() {
|
|
47035
|
-
return `---
|
|
47036
|
-
description: Elevasis SDK patterns -- imports, source structure, runtime, and platform tools
|
|
47037
|
-
paths:
|
|
47038
|
-
- src/**
|
|
47039
|
-
- elevasis.config.ts
|
|
47040
|
-
---
|
|
47041
|
-
|
|
47042
|
-
# SDK Patterns
|
|
47043
|
-
|
|
47044
|
-
## Imports
|
|
47045
|
-
|
|
47046
|
-
- \`@elevasis/sdk\` -- types and constants: \`WorkflowDefinition\`, \`StepType\`, \`ExecutionError\`, \`ToolingError\`
|
|
47047
|
-
- \`@elevasis/sdk/worker\` -- runtime: \`platform\`, \`PlatformToolError\`, typed adapters
|
|
47048
|
-
- **Never import from \`@repo/core\`** -- monorepo-internal, not available in external projects
|
|
47049
|
-
|
|
47050
|
-
## Source Structure
|
|
47051
|
-
|
|
47052
|
-
- All resource definitions live in \`src/\` and are exported via \`src/index.ts\`
|
|
47053
|
-
- Organize by business domain: \`src/<domain>/\` (e.g., \`src/operations/\`, \`src/acquisition/\`)
|
|
47054
|
-
- Each domain barrel (\`src/<domain>/index.ts\`) exports \`workflows\` and \`agents\` arrays
|
|
47055
|
-
- Cross-domain utilities go in \`src/shared/\`; domain-specific utilities in \`src/<domain>/shared/\`
|
|
47056
|
-
- The default export in \`src/index.ts\` must be an \`OrganizationResources\` object
|
|
47057
|
-
- \`resourceId\` must be lowercase with hyphens, unique per organization
|
|
47058
|
-
- \`dist/\` is generated by deploy -- never commit it
|
|
47059
|
-
|
|
47060
|
-
## Runtime
|
|
47061
|
-
|
|
47062
|
-
- \`.env\` contains only \`ELEVASIS_PLATFORM_KEY\` for CLI auth -- never deployed, never in worker memory
|
|
47063
|
-
- Integration credentials are managed via the \`creds\` skill or Command Center UI
|
|
47064
|
-
|
|
47065
|
-
## Platform Tools
|
|
47066
|
-
|
|
47067
|
-
Prefer typed adapters over raw \`platform.call()\`.
|
|
47068
|
-
|
|
47069
|
-
### Singleton adapters (no credential needed)
|
|
47070
|
-
|
|
47071
|
-
\`\`\`typescript
|
|
47072
|
-
import { scheduler, storage, llm, notifications, acqDb, pdf, approval, execution, email } from '@elevasis/sdk/worker'
|
|
47073
|
-
\`\`\`
|
|
47074
|
-
|
|
47075
|
-
### Factory adapters (credential-bound)
|
|
47076
|
-
|
|
47077
|
-
\`\`\`typescript
|
|
47078
|
-
import { createAttioAdapter, createResendAdapter } from '@elevasis/sdk/worker'
|
|
47079
|
-
const attio = createAttioAdapter('credential-name')
|
|
47080
|
-
\`\`\`
|
|
47081
|
-
|
|
47082
|
-
Use \`platform.call()\` directly only for tools without adapters: \`supabase\`, \`session-memory\`, \`hitl\`, \`status\`, \`http\`.
|
|
47083
|
-
`;
|
|
47084
|
-
}
|
|
47085
|
-
function claudeWorkspaceRulesTemplate() {
|
|
47086
|
-
return `---
|
|
47087
|
-
description: Project-specific patterns for this workspace, promoted as the project grows
|
|
47088
|
-
paths:
|
|
47089
|
-
- src/**
|
|
47090
|
-
- .claude/rules/workspace-patterns.md
|
|
47091
|
-
---
|
|
47092
|
-
|
|
47093
|
-
# Workspace Patterns
|
|
47094
|
-
|
|
47095
|
-
Add project-specific patterns here as they emerge. Only add patterns that have already
|
|
47096
|
-
occurred multiple times or represent a deliberate convention -- not speculative rules.
|
|
47097
|
-
|
|
47098
|
-
## Rule File Ownership
|
|
47099
|
-
|
|
47100
|
-
This file is yours. The other \`.claude/rules/\` files are SDK-owned and updated by
|
|
47101
|
-
\`elevasis-sdk update\` -- do not add project-specific notes to them, add them here instead:
|
|
47102
|
-
|
|
47103
|
-
- \`sdk-patterns.md\` -- SDK imports, source structure, runtime, adapter patterns
|
|
47104
|
-
- \`docs-authoring.md\` -- MDX escaping, frontmatter, docs conventions
|
|
47105
|
-
- \`memory-conventions.md\` -- memory system structure and pruning
|
|
47106
|
-
- \`project-map.md\` -- auto-generated project map conventions
|
|
47107
|
-
- \`task-tracking.md\` -- in-progress task conventions
|
|
47108
|
-
- \`logging.md\` -- context.logger usage, console.log prohibition, logging standard
|
|
47109
|
-
|
|
47110
|
-
## When to Add a Rule
|
|
47111
|
-
|
|
47112
|
-
- An error has recurred 3+ times (CLAUDE.md instructs you to promote from \`.claude/memory/errors/\`)
|
|
47113
|
-
- A pattern appears across 3+ resources and is worth documenting for consistency
|
|
47114
|
-
- A naming or structural convention exists that future sessions would likely get wrong
|
|
47115
|
-
|
|
47116
|
-
## Patterns
|
|
47117
|
-
|
|
47118
|
-
<!-- Rules are added here as the project grows. Examples:
|
|
47119
|
-
- "All Attio records use 'attio-main' as the credential name"
|
|
47120
|
-
- "Workflow IDs follow the pattern: <domain>-<verb>-<noun>"
|
|
47121
|
-
- "Shared LLM prompt templates live in src/shared/prompts.ts"
|
|
47122
|
-
-->
|
|
47123
|
-
`;
|
|
47124
|
-
}
|
|
47125
|
-
function claudeDocsAuthoringRuleTemplate() {
|
|
47126
|
-
return `---
|
|
47127
|
-
description: Documentation conventions for docs/ files -- MDX escaping, frontmatter, structure
|
|
47128
|
-
paths:
|
|
47129
|
-
- docs/**/*.mdx
|
|
47130
|
-
---
|
|
47131
|
-
|
|
47132
|
-
# Docs Authoring
|
|
47133
|
-
|
|
47134
|
-
## MDX Escaping
|
|
47135
|
-
|
|
47136
|
-
- Less-than \`<\` must be \`\\<\` (MDX interprets bare \`<\` as JSX tag)
|
|
47137
|
-
- Curly braces \`{var}\` must be in backticks or escaped: \`\\{var\\}\`
|
|
47138
|
-
- Greater-than \`>\` must be \`\\>\`
|
|
47139
|
-
|
|
47140
|
-
## Frontmatter
|
|
47141
|
-
|
|
47142
|
-
Every \`.mdx\` file requires \`title\` and \`description\`:
|
|
47143
|
-
|
|
47144
|
-
\`\`\`yaml
|
|
47145
|
-
---
|
|
47146
|
-
title: Feature Name
|
|
47147
|
-
description: Concise description
|
|
47148
|
-
---
|
|
47149
|
-
\`\`\`
|
|
47150
|
-
|
|
47151
|
-
## Structure
|
|
47152
|
-
|
|
47153
|
-
- \`docs/project-map.mdx\` is auto-generated -- do not edit manually
|
|
47154
|
-
- \`docs/in-progress/\` for task tracking docs
|
|
47155
|
-
- Sort order via \`order\` frontmatter field (lower = earlier)
|
|
47156
|
-
`;
|
|
47157
|
-
}
|
|
47158
|
-
function claudeMemoryConventionsRuleTemplate() {
|
|
47159
|
-
return `---
|
|
47160
|
-
description: Memory system conventions -- what to store, structure, pruning
|
|
47161
|
-
paths:
|
|
47162
|
-
- .claude/memory/**
|
|
47163
|
-
---
|
|
47164
|
-
|
|
47165
|
-
# Memory Conventions
|
|
47166
|
-
|
|
47167
|
-
## What Memory Is
|
|
47168
|
-
|
|
47169
|
-
Memory stores persistent agent state: skills, errors, tutorial progress.
|
|
47170
|
-
It is NOT for instructions (commands), reference docs, or templates.
|
|
47171
|
-
|
|
47172
|
-
## Structure
|
|
47173
|
-
|
|
47174
|
-
- \`index.md\` at every level maps to children
|
|
47175
|
-
- Start at root index and drill down
|
|
47176
|
-
- When a file outgrows a single document, split into a subdirectory
|
|
47177
|
-
|
|
47178
|
-
## Pruning
|
|
47179
|
-
|
|
47180
|
-
- Keep ~20 recent entries per table; drop stale patterns (30+ days)
|
|
47181
|
-
- If an error recurs 3+ times, promote to \`.claude/rules/workspace-patterns.md\`
|
|
47182
|
-
`;
|
|
47183
|
-
}
|
|
47184
|
-
function claudeProjectMapRuleTemplate() {
|
|
47185
|
-
return `---
|
|
47186
|
-
description: Project map conventions -- auto-generated, do not edit, maintained by deploy and /fix
|
|
47187
|
-
paths:
|
|
47188
|
-
- docs/project-map.mdx
|
|
47189
|
-
- docs/resource-map.mdx
|
|
47190
|
-
---
|
|
47191
|
-
|
|
47192
|
-
# Project Map
|
|
47193
|
-
|
|
47194
|
-
- \`docs/project-map.mdx\` and \`docs/resource-map.mdx\` are fully auto-generated by \`elevasis-sdk deploy\`
|
|
47195
|
-
- Do not edit either file manually -- changes are overwritten on next deploy
|
|
47196
|
-
- \`/fix\` step 8 checks for drift and patches the map
|
|
47197
|
-
- If a new command, rule, skill, or memory file is added, run \`/fix\` or \`elevasis-sdk deploy\` to update
|
|
47198
|
-
`;
|
|
47199
|
-
}
|
|
47200
|
-
function claudeTaskTrackingRuleTemplate() {
|
|
47201
|
-
return `---
|
|
47202
|
-
description: In-progress task conventions -- /work command, doc format, status values, auto-save behavior
|
|
47203
|
-
paths:
|
|
47204
|
-
- docs/in-progress/**
|
|
47205
|
-
---
|
|
47206
|
-
|
|
47207
|
-
# Task Tracking
|
|
47208
|
-
|
|
47209
|
-
## Status Values
|
|
47210
|
-
|
|
47211
|
-
Exactly three values for frontmatter \`status\`: \`planned\`, \`in-progress\`, \`complete\`.
|
|
47212
|
-
|
|
47213
|
-
## Doc Format
|
|
47214
|
-
|
|
47215
|
-
- Frontmatter: \`title\`, \`description\`, \`status\`
|
|
47216
|
-
- Sections: Objective, Plan, Progress, Resume Context
|
|
47217
|
-
- Progress subsections use markers: \`### Step N: Title -- PENDING\`, \`-- IN PROGRESS\`, \`-- COMPLETE\`
|
|
47218
|
-
|
|
47219
|
-
## Auto-Update Behavior
|
|
47220
|
-
|
|
47221
|
-
- When working on a tracked task, update the Progress section when a plan step transitions:
|
|
47222
|
-
- PENDING -> IN PROGRESS (starting work on a step)
|
|
47223
|
-
- IN PROGRESS -> COMPLETE (finishing a step)
|
|
47224
|
-
- Do NOT update on every action -- only on step transitions
|
|
47225
|
-
|
|
47226
|
-
## Auto-Save Behavior
|
|
47227
|
-
|
|
47228
|
-
The agent auto-saves progress (no user action needed) when:
|
|
47229
|
-
- The conversation context is getting heavy (many tool calls, large file reads)
|
|
47230
|
-
- The user appears to be wrapping up (thanks, goodbye, switching topics)
|
|
47231
|
-
- Significant progress has been made (2+ steps completed without saving)
|
|
47232
|
-
- Before a context reset
|
|
47233
|
-
|
|
47234
|
-
Auto-save updates the task doc's Progress and Resume Context sections silently, then briefly confirms.
|
|
47235
|
-
|
|
47236
|
-
## Completion Suggestions
|
|
47237
|
-
|
|
47238
|
-
When all plan steps are marked COMPLETE, **suggest** completing the task -- never auto-invoke. Ask: "All steps for '{task}' look done. Want me to finalize it?"
|
|
47239
|
-
|
|
47240
|
-
## Directory Conventions
|
|
47241
|
-
|
|
47242
|
-
- \`docs/in-progress/\` for all active task docs
|
|
47243
|
-
- Small tasks: \`<slug>.mdx\` directly in \`docs/in-progress/\`
|
|
47244
|
-
- Multi-file tasks: \`<slug>/index.mdx\` with supporting docs alongside
|
|
47245
|
-
- Completed tasks move OUT of \`docs/in-progress/\` to \`docs/<relevant-dir>/\`
|
|
47246
|
-
`;
|
|
47247
|
-
}
|
|
47248
|
-
function claudeLoggingRuleTemplate() {
|
|
47249
|
-
return `---
|
|
47250
|
-
description: Logging conventions for workflow and agent handlers
|
|
47251
|
-
paths:
|
|
47252
|
-
- src/**
|
|
47253
|
-
---
|
|
47254
|
-
|
|
47255
|
-
# Logging
|
|
47256
|
-
|
|
47257
|
-
## Always Use \`context.logger\` in Handlers
|
|
47258
|
-
|
|
47259
|
-
**Never use \`console.log\`, \`console.warn\`, or \`console.error\` in step/agent handlers.**
|
|
47260
|
-
The platform does not capture \`console.*\` output \u2014 it will not appear in execution logs.
|
|
47261
|
-
|
|
47262
|
-
\`\`\`typescript
|
|
47263
|
-
// \u274C WRONG \u2014 invisible in Command Center
|
|
47264
|
-
handler: async (rawInput) => {
|
|
47265
|
-
console.log('Processing...')
|
|
47266
|
-
}
|
|
47267
|
-
|
|
47268
|
-
// \u2705 CORRECT \u2014 visible in Command Center
|
|
47269
|
-
handler: async (rawInput, context) => {
|
|
47270
|
-
context.logger.info('Processing...')
|
|
47271
|
-
}
|
|
47272
|
-
\`\`\`
|
|
47273
|
-
|
|
47274
|
-
## Logger Methods
|
|
47275
|
-
|
|
47276
|
-
\`\`\`typescript
|
|
47277
|
-
context.logger.debug('Verbose detail \u2014 shown in debug mode only')
|
|
47278
|
-
context.logger.info('Normal progress messages')
|
|
47279
|
-
context.logger.warn('Non-fatal issue \u2014 skipped, retried, partial result')
|
|
47280
|
-
context.logger.error('Fatal error or unexpected failure')
|
|
47281
|
-
\`\`\`
|
|
47282
|
-
|
|
47283
|
-
## Extensive Logging Standard
|
|
47284
|
-
|
|
47285
|
-
Every handler should log:
|
|
47286
|
-
|
|
47287
|
-
1. **Entry** \u2014 step name + key input params (category, count, domain, etc.)
|
|
47288
|
-
2. **Progress** \u2014 inside loops: per-item status (processed, skipped, failed)
|
|
47289
|
-
3. **Decisions** \u2014 idempotency skips, early exits, conditional branches
|
|
47290
|
-
4. **Summary** \u2014 counts at the end (X processed, Y skipped, Z errors)
|
|
47291
|
-
|
|
47292
|
-
\`\`\`typescript
|
|
47293
|
-
handler: async (rawInput, context) => {
|
|
47294
|
-
const data = rawInput as SomeType
|
|
47295
|
-
context.logger.info(\`[step-name] Starting \u2014 \${data.items.length} items\`)
|
|
47296
|
-
|
|
47297
|
-
let processed = 0, skipped = 0
|
|
47298
|
-
for (const item of data.items) {
|
|
47299
|
-
if (item.alreadyDone) {
|
|
47300
|
-
skipped++
|
|
47301
|
-
context.logger.info(\`[step-name] Skipping \${item.name} \u2014 already complete\`)
|
|
47302
|
-
continue
|
|
47303
|
-
}
|
|
47304
|
-
// ...
|
|
47305
|
-
processed++
|
|
47306
|
-
context.logger.info(\`[step-name] Processed \${item.name}\`)
|
|
47307
|
-
}
|
|
47308
|
-
|
|
47309
|
-
context.logger.info(\`[step-name] Done \u2014 \${processed} processed, \${skipped} skipped\`)
|
|
47310
|
-
}
|
|
47311
|
-
\`\`\`
|
|
47312
|
-
|
|
47313
|
-
## Warnings vs Errors
|
|
47314
|
-
|
|
47315
|
-
- \`warn\`: skipped item, not found in DB, LLM timeout on one domain (processing continues)
|
|
47316
|
-
- \`error\`: step-level failures that propagate as thrown errors (log before throwing if possible)
|
|
47317
|
-
`;
|
|
47318
|
-
}
|
|
47319
|
-
function claudePostEditValidateHookTemplate() {
|
|
47320
|
-
return `#!/usr/bin/env node
|
|
47321
|
-
// post-edit-validate.mjs
|
|
47322
|
-
// PostToolUse hook \u2014 auto-formats with prettier, type-checks .ts/.tsx files.
|
|
47323
|
-
// Fires after Edit|Write|MultiEdit succeeds.
|
|
47324
|
-
|
|
47325
|
-
import { existsSync } from 'node:fs'
|
|
47326
|
-
import { resolve, normalize, extname, join, dirname } from 'node:path'
|
|
47327
|
-
import { execSync } from 'node:child_process'
|
|
47328
|
-
|
|
47329
|
-
const ROOT = process.env.CLAUDE_PROJECT_DIR ?? process.cwd()
|
|
47330
|
-
|
|
47331
|
-
// Extensions prettier should format
|
|
47332
|
-
const PRETTIER_EXTENSIONS = new Set([
|
|
47333
|
-
'.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json', '.css', '.md', '.mdx'
|
|
47334
|
-
])
|
|
47335
|
-
|
|
47336
|
-
// Extensions that trigger type-checking
|
|
47337
|
-
const TS_EXTENSIONS = new Set(['.ts', '.tsx'])
|
|
47338
|
-
|
|
47339
|
-
function findNearestTsconfig(startDir) {
|
|
47340
|
-
let dir = startDir
|
|
47341
|
-
const root = normalize(ROOT)
|
|
47342
|
-
while (dir.length >= root.length) {
|
|
47343
|
-
const candidate = join(dir, 'tsconfig.json')
|
|
47344
|
-
if (existsSync(candidate)) return candidate
|
|
47345
|
-
const parent = dirname(dir)
|
|
47346
|
-
if (parent === dir) break
|
|
47347
|
-
dir = parent
|
|
47348
|
-
}
|
|
47349
|
-
return null
|
|
47350
|
-
}
|
|
47351
|
-
|
|
47352
|
-
try {
|
|
47353
|
-
const chunks = []
|
|
47354
|
-
for await (const chunk of process.stdin) chunks.push(chunk)
|
|
47355
|
-
const input = JSON.parse(Buffer.concat(chunks).toString())
|
|
47356
|
-
|
|
47357
|
-
const filePath = input.tool_input?.file_path
|
|
47358
|
-
if (!filePath) process.exit(0)
|
|
47359
|
-
|
|
47360
|
-
const ext = extname(filePath).toLowerCase()
|
|
47361
|
-
const absPath = normalize(resolve(filePath))
|
|
47362
|
-
if (!existsSync(absPath)) process.exit(0)
|
|
47363
|
-
|
|
47364
|
-
const results = []
|
|
47365
|
-
|
|
47366
|
-
// 1. Prettier
|
|
47367
|
-
if (PRETTIER_EXTENSIONS.has(ext)) {
|
|
47368
|
-
try {
|
|
47369
|
-
execSync('pnpm exec prettier --write "' + absPath + '"', {
|
|
47370
|
-
cwd: ROOT,
|
|
47371
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
47372
|
-
timeout: 10_000
|
|
47373
|
-
})
|
|
47374
|
-
} catch (err) {
|
|
47375
|
-
const stderr = err.stderr?.toString().trim() || ''
|
|
47376
|
-
if (stderr && !/ignored/i.test(stderr)) {
|
|
47377
|
-
results.push('Prettier error: ' + stderr.slice(0, 300))
|
|
47378
|
-
}
|
|
47379
|
-
}
|
|
47380
|
-
}
|
|
47381
|
-
|
|
47382
|
-
// 2. Type-check for .ts/.tsx
|
|
47383
|
-
if (TS_EXTENSIONS.has(ext)) {
|
|
47384
|
-
const tsconfig = findNearestTsconfig(dirname(absPath))
|
|
47385
|
-
if (tsconfig) {
|
|
47386
|
-
try {
|
|
47387
|
-
execSync('pnpm exec tsc --noEmit -p "' + tsconfig + '"', {
|
|
47388
|
-
cwd: ROOT,
|
|
47389
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
47390
|
-
timeout: 30_000,
|
|
47391
|
-
env: { ...process.env, NODE_OPTIONS: '--max-old-space-size=4096' }
|
|
47392
|
-
})
|
|
47393
|
-
} catch (err) {
|
|
47394
|
-
if (err.killed) process.exit(0) // Don't block on timeout
|
|
47395
|
-
const stdout = err.stdout?.toString() || ''
|
|
47396
|
-
if (stdout.includes('error TS')) {
|
|
47397
|
-
const errorLines = stdout
|
|
47398
|
-
.split('\\n')
|
|
47399
|
-
.filter(l => l.includes('error TS'))
|
|
47400
|
-
.slice(0, 10)
|
|
47401
|
-
results.push('Type errors after editing ' + filePath + ':\\n' + errorLines.join('\\n'))
|
|
47402
|
-
}
|
|
47403
|
-
}
|
|
47404
|
-
}
|
|
47405
|
-
}
|
|
47406
|
-
|
|
47407
|
-
// Output errors to Claude's context (silence = success)
|
|
47408
|
-
if (results.length > 0) {
|
|
47409
|
-
process.stderr.write(results.join('\\n\\n'))
|
|
47410
|
-
process.exit(2) // Exit 2 = send stderr as feedback to Claude
|
|
47411
|
-
}
|
|
47412
|
-
} catch {}
|
|
47413
|
-
|
|
47414
|
-
process.exit(0)
|
|
47415
|
-
`;
|
|
47416
|
-
}
|
|
47417
|
-
function claudeToolFailureRecoveryHookTemplate() {
|
|
47418
|
-
return `#!/usr/bin/env node
|
|
47419
|
-
// tool-failure-recovery.mjs
|
|
47420
|
-
// PostToolUseFailure hook \u2014 pattern-matches known Bash errors and returns
|
|
47421
|
-
// recovery advice via stderr + exit 2 (feedback to Claude).
|
|
47422
|
-
|
|
47423
|
-
const RECOVERY_TABLE = [
|
|
47424
|
-
{
|
|
47425
|
-
test: r => /JavaScript heap out of memory/i.test(r),
|
|
47426
|
-
advice: 'Out of memory.',
|
|
47427
|
-
fix: 'Run the command with NODE_OPTIONS="--max-old-space-size=4096".',
|
|
47428
|
-
why: 'Large TypeScript projects can exceed Node default heap limit.',
|
|
47429
|
-
},
|
|
47430
|
-
{
|
|
47431
|
-
test: r => /boundary hook/i.test(r) && /block|denied/i.test(r),
|
|
47432
|
-
advice: 'Command blocked by SDK boundary hook.',
|
|
47433
|
-
fix: 'Ask the user to run this command manually.',
|
|
47434
|
-
why: 'The boundary hook blocks file modifications (Write, Edit, destructive Bash) outside the project boundary.',
|
|
47435
|
-
see: 'CLAUDE.md',
|
|
47436
|
-
},
|
|
47437
|
-
{
|
|
47438
|
-
test: r => /ENOENT/.test(r) && /node_modules/.test(r),
|
|
47439
|
-
advice: 'Missing node_modules dependency.',
|
|
47440
|
-
fix: 'Run: pnpm install',
|
|
47441
|
-
why: 'Dependencies are not installed or were cleared.',
|
|
47442
|
-
},
|
|
47443
|
-
{
|
|
47444
|
-
test: r => /ERR_MODULE_NOT_FOUND/.test(r) && /@elevasis\\/sdk/.test(r),
|
|
47445
|
-
advice: '@elevasis/sdk module not found.',
|
|
47446
|
-
fix: 'Run: pnpm install \u2014 then verify @elevasis/sdk is in package.json dependencies.',
|
|
47447
|
-
why: 'The SDK package is not installed or the version is mismatched.',
|
|
47448
|
-
},
|
|
47449
|
-
{
|
|
47450
|
-
test: r => /ERR_MODULE_NOT_FOUND/.test(r),
|
|
47451
|
-
advice: 'Module not found at import path.',
|
|
47452
|
-
fix: 'Check the import path and verify the package is installed (pnpm install).',
|
|
47453
|
-
why: 'The import path does not match any installed package or local file.',
|
|
47454
|
-
},
|
|
47455
|
-
{
|
|
47456
|
-
test: r => /TS2307/.test(r) || (/cannot find/i.test(r) && /declaration/i.test(r)),
|
|
47457
|
-
advice: 'TypeScript cannot resolve module or declaration file.',
|
|
47458
|
-
fix: 'Check that the package is installed and tsconfig paths are correct.',
|
|
47459
|
-
why: 'Missing dependency or incorrect TypeScript configuration.',
|
|
47460
|
-
},
|
|
47461
|
-
{
|
|
47462
|
-
test: r => /EPERM/.test(r) || /permission denied/i.test(r),
|
|
47463
|
-
advice: 'Permission denied (EPERM).',
|
|
47464
|
-
fix: 'Close the file in any other process (editor, terminal, or dev server) and retry.',
|
|
47465
|
-
why: 'On Windows, files locked by another process cannot be written to.',
|
|
47466
|
-
},
|
|
47467
|
-
{
|
|
47468
|
-
test: r => /lockfile/i.test(r) && /conflict|outdated|ERR_PNPM/i.test(r),
|
|
47469
|
-
advice: 'pnpm lockfile conflict or outdated.',
|
|
47470
|
-
fix: 'Run: pnpm install to regenerate the lockfile.',
|
|
47471
|
-
why: 'The lockfile is out of sync with package.json changes.',
|
|
47472
|
-
},
|
|
47473
|
-
{
|
|
47474
|
-
test: r => /elevasis-sdk check/.test(r) || /elevasis-sdk deploy/.test(r),
|
|
47475
|
-
advice: 'elevasis-sdk CLI command failed.',
|
|
47476
|
-
fix: 'Check the error output above. Common causes: missing .env ELEVASIS_API_KEY, invalid resource schemas, or network issues.',
|
|
47477
|
-
why: 'The SDK CLI validates resources and communicates with the platform API.',
|
|
47478
|
-
},
|
|
47479
|
-
{
|
|
47480
|
-
test: r => /EADDRINUSE/.test(r),
|
|
47481
|
-
advice: 'Port already in use.',
|
|
47482
|
-
fix: 'Find and kill the process using the port, or use a different port.',
|
|
47483
|
-
why: 'A previous dev server or process is still holding the port.',
|
|
47484
|
-
},
|
|
47485
|
-
]
|
|
47486
|
-
|
|
47487
|
-
function formatRecovery(entry) {
|
|
47488
|
-
let msg = 'FAILED: ' + entry.advice + '\\nFIX: ' + entry.fix
|
|
47489
|
-
if (entry.why) msg += '\\nWHY: ' + entry.why
|
|
47490
|
-
if (entry.see) msg += '\\nSEE: ' + entry.see
|
|
47491
|
-
return msg
|
|
47492
|
-
}
|
|
47493
|
-
|
|
47494
|
-
try {
|
|
47495
|
-
const chunks = []
|
|
47496
|
-
for await (const chunk of process.stdin) chunks.push(chunk)
|
|
47497
|
-
const input = JSON.parse(Buffer.concat(chunks).toString())
|
|
47498
|
-
|
|
47499
|
-
const response = input.tool_response ?? ''
|
|
47500
|
-
|
|
47501
|
-
for (const entry of RECOVERY_TABLE) {
|
|
47502
|
-
if (entry.test(response)) {
|
|
47503
|
-
process.stderr.write(formatRecovery(entry))
|
|
47504
|
-
process.exit(2)
|
|
47505
|
-
}
|
|
47506
|
-
}
|
|
47507
|
-
} catch {}
|
|
47508
|
-
|
|
47509
|
-
process.exit(0)
|
|
47510
|
-
`;
|
|
47511
|
-
}
|
|
47512
|
-
|
|
47513
|
-
// src/cli/commands/templates/core/resources.ts
|
|
47514
|
-
function starterTemplate() {
|
|
47515
|
-
return `import type { OrganizationResources } from '@elevasis/sdk'
|
|
47516
|
-
import * as operations from './operations/index.js'
|
|
47517
|
-
import * as example from './example/index.js'
|
|
47518
|
-
|
|
47519
|
-
const org: OrganizationResources = {
|
|
47520
|
-
workflows: [
|
|
47521
|
-
...operations.workflows,
|
|
47522
|
-
...example.workflows,
|
|
47523
|
-
],
|
|
47524
|
-
agents: [
|
|
47525
|
-
...operations.agents,
|
|
47526
|
-
...example.agents,
|
|
47527
|
-
],
|
|
47528
|
-
}
|
|
47529
|
-
export default org
|
|
47530
|
-
`;
|
|
47531
|
-
}
|
|
47532
|
-
function starterWorkflowTemplate() {
|
|
47533
|
-
return `import type { WorkflowDefinition } from '@elevasis/sdk'
|
|
47534
|
-
import { z } from 'zod'
|
|
47535
|
-
|
|
47536
|
-
const echoInput = z.object({ message: z.string() })
|
|
47537
|
-
const echoOutput = z.object({ echo: z.string() })
|
|
47538
|
-
type EchoInput = z.infer<typeof echoInput>
|
|
47539
|
-
|
|
47540
|
-
export const echo: WorkflowDefinition = {
|
|
47541
|
-
config: {
|
|
47542
|
-
resourceId: 'echo',
|
|
47543
|
-
name: 'Echo',
|
|
47544
|
-
type: 'workflow',
|
|
47545
|
-
description: 'Echoes the input message back',
|
|
47546
|
-
version: '1.0.0',
|
|
47547
|
-
status: 'dev',
|
|
47548
|
-
},
|
|
47549
|
-
contract: {
|
|
47550
|
-
inputSchema: echoInput,
|
|
47551
|
-
outputSchema: echoOutput,
|
|
47552
|
-
},
|
|
47553
|
-
steps: {
|
|
47554
|
-
echo: {
|
|
47555
|
-
id: 'echo',
|
|
47556
|
-
name: 'Echo Message',
|
|
47557
|
-
description: 'Returns the input message',
|
|
47558
|
-
handler: async (input) => {
|
|
47559
|
-
const { message } = input as EchoInput
|
|
47560
|
-
return { echo: message }
|
|
47561
|
-
},
|
|
47562
|
-
inputSchema: echoInput,
|
|
47563
|
-
outputSchema: echoOutput,
|
|
47564
|
-
next: null,
|
|
47565
|
-
},
|
|
47566
|
-
},
|
|
47567
|
-
entryPoint: 'echo',
|
|
47568
|
-
}
|
|
47569
|
-
`;
|
|
47570
|
-
}
|
|
47571
|
-
function platformStatusTemplate() {
|
|
47572
|
-
return `import type { WorkflowDefinition } from '@elevasis/sdk'
|
|
47573
|
-
import { StepType } from '@elevasis/sdk'
|
|
47574
|
-
import { platform } from '@elevasis/sdk/worker'
|
|
47575
|
-
import { llm } from '@elevasis/sdk/worker'
|
|
47576
|
-
import { z } from 'zod'
|
|
47577
|
-
|
|
47578
|
-
const input = z.object({
|
|
47579
|
-
timeRange: z.enum(['1h', '24h', '7d']).default('24h').describe('Time window for status data'),
|
|
47580
|
-
})
|
|
47581
|
-
|
|
47582
|
-
const statusData = z.object({
|
|
47583
|
-
raw: z.unknown().describe('Raw status overview from platform'),
|
|
47584
|
-
})
|
|
47585
|
-
|
|
47586
|
-
const output = z.object({
|
|
47587
|
-
raw: z.unknown().describe('Raw status overview from platform'),
|
|
47588
|
-
summary: z.string().describe('Natural language status summary'),
|
|
47589
|
-
})
|
|
47590
|
-
|
|
47591
|
-
type Input = z.infer<typeof input>
|
|
47592
|
-
|
|
47593
|
-
export const platformStatus: WorkflowDefinition = {
|
|
47594
|
-
config: {
|
|
47595
|
-
resourceId: 'platform-status',
|
|
47596
|
-
name: 'Platform Status',
|
|
47597
|
-
type: 'workflow',
|
|
47598
|
-
description: 'Gathers cross-system platform status and compiles a natural language summary',
|
|
47599
|
-
version: '1.0.0',
|
|
47600
|
-
status: 'dev',
|
|
47601
|
-
},
|
|
47602
|
-
contract: { inputSchema: input, outputSchema: output },
|
|
47603
|
-
steps: {
|
|
47604
|
-
'gather-status': {
|
|
47605
|
-
id: 'gather-status',
|
|
47606
|
-
name: 'Gather Status',
|
|
47607
|
-
description: 'Queries platform status overview (executions, pending items, schedules, credentials)',
|
|
47608
|
-
handler: async (rawInput) => {
|
|
47609
|
-
const { timeRange } = rawInput as Input
|
|
47610
|
-
const raw = await platform.call({
|
|
47611
|
-
tool: 'status',
|
|
47612
|
-
method: 'overview',
|
|
47613
|
-
params: { timeRange },
|
|
47614
|
-
})
|
|
47615
|
-
return { raw }
|
|
47616
|
-
},
|
|
47617
|
-
inputSchema: input,
|
|
47618
|
-
outputSchema: statusData,
|
|
47619
|
-
next: { type: StepType.LINEAR, target: 'compile-report' },
|
|
47620
|
-
},
|
|
47621
|
-
'compile-report': {
|
|
47622
|
-
id: 'compile-report',
|
|
47623
|
-
name: 'Compile Report',
|
|
47624
|
-
description: 'Generates a natural language summary from raw status data',
|
|
47625
|
-
handler: async (rawInput) => {
|
|
47626
|
-
const { raw } = rawInput as z.infer<typeof statusData>
|
|
47627
|
-
const result = await llm.generate({
|
|
47628
|
-
provider: 'google',
|
|
47629
|
-
model: 'gemini-3-flash-preview',
|
|
47630
|
-
messages: [
|
|
47631
|
-
{
|
|
47632
|
-
role: 'user',
|
|
47633
|
-
content: [
|
|
47634
|
-
'Summarize this platform status overview in 3-5 concise bullet points.',
|
|
47635
|
-
'Focus on: execution health, pending items needing attention, upcoming schedules, and credential coverage.',
|
|
47636
|
-
'Be specific with numbers. Flag any issues.',
|
|
47637
|
-
'',
|
|
47638
|
-
JSON.stringify(raw, null, 2),
|
|
47639
|
-
].join('\\n'),
|
|
47640
|
-
},
|
|
47641
|
-
],
|
|
47642
|
-
responseSchema: {
|
|
47643
|
-
type: 'object',
|
|
47644
|
-
properties: {
|
|
47645
|
-
summary: { type: 'string', description: 'Natural language status summary with bullet points' },
|
|
47646
|
-
},
|
|
47647
|
-
required: ['summary'],
|
|
47648
|
-
},
|
|
47649
|
-
temperature: 0,
|
|
47650
|
-
})
|
|
47651
|
-
const summary = (result as any)?.summary ?? String(result)
|
|
47652
|
-
return { raw, summary }
|
|
47653
|
-
},
|
|
47654
|
-
inputSchema: statusData,
|
|
47655
|
-
outputSchema: output,
|
|
47656
|
-
next: null,
|
|
47657
|
-
},
|
|
47658
|
-
},
|
|
47659
|
-
entryPoint: 'gather-status',
|
|
47660
|
-
}
|
|
47661
|
-
`;
|
|
47662
|
-
}
|
|
47663
|
-
function operationsBarrelTemplate() {
|
|
47664
|
-
return `import { platformStatus } from './platform-status.js'
|
|
47665
|
-
|
|
47666
|
-
export const workflows = [platformStatus]
|
|
47667
|
-
export const agents = []
|
|
47668
|
-
`;
|
|
47669
|
-
}
|
|
47670
|
-
function exampleBarrelTemplate() {
|
|
47671
|
-
return `import { echo } from './echo.js'
|
|
47672
|
-
|
|
47673
|
-
export const workflows = [echo]
|
|
47674
|
-
export const agents = []
|
|
47675
|
-
`;
|
|
47676
|
-
}
|
|
47677
|
-
|
|
47678
|
-
// src/cli/commands/templates/core/index.ts
|
|
47679
|
-
function getManagedTemplates(ctx = {}) {
|
|
47680
|
-
return {
|
|
47681
|
-
"elevasis.config.ts": configTemplate,
|
|
47682
|
-
".gitignore": () => gitignoreTemplate(ctx),
|
|
47683
|
-
"CLAUDE.md": () => claudeMdTemplate(ctx),
|
|
47684
|
-
".claude/settings.json": claudeSettingsTemplate,
|
|
47685
|
-
".claude/scripts/statusline-command.js": claudeStatuslineScriptTemplate,
|
|
47686
|
-
".claude/hooks/enforce-sdk-boundary.mjs": claudeSdkBoundaryHookTemplate,
|
|
47687
|
-
".claude/hooks/post-edit-validate.mjs": claudePostEditValidateHookTemplate,
|
|
47688
|
-
".claude/hooks/tool-failure-recovery.mjs": claudeToolFailureRecoveryHookTemplate,
|
|
47689
|
-
".claude/commands/tutorial.md": claudeTutorialCommandTemplate,
|
|
47690
|
-
".claude/commands/init.md": claudeInitCommandTemplate,
|
|
47691
|
-
".claude/commands/status.md": claudeStatusCommandTemplate,
|
|
47692
|
-
".claude/commands/fix.md": claudeFixCommandTemplate,
|
|
47693
|
-
".claude/commands/deploy.md": claudeDeployCommandTemplate,
|
|
47694
|
-
".claude/skills/diagnostics/SKILL.md": claudeDiagnosticsSkillTemplate,
|
|
47695
|
-
".claude/skills/work/SKILL.md": claudeWorkSkillTemplate,
|
|
47696
|
-
".claude/commands/docs.md": claudeDocsCommandTemplate,
|
|
47697
|
-
".claude/skills/creds/SKILL.md": claudeCredsSkillTemplate,
|
|
47698
|
-
".claude/rules/sdk-patterns.md": claudeSdkPatternsRuleTemplate,
|
|
47699
|
-
".claude/rules/docs-authoring.md": claudeDocsAuthoringRuleTemplate,
|
|
47700
|
-
".claude/rules/memory-conventions.md": claudeMemoryConventionsRuleTemplate,
|
|
47701
|
-
".claude/rules/project-map.md": claudeProjectMapRuleTemplate,
|
|
47702
|
-
".claude/rules/task-tracking.md": claudeTaskTrackingRuleTemplate,
|
|
47703
|
-
".claude/rules/logging.md": claudeLoggingRuleTemplate
|
|
47704
|
-
};
|
|
47705
|
-
}
|
|
47706
|
-
|
|
47707
|
-
// src/cli/commands/templates/ui/files.ts
|
|
47708
|
-
function getUIFiles(orgSlug) {
|
|
47709
|
-
return {
|
|
47710
|
-
"ui/package.json": uiPackageJsonTemplate(orgSlug),
|
|
47711
|
-
"ui/index.html": uiIndexHtmlTemplate(),
|
|
47712
|
-
"ui/vite.config.ts": uiViteConfigTemplate(),
|
|
47713
|
-
"ui/tsconfig.json": uiTsconfigTemplate(),
|
|
47714
|
-
"ui/src/main.tsx": uiMainTsxTemplate(),
|
|
47715
|
-
"ui/src/App.tsx": uiAppTsxTemplate(),
|
|
47716
|
-
"ui/src/AuthRedirect.tsx": uiAuthRedirectTemplate(),
|
|
47717
|
-
"ui/src/vite-env.d.ts": uiViteEnvDtsTemplate(),
|
|
47718
|
-
"ui/.env": uiEnvTemplate()
|
|
47719
|
-
};
|
|
47720
|
-
}
|
|
47721
|
-
function uiPackageJsonTemplate(orgSlug) {
|
|
47722
|
-
return JSON.stringify(
|
|
47723
|
-
{
|
|
47724
|
-
name: `${orgSlug}-ui`,
|
|
47725
|
-
private: true,
|
|
47726
|
-
type: "module",
|
|
47727
|
-
scripts: {
|
|
47728
|
-
dev: "vite",
|
|
47729
|
-
build: "tsc && vite build",
|
|
47730
|
-
preview: "vite preview"
|
|
47731
|
-
},
|
|
47732
|
-
dependencies: {
|
|
47733
|
-
"@elevasis/sdk-ui": "latest",
|
|
47734
|
-
react: "^19.0.0",
|
|
47735
|
-
"react-dom": "^19.0.0",
|
|
47736
|
-
"react-router-dom": "^7.0.0"
|
|
47737
|
-
},
|
|
47738
|
-
devDependencies: {
|
|
47739
|
-
"@types/react": "^19.0.0",
|
|
47740
|
-
"@types/react-dom": "^19.0.0",
|
|
47741
|
-
"@vitejs/plugin-react": "^4.0.0",
|
|
47742
|
-
typescript: "^5.7.0",
|
|
47743
|
-
vite: "^6.0.0"
|
|
47744
|
-
}
|
|
47745
|
-
},
|
|
47746
|
-
null,
|
|
47747
|
-
2
|
|
47748
|
-
) + "\n";
|
|
47749
|
-
}
|
|
47750
|
-
function uiIndexHtmlTemplate() {
|
|
47751
|
-
return `<!doctype html>
|
|
47752
|
-
<html lang="en">
|
|
47753
|
-
<head>
|
|
47754
|
-
<meta charset="UTF-8" />
|
|
47755
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
47756
|
-
<title>Elevasis UI</title>
|
|
47757
|
-
</head>
|
|
47758
|
-
<body>
|
|
47759
|
-
<div id="root"></div>
|
|
47760
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
47761
|
-
</body>
|
|
47762
|
-
</html>
|
|
47763
|
-
`;
|
|
47764
|
-
}
|
|
47765
|
-
function uiViteConfigTemplate() {
|
|
47766
|
-
return `import { defineConfig } from 'vite'
|
|
47767
|
-
import react from '@vitejs/plugin-react'
|
|
47768
|
-
|
|
47769
|
-
export default defineConfig({
|
|
47770
|
-
plugins: [react()],
|
|
47771
|
-
server: {
|
|
47772
|
-
port: 5100,
|
|
47773
|
-
},
|
|
47774
|
-
})
|
|
47775
|
-
`;
|
|
47776
|
-
}
|
|
47777
|
-
function uiTsconfigTemplate() {
|
|
47778
|
-
return JSON.stringify(
|
|
47779
|
-
{
|
|
47780
|
-
compilerOptions: {
|
|
47781
|
-
target: "ES2022",
|
|
47782
|
-
lib: ["ES2022", "DOM", "DOM.Iterable"],
|
|
47783
|
-
module: "ESNext",
|
|
47784
|
-
moduleResolution: "bundler",
|
|
47785
|
-
jsx: "react-jsx",
|
|
47786
|
-
strict: true,
|
|
47787
|
-
esModuleInterop: true,
|
|
47788
|
-
skipLibCheck: true,
|
|
47789
|
-
forceConsistentCasingInFileNames: true,
|
|
47790
|
-
isolatedModules: true,
|
|
47791
|
-
noEmit: true
|
|
47792
|
-
},
|
|
47793
|
-
include: ["src"]
|
|
47794
|
-
},
|
|
47795
|
-
null,
|
|
47796
|
-
2
|
|
47797
|
-
) + "\n";
|
|
47798
|
-
}
|
|
47799
|
-
function uiMainTsxTemplate() {
|
|
47800
|
-
return `import { StrictMode } from 'react'
|
|
47801
|
-
import { createRoot } from 'react-dom/client'
|
|
47802
|
-
import { BrowserRouter } from 'react-router-dom'
|
|
47803
|
-
import { App } from './App'
|
|
47804
|
-
|
|
47805
|
-
createRoot(document.getElementById('root')!).render(
|
|
47806
|
-
<StrictMode>
|
|
47807
|
-
<BrowserRouter>
|
|
47808
|
-
<App />
|
|
47809
|
-
</BrowserRouter>
|
|
47810
|
-
</StrictMode>,
|
|
47811
|
-
)
|
|
47812
|
-
`;
|
|
47813
|
-
}
|
|
47814
|
-
function uiAppTsxTemplate() {
|
|
47815
|
-
return `import { ElevasisCoreProvider } from '@elevasis/sdk-ui'
|
|
47816
|
-
import { Routes, Route } from 'react-router-dom'
|
|
47817
|
-
import { AuthRedirect } from './AuthRedirect'
|
|
47818
|
-
|
|
47819
|
-
export function App() {
|
|
47820
|
-
return (
|
|
47821
|
-
<ElevasisCoreProvider
|
|
47822
|
-
auth={{
|
|
47823
|
-
mode: 'oauth',
|
|
47824
|
-
clientId: import.meta.env.VITE_WORKOS_CLIENT_ID,
|
|
47825
|
-
redirectUri: 'http://localhost:5100/auth-redirect',
|
|
47826
|
-
}}
|
|
47827
|
-
apiUrl="http://localhost:5170"
|
|
47828
|
-
theme={{
|
|
47829
|
-
colorScheme: 'dark',
|
|
47830
|
-
preset: 'default',
|
|
47831
|
-
}}
|
|
47832
|
-
>
|
|
47833
|
-
<Routes>
|
|
47834
|
-
<Route path="/" element={<h1>Home</h1>} />
|
|
47835
|
-
<Route path="/auth-redirect" element={<AuthRedirect />} />
|
|
47836
|
-
</Routes>
|
|
47837
|
-
</ElevasisCoreProvider>
|
|
47838
|
-
)
|
|
47839
|
-
}
|
|
47840
|
-
`;
|
|
47841
|
-
}
|
|
47842
|
-
function uiAuthRedirectTemplate() {
|
|
47843
|
-
return `import { useEffect } from 'react'
|
|
47844
|
-
import { useNavigate } from 'react-router-dom'
|
|
47845
|
-
import { useAuthContext } from '@elevasis/sdk-ui/auth'
|
|
47846
|
-
|
|
47847
|
-
export function AuthRedirect() {
|
|
47848
|
-
const { user } = useAuthContext()
|
|
47849
|
-
const navigate = useNavigate()
|
|
47850
|
-
|
|
47851
|
-
useEffect(() => {
|
|
47852
|
-
if (user) {
|
|
47853
|
-
navigate('/', { replace: true })
|
|
47854
|
-
}
|
|
47855
|
-
}, [user, navigate])
|
|
47856
|
-
|
|
47857
|
-
return <p>Signing in...</p>
|
|
47858
|
-
}
|
|
47859
|
-
`;
|
|
47860
|
-
}
|
|
47861
|
-
function uiViteEnvDtsTemplate() {
|
|
47862
|
-
return `/// <reference types="vite/client" />
|
|
47863
|
-
`;
|
|
47864
|
-
}
|
|
47865
|
-
function uiEnvTemplate() {
|
|
47866
|
-
return `VITE_WORKOS_CLIENT_ID=
|
|
47867
|
-
`;
|
|
47868
|
-
}
|
|
47869
|
-
|
|
47870
|
-
// src/cli/commands/templates/ui/index.ts
|
|
47871
|
-
var UI_INIT_FILES = [
|
|
47872
|
-
"ui/package.json",
|
|
47873
|
-
"ui/index.html",
|
|
47874
|
-
"ui/vite.config.ts",
|
|
47875
|
-
"ui/tsconfig.json",
|
|
47876
|
-
"ui/src/main.tsx",
|
|
47877
|
-
"ui/src/App.tsx",
|
|
47878
|
-
"ui/src/AuthRedirect.tsx",
|
|
47879
|
-
"ui/src/vite-env.d.ts",
|
|
47880
|
-
"ui/.env"
|
|
47881
|
-
];
|
|
47882
|
-
|
|
47883
|
-
// src/cli/commands/init.ts
|
|
47884
|
-
var INIT_ONLY_FILES = [
|
|
47885
|
-
"package.json",
|
|
47886
|
-
"pnpm-workspace.yaml",
|
|
47887
|
-
"tsconfig.json",
|
|
47888
|
-
".env",
|
|
47889
|
-
".npmrc",
|
|
47890
|
-
"src/index.ts",
|
|
47891
|
-
"src/operations/platform-status.ts",
|
|
47892
|
-
"src/operations/index.ts",
|
|
47893
|
-
"src/example/echo.ts",
|
|
47894
|
-
"src/example/index.ts",
|
|
47895
|
-
"src/shared/.gitkeep",
|
|
47896
|
-
"docs/index.mdx",
|
|
47897
|
-
"docs/in-progress/.gitkeep",
|
|
47898
|
-
".claude/rules/workspace-patterns.md"
|
|
47899
|
-
];
|
|
47900
|
-
var MANAGED_FILES = [
|
|
47901
|
-
"elevasis.config.ts",
|
|
47902
|
-
".gitignore",
|
|
47903
|
-
"CLAUDE.md",
|
|
47904
|
-
".claude/settings.json",
|
|
47905
|
-
".claude/hooks/enforce-sdk-boundary.mjs",
|
|
47906
|
-
".claude/hooks/post-edit-validate.mjs",
|
|
47907
|
-
".claude/hooks/tool-failure-recovery.mjs",
|
|
47908
|
-
".claude/commands/tutorial.md",
|
|
47909
|
-
".claude/commands/init.md",
|
|
47910
|
-
".claude/commands/status.md",
|
|
47911
|
-
".claude/commands/fix.md",
|
|
47912
|
-
".claude/commands/deploy.md",
|
|
47913
|
-
".claude/skills/diagnostics/SKILL.md",
|
|
47914
|
-
".claude/skills/work/SKILL.md",
|
|
47915
|
-
".claude/commands/docs.md",
|
|
47916
|
-
".claude/skills/creds/SKILL.md",
|
|
47917
|
-
".claude/rules/sdk-patterns.md",
|
|
47918
|
-
".claude/rules/docs-authoring.md",
|
|
47919
|
-
".claude/rules/memory-conventions.md",
|
|
47920
|
-
".claude/rules/project-map.md",
|
|
47921
|
-
".claude/rules/task-tracking.md",
|
|
47922
|
-
".claude/rules/logging.md",
|
|
47923
|
-
".claude/scripts/statusline-command.js"
|
|
47924
|
-
];
|
|
47925
|
-
var SCAFFOLD_FILES = [...INIT_ONLY_FILES, ...MANAGED_FILES];
|
|
47926
|
-
function registerInitCommand(program3) {
|
|
47927
|
-
program3.command("init [directory]").description("Scaffold a new Elevasis workspace\n Example: elevasis-sdk init my-workspace").option("--force", "Overwrite existing files").option("--ui", "Include a Vite + React UI app in ui/").action(
|
|
47928
|
-
wrapAction("init", async (directory, options2) => {
|
|
47929
|
-
const targetDir = directory ? (0, import_path3.resolve)(directory) : process.cwd();
|
|
47930
|
-
const orgSlug = toSlug((0, import_path3.basename)(targetDir));
|
|
47931
|
-
if (!options2.force) {
|
|
47932
|
-
const filesToCheck = options2.ui ? [...SCAFFOLD_FILES, ...UI_INIT_FILES] : SCAFFOLD_FILES;
|
|
47933
|
-
const conflicts = [];
|
|
47934
|
-
for (const file2 of filesToCheck) {
|
|
47935
|
-
try {
|
|
47936
|
-
await (0, import_promises2.access)((0, import_path3.resolve)(targetDir, file2));
|
|
47937
|
-
conflicts.push(file2);
|
|
47938
|
-
} catch {
|
|
47939
|
-
}
|
|
47940
|
-
}
|
|
47941
|
-
if (conflicts.length > 0) {
|
|
47942
|
-
console.error(source_default.red("Files already exist:"));
|
|
47943
|
-
for (const f of conflicts) {
|
|
47944
|
-
console.error(source_default.gray(` ${f}`));
|
|
47945
|
-
}
|
|
47946
|
-
console.error(source_default.gray("\n Use --force to overwrite."));
|
|
47947
|
-
throw new Error("Scaffold conflict");
|
|
47948
|
-
}
|
|
47949
|
-
}
|
|
47950
|
-
await (0, import_promises2.mkdir)((0, import_path3.resolve)(targetDir, "src/operations"), { recursive: true });
|
|
47951
|
-
await (0, import_promises2.mkdir)((0, import_path3.resolve)(targetDir, "src/example"), { recursive: true });
|
|
47952
|
-
await (0, import_promises2.mkdir)((0, import_path3.resolve)(targetDir, "src/shared"), { recursive: true });
|
|
47953
|
-
await (0, import_promises2.mkdir)((0, import_path3.resolve)(targetDir, "docs/in-progress"), { recursive: true });
|
|
47954
|
-
await (0, import_promises2.mkdir)((0, import_path3.resolve)(targetDir, ".claude/hooks"), { recursive: true });
|
|
47955
|
-
await (0, import_promises2.mkdir)((0, import_path3.resolve)(targetDir, ".claude/scripts"), { recursive: true });
|
|
47956
|
-
await (0, import_promises2.mkdir)((0, import_path3.resolve)(targetDir, ".claude/commands"), { recursive: true });
|
|
47957
|
-
await (0, import_promises2.mkdir)((0, import_path3.resolve)(targetDir, ".claude/skills/creds"), { recursive: true });
|
|
47958
|
-
await (0, import_promises2.mkdir)((0, import_path3.resolve)(targetDir, ".claude/rules"), { recursive: true });
|
|
47959
|
-
if (options2.ui) {
|
|
47960
|
-
await (0, import_promises2.mkdir)((0, import_path3.resolve)(targetDir, "ui/src"), { recursive: true });
|
|
47961
|
-
}
|
|
47962
|
-
const files = {
|
|
47963
|
-
"elevasis.config.ts": configTemplate(),
|
|
47964
|
-
"package.json": packageJsonTemplate(orgSlug),
|
|
47965
|
-
"pnpm-workspace.yaml": pnpmWorkspaceTemplate(),
|
|
47966
|
-
"tsconfig.json": tsconfigTemplate(),
|
|
47967
|
-
".env": envTemplate(),
|
|
47968
|
-
".npmrc": npmrcTemplate(),
|
|
47969
|
-
".gitignore": gitignoreTemplate({ hasUI: options2.ui }),
|
|
47970
|
-
"src/index.ts": starterTemplate(),
|
|
47971
|
-
"src/operations/platform-status.ts": platformStatusTemplate(),
|
|
47972
|
-
"src/operations/index.ts": operationsBarrelTemplate(),
|
|
47973
|
-
"src/example/echo.ts": starterWorkflowTemplate(),
|
|
47974
|
-
"src/example/index.ts": exampleBarrelTemplate(),
|
|
47975
|
-
"src/shared/.gitkeep": "",
|
|
47976
|
-
"docs/index.mdx": docsIndexTemplate(orgSlug),
|
|
47977
|
-
"docs/in-progress/.gitkeep": "",
|
|
47978
|
-
"CLAUDE.md": claudeMdTemplate({ hasUI: options2.ui }),
|
|
47979
|
-
".claude/settings.json": claudeSettingsTemplate(),
|
|
47980
|
-
".claude/hooks/enforce-sdk-boundary.mjs": claudeSdkBoundaryHookTemplate(),
|
|
47981
|
-
".claude/hooks/post-edit-validate.mjs": claudePostEditValidateHookTemplate(),
|
|
47982
|
-
".claude/hooks/tool-failure-recovery.mjs": claudeToolFailureRecoveryHookTemplate(),
|
|
47983
|
-
".claude/commands/tutorial.md": claudeTutorialCommandTemplate(),
|
|
47984
|
-
".claude/commands/init.md": claudeInitCommandTemplate(),
|
|
47985
|
-
".claude/commands/status.md": claudeStatusCommandTemplate(),
|
|
47986
|
-
".claude/commands/fix.md": claudeFixCommandTemplate(),
|
|
47987
|
-
".claude/commands/deploy.md": claudeDeployCommandTemplate(),
|
|
47988
|
-
".claude/skills/diagnostics/SKILL.md": claudeDiagnosticsSkillTemplate(),
|
|
47989
|
-
".claude/skills/work/SKILL.md": claudeWorkSkillTemplate(),
|
|
47990
|
-
".claude/commands/docs.md": claudeDocsCommandTemplate(),
|
|
47991
|
-
".claude/skills/creds/SKILL.md": claudeCredsSkillTemplate(),
|
|
47992
|
-
".claude/rules/sdk-patterns.md": claudeSdkPatternsRuleTemplate(),
|
|
47993
|
-
".claude/rules/workspace-patterns.md": claudeWorkspaceRulesTemplate(),
|
|
47994
|
-
".claude/rules/docs-authoring.md": claudeDocsAuthoringRuleTemplate(),
|
|
47995
|
-
".claude/rules/memory-conventions.md": claudeMemoryConventionsRuleTemplate(),
|
|
47996
|
-
".claude/rules/project-map.md": claudeProjectMapRuleTemplate(),
|
|
47997
|
-
".claude/rules/task-tracking.md": claudeTaskTrackingRuleTemplate(),
|
|
47998
|
-
".claude/rules/logging.md": claudeLoggingRuleTemplate(),
|
|
47999
|
-
".claude/scripts/statusline-command.js": claudeStatuslineScriptTemplate()
|
|
48000
|
-
};
|
|
48001
|
-
if (options2.ui) {
|
|
48002
|
-
Object.assign(files, getUIFiles(orgSlug));
|
|
48003
|
-
}
|
|
48004
|
-
for (const [filePath, content] of Object.entries(files)) {
|
|
48005
|
-
await (0, import_promises2.writeFile)((0, import_path3.resolve)(targetDir, filePath), content, "utf-8");
|
|
48006
|
-
}
|
|
48007
|
-
console.log(source_default.green.bold(" Workspace created!"));
|
|
48008
|
-
console.log("");
|
|
48009
|
-
console.log(source_default.gray(" Next steps:"));
|
|
48010
|
-
if (directory) {
|
|
48011
|
-
console.log(source_default.gray(` cd ${directory}`));
|
|
48012
|
-
}
|
|
48013
|
-
console.log(source_default.gray(" pnpm install"));
|
|
48014
|
-
console.log(source_default.gray(" # Add your API key to .env"));
|
|
48015
|
-
console.log(source_default.gray(" elevasis-sdk check"));
|
|
48016
|
-
console.log(source_default.gray(" elevasis-sdk deploy"));
|
|
48017
|
-
if (options2.ui) {
|
|
48018
|
-
console.log("");
|
|
48019
|
-
console.log(source_default.gray(" UI app:"));
|
|
48020
|
-
console.log(source_default.gray(" cd ui && pnpm install"));
|
|
48021
|
-
console.log(source_default.gray(" # Set VITE_WORKOS_CLIENT_ID in ui/.env"));
|
|
48022
|
-
console.log(source_default.gray(" pnpm dev"));
|
|
48023
|
-
}
|
|
48024
|
-
})
|
|
48025
|
-
);
|
|
48026
|
-
}
|
|
48027
|
-
function toSlug(name) {
|
|
48028
|
-
const slug = name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^[^a-z]+/, "").replace(/-+/g, "-").replace(/-$/, "");
|
|
48029
|
-
return slug.length >= 3 ? slug : "my-workspace";
|
|
48030
|
-
}
|
|
48031
|
-
|
|
48032
|
-
// src/cli/commands/update.ts
|
|
48033
|
-
var import_path4 = require("path");
|
|
48034
|
-
var import_promises3 = require("fs/promises");
|
|
48035
|
-
var SDK_OWNED_SECTIONS = [
|
|
48036
|
-
"Session Initialization",
|
|
48037
|
-
"Identity",
|
|
48038
|
-
"Navigation",
|
|
48039
|
-
"Interaction Guidance",
|
|
48040
|
-
"Commands",
|
|
48041
|
-
"Skills",
|
|
48042
|
-
"Maintaining Memory"
|
|
48043
|
-
];
|
|
48044
|
-
function parseSections(md) {
|
|
48045
|
-
const lines = md.split("\n");
|
|
48046
|
-
const sections = [];
|
|
48047
|
-
let currentHeading = "";
|
|
48048
|
-
let currentLines = [];
|
|
48049
|
-
for (const line of lines) {
|
|
48050
|
-
if (line.startsWith("## ")) {
|
|
48051
|
-
if (currentLines.length > 0 || currentHeading === "") {
|
|
48052
|
-
sections.push({ heading: currentHeading, content: currentLines.join("\n") });
|
|
48053
|
-
}
|
|
48054
|
-
currentHeading = line;
|
|
48055
|
-
currentLines = [line];
|
|
48056
|
-
} else {
|
|
48057
|
-
currentLines.push(line);
|
|
48058
|
-
}
|
|
48059
|
-
}
|
|
48060
|
-
if (currentLines.length > 0 || currentHeading !== "") {
|
|
48061
|
-
sections.push({ heading: currentHeading, content: currentLines.join("\n") });
|
|
48062
|
-
}
|
|
48063
|
-
return sections;
|
|
48064
|
-
}
|
|
48065
|
-
function mergeSections(existing, template, sdkOwned) {
|
|
48066
|
-
const existingSections = parseSections(existing);
|
|
48067
|
-
const templateSections = parseSections(template);
|
|
48068
|
-
const updated = [];
|
|
48069
|
-
const preserved = [];
|
|
48070
|
-
const templateMap = /* @__PURE__ */ new Map();
|
|
48071
|
-
for (const section of templateSections) {
|
|
48072
|
-
templateMap.set(section.heading, section);
|
|
48073
|
-
}
|
|
48074
|
-
const sdkOwnedSet = new Set(sdkOwned.map((s) => `## ${s}`));
|
|
48075
|
-
const resultSections = [];
|
|
48076
|
-
const processedHeadings = /* @__PURE__ */ new Set();
|
|
48077
|
-
for (const section of existingSections) {
|
|
48078
|
-
processedHeadings.add(section.heading);
|
|
48079
|
-
if (section.heading === "") {
|
|
48080
|
-
resultSections.push(section);
|
|
48081
|
-
continue;
|
|
48082
|
-
}
|
|
48083
|
-
if (sdkOwnedSet.has(section.heading)) {
|
|
48084
|
-
const templateSection = templateMap.get(section.heading);
|
|
48085
|
-
if (templateSection) {
|
|
48086
|
-
resultSections.push(templateSection);
|
|
48087
|
-
updated.push(section.heading.replace("## ", ""));
|
|
48088
|
-
} else {
|
|
48089
|
-
updated.push(section.heading.replace("## ", "") + " (removed)");
|
|
48090
|
-
}
|
|
48091
|
-
} else {
|
|
48092
|
-
resultSections.push(section);
|
|
48093
|
-
preserved.push(section.heading.replace("## ", ""));
|
|
48094
|
-
}
|
|
48095
|
-
}
|
|
48096
|
-
for (const section of templateSections) {
|
|
48097
|
-
if (section.heading !== "" && !processedHeadings.has(section.heading)) {
|
|
48098
|
-
resultSections.push(section);
|
|
48099
|
-
updated.push(section.heading.replace("## ", "") + " (new)");
|
|
48100
|
-
}
|
|
48101
|
-
}
|
|
48102
|
-
return {
|
|
48103
|
-
merged: resultSections.map((s) => s.content).join("\n"),
|
|
48104
|
-
updated,
|
|
48105
|
-
preserved
|
|
48106
|
-
};
|
|
48107
|
-
}
|
|
48108
|
-
function registerUpdateCommand(program3) {
|
|
48109
|
-
program3.command("update").description("Update project scaffold to latest template version").option("--ui", "Add a Vite + React UI app in ui/").action(
|
|
48110
|
-
wrapAction("update", async (options2 = {}) => {
|
|
48111
|
-
const cwd = process.cwd();
|
|
48112
|
-
const configPath = (0, import_path4.resolve)(cwd, "elevasis.config.ts");
|
|
48113
|
-
let currentVersion = 0;
|
|
48114
|
-
let configContents = "";
|
|
48115
|
-
try {
|
|
48116
|
-
configContents = await (0, import_promises3.readFile)(configPath, "utf-8");
|
|
48117
|
-
const match = configContents.match(/templateVersion:\s*(\d+)/);
|
|
48118
|
-
if (match) {
|
|
48119
|
-
currentVersion = parseInt(match[1], 10);
|
|
48120
|
-
}
|
|
48121
|
-
} catch {
|
|
48122
|
-
}
|
|
48123
|
-
const upToDate = currentVersion >= TEMPLATE_VERSION;
|
|
48124
|
-
if (upToDate && !options2.ui) {
|
|
48125
|
-
console.log(source_default.green(` Project is up to date (template version ${TEMPLATE_VERSION})`));
|
|
48126
|
-
return;
|
|
48127
|
-
}
|
|
48128
|
-
let hasUI = !!options2.ui;
|
|
48129
|
-
if (!hasUI) {
|
|
48130
|
-
try {
|
|
48131
|
-
await (0, import_promises3.access)((0, import_path4.resolve)(cwd, "ui"));
|
|
48132
|
-
hasUI = true;
|
|
48133
|
-
} catch {
|
|
48134
|
-
}
|
|
48135
|
-
}
|
|
48136
|
-
const managedTemplates = getManagedTemplates({ hasUI });
|
|
48137
|
-
const added = [];
|
|
48138
|
-
const flagged = [];
|
|
48139
|
-
const appendedGitignore = [];
|
|
48140
|
-
const mergedUpdated = [];
|
|
48141
|
-
const mergedPreserved = [];
|
|
48142
|
-
const uiAffectedFiles = /* @__PURE__ */ new Set([".gitignore", "CLAUDE.md"]);
|
|
48143
|
-
const filesToProcess = upToDate ? MANAGED_FILES.filter((f) => uiAffectedFiles.has(f)) : MANAGED_FILES;
|
|
48144
|
-
for (const file2 of filesToProcess) {
|
|
48145
|
-
const filePath = (0, import_path4.resolve)(cwd, file2);
|
|
48146
|
-
const templateFn = managedTemplates[file2];
|
|
48147
|
-
if (!templateFn) continue;
|
|
48148
|
-
const templateContent = templateFn();
|
|
48149
|
-
if (file2 === ".gitignore") {
|
|
48150
|
-
try {
|
|
48151
|
-
await (0, import_promises3.access)(filePath);
|
|
48152
|
-
const existingContent = await (0, import_promises3.readFile)(filePath, "utf-8");
|
|
48153
|
-
const existingLines = existingContent.split("\n");
|
|
48154
|
-
const templateLines = templateContent.split("\n");
|
|
48155
|
-
const linesToAppend = [];
|
|
48156
|
-
for (const line of templateLines) {
|
|
48157
|
-
if (line.trim() === "") continue;
|
|
48158
|
-
if (!existingLines.includes(line)) {
|
|
48159
|
-
linesToAppend.push(line);
|
|
48160
|
-
}
|
|
48161
|
-
}
|
|
48162
|
-
if (linesToAppend.length > 0) {
|
|
48163
|
-
const appendContent = (existingContent.endsWith("\n") ? "" : "\n") + linesToAppend.join("\n") + "\n";
|
|
48164
|
-
await (0, import_promises3.writeFile)(filePath, existingContent + appendContent, "utf-8");
|
|
48165
|
-
appendedGitignore.push(...linesToAppend);
|
|
48166
|
-
}
|
|
48167
|
-
} catch {
|
|
48168
|
-
await (0, import_promises3.mkdir)((0, import_path4.dirname)(filePath), { recursive: true });
|
|
48169
|
-
await (0, import_promises3.writeFile)(filePath, templateContent, "utf-8");
|
|
48170
|
-
added.push(file2);
|
|
48171
|
-
}
|
|
48172
|
-
continue;
|
|
48173
|
-
}
|
|
48174
|
-
if (file2 === "elevasis.config.ts") {
|
|
48175
|
-
if (configContents) {
|
|
48176
|
-
if (/templateVersion:\s*\d+/.test(configContents)) {
|
|
48177
|
-
const updated = configContents.replace(/templateVersion:\s*\d+/, `templateVersion: ${TEMPLATE_VERSION}`);
|
|
48178
|
-
await (0, import_promises3.writeFile)(filePath, updated, "utf-8");
|
|
48179
|
-
} else {
|
|
48180
|
-
const updated = configContents.replace(
|
|
48181
|
-
/\bexport default\s*\{/,
|
|
48182
|
-
`export default {
|
|
48183
|
-
templateVersion: ${TEMPLATE_VERSION},`
|
|
48184
|
-
);
|
|
48185
|
-
await (0, import_promises3.writeFile)(filePath, updated, "utf-8");
|
|
48186
|
-
}
|
|
48187
|
-
} else {
|
|
48188
|
-
await (0, import_promises3.mkdir)((0, import_path4.dirname)(filePath), { recursive: true });
|
|
48189
|
-
await (0, import_promises3.writeFile)(filePath, templateContent, "utf-8");
|
|
48190
|
-
added.push(file2);
|
|
48191
|
-
}
|
|
48192
|
-
continue;
|
|
48193
|
-
}
|
|
48194
|
-
if (file2 === "CLAUDE.md") {
|
|
48195
|
-
let existingContent = null;
|
|
48196
|
-
try {
|
|
48197
|
-
await (0, import_promises3.access)(filePath);
|
|
48198
|
-
existingContent = await (0, import_promises3.readFile)(filePath, "utf-8");
|
|
48199
|
-
} catch {
|
|
48200
|
-
}
|
|
48201
|
-
if (existingContent !== null) {
|
|
48202
|
-
const {
|
|
48203
|
-
merged,
|
|
48204
|
-
updated: sectionUpdated,
|
|
48205
|
-
preserved: sectionPreserved
|
|
48206
|
-
} = mergeSections(existingContent, templateContent, SDK_OWNED_SECTIONS);
|
|
48207
|
-
await (0, import_promises3.writeFile)(filePath, merged, "utf-8");
|
|
48208
|
-
mergedUpdated.push(...sectionUpdated);
|
|
48209
|
-
mergedPreserved.push(...sectionPreserved);
|
|
48210
|
-
} else {
|
|
48211
|
-
await (0, import_promises3.mkdir)((0, import_path4.dirname)(filePath), { recursive: true });
|
|
48212
|
-
await (0, import_promises3.writeFile)(filePath, templateContent, "utf-8");
|
|
48213
|
-
added.push(file2);
|
|
48214
|
-
}
|
|
48215
|
-
continue;
|
|
48216
|
-
}
|
|
48217
|
-
let exists = false;
|
|
48218
|
-
try {
|
|
48219
|
-
await (0, import_promises3.access)(filePath);
|
|
48220
|
-
exists = true;
|
|
48221
|
-
} catch {
|
|
48222
|
-
}
|
|
48223
|
-
if (!exists) {
|
|
48224
|
-
await (0, import_promises3.mkdir)((0, import_path4.dirname)(filePath), { recursive: true });
|
|
48225
|
-
await (0, import_promises3.writeFile)(filePath, templateContent, "utf-8");
|
|
48226
|
-
added.push(file2);
|
|
48227
|
-
} else {
|
|
48228
|
-
const existingContent = await (0, import_promises3.readFile)(filePath, "utf-8");
|
|
48229
|
-
const normalize = (s) => s.replace(/\r\n/g, "\n");
|
|
48230
|
-
if (normalize(existingContent) === normalize(templateContent)) {
|
|
48231
|
-
} else {
|
|
48232
|
-
flagged.push(file2);
|
|
48233
|
-
}
|
|
48234
|
-
}
|
|
48235
|
-
}
|
|
48236
|
-
const OBSOLETE_FILES = [
|
|
48237
|
-
".claude/commands/work.md",
|
|
48238
|
-
// v31: moved to .claude/skills/work/SKILL.md
|
|
48239
|
-
".claude/commands/meta.md",
|
|
48240
|
-
// v33: split into init.md, status.md, fix.md, deploy.md, health.md
|
|
48241
|
-
".claude/commands/health.md"
|
|
48242
|
-
// v33: moved to .claude/skills/diagnostics/SKILL.md
|
|
48243
|
-
];
|
|
48244
|
-
const removed = [];
|
|
48245
|
-
if (!upToDate) {
|
|
48246
|
-
for (const file2 of OBSOLETE_FILES) {
|
|
48247
|
-
const filePath = (0, import_path4.resolve)(cwd, file2);
|
|
48248
|
-
try {
|
|
48249
|
-
await (0, import_promises3.access)(filePath);
|
|
48250
|
-
await (0, import_promises3.unlink)(filePath);
|
|
48251
|
-
removed.push(file2);
|
|
48252
|
-
} catch {
|
|
48253
|
-
}
|
|
48254
|
-
}
|
|
48255
|
-
}
|
|
48256
|
-
const uiAdded = [];
|
|
48257
|
-
const uiSkipped = [];
|
|
48258
|
-
if (options2.ui) {
|
|
48259
|
-
const orgSlug = (0, import_path4.basename)(cwd).toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^[^a-z]+/, "").replace(/-+/g, "-").replace(/-$/, "") || "my-workspace";
|
|
48260
|
-
await (0, import_promises3.mkdir)((0, import_path4.resolve)(cwd, "ui/src"), { recursive: true });
|
|
48261
|
-
const uiFiles = getUIFiles(orgSlug);
|
|
48262
|
-
for (const [file2, content] of Object.entries(uiFiles)) {
|
|
48263
|
-
const filePath = (0, import_path4.resolve)(cwd, file2);
|
|
48264
|
-
let exists = false;
|
|
48265
|
-
try {
|
|
48266
|
-
await (0, import_promises3.access)(filePath);
|
|
48267
|
-
exists = true;
|
|
48268
|
-
} catch {
|
|
48269
|
-
}
|
|
48270
|
-
if (!exists) {
|
|
48271
|
-
await (0, import_promises3.writeFile)(filePath, content, "utf-8");
|
|
48272
|
-
uiAdded.push(file2);
|
|
48273
|
-
} else {
|
|
48274
|
-
uiSkipped.push(file2);
|
|
48275
|
-
}
|
|
48276
|
-
}
|
|
48277
|
-
}
|
|
48278
|
-
console.log("");
|
|
48279
|
-
if (upToDate) {
|
|
48280
|
-
console.log(source_default.green.bold(` Added UI to project (template version ${TEMPLATE_VERSION})`));
|
|
48281
|
-
} else {
|
|
48282
|
-
console.log(source_default.green.bold(` Updated @elevasis/sdk template v${currentVersion} -> v${TEMPLATE_VERSION}`));
|
|
48283
|
-
}
|
|
48284
|
-
if (added.length > 0) {
|
|
48285
|
-
console.log("");
|
|
48286
|
-
console.log(" Added:");
|
|
48287
|
-
for (const file2 of added) {
|
|
48288
|
-
console.log(source_default.green(` ${file2}`));
|
|
48289
|
-
}
|
|
48290
|
-
}
|
|
48291
|
-
if (removed.length > 0) {
|
|
48292
|
-
console.log("");
|
|
48293
|
-
console.log(" Removed (obsolete):");
|
|
48294
|
-
for (const file2 of removed) {
|
|
48295
|
-
console.log(source_default.red(` ${file2}`));
|
|
48296
|
-
}
|
|
48297
|
-
}
|
|
48298
|
-
if (appendedGitignore.length > 0) {
|
|
48299
|
-
console.log("");
|
|
48300
|
-
console.log(" Appended to .gitignore:");
|
|
48301
|
-
for (const entry of appendedGitignore) {
|
|
48302
|
-
console.log(source_default.yellow(` ${entry}`));
|
|
48303
|
-
}
|
|
48304
|
-
}
|
|
48305
|
-
if (flagged.length > 0) {
|
|
48306
|
-
console.log("");
|
|
48307
|
-
console.log(" Needs agent review:");
|
|
48308
|
-
for (const file2 of flagged) {
|
|
48309
|
-
console.log(source_default.cyan(` ${file2} (differs from template)`));
|
|
48310
|
-
}
|
|
48311
|
-
}
|
|
48312
|
-
if (flagged.length > 0) {
|
|
48313
|
-
console.log("");
|
|
48314
|
-
console.log(source_default.gray(" Run /fix in Claude Code to verify and repair the full framework."));
|
|
48315
|
-
}
|
|
48316
|
-
if (mergedUpdated.length > 0 || mergedPreserved.length > 0) {
|
|
48317
|
-
console.log("");
|
|
48318
|
-
console.log(" CLAUDE.md sections:");
|
|
48319
|
-
for (const section of mergedUpdated) {
|
|
48320
|
-
console.log(source_default.green(` updated: ${section}`));
|
|
48321
|
-
}
|
|
48322
|
-
for (const section of mergedPreserved) {
|
|
48323
|
-
console.log(source_default.gray(` preserved: ${section}`));
|
|
48324
|
-
}
|
|
48325
|
-
}
|
|
48326
|
-
if (uiAdded.length > 0) {
|
|
48327
|
-
console.log("");
|
|
48328
|
-
console.log(" UI scaffold added:");
|
|
48329
|
-
for (const file2 of uiAdded) {
|
|
48330
|
-
console.log(source_default.green(` ${file2}`));
|
|
48331
|
-
}
|
|
48332
|
-
console.log("");
|
|
48333
|
-
console.log(source_default.gray(" Next: cd ui && pnpm install"));
|
|
48334
|
-
console.log(source_default.gray(" Set VITE_WORKOS_CLIENT_ID in ui/.env"));
|
|
48335
|
-
}
|
|
48336
|
-
if (uiSkipped.length > 0) {
|
|
48337
|
-
console.log("");
|
|
48338
|
-
console.log(" UI files already exist (skipped):");
|
|
48339
|
-
for (const file2 of uiSkipped) {
|
|
48340
|
-
console.log(source_default.gray(` ${file2}`));
|
|
48341
|
-
}
|
|
48342
|
-
}
|
|
48343
|
-
console.log("");
|
|
48344
|
-
})
|
|
48345
|
-
);
|
|
48346
|
-
}
|
|
45306
|
+
// src/cli/commands/creds/creds.ts
|
|
45307
|
+
init_config();
|
|
48347
45308
|
|
|
48348
45309
|
// src/cli/commands/creds/creds-list.ts
|
|
48349
45310
|
async function listCreds(apiUrl, json2) {
|
|
@@ -48494,10 +45455,10 @@ Credential renamed successfully!`));
|
|
|
48494
45455
|
var import_readline = require("readline");
|
|
48495
45456
|
function confirm(message) {
|
|
48496
45457
|
const rl = (0, import_readline.createInterface)({ input: process.stdin, output: process.stdout });
|
|
48497
|
-
return new Promise((
|
|
45458
|
+
return new Promise((resolve4) => {
|
|
48498
45459
|
rl.question(message, (answer) => {
|
|
48499
45460
|
rl.close();
|
|
48500
|
-
|
|
45461
|
+
resolve4(answer.toLowerCase() === "y" || answer.toLowerCase() === "yes");
|
|
48501
45462
|
});
|
|
48502
45463
|
});
|
|
48503
45464
|
}
|
|
@@ -48555,6 +45516,9 @@ function registerCredsCommand(program3) {
|
|
|
48555
45516
|
}));
|
|
48556
45517
|
}
|
|
48557
45518
|
|
|
45519
|
+
// src/cli/commands/error/error.ts
|
|
45520
|
+
init_config();
|
|
45521
|
+
|
|
48558
45522
|
// src/cli/commands/error/error-resolve.ts
|
|
48559
45523
|
async function resolveError(apiUrl, errorId) {
|
|
48560
45524
|
const spinner = ora("Resolving error...").start();
|
|
@@ -48591,6 +45555,7 @@ function registerErrorCommand(program3) {
|
|
|
48591
45555
|
}
|
|
48592
45556
|
|
|
48593
45557
|
// src/cli/commands/rename.ts
|
|
45558
|
+
init_config();
|
|
48594
45559
|
function registerRenameCommand(program3) {
|
|
48595
45560
|
program3.command("rename <oldResourceId>").description("Rename a resource ID across all platform tables (dry run by default)").requiredOption("--to <newResourceId>", "New resource ID").option("--execute", "Apply the rename (default: dry run preview only)").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API URL").action(
|
|
48596
45561
|
wrapAction("rename", async (oldResourceId, options2) => {
|
|
@@ -48628,8 +45593,638 @@ function registerRenameCommand(program3) {
|
|
|
48628
45593
|
);
|
|
48629
45594
|
}
|
|
48630
45595
|
|
|
45596
|
+
// src/cli/commands/project/projects.ts
|
|
45597
|
+
init_config();
|
|
45598
|
+
function registerProjectList(program3) {
|
|
45599
|
+
program3.command("project:list").description("List all projects\n Example: elevasis-sdk project:list --kind internal").option("--kind <kind>", "Filter by kind: client_engagement | internal | research | other").option("--status <status>", "Filter by status: active | on_track | at_risk | blocked | completed | paused").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45600
|
+
wrapAction("project:list", async (options2) => {
|
|
45601
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45602
|
+
const params = new URLSearchParams();
|
|
45603
|
+
if (options2.kind) params.set("kind", options2.kind);
|
|
45604
|
+
if (options2.status) params.set("status", options2.status);
|
|
45605
|
+
const qs = params.toString();
|
|
45606
|
+
const endpoint = `/api/external/projects${qs ? `?${qs}` : ""}`;
|
|
45607
|
+
const result = await apiGet(endpoint, apiUrl);
|
|
45608
|
+
if (options2.pretty) {
|
|
45609
|
+
const projects = result.projects;
|
|
45610
|
+
if (projects.length === 0) {
|
|
45611
|
+
console.log(source_default.yellow("No projects found."));
|
|
45612
|
+
return;
|
|
45613
|
+
}
|
|
45614
|
+
console.log(source_default.cyan(`
|
|
45615
|
+
Projects (${projects.length}):
|
|
45616
|
+
`));
|
|
45617
|
+
for (const p of projects) {
|
|
45618
|
+
console.log(` ${source_default.bold(p.name)} ${source_default.dim(p.kind)} ${source_default.gray(p.status)}`);
|
|
45619
|
+
console.log(source_default.gray(` ID: ${p.id}`));
|
|
45620
|
+
if (p.description) console.log(source_default.gray(` ${p.description}`));
|
|
45621
|
+
}
|
|
45622
|
+
console.log();
|
|
45623
|
+
} else {
|
|
45624
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45625
|
+
}
|
|
45626
|
+
})
|
|
45627
|
+
);
|
|
45628
|
+
}
|
|
45629
|
+
function registerProjectGet(program3) {
|
|
45630
|
+
program3.command("project:get <id>").description("Get a project by ID\n Example: elevasis-sdk project:get <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45631
|
+
wrapAction("project:get", async (id, options2) => {
|
|
45632
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45633
|
+
const result = await apiGet(`/api/external/projects/${id}`, apiUrl);
|
|
45634
|
+
if (options2.pretty) {
|
|
45635
|
+
const p = result.project;
|
|
45636
|
+
console.log(source_default.cyan(`
|
|
45637
|
+
Project: ${p.name}`));
|
|
45638
|
+
console.log(source_default.gray(` ID: ${p.id}`));
|
|
45639
|
+
console.log(source_default.gray(` Kind: ${p.kind}`));
|
|
45640
|
+
console.log(source_default.gray(` Status: ${p.status}`));
|
|
45641
|
+
if (p.description) console.log(source_default.gray(` Description: ${p.description}`));
|
|
45642
|
+
console.log();
|
|
45643
|
+
} else {
|
|
45644
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45645
|
+
}
|
|
45646
|
+
})
|
|
45647
|
+
);
|
|
45648
|
+
}
|
|
45649
|
+
function registerProjectCreate(program3) {
|
|
45650
|
+
program3.command("project:create").description('Create a new project\n Example: elevasis-sdk project:create --name "My Project" --kind internal').requiredOption("--name <name>", "Project name").requiredOption("--kind <kind>", "Project kind: client_engagement | internal | research | other").option("--status <status>", "Project status: active | on_track | at_risk | blocked | completed | paused").option("--description <description>", "Project description").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45651
|
+
wrapAction(
|
|
45652
|
+
"project:create",
|
|
45653
|
+
async (options2) => {
|
|
45654
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45655
|
+
const body = {
|
|
45656
|
+
name: options2.name,
|
|
45657
|
+
kind: options2.kind
|
|
45658
|
+
};
|
|
45659
|
+
if (options2.status) body.status = options2.status;
|
|
45660
|
+
if (options2.description) body.description = options2.description;
|
|
45661
|
+
const result = await apiPost("/api/external/projects", body, apiUrl);
|
|
45662
|
+
if (options2.pretty) {
|
|
45663
|
+
const p = result.project;
|
|
45664
|
+
console.log(source_default.green(`
|
|
45665
|
+
Project created: ${p.name}`));
|
|
45666
|
+
console.log(source_default.gray(` ID: ${p.id}`));
|
|
45667
|
+
console.log(source_default.gray(` Kind: ${p.kind}`));
|
|
45668
|
+
console.log(source_default.gray(` Status: ${p.status}`));
|
|
45669
|
+
console.log();
|
|
45670
|
+
} else {
|
|
45671
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45672
|
+
}
|
|
45673
|
+
}
|
|
45674
|
+
)
|
|
45675
|
+
);
|
|
45676
|
+
}
|
|
45677
|
+
function registerProjectUpdate(program3) {
|
|
45678
|
+
program3.command("project:update <id>").description("Update a project\n Example: elevasis-sdk project:update <uuid> --status completed").option("--name <name>", "New project name").option("--status <status>", "New status: active | on_track | at_risk | blocked | completed | paused").option("--description <description>", "New description").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45679
|
+
wrapAction(
|
|
45680
|
+
"project:update",
|
|
45681
|
+
async (id, options2) => {
|
|
45682
|
+
const body = {};
|
|
45683
|
+
if (options2.name !== void 0) body.name = options2.name;
|
|
45684
|
+
if (options2.status !== void 0) body.status = options2.status;
|
|
45685
|
+
if (options2.description !== void 0) body.description = options2.description;
|
|
45686
|
+
if (Object.keys(body).length === 0) {
|
|
45687
|
+
process.stderr.write(
|
|
45688
|
+
JSON.stringify({
|
|
45689
|
+
error: "At least one field must be provided (--name, --status, --description)",
|
|
45690
|
+
code: "MISSING_FIELDS"
|
|
45691
|
+
}) + "\n"
|
|
45692
|
+
);
|
|
45693
|
+
process.exit(1);
|
|
45694
|
+
}
|
|
45695
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45696
|
+
const result = await apiPatch(`/api/external/projects/${id}`, body, apiUrl);
|
|
45697
|
+
if (options2.pretty) {
|
|
45698
|
+
const p = result.project;
|
|
45699
|
+
console.log(source_default.green(`
|
|
45700
|
+
Project updated: ${p.name}`));
|
|
45701
|
+
console.log(source_default.gray(` Status: ${p.status}`));
|
|
45702
|
+
console.log();
|
|
45703
|
+
} else {
|
|
45704
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45705
|
+
}
|
|
45706
|
+
}
|
|
45707
|
+
)
|
|
45708
|
+
);
|
|
45709
|
+
}
|
|
45710
|
+
function registerProjectDelete(program3) {
|
|
45711
|
+
program3.command("project:delete <id>").description("Delete a project\n Example: elevasis-sdk project:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45712
|
+
wrapAction("project:delete", async (id, options2) => {
|
|
45713
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45714
|
+
const result = await apiDelete(`/api/external/projects/${id}`, apiUrl);
|
|
45715
|
+
if (options2.pretty) {
|
|
45716
|
+
console.log(source_default.green(`
|
|
45717
|
+
Project ${id} deleted.`));
|
|
45718
|
+
console.log();
|
|
45719
|
+
} else {
|
|
45720
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45721
|
+
}
|
|
45722
|
+
})
|
|
45723
|
+
);
|
|
45724
|
+
}
|
|
45725
|
+
|
|
45726
|
+
// src/cli/commands/project/milestones.ts
|
|
45727
|
+
init_config();
|
|
45728
|
+
function registerMilestoneList(program3) {
|
|
45729
|
+
program3.command("project:milestone:list").description("List milestones for a project\n Example: elevasis-sdk project:milestone:list --project <uuid>").requiredOption("--project <project-id>", "Project ID (UUID)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45730
|
+
wrapAction("project:milestone:list", async (options2) => {
|
|
45731
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45732
|
+
const result = await apiGet(`/api/external/projects/${options2.project}/milestones`, apiUrl);
|
|
45733
|
+
if (options2.pretty) {
|
|
45734
|
+
const milestones = result.milestones;
|
|
45735
|
+
if (milestones.length === 0) {
|
|
45736
|
+
console.log(source_default.yellow("No milestones found."));
|
|
45737
|
+
return;
|
|
45738
|
+
}
|
|
45739
|
+
console.log(source_default.cyan(`
|
|
45740
|
+
Milestones (${milestones.length}):
|
|
45741
|
+
`));
|
|
45742
|
+
for (const m of milestones) {
|
|
45743
|
+
console.log(` ${source_default.bold(m.name)} ${source_default.gray(m.status)}`);
|
|
45744
|
+
console.log(source_default.gray(` ID: ${m.id}`));
|
|
45745
|
+
if (m.due_date) console.log(source_default.gray(` Due: ${m.due_date}`));
|
|
45746
|
+
}
|
|
45747
|
+
console.log();
|
|
45748
|
+
} else {
|
|
45749
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45750
|
+
}
|
|
45751
|
+
})
|
|
45752
|
+
);
|
|
45753
|
+
}
|
|
45754
|
+
function registerMilestoneCreate(program3) {
|
|
45755
|
+
program3.command("project:milestone:create").description(
|
|
45756
|
+
'Create a milestone\n Example: elevasis-sdk project:milestone:create --project <uuid> --name "Phase 1"'
|
|
45757
|
+
).requiredOption("--project <project-id>", "Project ID (UUID)").requiredOption("--name <name>", "Milestone name").option("--status <status>", "Status: upcoming | in_progress | completed | overdue | blocked").option("--due-date <date>", "Due date (ISO 8601, e.g. 2026-06-01)").option("--description <description>", "Milestone description").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45758
|
+
wrapAction(
|
|
45759
|
+
"project:milestone:create",
|
|
45760
|
+
async (options2) => {
|
|
45761
|
+
const body = { name: options2.name };
|
|
45762
|
+
if (options2.status) body.status = options2.status;
|
|
45763
|
+
if (options2.dueDate) body.due_date = options2.dueDate;
|
|
45764
|
+
if (options2.description) body.description = options2.description;
|
|
45765
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45766
|
+
const result = await apiPost(
|
|
45767
|
+
`/api/external/projects/${options2.project}/milestones`,
|
|
45768
|
+
body,
|
|
45769
|
+
apiUrl
|
|
45770
|
+
);
|
|
45771
|
+
if (options2.pretty) {
|
|
45772
|
+
const m = result.milestone;
|
|
45773
|
+
console.log(source_default.green(`
|
|
45774
|
+
Milestone created: ${m.name}`));
|
|
45775
|
+
console.log(source_default.gray(` ID: ${m.id}`));
|
|
45776
|
+
console.log(source_default.gray(` Status: ${m.status}`));
|
|
45777
|
+
if (m.due_date) console.log(source_default.gray(` Due: ${m.due_date}`));
|
|
45778
|
+
console.log();
|
|
45779
|
+
} else {
|
|
45780
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45781
|
+
}
|
|
45782
|
+
}
|
|
45783
|
+
)
|
|
45784
|
+
);
|
|
45785
|
+
}
|
|
45786
|
+
function registerMilestoneUpdate(program3) {
|
|
45787
|
+
program3.command("project:milestone:update <id>").description("Update a milestone\n Example: elevasis-sdk project:milestone:update <uuid> --status completed").option("--name <name>", "New milestone name").option("--status <status>", "New status: upcoming | in_progress | completed | overdue | blocked").option("--due-date <date>", "New due date (ISO 8601)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45788
|
+
wrapAction(
|
|
45789
|
+
"project:milestone:update",
|
|
45790
|
+
async (id, options2) => {
|
|
45791
|
+
const body = {};
|
|
45792
|
+
if (options2.name !== void 0) body.name = options2.name;
|
|
45793
|
+
if (options2.status !== void 0) body.status = options2.status;
|
|
45794
|
+
if (options2.dueDate !== void 0) body.due_date = options2.dueDate;
|
|
45795
|
+
if (Object.keys(body).length === 0) {
|
|
45796
|
+
process.stderr.write(
|
|
45797
|
+
JSON.stringify({
|
|
45798
|
+
error: "At least one field must be provided (--name, --status, --due-date)",
|
|
45799
|
+
code: "MISSING_FIELDS"
|
|
45800
|
+
}) + "\n"
|
|
45801
|
+
);
|
|
45802
|
+
process.exit(1);
|
|
45803
|
+
}
|
|
45804
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45805
|
+
const result = await apiPatch(`/api/external/milestones/${id}`, body, apiUrl);
|
|
45806
|
+
if (options2.pretty) {
|
|
45807
|
+
const m = result.milestone;
|
|
45808
|
+
console.log(source_default.green(`
|
|
45809
|
+
Milestone updated: ${m.name}`));
|
|
45810
|
+
console.log(source_default.gray(` Status: ${m.status}`));
|
|
45811
|
+
console.log();
|
|
45812
|
+
} else {
|
|
45813
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45814
|
+
}
|
|
45815
|
+
}
|
|
45816
|
+
)
|
|
45817
|
+
);
|
|
45818
|
+
}
|
|
45819
|
+
function registerMilestoneDelete(program3) {
|
|
45820
|
+
program3.command("project:milestone:delete <id>").description("Delete a milestone\n Example: elevasis-sdk project:milestone:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45821
|
+
wrapAction("project:milestone:delete", async (id, options2) => {
|
|
45822
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45823
|
+
const result = await apiDelete(`/api/external/milestones/${id}`, apiUrl);
|
|
45824
|
+
if (options2.pretty) {
|
|
45825
|
+
console.log(source_default.green(`
|
|
45826
|
+
Milestone ${id} deleted.`));
|
|
45827
|
+
console.log();
|
|
45828
|
+
} else {
|
|
45829
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45830
|
+
}
|
|
45831
|
+
})
|
|
45832
|
+
);
|
|
45833
|
+
}
|
|
45834
|
+
|
|
45835
|
+
// src/cli/commands/project/tasks.ts
|
|
45836
|
+
init_config();
|
|
45837
|
+
function registerTaskList(program3) {
|
|
45838
|
+
program3.command("project:task:list").description(
|
|
45839
|
+
"List tasks for a project\n Example: elevasis-sdk project:task:list --project <uuid> --status in_progress"
|
|
45840
|
+
).requiredOption("--project <project-id>", "Project ID (UUID)").option(
|
|
45841
|
+
"--status <status>",
|
|
45842
|
+
"Filter by status: planned | in_progress | blocked | completed | cancelled | submitted | approved | rejected | revision_requested"
|
|
45843
|
+
).option("--milestone <milestone-id>", "Filter by milestone ID (UUID)").option("--parent <parent-task-id>", "Filter by parent task ID (UUID)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45844
|
+
wrapAction(
|
|
45845
|
+
"project:task:list",
|
|
45846
|
+
async (options2) => {
|
|
45847
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45848
|
+
const params = new URLSearchParams();
|
|
45849
|
+
if (options2.status) params.set("status", options2.status);
|
|
45850
|
+
if (options2.milestone) params.set("milestone_id", options2.milestone);
|
|
45851
|
+
if (options2.parent) params.set("parent_task_id", options2.parent);
|
|
45852
|
+
const qs = params.toString();
|
|
45853
|
+
const endpoint = `/api/external/projects/${options2.project}/tasks${qs ? `?${qs}` : ""}`;
|
|
45854
|
+
const result = await apiGet(endpoint, apiUrl);
|
|
45855
|
+
if (options2.pretty) {
|
|
45856
|
+
const tasks = result.tasks;
|
|
45857
|
+
if (tasks.length === 0) {
|
|
45858
|
+
console.log(source_default.yellow("No tasks found."));
|
|
45859
|
+
return;
|
|
45860
|
+
}
|
|
45861
|
+
console.log(source_default.cyan(`
|
|
45862
|
+
Tasks (${tasks.length}):
|
|
45863
|
+
`));
|
|
45864
|
+
for (const t of tasks) {
|
|
45865
|
+
console.log(` ${source_default.bold(t.name)} ${source_default.dim(t.type ?? "")} ${source_default.gray(t.status)}`);
|
|
45866
|
+
console.log(source_default.gray(` ID: ${t.id}`));
|
|
45867
|
+
if (t.description) console.log(source_default.gray(` ${t.description}`));
|
|
45868
|
+
}
|
|
45869
|
+
console.log();
|
|
45870
|
+
} else {
|
|
45871
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45872
|
+
}
|
|
45873
|
+
}
|
|
45874
|
+
)
|
|
45875
|
+
);
|
|
45876
|
+
}
|
|
45877
|
+
function registerTaskGet(program3) {
|
|
45878
|
+
program3.command("project:task:get <id>").description("Get a task by ID\n Example: elevasis-sdk project:task:get <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45879
|
+
wrapAction("project:task:get", async (id, options2) => {
|
|
45880
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45881
|
+
const result = await apiGet(`/api/external/tasks/${id}`, apiUrl);
|
|
45882
|
+
if (options2.pretty) {
|
|
45883
|
+
const t = result.task;
|
|
45884
|
+
console.log(source_default.cyan(`
|
|
45885
|
+
Task: ${t.name}`));
|
|
45886
|
+
console.log(source_default.gray(` ID: ${t.id}`));
|
|
45887
|
+
console.log(source_default.gray(` Type: ${t.type ?? "other"}`));
|
|
45888
|
+
console.log(source_default.gray(` Status: ${t.status}`));
|
|
45889
|
+
if (t.description) console.log(source_default.gray(` Description: ${t.description}`));
|
|
45890
|
+
if (t.milestone_id) console.log(source_default.gray(` Milestone: ${t.milestone_id}`));
|
|
45891
|
+
console.log();
|
|
45892
|
+
} else {
|
|
45893
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45894
|
+
}
|
|
45895
|
+
})
|
|
45896
|
+
);
|
|
45897
|
+
}
|
|
45898
|
+
function registerTaskCreate(program3) {
|
|
45899
|
+
program3.command("project:task:create").description(
|
|
45900
|
+
'Create a task\n Example: elevasis-sdk project:task:create --project <uuid> --title "Implement feature"'
|
|
45901
|
+
).requiredOption("--project <project-id>", "Project ID (UUID)").requiredOption("--title <title>", "Task title / name").option("--status <status>", "Status: planned | in_progress | blocked | completed | cancelled").option(
|
|
45902
|
+
"--type <type>",
|
|
45903
|
+
"Type: documentation | code | report | design | refactor | feature | bug | research | other"
|
|
45904
|
+
).option("--milestone <milestone-id>", "Milestone ID (UUID)").option("--parent <parent-task-id>", "Parent task ID (UUID) for subtasks").option("--description <description>", "Task description").option("--checklist <json>", `Checklist items as JSON array: '[{"id":"1","label":"Step","completed":false}]'`).option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45905
|
+
wrapAction(
|
|
45906
|
+
"project:task:create",
|
|
45907
|
+
async (options2) => {
|
|
45908
|
+
const body = {
|
|
45909
|
+
project_id: options2.project,
|
|
45910
|
+
name: options2.title
|
|
45911
|
+
};
|
|
45912
|
+
if (options2.status) body.status = options2.status;
|
|
45913
|
+
if (options2.type) body.type = options2.type;
|
|
45914
|
+
if (options2.milestone) body.milestone_id = options2.milestone;
|
|
45915
|
+
if (options2.parent) body.parent_task_id = options2.parent;
|
|
45916
|
+
if (options2.description) body.description = options2.description;
|
|
45917
|
+
if (options2.checklist) {
|
|
45918
|
+
try {
|
|
45919
|
+
body.checklist = JSON.parse(options2.checklist);
|
|
45920
|
+
} catch {
|
|
45921
|
+
process.stderr.write(
|
|
45922
|
+
JSON.stringify({ error: "--checklist must be valid JSON", code: "INVALID_JSON" }) + "\n"
|
|
45923
|
+
);
|
|
45924
|
+
process.exit(1);
|
|
45925
|
+
}
|
|
45926
|
+
}
|
|
45927
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45928
|
+
const result = await apiPost("/api/external/tasks", body, apiUrl);
|
|
45929
|
+
if (options2.pretty) {
|
|
45930
|
+
const t = result.task;
|
|
45931
|
+
console.log(source_default.green(`
|
|
45932
|
+
Task created: ${t.name}`));
|
|
45933
|
+
console.log(source_default.gray(` ID: ${t.id}`));
|
|
45934
|
+
console.log(source_default.gray(` Status: ${t.status}`));
|
|
45935
|
+
console.log();
|
|
45936
|
+
} else {
|
|
45937
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45938
|
+
}
|
|
45939
|
+
}
|
|
45940
|
+
)
|
|
45941
|
+
);
|
|
45942
|
+
}
|
|
45943
|
+
function registerTaskUpdate(program3) {
|
|
45944
|
+
program3.command("project:task:update <id>").description("Update a task\n Example: elevasis-sdk project:task:update <uuid> --status completed").option("--title <title>", "New task title").option(
|
|
45945
|
+
"--status <status>",
|
|
45946
|
+
"New status: planned | in_progress | blocked | completed | cancelled | submitted | approved | rejected | revision_requested"
|
|
45947
|
+
).option("--milestone <milestone-id>", "New milestone ID (UUID)").option("--description <description>", "New description").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45948
|
+
wrapAction(
|
|
45949
|
+
"project:task:update",
|
|
45950
|
+
async (id, options2) => {
|
|
45951
|
+
const body = {};
|
|
45952
|
+
if (options2.title !== void 0) body.name = options2.title;
|
|
45953
|
+
if (options2.status !== void 0) body.status = options2.status;
|
|
45954
|
+
if (options2.milestone !== void 0) body.milestone_id = options2.milestone;
|
|
45955
|
+
if (options2.description !== void 0) body.description = options2.description;
|
|
45956
|
+
if (Object.keys(body).length === 0) {
|
|
45957
|
+
process.stderr.write(
|
|
45958
|
+
JSON.stringify({
|
|
45959
|
+
error: "At least one field must be provided (--title, --status, --milestone, --description)",
|
|
45960
|
+
code: "MISSING_FIELDS"
|
|
45961
|
+
}) + "\n"
|
|
45962
|
+
);
|
|
45963
|
+
process.exit(1);
|
|
45964
|
+
}
|
|
45965
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45966
|
+
const result = await apiPatch(`/api/external/tasks/${id}`, body, apiUrl);
|
|
45967
|
+
if (options2.pretty) {
|
|
45968
|
+
const t = result.task;
|
|
45969
|
+
console.log(source_default.green(`
|
|
45970
|
+
Task updated: ${t.name}`));
|
|
45971
|
+
console.log(source_default.gray(` Status: ${t.status}`));
|
|
45972
|
+
console.log();
|
|
45973
|
+
} else {
|
|
45974
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45975
|
+
}
|
|
45976
|
+
}
|
|
45977
|
+
)
|
|
45978
|
+
);
|
|
45979
|
+
}
|
|
45980
|
+
function registerTaskDelete(program3) {
|
|
45981
|
+
program3.command("project:task:delete <id>").description("Delete a task\n Example: elevasis-sdk project:task:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
45982
|
+
wrapAction("project:task:delete", async (id, options2) => {
|
|
45983
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
45984
|
+
const result = await apiDelete(`/api/external/tasks/${id}`, apiUrl);
|
|
45985
|
+
if (options2.pretty) {
|
|
45986
|
+
console.log(source_default.green(`
|
|
45987
|
+
Task ${id} deleted.`));
|
|
45988
|
+
console.log();
|
|
45989
|
+
} else {
|
|
45990
|
+
console.log(JSON.stringify(result, null, 2));
|
|
45991
|
+
}
|
|
45992
|
+
})
|
|
45993
|
+
);
|
|
45994
|
+
}
|
|
45995
|
+
function registerTaskResume(program3) {
|
|
45996
|
+
program3.command("project:task:resume <id>").description(
|
|
45997
|
+
"Fetch the resume_context JSONB for a task (used by /work resume)\n Example: elevasis-sdk project:task:resume <uuid>"
|
|
45998
|
+
).option("--api-url <url>", "API base URL").option("--pretty", "Render a human-readable resume briefing instead of raw JSON").action(
|
|
45999
|
+
wrapAction("project:task:resume", async (id, options2) => {
|
|
46000
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
46001
|
+
const result = await apiGet(`/api/external/tasks/${id}`, apiUrl);
|
|
46002
|
+
const task = result.task;
|
|
46003
|
+
const ctx = task.resume_context ?? {};
|
|
46004
|
+
if (options2.pretty) {
|
|
46005
|
+
console.log(source_default.cyan(`
|
|
46006
|
+
Resume briefing for task: ${task.name}`));
|
|
46007
|
+
console.log(source_default.gray(` Status: ${task.status}`));
|
|
46008
|
+
console.log();
|
|
46009
|
+
if (ctx.current_state) {
|
|
46010
|
+
console.log(source_default.bold("Current state:"));
|
|
46011
|
+
console.log(` ${ctx.current_state}`);
|
|
46012
|
+
console.log();
|
|
46013
|
+
}
|
|
46014
|
+
if (ctx.next_steps) {
|
|
46015
|
+
console.log(source_default.bold("Next steps:"));
|
|
46016
|
+
console.log(` ${ctx.next_steps}`);
|
|
46017
|
+
console.log();
|
|
46018
|
+
}
|
|
46019
|
+
if (Array.isArray(ctx.files_modified) && ctx.files_modified.length > 0) {
|
|
46020
|
+
console.log(source_default.bold("Files modified:"));
|
|
46021
|
+
for (const f of ctx.files_modified) console.log(` - ${f}`);
|
|
46022
|
+
console.log();
|
|
46023
|
+
}
|
|
46024
|
+
if (Array.isArray(ctx.key_docs) && ctx.key_docs.length > 0) {
|
|
46025
|
+
console.log(source_default.bold("Key docs:"));
|
|
46026
|
+
for (const d of ctx.key_docs) console.log(` - ${d}`);
|
|
46027
|
+
console.log();
|
|
46028
|
+
}
|
|
46029
|
+
if (Array.isArray(ctx.tools) && ctx.tools.length > 0) {
|
|
46030
|
+
console.log(source_default.bold("Tools used:"));
|
|
46031
|
+
for (const t of ctx.tools) console.log(` - ${t}`);
|
|
46032
|
+
console.log();
|
|
46033
|
+
}
|
|
46034
|
+
if (ctx.last_saved) {
|
|
46035
|
+
console.log(source_default.gray(`Last saved: ${ctx.last_saved}`));
|
|
46036
|
+
}
|
|
46037
|
+
} else {
|
|
46038
|
+
console.log(JSON.stringify(ctx, null, 2));
|
|
46039
|
+
}
|
|
46040
|
+
})
|
|
46041
|
+
);
|
|
46042
|
+
}
|
|
46043
|
+
function registerTaskSave(program3) {
|
|
46044
|
+
program3.command("project:task:save <id>").description(
|
|
46045
|
+
`Merge fields into resume_context for a task (used by /work save)
|
|
46046
|
+
Example: elevasis-sdk project:task:save <uuid> --current-state "Implemented X" --files-modified '["src/foo.ts"]'`
|
|
46047
|
+
).requiredOption("--current-state <text>", "Current state description").option("--files-modified <json>", "JSON array of modified file paths").option("--next-steps <text>", "Next steps description").option("--key-docs <json>", "JSON array of key doc paths").option("--tools <json>", "JSON array of tool names used").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
46048
|
+
wrapAction(
|
|
46049
|
+
"project:task:save",
|
|
46050
|
+
async (id, options2) => {
|
|
46051
|
+
const body = {
|
|
46052
|
+
current_state: options2.currentState
|
|
46053
|
+
};
|
|
46054
|
+
if (options2.filesModified !== void 0) {
|
|
46055
|
+
try {
|
|
46056
|
+
body.files_modified = JSON.parse(options2.filesModified);
|
|
46057
|
+
} catch {
|
|
46058
|
+
process.stderr.write(
|
|
46059
|
+
JSON.stringify({ error: "--files-modified must be valid JSON array", code: "INVALID_JSON" }) + "\n"
|
|
46060
|
+
);
|
|
46061
|
+
process.exit(1);
|
|
46062
|
+
}
|
|
46063
|
+
}
|
|
46064
|
+
if (options2.nextSteps !== void 0) {
|
|
46065
|
+
body.next_steps = options2.nextSteps;
|
|
46066
|
+
}
|
|
46067
|
+
if (options2.keyDocs !== void 0) {
|
|
46068
|
+
try {
|
|
46069
|
+
body.key_docs = JSON.parse(options2.keyDocs);
|
|
46070
|
+
} catch {
|
|
46071
|
+
process.stderr.write(
|
|
46072
|
+
JSON.stringify({ error: "--key-docs must be valid JSON array", code: "INVALID_JSON" }) + "\n"
|
|
46073
|
+
);
|
|
46074
|
+
process.exit(1);
|
|
46075
|
+
}
|
|
46076
|
+
}
|
|
46077
|
+
if (options2.tools !== void 0) {
|
|
46078
|
+
try {
|
|
46079
|
+
body.tools = JSON.parse(options2.tools);
|
|
46080
|
+
} catch {
|
|
46081
|
+
process.stderr.write(
|
|
46082
|
+
JSON.stringify({ error: "--tools must be valid JSON array", code: "INVALID_JSON" }) + "\n"
|
|
46083
|
+
);
|
|
46084
|
+
process.exit(1);
|
|
46085
|
+
}
|
|
46086
|
+
}
|
|
46087
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
46088
|
+
const result = await apiPatch(`/api/external/tasks/${id}/resume-context`, body, apiUrl);
|
|
46089
|
+
if (options2.pretty) {
|
|
46090
|
+
console.log(source_default.green(`
|
|
46091
|
+
Resume context saved for task ${id}`));
|
|
46092
|
+
if (result.task?.resume_context) {
|
|
46093
|
+
const ctx = result.task.resume_context;
|
|
46094
|
+
if (ctx.last_saved) console.log(source_default.gray(` Saved at: ${ctx.last_saved}`));
|
|
46095
|
+
}
|
|
46096
|
+
console.log();
|
|
46097
|
+
} else {
|
|
46098
|
+
console.log(JSON.stringify(result, null, 2));
|
|
46099
|
+
}
|
|
46100
|
+
}
|
|
46101
|
+
)
|
|
46102
|
+
);
|
|
46103
|
+
}
|
|
46104
|
+
|
|
46105
|
+
// src/cli/commands/project/notes.ts
|
|
46106
|
+
init_config();
|
|
46107
|
+
function registerNoteList(program3) {
|
|
46108
|
+
program3.command("project:note:list").description("List notes for a project\n Example: elevasis-sdk project:note:list --project <uuid>").requiredOption("--project <project-id>", "Project ID (UUID)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
46109
|
+
wrapAction("project:note:list", async (options2) => {
|
|
46110
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
46111
|
+
const result = await apiGet(`/api/external/projects/${options2.project}/notes`, apiUrl);
|
|
46112
|
+
if (options2.pretty) {
|
|
46113
|
+
const notes = result.notes;
|
|
46114
|
+
if (notes.length === 0) {
|
|
46115
|
+
console.log(source_default.yellow("No notes found."));
|
|
46116
|
+
return;
|
|
46117
|
+
}
|
|
46118
|
+
console.log(source_default.cyan(`
|
|
46119
|
+
Notes (${notes.length}):
|
|
46120
|
+
`));
|
|
46121
|
+
for (const n of notes) {
|
|
46122
|
+
console.log(` ${source_default.bold(n.type ?? "status_update")} ${source_default.gray(n.occurred_at ?? "")}`);
|
|
46123
|
+
console.log(source_default.gray(` ID: ${n.id}`));
|
|
46124
|
+
console.log(source_default.gray(` ${n.content.slice(0, 120)}${n.content.length > 120 ? "..." : ""}`));
|
|
46125
|
+
console.log();
|
|
46126
|
+
}
|
|
46127
|
+
} else {
|
|
46128
|
+
console.log(JSON.stringify(result, null, 2));
|
|
46129
|
+
}
|
|
46130
|
+
})
|
|
46131
|
+
);
|
|
46132
|
+
}
|
|
46133
|
+
function registerNoteCreate(program3) {
|
|
46134
|
+
program3.command("project:note:create").description(
|
|
46135
|
+
'Create a note\n Example: elevasis-sdk project:note:create --project <uuid> --content "Status update"'
|
|
46136
|
+
).requiredOption("--project <project-id>", "Project ID (UUID)").requiredOption("--content <content>", "Note content").option("--task <task-id>", "Attach to a task (UUID)").option("--milestone <milestone-id>", "Attach to a milestone (UUID)").option("--type <type>", "Note type: call_note | status_update | issue | blocker").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
46137
|
+
wrapAction(
|
|
46138
|
+
"project:note:create",
|
|
46139
|
+
async (options2) => {
|
|
46140
|
+
const body = {
|
|
46141
|
+
project_id: options2.project,
|
|
46142
|
+
content: options2.content
|
|
46143
|
+
};
|
|
46144
|
+
if (options2.task) body.task_id = options2.task;
|
|
46145
|
+
if (options2.milestone) body.milestone_id = options2.milestone;
|
|
46146
|
+
if (options2.type) body.type = options2.type;
|
|
46147
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
46148
|
+
const result = await apiPost("/api/external/notes", body, apiUrl);
|
|
46149
|
+
if (options2.pretty) {
|
|
46150
|
+
const n = result.note;
|
|
46151
|
+
console.log(source_default.green(`
|
|
46152
|
+
Note created`));
|
|
46153
|
+
console.log(source_default.gray(` ID: ${n.id}`));
|
|
46154
|
+
console.log(source_default.gray(` Type: ${n.type}`));
|
|
46155
|
+
console.log();
|
|
46156
|
+
} else {
|
|
46157
|
+
console.log(JSON.stringify(result, null, 2));
|
|
46158
|
+
}
|
|
46159
|
+
}
|
|
46160
|
+
)
|
|
46161
|
+
);
|
|
46162
|
+
}
|
|
46163
|
+
function registerNoteUpdate(program3) {
|
|
46164
|
+
program3.command("project:note:update <id>").description('Update a note\n Example: elevasis-sdk project:note:update <uuid> --content "Updated content"').requiredOption("--content <content>", "New note content").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
46165
|
+
wrapAction("project:note:update", async (id, options2) => {
|
|
46166
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
46167
|
+
const result = await apiPatch(`/api/external/notes/${id}`, { content: options2.content }, apiUrl);
|
|
46168
|
+
if (options2.pretty) {
|
|
46169
|
+
console.log(source_default.green(`
|
|
46170
|
+
Note ${id} updated.`));
|
|
46171
|
+
console.log();
|
|
46172
|
+
} else {
|
|
46173
|
+
console.log(JSON.stringify(result, null, 2));
|
|
46174
|
+
}
|
|
46175
|
+
})
|
|
46176
|
+
);
|
|
46177
|
+
}
|
|
46178
|
+
function registerNoteDelete(program3) {
|
|
46179
|
+
program3.command("project:note:delete <id>").description("Delete a note\n Example: elevasis-sdk project:note:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
|
|
46180
|
+
wrapAction("project:note:delete", async (id, options2) => {
|
|
46181
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
46182
|
+
const result = await apiDelete(`/api/external/notes/${id}`, apiUrl);
|
|
46183
|
+
if (options2.pretty) {
|
|
46184
|
+
console.log(source_default.green(`
|
|
46185
|
+
Note ${id} deleted.`));
|
|
46186
|
+
console.log();
|
|
46187
|
+
} else {
|
|
46188
|
+
console.log(JSON.stringify(result, null, 2));
|
|
46189
|
+
}
|
|
46190
|
+
})
|
|
46191
|
+
);
|
|
46192
|
+
}
|
|
46193
|
+
|
|
46194
|
+
// src/cli/commands/project/project.ts
|
|
46195
|
+
function registerProjectCommands(program3) {
|
|
46196
|
+
registerProjectList(program3);
|
|
46197
|
+
registerProjectGet(program3);
|
|
46198
|
+
registerProjectCreate(program3);
|
|
46199
|
+
registerProjectUpdate(program3);
|
|
46200
|
+
registerProjectDelete(program3);
|
|
46201
|
+
registerMilestoneList(program3);
|
|
46202
|
+
registerMilestoneCreate(program3);
|
|
46203
|
+
registerMilestoneUpdate(program3);
|
|
46204
|
+
registerMilestoneDelete(program3);
|
|
46205
|
+
registerTaskList(program3);
|
|
46206
|
+
registerTaskGet(program3);
|
|
46207
|
+
registerTaskCreate(program3);
|
|
46208
|
+
registerTaskUpdate(program3);
|
|
46209
|
+
registerTaskDelete(program3);
|
|
46210
|
+
registerTaskResume(program3);
|
|
46211
|
+
registerTaskSave(program3);
|
|
46212
|
+
registerNoteList(program3);
|
|
46213
|
+
registerNoteCreate(program3);
|
|
46214
|
+
registerNoteUpdate(program3);
|
|
46215
|
+
registerNoteDelete(program3);
|
|
46216
|
+
}
|
|
46217
|
+
|
|
48631
46218
|
// src/cli/index.ts
|
|
48632
|
-
(
|
|
46219
|
+
init_config();
|
|
46220
|
+
var envPath = findEnvFile();
|
|
46221
|
+
if (envPath) {
|
|
46222
|
+
(0, import_dotenv.config)({ path: envPath, override: true });
|
|
46223
|
+
} else if (!process.env.ELEVASIS_PLATFORM_KEY) {
|
|
46224
|
+
const cwd = process.cwd();
|
|
46225
|
+
console.error(source_default.yellow(`\u26A0 No .env file found (searched upward from ${cwd})`));
|
|
46226
|
+
console.error(source_default.gray(" Set ELEVASIS_PLATFORM_KEY in a .env at your project root."));
|
|
46227
|
+
}
|
|
48633
46228
|
var program2 = new Command();
|
|
48634
46229
|
program2.name("elevasis-sdk").description(
|
|
48635
46230
|
source_default.cyan("Elevasis SDK CLI") + `
|
|
@@ -48644,8 +46239,6 @@ Commands:
|
|
|
48644
46239
|
elevasis-sdk execution <resourceId> <id> Get execution details
|
|
48645
46240
|
elevasis-sdk deployments List deployments
|
|
48646
46241
|
elevasis-sdk rename <id> --to <newId> [--prod] Rename resource across platform tables
|
|
48647
|
-
elevasis-sdk update Update workspace scaffold to latest template
|
|
48648
|
-
elevasis-sdk init [directory] Scaffold a new workspace
|
|
48649
46242
|
|
|
48650
46243
|
Use "elevasis-sdk <command> --help" for more information about a command.`
|
|
48651
46244
|
).version(SDK_VERSION);
|
|
@@ -48657,11 +46250,10 @@ registerExecutionsCommand(program2);
|
|
|
48657
46250
|
registerExecutionCommand(program2);
|
|
48658
46251
|
registerDescribeCommand(program2);
|
|
48659
46252
|
registerDeploymentsCommand(program2);
|
|
48660
|
-
registerInitCommand(program2);
|
|
48661
|
-
registerUpdateCommand(program2);
|
|
48662
46253
|
registerCredsCommand(program2);
|
|
48663
46254
|
registerErrorCommand(program2);
|
|
48664
46255
|
registerRenameCommand(program2);
|
|
46256
|
+
registerProjectCommands(program2);
|
|
48665
46257
|
program2.parse();
|
|
48666
46258
|
/*! Bundled license information:
|
|
48667
46259
|
|