@netnodeag/kraftwerk 0.34.2 → 0.35.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/README.md +14 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.js +42 -2
- package/dist/inspector/git.d.ts +83 -0
- package/dist/inspector/git.js +651 -0
- package/dist/inspector/instances.js +9 -1
- package/dist/inspector/server.js +132 -3
- package/dist/inspector/settings.d.ts +11 -1
- package/dist/inspector/settings.js +45 -0
- package/dist/runner/docker.d.ts +1 -0
- package/dist/runner/docker.js +1 -1
- package/inspector/dist/assets/{editor-CXrDJOv_.js → editor-BABv2LmA.js} +3 -3
- package/inspector/dist/assets/index-BXspF2KR.css +1 -0
- package/inspector/dist/assets/{index-DAi1VtJ8.js → index-BbTer62d.js} +1 -1
- package/inspector/dist/assets/{index-C3hpUVfp.js → index-Bmm4zJNU.js} +1 -1
- package/inspector/dist/assets/{index-x5G6Np7T.js → index-ByWpqzAI.js} +1 -1
- package/inspector/dist/assets/{index-Upf-BEsx.js → index-CCACy6uF.js} +1 -1
- package/inspector/dist/assets/{index-BNcXQYbv.js → index-Ca9Qs5LZ.js} +1 -1
- package/inspector/dist/assets/{index-Bumwg9SM.js → index-CdwTmXTV.js} +1 -1
- package/inspector/dist/assets/{index-CMMYSoL3.js → index-CjlJeW9z.js} +1 -1
- package/inspector/dist/assets/{index-CszaAR9T.js → index-CzPQygR7.js} +1 -1
- package/inspector/dist/assets/{index-DrSWAGft.js → index-DCR7u4Xa.js} +1 -1
- package/inspector/dist/assets/{index-BxEG-IdY.js → index-DbWUNbt-.js} +1 -1
- package/inspector/dist/assets/{index-BULB2rC_.js → index-DuPp3MUc.js} +1 -1
- package/inspector/dist/assets/{index-CNJyAniG.js → index-DuwmzZAr.js} +1 -1
- package/inspector/dist/assets/{index-CUCCMUMY.js → index-Gx93brFq.js} +1 -1
- package/inspector/dist/assets/{index-BIDsfw8C.js → index-HBdsdJhD.js} +1 -1
- package/inspector/dist/assets/{index-7J4zAS6J.js → index-hkVov8T4.js} +1 -1
- package/inspector/dist/assets/{index-BQMgADlc.js → index-sLxulPOm.js} +1 -1
- package/inspector/dist/assets/index-uEig4--d.js +217 -0
- package/inspector/dist/assets/{index-ChuqpBnv.js → index-wkYwz0Tl.js} +1 -1
- package/inspector/dist/index.html +2 -2
- package/package.json +5 -2
- package/schema/kraftwerk.schema.json +35 -1
- package/inspector/dist/assets/index-B7rwNdVj.css +0 -1
- package/inspector/dist/assets/index-BBGjdXk1.js +0 -213
package/README.md
CHANGED
|
@@ -160,6 +160,20 @@ kraftwerk run --sandbox website-check "https://..." # isolated container per r
|
|
|
160
160
|
kraftwerk runner ps / stop <run-id> # see / stop running sandbox containers
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
+
The inspector binds `127.0.0.1` — it has no authentication of its own and
|
|
164
|
+
its chat runs coding agents against the repo, so it stays off the LAN, and
|
|
165
|
+
while bound there it only answers requests whose `Host` is a loopback name
|
|
166
|
+
(so a page on another site cannot reach it by re-pointing its own DNS at
|
|
167
|
+
127.0.0.1). Inside a container it binds all interfaces instead, because the
|
|
168
|
+
port mapping is the boundary there (`deploy-starter/` publishes to
|
|
169
|
+
localhost, and its traefik override adds basic-auth). `KRAFTWERK_UI_HOST`
|
|
170
|
+
overrides the default either way. A reverse proxy in front of it must set
|
|
171
|
+
`X-Forwarded-Host` to the host the browser addressed (Caddy and traefik do
|
|
172
|
+
by default; nginx needs `proxy_set_header X-Forwarded-Host $host;`): the
|
|
173
|
+
loopback bind answers a non-loopback `Host` only when that header is
|
|
174
|
+
present, and state-changing requests are refused when `Origin` names a
|
|
175
|
+
different host.
|
|
176
|
+
|
|
163
177
|
### The kraftwerk.yml project config
|
|
164
178
|
|
|
165
179
|
Optional, at the project root, and also the root marker for the walk-up. All
|
package/dist/config.d.ts
CHANGED
|
@@ -21,12 +21,34 @@
|
|
|
21
21
|
* - name: other space
|
|
22
22
|
* url: https://localhost:1985
|
|
23
23
|
* icon: "🛰" # optional emoji shown next to the entry
|
|
24
|
+
* git: # workspace git sync (absent = off, bare key = on with defaults)
|
|
25
|
+
* remote: origin
|
|
26
|
+
* interval: 300 # seconds between background fetches
|
|
27
|
+
* autosync: pull # off | pull
|
|
24
28
|
*/
|
|
25
29
|
/** Stable, versionless URL of the workflow JSON schema (editor validation). */
|
|
26
30
|
export declare const SCHEMA_URL = "https://raw.githubusercontent.com/NETNODEAG/kraftwerk/main/kraftwerk/schema/workflow.schema.json";
|
|
27
31
|
/** Stable, versionless URL of the kraftwerk.yml JSON schema (editor validation). */
|
|
28
32
|
export declare const CONFIG_SCHEMA_URL = "https://raw.githubusercontent.com/NETNODEAG/kraftwerk/main/kraftwerk/schema/kraftwerk.schema.json";
|
|
29
33
|
export declare const CONFIG_FILENAMES: string[];
|
|
34
|
+
/**
|
|
35
|
+
* Git sync for the workspace. The synced paths are not configurable: they
|
|
36
|
+
* are the roots this file already declares (workflows, knowledge, agents,
|
|
37
|
+
* skills) plus kraftwerk.yml itself. Commit and push stay manual; the
|
|
38
|
+
* interval only fetches, and pulls when `autosync` allows it.
|
|
39
|
+
*/
|
|
40
|
+
export interface GitConfig {
|
|
41
|
+
/** false keeps the block but turns the feature off. Default: true. */
|
|
42
|
+
enabled?: boolean;
|
|
43
|
+
/** Remote to fetch, pull and push. Default: origin. */
|
|
44
|
+
remote?: string;
|
|
45
|
+
/** Branch to sync. Default: whatever is checked out. */
|
|
46
|
+
branch?: string;
|
|
47
|
+
/** Seconds between background fetches. 0 disables the timer. Default: 300. */
|
|
48
|
+
interval?: number;
|
|
49
|
+
/** off = fetch only. pull = also fast-forward when behind and clean. Default: pull. */
|
|
50
|
+
autosync?: "off" | "pull";
|
|
51
|
+
}
|
|
30
52
|
/** One entry of the workspace switcher: another kraftwerk instance to link to. */
|
|
31
53
|
export interface SwitcherEntry {
|
|
32
54
|
/** Display name of the other workspace. */
|
|
@@ -55,6 +77,8 @@ export interface ProjectConfig {
|
|
|
55
77
|
skills?: string;
|
|
56
78
|
/** Other kraftwerk workspaces, shown as a switcher dropdown in the inspector header. */
|
|
57
79
|
switcher?: SwitcherEntry[];
|
|
80
|
+
/** Workspace git sync. Absent = off. */
|
|
81
|
+
git?: GitConfig;
|
|
58
82
|
}
|
|
59
83
|
export interface Project {
|
|
60
84
|
/** Absolute project root the CLI operates on. */
|
package/dist/config.js
CHANGED
|
@@ -24,6 +24,10 @@ import { parse } from "yaml";
|
|
|
24
24
|
* - name: other space
|
|
25
25
|
* url: https://localhost:1985
|
|
26
26
|
* icon: "🛰" # optional emoji shown next to the entry
|
|
27
|
+
* git: # workspace git sync (absent = off, bare key = on with defaults)
|
|
28
|
+
* remote: origin
|
|
29
|
+
* interval: 300 # seconds between background fetches
|
|
30
|
+
* autosync: pull # off | pull
|
|
27
31
|
*/
|
|
28
32
|
/** Stable, versionless URL of the workflow JSON schema (editor validation). */
|
|
29
33
|
export const SCHEMA_URL = "https://raw.githubusercontent.com/NETNODEAG/kraftwerk/main/kraftwerk/schema/workflow.schema.json";
|
|
@@ -83,6 +87,7 @@ export async function resolveProject(cwd) {
|
|
|
83
87
|
const root = gitFallback ?? start;
|
|
84
88
|
return { root, config: {}, outputDir: path.join(root, "output") };
|
|
85
89
|
}
|
|
90
|
+
const KNOWN_KEYS = ["name", "icon", "port", "workflows", "output", "knowledge", "agents", "skills", "switcher", "git"];
|
|
86
91
|
async function loadConfig(configPath) {
|
|
87
92
|
let raw;
|
|
88
93
|
try {
|
|
@@ -94,10 +99,10 @@ async function loadConfig(configPath) {
|
|
|
94
99
|
if (raw === null || raw === undefined)
|
|
95
100
|
return {};
|
|
96
101
|
if (typeof raw !== "object" || Array.isArray(raw)) {
|
|
97
|
-
throw new Error(`${path.basename(configPath)}: expected a mapping (
|
|
102
|
+
throw new Error(`${path.basename(configPath)}: expected a mapping (${KNOWN_KEYS.join(", ")})`);
|
|
98
103
|
}
|
|
99
104
|
const config = raw;
|
|
100
|
-
const known =
|
|
105
|
+
const known = KNOWN_KEYS;
|
|
101
106
|
for (const key of Object.keys(config)) {
|
|
102
107
|
if (!known.includes(key)) {
|
|
103
108
|
throw new Error(`${path.basename(configPath)}: unknown key "${key}" (allowed: ${known.join(", ")})`);
|
|
@@ -110,6 +115,14 @@ async function loadConfig(configPath) {
|
|
|
110
115
|
else if (key === "switcher") {
|
|
111
116
|
validateSwitcher(configPath, config[key]);
|
|
112
117
|
}
|
|
118
|
+
else if (key === "git") {
|
|
119
|
+
// A bare `git:` line parses as null. Every field has a default, so read
|
|
120
|
+
// it as "on, with defaults" instead of failing the whole config load
|
|
121
|
+
// and taking the rest of the inspector down with it.
|
|
122
|
+
if (config[key] === null)
|
|
123
|
+
config[key] = {};
|
|
124
|
+
validateGit(configPath, config[key]);
|
|
125
|
+
}
|
|
113
126
|
else if (typeof config[key] !== "string") {
|
|
114
127
|
throw new Error(`${path.basename(configPath)}: ${key} must be a string`);
|
|
115
128
|
}
|
|
@@ -142,3 +155,30 @@ function validateSwitcher(configPath, value) {
|
|
|
142
155
|
}
|
|
143
156
|
});
|
|
144
157
|
}
|
|
158
|
+
function validateGit(configPath, value) {
|
|
159
|
+
const file = path.basename(configPath);
|
|
160
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
161
|
+
throw new Error(`${file}: git must be a mapping (enabled, remote, branch, interval, autosync)`);
|
|
162
|
+
}
|
|
163
|
+
const g = value;
|
|
164
|
+
const known = ["enabled", "remote", "branch", "interval", "autosync"];
|
|
165
|
+
for (const key of Object.keys(g)) {
|
|
166
|
+
if (!known.includes(key)) {
|
|
167
|
+
throw new Error(`${file}: git.${key} is unknown (allowed: ${known.join(", ")})`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (g.enabled !== undefined && typeof g.enabled !== "boolean") {
|
|
171
|
+
throw new Error(`${file}: git.enabled must be true or false`);
|
|
172
|
+
}
|
|
173
|
+
for (const key of ["remote", "branch"]) {
|
|
174
|
+
if (g[key] !== undefined && (typeof g[key] !== "string" || !g[key].trim())) {
|
|
175
|
+
throw new Error(`${file}: git.${key} must be a non-empty string`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (g.interval !== undefined && (typeof g.interval !== "number" || !Number.isInteger(g.interval) || g.interval < 0)) {
|
|
179
|
+
throw new Error(`${file}: git.interval must be a whole number of seconds (0 disables the timer)`);
|
|
180
|
+
}
|
|
181
|
+
if (g.autosync !== undefined && g.autosync !== "off" && g.autosync !== "pull") {
|
|
182
|
+
throw new Error(`${file}: git.autosync must be "off" or "pull"`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export interface GitFile {
|
|
2
|
+
/** Path relative to the repo root, which is what git speaks. */
|
|
3
|
+
path: string;
|
|
4
|
+
/** Two-letter porcelain code, e.g. " M", "??", "A ". */
|
|
5
|
+
code: string;
|
|
6
|
+
/** Human label for the code: modified, added, deleted, renamed, untracked. */
|
|
7
|
+
status: string;
|
|
8
|
+
/** Inside a synced root and not denied, so it can be selected. */
|
|
9
|
+
syncable: boolean;
|
|
10
|
+
/** Why it cannot be selected, when it cannot. */
|
|
11
|
+
reason?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface GitStatus {
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
/** Set when the feature is on but the repo cannot be used. */
|
|
16
|
+
error?: string;
|
|
17
|
+
repoRoot?: string;
|
|
18
|
+
branch?: string;
|
|
19
|
+
/** Configured or inferred upstream, absent when the branch tracks nothing. */
|
|
20
|
+
upstream?: string;
|
|
21
|
+
remote?: string;
|
|
22
|
+
ahead?: number;
|
|
23
|
+
behind?: number;
|
|
24
|
+
/** True when the branches have diverged, which needs a terminal. */
|
|
25
|
+
diverged?: boolean;
|
|
26
|
+
files?: GitFile[];
|
|
27
|
+
/** Blocked entries left out of `files` because the list was capped. */
|
|
28
|
+
blockedHidden?: number;
|
|
29
|
+
/** Repo-relative roots that may be committed. */
|
|
30
|
+
scope?: string[];
|
|
31
|
+
autosync?: "off" | "pull";
|
|
32
|
+
interval?: number;
|
|
33
|
+
lastFetch?: string;
|
|
34
|
+
lastPull?: string;
|
|
35
|
+
lastError?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface GitDiff {
|
|
38
|
+
diff: string;
|
|
39
|
+
error?: string;
|
|
40
|
+
/** The diff was cut at MAX_DIFF; the rest is available in a terminal. */
|
|
41
|
+
truncated?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Everything the git screen renders. Each call shells out to git a handful
|
|
45
|
+
* of times, and the nav badge polls it from every open tab, so results are
|
|
46
|
+
* cached for a beat.
|
|
47
|
+
*/
|
|
48
|
+
export declare function gitStatus(fresh?: boolean): Promise<GitStatus>;
|
|
49
|
+
/**
|
|
50
|
+
* Unified diff for one changed file. Reading is as sensitive as writing
|
|
51
|
+
* here: this endpoint has no auth of its own, and a diff of an untracked
|
|
52
|
+
* .env is the file itself. So the status list is the one source of readable
|
|
53
|
+
* paths: a file not listed there, or listed as blocked, is not shown.
|
|
54
|
+
* Status never lists ignored files, which covers .gitignore too.
|
|
55
|
+
*/
|
|
56
|
+
export declare function gitDiff(file: string): Promise<GitDiff>;
|
|
57
|
+
/** Stage the given repo-relative paths and commit just those. */
|
|
58
|
+
export declare function gitCommit(paths: string[], message: string): Promise<{
|
|
59
|
+
ok: boolean;
|
|
60
|
+
error?: string;
|
|
61
|
+
committed?: number;
|
|
62
|
+
}>;
|
|
63
|
+
export declare function gitFetch(): Promise<{
|
|
64
|
+
ok: boolean;
|
|
65
|
+
error?: string;
|
|
66
|
+
}>;
|
|
67
|
+
/** Fast-forward only. A diverged branch is the user's problem, not ours. */
|
|
68
|
+
export declare function gitPull(): Promise<{
|
|
69
|
+
ok: boolean;
|
|
70
|
+
error?: string;
|
|
71
|
+
}>;
|
|
72
|
+
export declare function gitPush(): Promise<{
|
|
73
|
+
ok: boolean;
|
|
74
|
+
error?: string;
|
|
75
|
+
}>;
|
|
76
|
+
/**
|
|
77
|
+
* Fetch on an interval, and fast-forward when `autosync: pull` is set. Never
|
|
78
|
+
* commits. A pull is skipped while the tree is dirty, so nobody's unsaved
|
|
79
|
+
* work is disturbed by a background merge. Ticks are chained, not scheduled
|
|
80
|
+
* on a fixed interval: a fetch against a slow remote must finish (or time
|
|
81
|
+
* out) before the next one starts, or a short interval piles up processes.
|
|
82
|
+
*/
|
|
83
|
+
export declare function startGitSync(): void;
|