@agent-native/core 0.7.6 → 0.7.10

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.
@@ -66,6 +66,18 @@ export type ResourceScope = "personal" | "shared" | "all";
66
66
  export declare function withMcpServersFolder(tree: TreeNode[], servers: McpServer[], opts?: {
67
67
  alwaysShow?: boolean;
68
68
  }): TreeNode[];
69
+ /**
70
+ * Group top-level `scripts/` and `tasks/` folders into a virtual
71
+ * `agent-scratch/` folder.
72
+ *
73
+ * The agent occasionally writes scratch scripts and task notes to the
74
+ * resources store while working through a request. These aren't user
75
+ * content — they're agent machinery — and they clutter the top of the
76
+ * personal tree. Grouping them under a single clearly-labeled folder
77
+ * keeps them visible (so the user can inspect or delete) without making
78
+ * them look like first-class personal files.
79
+ */
80
+ export declare function withAgentScratchFolder(tree: TreeNode[]): TreeNode[];
69
81
  export declare function useResources(scope?: ResourceScope): import("@tanstack/react-query").UseQueryResult<ResourceMeta[], Error>;
70
82
  export declare function useResourceTree(scope?: ResourceScope): import("@tanstack/react-query").UseQueryResult<TreeNode[], Error>;
71
83
  export declare function useResource(id: string | null): import("@tanstack/react-query").UseQueryResult<Resource, Error>;
@@ -1 +1 @@
1
- {"version":3,"file":"use-resources.d.ts","sourceRoot":"","sources":["../../../src/client/resources/use-resources.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,IAAI,kBAAkB,EAClC,aAAa,EACd,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG,YAAY,CAAC;AAE7D,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,kDAAkD;IAClD,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,kEAAkE;IAClE,aAAa,CAAC,EAAE,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE1D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,QAAQ,EAAE,EAChB,OAAO,EAAE,SAAS,EAAE,EACpB,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9B,QAAQ,EAAE,CAqDZ;AAQD,wBAAgB,YAAY,CAAC,KAAK,GAAE,aAA0B,yEAU7D;AAED,wBAAgB,eAAe,CAAC,KAAK,GAAE,aAA0B,qEAUhE;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,mEAM5C;AAED,wBAAgB,iBAAiB;UAIrB,MAAM;cACF,MAAM;eACL,MAAM;aACR,OAAO;YAcrB;AAED,wBAAgB,iBAAiB;QAOvB,MAAM;cACA,MAAM;WACT,MAAM;eACF,MAAM;YAetB;AAED,wBAAgB,iBAAiB,oFAahC;AAED,wBAAgB,iBAAiB,0FAehC"}
1
+ {"version":3,"file":"use-resources.d.ts","sourceRoot":"","sources":["../../../src/client/resources/use-resources.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,IAAI,kBAAkB,EAClC,aAAa,EACd,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG,YAAY,CAAC;AAE7D,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,kDAAkD;IAClD,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,kEAAkE;IAClE,aAAa,CAAC,EAAE,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE1D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,QAAQ,EAAE,EAChB,OAAO,EAAE,SAAS,EAAE,EACpB,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GAC9B,QAAQ,EAAE,CAqDZ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAyBnE;AAQD,wBAAgB,YAAY,CAAC,KAAK,GAAE,aAA0B,yEAU7D;AAED,wBAAgB,eAAe,CAAC,KAAK,GAAE,aAA0B,qEAUhE;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,mEAM5C;AAED,wBAAgB,iBAAiB;UAIrB,MAAM;cACF,MAAM;eACL,MAAM;aACR,OAAO;YAcrB;AAED,wBAAgB,iBAAiB;QAOvB,MAAM;cACA,MAAM;WACT,MAAM;eACF,MAAM;YAetB;AAED,wBAAgB,iBAAiB,oFAahC;AAED,wBAAgB,iBAAiB,0FAehC"}
@@ -62,6 +62,45 @@ export function withMcpServersFolder(tree, servers, opts) {
62
62
  void now;
63
63
  return [...foldersFirst, ...files];
64
64
  }
65
+ /**
66
+ * Group top-level `scripts/` and `tasks/` folders into a virtual
67
+ * `agent-scratch/` folder.
68
+ *
69
+ * The agent occasionally writes scratch scripts and task notes to the
70
+ * resources store while working through a request. These aren't user
71
+ * content — they're agent machinery — and they clutter the top of the
72
+ * personal tree. Grouping them under a single clearly-labeled folder
73
+ * keeps them visible (so the user can inspect or delete) without making
74
+ * them look like first-class personal files.
75
+ */
76
+ export function withAgentScratchFolder(tree) {
77
+ const scratch = [];
78
+ const rest = [];
79
+ for (const n of tree) {
80
+ if (n.type === "folder" && (n.name === "scripts" || n.name === "tasks")) {
81
+ scratch.push(n);
82
+ }
83
+ else {
84
+ rest.push(n);
85
+ }
86
+ }
87
+ if (scratch.length === 0)
88
+ return tree;
89
+ const folder = {
90
+ name: "agent-scratch",
91
+ path: "agent-scratch",
92
+ type: "folder",
93
+ children: scratch,
94
+ };
95
+ const folders = [];
96
+ const files = [];
97
+ for (const n of rest) {
98
+ (n.type === "folder" ? folders : files).push(n);
99
+ }
100
+ folders.push(folder);
101
+ folders.sort((a, b) => a.name.localeCompare(b.name));
102
+ return [...folders, ...files];
103
+ }
65
104
  async function fetchJson(url) {
66
105
  const res = await fetch(url);
67
106
  if (!res.ok)
@@ -1 +1 @@
1
- {"version":3,"file":"use-resources.js","sourceRoot":"","sources":["../../../src/client/resources/use-resources.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-resources.js","sourceRoot":"","sources":["../../../src/client/resources/use-resources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAgE9E;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAgB,EAChB,OAAoB,EACpB,IAA+B;IAE/B,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,KAAK,CAAC;IAC7C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAErD,sEAAsE;IACtE,wEAAwE;IACxE,kCAAkC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAC1D,CAAC;IAEF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAe,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,IAAI,OAAO,CAAC;QAC1C,OAAO;YACL,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,OAAO;YACtB,IAAI;YACJ,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,YAAY;YAClB,aAAa,EAAE,CAAC;YAChB,QAAQ,EAAE;gBACR,EAAE,EAAE,SAAS;gBACb,IAAI;gBACJ,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,CAAC;gBACP,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,SAAS,EAAE,CAAC,CAAC,SAAS;aACvB;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAa;QACvB,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,QAAQ;QACd,QAAQ;KACT,CAAC;IAEF,6EAA6E;IAC7E,+DAA+D;IAC/D,MAAM,YAAY,GAAe,EAAE,CAAC;IACpC,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,yEAAyE;IACzE,+DAA+D;IAC/D,KAAK,GAAG,CAAC;IACT,OAAO,CAAC,GAAG,YAAY,EAAE,GAAG,KAAK,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAgB;IACrD,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,MAAM,IAAI,GAAe,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACf,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,MAAM,GAAa;QACvB,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,OAAO;KAClB,CAAC;IACF,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,KAAK,UAAU,SAAS,CAAI,GAAW;IACrC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,KAAK,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;IAC1E,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAuB,UAAU;IAC5D,OAAO,QAAQ,CAAiB;QAC9B,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC;QACtC,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,IAAI,GAAG,MAAM,SAAS,CAC1B,kCAAkC,KAAK,EAAE,CAC1C,CAAC;YACF,OAAO,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;QAC9B,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAuB,UAAU;IAC/D,OAAO,QAAQ,CAAa;QAC1B,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC;QACtC,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,IAAI,GAAG,MAAM,SAAS,CAC1B,uCAAuC,KAAK,EAAE,CAC/C,CAAC;YACF,OAAO,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QACzB,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAiB;IAC3C,OAAO,QAAQ,CAAW;QACxB,QAAQ,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC;QAC1B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,4BAA4B,EAAE,EAAE,CAAC;QAC1D,OAAO,EAAE,CAAC,CAAC,EAAE;KACd,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,KAAK,EAAE,IAKlB,EAAE,EAAE;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,0BAA0B,EAAE;gBAClD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YACjE,OAAO,GAAG,CAAC,IAAI,EAAuB,CAAC;QACzC,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,KAAK,EAAE,EACjB,EAAE,EACF,GAAG,IAAI,EAMR,EAAE,EAAE;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,4BAA4B,EAAE,EAAE,EAAE;gBACxD,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YACjE,OAAO,GAAG,CAAC,IAAI,EAAuB,CAAC;QACzC,CAAC;QACD,SAAS,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE;YAC9B,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;YAC3D,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC1E,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,KAAK,EAAE,EAAU,EAAE,EAAE;YAC/B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,4BAA4B,EAAE,EAAE,EAAE;gBACxD,MAAM,EAAE,QAAQ;aACjB,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,WAAW,CAAC;QACjB,UAAU,EAAE,KAAK,EAAE,QAAkB,EAAE,EAAE;YACvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,iCAAiC,EAAE;gBACzD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,QAAQ;aACf,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YACjE,OAAO,GAAG,CAAC,IAAI,EAAuB,CAAC;QACzC,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-chat-plugin.d.ts","sourceRoot":"","sources":["../../src/server/agent-chat-plugin.ts"],"names":[],"mappings":"AAGA,OAAO,EASL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,gBAAgB,EAUjB,MAAM,wBAAwB,CAAC;AAkiChC,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9D,MAAM,WAAW,sBAAsB;IACrC,+DAA+D;IAC/D,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,CAAC,MACG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAC9C,wCAAwC;IACxC,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,CAAC,MACG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAC9C,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,EACH,OAAO,0BAA0B,EAAE,WAAW,GAC9C,MAAM,GACN;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IACtD,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,gBAAgB,CAAC,EACb,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAC/B,CAAC,MACG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAClD,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtE;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,CACb,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,MAAM,KACV,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5C;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAkgBD,wBAAgB,qBAAqB,CACnC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,cAAc,CAivDhB;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,cAAwC,CAAC;AAa9E,yEAAyE;AACzE,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,IAAI,CAE7D"}
1
+ {"version":3,"file":"agent-chat-plugin.d.ts","sourceRoot":"","sources":["../../src/server/agent-chat-plugin.ts"],"names":[],"mappings":"AAGA,OAAO,EASL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,gBAAgB,EAUjB,MAAM,wBAAwB,CAAC;AAoiChC,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9D,MAAM,WAAW,sBAAsB;IACrC,+DAA+D;IAC/D,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,CAAC,MACG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAC9C,wCAAwC;IACxC,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,CAAC,MACG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAC9C,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,EACH,OAAO,0BAA0B,EAAE,WAAW,GAC9C,MAAM,GACN;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IACtD,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,gBAAgB,CAAC,EACb,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAC/B,CAAC,MACG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAC/B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAClD,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtE;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,CACb,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,MAAM,KACV,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5C;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAogBD,wBAAgB,qBAAqB,CACnC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,cAAc,CA00DhB;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,cAAwC,CAAC;AAa9E,yEAAyE;AACzE,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,IAAI,CAE7D"}
@@ -10,7 +10,7 @@ import { buildAssistantMessage, extractThreadMeta, } from "../agent/thread-data-
10
10
  import { defineEventHandler, setResponseStatus, setResponseHeader, getMethod, getQuery, getHeader, } from "h3";
11
11
  import { getSession } from "./auth.js";
12
12
  import { getOrigin } from "./google-oauth.js";
13
- import { createThread, getThread, listThreads, searchThreads, updateThreadData, deleteThread, } from "../chat-threads/store.js";
13
+ import { createThread, getThread, listThreads, searchThreads, updateThreadData, withThreadDataLock, deleteThread, setThreadQueuedMessages, } from "../chat-threads/store.js";
14
14
  import { resourceListAccessible, resourceList, resourceGet, resourceGetByPath, ensurePersonalDefaults, SHARED_OWNER, } from "../resources/store.js";
15
15
  import nodePath from "node:path";
16
16
  import { readBody } from "./h3-helpers.js";
@@ -907,6 +907,8 @@ Resources can be personal (per-user) or shared (team-wide). By default, resource
907
907
 
908
908
  When the user gives instructions that should apply to all users/sessions, update the shared "AGENTS.md" resource.
909
909
 
910
+ **Resources are NOT an agent scratchpad.** Never use \`resource-write\` to store executable scripts, task plans, retry notes, or work-in-progress files you're writing to yourself. Specifically, do NOT create resources under \`scripts/\` or \`tasks/\` unless the user explicitly asked for a file at that path, or a tool (like \`create-job\` or \`spawn-task\`) writes there as part of its contract. If you can't complete a task with the tools you have, say so — don't improvise by leaving behind \`FINAL-*.md\`, \`EXECUTE-NOW-*.js\`, or similar artifacts. Resources are visible to the user in the workspace sidebar; every file you write is something they'll see and have to clean up.
911
+
910
912
  ### Navigation Rule
911
913
 
912
914
  When the user says "show me", "go to", "open", "switch to", or similar navigation language, ALWAYS use the \`navigate\` action to update the UI. The user expects to SEE the result in the main app, not just read it in chat. Navigate first, then fetch/display data.
@@ -1357,6 +1359,22 @@ export function createAgentChatPlugin(options) {
1357
1359
  // this, requests can race ahead of the bootstrap and hit the SSR catch-all.
1358
1360
  const { awaitBootstrap } = await import("./framework-request-handler.js");
1359
1361
  await awaitBootstrap(nitroApp);
1362
+ // Reap phantom runs left over from the previous process (HMR restart,
1363
+ // process crash, isolate eviction). Any run whose heartbeat is already
1364
+ // stale by startup time had a dead producer; mark it errored so the
1365
+ // next /runs/active check returns a terminal status and reconnecting
1366
+ // clients don't spin on "Thinking...". Runs owned by OTHER live
1367
+ // isolates are protected by their fresh heartbeats.
1368
+ try {
1369
+ const { reapAllStaleRuns } = await import("../agent/run-store.js");
1370
+ const reaped = await reapAllStaleRuns();
1371
+ if (reaped > 0) {
1372
+ console.log(`[agent-chat] reaped ${reaped} stale run(s) on startup`);
1373
+ }
1374
+ }
1375
+ catch {
1376
+ // Best effort — don't block plugin init if SQL isn't ready yet.
1377
+ }
1360
1378
  const env = process.env.NODE_ENV;
1361
1379
  // AGENT_MODE=production forces production agent constraints even in dev
1362
1380
  const canToggle = (env === "development" || env === "test") &&
@@ -1891,53 +1909,71 @@ export function createAgentChatPlugin(options) {
1891
1909
  const onRunComplete = async (run, threadId) => {
1892
1910
  if (!threadId)
1893
1911
  return;
1894
- try {
1895
- const thread = await getThread(threadId);
1896
- if (!thread)
1897
- return;
1898
- const assistantMsg = buildAssistantMessage(run.events ?? [], run.runId);
1899
- if (!assistantMsg) {
1900
- // No content produced — just bump timestamp
1901
- await updateThreadData(threadId, thread.threadData, thread.title, thread.preview, thread.messageCount);
1902
- return;
1903
- }
1904
- // Parse existing thread_data, append assistant message only if
1905
- // the frontend hasn't already saved it (avoids duplicates when
1906
- // the client is still connected during a normal flow).
1907
- let repo;
1912
+ // Serialize the read-modify-write against the same thread's other
1913
+ // `thread_data` writers (setThreadQueuedMessages, setThreadEngineMeta,
1914
+ // the frontend-triggered saves below). Without the lock, a concurrent
1915
+ // queued-message save can clobber the assistant message we just
1916
+ // appended here, or vice versa.
1917
+ await withThreadDataLock(threadId, async () => {
1908
1918
  try {
1909
- repo = JSON.parse(thread.threadData || "{}");
1919
+ const thread = await getThread(threadId);
1920
+ if (!thread)
1921
+ return;
1922
+ const assistantMsg = buildAssistantMessage(run.events ?? [], run.runId);
1923
+ if (!assistantMsg) {
1924
+ // No content produced — just bump timestamp
1925
+ await updateThreadData(threadId, thread.threadData, thread.title, thread.preview, thread.messageCount);
1926
+ return;
1927
+ }
1928
+ // Parse existing thread_data, append assistant message only if
1929
+ // the frontend hasn't already saved it (avoids duplicates when
1930
+ // the client is still connected during a normal flow).
1931
+ let repo;
1932
+ try {
1933
+ repo = JSON.parse(thread.threadData || "{}");
1934
+ }
1935
+ catch {
1936
+ repo = {};
1937
+ }
1938
+ if (!Array.isArray(repo.messages))
1939
+ repo.messages = [];
1940
+ const lastMsg = repo.messages[repo.messages.length - 1];
1941
+ // Check both wrapped ({ message: { role } }) and unwrapped ({ role }) formats
1942
+ const lastRole = lastMsg?.message?.role ?? lastMsg?.role;
1943
+ const lastContent = lastMsg?.message?.content ?? lastMsg?.content;
1944
+ const lastContentIsEmpty = Array.isArray(lastContent)
1945
+ ? lastContent.length === 0
1946
+ : lastContent == null || lastContent === "";
1947
+ if (lastRole === "assistant" && !lastContentIsEmpty) {
1948
+ // Frontend already saved the assistant response — just bump timestamp
1949
+ await updateThreadData(threadId, thread.threadData, thread.title, thread.preview, thread.messageCount);
1950
+ return;
1951
+ }
1952
+ if (lastRole === "assistant" && lastContentIsEmpty) {
1953
+ // The frontend wrote an empty assistant placeholder before the stream
1954
+ // had any content (common when the user reloads mid-run, and the 5s
1955
+ // periodic save raced with the first text chunk). Replace it with
1956
+ // the server's reconstructed message so the turn isn't lost.
1957
+ repo.messages.pop();
1958
+ }
1959
+ // Determine if repo uses wrapped format ({ message, parentId }) or flat format
1960
+ const isWrapped = lastMsg && "message" in lastMsg;
1961
+ if (isWrapped) {
1962
+ const parentId = repo.messages.length > 0
1963
+ ? (repo.messages[repo.messages.length - 1].message?.id ?? null)
1964
+ : null;
1965
+ repo.messages.push({ message: assistantMsg, parentId });
1966
+ }
1967
+ else {
1968
+ repo.messages.push(assistantMsg);
1969
+ }
1970
+ const meta = extractThreadMeta(repo);
1971
+ await updateThreadData(threadId, JSON.stringify(repo), meta.title || thread.title, meta.preview || thread.preview, repo.messages.length);
1910
1972
  }
1911
1973
  catch {
1912
- repo = {};
1974
+ // Best-effort — don't break cleanup
1913
1975
  }
1914
- if (!Array.isArray(repo.messages))
1915
- repo.messages = [];
1916
- const lastMsg = repo.messages[repo.messages.length - 1];
1917
- // Check both wrapped ({ message: { role } }) and unwrapped ({ role }) formats
1918
- const lastRole = lastMsg?.message?.role ?? lastMsg?.role;
1919
- if (lastRole === "assistant") {
1920
- // Frontend already saved the assistant response — just bump timestamp
1921
- await updateThreadData(threadId, thread.threadData, thread.title, thread.preview, thread.messageCount);
1922
- return;
1923
- }
1924
- // Determine if repo uses wrapped format ({ message, parentId }) or flat format
1925
- const isWrapped = lastMsg && "message" in lastMsg;
1926
- if (isWrapped) {
1927
- const parentId = repo.messages.length > 0
1928
- ? (repo.messages[repo.messages.length - 1].message?.id ?? null)
1929
- : null;
1930
- repo.messages.push({ message: assistantMsg, parentId });
1931
- }
1932
- else {
1933
- repo.messages.push(assistantMsg);
1934
- }
1935
- const meta = extractThreadMeta(repo);
1936
- await updateThreadData(threadId, JSON.stringify(repo), meta.title || thread.title, meta.preview || thread.preview, repo.messages.length);
1937
- }
1938
- catch {
1939
- // Best-effort — don't break cleanup
1940
- }
1976
+ });
1941
1977
  };
1942
1978
  // ─── Agent Teams: per-run send reference ─────────────────────────
1943
1979
  // Team tools need to emit events to the parent chat's SSE stream.
@@ -2678,6 +2714,7 @@ export function createAgentChatPlugin(options) {
2678
2714
  runId: run.runId,
2679
2715
  threadId: run.threadId,
2680
2716
  status: run.status,
2717
+ heartbeatAt: run.heartbeatAt,
2681
2718
  };
2682
2719
  }
2683
2720
  setResponseStatus(event, 405);
@@ -2711,13 +2748,60 @@ export function createAgentChatPlugin(options) {
2711
2748
  return thread;
2712
2749
  }
2713
2750
  if (method === "PUT") {
2751
+ // Hold the thread_data lock for the full read-modify-write so
2752
+ // periodic saves from the frontend don't race with
2753
+ // onRunComplete / setThreadQueuedMessages / setThreadEngineMeta.
2754
+ // Without the lock, a client save that lands during an agent
2755
+ // run could clobber the assistant message the server just
2756
+ // appended (and vice versa).
2757
+ return await withThreadDataLock(threadId, async () => {
2758
+ const thread = await getThread(threadId);
2759
+ if (!thread || thread.ownerEmail !== owner) {
2760
+ setResponseStatus(event, 404);
2761
+ return { error: "Thread not found" };
2762
+ }
2763
+ const body = await readBody(event);
2764
+ let newThreadData = body.threadData || thread.threadData;
2765
+ // Preserve queuedMessages from the existing thread_data when the
2766
+ // incoming blob doesn't include it. Periodic full-thread saves
2767
+ // (exported via threadRuntime.export) don't carry the queue, and
2768
+ // we don't want them to clobber queued-message state persisted
2769
+ // via POST /threads/:id/queued.
2770
+ if (body.threadData) {
2771
+ try {
2772
+ const existing = JSON.parse(thread.threadData);
2773
+ if (existing.queuedMessages !== undefined) {
2774
+ const incoming = JSON.parse(newThreadData);
2775
+ if (incoming.queuedMessages === undefined) {
2776
+ incoming.queuedMessages = existing.queuedMessages;
2777
+ newThreadData = JSON.stringify(incoming);
2778
+ }
2779
+ }
2780
+ }
2781
+ catch {
2782
+ // Invalid JSON in either side — fall back to raw body blob.
2783
+ }
2784
+ }
2785
+ await updateThreadData(threadId, newThreadData, body.title ?? thread.title, body.preview ?? thread.preview, body.messageCount || thread.messageCount);
2786
+ return { ok: true };
2787
+ });
2788
+ }
2789
+ // POST /threads/:id/queued — debounced writes from the client
2790
+ // when the user adds/removes/dequeues a queued message. Keeps
2791
+ // queued messages durable across reloads without piggybacking
2792
+ // on full-thread saves.
2793
+ if (method === "POST" &&
2794
+ /\/threads\/[^/?]+\/queued/.test(event.node?.req?.url || event.path || "")) {
2714
2795
  const thread = await getThread(threadId);
2715
2796
  if (!thread || thread.ownerEmail !== owner) {
2716
2797
  setResponseStatus(event, 404);
2717
2798
  return { error: "Thread not found" };
2718
2799
  }
2719
2800
  const body = await readBody(event);
2720
- await updateThreadData(threadId, body.threadData || thread.threadData, body.title ?? thread.title, body.preview ?? thread.preview, body.messageCount || thread.messageCount);
2801
+ const queued = Array.isArray(body?.queuedMessages)
2802
+ ? body.queuedMessages
2803
+ : [];
2804
+ await setThreadQueuedMessages(threadId, queued);
2721
2805
  return { ok: true };
2722
2806
  }
2723
2807
  if (method === "DELETE") {