gitdone-agent 0.1.2 → 0.1.3

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/index.js +74 -13
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -3,10 +3,31 @@
3
3
  // Usage: bun index.js --key=gdo_xxx --name=my-repo --path=/path/to/repo [--install]
4
4
 
5
5
  import { execSync, spawn } from 'node:child_process'
6
- import { existsSync, writeFileSync, unlinkSync } from 'node:fs'
6
+ import { existsSync, writeFileSync, unlinkSync, mkdirSync, copyFileSync, appendFileSync } from 'node:fs'
7
7
  import { resolve, join } from 'node:path'
8
8
  import { homedir } from 'node:os'
9
9
 
10
+ // ─── Stable agent dir + logging ────────────────────────────────────────────────
11
+ // Everything persistent lives here: a stable copy of the agent script (so
12
+ // autostart never points at a purged npx temp dir) and a per-repo log file
13
+ // (so failures are visible even when the agent runs in a hidden window).
14
+
15
+ const AGENT_DIR = join(homedir(), '.gitdone-agent')
16
+
17
+ function ensureAgentDir() {
18
+ if (!existsSync(AGENT_DIR)) mkdirSync(AGENT_DIR, { recursive: true })
19
+ }
20
+
21
+ let LOG_PATH = null
22
+
23
+ function log(msg) {
24
+ const line = `[${new Date().toISOString()}] ${msg}`
25
+ console.log(line)
26
+ if (LOG_PATH) {
27
+ try { appendFileSync(LOG_PATH, line + '\n') } catch { /* best-effort */ }
28
+ }
29
+ }
30
+
10
31
  // ─── Arg parsing ─────────────────────────────────────────────────────────────
11
32
 
12
33
  function parseArgs() {
@@ -27,17 +48,18 @@ function parseArgs() {
27
48
  const url = (args.url ?? 'https://gitdone.eu').replace(/\/$/, '')
28
49
  const install = 'install' in args
29
50
  const uninstall = 'uninstall' in args
51
+ const doctor = 'doctor' in args
30
52
 
31
- if (!key && !uninstall) {
53
+ if (!key && !uninstall && !doctor) {
32
54
  console.error('Error: --key is required (e.g. --key=gdo_xxx)')
33
55
  process.exit(1)
34
56
  }
35
- if (!existsSync(repoPath) && !uninstall) {
57
+ if (!existsSync(repoPath) && !uninstall && !doctor) {
36
58
  console.error(`Error: path does not exist: ${repoPath}`)
37
59
  process.exit(1)
38
60
  }
39
61
 
40
- return { key, path: repoPath, name, projectId, interval, url, install, uninstall }
62
+ return { key, path: repoPath, name, projectId, interval, url, install, uninstall, doctor }
41
63
  }
42
64
 
43
65
  // ─── Windows auto-start ───────────────────────────────────────────────────────
@@ -53,8 +75,19 @@ function getNodePath() {
53
75
  }
54
76
 
55
77
  function installStartup({ name, key, path: repoPath, url, interval, projectId }) {
78
+ ensureAgentDir()
56
79
  const nodePath = getNodePath()
57
- const agentPath = resolve(process.argv[1])
80
+
81
+ // Copy this script to a stable location. process.argv[1] may point inside an
82
+ // npx cache dir that gets purged later — referencing it from autostart would
83
+ // silently break on the next login. A stable copy survives.
84
+ const stableAgent = join(AGENT_DIR, 'agent.mjs')
85
+ try {
86
+ copyFileSync(resolve(process.argv[1]), stableAgent)
87
+ } catch (err) {
88
+ console.error(`Warning: could not copy agent to ${stableAgent}: ${err.message}`)
89
+ }
90
+ const agentPath = existsSync(stableAgent) ? stableAgent : resolve(process.argv[1])
58
91
  const startupDir = getStartupDir()
59
92
 
60
93
  const argLine = [
@@ -76,9 +109,11 @@ function installStartup({ name, key, path: repoPath, url, interval, projectId })
76
109
  writeFileSync(vbsPath, vbs, 'utf8')
77
110
 
78
111
  console.log(`✓ Инсталиран! При следващото влизане в Windows агентът ще стартира автоматично.`)
79
- console.log(` Файл: ${vbsPath}`)
80
- console.log(` Repo : ${repoPath}`)
81
- console.log(` Name : ${name}`)
112
+ console.log(` Файл : ${vbsPath}`)
113
+ console.log(` Агент : ${agentPath}`)
114
+ console.log(` Repo : ${repoPath}`)
115
+ console.log(` Name : ${name}`)
116
+ console.log(` Лог : ${join(AGENT_DIR, `${name}.log`)}`)
82
117
  console.log()
83
118
  }
84
119
 
@@ -92,6 +127,20 @@ function uninstallStartup(name) {
92
127
  }
93
128
  }
94
129
 
130
+ // ─── Doctor: print where things are so "offline" is debuggable ─────────────────
131
+
132
+ function runDoctor(name) {
133
+ const vbsPath = join(getStartupDir(), `gitdone-${name}.vbs`)
134
+ const stableAgent = join(AGENT_DIR, 'agent.mjs')
135
+ const logPath = join(AGENT_DIR, `${name}.log`)
136
+ console.log('gitdone-agent doctor')
137
+ console.log(` node : ${getNodePath()}`)
138
+ console.log(` agent dir : ${AGENT_DIR} ${existsSync(AGENT_DIR) ? '(ok)' : '(MISSING)'}`)
139
+ console.log(` stable agent : ${stableAgent} ${existsSync(stableAgent) ? '(ok)' : '(not installed)'}`)
140
+ console.log(` autostart vbs : ${vbsPath} ${existsSync(vbsPath) ? '(ok)' : '(not installed)'}`)
141
+ console.log(` log file : ${logPath} ${existsSync(logPath) ? '(ok)' : '(none yet)'}`)
142
+ }
143
+
95
144
  // ─── Git helpers ─────────────────────────────────────────────────────────────
96
145
 
97
146
  function git(cmd, cwd) {
@@ -174,11 +223,11 @@ async function executeCommand(cmd, repoPath, url, key) {
174
223
  const out = git('git pull', repoPath)
175
224
  result = out || 'pulled'
176
225
  }
177
- console.log(`[${new Date().toLocaleTimeString()}] ✓ ${cmd.type}: ${result}`)
226
+ log(`✓ ${cmd.type}: ${result}`)
178
227
  } catch (err) {
179
228
  status = 'error'
180
229
  result = err.message
181
- console.error(`[${new Date().toLocaleTimeString()}] ✗ ${cmd.type} failed: ${result}`)
230
+ log(`✗ ${cmd.type} failed: ${result}`)
182
231
  }
183
232
  await reportCommandResult(url, key, cmd.id, status, result)
184
233
  }
@@ -203,7 +252,19 @@ async function push({ url, key, name, projectId, repoPath, snapshot }) {
203
252
 
204
253
  async function main() {
205
254
  const config = parseArgs()
206
- const { key, path: repoPath, name, projectId, interval, url, install, uninstall } = config
255
+ const { key, path: repoPath, name, projectId, interval, url, install, uninstall, doctor } = config
256
+
257
+ if (doctor) {
258
+ runDoctor(name)
259
+ process.exit(0)
260
+ }
261
+
262
+ // Route all runtime logs to a per-repo file too, so a silently-running
263
+ // (hidden-window) agent still leaves a trail to debug "why is it offline".
264
+ if (!uninstall) {
265
+ ensureAgentDir()
266
+ LOG_PATH = join(AGENT_DIR, `${name}.log`)
267
+ }
207
268
 
208
269
  if (uninstall) {
209
270
  uninstallStartup(name)
@@ -243,9 +304,9 @@ async function main() {
243
304
  const snapshot = getSnapshot(repoPath)
244
305
  await push({ url, key, name, projectId, repoPath, snapshot })
245
306
  const changed = snapshot.modified.length + snapshot.staged.length
246
- console.log(`[${new Date().toLocaleTimeString()}] ✓ pushed — branch: ${snapshot.branch}, changes: ${changed}`)
307
+ log(`✓ pushed — branch: ${snapshot.branch}, changes: ${changed}`)
247
308
  } catch (err) {
248
- console.error(`[${new Date().toLocaleTimeString()}] ✗ error: ${err.message}`)
309
+ log(`✗ error: ${err.message}`)
249
310
  }
250
311
  }
251
312
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitdone-agent",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Local git agent for gitdone — watches a local repo and sends snapshots to gitdone.eu",
5
5
  "type": "module",
6
6
  "bin": {