@netnodeag/kraftwerk 0.37.0 → 0.37.1
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/projects.js +2 -1
- package/dist/cli/ui.js +2 -2
- package/dist/config.d.ts +8 -0
- package/dist/config.js +13 -0
- package/dist/inspector/instances.js +7 -7
- package/package.json +1 -1
package/dist/cli/projects.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
+
import { absolutePath } from "../config.js";
|
|
3
4
|
import Table from "cli-table3";
|
|
4
5
|
import { discoverWorkspaces, forgetProject, startProject, stopProject, tildify, } from "../inspector/instances.js";
|
|
5
6
|
/**
|
|
@@ -43,7 +44,7 @@ const status = (e) => {
|
|
|
43
44
|
/** Match a ref against known workspaces; `needRoot` excludes rootless live instances (start/forget need a root). */
|
|
44
45
|
async function resolveRef(ref, needRoot = true) {
|
|
45
46
|
const all = (await discoverWorkspaces()).filter((e) => e.root || !needRoot);
|
|
46
|
-
const abs =
|
|
47
|
+
const abs = absolutePath(ref);
|
|
47
48
|
const port = /^\d+$/.test(ref) ? `http://localhost:${ref}` : `http://${ref.replace(/^https?:\/\//, "")}`;
|
|
48
49
|
const hits = all.filter((e) => e.root === abs ||
|
|
49
50
|
e.root === ref ||
|
package/dist/cli/ui.js
CHANGED
|
@@ -4,7 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { spawn, spawnSync } from "node:child_process";
|
|
6
6
|
import chalk from "chalk";
|
|
7
|
-
import { resolveProject } from "../config.js";
|
|
7
|
+
import { absolutePath, resolveProject } from "../config.js";
|
|
8
8
|
import { selfCommand } from "../inspector/self-command.js";
|
|
9
9
|
import { RESTART_EXIT_CODE, startInspector } from "../inspector/server.js";
|
|
10
10
|
/**
|
|
@@ -52,7 +52,7 @@ export async function runUi(cwd, opts) {
|
|
|
52
52
|
return superviseUi(opts);
|
|
53
53
|
const staticDir = ensureBuilt();
|
|
54
54
|
const project = await resolveProject(cwd);
|
|
55
|
-
const outputDir = opts.output ?
|
|
55
|
+
const outputDir = opts.output ? absolutePath(opts.output, cwd) : project.outputDir;
|
|
56
56
|
// Port precedence: --port flag > kraftwerk.yml `port` > 1981.
|
|
57
57
|
const port = opts.port ? Number(opts.port) : (project.config.port ?? 1981);
|
|
58
58
|
await startInspector({ outputDir, staticDir, port, projectRoot: project.root });
|
package/dist/config.d.ts
CHANGED
|
@@ -120,6 +120,14 @@ export interface Project {
|
|
|
120
120
|
outputDir: string;
|
|
121
121
|
}
|
|
122
122
|
/** True when the path exists and is a directory. */
|
|
123
|
+
/**
|
|
124
|
+
* A user-supplied path as an absolute one: a leading `~` is the home
|
|
125
|
+
* directory (shells expand it, JSON bodies and quoted args do not), then
|
|
126
|
+
* path.resolve. Every path that gets stored or compared — registry roots,
|
|
127
|
+
* `--output`, project refs — goes through here so nothing ever persists
|
|
128
|
+
* `~/…` or `<cwd>/~/…`.
|
|
129
|
+
*/
|
|
130
|
+
export declare function absolutePath(p: string, from?: string): string;
|
|
123
131
|
export declare const isDir: (p: string) => Promise<boolean>;
|
|
124
132
|
/**
|
|
125
133
|
* Resolve the project for a cwd: walk up until a kraftwerk.yml or a
|
package/dist/config.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { parse } from "yaml";
|
|
4
5
|
/**
|
|
@@ -63,6 +64,18 @@ export function gitignoreHas(text, entry) {
|
|
|
63
64
|
}
|
|
64
65
|
const exists = async (p) => !!(await stat(p).catch(() => null));
|
|
65
66
|
/** True when the path exists and is a directory. */
|
|
67
|
+
/**
|
|
68
|
+
* A user-supplied path as an absolute one: a leading `~` is the home
|
|
69
|
+
* directory (shells expand it, JSON bodies and quoted args do not), then
|
|
70
|
+
* path.resolve. Every path that gets stored or compared — registry roots,
|
|
71
|
+
* `--output`, project refs — goes through here so nothing ever persists
|
|
72
|
+
* `~/…` or `<cwd>/~/…`.
|
|
73
|
+
*/
|
|
74
|
+
export function absolutePath(p, from = process.cwd()) {
|
|
75
|
+
if (p === "~" || p.startsWith("~/") || p.startsWith("~\\"))
|
|
76
|
+
p = path.join(os.homedir(), p.slice(1));
|
|
77
|
+
return path.resolve(from, p);
|
|
78
|
+
}
|
|
66
79
|
export const isDir = async (p) => (await stat(p).catch(() => null))?.isDirectory() ?? false;
|
|
67
80
|
async function findConfigFile(dir) {
|
|
68
81
|
for (const name of CONFIG_FILENAMES) {
|
|
@@ -3,7 +3,7 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
import fsSync, { promises as fs } from "node:fs";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import { isDir, resolveProject } from "../config.js";
|
|
6
|
+
import { absolutePath, isDir, resolveProject } from "../config.js";
|
|
7
7
|
import { selfCommand } from "./self-command.js";
|
|
8
8
|
/**
|
|
9
9
|
* Two registries under ~/.kraftwerk, two lifecycles:
|
|
@@ -31,7 +31,7 @@ const LOGS_DIR = path.join(HOME, "logs");
|
|
|
31
31
|
const selfFile = () => path.join(INSTANCES_DIR, `${process.pid}.json`);
|
|
32
32
|
let selfPort = null;
|
|
33
33
|
let selfRoot = null;
|
|
34
|
-
const projectKey = (root) => createHash("sha1").update(
|
|
34
|
+
const projectKey = (root) => createHash("sha1").update(absolutePath(root)).digest("hex").slice(0, 16);
|
|
35
35
|
const projectFile = (root) => path.join(PROJECTS_DIR, `${projectKey(root)}.json`);
|
|
36
36
|
/** ~/… for display. */
|
|
37
37
|
export const tildify = (p) => {
|
|
@@ -42,7 +42,7 @@ export const tildify = (p) => {
|
|
|
42
42
|
/** Write this instance's registry file (call once the server listens). */
|
|
43
43
|
export async function registerInstance(port, root) {
|
|
44
44
|
selfPort = port;
|
|
45
|
-
selfRoot =
|
|
45
|
+
selfRoot = absolutePath(root);
|
|
46
46
|
try {
|
|
47
47
|
await fs.mkdir(INSTANCES_DIR, { recursive: true });
|
|
48
48
|
const rec = { pid: process.pid, port, startedAt: new Date().toISOString(), root: selfRoot };
|
|
@@ -151,7 +151,7 @@ async function readProject(file) {
|
|
|
151
151
|
}
|
|
152
152
|
/** Upsert the project record for a root (call on every inspector start). */
|
|
153
153
|
export async function registerProject(root) {
|
|
154
|
-
const abs =
|
|
154
|
+
const abs = absolutePath(root);
|
|
155
155
|
const now = new Date().toISOString();
|
|
156
156
|
try {
|
|
157
157
|
await fs.mkdir(PROJECTS_DIR, { recursive: true });
|
|
@@ -395,7 +395,7 @@ export async function listWorkspacesDetailed() {
|
|
|
395
395
|
* straight to it.
|
|
396
396
|
*/
|
|
397
397
|
export async function startProject(root) {
|
|
398
|
-
const abs =
|
|
398
|
+
const abs = absolutePath(root);
|
|
399
399
|
const { name, port, exists } = await describeRoot(abs);
|
|
400
400
|
if (!exists)
|
|
401
401
|
return { ok: false, error: `not a project directory (missing or moved): ${abs}` };
|
|
@@ -464,12 +464,12 @@ export async function startProject(root) {
|
|
|
464
464
|
* that registered no root. Waits up to ~5s for the port to go quiet.
|
|
465
465
|
*/
|
|
466
466
|
export async function stopProject(target) {
|
|
467
|
-
if (target.root &&
|
|
467
|
+
if (target.root && absolutePath(target.root) === selfRoot) {
|
|
468
468
|
return { ok: false, error: "that is this workspace — stop it from its own terminal or pid" };
|
|
469
469
|
}
|
|
470
470
|
cache = wsCache = null;
|
|
471
471
|
const live = await discoverInstances();
|
|
472
|
-
const inst = live.find((i) => (target.root && i.root ===
|
|
472
|
+
const inst = live.find((i) => (target.root && i.root === absolutePath(target.root)) || (target.url && i.url === target.url));
|
|
473
473
|
if (!inst)
|
|
474
474
|
return { ok: false, error: "not running" };
|
|
475
475
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netnodeag/kraftwerk",
|
|
3
|
-
"version": "0.37.
|
|
3
|
+
"version": "0.37.1",
|
|
4
4
|
"description": "Open-source agentic workspace for teams — where people and AI agents get work done together: agents (Claude Code, Codex, Pi), skills, shared knowledge, repeatable workflows, and deterministic verification",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|