@foothill/agent-move 1.0.9 → 1.0.10

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 (111) hide show
  1. package/README.md +46 -9
  2. package/package.json +1 -1
  3. package/packages/client/dist/assets/{BufferResource-Ddjob236.js → BufferResource-Dfd5uHKt.js} +1 -1
  4. package/packages/client/dist/assets/{CanvasRenderer-B0w6SYyW.js → CanvasRenderer-7Cv6xZVP.js} +1 -1
  5. package/packages/client/dist/assets/{Filter-NcMGuiK-.js → Filter-CBX7EB7j.js} +1 -1
  6. package/packages/client/dist/assets/{RenderTargetSystem-DgAzY5_U.js → RenderTargetSystem-ko-v73NG.js} +1 -1
  7. package/packages/client/dist/assets/{WebGLRenderer-DUWXDPIX.js → WebGLRenderer-vhPQEPUG.js} +1 -1
  8. package/packages/client/dist/assets/{WebGPURenderer-C1HbrllR.js → WebGPURenderer-Dwywvwqe.js} +1 -1
  9. package/packages/client/dist/assets/{browserAll-CaF1Fl0O.js → browserAll-QyCAT8_K.js} +1 -1
  10. package/packages/client/dist/assets/index-BPJtz4FL.js +722 -0
  11. package/packages/client/dist/assets/{webworkerAll-BJ6UhC7r.js → webworkerAll-hM-gNP7L.js} +1 -1
  12. package/packages/client/dist/index.html +1 -1
  13. package/packages/server/dist/config.d.ts +4 -0
  14. package/packages/server/dist/config.d.ts.map +1 -1
  15. package/packages/server/dist/config.js +5 -1
  16. package/packages/server/dist/config.js.map +1 -1
  17. package/packages/server/dist/index.d.ts.map +1 -1
  18. package/packages/server/dist/index.js +790 -77
  19. package/packages/server/dist/index.js.map +1 -1
  20. package/packages/server/dist/state/activity-processor.d.ts +1 -1
  21. package/packages/server/dist/state/activity-processor.d.ts.map +1 -1
  22. package/packages/server/dist/state/activity-processor.js +1 -1
  23. package/packages/server/dist/state/activity-processor.js.map +1 -1
  24. package/packages/server/dist/state/agent-state-manager.d.ts +1 -2
  25. package/packages/server/dist/state/agent-state-manager.d.ts.map +1 -1
  26. package/packages/server/dist/state/agent-state-manager.js +87 -2
  27. package/packages/server/dist/state/agent-state-manager.js.map +1 -1
  28. package/packages/server/dist/state/role-resolver.d.ts +1 -2
  29. package/packages/server/dist/state/role-resolver.d.ts.map +1 -1
  30. package/packages/server/dist/state/role-resolver.js.map +1 -1
  31. package/packages/server/dist/state/task-graph-manager.d.ts +12 -0
  32. package/packages/server/dist/state/task-graph-manager.d.ts.map +1 -1
  33. package/packages/server/dist/state/task-graph-manager.js +80 -0
  34. package/packages/server/dist/state/task-graph-manager.js.map +1 -1
  35. package/packages/server/dist/watcher/claude/claude-paths.d.ts +18 -0
  36. package/packages/server/dist/watcher/claude/claude-paths.d.ts.map +1 -0
  37. package/packages/server/dist/watcher/{claude-paths.js → claude/claude-paths.js} +47 -55
  38. package/packages/server/dist/watcher/claude/claude-paths.js.map +1 -0
  39. package/packages/server/dist/watcher/{file-watcher.d.ts → claude/claude-watcher.d.ts} +3 -3
  40. package/packages/server/dist/watcher/claude/claude-watcher.d.ts.map +1 -0
  41. package/packages/server/dist/watcher/{file-watcher.js → claude/claude-watcher.js} +59 -65
  42. package/packages/server/dist/watcher/claude/claude-watcher.js.map +1 -0
  43. package/packages/server/dist/watcher/claude/jsonl-parser.d.ts +6 -0
  44. package/packages/server/dist/watcher/claude/jsonl-parser.d.ts.map +1 -0
  45. package/packages/server/dist/watcher/{jsonl-parser.js → claude/jsonl-parser.js} +1 -1
  46. package/packages/server/dist/watcher/claude/jsonl-parser.js.map +1 -0
  47. package/packages/server/dist/watcher/codex/codex-parser.d.ts +30 -0
  48. package/packages/server/dist/watcher/codex/codex-parser.d.ts.map +1 -0
  49. package/packages/server/dist/watcher/codex/codex-parser.js +326 -0
  50. package/packages/server/dist/watcher/codex/codex-parser.js.map +1 -0
  51. package/packages/server/dist/watcher/codex/codex-paths.d.ts +35 -0
  52. package/packages/server/dist/watcher/codex/codex-paths.d.ts.map +1 -0
  53. package/packages/server/dist/watcher/codex/codex-paths.js +46 -0
  54. package/packages/server/dist/watcher/codex/codex-paths.js.map +1 -0
  55. package/packages/server/dist/watcher/codex/codex-watcher.d.ts +42 -0
  56. package/packages/server/dist/watcher/codex/codex-watcher.d.ts.map +1 -0
  57. package/packages/server/dist/watcher/codex/codex-watcher.js +577 -0
  58. package/packages/server/dist/watcher/codex/codex-watcher.js.map +1 -0
  59. package/packages/server/dist/watcher/opencode/opencode-parser.d.ts +1 -1
  60. package/packages/server/dist/watcher/opencode/opencode-parser.d.ts.map +1 -1
  61. package/packages/server/dist/watcher/opencode/opencode-parser.js +31 -2
  62. package/packages/server/dist/watcher/opencode/opencode-paths.d.ts +1 -1
  63. package/packages/server/dist/watcher/opencode/opencode-paths.d.ts.map +1 -1
  64. package/packages/server/dist/watcher/opencode/opencode-paths.js +1 -0
  65. package/packages/server/dist/watcher/opencode/opencode-paths.js.map +1 -1
  66. package/packages/server/dist/watcher/opencode/opencode-watcher.d.ts.map +1 -1
  67. package/packages/server/dist/watcher/opencode/opencode-watcher.js +48 -10
  68. package/packages/server/dist/watcher/opencode/opencode-watcher.js.map +1 -1
  69. package/packages/server/dist/watcher/path-utils.d.ts +10 -0
  70. package/packages/server/dist/watcher/path-utils.d.ts.map +1 -0
  71. package/packages/server/dist/watcher/path-utils.js +38 -0
  72. package/packages/server/dist/watcher/path-utils.js.map +1 -0
  73. package/packages/server/dist/watcher/pi/pi-parser.d.ts +19 -0
  74. package/packages/server/dist/watcher/pi/pi-parser.d.ts.map +1 -0
  75. package/packages/server/dist/watcher/pi/pi-parser.js +307 -0
  76. package/packages/server/dist/watcher/pi/pi-parser.js.map +1 -0
  77. package/packages/server/dist/watcher/pi/pi-paths.d.ts +28 -0
  78. package/packages/server/dist/watcher/pi/pi-paths.d.ts.map +1 -0
  79. package/packages/server/dist/watcher/pi/pi-paths.js +86 -0
  80. package/packages/server/dist/watcher/pi/pi-paths.js.map +1 -0
  81. package/packages/server/dist/watcher/pi/pi-watcher.d.ts +36 -0
  82. package/packages/server/dist/watcher/pi/pi-watcher.d.ts.map +1 -0
  83. package/packages/server/dist/watcher/pi/pi-watcher.js +593 -0
  84. package/packages/server/dist/watcher/pi/pi-watcher.js.map +1 -0
  85. package/packages/server/dist/watcher/session-scanner.d.ts +9 -3
  86. package/packages/server/dist/watcher/session-scanner.d.ts.map +1 -1
  87. package/packages/server/dist/watcher/session-scanner.js +11 -9
  88. package/packages/server/dist/watcher/session-scanner.js.map +1 -1
  89. package/packages/server/dist/watcher/types.d.ts +30 -0
  90. package/packages/server/dist/watcher/types.d.ts.map +1 -0
  91. package/packages/server/dist/watcher/types.js +14 -0
  92. package/packages/server/dist/watcher/types.js.map +1 -0
  93. package/packages/shared/dist/constants/colors.d.ts +1 -1
  94. package/packages/shared/dist/constants/colors.js +1 -1
  95. package/packages/shared/dist/constants/colors.js.map +1 -1
  96. package/packages/shared/dist/constants/tools.d.ts.map +1 -1
  97. package/packages/shared/dist/constants/tools.js +30 -1
  98. package/packages/shared/dist/constants/tools.js.map +1 -1
  99. package/packages/shared/dist/index.d.ts +1 -1
  100. package/packages/shared/dist/index.d.ts.map +1 -1
  101. package/packages/shared/dist/types/agent.d.ts +3 -0
  102. package/packages/shared/dist/types/agent.d.ts.map +1 -1
  103. package/packages/client/dist/assets/index-Dh8yWoLP.js +0 -711
  104. package/packages/server/dist/watcher/claude-paths.d.ts +0 -32
  105. package/packages/server/dist/watcher/claude-paths.d.ts.map +0 -1
  106. package/packages/server/dist/watcher/claude-paths.js.map +0 -1
  107. package/packages/server/dist/watcher/file-watcher.d.ts.map +0 -1
  108. package/packages/server/dist/watcher/file-watcher.js.map +0 -1
  109. package/packages/server/dist/watcher/jsonl-parser.d.ts +0 -21
  110. package/packages/server/dist/watcher/jsonl-parser.d.ts.map +0 -1
  111. package/packages/server/dist/watcher/jsonl-parser.js.map +0 -1
@@ -1,6 +1,38 @@
1
- // dist/watcher/claude-paths.js
2
- import { existsSync } from "fs";
1
+ // dist/watcher/claude/claude-paths.js
3
2
  import { join } from "path";
3
+ import { existsSync } from "fs";
4
+ function resolveEncodedPath(root, segments) {
5
+ try {
6
+ const parts = segments.split("-").filter(Boolean);
7
+ let currentPath = root;
8
+ let lastName = "";
9
+ let i = 0;
10
+ while (i < parts.length) {
11
+ let found = false;
12
+ const maxLen = Math.min(parts.length - i, 6);
13
+ for (let len = 1; len <= maxLen; len++) {
14
+ const segment = parts.slice(i, i + len).join("-");
15
+ for (const prefix of ["", "."]) {
16
+ const testPath = join(currentPath, prefix + segment);
17
+ if (existsSync(testPath)) {
18
+ currentPath = testPath;
19
+ lastName = prefix + segment;
20
+ i += len;
21
+ found = true;
22
+ break;
23
+ }
24
+ }
25
+ if (found)
26
+ break;
27
+ }
28
+ if (!found)
29
+ break;
30
+ }
31
+ return lastName || null;
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
4
36
  var ClaudePaths = class {
5
37
  /**
6
38
  * Parse a JSONL session file path to extract project info.
@@ -13,6 +45,7 @@ var ClaudePaths = class {
13
45
  const projectsIdx = parts.indexOf("projects");
14
46
  if (projectsIdx === -1 || projectsIdx + 1 >= parts.length) {
15
47
  return {
48
+ agentType: "claude",
16
49
  projectPath: "unknown",
17
50
  projectName: "Unknown",
18
51
  isSubagent: false,
@@ -26,6 +59,7 @@ var ClaudePaths = class {
26
59
  const isSubagent = depthAfterProject > 1;
27
60
  const parentSessionId = isSubagent ? parts[projectsIdx + 2] : null;
28
61
  return {
62
+ agentType: "claude",
29
63
  projectPath: encodedProjectName,
30
64
  projectName,
31
65
  isSubagent,
@@ -39,64 +73,22 @@ var ClaudePaths = class {
39
73
  * e.g., "C--projects-fts-temp-agent-move" → "agent-move"
40
74
  */
41
75
  decodeProjectName(encoded) {
42
- const resolved = this.resolveToFolderName(encoded);
43
- if (resolved)
44
- return resolved;
76
+ const driveMatch = encoded.match(/^([A-Za-z])--(.*)/);
77
+ const unixMatch = !driveMatch && encoded.match(/^-(.*)/);
78
+ if (driveMatch) {
79
+ const resolved = resolveEncodedPath(driveMatch[1] + ":/", driveMatch[2]);
80
+ if (resolved)
81
+ return resolved;
82
+ } else if (unixMatch) {
83
+ const resolved = resolveEncodedPath("/", unixMatch[1]);
84
+ if (resolved)
85
+ return resolved;
86
+ }
45
87
  const parts = encoded.split("-").filter((p) => p.length > 0);
46
88
  if (parts.length <= 2)
47
89
  return parts.join("/");
48
90
  return parts.slice(-2).join("/");
49
91
  }
50
- /**
51
- * Greedily resolve the encoded path against the filesystem.
52
- * Tries each dash-segment as a directory, joining multiple segments
53
- * when a single one doesn't exist (to handle dashes in folder names).
54
- */
55
- resolveToFolderName(encoded) {
56
- try {
57
- let root;
58
- let rest;
59
- const driveMatch = encoded.match(/^([A-Za-z])--(.*)/);
60
- const unixMatch = !driveMatch && encoded.match(/^-(.*)/);
61
- if (driveMatch) {
62
- root = driveMatch[1] + ":/";
63
- rest = driveMatch[2];
64
- } else if (unixMatch) {
65
- root = "/";
66
- rest = unixMatch[1];
67
- } else {
68
- return null;
69
- }
70
- const parts = rest.split("-").filter(Boolean);
71
- let currentPath = root;
72
- let lastName = "";
73
- let i = 0;
74
- while (i < parts.length) {
75
- let found = false;
76
- const maxLen = Math.min(parts.length - i, 6);
77
- for (let len = 1; len <= maxLen; len++) {
78
- const segment = parts.slice(i, i + len).join("-");
79
- for (const prefix of ["", "."]) {
80
- const testPath = join(currentPath, prefix + segment);
81
- if (existsSync(testPath)) {
82
- currentPath = testPath;
83
- lastName = prefix + segment;
84
- i += len;
85
- found = true;
86
- break;
87
- }
88
- }
89
- if (found)
90
- break;
91
- }
92
- if (!found)
93
- break;
94
- }
95
- return lastName || null;
96
- } catch {
97
- return null;
98
- }
99
- }
100
92
  };
101
93
  var claudePaths = new ClaudePaths();
102
94
  export {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-paths.js","sourceRoot":"","sources":["../../../src/watcher/claude/claude-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGtD,MAAM,WAAW;IACf;;;;OAIG;IACH,gBAAgB,CAAC,QAAgB;QAC/B,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAEpC,8BAA8B;QAC9B,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,WAAW,KAAK,CAAC,CAAC,IAAI,WAAW,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAC1D,OAAO;gBACL,SAAS,EAAE,QAAQ;gBACnB,WAAW,EAAE,SAAS;gBACtB,WAAW,EAAE,SAAS;gBACtB,UAAU,EAAE,KAAK;gBACjB,UAAU,EAAE,SAAS;gBACrB,eAAe,EAAE,IAAI;aACtB,CAAC;QACJ,CAAC;QAED,MAAM,kBAAkB,GAAG,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;QAClD,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;QAE/D,8FAA8F;QAC9F,4FAA4F;QAC5F,MAAM,iBAAiB,GAAG,KAAK,CAAC,MAAM,GAAG,WAAW,GAAG,CAAC,CAAC;QACzD,MAAM,UAAU,GAAG,iBAAiB,GAAG,CAAC,CAAC;QAEzC,oDAAoD;QACpD,8DAA8D;QAC9D,MAAM,eAAe,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAEnE,OAAO;YACL,SAAS,EAAE,QAAQ;YACnB,WAAW,EAAE,kBAAkB;YAC/B,WAAW;YACX,UAAU;YACV,UAAU,EAAE,kBAAkB;YAC9B,eAAe;SAChB,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,iBAAiB,CAAC,OAAe;QAC/B,8DAA8D;QAC9D,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACtD,uDAAuD;QACvD,MAAM,SAAS,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAEzD,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YACzE,IAAI,QAAQ;gBAAE,OAAO,QAAQ,CAAC;QAChC,CAAC;aAAM,IAAI,SAAS,EAAE,CAAC;YACrB,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YACvD,IAAI,QAAQ;gBAAE,OAAO,QAAQ,CAAC;QAChC,CAAC;QAED,wCAAwC;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC7D,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9C,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC"}
@@ -1,5 +1,5 @@
1
- import type { AgentStateManager } from '../state/agent-state-manager.js';
2
- import type { AgentWatcher } from './agent-watcher.js';
1
+ import type { AgentStateManager } from '../../state/agent-state-manager.js';
2
+ import type { AgentWatcher } from '../agent-watcher.js';
3
3
  export declare class FileWatcher implements AgentWatcher {
4
4
  private claudeHome;
5
5
  private stateManager;
@@ -14,4 +14,4 @@ export declare class FileWatcher implements AgentWatcher {
14
14
  private processFile;
15
15
  private doProcessFile;
16
16
  }
17
- //# sourceMappingURL=file-watcher.d.ts.map
17
+ //# sourceMappingURL=claude-watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-watcher.d.ts","sourceRoot":"","sources":["../../../src/watcher/claude/claude-watcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAI5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,qBAAa,WAAY,YAAW,YAAY;IAQ5C,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,YAAY;IARtB,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,MAAM,CAAqB;IACnC,8EAA8E;IAC9E,OAAO,CAAC,SAAS,CAAoC;gBAG3C,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,iBAAiB;IAGnC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B5B,IAAI,IAAI,IAAI;IAMZ,OAAO,CAAC,WAAW;YAcL,aAAa;CA4C5B"}
@@ -1,9 +1,9 @@
1
- // dist/watcher/file-watcher.js
1
+ // dist/watcher/claude/claude-watcher.js
2
2
  import chokidar from "chokidar";
3
3
  import { stat as stat2, open } from "fs/promises";
4
4
  import { join as join4, basename } from "path";
5
- import { existsSync } from "fs";
6
5
  import { join } from "path";
6
+ import { existsSync } from "fs";
7
7
  import { readdir, stat } from "fs/promises";
8
8
  import { join as join3 } from "path";
9
9
  import { homedir } from "os";
@@ -99,6 +99,38 @@ var JsonlParser = class {
99
99
  return null;
100
100
  }
101
101
  };
102
+ function resolveEncodedPath(root, segments) {
103
+ try {
104
+ const parts = segments.split("-").filter(Boolean);
105
+ let currentPath = root;
106
+ let lastName = "";
107
+ let i = 0;
108
+ while (i < parts.length) {
109
+ let found = false;
110
+ const maxLen = Math.min(parts.length - i, 6);
111
+ for (let len = 1; len <= maxLen; len++) {
112
+ const segment = parts.slice(i, i + len).join("-");
113
+ for (const prefix of ["", "."]) {
114
+ const testPath = join(currentPath, prefix + segment);
115
+ if (existsSync(testPath)) {
116
+ currentPath = testPath;
117
+ lastName = prefix + segment;
118
+ i += len;
119
+ found = true;
120
+ break;
121
+ }
122
+ }
123
+ if (found)
124
+ break;
125
+ }
126
+ if (!found)
127
+ break;
128
+ }
129
+ return lastName || null;
130
+ } catch {
131
+ return null;
132
+ }
133
+ }
102
134
  var ClaudePaths = class {
103
135
  /**
104
136
  * Parse a JSONL session file path to extract project info.
@@ -111,6 +143,7 @@ var ClaudePaths = class {
111
143
  const projectsIdx = parts.indexOf("projects");
112
144
  if (projectsIdx === -1 || projectsIdx + 1 >= parts.length) {
113
145
  return {
146
+ agentType: "claude",
114
147
  projectPath: "unknown",
115
148
  projectName: "Unknown",
116
149
  isSubagent: false,
@@ -124,6 +157,7 @@ var ClaudePaths = class {
124
157
  const isSubagent = depthAfterProject > 1;
125
158
  const parentSessionId = isSubagent ? parts[projectsIdx + 2] : null;
126
159
  return {
160
+ agentType: "claude",
127
161
  projectPath: encodedProjectName,
128
162
  projectName,
129
163
  isSubagent,
@@ -137,64 +171,22 @@ var ClaudePaths = class {
137
171
  * e.g., "C--projects-fts-temp-agent-move" → "agent-move"
138
172
  */
139
173
  decodeProjectName(encoded) {
140
- const resolved = this.resolveToFolderName(encoded);
141
- if (resolved)
142
- return resolved;
174
+ const driveMatch = encoded.match(/^([A-Za-z])--(.*)/);
175
+ const unixMatch = !driveMatch && encoded.match(/^-(.*)/);
176
+ if (driveMatch) {
177
+ const resolved = resolveEncodedPath(driveMatch[1] + ":/", driveMatch[2]);
178
+ if (resolved)
179
+ return resolved;
180
+ } else if (unixMatch) {
181
+ const resolved = resolveEncodedPath("/", unixMatch[1]);
182
+ if (resolved)
183
+ return resolved;
184
+ }
143
185
  const parts = encoded.split("-").filter((p) => p.length > 0);
144
186
  if (parts.length <= 2)
145
187
  return parts.join("/");
146
188
  return parts.slice(-2).join("/");
147
189
  }
148
- /**
149
- * Greedily resolve the encoded path against the filesystem.
150
- * Tries each dash-segment as a directory, joining multiple segments
151
- * when a single one doesn't exist (to handle dashes in folder names).
152
- */
153
- resolveToFolderName(encoded) {
154
- try {
155
- let root;
156
- let rest;
157
- const driveMatch = encoded.match(/^([A-Za-z])--(.*)/);
158
- const unixMatch = !driveMatch && encoded.match(/^-(.*)/);
159
- if (driveMatch) {
160
- root = driveMatch[1] + ":/";
161
- rest = driveMatch[2];
162
- } else if (unixMatch) {
163
- root = "/";
164
- rest = unixMatch[1];
165
- } else {
166
- return null;
167
- }
168
- const parts = rest.split("-").filter(Boolean);
169
- let currentPath = root;
170
- let lastName = "";
171
- let i = 0;
172
- while (i < parts.length) {
173
- let found = false;
174
- const maxLen = Math.min(parts.length - i, 6);
175
- for (let len = 1; len <= maxLen; len++) {
176
- const segment = parts.slice(i, i + len).join("-");
177
- for (const prefix of ["", "."]) {
178
- const testPath = join(currentPath, prefix + segment);
179
- if (existsSync(testPath)) {
180
- currentPath = testPath;
181
- lastName = prefix + segment;
182
- i += len;
183
- found = true;
184
- break;
185
- }
186
- }
187
- if (found)
188
- break;
189
- }
190
- if (!found)
191
- break;
192
- }
193
- return lastName || null;
194
- } catch {
195
- return null;
196
- }
197
- }
198
190
  };
199
191
  var claudePaths = new ClaudePaths();
200
192
  var config = {
@@ -208,22 +200,25 @@ var config = {
208
200
  activeThresholdMs: 10 * 60 * 1e3,
209
201
  // 10 minutes
210
202
  /** Enable OpenCode session watching (auto-detected if storage dir exists) */
211
- enableOpenCode: process.env.AGENT_MOVE_OPENCODE !== "false"
203
+ enableOpenCode: process.env.AGENT_MOVE_OPENCODE !== "false",
204
+ /** Enable pi coding agent session watching (auto-detected if sessions dir exists) */
205
+ enablePi: process.env.AGENT_MOVE_PI !== "false",
206
+ /** Enable Codex CLI session watching (auto-detected if sessions dir exists) */
207
+ enableCodex: process.env.AGENT_MOVE_CODEX !== "false"
212
208
  };
213
209
  var SessionScanner = class {
214
- claudeHome;
215
- constructor(claudeHome) {
216
- this.claudeHome = claudeHome;
210
+ rootDir;
211
+ constructor(rootDir) {
212
+ this.rootDir = rootDir;
217
213
  }
218
- /** Find all recently active JSONL session files */
214
+ /** Find the most recently modified JSONL per project subdirectory */
219
215
  async scan() {
220
216
  const results = [];
221
- const projectsDir = join3(this.claudeHome, "projects");
222
217
  try {
223
- const projects = await readdir(projectsDir);
218
+ const projects = await readdir(this.rootDir);
224
219
  const now = Date.now();
225
220
  for (const project of projects) {
226
- const projectDir = join3(projectsDir, project);
221
+ const projectDir = join3(this.rootDir, project);
227
222
  try {
228
223
  const projectStat = await stat(projectDir);
229
224
  if (!projectStat.isDirectory())
@@ -253,7 +248,6 @@ var SessionScanner = class {
253
248
  }
254
249
  }
255
250
  } catch {
256
- console.log("No projects directory found \u2014 will wait for new sessions");
257
251
  }
258
252
  return results;
259
253
  }
@@ -271,7 +265,7 @@ var FileWatcher = class {
271
265
  this.stateManager = stateManager;
272
266
  }
273
267
  async start() {
274
- const scanner = new SessionScanner(this.claudeHome);
268
+ const scanner = new SessionScanner(join4(this.claudeHome, "projects"));
275
269
  const existingFiles = await scanner.scan();
276
270
  for (const file of existingFiles) {
277
271
  await this.processFile(file);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-watcher.js","sourceRoot":"","sources":["../../../src/watcher/claude/claude-watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ParsedActivity } from '../types.js';
2
+ export declare class JsonlParser {
3
+ parseLine(line: string): ParsedActivity | null;
4
+ private extractActivity;
5
+ }
6
+ //# sourceMappingURL=jsonl-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl-parser.d.ts","sourceRoot":"","sources":["../../../src/watcher/claude/jsonl-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,qBAAa,WAAW;IACtB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAS9C,OAAO,CAAC,eAAe;CAsGxB"}
@@ -1,4 +1,4 @@
1
- // dist/watcher/jsonl-parser.js
1
+ // dist/watcher/claude/jsonl-parser.js
2
2
  var JsonlParser = class {
3
3
  parseLine(line) {
4
4
  try {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl-parser.js","sourceRoot":"","sources":["../../../src/watcher/claude/jsonl-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { ParsedActivity } from '../types.js';
2
+ import type { CodexSessionMeta } from './codex-paths.js';
3
+ export interface CodexEnvelope {
4
+ timestamp: string;
5
+ type: string;
6
+ payload: Record<string, unknown>;
7
+ }
8
+ export declare class CodexParser {
9
+ /**
10
+ * Parse a single JSONL line into the envelope structure.
11
+ */
12
+ parseRaw(line: string): CodexEnvelope | null;
13
+ /**
14
+ * Try to extract session_meta payload. Returns null if not a session_meta envelope.
15
+ */
16
+ tryGetSessionMeta(envelope: CodexEnvelope): CodexSessionMeta | null;
17
+ /**
18
+ * Try to extract model from a turn_context envelope. Returns null otherwise.
19
+ */
20
+ tryGetModel(envelope: CodexEnvelope): string | null;
21
+ /**
22
+ * Parse a Codex JSONL envelope into a ParsedActivity.
23
+ * Model is passed in from the watcher (tracked per-file).
24
+ * Returns null for non-actionable entries.
25
+ */
26
+ parseEntry(envelope: CodexEnvelope, model: string | null): ParsedActivity | null;
27
+ private parseResponseItem;
28
+ private parseEventMsg;
29
+ }
30
+ //# sourceMappingURL=codex-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-parser.d.ts","sourceRoot":"","sources":["../../../src/watcher/codex/codex-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAIzD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AA+BD,qBAAa,WAAW;IACtB;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAY5C;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,gBAAgB,GAAG,IAAI;IAKnE;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI;IAMnD;;;;OAIG;IACH,UAAU,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,GAAG,IAAI;IAUhF,OAAO,CAAC,iBAAiB;IA4CzB,OAAO,CAAC,aAAa;CAwCtB"}