@softprobe/opencode-plugin 0.1.5 → 0.1.7

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/README.md CHANGED
@@ -8,6 +8,9 @@ and used to improve agents.
8
8
 
9
9
  ## Install
10
10
 
11
+ Full guide: [Agent QA · OpenCode](https://docs.softprobe.ai/en/agent-qa/opencode)
12
+ (Explorer can also give you a short pasteable OpenCode chat prompt).
13
+
11
14
  Enable OpenTelemetry and add the plugin in `opencode.json` / `opencode.jsonc`:
12
15
 
13
16
  ```json
@@ -69,16 +72,18 @@ credentials when `SPCODE_MODE` is on (see softprobe-code
69
72
 
70
73
  ### Sub-agent sessions
71
74
 
72
- OpenCode runs sub-agents (the `task` tool) in child sessions. The plugin nests
73
- each child session's turn under the dispatching task span, so a whole agent
74
- run — root session plus any sub-agents, recursively — forms a single trace
75
- instead of several disconnected ones. The link comes from the task part's
75
+ OpenCode runs sub-agents (the `task` tool) in child OpenCode sessions. The
76
+ plugin nests each child turn under the dispatching task span (`parent_span_id`)
77
+ and stamps the **root** OpenCode session id as `sp.session.id` /
78
+ `gen_ai.conversation.id` on every nested span — one product Session for the
79
+ whole chat. Child `ses_*` ids stay internal to the plugin graph and are never
80
+ the product session key. Linkage comes from the task part's
76
81
  `state.metadata.sessionId` (authoritative), with `task_id` resume and
77
82
  parentID + task-call inference as fallbacks; ambiguous dispatches (e.g.
78
- parallel identical task calls) are left unnested rather than guessed. Each
79
- span keeps its own `sp.session.id`; the parent side is recorded as
80
- `sp.metadata.opencode.parentSessionID` / `sp.metadata.opencode.parentTaskCallID`
81
- on the child turn and `sp.child.session.id` on the task span.
83
+ parallel identical task calls) are left unnested rather than guessed. Nested
84
+ turns also carry `sp.metadata.opencode.parentSessionID` /
85
+ `sp.metadata.opencode.parentTaskCallID`, and the task span records
86
+ `sp.child.session.id` for the OpenCode child session id.
82
87
 
83
88
  Session lifecycle is isolated per session: a sub-agent session going idle
84
89
  finalizes only its own spans, never the parent session's in-flight work.
@@ -47,6 +47,8 @@ export declare class SessionGraph {
47
47
  markRoot(sessionID: string): void;
48
48
  isRoot(sessionID: string): boolean;
49
49
  parentOf(sessionID: string): string | undefined;
50
+ /** Walk parent links to the product (root) session id. */
51
+ rootSessionId(sessionID: string): string;
50
52
  registerTaskCall(callID: string, sessionID: string, args: TaskCallArgs): void;
51
53
  endTaskCall(callID: string): void;
52
54
  bind(binding: TaskBinding): void;
@@ -67,6 +67,20 @@ export class SessionGraph {
67
67
  parentOf(sessionID) {
68
68
  return this.parents.get(sessionID);
69
69
  }
70
+ /** Walk parent links to the product (root) session id. */
71
+ rootSessionId(sessionID) {
72
+ let current = sessionID;
73
+ const seen = new Set();
74
+ while (true) {
75
+ if (seen.has(current))
76
+ return current;
77
+ seen.add(current);
78
+ const parent = this.parents.get(current);
79
+ if (!parent)
80
+ return current;
81
+ current = parent;
82
+ }
83
+ }
70
84
  registerTaskCall(callID, sessionID, args) {
71
85
  const existing = this.taskCalls.get(callID);
72
86
  if (existing) {
package/dist/softprobe.js CHANGED
@@ -391,8 +391,11 @@ export class SoftprobeSessionTracer {
391
391
  this.generationParents.get(sessionID));
392
392
  }
393
393
  sessionAttrs(sessionID) {
394
+ // Product session is always the root OpenCode session; child ses_* scopes
395
+ // keep their own bookkeeping keys but stamp the root on every span.
396
+ const productSessionId = this.sessionGraph.rootSessionId(sessionID);
394
397
  return {
395
- sessionId: sessionID,
398
+ sessionId: productSessionId,
396
399
  ...(this.userId ? { userId: this.userId } : {}),
397
400
  };
398
401
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softprobe/opencode-plugin",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "OpenCode plugin that sends session telemetry to Softprobe",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,7 +25,7 @@
25
25
  "lint": "tsc -p tsconfig.json --noEmit"
26
26
  },
27
27
  "dependencies": {
28
- "@softprobe/tracing": "0.1.5"
28
+ "@softprobe/tracing": "0.1.7"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@opencode-ai/plugin": ">=1.15.0",