@rallycry/conveyor-agent 7.0.5 → 7.0.6
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.
|
@@ -9,12 +9,16 @@ import {
|
|
|
9
9
|
// src/connection/agent-connection.ts
|
|
10
10
|
import { io } from "socket.io-client";
|
|
11
11
|
var EVENT_BATCH_MS = 500;
|
|
12
|
-
var AgentConnection = class {
|
|
12
|
+
var AgentConnection = class _AgentConnection {
|
|
13
13
|
socket = null;
|
|
14
14
|
config;
|
|
15
15
|
eventBuffer = [];
|
|
16
16
|
flushTimer = null;
|
|
17
17
|
lastEmittedStatus = null;
|
|
18
|
+
// Dedup: suppress near-identical messages within a short window
|
|
19
|
+
recentMessages = [];
|
|
20
|
+
static DEDUP_WINDOW_MS = 3e4;
|
|
21
|
+
static DEDUP_SIMILARITY_THRESHOLD = 0.7;
|
|
18
22
|
// Early-buffering: events that arrive before callbacks are registered
|
|
19
23
|
earlyMessages = [];
|
|
20
24
|
earlyStop = false;
|
|
@@ -237,6 +241,7 @@ var AgentConnection = class {
|
|
|
237
241
|
// ── Convenience methods (thin wrappers around call / emit) ─────────
|
|
238
242
|
emitStatus(status) {
|
|
239
243
|
this.lastEmittedStatus = status;
|
|
244
|
+
this.flushEvents();
|
|
240
245
|
void this.call("reportAgentStatus", {
|
|
241
246
|
sessionId: this.config.sessionId,
|
|
242
247
|
status
|
|
@@ -245,12 +250,42 @@ var AgentConnection = class {
|
|
|
245
250
|
}
|
|
246
251
|
postChatMessage(content) {
|
|
247
252
|
if (!this.socket) return;
|
|
253
|
+
if (this.isDuplicateMessage(content)) {
|
|
254
|
+
process.stderr.write(`[dedup] Suppressed near-duplicate message
|
|
255
|
+
`);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
248
258
|
void this.call("postAgentMessage", {
|
|
249
259
|
sessionId: this.config.sessionId,
|
|
250
260
|
content
|
|
251
261
|
}).catch(() => {
|
|
252
262
|
});
|
|
253
263
|
}
|
|
264
|
+
isDuplicateMessage(content) {
|
|
265
|
+
const now = Date.now();
|
|
266
|
+
this.recentMessages = this.recentMessages.filter(
|
|
267
|
+
(m) => now - m.timestamp < _AgentConnection.DEDUP_WINDOW_MS
|
|
268
|
+
);
|
|
269
|
+
const words = new Set(
|
|
270
|
+
content.toLowerCase().split(/\s+/).filter((w) => w.length >= 3)
|
|
271
|
+
);
|
|
272
|
+
if (words.size === 0) return false;
|
|
273
|
+
for (const recent of this.recentMessages) {
|
|
274
|
+
let intersection = 0;
|
|
275
|
+
for (const w of words) {
|
|
276
|
+
if (recent.words.has(w)) intersection++;
|
|
277
|
+
}
|
|
278
|
+
const union = (/* @__PURE__ */ new Set([...words, ...recent.words])).size;
|
|
279
|
+
if (union > 0 && intersection / union > _AgentConnection.DEDUP_SIMILARITY_THRESHOLD) {
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
this.recentMessages.push({ words, timestamp: now });
|
|
284
|
+
if (this.recentMessages.length > 3) {
|
|
285
|
+
this.recentMessages.shift();
|
|
286
|
+
}
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
254
289
|
sendHeartbeat() {
|
|
255
290
|
if (!this.socket) return;
|
|
256
291
|
const statusMap = {
|
|
@@ -696,10 +731,12 @@ function tryPush(cwd, branch) {
|
|
|
696
731
|
}
|
|
697
732
|
function isAuthError(cwd) {
|
|
698
733
|
try {
|
|
699
|
-
execSync("git push --dry-run
|
|
734
|
+
execSync("git push --dry-run", { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
700
735
|
return false;
|
|
701
736
|
} catch (err) {
|
|
702
|
-
const
|
|
737
|
+
const stderr = err.stderr?.toString() ?? "";
|
|
738
|
+
const stdout = err.stdout?.toString() ?? "";
|
|
739
|
+
const msg = stderr || stdout || (err instanceof Error ? err.message : "");
|
|
703
740
|
return /authentication|authorization|403|401|token/i.test(msg);
|
|
704
741
|
}
|
|
705
742
|
}
|
|
@@ -2890,6 +2927,45 @@ function buildPmTools(connection, options) {
|
|
|
2890
2927
|
// src/tools/discovery-tools.ts
|
|
2891
2928
|
import { z as z3 } from "zod";
|
|
2892
2929
|
var SP_DESCRIPTION2 = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
|
|
2930
|
+
function buildSearchIconsTool(connection) {
|
|
2931
|
+
return defineTool(
|
|
2932
|
+
"search_icons",
|
|
2933
|
+
"Search for icons by keyword. Searches both the Conveyor database (existing icons) and FontAwesome library (~2200 icons). Returns matching icons with IDs and preview info. Use this to find an icon before generating one.",
|
|
2934
|
+
{
|
|
2935
|
+
query: z3.string().describe("Search query for icon name or keyword (e.g. 'bug', 'gear', 'star')")
|
|
2936
|
+
},
|
|
2937
|
+
async ({ query }) => {
|
|
2938
|
+
try {
|
|
2939
|
+
const [dbIcons, faIcons] = await Promise.all([
|
|
2940
|
+
connection.call("listIcons", { sessionId: connection.sessionId }),
|
|
2941
|
+
connection.call("searchFaIcons", { sessionId: connection.sessionId, query })
|
|
2942
|
+
]);
|
|
2943
|
+
const q = query.toLowerCase();
|
|
2944
|
+
const matchingDbIcons = dbIcons.filter((icon) => icon.name.toLowerCase().includes(q));
|
|
2945
|
+
const dbFaIds = new Set(matchingDbIcons.map((i) => i.name));
|
|
2946
|
+
const uniqueFaIcons = faIcons.filter((fa) => !dbFaIds.has(fa.fontAwesomeId));
|
|
2947
|
+
const results = {
|
|
2948
|
+
existingIcons: matchingDbIcons.map((i) => ({
|
|
2949
|
+
id: i.id,
|
|
2950
|
+
name: i.name,
|
|
2951
|
+
source: "database"
|
|
2952
|
+
})),
|
|
2953
|
+
fontAwesomeIcons: uniqueFaIcons.map((fa) => ({
|
|
2954
|
+
fontAwesomeId: fa.fontAwesomeId,
|
|
2955
|
+
label: fa.label,
|
|
2956
|
+
styles: fa.styles,
|
|
2957
|
+
source: "fontawesome"
|
|
2958
|
+
}))
|
|
2959
|
+
};
|
|
2960
|
+
return textResult(JSON.stringify(results, null, 2));
|
|
2961
|
+
} catch (error) {
|
|
2962
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
2963
|
+
return textResult(`Failed to search icons: ${message}`);
|
|
2964
|
+
}
|
|
2965
|
+
},
|
|
2966
|
+
{ annotations: { readOnlyHint: true } }
|
|
2967
|
+
);
|
|
2968
|
+
}
|
|
2893
2969
|
function buildIconTools(connection) {
|
|
2894
2970
|
return [
|
|
2895
2971
|
defineTool(
|
|
@@ -2912,10 +2988,10 @@ function buildIconTools(connection) {
|
|
|
2912
2988
|
),
|
|
2913
2989
|
defineTool(
|
|
2914
2990
|
"generate_task_icon",
|
|
2915
|
-
"
|
|
2991
|
+
"Find a FontAwesome icon matching the description and assign it to this task. Falls back to a placeholder if no match is found. Provide a concise keyword or description.",
|
|
2916
2992
|
{
|
|
2917
2993
|
prompt: z3.string().describe(
|
|
2918
|
-
"
|
|
2994
|
+
"Keyword or description to search FontAwesome icons (e.g. 'bug', 'gear', 'rocket')"
|
|
2919
2995
|
),
|
|
2920
2996
|
aspectRatio: z3.enum(["auto", "portrait", "landscape", "square"]).optional().describe("Icon aspect ratio, defaults to square")
|
|
2921
2997
|
},
|
|
@@ -2970,6 +3046,7 @@ function buildDiscoveryTools(connection) {
|
|
|
2970
3046
|
}
|
|
2971
3047
|
}
|
|
2972
3048
|
),
|
|
3049
|
+
buildSearchIconsTool(connection),
|
|
2973
3050
|
...buildIconTools(connection)
|
|
2974
3051
|
];
|
|
2975
3052
|
}
|
|
@@ -4880,6 +4957,7 @@ async function handleExitPlanMode(host, input) {
|
|
|
4880
4957
|
host.connection.postChatMessage(
|
|
4881
4958
|
"Plan complete. The task stays in Planning \u2014 identify it or switch to Build mode when ready."
|
|
4882
4959
|
);
|
|
4960
|
+
host.requestStop();
|
|
4883
4961
|
return { behavior: "allow", updatedInput: input };
|
|
4884
4962
|
}
|
|
4885
4963
|
await host.connection.triggerIdentification();
|
|
@@ -5392,6 +5470,10 @@ var QueryBridge = class {
|
|
|
5392
5470
|
this.costTracker = new CostTracker();
|
|
5393
5471
|
this.planSync = new PlanSync(workspaceDir, connection);
|
|
5394
5472
|
}
|
|
5473
|
+
connection;
|
|
5474
|
+
mode;
|
|
5475
|
+
runnerConfig;
|
|
5476
|
+
callbacks;
|
|
5395
5477
|
harness;
|
|
5396
5478
|
costTracker;
|
|
5397
5479
|
planSync;
|
|
@@ -5485,6 +5567,7 @@ var QueryBridge = class {
|
|
|
5485
5567
|
return bridge._abortController;
|
|
5486
5568
|
},
|
|
5487
5569
|
isStopped: () => bridge._stopped,
|
|
5570
|
+
requestStop: () => bridge.stop(),
|
|
5488
5571
|
createInputStream: (prompt) => bridge.createInputStream(prompt),
|
|
5489
5572
|
snapshotPlanFiles: () => bridge.planSync.snapshotPlanFiles(),
|
|
5490
5573
|
syncPlanFile: () => bridge.planSync.syncPlanFile(),
|
|
@@ -6170,6 +6253,8 @@ var CommitWatcher = class {
|
|
|
6170
6253
|
this.config = config;
|
|
6171
6254
|
this.callbacks = callbacks;
|
|
6172
6255
|
}
|
|
6256
|
+
config;
|
|
6257
|
+
callbacks;
|
|
6173
6258
|
interval = null;
|
|
6174
6259
|
lastKnownRemoteSha = null;
|
|
6175
6260
|
branch = null;
|
|
@@ -7342,4 +7427,4 @@ export {
|
|
|
7342
7427
|
loadForwardPorts,
|
|
7343
7428
|
loadConveyorConfig
|
|
7344
7429
|
};
|
|
7345
|
-
//# sourceMappingURL=chunk-
|
|
7430
|
+
//# sourceMappingURL=chunk-3H2FXJFD.js.map
|