@sebastianandreasson/pi-autonomous-agents 0.13.0 → 0.13.1

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/package.json +1 -1
  2. package/src/pi-sdk-turn.mjs +60 -19
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sebastianandreasson/pi-autonomous-agents",
3
3
  "private": false,
4
- "version": "0.13.0",
4
+ "version": "0.13.1",
5
5
  "type": "module",
6
6
  "description": "Portable unattended PI harness for developer/tester/visual-review loops.",
7
7
  "license": "MIT",
@@ -132,6 +132,47 @@ function deriveTokenAttributionKind({ activeToolName, pendingToolNames, pendingF
132
132
  return 'agent'
133
133
  }
134
134
 
135
+ function emitTokenUsageAttribution({
136
+ request,
137
+ sessionId,
138
+ model,
139
+ tokenUsage,
140
+ activeToolName,
141
+ pendingToolNames,
142
+ pendingFiles,
143
+ lastAssistantActivity,
144
+ }) {
145
+ const usage = normalizeTokenUsage(tokenUsage)
146
+ if (usage.totalTokens <= 0 && usage.inputTokens <= 0 && usage.outputTokens <= 0) {
147
+ return
148
+ }
149
+
150
+ const toolNames = normalizeStringList([...pendingToolNames])
151
+ const files = normalizeStringList([...pendingFiles])
152
+ const attributionKind = deriveTokenAttributionKind({
153
+ activeToolName,
154
+ pendingToolNames,
155
+ pendingFiles,
156
+ lastAssistantActivity,
157
+ })
158
+
159
+ emitLiveFeed(request, {
160
+ type: 'token_usage',
161
+ text: [
162
+ formatTokenUsageSummary(usage),
163
+ attributionKind !== 'agent' ? `attribution=${attributionKind}` : '',
164
+ files.length > 0 ? `files=${files.slice(0, 3).join(',')}${files.length > 3 ? ',…' : ''}` : '',
165
+ ].filter(Boolean).join(' '),
166
+ ...usage,
167
+ attributionKind,
168
+ toolNames,
169
+ files,
170
+ primaryFile: files[0] ?? '',
171
+ sessionId: String(sessionId ?? ''),
172
+ model: String(model ?? ''),
173
+ })
174
+ }
175
+
135
176
  export function splitModelSpec(modelSpec) {
136
177
  const raw = String(modelSpec ?? '').trim()
137
178
  if (raw === '') {
@@ -523,29 +564,16 @@ export async function runSdkTurnWithPi(pi, request) {
523
564
  if (event.type === 'token_usage') {
524
565
  tokenUsageEvents += 1
525
566
  tokenUsage = addTokenUsage(tokenUsage, event)
526
- const toolNames = normalizeStringList([...pendingToolNames])
527
- const files = normalizeStringList([...pendingFiles])
528
- const attributionKind = deriveTokenAttributionKind({
567
+ emitTokenUsageAttribution({
568
+ request,
569
+ sessionId: session?.sessionId ?? '',
570
+ model: requestedModel,
571
+ tokenUsage: event,
529
572
  activeToolName,
530
573
  pendingToolNames,
531
574
  pendingFiles,
532
575
  lastAssistantActivity,
533
576
  })
534
- emitLiveFeed(request, {
535
- type: 'token_usage',
536
- text: [
537
- formatTokenUsageSummary(event),
538
- attributionKind !== 'agent' ? `attribution=${attributionKind}` : '',
539
- files.length > 0 ? `files=${files.slice(0, 3).join(',')}${files.length > 3 ? ',…' : ''}` : '',
540
- ].filter(Boolean).join(' '),
541
- ...normalizeTokenUsage(event),
542
- attributionKind,
543
- toolNames,
544
- files,
545
- primaryFile: files[0] ?? '',
546
- sessionId: String(session?.sessionId ?? ''),
547
- model: requestedModel,
548
- })
549
577
  pendingToolNames.clear()
550
578
  pendingFiles.clear()
551
579
  }
@@ -723,7 +751,20 @@ export async function runSdkTurnWithPi(pi, request) {
723
751
  const messageUpdates = events.filter((event) => event.type === 'message_update').length
724
752
  const lastAssistantMessage = getLastAssistantMessage(session.messages)
725
753
  if (tokenUsageEvents === 0) {
726
- tokenUsage = addTokenUsage(tokenUsage, lastAssistantMessage?.usage)
754
+ const fallbackUsage = normalizeTokenUsage(lastAssistantMessage?.usage)
755
+ tokenUsage = addTokenUsage(tokenUsage, fallbackUsage)
756
+ emitTokenUsageAttribution({
757
+ request,
758
+ sessionId: session?.sessionId ?? '',
759
+ model: requestedModel,
760
+ tokenUsage: fallbackUsage,
761
+ activeToolName,
762
+ pendingToolNames,
763
+ pendingFiles,
764
+ lastAssistantActivity,
765
+ })
766
+ pendingToolNames.clear()
767
+ pendingFiles.clear()
727
768
  }
728
769
  const assistantText = extractAssistantText(lastAssistantMessage).trim()
729
770
  const assistantError = String(lastAssistantMessage?.errorMessage ?? '').trim()