ai-project-manage-cli 7.0.6 → 7.0.8

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.
Files changed (2) hide show
  1. package/dist/index.js +103 -28
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1853,6 +1853,61 @@ function saveMemberPlanDocument(input) {
1853
1853
  }
1854
1854
 
1855
1855
  // src/event-session.ts
1856
+ var MAX_TOOL_CALL_RESULT_BYTES = 1024 * 1024;
1857
+ function utf8ByteLength(text) {
1858
+ return Buffer.byteLength(text, "utf8");
1859
+ }
1860
+ function truncateUtf8ByBytes(text, maxBytes) {
1861
+ if (maxBytes <= 0) {
1862
+ return "";
1863
+ }
1864
+ if (utf8ByteLength(text) <= maxBytes) {
1865
+ return text;
1866
+ }
1867
+ let end = 0;
1868
+ for (let index = 0; index < text.length; index += 1) {
1869
+ if (utf8ByteLength(text.slice(0, index + 1)) > maxBytes) {
1870
+ break;
1871
+ }
1872
+ end = index + 1;
1873
+ }
1874
+ return text.slice(0, end);
1875
+ }
1876
+ function serializeToolCallResult(result) {
1877
+ return typeof result === "string" ? result : JSON.stringify(result);
1878
+ }
1879
+ function truncateToolCallResult(result) {
1880
+ if (result === void 0 || result === null) {
1881
+ return result;
1882
+ }
1883
+ const originalText = serializeToolCallResult(result);
1884
+ const originalBytes = utf8ByteLength(originalText);
1885
+ if (originalBytes <= MAX_TOOL_CALL_RESULT_BYTES) {
1886
+ return result;
1887
+ }
1888
+ const meta = {
1889
+ _apmTruncated: true,
1890
+ _apmOriginalBytes: originalBytes,
1891
+ _apmMaxBytes: MAX_TOOL_CALL_RESULT_BYTES,
1892
+ _apmMessage: "tool_call result \u8D85\u8FC7\u5E73\u53F0\u540C\u6B65\u5927\u5C0F\u4E0A\u9650\uFF0C\u4EE5\u4E0B\u5185\u5BB9\u5DF2\u622A\u65AD\uFF1B\u5B8C\u6574\u7ED3\u679C\u4EC5\u4FDD\u7559\u5728\u672C\u5730 Cursor \u8FD0\u884C\u4E2D\u3002"
1893
+ };
1894
+ let low = 0;
1895
+ let high = originalBytes;
1896
+ let content = "";
1897
+ while (low <= high) {
1898
+ const mid = Math.floor((low + high) / 2);
1899
+ const candidateContent = truncateUtf8ByBytes(originalText, mid);
1900
+ const candidate = { ...meta, content: candidateContent };
1901
+ const candidateBytes = utf8ByteLength(JSON.stringify(candidate));
1902
+ if (candidateBytes <= MAX_TOOL_CALL_RESULT_BYTES) {
1903
+ content = candidateContent;
1904
+ low = mid + 1;
1905
+ } else {
1906
+ high = mid - 1;
1907
+ }
1908
+ }
1909
+ return { ...meta, content };
1910
+ }
1856
1911
  var EventSession = class {
1857
1912
  events = [];
1858
1913
  dirtyIndices = /* @__PURE__ */ new Set();
@@ -1938,7 +1993,7 @@ var EventSession = class {
1938
1993
  return {
1939
1994
  type: "tool_call",
1940
1995
  args: event.args,
1941
- result: event.result,
1996
+ result: truncateToolCallResult(event.result),
1942
1997
  status: event.status,
1943
1998
  call_id: event.call_id,
1944
1999
  name: event.name
@@ -1958,15 +2013,26 @@ var EventSession = class {
1958
2013
  return { type: "status", status: event.status, message: event.message };
1959
2014
  }
1960
2015
  }
2016
+ getDirtyIndices() {
2017
+ return [...this.dirtyIndices].sort((a, b) => a - b);
2018
+ }
2019
+ /** 按 index 读取待同步 event(上传时取最新内容,避免 snapshot 过期)。 */
2020
+ getSyncEvent(index) {
2021
+ if (!this.dirtyIndices.has(index)) {
2022
+ return null;
2023
+ }
2024
+ const event = this.events[index];
2025
+ if (!event) {
2026
+ return null;
2027
+ }
2028
+ return {
2029
+ index,
2030
+ type: event.type,
2031
+ data: JSON.stringify(event)
2032
+ };
2033
+ }
1961
2034
  getDirtyEvents() {
1962
- return [...this.dirtyIndices].sort((a, b) => a - b).map((index) => {
1963
- const event = this.events[index];
1964
- return {
1965
- index,
1966
- type: event.type,
1967
- data: JSON.stringify(event)
1968
- };
1969
- });
2035
+ return this.getDirtyIndices().map((index) => this.getSyncEvent(index)).filter((event) => event !== null);
1970
2036
  }
1971
2037
  clearDirty(indices) {
1972
2038
  for (const index of indices) {
@@ -2210,8 +2276,19 @@ function createAskQuestionTool(handlers) {
2210
2276
  batchId: randomUUID(),
2211
2277
  ...validated.input
2212
2278
  };
2279
+ try {
2280
+ await handlers.onAskQuestion(batch);
2281
+ } catch (err) {
2282
+ const message = err instanceof Error ? err.message : String(err);
2283
+ console.error(
2284
+ `[apm] AskQuestion \u63D0\u4EA4\u5931\u8D25 batchId=${batch.batchId}: ${message}`
2285
+ );
2286
+ return {
2287
+ content: [{ type: "text", text: `\u63D0\u4EA4\u95EE\u9898\u5931\u8D25: ${message}` }],
2288
+ isError: true
2289
+ };
2290
+ }
2213
2291
  batches.push(batch);
2214
- await handlers.onAskQuestion(batch);
2215
2292
  console.log(
2216
2293
  `[apm] AskQuestion \u5DF2\u63D0\u4EA4 batchId=${batch.batchId} questions=${batch.questions.length}`
2217
2294
  );
@@ -2232,22 +2309,20 @@ function createThrottledCursorLogSync(cfg, ctx, onError) {
2232
2309
  let timer;
2233
2310
  let latestSession;
2234
2311
  let syncChain = Promise.resolve();
2235
- const syncDirtyEventsOnce = async (session) => {
2236
- const events = session.getDirtyEvents();
2237
- if (events.length === 0) {
2238
- return;
2239
- }
2240
- lastRunAt = Date.now();
2241
- try {
2242
- await syncCursorLog(cfg, ctx, events);
2243
- session.clearDirty(events.map((event) => event.index));
2244
- } catch (err) {
2245
- onError(err);
2246
- }
2247
- };
2248
2312
  const drainDirtyEvents = async (session) => {
2249
- while (session.getDirtyEvents().length > 0) {
2250
- await syncDirtyEventsOnce(session);
2313
+ const pendingIndices = session.getDirtyIndices();
2314
+ for (const index of pendingIndices) {
2315
+ const event = session.getSyncEvent(index);
2316
+ if (!event) {
2317
+ continue;
2318
+ }
2319
+ lastRunAt = Date.now();
2320
+ try {
2321
+ await syncCursorLog(cfg, ctx, event);
2322
+ session.clearDirty([index]);
2323
+ } catch (err) {
2324
+ onError(err);
2325
+ }
2251
2326
  }
2252
2327
  };
2253
2328
  const enqueueSync = (session) => {
@@ -2285,9 +2360,9 @@ function createThrottledCursorLogSync(cfg, ctx, onError) {
2285
2360
  }
2286
2361
  };
2287
2362
  }
2288
- async function syncCursorLog(cfg, ctx, events) {
2363
+ async function syncCursorLog(cfg, ctx, event) {
2289
2364
  const agentId = ctx.agentId.trim();
2290
- if (!agentId || events.length === 0) {
2365
+ if (!agentId) {
2291
2366
  return;
2292
2367
  }
2293
2368
  const api = createApmApiClient(cfg);
@@ -2295,7 +2370,7 @@ async function syncCursorLog(cfg, ctx, events) {
2295
2370
  taskId: ctx.taskId,
2296
2371
  mailboxMessageId: ctx.mailboxMessageId,
2297
2372
  agentId,
2298
- events
2373
+ events: [event]
2299
2374
  });
2300
2375
  }
2301
2376
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "7.0.6",
3
+ "version": "7.0.8",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,