snow-flow 10.0.202 → 10.0.204

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "10.0.202",
3
+ "version": "10.0.204",
4
4
  "name": "snow-flow",
5
5
  "description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
6
6
  "license": "Elastic-2.0",
@@ -77,7 +77,9 @@ export namespace AnonymousTelemetry {
77
77
 
78
78
  let messageCount = 0
79
79
  let exitReason: "normal" | "error" | "interrupt" = "normal"
80
+ let exitErrorMessage: string | undefined
80
81
  let configDisabled = false
82
+ let endPingSent = false
81
83
  const startTime = Date.now()
82
84
  const sessionId = crypto.randomUUID()
83
85
  const installMethod = detectInstallMethod()
@@ -88,12 +90,36 @@ export namespace AnonymousTelemetry {
88
90
  }),
89
91
  ]
90
92
 
93
+ const flushEndPing = async (reason?: "normal" | "error" | "interrupt", errorMessage?: string) => {
94
+ if (configDisabled || endPingSent) return
95
+ if (reason) exitReason = reason
96
+ if (errorMessage) exitErrorMessage = errorMessage.slice(0, 500)
97
+ endPingSent = true
98
+
99
+ const sessionDurationSec = Math.round((Date.now() - startTime) / 1000)
100
+
101
+ await sendPing({
102
+ ...basePayload,
103
+ type: "end",
104
+ exitReason,
105
+ exitErrorMessage,
106
+ sessionDurationSec,
107
+ messageCount,
108
+ timestamp: Date.now(),
109
+ })
110
+ }
111
+
91
112
  // Track exit reason via process signals
92
- const onError = () => {
113
+ const onError = (err: unknown) => {
93
114
  exitReason = "error"
115
+ if (err instanceof Error) exitErrorMessage = `${err.name}: ${err.message}`.slice(0, 500)
116
+ else if (typeof err === "string") exitErrorMessage = err.slice(0, 500)
117
+ else exitErrorMessage = String(err).slice(0, 500)
118
+ void flushEndPing("error", exitErrorMessage)
94
119
  }
95
120
  const onInterrupt = () => {
96
121
  exitReason = "interrupt"
122
+ void flushEndPing("interrupt")
97
123
  }
98
124
  process.on("uncaughtException", onError)
99
125
  process.on("unhandledRejection", onError)
@@ -142,9 +168,15 @@ export namespace AnonymousTelemetry {
142
168
  get exitReason() {
143
169
  return exitReason
144
170
  },
171
+ get exitErrorMessage() {
172
+ return exitErrorMessage
173
+ },
145
174
  get configDisabled() {
146
175
  return configDisabled
147
176
  },
177
+ async flushEndPing() {
178
+ await flushEndPing()
179
+ },
148
180
  cleanup() {
149
181
  process.removeListener("uncaughtException", onError)
150
182
  process.removeListener("unhandledRejection", onError)
@@ -158,17 +190,7 @@ export namespace AnonymousTelemetry {
158
190
  if (current.disabled || current.configDisabled) return
159
191
 
160
192
  if ("cleanup" in current) current.cleanup()
161
-
162
- const sessionDurationSec = Math.round((Date.now() - current.startTime) / 1000)
163
-
164
- await sendPing({
165
- ...current.basePayload,
166
- type: "end",
167
- exitReason: current.exitReason,
168
- sessionDurationSec,
169
- messageCount: current.messageCount,
170
- timestamp: Date.now(),
171
- })
193
+ if ("flushEndPing" in current) await current.flushEndPing()
172
194
  },
173
195
  )
174
196