@jamesmurdza/opencode-daytona 0.1.22 → 0.1.23

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 (117) hide show
  1. package/.opencode/plugin/daytona/core/logger.d.ts +2 -2
  2. package/.opencode/plugin/daytona/core/logger.js +28 -15
  3. package/.opencode/plugin/daytona/core/logger.js.map +1 -1
  4. package/.opencode/plugin/daytona/core/project-data-storage.d.ts +11 -7
  5. package/.opencode/plugin/daytona/core/project-data-storage.js +84 -43
  6. package/.opencode/plugin/daytona/core/project-data-storage.js.map +1 -1
  7. package/.opencode/plugin/daytona/core/session-manager.d.ts +4 -1
  8. package/.opencode/plugin/daytona/core/session-manager.js +92 -33
  9. package/.opencode/plugin/daytona/core/session-manager.js.map +1 -1
  10. package/.opencode/plugin/daytona/core/toast.d.ts +4 -1
  11. package/.opencode/plugin/daytona/core/toast.js +6 -3
  12. package/.opencode/plugin/daytona/core/toast.js.map +1 -1
  13. package/.opencode/plugin/daytona/core/types.d.ts +10 -8
  14. package/.opencode/plugin/daytona/core/types.js +10 -6
  15. package/.opencode/plugin/daytona/core/types.js.map +1 -1
  16. package/.opencode/plugin/daytona/git/host-git-manager.d.ts +25 -5
  17. package/.opencode/plugin/daytona/git/host-git-manager.js +191 -44
  18. package/.opencode/plugin/daytona/git/host-git-manager.js.map +1 -1
  19. package/.opencode/plugin/daytona/git/index.d.ts +4 -1
  20. package/.opencode/plugin/daytona/git/index.js +9 -1
  21. package/.opencode/plugin/daytona/git/index.js.map +1 -1
  22. package/.opencode/plugin/daytona/git/sandbox-git-manager.d.ts +4 -1
  23. package/.opencode/plugin/daytona/git/sandbox-git-manager.js +19 -11
  24. package/.opencode/plugin/daytona/git/sandbox-git-manager.js.map +1 -1
  25. package/.opencode/plugin/daytona/git/session-git-manager.d.ts +11 -2
  26. package/.opencode/plugin/daytona/git/session-git-manager.js +39 -22
  27. package/.opencode/plugin/daytona/git/session-git-manager.js.map +1 -1
  28. package/.opencode/plugin/daytona/index.d.ts +131 -23
  29. package/.opencode/plugin/daytona/index.js +27 -16
  30. package/.opencode/plugin/daytona/index.js.map +1 -1
  31. package/.opencode/plugin/daytona/plugins/custom-tools.d.ts +129 -5
  32. package/.opencode/plugin/daytona/plugins/custom-tools.js +15 -15
  33. package/.opencode/plugin/daytona/plugins/custom-tools.js.map +1 -1
  34. package/.opencode/plugin/daytona/plugins/session-events.d.ts +10 -0
  35. package/.opencode/plugin/daytona/plugins/session-events.js +51 -0
  36. package/.opencode/plugin/daytona/plugins/session-events.js.map +1 -0
  37. package/.opencode/plugin/daytona/plugins/system-transform.d.ts +8 -5
  38. package/.opencode/plugin/daytona/plugins/system-transform.js +19 -16
  39. package/.opencode/plugin/daytona/plugins/system-transform.js.map +1 -1
  40. package/.opencode/plugin/daytona/tools/bash.d.ts +6 -2
  41. package/.opencode/plugin/daytona/tools/bash.js +12 -4
  42. package/.opencode/plugin/daytona/tools/bash.js.map +1 -1
  43. package/.opencode/plugin/daytona/tools/edit.d.ts +6 -2
  44. package/.opencode/plugin/daytona/tools/edit.js +13 -5
  45. package/.opencode/plugin/daytona/tools/edit.js.map +1 -1
  46. package/.opencode/plugin/daytona/tools/get-preview-url.d.ts +6 -2
  47. package/.opencode/plugin/daytona/tools/get-preview-url.js +11 -3
  48. package/.opencode/plugin/daytona/tools/get-preview-url.js.map +1 -1
  49. package/.opencode/plugin/daytona/tools/glob.d.ts +6 -2
  50. package/.opencode/plugin/daytona/tools/glob.js +11 -3
  51. package/.opencode/plugin/daytona/tools/glob.js.map +1 -1
  52. package/.opencode/plugin/daytona/tools/grep.d.ts +6 -2
  53. package/.opencode/plugin/daytona/tools/grep.js +11 -3
  54. package/.opencode/plugin/daytona/tools/grep.js.map +1 -1
  55. package/.opencode/plugin/daytona/tools/ls.d.ts +6 -2
  56. package/.opencode/plugin/daytona/tools/ls.js +11 -3
  57. package/.opencode/plugin/daytona/tools/ls.js.map +1 -1
  58. package/.opencode/plugin/daytona/tools/lsp.d.ts +6 -2
  59. package/.opencode/plugin/daytona/tools/lsp.js +13 -5
  60. package/.opencode/plugin/daytona/tools/lsp.js.map +1 -1
  61. package/.opencode/plugin/daytona/tools/multiedit.d.ts +6 -2
  62. package/.opencode/plugin/daytona/tools/multiedit.js +14 -6
  63. package/.opencode/plugin/daytona/tools/multiedit.js.map +1 -1
  64. package/.opencode/plugin/daytona/tools/patch.d.ts +7 -5
  65. package/.opencode/plugin/daytona/tools/patch.js +13 -13
  66. package/.opencode/plugin/daytona/tools/patch.js.map +1 -1
  67. package/.opencode/plugin/daytona/tools/read.d.ts +6 -2
  68. package/.opencode/plugin/daytona/tools/read.js +11 -3
  69. package/.opencode/plugin/daytona/tools/read.js.map +1 -1
  70. package/.opencode/plugin/daytona/tools/write.d.ts +6 -2
  71. package/.opencode/plugin/daytona/tools/write.js +12 -4
  72. package/.opencode/plugin/daytona/tools/write.js.map +1 -1
  73. package/.opencode/plugin/daytona/tools.d.ts +14 -16
  74. package/.opencode/plugin/daytona/tools.js +30 -23
  75. package/.opencode/plugin/daytona/tools.js.map +1 -1
  76. package/.opencode/plugin/index.d.ts +7 -4
  77. package/.opencode/plugin/index.js +12 -3
  78. package/.opencode/plugin/index.js.map +1 -1
  79. package/README.md +58 -26
  80. package/package.json +34 -17
  81. package/.opencode/plugin/daytona/core/logger.d.ts.map +0 -1
  82. package/.opencode/plugin/daytona/core/project-data-storage.d.ts.map +0 -1
  83. package/.opencode/plugin/daytona/core/session-manager.d.ts.map +0 -1
  84. package/.opencode/plugin/daytona/core/toast.d.ts.map +0 -1
  85. package/.opencode/plugin/daytona/core/types.d.ts.map +0 -1
  86. package/.opencode/plugin/daytona/git/host-git-manager.d.ts.map +0 -1
  87. package/.opencode/plugin/daytona/git/index.d.ts.map +0 -1
  88. package/.opencode/plugin/daytona/git/sandbox-git-manager.d.ts.map +0 -1
  89. package/.opencode/plugin/daytona/git/session-git-manager.d.ts.map +0 -1
  90. package/.opencode/plugin/daytona/index.d.ts.map +0 -1
  91. package/.opencode/plugin/daytona/plugins/custom-tools.d.ts.map +0 -1
  92. package/.opencode/plugin/daytona/plugins/index.d.ts +0 -8
  93. package/.opencode/plugin/daytona/plugins/index.d.ts.map +0 -1
  94. package/.opencode/plugin/daytona/plugins/index.js +0 -8
  95. package/.opencode/plugin/daytona/plugins/index.js.map +0 -1
  96. package/.opencode/plugin/daytona/plugins/session-cleanup.d.ts +0 -8
  97. package/.opencode/plugin/daytona/plugins/session-cleanup.d.ts.map +0 -1
  98. package/.opencode/plugin/daytona/plugins/session-cleanup.js +0 -36
  99. package/.opencode/plugin/daytona/plugins/session-cleanup.js.map +0 -1
  100. package/.opencode/plugin/daytona/plugins/session-idle-auto-commit.d.ts +0 -7
  101. package/.opencode/plugin/daytona/plugins/session-idle-auto-commit.d.ts.map +0 -1
  102. package/.opencode/plugin/daytona/plugins/session-idle-auto-commit.js +0 -44
  103. package/.opencode/plugin/daytona/plugins/session-idle-auto-commit.js.map +0 -1
  104. package/.opencode/plugin/daytona/plugins/system-transform.d.ts.map +0 -1
  105. package/.opencode/plugin/daytona/tools/bash.d.ts.map +0 -1
  106. package/.opencode/plugin/daytona/tools/edit.d.ts.map +0 -1
  107. package/.opencode/plugin/daytona/tools/get-preview-url.d.ts.map +0 -1
  108. package/.opencode/plugin/daytona/tools/glob.d.ts.map +0 -1
  109. package/.opencode/plugin/daytona/tools/grep.d.ts.map +0 -1
  110. package/.opencode/plugin/daytona/tools/ls.d.ts.map +0 -1
  111. package/.opencode/plugin/daytona/tools/lsp.d.ts.map +0 -1
  112. package/.opencode/plugin/daytona/tools/multiedit.d.ts.map +0 -1
  113. package/.opencode/plugin/daytona/tools/patch.d.ts.map +0 -1
  114. package/.opencode/plugin/daytona/tools/read.d.ts.map +0 -1
  115. package/.opencode/plugin/daytona/tools/write.d.ts.map +0 -1
  116. package/.opencode/plugin/daytona/tools.d.ts.map +0 -1
  117. package/.opencode/plugin/index.d.ts.map +0 -1
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Logger class for handling plugin logging
2
+ * Copyright 2025 Daytona Platforms Inc.
3
+ * SPDX-License-Identifier: Apache-2.0
3
4
  */
4
5
  import type { LogLevel } from './types';
5
6
  export declare function setLogFilePath(path: string): void;
@@ -12,4 +13,3 @@ declare class Logger {
12
13
  }
13
14
  export declare const logger: Logger;
14
15
  export {};
15
- //# sourceMappingURL=logger.d.ts.map
@@ -1,11 +1,19 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright 2025 Daytona Platforms Inc.
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.logger = void 0;
8
+ exports.setLogFilePath = setLogFilePath;
1
9
  /**
2
10
  * Logger class for handling plugin logging
3
11
  */
4
- import { appendFileSync, mkdirSync, statSync, truncateSync } from 'fs';
5
- import { dirname } from 'path';
6
- import { LOG_LEVEL_INFO, LOG_LEVEL_ERROR, LOG_LEVEL_WARN } from './types';
12
+ const fs_1 = require("fs");
13
+ const path_1 = require("path");
14
+ const types_1 = require("./types");
7
15
  let logFilePath;
8
- export function setLogFilePath(path) {
16
+ function setLogFilePath(path) {
9
17
  logFilePath = path;
10
18
  }
11
19
  class Logger {
@@ -14,20 +22,25 @@ class Logger {
14
22
  throw new Error('Logger file path not set. Call setLogFilePath(path) before use.');
15
23
  return logFilePath;
16
24
  }
17
- log(message, level = LOG_LEVEL_INFO) {
25
+ log(message, level = types_1.LOG_LEVEL_INFO) {
18
26
  // Ensure log directory exists
19
27
  try {
20
- mkdirSync(dirname(this.logFile), { recursive: true });
28
+ (0, fs_1.mkdirSync)((0, path_1.dirname)(this.logFile), { recursive: true });
21
29
  }
22
30
  catch (err) {
23
31
  // Directory may already exist, ignore
24
32
  }
25
- // Truncate log file if it exceeds 5MB
33
+ // Trim log file if it exceeds 3MB (keep last 1MB)
26
34
  try {
27
- const stats = statSync(this.logFile);
28
- const maxSize = 5 * 1024 * 1024; // 5MB
35
+ const stats = (0, fs_1.statSync)(this.logFile);
36
+ const maxSize = 3 * 1024 * 1024;
37
+ const keepSize = 1024 * 1024;
29
38
  if (stats.size > maxSize) {
30
- truncateSync(this.logFile, 0);
39
+ const content = (0, fs_1.readFileSync)(this.logFile, 'utf8');
40
+ const trimmed = content.slice(-keepSize);
41
+ // Drop partial first line so we don't start mid-log
42
+ const firstNewline = trimmed.indexOf('\n');
43
+ (0, fs_1.writeFileSync)(this.logFile, firstNewline >= 0 ? trimmed.slice(firstNewline + 1) : trimmed);
31
44
  }
32
45
  }
33
46
  catch (err) {
@@ -35,17 +48,17 @@ class Logger {
35
48
  }
36
49
  const timestamp = new Date().toISOString();
37
50
  const logEntry = `[${timestamp}] [${level}] ${message}\n`;
38
- appendFileSync(this.logFile, logEntry);
51
+ (0, fs_1.appendFileSync)(this.logFile, logEntry);
39
52
  }
40
53
  info(message) {
41
- this.log(message, LOG_LEVEL_INFO);
54
+ this.log(message, types_1.LOG_LEVEL_INFO);
42
55
  }
43
56
  error(message) {
44
- this.log(message, LOG_LEVEL_ERROR);
57
+ this.log(message, types_1.LOG_LEVEL_ERROR);
45
58
  }
46
59
  warn(message) {
47
- this.log(message, LOG_LEVEL_WARN);
60
+ this.log(message, types_1.LOG_LEVEL_WARN);
48
61
  }
49
62
  }
50
- export const logger = new Logger();
63
+ exports.logger = new Logger();
51
64
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../../../.opencode/plugin/daytona/core/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAE9B,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAEzE,IAAI,WAA+B,CAAA;AAEnC,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,WAAW,GAAG,IAAI,CAAA;AACpB,CAAC;AAED,MAAM,MAAM;IACV,IAAY,OAAO;QACjB,IAAI,CAAC,WAAW;YAAE,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;QACpG,OAAO,WAAW,CAAA;IACpB,CAAC;IAED,GAAG,CAAC,OAAe,EAAE,QAAkB,cAAc;QACnD,8BAA8B;QAC9B,IAAI,CAAC;YACH,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,sCAAsC;QACxC,CAAC;QACD,sCAAsC;QACtC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACpC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA,CAAC,MAAM;YACtC,IAAI,KAAK,CAAC,IAAI,GAAG,OAAO,EAAE,CAAC;gBACzB,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iCAAiC;QACnC,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QAC1C,MAAM,QAAQ,GAAG,IAAI,SAAS,MAAM,KAAK,KAAK,OAAO,IAAI,CAAA;QACzD,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,CAAC,OAAe;QAClB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;IACnC,CAAC;IAED,KAAK,CAAC,OAAe;QACnB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;IACpC,CAAC;IAED,IAAI,CAAC,OAAe;QAClB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;IACnC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAA"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../../../../../libs/opencode-plugin/.opencode/plugin/daytona/core/logger.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAaH,wCAEC;AAbD;;GAEG;AAEH,2BAAqF;AACrF,+BAA8B;AAE9B,mCAAyE;AAEzE,IAAI,WAA+B,CAAA;AAEnC,SAAgB,cAAc,CAAC,IAAY;IACzC,WAAW,GAAG,IAAI,CAAA;AACpB,CAAC;AAED,MAAM,MAAM;IACV,IAAY,OAAO;QACjB,IAAI,CAAC,WAAW;YAAE,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;QACpG,OAAO,WAAW,CAAA;IACpB,CAAC;IAED,GAAG,CAAC,OAAe,EAAE,QAAkB,sBAAc;QACnD,8BAA8B;QAC9B,IAAI,CAAC;YACH,IAAA,cAAS,EAAC,IAAA,cAAO,EAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,sCAAsC;QACxC,CAAC;QACD,kDAAkD;QAClD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAA,aAAQ,EAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACpC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA;YAC/B,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAA;YAC5B,IAAI,KAAK,CAAC,IAAI,GAAG,OAAO,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAG,IAAA,iBAAY,EAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;gBAClD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAA;gBACxC,oDAAoD;gBACpD,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;gBAC1C,IAAA,kBAAa,EAAC,IAAI,CAAC,OAAO,EAAE,YAAY,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;YAC5F,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iCAAiC;QACnC,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QAC1C,MAAM,QAAQ,GAAG,IAAI,SAAS,MAAM,KAAK,KAAK,OAAO,IAAI,CAAA;QACzD,IAAA,mBAAc,EAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,CAAC,OAAe;QAClB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,sBAAc,CAAC,CAAA;IACnC,CAAC;IAED,KAAK,CAAC,OAAe;QACnB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,uBAAe,CAAC,CAAA;IACpC,CAAC;IAED,IAAI,CAAC,OAAe;QAClB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,sBAAc,CAAC,CAAA;IACnC,CAAC;CACF;AAEY,QAAA,MAAM,GAAG,IAAI,MAAM,EAAE,CAAA"}
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Handles file storage operations for project session data
3
- * Stores data per-project in ~/.local/share/opencode/storage/daytona/{projectId}.json
2
+ * Copyright 2025 Daytona Platforms Inc.
3
+ * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import type { ProjectSessionData, SessionInfo } from './types';
6
6
  export declare class ProjectDataStorage {
@@ -10,18 +10,23 @@ export declare class ProjectDataStorage {
10
10
  * Get the file path for a project's session data
11
11
  */
12
12
  private getProjectFilePath;
13
+ /**
14
+ * List known project IDs from storage.
15
+ */
16
+ private listProjectIds;
13
17
  /**
14
18
  * Load project session data from disk
15
19
  */
16
20
  load(projectId: string): ProjectSessionData | null;
17
21
  /**
18
- * Save project session data to disk
22
+ * Get a session for a project. If not found in the requested project, search all other
23
+ * projects on disk and, if found, migrate it into the requested project.
19
24
  */
20
- save(projectId: string, worktree: string, sessions: Record<string, SessionInfo>, lastBranchNumber?: number): void;
25
+ getSession(projectId: string, worktree: string, sessionId: string): SessionInfo | undefined;
21
26
  /**
22
- * Get the next available branch number for a project
27
+ * Save project session data to disk
23
28
  */
24
- getNextBranchNumber(projectId: string): number;
29
+ save(projectId: string, worktree: string, sessions: Record<string, SessionInfo>): void;
25
30
  /**
26
31
  * Get branch number for a sandbox
27
32
  */
@@ -35,4 +40,3 @@ export declare class ProjectDataStorage {
35
40
  */
36
41
  removeSession(projectId: string, worktree: string, sessionId: string): void;
37
42
  }
38
- //# sourceMappingURL=project-data-storage.d.ts.map
@@ -1,24 +1,45 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright 2025 Daytona Platforms Inc.
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ProjectDataStorage = void 0;
1
8
  /**
2
9
  * Handles file storage operations for project session data
3
10
  * Stores data per-project in ~/.local/share/opencode/storage/daytona/{projectId}.json
4
11
  */
5
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
6
- import { join } from 'path';
7
- import { logger } from './logger';
8
- export class ProjectDataStorage {
12
+ const fs_1 = require("fs");
13
+ const path_1 = require("path");
14
+ const logger_1 = require("./logger");
15
+ class ProjectDataStorage {
9
16
  storageDir;
10
17
  constructor(storageDir) {
11
18
  this.storageDir = storageDir;
12
19
  // Ensure storage directory exists
13
- if (!existsSync(this.storageDir)) {
14
- mkdirSync(this.storageDir, { recursive: true });
20
+ if (!(0, fs_1.existsSync)(this.storageDir)) {
21
+ (0, fs_1.mkdirSync)(this.storageDir, { recursive: true });
15
22
  }
16
23
  }
17
24
  /**
18
25
  * Get the file path for a project's session data
19
26
  */
20
27
  getProjectFilePath(projectId) {
21
- return join(this.storageDir, `${projectId}.json`);
28
+ return (0, path_1.join)(this.storageDir, `${projectId}.json`);
29
+ }
30
+ /**
31
+ * List known project IDs from storage.
32
+ */
33
+ listProjectIds() {
34
+ try {
35
+ return (0, fs_1.readdirSync)(this.storageDir)
36
+ .filter((name) => name.endsWith('.json'))
37
+ .map((name) => name.slice(0, -'.json'.length));
38
+ }
39
+ catch (err) {
40
+ logger_1.logger.error(`Failed to list project data files: ${err}`);
41
+ return [];
42
+ }
22
43
  }
23
44
  /**
24
45
  * Load project session data from disk
@@ -26,49 +47,73 @@ export class ProjectDataStorage {
26
47
  load(projectId) {
27
48
  const filePath = this.getProjectFilePath(projectId);
28
49
  try {
29
- if (existsSync(filePath)) {
30
- return JSON.parse(readFileSync(filePath, 'utf-8'));
50
+ if ((0, fs_1.existsSync)(filePath)) {
51
+ return JSON.parse((0, fs_1.readFileSync)(filePath, 'utf-8'));
31
52
  }
32
53
  }
33
54
  catch (err) {
34
- logger.error(`Failed to load project data for ${projectId}: ${err}`);
55
+ logger_1.logger.error(`Failed to load project data for ${projectId}: ${err}`);
35
56
  }
36
57
  return null;
37
58
  }
59
+ /**
60
+ * Get a session for a project. If not found in the requested project, search all other
61
+ * projects on disk and, if found, migrate it into the requested project.
62
+ */
63
+ getSession(projectId, worktree, sessionId) {
64
+ const current = this.load(projectId);
65
+ const currentSession = current?.sessions?.[sessionId];
66
+ if (currentSession) {
67
+ return currentSession;
68
+ }
69
+ // Look in other projects and migrate if found.
70
+ for (const otherProjectId of this.listProjectIds()) {
71
+ if (otherProjectId === projectId)
72
+ continue;
73
+ const otherData = this.load(otherProjectId);
74
+ const found = otherData?.sessions?.[sessionId];
75
+ if (!found)
76
+ continue;
77
+ const destination = current ?? {
78
+ projectId,
79
+ worktree,
80
+ sessions: {},
81
+ };
82
+ // Remove from source first (best effort).
83
+ try {
84
+ delete otherData.sessions[sessionId];
85
+ this.save(otherProjectId, otherData.worktree, otherData.sessions);
86
+ }
87
+ catch (err) {
88
+ logger_1.logger.warn(`Failed to remove session ${sessionId} from project ${otherProjectId}: ${err}`);
89
+ }
90
+ // Add to destination and persist.
91
+ destination.sessions[sessionId] = found;
92
+ // Prefer the worktree for the project we're actually operating on.
93
+ destination.worktree = worktree;
94
+ this.save(projectId, destination.worktree, destination.sessions);
95
+ logger_1.logger.info(`Migrated session ${sessionId} from project ${otherProjectId} to project ${projectId}`);
96
+ return found;
97
+ }
98
+ return undefined;
99
+ }
38
100
  /**
39
101
  * Save project session data to disk
40
102
  */
41
- save(projectId, worktree, sessions, lastBranchNumber) {
103
+ save(projectId, worktree, sessions) {
42
104
  const filePath = this.getProjectFilePath(projectId);
43
105
  const projectData = {
44
106
  projectId,
45
107
  worktree,
46
- lastBranchNumber,
47
108
  sessions,
48
109
  };
49
110
  try {
50
- writeFileSync(filePath, JSON.stringify(projectData, null, 2));
51
- logger.info(`Saved project data for ${projectId}`);
111
+ (0, fs_1.writeFileSync)(filePath, JSON.stringify(projectData, null, 2));
112
+ logger_1.logger.info(`Saved project data for ${projectId}`);
52
113
  }
53
114
  catch (err) {
54
- logger.error(`Failed to save project data for ${projectId}: ${err}`);
55
- }
56
- }
57
- /**
58
- * Get the next available branch number for a project
59
- */
60
- getNextBranchNumber(projectId) {
61
- const projectData = this.load(projectId);
62
- if (!projectData) {
63
- return 1;
115
+ logger_1.logger.error(`Failed to save project data for ${projectId}: ${err}`);
64
116
  }
65
- const branchNumbers = Object.values(projectData.sessions)
66
- .map(s => s.branchNumber)
67
- .filter((n) => n !== undefined);
68
- // Use a persisted monotonic pointer so we never reuse deleted numbers.
69
- const pointer = projectData.lastBranchNumber ?? 0;
70
- const maxInSessions = branchNumbers.length > 0 ? Math.max(...branchNumbers) : 0;
71
- return Math.max(pointer, maxInSessions) + 1;
72
117
  }
73
118
  /**
74
119
  * Get branch number for a sandbox
@@ -78,7 +123,7 @@ export class ProjectDataStorage {
78
123
  if (!projectData) {
79
124
  return undefined;
80
125
  }
81
- const session = Object.values(projectData.sessions).find(s => s.sandboxId === sandboxId);
126
+ const session = Object.values(projectData.sessions).find((s) => s.sandboxId === sandboxId);
82
127
  return session?.branchNumber;
83
128
  }
84
129
  /**
@@ -88,32 +133,28 @@ export class ProjectDataStorage {
88
133
  const projectData = this.load(projectId) || {
89
134
  projectId,
90
135
  worktree,
91
- lastBranchNumber: 0,
92
136
  sessions: {},
93
137
  };
94
138
  const now = Date.now();
95
139
  if (!projectData.sessions[sessionId]) {
96
- // Assign branch number if not provided
97
- const assignedBranchNumber = branchNumber ?? this.getNextBranchNumber(projectId);
98
140
  projectData.sessions[sessionId] = {
99
141
  sandboxId,
100
- branchNumber: assignedBranchNumber,
142
+ ...(branchNumber !== undefined ? { branchNumber } : {}),
101
143
  created: now,
102
144
  lastAccessed: now,
103
145
  };
104
- projectData.lastBranchNumber = Math.max(projectData.lastBranchNumber ?? 0, assignedBranchNumber);
105
146
  }
106
147
  else {
107
148
  projectData.sessions[sessionId].sandboxId = sandboxId;
108
149
  projectData.sessions[sessionId].lastAccessed = now;
109
150
  // Only update branch number if it wasn't set before
110
151
  if (projectData.sessions[sessionId].branchNumber === undefined) {
111
- const assignedBranchNumber = branchNumber ?? this.getNextBranchNumber(projectId);
112
- projectData.sessions[sessionId].branchNumber = assignedBranchNumber;
113
- projectData.lastBranchNumber = Math.max(projectData.lastBranchNumber ?? 0, assignedBranchNumber);
152
+ if (branchNumber !== undefined) {
153
+ projectData.sessions[sessionId].branchNumber = branchNumber;
154
+ }
114
155
  }
115
156
  }
116
- this.save(projectId, worktree, projectData.sessions, projectData.lastBranchNumber);
157
+ this.save(projectId, worktree, projectData.sessions);
117
158
  }
118
159
  /**
119
160
  * Remove a session from the project file
@@ -122,9 +163,9 @@ export class ProjectDataStorage {
122
163
  const projectData = this.load(projectId);
123
164
  if (projectData && projectData.sessions[sessionId]) {
124
165
  delete projectData.sessions[sessionId];
125
- // Intentionally keep lastBranchNumber so branch numbering remains monotonic
126
- this.save(projectId, worktree, projectData.sessions, projectData.lastBranchNumber);
166
+ this.save(projectId, worktree, projectData.sessions);
127
167
  }
128
168
  }
129
169
  }
170
+ exports.ProjectDataStorage = ProjectDataStorage;
130
171
  //# sourceMappingURL=project-data-storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"project-data-storage.js","sourceRoot":"","sources":["../../../../../.opencode/plugin/daytona/core/project-data-storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project-data-storage.js","sourceRoot":"","sources":["../../../../../../../libs/opencode-plugin/.opencode/plugin/daytona/core/project-data-storage.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Copyright 2025 Daytona Platforms Inc.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
1
5
  /**
2
6
  * Manages Daytona sandbox sessions and persists session-sandbox mappings
3
7
  * Stores data per-project in ~/.local/share/opencode/storage/daytona/{projectId}.json
@@ -40,4 +44,3 @@ export declare class DaytonaSessionManager {
40
44
  */
41
45
  deleteSandbox(sessionId: string, projectId: string): Promise<void>;
42
46
  }
43
- //# sourceMappingURL=session-manager.d.ts.map
@@ -1,13 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright 2025 Daytona Platforms Inc.
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.DaytonaSessionManager = void 0;
1
8
  /**
2
9
  * Manages Daytona sandbox sessions and persists session-sandbox mappings
3
10
  * Stores data per-project in ~/.local/share/opencode/storage/daytona/{projectId}.json
4
11
  */
5
- import { Daytona } from '@daytonaio/sdk';
6
- import { logger } from './logger';
7
- import { SessionGitManager } from '../git/session-git-manager';
8
- import { ProjectDataStorage } from './project-data-storage';
9
- import { toast } from './toast';
10
- export class DaytonaSessionManager {
12
+ const sdk_1 = require("@daytonaio/sdk");
13
+ const logger_1 = require("./logger");
14
+ const session_git_manager_1 = require("../git/session-git-manager");
15
+ const sandbox_git_manager_1 = require("../git/sandbox-git-manager");
16
+ const project_data_storage_1 = require("./project-data-storage");
17
+ const toast_1 = require("./toast");
18
+ class DaytonaSessionManager {
11
19
  apiKey;
12
20
  dataStorage;
13
21
  sessionSandboxes;
@@ -15,7 +23,7 @@ export class DaytonaSessionManager {
15
23
  repoPath;
16
24
  constructor(apiKey, storageDir, repoPath) {
17
25
  this.apiKey = apiKey;
18
- this.dataStorage = new ProjectDataStorage(storageDir);
26
+ this.dataStorage = new project_data_storage_1.ProjectDataStorage(storageDir);
19
27
  this.repoPath = repoPath;
20
28
  this.sessionSandboxes = new Map();
21
29
  }
@@ -40,7 +48,7 @@ export class DaytonaSessionManager {
40
48
  for (const [sessionId, sessionInfo] of Object.entries(projectData.sessions)) {
41
49
  this.sessionSandboxes.set(sessionId, { id: sessionInfo.sandboxId });
42
50
  }
43
- logger.info(`Loaded ${Object.keys(projectData.sessions).length} sessions for project ${projectId}`);
51
+ logger_1.logger.info(`Loaded ${Object.keys(projectData.sessions).length} sessions for project ${projectId}`);
44
52
  }
45
53
  }
46
54
  /**
@@ -49,6 +57,7 @@ export class DaytonaSessionManager {
49
57
  setProjectContext(projectId) {
50
58
  if (this.currentProjectId !== projectId) {
51
59
  this.currentProjectId = projectId;
60
+ this.sessionSandboxes.clear();
52
61
  this.loadProjectSessions(projectId);
53
62
  }
54
63
  }
@@ -63,11 +72,11 @@ export class DaytonaSessionManager {
63
72
  */
64
73
  async getSandbox(sessionId, projectId, worktree, pluginCtx) {
65
74
  if (pluginCtx?.client?.tui) {
66
- toast.initialize(pluginCtx.client.tui);
75
+ toast_1.toast.initialize(pluginCtx.client.tui);
67
76
  }
68
77
  if (!this.apiKey) {
69
- logger.error('DAYTONA_API_KEY is not set. Cannot create or retrieve sandbox.');
70
- toast.show({
78
+ logger_1.logger.error('DAYTONA_API_KEY is not set. Cannot create or retrieve sandbox.');
79
+ toast_1.toast.show({
71
80
  title: 'Sandbox error',
72
81
  message: 'DAYTONA_API_KEY is not set. Please set the environment variable to use Daytona sandboxes.',
73
82
  variant: 'error',
@@ -82,7 +91,7 @@ export class DaytonaSessionManager {
82
91
  // Refresh sandbox state and ensure it's running
83
92
  await existing.refreshData();
84
93
  if (existing.state !== 'started') {
85
- logger.info(`Starting sandbox ${existing.id} (current state: ${existing.state})`);
94
+ logger_1.logger.info(`Starting sandbox ${existing.id} (current state: ${existing.state})`);
86
95
  await existing.start();
87
96
  }
88
97
  this.dataStorage.updateSession(projectId, worktree, sessionId, existing.id);
@@ -90,50 +99,99 @@ export class DaytonaSessionManager {
90
99
  }
91
100
  // If we have a sandboxId but not a full sandbox object, reconnect to it
92
101
  if (this.isPartiallyInitialized(existing)) {
93
- logger.info(`Reconnecting to existing sandbox: ${existing.id}`);
94
- const daytona = new Daytona({ apiKey: this.apiKey });
102
+ logger_1.logger.info(`Reconnecting to existing sandbox: ${existing.id}`);
103
+ const daytona = new sdk_1.Daytona({ apiKey: this.apiKey });
104
+ const reconnectStart = Date.now();
105
+ logger_1.logger.info(`Daytona get begin sandboxId=${existing.id}`);
95
106
  const sandbox = await daytona.get(existing.id);
107
+ logger_1.logger.info(`Daytona get done sandboxId=${existing.id} in ${Date.now() - reconnectStart}ms`);
108
+ logger_1.logger.info(`Starting sandbox begin sandboxId=${sandbox.id}`);
96
109
  await sandbox.start();
110
+ logger_1.logger.info(`Starting sandbox done sandboxId=${sandbox.id} in ${Date.now() - reconnectStart}ms`);
97
111
  this.sessionSandboxes.set(sessionId, sandbox);
98
112
  // Preserve branch number if it exists for this sandbox
99
113
  let branchNumber = this.dataStorage.getBranchNumberForSandbox(projectId, sandbox.id);
100
114
  if (!branchNumber) {
101
- branchNumber = this.dataStorage.getNextBranchNumber(projectId);
115
+ try {
116
+ branchNumber = session_git_manager_1.SessionGitManager.allocateAndReserveBranchNumber(worktree);
117
+ }
118
+ catch {
119
+ // No local git repo (or git unavailable) shouldn't block sandbox usage.
120
+ branchNumber = undefined;
121
+ }
102
122
  }
103
123
  this.dataStorage.updateSession(projectId, worktree, sessionId, sandbox.id, branchNumber);
104
- toast.show({
124
+ toast_1.toast.show({
105
125
  title: 'Sandbox connected',
106
126
  message: `Connected to existing sandbox.`,
107
127
  variant: 'info',
108
128
  });
129
+ // Even if git syncing is disabled, ensure the project directory exists in the sandbox.
130
+ if (!branchNumber) {
131
+ try {
132
+ await new sandbox_git_manager_1.DaytonaSandboxGitManager(sandbox, this.repoPath).ensureDirectory();
133
+ }
134
+ catch (err) {
135
+ logger_1.logger.warn(`Failed to ensure sandbox project directory exists: ${err}`);
136
+ }
137
+ }
109
138
  return sandbox;
110
139
  }
140
+ // If not in cache/storage for this project, try to recover from other projects and migrate.
141
+ if (!existing) {
142
+ const migrated = this.dataStorage.getSession(projectId, worktree, sessionId);
143
+ if (migrated?.sandboxId) {
144
+ logger_1.logger.info(`Recovered session ${sessionId} for project ${projectId} (migrated from another project)`);
145
+ this.sessionSandboxes.set(sessionId, { id: migrated.sandboxId });
146
+ // Re-run getSandbox to go through the normal reconnect path.
147
+ return this.getSandbox(sessionId, projectId, worktree, pluginCtx);
148
+ }
149
+ }
111
150
  // Otherwise, create a new sandbox
112
- logger.info(`Creating new sandbox for session: ${sessionId} in project: ${projectId}`);
113
- const daytona = new Daytona({ apiKey: this.apiKey });
114
- const sandbox = await daytona.create();
151
+ logger_1.logger.info(`Creating new sandbox for session: ${sessionId} in project: ${projectId}`);
152
+ const daytona = new sdk_1.Daytona({ apiKey: this.apiKey });
153
+ const createStart = Date.now();
154
+ logger_1.logger.info(`Daytona create begin sessionId=${sessionId}`);
155
+ const waitingLog = setTimeout(() => {
156
+ logger_1.logger.warn(`Daytona create still waiting after ${Date.now() - createStart}ms (sessionId=${sessionId})`);
157
+ }, 15_000);
158
+ const sandbox = await daytona.create().finally(() => clearTimeout(waitingLog));
159
+ logger_1.logger.info(`Daytona create done sessionId=${sessionId} sandboxId=${sandbox.id} in ${Date.now() - createStart}ms`);
115
160
  this.sessionSandboxes.set(sessionId, sandbox);
116
161
  // Get or assign branch number for this sandbox
117
162
  let branchNumber = this.dataStorage.getBranchNumberForSandbox(projectId, sandbox.id);
118
163
  if (!branchNumber) {
119
- branchNumber = this.dataStorage.getNextBranchNumber(projectId);
164
+ try {
165
+ branchNumber = session_git_manager_1.SessionGitManager.allocateAndReserveBranchNumber(worktree);
166
+ }
167
+ catch (err) {
168
+ logger_1.logger.warn(`allocateAndReserveBranchNumber failed sessionId=${sessionId}: ${err}`);
169
+ // No local git repo (or git unavailable) shouldn't block sandbox usage.
170
+ branchNumber = undefined;
171
+ }
120
172
  }
121
173
  this.dataStorage.updateSession(projectId, worktree, sessionId, sandbox.id, branchNumber);
122
- logger.info(`Sandbox created successfully: ${sandbox.id} with branch number ${branchNumber}`);
174
+ logger_1.logger.info(`Sandbox created successfully: ${sandbox.id}${branchNumber ? ` with branch number ${branchNumber}` : ''}`);
123
175
  // Initialize git repo in the sandbox and sync with host
124
176
  try {
125
- const sessionGit = new SessionGitManager(sandbox, this.repoPath, branchNumber);
126
- await sessionGit.initializeAndSync(pluginCtx);
177
+ if (branchNumber) {
178
+ const sessionGit = new session_git_manager_1.SessionGitManager(sandbox, this.repoPath, worktree, branchNumber);
179
+ await sessionGit.initializeAndSync(pluginCtx);
180
+ }
181
+ else {
182
+ // Git disabled; still ensure the directory exists so tools can operate.
183
+ await new sandbox_git_manager_1.DaytonaSandboxGitManager(sandbox, this.repoPath).ensureDirectory();
184
+ }
127
185
  }
128
186
  catch (err) {
129
- logger.error(`Failed to initialize git repo or push local changes in sandbox: ${err}`);
130
- toast.show({
187
+ logger_1.logger.error(`Failed to initialize git repo or push local changes in sandbox: ${err}`);
188
+ toast_1.toast.show({
131
189
  title: 'Git error',
132
190
  message: err?.message || 'Failed to initialize git repo in sandbox.',
133
191
  variant: 'error',
134
192
  });
135
193
  }
136
- toast.show({
194
+ toast_1.toast.show({
137
195
  title: 'Sandbox created',
138
196
  message: `Created new sandbox for session.`,
139
197
  variant: 'success',
@@ -147,22 +205,22 @@ export class DaytonaSessionManager {
147
205
  let sandbox = this.sessionSandboxes.get(sessionId);
148
206
  // If not in cache, try to load from storage and reconnect
149
207
  if (!sandbox || this.isPartiallyInitialized(sandbox)) {
150
- const projectData = this.dataStorage.load(projectId);
151
- const sessionInfo = projectData?.sessions?.[sessionId];
208
+ const storedWorktree = this.dataStorage.load(projectId)?.worktree ?? '';
209
+ const sessionInfo = this.dataStorage.getSession(projectId, storedWorktree, sessionId);
152
210
  if (sessionInfo?.sandboxId) {
153
- const daytona = new Daytona({ apiKey: this.apiKey });
211
+ const daytona = new sdk_1.Daytona({ apiKey: this.apiKey });
154
212
  try {
155
213
  sandbox = await daytona.get(sessionInfo.sandboxId);
156
214
  this.sessionSandboxes.set(sessionId, sandbox);
157
215
  }
158
216
  catch (err) {
159
- logger.error(`Failed to reconnect to sandbox ${sessionInfo.sandboxId}: ${err}`);
217
+ logger_1.logger.error(`Failed to reconnect to sandbox ${sessionInfo.sandboxId}: ${err}`);
160
218
  }
161
219
  }
162
220
  }
163
221
  // Delete the sandbox if we have a fully initialized one
164
222
  if (this.isFullyInitialized(sandbox)) {
165
- logger.info(`Removing sandbox for session: ${sessionId}`);
223
+ logger_1.logger.info(`Removing sandbox for session: ${sessionId}`);
166
224
  await sandbox.delete();
167
225
  this.sessionSandboxes.delete(sessionId);
168
226
  // Remove from storage
@@ -170,11 +228,12 @@ export class DaytonaSessionManager {
170
228
  if (projectData) {
171
229
  this.dataStorage.removeSession(projectId, projectData.worktree, sessionId);
172
230
  }
173
- logger.info(`Sandbox deleted successfully.`);
231
+ logger_1.logger.info(`Sandbox deleted successfully.`);
174
232
  }
175
233
  else {
176
- logger.warn(`No sandbox found for session: ${sessionId}`);
234
+ logger_1.logger.warn(`No sandbox found for session: ${sessionId}`);
177
235
  }
178
236
  }
179
237
  }
238
+ exports.DaytonaSessionManager = DaytonaSessionManager;
180
239
  //# sourceMappingURL=session-manager.js.map