@openparachute/agent 0.2.2 → 0.2.3-rc.3
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/.parachute/module.json +3 -3
- package/package.json +4 -1
- package/src/transports/vault.ts +40 -22
- package/web/ui/dist/assets/index-5KEwEhfi.js +60 -0
- package/web/ui/dist/index.html +1 -1
- package/src/_parked/interactive-spawn.test.ts +0 -324
- package/src/_parked/interactive-spawn.ts +0 -701
- package/src/agent-defs.test.ts +0 -1504
- package/src/agent-mcp-config.test.ts +0 -115
- package/src/agents.test.ts +0 -360
- package/src/auth.test.ts +0 -46
- package/src/backends/attached-queue.test.ts +0 -376
- package/src/backends/programmatic.test.ts +0 -1715
- package/src/backends/registry.test.ts +0 -1494
- package/src/backends/stream-json.test.ts +0 -570
- package/src/channel-backend-wiring.test.ts +0 -237
- package/src/credentials.test.ts +0 -274
- package/src/cron.test.ts +0 -342
- package/src/daemon-agent-def-api.test.ts +0 -166
- package/src/daemon-agent-defs-api.test.ts +0 -953
- package/src/daemon-agent-env-api.test.ts +0 -338
- package/src/daemon-attached-queue-store.test.ts +0 -65
- package/src/daemon-config-api.test.ts +0 -962
- package/src/daemon-jobs-api.test.ts +0 -271
- package/src/daemon-vault-chat.test.ts +0 -250
- package/src/daemon.test.ts +0 -746
- package/src/def-vaults.test.ts +0 -136
- package/src/delivery-state.test.ts +0 -110
- package/src/effective-env.test.ts +0 -114
- package/src/grants.test.ts +0 -638
- package/src/hub-jwt.test.ts +0 -161
- package/src/jobs.test.ts +0 -245
- package/src/mcp-http.test.ts +0 -265
- package/src/mint-token.test.ts +0 -152
- package/src/module-manifest.test.ts +0 -158
- package/src/programmatic-wiring.test.ts +0 -838
- package/src/registry.test.ts +0 -227
- package/src/resolve-port.test.ts +0 -64
- package/src/routing.test.ts +0 -184
- package/src/runner.test.ts +0 -506
- package/src/sandbox/config.test.ts +0 -150
- package/src/sandbox/egress.test.ts +0 -113
- package/src/sandbox/live-seatbelt.test.ts +0 -277
- package/src/sandbox/mounts.test.ts +0 -154
- package/src/sandbox/sandbox.test.ts +0 -168
- package/src/services-manifest.test.ts +0 -106
- package/src/spa-serve.test.ts +0 -116
- package/src/spawn-agent-cli.test.ts +0 -172
- package/src/spawn-agent.test.ts +0 -1218
- package/src/spawn-deps.test.ts +0 -54
- package/src/terminal-assets.test.ts +0 -50
- package/src/terminal.test.ts +0 -530
- package/src/transports/http-ui.test.ts +0 -455
- package/src/transports/telegram.test.ts +0 -174
- package/src/transports/vault.test.ts +0 -2011
- package/src/ui-kit.test.ts +0 -178
- package/web/ui/dist/assets/index-VFETBk0a.js +0 -60
- package/web/ui/tsconfig.json +0 -21
package/src/ui-kit.test.ts
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for the shared UI kit (src/ui-kit.ts) — the foundation every
|
|
3
|
-
* channel page adopts. Guards the shell contract (active-tab marking, controls
|
|
4
|
-
* slot, nav set) + the token/CSS invariants the pages depend on.
|
|
5
|
-
*/
|
|
6
|
-
import { describe, test, expect } from "bun:test";
|
|
7
|
-
import { THEME_CSS, SHELL_JS, appShell, NAV_VIEWS, BRAND } from "./ui-kit.ts";
|
|
8
|
-
|
|
9
|
-
describe("appShell", () => {
|
|
10
|
-
test("renders the brand + all nav tabs, marking only the active one", () => {
|
|
11
|
-
const h = appShell({ active: "agents" });
|
|
12
|
-
expect(h).toContain("app-header");
|
|
13
|
-
expect(h).toContain('class="brand-mark"');
|
|
14
|
-
for (const v of NAV_VIEWS) expect(h).toContain(`data-view="${v.view}"`);
|
|
15
|
-
// active tab gets class="active"; others don't.
|
|
16
|
-
expect(h).toContain('data-view="agents" href="#" class="active"');
|
|
17
|
-
expect(h).toContain('data-view="chat" href="#"');
|
|
18
|
-
expect(h).not.toContain('data-view="chat" href="#" class="active"');
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test("marks Home active when it is the current view", () => {
|
|
22
|
-
const h = appShell({ active: "home" });
|
|
23
|
-
expect(h).toContain('data-view="home" href="#" class="active"');
|
|
24
|
-
expect(h).toContain('data-view="chat" href="#"');
|
|
25
|
-
expect(h).not.toContain('data-view="chat" href="#" class="active"');
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
test("status defaults, and a custom status + tag suffix render", () => {
|
|
29
|
-
expect(appShell({ active: "chat" })).toContain('id="status"');
|
|
30
|
-
const h = appShell({ active: "chat", status: "● ready", tag: "chat" });
|
|
31
|
-
expect(h).toContain("● ready");
|
|
32
|
-
expect(h).toContain("· chat");
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test("controls slot is injected before the status when provided, omitted otherwise", () => {
|
|
36
|
-
const withCtl = appShell({ active: "terminal", controls: "<button id='reconnect'>Reconnect</button>" });
|
|
37
|
-
expect(withCtl).toContain("app-controls");
|
|
38
|
-
expect(withCtl).toContain("id='reconnect'");
|
|
39
|
-
expect(appShell({ active: "terminal" })).not.toContain("app-controls");
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test("nav covers exactly home/chat/agents/schedules/terminal/config, Home first", () => {
|
|
43
|
-
expect(NAV_VIEWS.map((v) => v.view)).toEqual([
|
|
44
|
-
"home",
|
|
45
|
-
"chat",
|
|
46
|
-
"agents",
|
|
47
|
-
"schedules",
|
|
48
|
-
"terminal",
|
|
49
|
-
"config",
|
|
50
|
-
]);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe("THEME_CSS", () => {
|
|
55
|
-
test("declares the brand tokens incl. the warm-light bg, accent, warn, and dark term pane", () => {
|
|
56
|
-
expect(THEME_CSS).toContain(":root");
|
|
57
|
-
expect(THEME_CSS).toContain(`--bg: ${BRAND.bg}`); // #faf8f4, the warm light brand
|
|
58
|
-
expect(THEME_CSS).toContain(`--accent: ${BRAND.accent}`);
|
|
59
|
-
expect(THEME_CSS).toContain(`--warn: ${BRAND.warn}`);
|
|
60
|
-
expect(THEME_CSS).toContain(`--term-bg: ${BRAND.termBg}`); // #000 — the only intended black
|
|
61
|
-
});
|
|
62
|
-
test("ships the shared component layer (shell + buttons + banners + pills)", () => {
|
|
63
|
-
for (const sel of [".app-nav", ".app-nav a.active", ".btn-primary", ".banner-warn", ".pill.warn"]) {
|
|
64
|
-
expect(THEME_CSS).toContain(sel);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
test("carries NO leftover dark-console tokens (the pages unified on the brand)", () => {
|
|
68
|
-
expect(THEME_CSS).not.toContain("#0f1115");
|
|
69
|
-
expect(THEME_CSS).not.toContain("--panel");
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
describe("SHELL_JS", () => {
|
|
74
|
-
test("provides MOUNT derivation, nav wiring, token fetch, and helpers", () => {
|
|
75
|
-
for (const sym of ["var MOUNT", "function wireShell", "function escapeHtml", "function setStatus", "function fetchToken", "function authedFetch", "function setTerminalNavVisible"]) {
|
|
76
|
-
expect(SHELL_JS).toContain(sym);
|
|
77
|
-
}
|
|
78
|
-
// It hits the hub agent-token endpoint with the operator cookie.
|
|
79
|
-
expect(SHELL_JS).toContain("/admin/agent-token");
|
|
80
|
-
expect(SHELL_JS).toContain('credentials: "include"');
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// Terminal-nav cleanup (Parachute Agent Phase 1): wireShell hides the standalone
|
|
84
|
-
// Terminal nav entry by default (programmatic backend has no terminal); pages
|
|
85
|
-
// reveal it via setTerminalNavVisible when an interactive agent exists. The
|
|
86
|
-
// Terminal page itself (active === "terminal") shows it.
|
|
87
|
-
test("wireShell gates the Terminal nav link via setTerminalNavVisible", () => {
|
|
88
|
-
expect(SHELL_JS).toContain('a[data-view="terminal"]');
|
|
89
|
-
// wireShell defaults the terminal entry to its own-page-only visibility.
|
|
90
|
-
expect(SHELL_JS).toContain('setTerminalNavVisible(active === "terminal")');
|
|
91
|
-
});
|
|
92
|
-
test("is safe to interpolate — no naked backtick that could break a host literal", () => {
|
|
93
|
-
expect(SHELL_JS.includes("`")).toBe(false);
|
|
94
|
-
});
|
|
95
|
-
test("exports a renderMarkdown helper (reused by the chat transcript)", () => {
|
|
96
|
-
expect(SHELL_JS).toContain("function renderMarkdown");
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// renderMarkdown lives inside SHELL_JS (vanilla JS, no DOM). Evaluate SHELL_JS in
|
|
101
|
-
// a fresh function scope and hand back its renderMarkdown so we can exercise it
|
|
102
|
-
// directly — the same code the chat page runs in the browser.
|
|
103
|
-
function loadRenderMarkdown(): (text: string) => string {
|
|
104
|
-
// SHELL_JS defines `var MOUNT = window.location...` at the top; stub a minimal
|
|
105
|
-
// window so that line doesn't throw when evaluated outside a browser.
|
|
106
|
-
const factory = new Function(
|
|
107
|
-
"window",
|
|
108
|
-
SHELL_JS + "\nreturn renderMarkdown;",
|
|
109
|
-
) as (w: unknown) => (text: string) => string;
|
|
110
|
-
return factory({ location: { pathname: "/ui" } });
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
describe("renderMarkdown (SHELL_JS, XSS-safe Markdown subset)", () => {
|
|
114
|
-
const renderMarkdown = loadRenderMarkdown();
|
|
115
|
-
|
|
116
|
-
test("escapes raw HTML first — a <script> tag never survives as markup", () => {
|
|
117
|
-
const out = renderMarkdown("<script>alert(1)</script>");
|
|
118
|
-
expect(out).not.toContain("<script>");
|
|
119
|
-
expect(out).toContain("<script>");
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
test("renders bold and italic", () => {
|
|
123
|
-
expect(renderMarkdown("**bold**")).toContain("<strong>bold</strong>");
|
|
124
|
-
expect(renderMarkdown("an *italic* word")).toContain("<em>italic</em>");
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test("renders inline code and fenced code blocks", () => {
|
|
128
|
-
const bt = String.fromCharCode(96);
|
|
129
|
-
expect(renderMarkdown(bt + "inline" + bt)).toContain("<code>inline</code>");
|
|
130
|
-
const fenced = renderMarkdown(bt + bt + bt + "\nconst x = 1;\n" + bt + bt + bt);
|
|
131
|
-
expect(fenced).toContain("<pre><code>");
|
|
132
|
-
expect(fenced).toContain("const x = 1;");
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
test("does not apply inline rules inside code spans", () => {
|
|
136
|
-
const bt = String.fromCharCode(96);
|
|
137
|
-
const out = renderMarkdown(bt + "**not bold**" + bt);
|
|
138
|
-
expect(out).toContain("<code>**not bold**</code>");
|
|
139
|
-
expect(out).not.toContain("<strong>");
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
test("renders http/https links as anchors with the url preserved", () => {
|
|
143
|
-
const out = renderMarkdown("[site](https://example.com/x)");
|
|
144
|
-
expect(out).toContain('href="https://example.com/x"');
|
|
145
|
-
expect(out).toContain(">site</a>");
|
|
146
|
-
expect(out).toContain('rel="noopener noreferrer"');
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
test("rejects javascript: URLs — renders inert escaped text, no anchor", () => {
|
|
150
|
-
const out = renderMarkdown("[click](javascript:alert(1))");
|
|
151
|
-
// No anchor and no href is produced — the would-be URL never reaches markup.
|
|
152
|
-
expect(out).not.toContain("<a ");
|
|
153
|
-
expect(out).not.toContain("href=");
|
|
154
|
-
// The markdown is left as inert escaped text (safe — not an executable link).
|
|
155
|
-
expect(out).toContain("[click]");
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test("rejects data: URLs too — only http/https survive as anchors", () => {
|
|
159
|
-
const out = renderMarkdown("[x](data:text/html,<script>alert(1)</script>)");
|
|
160
|
-
expect(out).not.toContain("<a ");
|
|
161
|
-
expect(out).not.toContain("href=");
|
|
162
|
-
// any escaped markup inside is inert text, never executable.
|
|
163
|
-
expect(out).not.toContain("<script>");
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test("escapes other canonical XSS vectors (img onerror, svg onload)", () => {
|
|
167
|
-
const out1 = renderMarkdown('<img src=x onerror=alert(1)>');
|
|
168
|
-
expect(out1).not.toContain("<img");
|
|
169
|
-
expect(out1).toContain("<img");
|
|
170
|
-
const out2 = renderMarkdown('<svg onload=alert(1)>');
|
|
171
|
-
expect(out2).not.toContain("<svg");
|
|
172
|
-
expect(out2).toContain("<svg");
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
test("converts newlines to <br>", () => {
|
|
176
|
-
expect(renderMarkdown("line1\nline2")).toContain("line1<br>line2");
|
|
177
|
-
});
|
|
178
|
-
});
|