@elevasis/sdk 0.5.15 → 0.5.17
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 +183 -185
- package/dist/index.d.ts +26 -3
- package/dist/index.js +18 -5
- package/dist/templates.js +89 -109
- package/dist/worker/index.js +64 -31
- package/package.json +1 -1
- package/reference/framework/agent.mdx +7 -7
- package/reference/framework/index.mdx +10 -10
- package/reference/framework/project-structure.mdx +3 -3
- package/reference/getting-started.mdx +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -40221,7 +40221,7 @@ var GPT5ConfigSchema = external_exports.object({
|
|
|
40221
40221
|
apiKey: external_exports.string(),
|
|
40222
40222
|
temperature: external_exports.literal(1),
|
|
40223
40223
|
// Required to be exactly 1
|
|
40224
|
-
|
|
40224
|
+
maxOutputTokens: external_exports.number().min(4e3).optional(),
|
|
40225
40225
|
topP: external_exports.number().min(0).max(1).optional(),
|
|
40226
40226
|
modelOptions: GPT5OptionsSchema.optional()
|
|
40227
40227
|
});
|
|
@@ -40230,7 +40230,7 @@ var MockConfigSchema = external_exports.object({
|
|
|
40230
40230
|
provider: external_exports.enum(["mock"]),
|
|
40231
40231
|
apiKey: external_exports.string(),
|
|
40232
40232
|
temperature: external_exports.number().min(0).max(2).optional(),
|
|
40233
|
-
|
|
40233
|
+
maxOutputTokens: external_exports.number().min(500).optional(),
|
|
40234
40234
|
topP: external_exports.number().min(0).max(1).optional(),
|
|
40235
40235
|
modelOptions: external_exports.object({}).strict().optional()
|
|
40236
40236
|
// No options supported
|
|
@@ -40250,7 +40250,7 @@ var OpenRouterConfigSchema = external_exports.object({
|
|
|
40250
40250
|
provider: external_exports.literal("openrouter"),
|
|
40251
40251
|
apiKey: external_exports.string(),
|
|
40252
40252
|
temperature: external_exports.number().min(0).max(2).optional(),
|
|
40253
|
-
|
|
40253
|
+
maxOutputTokens: external_exports.number().min(500).optional(),
|
|
40254
40254
|
topP: external_exports.number().min(0).max(1).optional(),
|
|
40255
40255
|
modelOptions: OpenRouterOptionsSchema.optional()
|
|
40256
40256
|
});
|
|
@@ -40264,7 +40264,7 @@ var GoogleConfigSchema = external_exports.object({
|
|
|
40264
40264
|
apiKey: external_exports.string(),
|
|
40265
40265
|
temperature: external_exports.literal(1).optional(),
|
|
40266
40266
|
// Must be 1 for Gemini 3 (changing degrades performance)
|
|
40267
|
-
|
|
40267
|
+
maxOutputTokens: external_exports.number().min(500).optional(),
|
|
40268
40268
|
topP: external_exports.number().min(0).max(1).optional(),
|
|
40269
40269
|
modelOptions: GoogleOptionsSchema.optional()
|
|
40270
40270
|
});
|
|
@@ -40274,7 +40274,7 @@ var AnthropicConfigSchema = external_exports.object({
|
|
|
40274
40274
|
provider: external_exports.literal("anthropic"),
|
|
40275
40275
|
apiKey: external_exports.string(),
|
|
40276
40276
|
temperature: external_exports.number().min(0).max(1).optional(),
|
|
40277
|
-
|
|
40277
|
+
maxOutputTokens: external_exports.number().min(1e3).optional(),
|
|
40278
40278
|
// Anthropic requires max_tokens
|
|
40279
40279
|
topP: external_exports.number().min(0).max(1).optional(),
|
|
40280
40280
|
modelOptions: AnthropicOptionsSchema.optional()
|
|
@@ -43228,6 +43228,17 @@ function buildEdges(resources) {
|
|
|
43228
43228
|
}
|
|
43229
43229
|
|
|
43230
43230
|
// ../core/src/platform/registry/resource-registry.ts
|
|
43231
|
+
function filterArchived(org) {
|
|
43232
|
+
return {
|
|
43233
|
+
...org,
|
|
43234
|
+
workflows: org.workflows?.filter((w) => !w.config.archived),
|
|
43235
|
+
agents: org.agents?.filter((a) => !a.config.archived),
|
|
43236
|
+
triggers: org.triggers?.filter((t) => !t.archived),
|
|
43237
|
+
integrations: org.integrations?.filter((i) => !i.archived),
|
|
43238
|
+
externalResources: org.externalResources?.filter((e) => !e.archived),
|
|
43239
|
+
humanCheckpoints: org.humanCheckpoints?.filter((h) => !h.archived)
|
|
43240
|
+
};
|
|
43241
|
+
}
|
|
43231
43242
|
var ResourceRegistry = class {
|
|
43232
43243
|
constructor(registry2) {
|
|
43233
43244
|
this.registry = registry2;
|
|
@@ -43359,6 +43370,7 @@ var ResourceRegistry = class {
|
|
|
43359
43370
|
* @throws Error if incoming deployment contains duplicate resourceIds
|
|
43360
43371
|
*/
|
|
43361
43372
|
registerOrganization(orgName, org, remote) {
|
|
43373
|
+
org = filterArchived(org);
|
|
43362
43374
|
const incomingWorkflowIds = (org.workflows ?? []).map((w) => w.config.resourceId);
|
|
43363
43375
|
const incomingAgentIds = (org.agents ?? []).map((a) => a.config.resourceId);
|
|
43364
43376
|
const incomingIds = [...incomingWorkflowIds, ...incomingAgentIds];
|
|
@@ -43420,6 +43432,7 @@ var ResourceRegistry = class {
|
|
|
43420
43432
|
* @param org - Resource definitions with real handlers (not stubs)
|
|
43421
43433
|
*/
|
|
43422
43434
|
registerStaticResources(orgName, org) {
|
|
43435
|
+
org = filterArchived(org);
|
|
43423
43436
|
const incomingWorkflowIds = (org.workflows ?? []).map((w) => w.config.resourceId);
|
|
43424
43437
|
const incomingAgentIds = (org.agents ?? []).map((a) => a.config.resourceId);
|
|
43425
43438
|
const incomingIds = [...incomingWorkflowIds, ...incomingAgentIds];
|
|
@@ -43851,7 +43864,7 @@ async function apiDelete(endpoint, apiUrl = resolveApiUrl()) {
|
|
|
43851
43864
|
// package.json
|
|
43852
43865
|
var package_default = {
|
|
43853
43866
|
name: "@elevasis/sdk",
|
|
43854
|
-
version: "0.5.
|
|
43867
|
+
version: "0.5.17",
|
|
43855
43868
|
description: "SDK for building Elevasis organization resources",
|
|
43856
43869
|
type: "module",
|
|
43857
43870
|
bin: {
|
|
@@ -44422,6 +44435,8 @@ function registerDeployCommand(program3) {
|
|
|
44422
44435
|
}
|
|
44423
44436
|
const validateSpinner = ora("Validating...").start();
|
|
44424
44437
|
let org;
|
|
44438
|
+
let activeWorkflows = [];
|
|
44439
|
+
let activeAgents = [];
|
|
44425
44440
|
try {
|
|
44426
44441
|
const jiti = (0, import_jiti.createJiti)(import_meta.url);
|
|
44427
44442
|
const entryModule = await jiti.import((0, import_path.resolve)(entryPath));
|
|
@@ -44432,20 +44447,24 @@ function registerDeployCommand(program3) {
|
|
|
44432
44447
|
throw new Error("Invalid entry: no default export found");
|
|
44433
44448
|
}
|
|
44434
44449
|
new ResourceRegistry({ [orgName]: org });
|
|
44435
|
-
|
|
44436
|
-
|
|
44437
|
-
const
|
|
44450
|
+
activeWorkflows = (org.workflows ?? []).filter((w) => !w.config.archived);
|
|
44451
|
+
activeAgents = (org.agents ?? []).filter((a) => !a.config.archived);
|
|
44452
|
+
const archivedCount = (org.workflows?.length ?? 0) + (org.agents?.length ?? 0) - activeWorkflows.length - activeAgents.length;
|
|
44453
|
+
const totalCount = activeWorkflows.length + activeAgents.length;
|
|
44438
44454
|
validateSpinner.succeed(
|
|
44439
44455
|
source_default.green("Validating...") + source_default.white(" done") + source_default.gray(` (${totalCount} resource${totalCount !== 1 ? "s" : ""}, 0 errors)`)
|
|
44440
44456
|
);
|
|
44457
|
+
if (archivedCount > 0) {
|
|
44458
|
+
console.log(source_default.gray(` Skipping ${archivedCount} archived resource${archivedCount !== 1 ? "s" : ""}`));
|
|
44459
|
+
}
|
|
44441
44460
|
console.log("");
|
|
44442
44461
|
console.log(source_default.gray(` Org: ${orgName}`));
|
|
44443
44462
|
console.log(source_default.gray(` Target: ${apiUrl} (${env2})`));
|
|
44444
44463
|
console.log("");
|
|
44445
|
-
for (const w of
|
|
44464
|
+
for (const w of activeWorkflows) {
|
|
44446
44465
|
console.log(source_default.gray(` workflow ${source_default.white(w.config.resourceId)} v${w.config.version}`));
|
|
44447
44466
|
}
|
|
44448
|
-
for (const a of
|
|
44467
|
+
for (const a of activeAgents) {
|
|
44449
44468
|
console.log(source_default.gray(` agent ${source_default.white(a.config.resourceId)} v${a.config.version}`));
|
|
44450
44469
|
}
|
|
44451
44470
|
console.log("");
|
|
@@ -44489,7 +44508,7 @@ function registerDeployCommand(program3) {
|
|
|
44489
44508
|
);
|
|
44490
44509
|
}
|
|
44491
44510
|
const schemaWarnings = [];
|
|
44492
|
-
const workflows =
|
|
44511
|
+
const workflows = activeWorkflows.map((w) => {
|
|
44493
44512
|
const meta = {
|
|
44494
44513
|
resourceId: w.config.resourceId,
|
|
44495
44514
|
name: w.config.name,
|
|
@@ -44514,7 +44533,7 @@ function registerDeployCommand(program3) {
|
|
|
44514
44533
|
}
|
|
44515
44534
|
return meta;
|
|
44516
44535
|
});
|
|
44517
|
-
const agents =
|
|
44536
|
+
const agents = activeAgents.map((a) => {
|
|
44518
44537
|
const meta = {
|
|
44519
44538
|
resourceId: a.config.resourceId,
|
|
44520
44539
|
name: a.config.name,
|
|
@@ -44615,7 +44634,7 @@ startWorker(org)
|
|
|
44615
44634
|
}
|
|
44616
44635
|
const result = await response.json();
|
|
44617
44636
|
uploadSpinner.succeed(source_default.green("Uploading...") + source_default.white(" done"));
|
|
44618
|
-
const totalResources =
|
|
44637
|
+
const totalResources = activeWorkflows.length + activeAgents.length;
|
|
44619
44638
|
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
|
|
44620
44639
|
if (result.status === "active") {
|
|
44621
44640
|
console.log("");
|
|
@@ -44753,6 +44772,7 @@ function registerCheckCommand(program3) {
|
|
|
44753
44772
|
}
|
|
44754
44773
|
|
|
44755
44774
|
// src/cli/commands/exec.ts
|
|
44775
|
+
var import_node_fs = require("node:fs");
|
|
44756
44776
|
var POLL_INTERVAL_MS = 3e3;
|
|
44757
44777
|
async function pollForCompletion(resourceId, executionId, apiUrl) {
|
|
44758
44778
|
const pollSpinner = ora("Waiting for completion...").start();
|
|
@@ -44771,10 +44791,7 @@ async function pollForCompletion(resourceId, executionId, apiUrl) {
|
|
|
44771
44791
|
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
44772
44792
|
pollSpinner.text = `Waiting for completion... (${elapsed}s)`;
|
|
44773
44793
|
try {
|
|
44774
|
-
const detail = await apiGet(
|
|
44775
|
-
`/api/external/executions/${resourceId}/${executionId}`,
|
|
44776
|
-
apiUrl
|
|
44777
|
-
);
|
|
44794
|
+
const detail = await apiGet(`/api/external/executions/${resourceId}/${executionId}`, apiUrl);
|
|
44778
44795
|
if (detail.status === "completed" || detail.status === "failed") {
|
|
44779
44796
|
process.removeListener("SIGINT", cleanup);
|
|
44780
44797
|
if (detail.status === "completed") {
|
|
@@ -44807,70 +44824,71 @@ async function pollForCompletion(resourceId, executionId, apiUrl) {
|
|
|
44807
44824
|
}
|
|
44808
44825
|
function registerExecCommand(program3) {
|
|
44809
44826
|
program3.command("exec <resourceId>").description(`Execute a deployed resource
|
|
44810
|
-
Example: elevasis-sdk exec my-workflow -i '{"key":"value"}'`).option("-i, --input <json>", "Input data as JSON string").option("--async", "Execute asynchronously with polling").option("--api-url <url>", "API URL").action(
|
|
44811
|
-
|
|
44812
|
-
|
|
44813
|
-
|
|
44814
|
-
|
|
44815
|
-
|
|
44816
|
-
|
|
44817
|
-
|
|
44818
|
-
|
|
44819
|
-
|
|
44820
|
-
|
|
44821
|
-
console.log(source_default.gray(" Execution ID:"), source_default.cyan(asyncResult.executionId));
|
|
44822
|
-
console.log("");
|
|
44823
|
-
await pollForCompletion(resourceId, asyncResult.executionId, apiUrl);
|
|
44824
|
-
return;
|
|
44825
|
-
}
|
|
44826
|
-
const spinner = ora(`Executing ${resourceId}...`).start();
|
|
44827
|
-
try {
|
|
44828
|
-
const result = await apiPost(
|
|
44829
|
-
"/api/external/execute",
|
|
44830
|
-
{ resourceId, input },
|
|
44831
|
-
apiUrl
|
|
44832
|
-
);
|
|
44833
|
-
if (result.success) {
|
|
44834
|
-
spinner.succeed(source_default.green("Execution complete"));
|
|
44835
|
-
console.log(source_default.gray(" Execution ID:"), source_default.cyan(result.executionId));
|
|
44836
|
-
console.log("");
|
|
44837
|
-
console.log(source_default.green(" Output:"));
|
|
44838
|
-
console.log(JSON.stringify(result.data, null, 2));
|
|
44839
|
-
} else {
|
|
44840
|
-
spinner.fail(source_default.red("Execution failed"));
|
|
44841
|
-
console.log(source_default.gray(" Execution ID:"), source_default.cyan(result.executionId));
|
|
44842
|
-
}
|
|
44843
|
-
} catch (error46) {
|
|
44844
|
-
const message = error46 instanceof Error ? error46.message : String(error46);
|
|
44845
|
-
const isConnectionFailure = message.includes("fetch failed") || message.includes("ECONNRESET") || message.includes("socket hang up") || message.includes("network");
|
|
44846
|
-
if (isConnectionFailure) {
|
|
44847
|
-
spinner.warn("Connection lost -- execution may still be running");
|
|
44848
|
-
console.log();
|
|
44849
|
-
try {
|
|
44850
|
-
const recoverSpinner = ora("Recovering execution...").start();
|
|
44851
|
-
const listResult = await apiGet(
|
|
44852
|
-
`/api/external/executions/${resourceId}?limit=1`,
|
|
44827
|
+
Example: elevasis-sdk exec my-workflow -i '{"key":"value"}'`).option("-i, --input <json>", "Input data as JSON string").option("-f, --input-file <path>", "Read input from a JSON file (avoids shell escaping issues)").option("--async", "Execute asynchronously with polling").option("--api-url <url>", "API URL").action(
|
|
44828
|
+
wrapAction(
|
|
44829
|
+
"exec",
|
|
44830
|
+
async (resourceId, options2) => {
|
|
44831
|
+
const input = options2.inputFile ? JSON.parse((0, import_node_fs.readFileSync)(options2.inputFile, "utf8")) : options2.input ? JSON.parse(options2.input) : {};
|
|
44832
|
+
const apiUrl = resolveApiUrl(options2.apiUrl);
|
|
44833
|
+
if (options2.async) {
|
|
44834
|
+
const asyncSpinner = ora(`Starting async execution of ${resourceId}...`).start();
|
|
44835
|
+
const asyncResult = await apiPost(
|
|
44836
|
+
"/api/external/execute-async",
|
|
44837
|
+
{ resourceId, input },
|
|
44853
44838
|
apiUrl
|
|
44854
44839
|
);
|
|
44855
|
-
|
|
44856
|
-
|
|
44857
|
-
|
|
44858
|
-
|
|
44859
|
-
|
|
44840
|
+
asyncSpinner.succeed(source_default.green("Execution started"));
|
|
44841
|
+
console.log(source_default.gray(" Execution ID:"), source_default.cyan(asyncResult.executionId));
|
|
44842
|
+
console.log("");
|
|
44843
|
+
await pollForCompletion(resourceId, asyncResult.executionId, apiUrl);
|
|
44844
|
+
return;
|
|
44845
|
+
}
|
|
44846
|
+
const spinner = ora(`Executing ${resourceId}...`).start();
|
|
44847
|
+
try {
|
|
44848
|
+
const result = await apiPost("/api/external/execute", { resourceId, input }, apiUrl);
|
|
44849
|
+
if (result.success) {
|
|
44850
|
+
spinner.succeed(source_default.green("Execution complete"));
|
|
44851
|
+
console.log(source_default.gray(" Execution ID:"), source_default.cyan(result.executionId));
|
|
44852
|
+
console.log("");
|
|
44853
|
+
console.log(source_default.green(" Output:"));
|
|
44854
|
+
console.log(JSON.stringify(result.data, null, 2));
|
|
44860
44855
|
} else {
|
|
44861
|
-
|
|
44862
|
-
console.log(source_default.
|
|
44856
|
+
spinner.fail(source_default.red("Execution failed"));
|
|
44857
|
+
console.log(source_default.gray(" Execution ID:"), source_default.cyan(result.executionId));
|
|
44863
44858
|
}
|
|
44864
|
-
} catch {
|
|
44865
|
-
|
|
44866
|
-
|
|
44859
|
+
} catch (error46) {
|
|
44860
|
+
const message = error46 instanceof Error ? error46.message : String(error46);
|
|
44861
|
+
const isConnectionFailure = message.includes("fetch failed") || message.includes("ECONNRESET") || message.includes("socket hang up") || message.includes("network");
|
|
44862
|
+
if (isConnectionFailure) {
|
|
44863
|
+
spinner.warn("Connection lost -- execution may still be running");
|
|
44864
|
+
console.log();
|
|
44865
|
+
try {
|
|
44866
|
+
const recoverSpinner = ora("Recovering execution...").start();
|
|
44867
|
+
const listResult = await apiGet(
|
|
44868
|
+
`/api/external/executions/${resourceId}?limit=1`,
|
|
44869
|
+
apiUrl
|
|
44870
|
+
);
|
|
44871
|
+
const running = listResult.executions.find((e) => e.status === "running");
|
|
44872
|
+
if (running) {
|
|
44873
|
+
recoverSpinner.succeed(`Found running execution: ${running.id}`);
|
|
44874
|
+
console.log();
|
|
44875
|
+
await pollForCompletion(resourceId, running.id, apiUrl);
|
|
44876
|
+
} else {
|
|
44877
|
+
recoverSpinner.info("No running execution found -- it may have already completed");
|
|
44878
|
+
console.log(source_default.dim(" Check status manually or re-run with --async"));
|
|
44879
|
+
}
|
|
44880
|
+
} catch {
|
|
44881
|
+
console.log(source_default.yellow("Could not recover. The execution may still be running on the server."));
|
|
44882
|
+
console.log(source_default.dim(" Check status manually or re-run with --async"));
|
|
44883
|
+
}
|
|
44884
|
+
process.exit(0);
|
|
44885
|
+
}
|
|
44886
|
+
spinner.fail(source_default.red("Execution failed"));
|
|
44887
|
+
throw error46;
|
|
44867
44888
|
}
|
|
44868
|
-
process.exit(0);
|
|
44869
44889
|
}
|
|
44870
|
-
|
|
44871
|
-
|
|
44872
|
-
}
|
|
44873
|
-
}));
|
|
44890
|
+
)
|
|
44891
|
+
);
|
|
44874
44892
|
}
|
|
44875
44893
|
|
|
44876
44894
|
// src/cli/commands/resources.ts
|
|
@@ -45180,7 +45198,7 @@ var import_path3 = require("path");
|
|
|
45180
45198
|
var import_promises2 = require("fs/promises");
|
|
45181
45199
|
|
|
45182
45200
|
// src/cli/commands/templates/core/workspace.ts
|
|
45183
|
-
var TEMPLATE_VERSION =
|
|
45201
|
+
var TEMPLATE_VERSION = 29;
|
|
45184
45202
|
function configTemplate() {
|
|
45185
45203
|
return `import type { ElevasConfig } from '@elevasis/sdk'
|
|
45186
45204
|
|
|
@@ -45410,8 +45428,8 @@ process.stdin.on('end', () => {
|
|
|
45410
45428
|
function claudeSdkBoundaryHookTemplate() {
|
|
45411
45429
|
return String.raw`#!/usr/bin/env node
|
|
45412
45430
|
// enforce-sdk-boundary.mjs
|
|
45413
|
-
// Blocks
|
|
45414
|
-
//
|
|
45431
|
+
// Blocks file modifications (Write, Edit, MultiEdit, destructive Bash) outside the project root.
|
|
45432
|
+
// Git, gh, and other CLI tools are NOT blocked -- the agent can use them freely.
|
|
45415
45433
|
|
|
45416
45434
|
import { resolve, normalize } from "node:path";
|
|
45417
45435
|
import { appendFileSync, mkdirSync } from "node:fs";
|
|
@@ -45456,44 +45474,6 @@ try {
|
|
|
45456
45474
|
if (input.tool_name === "Bash") {
|
|
45457
45475
|
const cmd = input.tool_input?.command ?? "";
|
|
45458
45476
|
|
|
45459
|
-
// GitHub CLI -- blocked (affects shared remote state, user-initiated only)
|
|
45460
|
-
if (/\bgh\b/.test(cmd)) {
|
|
45461
|
-
deny(
|
|
45462
|
-
"BLOCKED: GitHub CLI (gh) command detected.\n" +
|
|
45463
|
-
"WHY: GitHub CLI operations affect shared remote state (PRs, issues, releases). These must be user-initiated.\n" +
|
|
45464
|
-
"INSTEAD: Ask the user to run this gh command manually."
|
|
45465
|
-
);
|
|
45466
|
-
process.exit(0);
|
|
45467
|
-
}
|
|
45468
|
-
|
|
45469
|
-
// Destructive git -- blocked
|
|
45470
|
-
if (/(?<!-)\bgit\s+reset\b/.test(cmd) && /--hard/.test(cmd)) {
|
|
45471
|
-
deny(
|
|
45472
|
-
"BLOCKED: git reset --hard detected.\n" +
|
|
45473
|
-
"WHY: Hard resets destroy uncommitted work and cannot be undone. This must be user-initiated.\n" +
|
|
45474
|
-
"INSTEAD: Ask the user to run this git command manually."
|
|
45475
|
-
);
|
|
45476
|
-
process.exit(0);
|
|
45477
|
-
}
|
|
45478
|
-
|
|
45479
|
-
if (/(?<!-)\bgit\s+clean\b/.test(cmd) && /-[a-zA-Z]*f/.test(cmd)) {
|
|
45480
|
-
deny(
|
|
45481
|
-
"BLOCKED: git clean -f detected.\n" +
|
|
45482
|
-
"WHY: Force-cleaning the working tree permanently removes untracked files. This must be user-initiated.\n" +
|
|
45483
|
-
"INSTEAD: Ask the user to run this git command manually."
|
|
45484
|
-
);
|
|
45485
|
-
process.exit(0);
|
|
45486
|
-
}
|
|
45487
|
-
|
|
45488
|
-
if (/(?<!-)\bgit\s+(rebase|merge)\b/.test(cmd)) {
|
|
45489
|
-
deny(
|
|
45490
|
-
"BLOCKED: git rebase/merge detected.\n" +
|
|
45491
|
-
"WHY: Rebase and merge rewrite history or combine branches in ways that require user judgment.\n" +
|
|
45492
|
-
"INSTEAD: Ask the user to run this git command manually."
|
|
45493
|
-
);
|
|
45494
|
-
process.exit(0);
|
|
45495
|
-
}
|
|
45496
|
-
|
|
45497
45477
|
// Path-scoped blocks -- destructive commands or redirects outside project root
|
|
45498
45478
|
const winPaths = cmd.match(/(?<![A-Za-z])[A-Za-z]:[/\\][^\s"'|;&)]+/g) || [];
|
|
45499
45479
|
const unixPaths = cmd.match(/(?<=\s|^|"|')\/[^\s"'|;&)]+/g) || [];
|
|
@@ -45676,7 +45656,7 @@ For detailed per-dimension adaptation rules, read
|
|
|
45676
45656
|
| --- | --- |
|
|
45677
45657
|
| \`/meta\` | Project lifecycle: init, status, fix, deploy, health |
|
|
45678
45658
|
| \`/docs\` | Browse, create, and verify permanent documentation |
|
|
45679
|
-
| \`/work\` | Task tracking: create, save, resume
|
|
45659
|
+
| \`/work\` | Task tracking: auto-detects intent (create, save, resume); suggests complete |
|
|
45680
45660
|
| \`/tutorial\` | Progressive learning path (21 items across 4 sections) |
|
|
45681
45661
|
|
|
45682
45662
|
## Skills
|
|
@@ -45908,43 +45888,46 @@ Observation focus: full lifecycle coverage, pipeline internals.
|
|
|
45908
45888
|
**Item 4: /work and /docs**
|
|
45909
45889
|
|
|
45910
45890
|
When automation is none:
|
|
45911
|
-
"You can ask the assistant to track work across conversations.
|
|
45912
|
-
|
|
45913
|
-
you
|
|
45914
|
-
|
|
45915
|
-
|
|
45916
|
-
|
|
45917
|
-
|
|
45891
|
+
"You can ask the assistant to track work across conversations. Just say /work and tell it
|
|
45892
|
+
what you're working on -- it figures out the rest. It'll save your progress automatically,
|
|
45893
|
+
and next session you just say /work to pick up where you left off." Walk through the
|
|
45894
|
+
concept without deep command details. Then introduce /docs:
|
|
45895
|
+
"When a task is done, the assistant will ask if you want to finalize it -- that moves it
|
|
45896
|
+
to docs/ permanently. /docs helps you find and read what's there -- like a notebook for
|
|
45897
|
+
your project." Run /docs (no args) to show the docs/ overview together.
|
|
45898
|
+
Verify: Run \`/work\` and describe "practice task", see it created automatically.
|
|
45918
45899
|
Then run /docs to see the docs/ structure.
|
|
45919
45900
|
Observation focus: persistence concept, cross-session continuity, docs as permanent notes.
|
|
45920
45901
|
|
|
45921
45902
|
When automation is low-code:
|
|
45922
|
-
Show /work
|
|
45923
|
-
|
|
45924
|
-
|
|
45903
|
+
Show /work as intent-driven: the agent detects whether to create, resume, or save based
|
|
45904
|
+
on context. Create happens when you describe new work, resume when you pick an existing
|
|
45905
|
+
task, save happens automatically when progress is made. Complete is the only action that
|
|
45906
|
+
asks permission first.
|
|
45925
45907
|
Then introduce /docs: "/docs is for permanent knowledge -- things that don't expire. Use
|
|
45926
45908
|
/docs create to document a workflow or integration. Use /docs verify to check if your
|
|
45927
45909
|
docs match the current code." Explain the boundary: /work manages in-progress/, /docs
|
|
45928
45910
|
manages permanent docs/.
|
|
45929
|
-
Verify:
|
|
45930
|
-
|
|
45931
|
-
Observation focus: task tracking
|
|
45911
|
+
Verify: Run \`/work\` and describe "practice task", see auto-create. Make some changes,
|
|
45912
|
+
then notice auto-save. Then run /docs to browse docs/.
|
|
45913
|
+
Observation focus: intent-driven task tracking, /work vs /docs separation.
|
|
45932
45914
|
|
|
45933
45915
|
When automation is custom:
|
|
45934
45916
|
Read \`.claude/commands/work.md\`. Full /work coverage:
|
|
45935
|
-
|
|
45936
|
-
|
|
45937
|
-
|
|
45917
|
+
Intent detection table (list, create, resume, save auto-invoked; complete always suggests).
|
|
45918
|
+
Task doc anatomy: kebab-case filename, frontmatter with status, Objective/Plan/Progress/
|
|
45919
|
+
Resume Context sections. Auto-save behavior: triggers on heavy context, wrap-up signals,
|
|
45920
|
+
2+ steps completed. Resolution order for resume: number, keyword match, single in-progress.
|
|
45938
45921
|
Then read \`.claude/commands/docs.md\`. Cover /docs operations:
|
|
45939
45922
|
/docs (default): browse permanent docs/, categorized with read-only auto-generated files
|
|
45940
45923
|
separate; /docs create: interview-driven, resource-aware doc creation from src/ code
|
|
45941
45924
|
analysis; /docs verify: cross-references resource IDs, schema fields, platform tools in
|
|
45942
45925
|
docs against src/ -- standalone analog of /meta fix step 5.
|
|
45943
|
-
Explain the relationship: /work owns docs/in-progress/ (task lifecycle),
|
|
45926
|
+
Explain the relationship: /work owns docs/in-progress/ (task lifecycle), completing a task
|
|
45944
45927
|
moves docs to permanent location, /docs browses and verifies what's there.
|
|
45945
|
-
Verify: Create a task
|
|
45946
|
-
to see it in the permanent docs/ listing.
|
|
45947
|
-
Observation focus:
|
|
45928
|
+
Verify: Create a task via /work, make progress, observe auto-save, then run /work complete
|
|
45929
|
+
to move it. Run /docs to see it in the permanent docs/ listing.
|
|
45930
|
+
Observation focus: intent detection, auto-save behavior, /work-to-/docs handoff, docs verification.
|
|
45948
45931
|
|
|
45949
45932
|
**Item 5: Your First Custom Workflow**
|
|
45950
45933
|
|
|
@@ -46478,6 +46461,8 @@ function claudeWorkCommandTemplate() {
|
|
|
46478
46461
|
|
|
46479
46462
|
You are a task tracking assistant for this Elevasis workspace. \`/work\` is the primary command for managing all work and projects.
|
|
46480
46463
|
|
|
46464
|
+
Your job is to **intelligently manage tasks without requiring the user to know subcommands**. Detect what the user needs from context and act accordingly.
|
|
46465
|
+
|
|
46481
46466
|
## Context
|
|
46482
46467
|
|
|
46483
46468
|
Read \`docs/priorities.mdx\` if it exists for current priorities.
|
|
@@ -46497,9 +46482,25 @@ When scanning, treat \`index.mdx\` as the primary task doc for a directory.
|
|
|
46497
46482
|
|
|
46498
46483
|
Enforce exactly three values in frontmatter: \`planned\`, \`in-progress\`, \`complete\`.
|
|
46499
46484
|
|
|
46500
|
-
##
|
|
46485
|
+
## Intent Detection
|
|
46486
|
+
|
|
46487
|
+
When \`/work\` is invoked (with or without arguments), detect intent from context:
|
|
46501
46488
|
|
|
46502
|
-
|
|
46489
|
+
| Signal | Action |
|
|
46490
|
+
|--------|--------|
|
|
46491
|
+
| No arguments, no active conversation context | **List** tasks, then let user pick |
|
|
46492
|
+
| User picks a number or names a task | **Resume** that task automatically |
|
|
46493
|
+
| User describes new work (not matching existing tasks) | **Create** a task doc automatically |
|
|
46494
|
+
| \`/work\` with a description that matches no existing task | **Create** automatically |
|
|
46495
|
+
| \`/work\` with a keyword/name matching an existing task | **Resume** automatically |
|
|
46496
|
+
| Conversation is getting heavy, user wrapping up, or 2+ steps completed | **Save** automatically |
|
|
46497
|
+
| All plan steps are COMPLETE | **Suggest** \`/work complete\` (never auto-invoke) |
|
|
46498
|
+
|
|
46499
|
+
**Key principle:** Create, save, and resume are auto-invoked. Complete always asks permission first.
|
|
46500
|
+
|
|
46501
|
+
## Behaviors
|
|
46502
|
+
|
|
46503
|
+
### List and Pick (default when no context)
|
|
46503
46504
|
|
|
46504
46505
|
1. Scan \`docs/in-progress/\` recursively for \`.mdx\` files with \`status\` frontmatter
|
|
46505
46506
|
2. For directories, read \`index.mdx\` as the primary task doc
|
|
@@ -46518,30 +46519,25 @@ Active Tasks
|
|
|
46518
46519
|
3. [complete] CRM Integration
|
|
46519
46520
|
Completed: 2026-03-03
|
|
46520
46521
|
|
|
46521
|
-
Pick a task by number or name
|
|
46522
|
-
- "create" to start new work
|
|
46523
|
-
- "complete <name>" to finish a task
|
|
46522
|
+
Pick a task by number or name, or describe new work to start.
|
|
46524
46523
|
\`\`\`
|
|
46525
46524
|
|
|
46526
46525
|
4. Cross-reference with \`docs/priorities.mdx\` if it exists
|
|
46527
|
-
5. When the user picks a number or describes a task
|
|
46528
|
-
6. If no tasks found,
|
|
46529
|
-
|
|
46530
|
-
### \`create [description]\`
|
|
46526
|
+
5. When the user picks a number or describes a task, auto-invoke the appropriate flow (resume or create)
|
|
46527
|
+
6. If no tasks found, ask: "What are you trying to accomplish?"
|
|
46531
46528
|
|
|
46532
|
-
|
|
46529
|
+
### Create (auto-invoked when new work detected)
|
|
46533
46530
|
|
|
46534
|
-
1. If
|
|
46535
|
-
2.
|
|
46531
|
+
1. If the user's intent is clear, skip the interview and create directly
|
|
46532
|
+
2. If ambiguous, ask 1-2 focused questions:
|
|
46536
46533
|
- "What does success look like?" (acceptance criteria)
|
|
46537
|
-
- "
|
|
46538
|
-
|
|
46539
|
-
|
|
46540
|
-
- Scan \`docs/in-progress/\` for existing directories related to the topic
|
|
46534
|
+
- "Do we need to investigate anything first, or is the path clear?"
|
|
46535
|
+
3. Scan \`docs/in-progress/\` for existing directories related to the topic
|
|
46536
|
+
4. Determine directory placement:
|
|
46541
46537
|
- If related to existing directory, create as a file within it
|
|
46542
46538
|
- If new concept that may grow, create \`docs/in-progress/<slug>/index.mdx\`
|
|
46543
46539
|
- If small/standalone, create \`docs/in-progress/<slug>.mdx\`
|
|
46544
|
-
|
|
46540
|
+
5. Create the doc with \`status: planned\` and structured sections:
|
|
46545
46541
|
|
|
46546
46542
|
\`\`\`yaml
|
|
46547
46543
|
---
|
|
@@ -46553,15 +46549,20 @@ status: planned
|
|
|
46553
46549
|
|
|
46554
46550
|
Sections: Objective (what and why), Plan (numbered steps), Progress (per-step tracking with PENDING markers), Resume Context (current state, key docs, "To continue" prompt).
|
|
46555
46551
|
|
|
46556
|
-
|
|
46557
|
-
|
|
46552
|
+
6. Update \`docs/priorities.mdx\` if it exists
|
|
46553
|
+
7. Report what was created with location and step count
|
|
46558
46554
|
|
|
46559
|
-
###
|
|
46555
|
+
### Save (auto-invoked when progress detected)
|
|
46560
46556
|
|
|
46561
|
-
|
|
46557
|
+
Auto-save triggers (do NOT ask, just save):
|
|
46558
|
+
- The conversation context is getting heavy (many tool calls, large file reads)
|
|
46559
|
+
- The user appears to be wrapping up (thanks, goodbye, switching topics)
|
|
46560
|
+
- Significant progress has been made (2+ steps completed without saving)
|
|
46561
|
+
- Before a context reset
|
|
46562
46562
|
|
|
46563
|
-
|
|
46564
|
-
|
|
46563
|
+
Save flow:
|
|
46564
|
+
1. Identify the current task from conversation context
|
|
46565
|
+
2. If not working on a tracked task, offer to create a new one
|
|
46565
46566
|
3. Update Progress section:
|
|
46566
46567
|
- Mark completed steps as \`COMPLETE\` with: what was done, key decisions, files changed
|
|
46567
46568
|
- Mark current step as \`IN PROGRESS\` with current state
|
|
@@ -46571,15 +46572,13 @@ Update the current task doc's Progress and Resume Context:
|
|
|
46571
46572
|
- Files Modified: table of file paths and descriptions of changes
|
|
46572
46573
|
- Key docs to read on resume: file paths with why they matter
|
|
46573
46574
|
- To continue: copy-pasteable prompt for the next session
|
|
46574
|
-
5. Set \`status\` appropriately (\`in-progress\` if ongoing
|
|
46575
|
-
6.
|
|
46575
|
+
5. Set \`status\` appropriately (\`in-progress\` if ongoing)
|
|
46576
|
+
6. Briefly confirm: "Progress saved to {path}."
|
|
46576
46577
|
|
|
46577
|
-
###
|
|
46578
|
-
|
|
46579
|
-
Resume in-progress work. Designed for non-technical users who may not know file paths.
|
|
46578
|
+
### Resume (auto-invoked when existing task detected)
|
|
46580
46579
|
|
|
46581
46580
|
**Resolution order:**
|
|
46582
|
-
1. If a number is given
|
|
46581
|
+
1. If a number is given, map to the numbered list from the task list
|
|
46583
46582
|
2. If a name/keyword is given, substring match against task titles and filenames in \`docs/in-progress/\`
|
|
46584
46583
|
3. If no argument, scan for \`status: in-progress\` docs -- if one found, use it; if multiple, list and ask
|
|
46585
46584
|
4. If multiple matches, list them and ask which to resume
|
|
@@ -46605,35 +46604,32 @@ Key context loaded:
|
|
|
46605
46604
|
Ready to continue. {Copy of "To continue" prompt}
|
|
46606
46605
|
\`\`\`
|
|
46607
46606
|
|
|
46608
|
-
###
|
|
46607
|
+
### Complete (NEVER auto-invoked -- always suggest)
|
|
46608
|
+
|
|
46609
|
+
When all plan steps are COMPLETE, suggest: "All steps for '{task}' look done. Want me to finalize it?"
|
|
46609
46610
|
|
|
46610
|
-
|
|
46611
|
+
Only proceed after explicit user confirmation. Then:
|
|
46611
46612
|
|
|
46612
|
-
1.
|
|
46613
|
-
2. **
|
|
46614
|
-
3. **Clean up the doc:**
|
|
46613
|
+
1. **Validate readiness:** Check that all plan steps are marked COMPLETE. If not, warn and ask for confirmation.
|
|
46614
|
+
2. **Clean up the doc:**
|
|
46615
46615
|
- Strip \`## Resume Context\` section entirely (header through next \`##\` or EOF)
|
|
46616
46616
|
- Strip progress markers: \`COMPLETE\`, \`IN PROGRESS\`, \`PENDING\` from step headings
|
|
46617
46617
|
- Remove steps still marked PENDING entirely (header + body) -- they were never done
|
|
46618
46618
|
- Remove \`status\` from frontmatter (keep \`title\` and \`description\`)
|
|
46619
46619
|
- Target 200-400 lines; flag if result exceeds 500 lines
|
|
46620
|
-
|
|
46620
|
+
3. **Determine destination:**
|
|
46621
46621
|
- Scan \`docs/\` (excluding \`docs/in-progress/\`) for existing directories related to this work
|
|
46622
46622
|
- If a related directory exists, propose merging into it
|
|
46623
46623
|
- If no related directory, propose \`docs/<slug>/\` or \`docs/<slug>.mdx\`
|
|
46624
46624
|
- Present the proposed destination and ask user to confirm
|
|
46625
|
-
|
|
46625
|
+
4. **Move the doc(s):**
|
|
46626
46626
|
- Single file: move from \`docs/in-progress/\` to destination
|
|
46627
46627
|
- Directory: move entire directory
|
|
46628
|
-
|
|
46628
|
+
5. **Verify and report:**
|
|
46629
46629
|
- Confirm destination exists, source removed
|
|
46630
46630
|
- Check no leftover \`status:\` or \`## Resume Context\` in moved files
|
|
46631
46631
|
- Update \`docs/priorities.mdx\` if it exists
|
|
46632
46632
|
- Report: task title, cleanup stats (lines before/after), destination path
|
|
46633
|
-
|
|
46634
|
-
## Completion Suggestions
|
|
46635
|
-
|
|
46636
|
-
When the agent observes that all plan steps for a task are marked COMPLETE and the user seems to be moving on, proactively suggest: "All steps for '{task}' are complete. Run \`/work complete\` to finalize it."
|
|
46637
46633
|
`;
|
|
46638
46634
|
}
|
|
46639
46635
|
function claudeDocsCommandTemplate() {
|
|
@@ -46699,7 +46695,7 @@ Steps:
|
|
|
46699
46695
|
|
|
46700
46696
|
### \`create [description]\` -- Reference Doc Creation
|
|
46701
46697
|
|
|
46702
|
-
Interview-driven creation for permanent documentation. Task docs go through \`/work
|
|
46698
|
+
Interview-driven creation for permanent documentation. Task docs go through \`/work\`.
|
|
46703
46699
|
|
|
46704
46700
|
1. If no description given, ask: "What do you want to document?"
|
|
46705
46701
|
2. Determine doc type (infer or ask):
|
|
@@ -47069,17 +47065,19 @@ Exactly three values for frontmatter \`status\`: \`planned\`, \`in-progress\`, \
|
|
|
47069
47065
|
- IN PROGRESS -> COMPLETE (finishing a step)
|
|
47070
47066
|
- Do NOT update on every action -- only on step transitions
|
|
47071
47067
|
|
|
47072
|
-
## Save
|
|
47068
|
+
## Auto-Save Behavior
|
|
47073
47069
|
|
|
47074
|
-
|
|
47070
|
+
The agent auto-saves progress (no user action needed) when:
|
|
47075
47071
|
- The conversation context is getting heavy (many tool calls, large file reads)
|
|
47076
47072
|
- The user appears to be wrapping up (thanks, goodbye, switching topics)
|
|
47077
47073
|
- Significant progress has been made (2+ steps completed without saving)
|
|
47078
|
-
- Before a
|
|
47074
|
+
- Before a context reset
|
|
47075
|
+
|
|
47076
|
+
Auto-save updates the task doc's Progress and Resume Context sections silently, then briefly confirms.
|
|
47079
47077
|
|
|
47080
47078
|
## Completion Suggestions
|
|
47081
47079
|
|
|
47082
|
-
When all plan steps are marked COMPLETE, suggest
|
|
47080
|
+
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?"
|
|
47083
47081
|
|
|
47084
47082
|
## Directory Conventions
|
|
47085
47083
|
|
|
@@ -47204,7 +47202,7 @@ const RECOVERY_TABLE = [
|
|
|
47204
47202
|
test: r => /boundary hook/i.test(r) && /block|denied/i.test(r),
|
|
47205
47203
|
advice: 'Command blocked by SDK boundary hook.',
|
|
47206
47204
|
fix: 'Ask the user to run this command manually.',
|
|
47207
|
-
why: 'The boundary hook blocks
|
|
47205
|
+
why: 'The boundary hook blocks file modifications (Write, Edit, destructive Bash) outside the project boundary.',
|
|
47208
47206
|
see: 'CLAUDE.md',
|
|
47209
47207
|
},
|
|
47210
47208
|
{
|