helloagents 3.0.38 → 3.1.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.
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync, readdirSync, rmSync, writeFileSync } from 'node:fs'
1
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'
2
2
  import { basename, dirname, join } from 'node:path'
3
3
 
4
4
  import {
@@ -43,67 +43,6 @@ function writeRuntimeDocument(filePath, payload) {
43
43
  writeJsonFileAtomic(filePath, payload)
44
44
  }
45
45
 
46
- function isSamePath(left = '', right = '') {
47
- if (process.platform === 'win32') {
48
- return left.toLowerCase() === right.toLowerCase()
49
- }
50
- return left === right
51
- }
52
-
53
- function isSeedOnlyState(body = '') {
54
- return String(body || '').includes('由运行时自动创建;后续按实际任务重写')
55
- }
56
-
57
- function looksLikeLegacyFlattenedSessionDir(entryName = '') {
58
- return /^[a-z0-9]{8}$/i.test(String(entryName || '').trim())
59
- }
60
-
61
- function migrateLegacyProjectScope(scope) {
62
- if (scope.scope !== 'project-session') return
63
- const workspaceDir = scope.workspaceDir || join(scope.activationDir, 'sessions', scope.workspace || scope.branch)
64
- const legacyStatePath = join(workspaceDir, 'STATE.md')
65
- const legacyRuntimePath = join(workspaceDir, 'runtime.json')
66
- if (isSamePath(workspaceDir, scope.sessionDir)) return
67
-
68
- const currentDocument = readStateDocument(scope.statePath)
69
- const currentCapsule = currentDocument.metadata && typeof currentDocument.metadata === 'object'
70
- ? currentDocument.metadata
71
- : null
72
- const legacyDocument = readStateDocument(legacyStatePath)
73
- const legacyCapsule = readRuntimeDocument(legacyRuntimePath)
74
- const shouldNormalizeCurrentBody = currentDocument.hasMetadata
75
- const shouldWriteBody = (!currentDocument.body.trim() && legacyDocument.body.trim()) || shouldNormalizeCurrentBody
76
- const shouldWriteRuntime = (legacyCapsule || currentCapsule) && !readRuntimeDocument(scope.runtimePath)
77
-
78
- if (shouldWriteBody) {
79
- writeStateDocument(scope.statePath, {
80
- body: currentDocument.body.trim() ? currentDocument.body : legacyDocument.body,
81
- })
82
- }
83
- if (shouldWriteRuntime) {
84
- writeRuntimeDocument(scope.runtimePath, legacyCapsule || currentCapsule)
85
- }
86
-
87
- if (existsSync(legacyStatePath) && shouldWriteBody) {
88
- const legacyCurrent = readStateDocument(legacyStatePath)
89
- if (legacyCurrent.hasMetadata) {
90
- writeStateDocument(legacyStatePath, {
91
- body: legacyCurrent.body,
92
- })
93
- }
94
- }
95
- if (existsSync(legacyRuntimePath) && shouldWriteRuntime) {
96
- rmSync(legacyRuntimePath, { force: true })
97
- }
98
- if (existsSync(workspaceDir)) {
99
- for (const entry of readdirSync(workspaceDir, { withFileTypes: true })) {
100
- if (!entry.isDirectory()) continue
101
- if (!looksLikeLegacyFlattenedSessionDir(entry.name)) continue
102
- rmSync(join(workspaceDir, entry.name), { recursive: true, force: true })
103
- }
104
- }
105
- }
106
-
107
46
  function normalizeOptions(options = {}) {
108
47
  if (!options || typeof options !== 'object') return {}
109
48
  if (options.payload && typeof options.payload === 'object') return options
@@ -114,7 +53,7 @@ function normalizeOptions(options = {}) {
114
53
  }
115
54
 
116
55
  function getEventSessionAlias(eventPayload = {}) {
117
- return eventPayload.sessionId || eventPayload.session_id || eventPayload['session-id'] || ''
56
+ return eventPayload.sessionAlias || eventPayload.session_alias || eventPayload['session-alias'] || eventPayload._helloagentsSessionAlias || ''
118
57
  }
119
58
 
120
59
  function getScope(cwd, options = {}) {
@@ -182,7 +121,6 @@ export function getSessionArtifactRelativePath(cwd, fileName, options = {}) {
182
121
 
183
122
  export function readSessionCapsule(cwd = process.cwd(), options = {}) {
184
123
  const scope = getScope(cwd, options)
185
- migrateLegacyProjectScope(scope)
186
124
  const capsule = readRuntimeDocument(scope.runtimePath)
187
125
  if (!capsule || Array.isArray(capsule)) return buildEmptyCapsule(scope)
188
126
  return {
@@ -201,7 +139,6 @@ export function readSessionCapsule(cwd = process.cwd(), options = {}) {
201
139
  export function writeSessionCapsule(cwd, capsule, options = {}) {
202
140
  const normalizedOptions = normalizeOptions(options)
203
141
  const scope = getScope(cwd, normalizedOptions)
204
- migrateLegacyProjectScope(scope)
205
142
  const shouldMaterialize = shouldMaterializeSessionState(normalizedOptions)
206
143
  const currentDocument = readStateDocument(scope.statePath)
207
144
  const hasBody = Boolean(currentDocument.body && currentDocument.body.trim())
@@ -246,7 +183,9 @@ export function writeSessionCapsule(cwd, capsule, options = {}) {
246
183
  })
247
184
  }
248
185
  writeActiveProjectSession(scope, {
186
+ payload: normalizedOptions.payload,
249
187
  env: normalizedOptions.env,
188
+ ppid: normalizedOptions.ppid,
250
189
  })
251
190
  return nextCapsule
252
191
  }
@@ -305,7 +244,9 @@ export function appendSessionEvent(cwd, eventPayload, options = {}) {
305
244
  writeActiveProjectSession(scope, {
306
245
  host: eventPayload.host || '',
307
246
  source: eventPayload.source || eventName,
247
+ payload: scopedOptions.payload,
308
248
  env: scopedOptions.env,
249
+ ppid: scopedOptions.ppid,
309
250
  })
310
251
  if (!shouldRecordSessionEvents(scopedOptions)) return ''
311
252
 
@@ -17,19 +17,31 @@ const PAYLOAD_SESSION_KEYS = [
17
17
  'tab',
18
18
  ]
19
19
 
20
- const PROJECT_PAYLOAD_SESSION_KEYS = [
20
+ const PROJECT_SESSION_PAYLOAD_KEYS = [
21
21
  'sessionId',
22
22
  'session_id',
23
23
  'session',
24
+ ]
25
+
26
+ const PROJECT_CONVERSATION_PAYLOAD_KEYS = [
24
27
  'conversationId',
25
28
  'conversation_id',
26
29
  'conversation',
30
+ ]
31
+
32
+ const PROJECT_THREAD_PAYLOAD_KEYS = [
27
33
  'threadId',
28
34
  'thread_id',
29
35
  'thread-id',
30
36
  'thread',
31
37
  ]
32
38
 
39
+ const PROJECT_PAYLOAD_SESSION_KEYS = [
40
+ ...PROJECT_SESSION_PAYLOAD_KEYS,
41
+ ...PROJECT_CONVERSATION_PAYLOAD_KEYS,
42
+ ...PROJECT_THREAD_PAYLOAD_KEYS,
43
+ ]
44
+
33
45
  const ENV_SESSION_KEYS = [
34
46
  'HELLOAGENTS_NOTIFY_SESSION_ID',
35
47
  'WT_SESSION',
@@ -46,7 +58,6 @@ const PROJECT_ENV_SESSION_KEYS = [
46
58
  ]
47
59
 
48
60
  const PROJECT_ALIAS_ENV_SESSION_KEYS = [
49
- 'HELLOAGENTS_NOTIFY_SESSION_ID',
50
61
  'WT_SESSION',
51
62
  'TERM_SESSION_ID',
52
63
  'KITTY_WINDOW_ID',
@@ -120,6 +131,9 @@ export {
120
131
  ENV_SESSION_KEYS,
121
132
  PAYLOAD_SESSION_KEYS,
122
133
  PROJECT_ALIAS_ENV_SESSION_KEYS,
134
+ PROJECT_CONVERSATION_PAYLOAD_KEYS,
123
135
  PROJECT_ENV_SESSION_KEYS,
124
136
  PROJECT_PAYLOAD_SESSION_KEYS,
137
+ PROJECT_SESSION_PAYLOAD_KEYS,
138
+ PROJECT_THREAD_PAYLOAD_KEYS,
125
139
  }
@@ -1,67 +1,23 @@
1
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
2
2
  import { dirname } from 'node:path'
3
3
 
4
- const STATE_META_BEGIN = '<!-- HELLOAGENTS_STATE_META'
5
- const STATE_META_END = 'HELLOAGENTS_STATE_META -->'
6
4
  export const AUTO_CREATED_STATE_MARKER = '由运行时自动创建;后续按实际任务重写'
7
5
 
8
6
  function normalizeText(content = '') {
9
7
  return String(content || '').replace(/^\uFEFF/, '')
10
8
  }
11
9
 
12
- function splitLines(content = '') {
13
- return normalizeText(content).replace(/\r\n/g, '\n').split('\n')
14
- }
15
-
16
- export function parseStateDocument(content = '') {
17
- const lines = splitLines(content)
18
- if (lines[0]?.trim() !== STATE_META_BEGIN) {
19
- return {
20
- hasMetadata: false,
21
- metadata: null,
22
- body: normalizeText(content),
23
- }
24
- }
25
-
26
- const endIndex = lines.findIndex((line, index) => index > 0 && line.trim() === STATE_META_END)
27
- if (endIndex < 0) {
28
- return {
29
- hasMetadata: false,
30
- metadata: null,
31
- body: normalizeText(content),
32
- }
33
- }
34
-
35
- const metadataText = lines.slice(1, endIndex).join('\n').trim()
36
- const body = lines.slice(endIndex + 1).join('\n').replace(/^\n+/, '')
37
- try {
38
- return {
39
- hasMetadata: true,
40
- metadata: JSON.parse(metadataText),
41
- body,
42
- }
43
- } catch {
44
- return {
45
- hasMetadata: false,
46
- metadata: null,
47
- body,
48
- }
49
- }
50
- }
51
-
52
10
  export function readStateDocument(filePath) {
53
11
  if (!filePath || !existsSync(filePath)) {
54
- return {
55
- hasMetadata: false,
56
- metadata: null,
57
- body: '',
58
- }
12
+ return { body: '' }
59
13
  }
60
14
 
61
- return parseStateDocument(readFileSync(filePath, 'utf-8'))
15
+ return {
16
+ body: normalizeText(readFileSync(filePath, 'utf-8')),
17
+ }
62
18
  }
63
19
 
64
- export function composeStateDocument({ metadata = {}, body = '' } = {}) {
20
+ export function composeStateDocument({ body = '' } = {}) {
65
21
  const normalizedBody = normalizeText(body).replace(/^\n+/, '')
66
22
  return normalizedBody ? `${normalizedBody.replace(/\n+$/, '')}\n` : ''
67
23
  }
@@ -70,7 +26,7 @@ export function looksLikeAutoCreatedState(body = '') {
70
26
  return normalizeText(body).includes(AUTO_CREATED_STATE_MARKER)
71
27
  }
72
28
 
73
- export function writeStateDocument(filePath, { metadata = {}, body = '' } = {}) {
29
+ export function writeStateDocument(filePath, { body = '' } = {}) {
74
30
  mkdirSync(dirname(filePath), { recursive: true })
75
- writeFileSync(filePath, composeStateDocument({ metadata, body }), 'utf-8')
31
+ writeFileSync(filePath, composeStateDocument({ body }), 'utf-8')
76
32
  }