quadwork 1.5.1 → 1.5.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/bin/quadwork.js +13 -1
- package/out/404.html +1 -1
- package/out/__next.__PAGE__.txt +1 -1
- package/out/__next._full.txt +1 -1
- package/out/__next._head.txt +1 -1
- package/out/__next._index.txt +1 -1
- package/out/__next._tree.txt +1 -1
- package/out/_next/static/chunks/{0-7v31f-nsgw-.js → 09sq17vme9g6p.js} +1 -1
- package/out/_next/static/chunks/{0m83k84.midd1.js → 0wreuebrwlg.2.js} +1 -1
- package/out/_not-found/__next._full.txt +1 -1
- package/out/_not-found/__next._head.txt +1 -1
- package/out/_not-found/__next._index.txt +1 -1
- package/out/_not-found/__next._not-found.__PAGE__.txt +1 -1
- package/out/_not-found/__next._not-found.txt +1 -1
- package/out/_not-found/__next._tree.txt +1 -1
- package/out/_not-found.html +1 -1
- package/out/_not-found.txt +1 -1
- package/out/app-shell/__next._full.txt +1 -1
- package/out/app-shell/__next._head.txt +1 -1
- package/out/app-shell/__next._index.txt +1 -1
- package/out/app-shell/__next._tree.txt +1 -1
- package/out/app-shell/__next.app-shell.__PAGE__.txt +1 -1
- package/out/app-shell/__next.app-shell.txt +1 -1
- package/out/app-shell.html +1 -1
- package/out/app-shell.txt +1 -1
- package/out/index.html +1 -1
- package/out/index.txt +1 -1
- package/out/project/_/__next._full.txt +2 -2
- package/out/project/_/__next._head.txt +1 -1
- package/out/project/_/__next._index.txt +1 -1
- package/out/project/_/__next._tree.txt +1 -1
- package/out/project/_/__next.project.$d$id.__PAGE__.txt +2 -2
- package/out/project/_/__next.project.$d$id.txt +1 -1
- package/out/project/_/__next.project.txt +1 -1
- package/out/project/_/memory/__next._full.txt +1 -1
- package/out/project/_/memory/__next._head.txt +1 -1
- package/out/project/_/memory/__next._index.txt +1 -1
- package/out/project/_/memory/__next._tree.txt +1 -1
- package/out/project/_/memory/__next.project.$d$id.memory.__PAGE__.txt +1 -1
- package/out/project/_/memory/__next.project.$d$id.memory.txt +1 -1
- package/out/project/_/memory/__next.project.$d$id.txt +1 -1
- package/out/project/_/memory/__next.project.txt +1 -1
- package/out/project/_/memory.html +1 -1
- package/out/project/_/memory.txt +1 -1
- package/out/project/_/queue/__next._full.txt +1 -1
- package/out/project/_/queue/__next._head.txt +1 -1
- package/out/project/_/queue/__next._index.txt +1 -1
- package/out/project/_/queue/__next._tree.txt +1 -1
- package/out/project/_/queue/__next.project.$d$id.queue.__PAGE__.txt +1 -1
- package/out/project/_/queue/__next.project.$d$id.queue.txt +1 -1
- package/out/project/_/queue/__next.project.$d$id.txt +1 -1
- package/out/project/_/queue/__next.project.txt +1 -1
- package/out/project/_/queue.html +1 -1
- package/out/project/_/queue.txt +1 -1
- package/out/project/_.html +1 -1
- package/out/project/_.txt +2 -2
- package/out/settings/__next._full.txt +1 -1
- package/out/settings/__next._head.txt +1 -1
- package/out/settings/__next._index.txt +1 -1
- package/out/settings/__next._tree.txt +1 -1
- package/out/settings/__next.settings.__PAGE__.txt +1 -1
- package/out/settings/__next.settings.txt +1 -1
- package/out/settings.html +1 -1
- package/out/settings.txt +1 -1
- package/out/setup/__next._full.txt +1 -1
- package/out/setup/__next._head.txt +1 -1
- package/out/setup/__next._index.txt +1 -1
- package/out/setup/__next._tree.txt +1 -1
- package/out/setup/__next.setup.__PAGE__.txt +1 -1
- package/out/setup/__next.setup.txt +1 -1
- package/out/setup.html +1 -1
- package/out/setup.txt +1 -1
- package/package.json +1 -1
- package/server/routes.chatWsSend.test.js +161 -0
- package/server/routes.js +250 -32
- package/server/routes.telegramBridge.test.js +145 -2
- package/templates/config.toml +8 -0
- /package/out/_next/static/{wxXtT0v8ALxniu3OdJwt5 → X4zdS6Y6HkLOaElNeHwnq}/_buildManifest.js +0 -0
- /package/out/_next/static/{wxXtT0v8ALxniu3OdJwt5 → X4zdS6Y6HkLOaElNeHwnq}/_clientMiddlewareManifest.js +0 -0
- /package/out/_next/static/{wxXtT0v8ALxniu3OdJwt5 → X4zdS6Y6HkLOaElNeHwnq}/_ssgManifest.js +0 -0
|
@@ -10,7 +10,15 @@ const assert = require("node:assert/strict");
|
|
|
10
10
|
const fs = require("node:fs");
|
|
11
11
|
const os = require("node:os");
|
|
12
12
|
const path = require("node:path");
|
|
13
|
-
const {
|
|
13
|
+
const { execFileSync } = require("node:child_process");
|
|
14
|
+
const {
|
|
15
|
+
readLastLines,
|
|
16
|
+
checkTelegramBridgePythonDeps,
|
|
17
|
+
resolveProjectAgentchattrUrl,
|
|
18
|
+
buildTelegramBridgeToml,
|
|
19
|
+
patchAgentchattrConfigForTelegramBridge,
|
|
20
|
+
buildTelegramBridgeSpawnEnv,
|
|
21
|
+
} = require("./routes");
|
|
14
22
|
|
|
15
23
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "qw-bridge-log-"));
|
|
16
24
|
function write(name, content) {
|
|
@@ -89,7 +97,142 @@ try {
|
|
|
89
97
|
assert.match(tail, /ModuleNotFoundError/);
|
|
90
98
|
assert.match(tail, /Install Bridge/);
|
|
91
99
|
|
|
92
|
-
|
|
100
|
+
// 9) #380: checkTelegramBridgePythonDeps accepts an explicit
|
|
101
|
+
// interpreter path. Passing a guaranteed-broken path must
|
|
102
|
+
// return { ok: false, error } without throwing.
|
|
103
|
+
const broken = checkTelegramBridgePythonDeps(path.join(tmp, "nope", "python3"));
|
|
104
|
+
assert.equal(broken.ok, false);
|
|
105
|
+
assert.ok(broken.error && broken.error.length > 0);
|
|
106
|
+
|
|
107
|
+
// 10) #380: start handler's missing-venv branch — we don't boot
|
|
108
|
+
// the server here, but the branch reduces to a plain
|
|
109
|
+
// fs.existsSync check on `<BRIDGE_DIR>/.venv/bin/python3`,
|
|
110
|
+
// so we verify the check returns false for a fixture dir
|
|
111
|
+
// that has no `.venv` subdir at all.
|
|
112
|
+
const fixtureBridgeDir = fs.mkdtempSync(path.join(tmp, "bridge-no-venv-"));
|
|
113
|
+
const missingVenvPython = path.join(fixtureBridgeDir, ".venv", "bin", "python3");
|
|
114
|
+
assert.equal(fs.existsSync(missingVenvPython), false);
|
|
115
|
+
|
|
116
|
+
// 11) #380: round-trip — build a real venv in a tmp dir, install
|
|
117
|
+
// a stdlib-only sentinel is trivially importable, and confirm
|
|
118
|
+
// checkTelegramBridgePythonDeps reports ok when `requests`
|
|
119
|
+
// is installed into that venv. Skipped gracefully on CI if
|
|
120
|
+
// `python3 -m venv` or network-backed pip install fails.
|
|
121
|
+
const venvDir = path.join(tmp, "case11-venv");
|
|
122
|
+
let venvSkipped = false;
|
|
123
|
+
try {
|
|
124
|
+
execFileSync("python3", ["-m", "venv", venvDir], { timeout: 30000, stdio: "pipe" });
|
|
125
|
+
const venvPython = path.join(venvDir, "bin", "python3");
|
|
126
|
+
const venvPip = path.join(venvDir, "bin", "pip");
|
|
127
|
+
// Without `requests` installed yet, the check must fail.
|
|
128
|
+
const before = checkTelegramBridgePythonDeps(venvPython);
|
|
129
|
+
assert.equal(before.ok, false);
|
|
130
|
+
try {
|
|
131
|
+
execFileSync(venvPip, ["install", "--quiet", "requests"], { timeout: 120000, stdio: "pipe" });
|
|
132
|
+
} catch {
|
|
133
|
+
venvSkipped = true;
|
|
134
|
+
}
|
|
135
|
+
if (!venvSkipped) {
|
|
136
|
+
const after = checkTelegramBridgePythonDeps(venvPython);
|
|
137
|
+
assert.equal(after.ok, true);
|
|
138
|
+
}
|
|
139
|
+
} catch {
|
|
140
|
+
venvSkipped = true;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 12) #383 Bug 1: resolveProjectAgentchattrUrl prefers the
|
|
144
|
+
// per-project URL over the global default. Every project
|
|
145
|
+
// after the first uses a distinct port, so silently reading
|
|
146
|
+
// the global default routed bridge traffic to the wrong AC
|
|
147
|
+
// instance.
|
|
148
|
+
assert.equal(
|
|
149
|
+
resolveProjectAgentchattrUrl(
|
|
150
|
+
{ agentchattr_url: "http://127.0.0.1:8300" },
|
|
151
|
+
{ id: "quadwork", agentchattr_url: "http://127.0.0.1:8301" },
|
|
152
|
+
),
|
|
153
|
+
"http://127.0.0.1:8301",
|
|
154
|
+
);
|
|
155
|
+
// Falls back to global default when the project has no URL of
|
|
156
|
+
// its own (legacy single-project installs).
|
|
157
|
+
assert.equal(
|
|
158
|
+
resolveProjectAgentchattrUrl(
|
|
159
|
+
{ agentchattr_url: "http://127.0.0.1:8300" },
|
|
160
|
+
{ id: "legacy" },
|
|
161
|
+
),
|
|
162
|
+
"http://127.0.0.1:8300",
|
|
163
|
+
);
|
|
164
|
+
// Hard-coded fallback when neither is set.
|
|
165
|
+
assert.equal(
|
|
166
|
+
resolveProjectAgentchattrUrl({}, {}),
|
|
167
|
+
"http://127.0.0.1:8300",
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
// 13) #383 Bug 2: buildTelegramBridgeToml writes agentchattr_url
|
|
171
|
+
// inside [telegram]. The upstream bridge's load_config only
|
|
172
|
+
// reads from that section — a separate [agentchattr] section
|
|
173
|
+
// is silently ignored and the bridge falls back to its
|
|
174
|
+
// hardcoded :8300 default.
|
|
175
|
+
const toml13 = buildTelegramBridgeToml({
|
|
176
|
+
bot_token: "123:abc",
|
|
177
|
+
chat_id: "-42",
|
|
178
|
+
agentchattr_url: "http://127.0.0.1:8301",
|
|
179
|
+
});
|
|
180
|
+
assert.match(toml13, /^\[telegram\]/);
|
|
181
|
+
assert.match(toml13, /bot_token = "123:abc"/);
|
|
182
|
+
assert.match(toml13, /chat_id = "-42"/);
|
|
183
|
+
assert.match(toml13, /agentchattr_url = "http:\/\/127\.0\.0\.1:8301"/);
|
|
184
|
+
// Must NOT emit a separate [agentchattr] section — the bridge
|
|
185
|
+
// would silently ignore it.
|
|
186
|
+
assert.equal(toml13.includes("\n[agentchattr]\n"), false);
|
|
187
|
+
|
|
188
|
+
// 14) #383 Bug 3: patchAgentchattrConfigForTelegramBridge is
|
|
189
|
+
// idempotent. The Install Bridge migration may run multiple
|
|
190
|
+
// times; it must not duplicate the section or corrupt the
|
|
191
|
+
// file.
|
|
192
|
+
const baseConfig =
|
|
193
|
+
"[agents.head]\nlabel = \"Head\"\n\n[agents.dev]\nlabel = \"Dev\"\n";
|
|
194
|
+
const first = patchAgentchattrConfigForTelegramBridge(baseConfig);
|
|
195
|
+
assert.equal(first.changed, true);
|
|
196
|
+
assert.match(first.text, /^\[agents\.telegram-bridge\]$/m);
|
|
197
|
+
assert.match(first.text, /label = "Telegram Bridge"/);
|
|
198
|
+
// Running a second time is a no-op.
|
|
199
|
+
const second = patchAgentchattrConfigForTelegramBridge(first.text);
|
|
200
|
+
assert.equal(second.changed, false);
|
|
201
|
+
assert.equal(second.text, first.text);
|
|
202
|
+
// A config that was hand-patched during diagnosis is recognized
|
|
203
|
+
// as already-correct — do not clobber the operator's edit.
|
|
204
|
+
const handPatched =
|
|
205
|
+
baseConfig + "\n[agents.telegram-bridge]\nlabel = \"Telegram Bridge\"\n";
|
|
206
|
+
const third = patchAgentchattrConfigForTelegramBridge(handPatched);
|
|
207
|
+
assert.equal(third.changed, false);
|
|
208
|
+
assert.equal(third.text, handPatched);
|
|
209
|
+
|
|
210
|
+
// 15) #383 Bug 4: buildTelegramBridgeSpawnEnv strips the three
|
|
211
|
+
// env vars the upstream bridge treats as higher-precedence
|
|
212
|
+
// than TOML. Without this, an operator shell that exported a
|
|
213
|
+
// different bot's token (common on machines running AC2)
|
|
214
|
+
// silently overrode the QuadWork-written TOML and the bridge
|
|
215
|
+
// ran as the wrong identity.
|
|
216
|
+
const scrubbed = buildTelegramBridgeSpawnEnv({
|
|
217
|
+
PATH: "/usr/bin",
|
|
218
|
+
HOME: "/home/op",
|
|
219
|
+
TELEGRAM_BOT_TOKEN: "wrong-token",
|
|
220
|
+
TELEGRAM_CHAT_ID: "-999",
|
|
221
|
+
AGENTCHATTR_URL: "http://127.0.0.1:9999",
|
|
222
|
+
});
|
|
223
|
+
assert.equal(scrubbed.TELEGRAM_BOT_TOKEN, undefined);
|
|
224
|
+
assert.equal(scrubbed.TELEGRAM_CHAT_ID, undefined);
|
|
225
|
+
assert.equal(scrubbed.AGENTCHATTR_URL, undefined);
|
|
226
|
+
// Non-telegram keys must pass through untouched — the bridge
|
|
227
|
+
// still needs PATH/HOME/etc. to find python and open files.
|
|
228
|
+
assert.equal(scrubbed.PATH, "/usr/bin");
|
|
229
|
+
assert.equal(scrubbed.HOME, "/home/op");
|
|
230
|
+
|
|
231
|
+
console.log(
|
|
232
|
+
"routes.telegramBridge.test.js: all assertions passed (15 cases" +
|
|
233
|
+
(venvSkipped ? ", case 11 pip step skipped" : "") +
|
|
234
|
+
")",
|
|
235
|
+
);
|
|
93
236
|
} finally {
|
|
94
237
|
try { fs.rmSync(tmp, { recursive: true, force: true }); } catch {}
|
|
95
238
|
}
|
package/templates/config.toml
CHANGED
|
@@ -37,6 +37,14 @@ cwd = "{{dev_cwd}}"
|
|
|
37
37
|
color = "#da7756"
|
|
38
38
|
label = "Dev Builder"
|
|
39
39
|
|
|
40
|
+
# #383: AC's registry rejects bases not declared in config.toml.
|
|
41
|
+
# The Telegram bridge registers as `telegram-bridge`, so every
|
|
42
|
+
# per-project AC config must declare it. The bridge has no
|
|
43
|
+
# command/cwd of its own — it is a long-running external client
|
|
44
|
+
# that posts to AC's HTTP API.
|
|
45
|
+
[agents.telegram-bridge]
|
|
46
|
+
label = "Telegram Bridge"
|
|
47
|
+
|
|
40
48
|
[routing]
|
|
41
49
|
default = "none"
|
|
42
50
|
max_agent_hops = 30
|
|
File without changes
|
|
File without changes
|
|
File without changes
|