oasis_test_v2 2.2.42 → 2.2.43

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 +121 -9
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -7347,12 +7347,18 @@ ${note}` : note };
7347
7347
  const stderrTail = [];
7348
7348
  const STDERR_MAX_LINES = 40;
7349
7349
  const STDERR_MAX_BYTES = 4e3;
7350
+ let turnMessage = "";
7351
+ let turnStderr = [];
7350
7352
  const stderrRl = readline3.createInterface({ input: child.stderr });
7351
7353
  stderrRl.on("line", (line) => {
7352
7354
  try {
7353
7355
  transcriptOut.write(line + "\n");
7354
7356
  } catch {
7355
7357
  }
7358
+ if (cfg.classifyPromptFailure) {
7359
+ turnStderr.push(line);
7360
+ if (turnStderr.length > PROMPT_TURN_STDERR_MAX_LINES) turnStderr.shift();
7361
+ }
7356
7362
  stderrTail.push(line);
7357
7363
  while (stderrTail.length > STDERR_MAX_LINES) stderrTail.shift();
7358
7364
  let total = stderrTail.reduce((n, l) => n + l.length + 1, 0);
@@ -7399,6 +7405,7 @@ ${note}` : note };
7399
7405
  },
7400
7406
  (text6) => {
7401
7407
  confirmAppendBatch();
7408
+ if (cfg.classifyPromptFailure && turnMessage.length < PROMPT_TURN_MESSAGE_MAX) turnMessage += text6;
7402
7409
  for (const cb of outputCbs) cb(text6);
7403
7410
  },
7404
7411
  (e) => {
@@ -7514,6 +7521,8 @@ ${task}` : task;
7514
7521
  }
7515
7522
  streamingCurrentTurn = true;
7516
7523
  const sendPrompt = async (text6) => {
7524
+ turnMessage = "";
7525
+ turnStderr = [];
7517
7526
  const p2 = client.request("session/prompt", { sessionId, prompt: [{ type: "text", text: text6 }] });
7518
7527
  inflightStopReason = p2.then((r) => extractStopReason(r), () => "");
7519
7528
  try {
@@ -7544,8 +7553,15 @@ ${task}` : task;
7544
7553
  inflightAppendBatch = [];
7545
7554
  }
7546
7555
  closingForExit = true;
7556
+ let failure;
7557
+ if (cfg.classifyPromptFailure) {
7558
+ await new Promise((r) => setTimeout(r, PROMPT_FAILURE_STDERR_SETTLE_MS));
7559
+ failure = cfg.classifyPromptFailure({ message: turnMessage, stderrLines: [...turnStderr], result: promptResult });
7560
+ }
7547
7561
  const usage = buildReportedUsage(client.usage, actualModel, cfg.inputTokensIncludeCacheRead === true);
7548
- if (!exited) finish({ code: 0, reason: "clean", transcriptRef, usage, model: actualModel });
7562
+ if (!exited) {
7563
+ finish(failure ? { code: null, reason: failure.reason, errorMessage: failure.errorMessage, transcriptRef, usage, model: actualModel } : { code: 0, reason: "clean", transcriptRef, usage, model: actualModel });
7564
+ }
7549
7565
  child.kill("SIGTERM");
7550
7566
  } catch (err) {
7551
7567
  lastRpcError = err instanceof Error ? err.message : String(err);
@@ -7637,7 +7653,7 @@ ${task}` : task;
7637
7653
  return run;
7638
7654
  }
7639
7655
  }
7640
- var import_node_child_process8, import_node_crypto10, fs9, path11, readline3, ACPClient, LEGACY_APPROVE_OPTION_ID;
7656
+ var import_node_child_process8, import_node_crypto10, fs9, path11, readline3, PROMPT_TURN_MESSAGE_MAX, PROMPT_TURN_STDERR_MAX_LINES, PROMPT_FAILURE_STDERR_SETTLE_MS, ACPClient, LEGACY_APPROVE_OPTION_ID;
7641
7657
  var init_acp = __esm({
7642
7658
  "../adapters/src/_core/acp.ts"() {
7643
7659
  "use strict";
@@ -7656,6 +7672,9 @@ var init_acp = __esm({
7656
7672
  init_transcript();
7657
7673
  init_filter_extra_args();
7658
7674
  init_root_bypass();
7675
+ PROMPT_TURN_MESSAGE_MAX = 4e3;
7676
+ PROMPT_TURN_STDERR_MAX_LINES = 200;
7677
+ PROMPT_FAILURE_STDERR_SETTLE_MS = 50;
7659
7678
  ACPClient = class {
7660
7679
  constructor(write, onOutput, onTelemetry, onStop, acceptNotification = () => true, finalUsageIsAuthoritative = false, vendorUsage) {
7661
7680
  this.write = write;
@@ -7935,12 +7954,47 @@ var init_acp = __esm({
7935
7954
  }
7936
7955
  });
7937
7956
 
7957
+ // ../adapters/src/hermes/prompt-failure.ts
7958
+ function classifyHermesPromptFailure(turn) {
7959
+ if (promptResultHasUsage(turn.result)) return void 0;
7960
+ const failed = failureFromMessage(turn.message) ?? failureFromStderr(turn.stderrLines);
7961
+ if (!failed) return void 0;
7962
+ return {
7963
+ reason: QUOTA_RE.test(failed.summary) ? "rate-limit" : "error",
7964
+ errorMessage: `API call failed after ${failed.retries} retries: ${failed.summary}`
7965
+ };
7966
+ }
7967
+ function promptResultHasUsage(result) {
7968
+ return typeof result === "object" && result !== null && result.usage != null;
7969
+ }
7970
+ function failureFromMessage(message) {
7971
+ const m2 = MESSAGE_RE.exec(message);
7972
+ return m2 ? { retries: m2[1], summary: m2[2].trim() } : void 0;
7973
+ }
7974
+ function failureFromStderr(lines) {
7975
+ for (let i = lines.length - 1; i >= 0; i--) {
7976
+ const m2 = STDERR_RE.exec(lines[i]);
7977
+ if (m2) return { retries: m2[1], summary: m2[2].trim() };
7978
+ }
7979
+ return void 0;
7980
+ }
7981
+ var QUOTA_RE, MESSAGE_RE, STDERR_RE;
7982
+ var init_prompt_failure = __esm({
7983
+ "../adapters/src/hermes/prompt-failure.ts"() {
7984
+ "use strict";
7985
+ QUOTA_RE = /\b429\b|rate.?limit|usage limit|quota|too many requests/i;
7986
+ MESSAGE_RE = /^\s*API call failed after (\d+) retries: (.+)/;
7987
+ STDERR_RE = /(?:^|:\s)API call failed after (\d+) retries\. (.+?)(?:\s\|\sprovider=.*)?$/;
7988
+ }
7989
+ });
7990
+
7938
7991
  // ../adapters/src/hermes/index.ts
7939
7992
  var HermesAdapter;
7940
7993
  var init_hermes = __esm({
7941
7994
  "../adapters/src/hermes/index.ts"() {
7942
7995
  "use strict";
7943
7996
  init_acp();
7997
+ init_prompt_failure();
7944
7998
  HermesAdapter = class {
7945
7999
  constructor(opts = {}) {
7946
8000
  this.opts = opts;
@@ -7972,6 +8026,8 @@ var init_hermes = __esm({
7972
8026
  // skills.external_dirs 配成该 env → hermes 每 session 发现各自技能。见
7973
8027
  // packages/adapters/docs/modules/07-skills-delivery.md 与 connect-script.ts。
7974
8028
  injectSkillsDirEnv: "OASIS_HERMES_SKILLS_DIR",
8029
+ // 重试用尽时 hermes 照样回 end_turn,只发一句「API call failed after N retries」——见 prompt-failure.ts。
8030
+ classifyPromptFailure: classifyHermesPromptFailure,
7975
8031
  ...this.opts.syncSkills ? { syncSkills: this.opts.syncSkills } : {}
7976
8032
  });
7977
8033
  }
@@ -7985,6 +8041,7 @@ var init_oasis_agent = __esm({
7985
8041
  "../adapters/src/oasis-agent/index.ts"() {
7986
8042
  "use strict";
7987
8043
  init_acp();
8044
+ init_prompt_failure();
7988
8045
  OasisAgentAdapter = class {
7989
8046
  constructor(opts = {}) {
7990
8047
  this.opts = opts;
@@ -8015,6 +8072,8 @@ var init_oasis_agent = __esm({
8015
8072
  // 名字分开才能在同机共存时一眼看出哪份 config 是给谁的。node enroll 会把该字面量写进
8016
8073
  // `~/.oasis-agent/home/config.yaml` 的 skills.external_dirs(见 connect-script.ts)。
8017
8074
  injectSkillsDirEnv: "OASIS_AGENT_SKILLS_DIR",
8075
+ // 分叉没动 acp_adapter/,失败回合的线上形态与 hermes 相同(未在分叉上实测)。
8076
+ classifyPromptFailure: classifyHermesPromptFailure,
8018
8077
  ...this.opts.syncSkills ? { syncSkills: this.opts.syncSkills } : {}
8019
8078
  });
8020
8079
  }
@@ -138626,7 +138685,7 @@ function classifyExitReason(info) {
138626
138685
  if (info.reason) return info.reason;
138627
138686
  const msg = info.errorMessage;
138628
138687
  if (!msg) return info.reason;
138629
- if (QUOTA_RE.test(msg)) return "rate-limit";
138688
+ if (QUOTA_RE2.test(msg)) return "rate-limit";
138630
138689
  if (UNREACHABLE_RE.test(msg)) return "server-unreachable";
138631
138690
  if (AUTH_RE.test(msg)) return "auth-error";
138632
138691
  return info.reason;
@@ -138643,11 +138702,11 @@ function extractResetHint(errorMessage) {
138643
138702
  const m2 = /((?:resets?|try again at)\s+[^·。\n]{1,48})/i.exec(errorMessage);
138644
138703
  return m2?.[1]?.trim().replace(/[.,;]$/, "");
138645
138704
  }
138646
- var QUOTA_RE, UNREACHABLE_RE, AUTH_RE;
138705
+ var QUOTA_RE2, UNREACHABLE_RE, AUTH_RE;
138647
138706
  var init_exit_classify = __esm({
138648
138707
  "../core/src/exit-classify.ts"() {
138649
138708
  "use strict";
138650
- QUOTA_RE = /hit your (?:weekly|session|usage|daily|monthly) limit|usage limit|rate.?limit|quota exceeded|too many requests|\b429\b/i;
138709
+ QUOTA_RE2 = /hit your (?:weekly|session|usage|daily|monthly) limit|usage limit|rate.?limit|quota exceeded|too many requests|\b429\b/i;
138651
138710
  UNREACHABLE_RE = /不在线|socket 非 OPEN|帧未送达|失联超宽限期|未见任何回执|unreachable|ECONNREFUSED|ETIMEDOUT/i;
138652
138711
  AUTH_RE = /\b401\b|\b403\b|unauthor|invalid[_ -]?api[_ -]?key|authentication failed|credential/i;
138653
138712
  }
@@ -206652,6 +206711,7 @@ async function startOasisServer(opts) {
206652
206711
  const label = ctx.effectLabel || ctx.command || "";
206653
206712
  return approved ? `\u547D\u4EE4\u5DF2\u7531 ${by} \u6279\u51C6\u5E76\u4EE5\u5176\u540D\u4E49\u6267\u884C${label ? `\uFF1A${label}` : ""}\u3002` : `\u547D\u4EE4\u5DF2\u88AB ${by} \u9A73\u56DE${reason ? `\uFF1A${reason}` : ""}\u3002`;
206654
206713
  };
206714
+ const GRAPH_EDIT_IN_FLIGHT_SUFFIX = "\uFF08\u8FD9\u6761\u662F\u5728\u4F60\u672C\u8F6E\u8FDB\u884C\u4E2D\u63D2\u5165\u7684\u901A\u77E5\uFF1A\u56DE\u5E94\u5B8C\u540E\u63A5\u7740\u505A\u4F60\u624B\u4E0A\u8FD8\u6CA1\u505A\u5B8C\u7684\u4E8B\uFF0C\u522B\u5C31\u6B64\u6536\u5C3E\u3002\uFF09";
206655
206715
  const authorizationResumePrompt = (resolution, ctx) => {
206656
206716
  const approved = resolution.status === "approved";
206657
206717
  const by = ctx.authorizedBy ?? "\u7BA1\u7406\u8005";
@@ -206705,12 +206765,43 @@ async function startOasisServer(opts) {
206705
206765
  await store.markMessageDeliveredToAgent?.(statusMessageId).catch(() => void 0);
206706
206766
  };
206707
206767
  const prompt2 = authorizationResumePrompt(resolution, ctx);
206768
+ const inFlightPrompt = ctx.kind === "graph-edit" ? `${prompt2}${GRAPH_EDIT_IN_FLIGHT_SUFFIX}` : prompt2;
206708
206769
  if (liveChat.isRunning(origin)) {
206709
- const appended = await liveChat.append(origin, prompt2, { system: true }).catch(() => ({ accepted: false }));
206770
+ const appended = await liveChat.append(origin, inFlightPrompt, { system: true }).catch(() => ({ accepted: false }));
206710
206771
  if (appended.accepted) await markDelivered();
206711
206772
  return;
206712
206773
  }
206713
206774
  const sessionCompanyId = session.companyId ?? companyId;
206775
+ let held;
206776
+ let itemStore;
206777
+ try {
206778
+ const turns = (opts.resolveChatTurns ? await opts.resolveChatTurns(sessionCompanyId) : opts.chatTurns) ?? null;
206779
+ itemStore = opts.resolveChatItems ? await opts.resolveChatItems(sessionCompanyId).catch(() => void 0) : opts.chatItems;
206780
+ const opened = await openChatTurn({
206781
+ turns,
206782
+ chatSessionId: origin,
206783
+ source: "internal",
206784
+ log: (m2) => console.warn(m2)
206785
+ });
206786
+ if (!opened.ok) {
206787
+ const appended = await liveChat.append(origin, inFlightPrompt, { system: true }).catch(() => ({ accepted: false }));
206788
+ if (appended.accepted) {
206789
+ await markDelivered();
206790
+ return;
206791
+ }
206792
+ console.warn(
206793
+ `[chat-system-message] \u6388\u6743\u5361\u7EC8\u5C40\u7EED\u8DD1\u672A\u5F00\u8F6E\uFF1A\u4F1A\u8BDD\u69FD\u88AB\u5360\u4E14\u672C\u5B9E\u4F8B\u63D2\u4E0D\u8FDB\uFF0C\u72B6\u6001\u6761\u7559\u4F5C\u5F85\u8865\u6295\uFF08draft=${draftId} session=${origin} company=${sessionCompanyId ?? "(\u9ED8\u8BA4)"} \u5360\u69FD\u8F6E=${opened.activeTurn.id} \u6765\u6E90=${opened.activeTurn.source}\uFF09`
206794
+ );
206795
+ return;
206796
+ }
206797
+ held = opened.turn;
206798
+ } catch (err) {
206799
+ console.error(
206800
+ `[chat-system-message] \u6388\u6743\u5361\u7EC8\u5C40\u7EED\u8DD1\u5360\u4F1A\u8BDD\u69FD\u5931\u8D25\uFF0C\u72B6\u6001\u6761\u7559\u4F5C\u5F85\u8865\u6295\uFF08draft=${draftId} session=${origin} company=${sessionCompanyId ?? "(\u9ED8\u8BA4)"}\uFF09:`,
206801
+ err
206802
+ );
206803
+ return;
206804
+ }
206714
206805
  let dispatched;
206715
206806
  try {
206716
206807
  dispatched = await dispatch({
@@ -206721,6 +206812,11 @@ async function startOasisServer(opts) {
206721
206812
  ...sessionCompanyId ? { companyId: sessionCompanyId } : {}
206722
206813
  });
206723
206814
  } catch (err) {
206815
+ await held?.settle({
206816
+ status: "failed",
206817
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
206818
+ lastError: err instanceof Error ? err.message : String(err)
206819
+ });
206724
206820
  console.error(
206725
206821
  `[chat-system-message] \u6388\u6743\u5361\u7EC8\u5C40\u7EED\u8DD1\u6D3E\u53D1\u5931\u8D25\uFF0C\u72B6\u6001\u6761\u7559\u4F5C\u5F85\u8865\u6295\uFF08draft=${draftId} session=${origin} company=${sessionCompanyId ?? "(\u672A\u5E26\uFF0C\u6309\u9ED8\u8BA4\u516C\u53F8)"}\uFF09:`,
206726
206822
  err
@@ -206744,9 +206840,25 @@ async function startOasisServer(opts) {
206744
206840
  chatStore: store,
206745
206841
  chatSessionId: origin,
206746
206842
  session: bgSession,
206747
- ...resumeOutputsPart ? { outputsPart: resumeOutputsPart } : {}
206843
+ ...resumeOutputsPart ? { outputsPart: resumeOutputsPart } : {},
206844
+ liveChat,
206845
+ liveHandle: {
206846
+ runtimeSessionId: dispatched.id,
206847
+ ...dispatched.runId ? { runId: dispatched.runId } : {},
206848
+ kill: () => {
206849
+ void dispatched.kill?.();
206850
+ },
206851
+ ...dispatched.appendInput ? { appendInput: (input) => dispatched.appendInput(input) } : {},
206852
+ get canAppendInput() {
206853
+ return typeof dispatched.appendInput === "function" && dispatched.canAppendInput !== false;
206854
+ }
206855
+ },
206856
+ ...itemStore ? { itemStore } : {},
206857
+ ...held ? { turnId: held.id } : {}
206748
206858
  });
206859
+ await held?.start({ assistantRunId: dispatched.runId ?? null, dispatchId: dispatched.runId ?? null });
206749
206860
  await markDelivered();
206861
+ void Promise.resolve(dispatched.done).then(() => held?.settle({ status: "succeeded", completedAt: (/* @__PURE__ */ new Date()).toISOString() })).catch((err) => held?.settle({ status: "failed", completedAt: (/* @__PURE__ */ new Date()).toISOString(), lastError: String(err) }));
206750
206862
  };
206751
206863
  const broadcastSeen = /* @__PURE__ */ new Set();
206752
206864
  let _broadcastFlushOwner = null;
@@ -207019,7 +207131,7 @@ async function startOasisServer(opts) {
207019
207131
  }
207020
207132
  },
207021
207133
  ...itemStore ? { itemStore } : {},
207022
- // 广播/委派回流带上 held turn id(B3);授权卡入口在别处,那条路本轮不接账本。
207134
+ // 广播/委派回流带上 held turn id(B3);授权卡续跑(settleAuthorizationStatusLine 第③档)同一口径。
207023
207135
  ...turnId ? { turnId } : {}
207024
207136
  });
207025
207137
  },
@@ -278589,7 +278701,7 @@ function shimScript() {
278589
278701
  }
278590
278702
 
278591
278703
  // src/index.ts
278592
- var PKG_VERSION = true ? "2.2.42" : "dev";
278704
+ var PKG_VERSION = true ? "2.2.43" : "dev";
278593
278705
  var LOCAL_BIN = localBin();
278594
278706
  var NPM_PREFIX = npmPrefix();
278595
278707
  var INSTANCE = DEFAULT_INSTANCE;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oasis_test_v2",
3
- "version": "2.2.42",
3
+ "version": "2.2.43",
4
4
  "description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
5
5
  "bin": {
6
6
  "oasis": "./dist/index.js"
@@ -26,6 +26,6 @@
26
26
  "node": ">=20"
27
27
  },
28
28
  "oasisRelease": {
29
- "sourceHead": "0f4fa607e6e47a8a8df2194a3a42b194fef3ef0b"
29
+ "sourceHead": "34968cfc5b0889a75157d9e05acecc3540285932"
30
30
  }
31
31
  }