@lazyingart/agintiflow 0.20.194 → 0.20.195

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazyingart/agintiflow",
3
- "version": "0.20.194",
3
+ "version": "0.20.195",
4
4
  "type": "module",
5
5
  "description": "AgInTiFlow is a project-aware agent workspace for hybrid wet-dry R&D, hardware-aware intelligence, software automation, and industrial workflows.",
6
6
  "license": "Apache-2.0",
package/src/agentlink.js CHANGED
@@ -4,6 +4,7 @@ import path from "node:path";
4
4
  import crypto from "node:crypto";
5
5
  import { agintiflowHome, globalSessionPaths, isSafeSessionId, listSessionIndex } from "./session-index.js";
6
6
  import { SessionStore } from "./session-store.js";
7
+ import { redactSensitiveText } from "./redaction.js";
7
8
 
8
9
  export const AGENTLINK_TOOL_NAMES = [
9
10
  "agentlink_status",
@@ -29,6 +30,18 @@ function safeText(value = "", limit = MAX_TEXT_BYTES) {
29
30
  return `${Buffer.from(text, "utf8").subarray(0, Math.max(limit - 40, 1)).toString("utf8").trim()}\n... [truncated]`;
30
31
  }
31
32
 
33
+ function safeEvidenceText(value = "", limit = 1200) {
34
+ return safeText(redactSensitiveText(value), limit);
35
+ }
36
+
37
+ function stripBalancedQuotes(value = "") {
38
+ const text = String(value || "").trim();
39
+ if (text.length >= 2 && ((text.startsWith('"') && text.endsWith('"')) || (text.startsWith("'") && text.endsWith("'")))) {
40
+ return text.slice(1, -1).trim();
41
+ }
42
+ return text;
43
+ }
44
+
32
45
  function safeId(value = "", fallbackPrefix = "agentlink") {
33
46
  const text = String(value || "")
34
47
  .trim()
@@ -456,6 +469,16 @@ export async function summarizeAgentLinkSession({ sessionId = "", eventLimit = 2
456
469
  } catch {
457
470
  artifacts = [];
458
471
  }
472
+ const recentChanges = events
473
+ .filter((event) => event.type === "file.changed" && event.data?.path)
474
+ .slice(-10)
475
+ .map((event) => ({
476
+ timestamp: event.timestamp,
477
+ path: safeEvidenceText(event.data.path, 500),
478
+ action: safeEvidenceText(event.data.action || "", 120),
479
+ afterHash: safeEvidenceText(event.data.afterHash || "", 120),
480
+ diff: safeEvidenceText(event.data.diff || "", 1200),
481
+ }));
459
482
  return {
460
483
  ok: true,
461
484
  sessionId: id,
@@ -476,6 +499,7 @@ export async function summarizeAgentLinkSession({ sessionId = "", eventLimit = 2
476
499
  toolName: event.data?.toolName || "",
477
500
  status: event.data?.status || "",
478
501
  })),
502
+ recentChanges,
479
503
  artifacts,
480
504
  },
481
505
  paths: {
@@ -636,10 +660,19 @@ export async function agentLinkCliCommand(argv = [], { cwd = process.cwd() } = {
636
660
  return { ok: true, boards: await listAgentLinkBoards({ limit: options.limit || 50, projectRoot: options.project || "" }, runtimeOptions) };
637
661
  }
638
662
  if (command === "create" || command === "new") {
663
+ let boardId = options.id || options.board || "";
664
+ let title = options.title || positionals.join(" ") || "";
665
+ if (!boardId && positionals.length >= 2 && /^[A-Za-z0-9._:-]*[-_.:][A-Za-z0-9._:-]*$/.test(positionals[0] || "")) {
666
+ boardId = positionals[0];
667
+ title = positionals.slice(1).join(" ");
668
+ } else if (!boardId && positionals.length === 1 && /^[A-Za-z0-9._:-]*[-_.:][A-Za-z0-9._:-]*$/.test(positionals[0] || "")) {
669
+ boardId = positionals[0];
670
+ title = positionals[0];
671
+ }
639
672
  return createAgentLinkBoard(
640
673
  {
641
- boardId: options.id || options.board || "",
642
- title: options.title || positionals.join(" ") || "",
674
+ boardId,
675
+ title,
643
676
  objective: options.objective || "",
644
677
  projectRoot: options.project || cwd,
645
678
  sessionId: options.session || "",
@@ -653,7 +686,7 @@ export async function agentLinkCliCommand(argv = [], { cwd = process.cwd() } = {
653
686
  if (command === "send" || command === "message") {
654
687
  const boardId = options.board || positionals.shift() || "default";
655
688
  const toSessionId = options["to-session"] || options.session || positionals.shift() || "";
656
- const content = options.content || positionals.join(" ");
689
+ const content = stripBalancedQuotes(options.content || positionals.join(" "));
657
690
  return sendAgentLinkMessage(
658
691
  { boardId, toSessionId, toNodeId: options["to-node"] || "", content, kind: options.kind || "message", priority: options.priority || "normal" },
659
692
  runtimeOptions
@@ -531,6 +531,71 @@ function mockLongJobToolForGoal(goal = "") {
531
531
  });
532
532
  }
533
533
 
534
+ function isMockAgentLinkGoal(goal = "") {
535
+ const text = String(goal || "");
536
+ if (
537
+ /\b(?:create|write|save|generate)\b/i.test(text) &&
538
+ /(?:[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+|[A-Za-z0-9_.-]+\.(?:md|txt|js|ts|json|py|tex|html|css|svg|csv|yml|yaml))/.test(text)
539
+ ) {
540
+ return false;
541
+ }
542
+ return /\b(agentlink|agent link|peer session|other session|another session|session context|shared context|inbox|handoff|collaborat(?:e|ion)|coordinate)\b/i.test(
543
+ text
544
+ );
545
+ }
546
+
547
+ function mockAgentLinkToolForGoal(goal = "") {
548
+ const text = String(goal || "");
549
+ if (!isMockAgentLinkGoal(text)) return null;
550
+ if (/\b(status|health|diagnose|diagnostic)\b/i.test(text) && !/\b(peer|session|context|other|another|shared)\b/i.test(text)) {
551
+ return mockToolCall("agentlink_status", {});
552
+ }
553
+ if (/\b(board|messages?|evidence|contract)\b/i.test(text) && /\b(read|show|get|list)\b/i.test(text)) {
554
+ const boardId = text.match(/\bboard\s+([A-Za-z0-9._:-]+)/i)?.[1] || "default";
555
+ return mockToolCall("agentlink_get_board", { boardId, limit: 50 });
556
+ }
557
+ return mockToolCall("agentlink_list_peers", { limit: 20, includeAllSessions: true });
558
+ }
559
+
560
+ function compactComparableText(value = "") {
561
+ return String(value || "").replace(/\s+/g, " ").trim().toLowerCase();
562
+ }
563
+
564
+ function sessionPeerFromAgentLinkPayload(payload = {}, currentGoal = "") {
565
+ const peers = Array.isArray(payload.peers) ? payload.peers : [];
566
+ const sessionPeers = peers.filter((peer) => peer.kind === "session" && peer.sessionId);
567
+ if (!sessionPeers.length) return null;
568
+ const comparableGoal = compactComparableText(currentGoal);
569
+ if (comparableGoal) {
570
+ const other = sessionPeers.find((peer) => {
571
+ const label = compactComparableText(`${peer.label || ""}\n${peer.role || ""}`);
572
+ return label !== comparableGoal && !label.includes(comparableGoal.slice(0, 120));
573
+ });
574
+ if (other) return other;
575
+ }
576
+ return sessionPeers[0] || null;
577
+ }
578
+
579
+ function summarizeAgentLinkMockResult(payload = {}) {
580
+ const summary = payload.summary || {};
581
+ const changes = Array.isArray(summary.recentChanges) ? summary.recentChanges : [];
582
+ const evidence = changes
583
+ .map((change) => [change.path ? `path=${change.path}` : "", change.afterHash ? `sha256=${change.afterHash}` : "", change.diff ? `diff=${change.diff}` : ""]
584
+ .filter(Boolean)
585
+ .join("\n"))
586
+ .filter(Boolean)
587
+ .join("\n\n");
588
+ return [
589
+ `session=${payload.sessionId || ""}`,
590
+ summary.goal ? `goal=${summary.goal}` : "",
591
+ `provider=${summary.provider || ""} model=${summary.model || ""}`,
592
+ changes.length ? `recentChanges=${changes.length}` : "recentChanges=0",
593
+ evidence ? `evidence:\n${evidence}` : "",
594
+ ]
595
+ .filter(Boolean)
596
+ .join("\n");
597
+ }
598
+
534
599
  function mockPathForGoal(goal = "") {
535
600
  const text = String(goal);
536
601
  if (/\bAGINTI\.md\b|project instructions|remember (?:that|this)|durable preference/i.test(text)) return "AGINTI.md";
@@ -1839,6 +1904,26 @@ export async function requestNextStep(client, config, messages) {
1839
1904
  if (client.mock) {
1840
1905
  const toolPayload = latestToolPayload(messages);
1841
1906
  if (toolPayload) {
1907
+ if (toolPayload.toolName === "agentlink_list_peers" && isMockAgentLinkGoal(config.goal)) {
1908
+ const peer = sessionPeerFromAgentLinkPayload(toolPayload, config.goal);
1909
+ if (peer?.sessionId) {
1910
+ return mockChatResponse("Mock mode will summarize the discovered AgentLink session.", [
1911
+ mockToolCall("agentlink_summarize_session", { sessionId: peer.sessionId, eventLimit: 50 }),
1912
+ ]);
1913
+ }
1914
+ return mockChatResponse("Mock mode could not find another AgentLink session.", [
1915
+ mockToolCall("finish", {
1916
+ result: "AgentLink peer lookup completed, but no session peer was available.",
1917
+ }),
1918
+ ]);
1919
+ }
1920
+ if (toolPayload.toolName === "agentlink_summarize_session" && isMockAgentLinkGoal(config.goal)) {
1921
+ return mockChatResponse("Mock mode finished from AgentLink safe session summary.", [
1922
+ mockToolCall("finish", {
1923
+ result: summarizeAgentLinkMockResult(toolPayload),
1924
+ }),
1925
+ ]);
1926
+ }
1842
1927
  if (toolPayload.ok === false && !toolPayload.blocked) {
1843
1928
  return mockChatResponse("Mock mode detected a tool failure and will stop instead of masking it.", [
1844
1929
  mockToolCall("finish", {
@@ -1922,6 +2007,11 @@ export async function requestNextStep(client, config, messages) {
1922
2007
  ]);
1923
2008
  }
1924
2009
 
2010
+ const agentLinkTool = mockAgentLinkToolForGoal(config.goal);
2011
+ if (agentLinkTool) {
2012
+ return mockChatResponse("Mock mode will exercise AgentLink coordination tools.", [agentLinkTool]);
2013
+ }
2014
+
1925
2015
  if (config.allowAuxiliaryTools) {
1926
2016
  const auxiliaryTool = mockAuxiliaryToolForGoal(config.goal);
1927
2017
  if (auxiliaryTool) {