coze_lab 0.1.3 → 0.1.5

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.
@@ -446,6 +446,32 @@ function resolveChannelId(ctx, eventFrom, defaultValue = "system/unknown") {
446
446
  let lastUserChannelId;
447
447
  let lastUserTraceContext;
448
448
  let lastOpenclawSessionId;
449
+ // Session-level coze-context cache. In a Coze session only the FIRST user
450
+ // message carries the <coze-context> block; /loop follow-ups and later turns
451
+ // do not. We cache the most recently seen context (per openclaw session id, plus
452
+ // a global last-seen fallback) so that ensureRootSpan can still attach the
453
+ // trace to the right Coze session on those later turns instead of dropping it.
454
+ const cozeContextBySession = new Map();
455
+ let lastCozeContext;
456
+ function rememberCozeContext(input, sessionId) {
457
+ const parsed = parseCozeContext(input);
458
+ if (Object.keys(parsed).length === 0)
459
+ return parsed;
460
+ lastCozeContext = parsed;
461
+ if (sessionId)
462
+ cozeContextBySession.set(sessionId, parsed);
463
+ return parsed;
464
+ }
465
+ function resolveCozeContext(input, sessionId) {
466
+ // Prefer context parsed from this turn's input; fall back to the per-session
467
+ // cache, then the global last-seen context.
468
+ const fromInput = parseCozeContext(input);
469
+ if (Object.keys(fromInput).length > 0)
470
+ return fromInput;
471
+ if (sessionId && cozeContextBySession.has(sessionId))
472
+ return cozeContextBySession.get(sessionId);
473
+ return lastCozeContext || {};
474
+ }
449
475
  // Active agent context: set in before_agent_start, cleared in agent_end.
450
476
  // All hooks between these two (llm_input, llm_output, tool calls, messages)
451
477
  // use this to ensure every span lands in the same Trace.
@@ -814,6 +840,9 @@ const cozeloopTracePlugin = {
814
840
  lastUserTraceContext = ctx;
815
841
  ctx.userInput = event.content;
816
842
  lastUserInput = event.content;
843
+ // Cache any coze-context as soon as we see the user input,
844
+ // so later /loop turns (which carry none) can inherit it.
845
+ rememberCozeContext(event.content, ctx.openclawSessionId || lastOpenclawSessionId);
817
846
  if (config.debug) {
818
847
  api.logger.info(`[CozeloopTrace] Saved user context: channelId=${channelId}, traceId=${ctx.traceId}`);
819
848
  }
@@ -895,6 +924,9 @@ const cozeloopTracePlugin = {
895
924
  lastUserInput = event.prompt;
896
925
  }
897
926
  }
927
+ // Cache coze-context from the prompt too (covers sessions where no
928
+ // message_received fired), so /loop follow-ups can inherit it.
929
+ rememberCozeContext(event.prompt, ctx.openclawSessionId || lastOpenclawSessionId);
898
930
  // Fallback: ensure root + agent spans exist in case before_agent_start
899
931
  // was not fired (older OpenClaw versions or resumed sessions).
900
932
  const channelIdForSpans = activeAgentChannelId || rawChannelId;
@@ -1166,9 +1198,20 @@ const cozeloopTracePlugin = {
1166
1198
  // Must be called before creating the agent span so that the exporter's
1167
1199
  // currentRootContext is set and the agent span becomes a proper child.
1168
1200
  const ensureRootSpan = async (ctx, channelId) => {
1169
- // Only trace sessions that carry coze-context no context means this
1170
- // is not a Coze-originated session and we skip it entirely.
1171
- if (!Object.keys(parseCozeContext(ctx.userInput)).length) {
1201
+ // Resolve coze-context with SESSION-LEVEL inheritance: only the first
1202
+ // user message of a Coze session carries the <coze-context> block, so
1203
+ // /loop follow-ups and later turns have none. Fall back to the per-
1204
+ // session cache (and global last-seen) instead of dropping the trace.
1205
+ // Only skip when NO context has ever been seen for this session.
1206
+ const ocSessionId = ctx.openclawSessionId || lastOpenclawSessionId;
1207
+ rememberCozeContext(ctx.userInput, ocSessionId);
1208
+ let cozeCtx = resolveCozeContext(ctx.userInput, ocSessionId);
1209
+ if (Object.keys(cozeCtx).length === 0) {
1210
+ // Try the fallback user inputs too before giving up.
1211
+ const fallbackInput = lastUserTraceContext?.userInput || lastUserInput;
1212
+ cozeCtx = resolveCozeContext(fallbackInput, ocSessionId);
1213
+ }
1214
+ if (Object.keys(cozeCtx).length === 0) {
1172
1215
  return;
1173
1216
  }
1174
1217
  // Check both: rootSpanStartTime indicates we created a root span before,
@@ -1207,7 +1250,7 @@ const cozeloopTracePlugin = {
1207
1250
  "run.id": ctx.runId,
1208
1251
  "turn.id": ctx.turnId,
1209
1252
  "openclaw.channel_id": channelId,
1210
- ...parseCozeContext(ctx.userInput),
1253
+ ...cozeCtx,
1211
1254
  },
1212
1255
  input: ctx.userInput,
1213
1256
  traceId: ctx.traceId,
@@ -1237,7 +1280,7 @@ const cozeloopTracePlugin = {
1237
1280
  "run.id": ctx.runId,
1238
1281
  "turn.id": ctx.turnId,
1239
1282
  "openclaw.channel_id": channelId,
1240
- ...parseCozeContext(ctx.userInput),
1283
+ ...resolveCozeContext(ctx.userInput, ctx.openclawSessionId || lastOpenclawSessionId),
1241
1284
  },
1242
1285
  traceId: ctx.traceId,
1243
1286
  spanId: ctx.agentSpanId,