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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +17 -13
- package/README_CN.md +17 -13
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/scripts/cli-branch.mjs +2 -5
- package/scripts/cli-codex-config.mjs +187 -26
- package/scripts/cli-codex.mjs +10 -14
- package/scripts/cli-doctor-codex.mjs +18 -15
- package/scripts/cli-doctor.mjs +48 -15
- package/scripts/cli-host-detect.mjs +38 -5
- package/scripts/cli-lifecycle-hosts.mjs +48 -20
- package/scripts/cli-messages.mjs +9 -8
- package/scripts/cli-process.mjs +16 -0
- package/scripts/cli-runtime-root.mjs +55 -12
- package/scripts/cli-toml.mjs +4 -0
- package/scripts/project-session-cleanup.mjs +0 -32
- package/scripts/runtime-scope.mjs +185 -100
- package/scripts/session-capsule.mjs +6 -65
- package/scripts/session-token.mjs +16 -2
- package/scripts/state-document.mjs +7 -51
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync,
|
|
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.
|
|
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
|
|
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
|
|
15
|
+
return {
|
|
16
|
+
body: normalizeText(readFileSync(filePath, 'utf-8')),
|
|
17
|
+
}
|
|
62
18
|
}
|
|
63
19
|
|
|
64
|
-
export function composeStateDocument({
|
|
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, {
|
|
29
|
+
export function writeStateDocument(filePath, { body = '' } = {}) {
|
|
74
30
|
mkdirSync(dirname(filePath), { recursive: true })
|
|
75
|
-
writeFileSync(filePath, composeStateDocument({
|
|
31
|
+
writeFileSync(filePath, composeStateDocument({ body }), 'utf-8')
|
|
76
32
|
}
|