@doriandev/devcc 0.1.2 → 0.2.0

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 (136) hide show
  1. package/README.md +556 -386
  2. package/bin/devcc.mjs +50 -23
  3. package/dist/devcc/agents/agents.d.ts +112 -0
  4. package/dist/devcc/agents/agents.d.ts.map +1 -0
  5. package/dist/devcc/agents/agents.js +179 -0
  6. package/dist/devcc/agents/agents.js.map +1 -0
  7. package/dist/devcc/app/App.d.ts +15 -0
  8. package/dist/devcc/app/App.d.ts.map +1 -1
  9. package/dist/devcc/app/App.js +326 -17
  10. package/dist/devcc/app/App.js.map +1 -1
  11. package/dist/devcc/app/controlPlaneCommands.d.ts +14 -0
  12. package/dist/devcc/app/controlPlaneCommands.d.ts.map +1 -0
  13. package/dist/devcc/app/controlPlaneCommands.js +179 -0
  14. package/dist/devcc/app/controlPlaneCommands.js.map +1 -0
  15. package/dist/devcc/app/keymap.d.ts.map +1 -1
  16. package/dist/devcc/app/keymap.js +24 -3
  17. package/dist/devcc/app/keymap.js.map +1 -1
  18. package/dist/devcc/automation.d.ts +31 -0
  19. package/dist/devcc/automation.d.ts.map +1 -0
  20. package/dist/devcc/automation.js +202 -0
  21. package/dist/devcc/automation.js.map +1 -0
  22. package/dist/devcc/cli.d.ts.map +1 -1
  23. package/dist/devcc/cli.js +46 -3
  24. package/dist/devcc/cli.js.map +1 -1
  25. package/dist/devcc/components/Sidebar.d.ts.map +1 -1
  26. package/dist/devcc/components/Sidebar.js +1 -0
  27. package/dist/devcc/components/Sidebar.js.map +1 -1
  28. package/dist/devcc/components/primitives.d.ts.map +1 -1
  29. package/dist/devcc/components/primitives.js +3 -0
  30. package/dist/devcc/components/primitives.js.map +1 -1
  31. package/dist/devcc/core/commands.d.ts +25 -0
  32. package/dist/devcc/core/commands.d.ts.map +1 -1
  33. package/dist/devcc/core/commands.js.map +1 -1
  34. package/dist/devcc/core/config.d.ts +69 -3
  35. package/dist/devcc/core/config.d.ts.map +1 -1
  36. package/dist/devcc/core/config.js +185 -5
  37. package/dist/devcc/core/config.js.map +1 -1
  38. package/dist/devcc/core/state.d.ts +19 -1
  39. package/dist/devcc/core/state.d.ts.map +1 -1
  40. package/dist/devcc/core/state.js +6 -0
  41. package/dist/devcc/core/state.js.map +1 -1
  42. package/dist/devcc/environment/EnvironmentService.d.ts +58 -0
  43. package/dist/devcc/environment/EnvironmentService.d.ts.map +1 -0
  44. package/dist/devcc/environment/EnvironmentService.js +159 -0
  45. package/dist/devcc/environment/EnvironmentService.js.map +1 -0
  46. package/dist/devcc/environment/integrations.d.ts +52 -0
  47. package/dist/devcc/environment/integrations.d.ts.map +1 -0
  48. package/dist/devcc/environment/integrations.js +94 -0
  49. package/dist/devcc/environment/integrations.js.map +1 -0
  50. package/dist/devcc/environment/tools.d.ts +51 -0
  51. package/dist/devcc/environment/tools.d.ts.map +1 -0
  52. package/dist/devcc/environment/tools.js +99 -0
  53. package/dist/devcc/environment/tools.js.map +1 -0
  54. package/dist/devcc/git/GitService.d.ts +26 -0
  55. package/dist/devcc/git/GitService.d.ts.map +1 -1
  56. package/dist/devcc/git/GitService.js +71 -2
  57. package/dist/devcc/git/GitService.js.map +1 -1
  58. package/dist/devcc/git/worktrees.d.ts +88 -0
  59. package/dist/devcc/git/worktrees.d.ts.map +1 -0
  60. package/dist/devcc/git/worktrees.js +226 -0
  61. package/dist/devcc/git/worktrees.js.map +1 -0
  62. package/dist/devcc/index.d.ts +13 -3
  63. package/dist/devcc/index.d.ts.map +1 -1
  64. package/dist/devcc/index.js +11 -1
  65. package/dist/devcc/index.js.map +1 -1
  66. package/dist/devcc/platform/launch.d.ts +30 -0
  67. package/dist/devcc/platform/launch.d.ts.map +1 -0
  68. package/dist/devcc/platform/launch.js +93 -0
  69. package/dist/devcc/platform/launch.js.map +1 -0
  70. package/dist/devcc/services/ServiceManager.d.ts +10 -2
  71. package/dist/devcc/services/ServiceManager.d.ts.map +1 -1
  72. package/dist/devcc/services/ServiceManager.js +18 -4
  73. package/dist/devcc/services/ServiceManager.js.map +1 -1
  74. package/dist/devcc/services/ollama.d.ts +64 -5
  75. package/dist/devcc/services/ollama.d.ts.map +1 -1
  76. package/dist/devcc/services/ollama.js +118 -17
  77. package/dist/devcc/services/ollama.js.map +1 -1
  78. package/dist/devcc/services/remote.d.ts +90 -0
  79. package/dist/devcc/services/remote.d.ts.map +1 -0
  80. package/dist/devcc/services/remote.js +233 -0
  81. package/dist/devcc/services/remote.js.map +1 -0
  82. package/dist/devcc/services/types.d.ts +8 -1
  83. package/dist/devcc/services/types.d.ts.map +1 -1
  84. package/dist/devcc/services/types.js.map +1 -1
  85. package/dist/devcc/utils/exec.d.ts +6 -0
  86. package/dist/devcc/utils/exec.d.ts.map +1 -1
  87. package/dist/devcc/utils/exec.js +12 -2
  88. package/dist/devcc/utils/exec.js.map +1 -1
  89. package/dist/devcc/verify/verify.d.ts +107 -0
  90. package/dist/devcc/verify/verify.d.ts.map +1 -0
  91. package/dist/devcc/verify/verify.js +203 -0
  92. package/dist/devcc/verify/verify.js.map +1 -0
  93. package/dist/devcc/views/OverviewView.d.ts.map +1 -1
  94. package/dist/devcc/views/OverviewView.js +55 -1
  95. package/dist/devcc/views/OverviewView.js.map +1 -1
  96. package/dist/devcc/views/ServicesView.d.ts +2 -0
  97. package/dist/devcc/views/ServicesView.d.ts.map +1 -1
  98. package/dist/devcc/views/ServicesView.js +15 -0
  99. package/dist/devcc/views/ServicesView.js.map +1 -1
  100. package/dist/devcc/views/SystemView.d.ts +10 -1
  101. package/dist/devcc/views/SystemView.d.ts.map +1 -1
  102. package/dist/devcc/views/SystemView.js +127 -19
  103. package/dist/devcc/views/SystemView.js.map +1 -1
  104. package/dist/devcc/views/WorktreesView.d.ts +48 -0
  105. package/dist/devcc/views/WorktreesView.d.ts.map +1 -0
  106. package/dist/devcc/views/WorktreesView.js +235 -0
  107. package/dist/devcc/views/WorktreesView.js.map +1 -0
  108. package/package.json +1 -1
  109. package/src/devcc/agents/agents.ts +282 -0
  110. package/src/devcc/app/App.ts +376 -20
  111. package/src/devcc/app/controlPlaneCommands.ts +197 -0
  112. package/src/devcc/app/keymap.ts +24 -3
  113. package/src/devcc/automation.ts +242 -0
  114. package/src/devcc/cli.ts +45 -3
  115. package/src/devcc/components/Sidebar.ts +1 -0
  116. package/src/devcc/components/primitives.ts +3 -0
  117. package/src/devcc/core/commands.ts +26 -0
  118. package/src/devcc/core/config.ts +271 -11
  119. package/src/devcc/core/state.ts +25 -0
  120. package/src/devcc/environment/EnvironmentService.ts +215 -0
  121. package/src/devcc/environment/integrations.ts +133 -0
  122. package/src/devcc/environment/tools.ts +151 -0
  123. package/src/devcc/git/GitService.ts +104 -2
  124. package/src/devcc/git/worktrees.ts +256 -0
  125. package/src/devcc/index.ts +57 -2
  126. package/src/devcc/platform/launch.ts +125 -0
  127. package/src/devcc/services/ServiceManager.ts +15 -3
  128. package/src/devcc/services/ollama.ts +162 -19
  129. package/src/devcc/services/remote.ts +306 -0
  130. package/src/devcc/services/types.ts +9 -1
  131. package/src/devcc/utils/exec.ts +26 -2
  132. package/src/devcc/verify/verify.ts +316 -0
  133. package/src/devcc/views/OverviewView.ts +76 -1
  134. package/src/devcc/views/ServicesView.ts +17 -0
  135. package/src/devcc/views/SystemView.ts +144 -22
  136. package/src/devcc/views/WorktreesView.ts +270 -0
@@ -18,6 +18,8 @@ export class ServiceManager extends TypedEmitter {
18
18
  adapters = new Map();
19
19
  detected = new Set();
20
20
  snapshots = new Map();
21
+ /** When each adapter was last asked for its status. */
22
+ checkedAt = new Map();
21
23
  timer = null;
22
24
  refreshing = false;
23
25
  intervalMs;
@@ -69,7 +71,7 @@ export class ServiceManager extends TypedEmitter {
69
71
  start() {
70
72
  if (this.timer)
71
73
  return;
72
- this.timer = setInterval(() => void this.refresh(), this.intervalMs);
74
+ this.timer = setInterval(() => void this.refresh({ polled: true }), this.intervalMs);
73
75
  this.timer.unref?.();
74
76
  }
75
77
  stop() {
@@ -78,15 +80,27 @@ export class ServiceManager extends TypedEmitter {
78
80
  clearInterval(this.timer);
79
81
  this.timer = null;
80
82
  }
81
- /** Refresh all detected adapters concurrently. Overlapping calls are skipped. */
82
- async refresh() {
83
+ /**
84
+ * Refresh all detected adapters concurrently. Overlapping calls are skipped.
85
+ * A `polled` refresh (the timer) skips adapters whose `refreshIntervalMs`
86
+ * has not elapsed; an explicit refresh checks everything.
87
+ */
88
+ async refresh(options = {}) {
83
89
  if (this.refreshing)
84
90
  return this.list();
85
91
  this.refreshing = true;
86
92
  try {
93
+ const now = Date.now();
87
94
  const targets = [...this.detected]
88
95
  .map((id) => this.adapters.get(id))
89
- .filter((a) => !!a);
96
+ .filter((a) => !!a)
97
+ .filter((adapter) => {
98
+ if (!options.polled || !adapter.refreshIntervalMs)
99
+ return true;
100
+ return now - (this.checkedAt.get(adapter.id) ?? 0) >= adapter.refreshIntervalMs;
101
+ });
102
+ for (const adapter of targets)
103
+ this.checkedAt.set(adapter.id, now);
90
104
  await Promise.all(targets.map(async (adapter) => {
91
105
  const status = await withTimeout(adapter.getStatus().catch((error) => {
92
106
  this.options.logger.debug("service status failed", {
@@ -1 +1 @@
1
- {"version":3,"file":"ServiceManager.js","sourceRoot":"","sources":["../../../src/devcc/services/ServiceManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ServiceManager.js","sourceRoot":"","sources":["../../../src/devcc/services/ServiceManager.ts"],"names":[],"mappings":"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"}
@@ -1,27 +1,86 @@
1
1
  import type { ServiceAdapter, ServiceStatus } from "./types.js";
2
+ interface OllamaModelDetails {
3
+ parameter_size?: string;
4
+ quantization_level?: string;
5
+ family?: string;
6
+ }
7
+ interface OllamaTagsResponse {
8
+ models?: {
9
+ name?: string;
10
+ size?: number;
11
+ details?: OllamaModelDetails;
12
+ }[];
13
+ }
14
+ interface OllamaPsResponse {
15
+ models?: {
16
+ name?: string;
17
+ size?: number;
18
+ size_vram?: number;
19
+ expires_at?: string;
20
+ details?: OllamaModelDetails;
21
+ }[];
22
+ }
23
+ export interface OllamaModel {
24
+ name: string;
25
+ /** Bytes on disk. */
26
+ size?: number;
27
+ parameterSize?: string;
28
+ quantization?: string;
29
+ family?: string;
30
+ /** Loaded into memory right now. */
31
+ loaded: boolean;
32
+ /** Bytes of VRAM in use, when loaded. */
33
+ vram?: number;
34
+ /** When Ollama will unload it. */
35
+ expiresAt?: Date;
36
+ }
2
37
  export interface OllamaServiceOptions {
38
+ /** Defaults to `ollama`; set for extra endpoints. */
39
+ id?: string;
40
+ name?: string;
41
+ /** `http://gpu-server:11434`. Takes precedence over host/port and `OLLAMA_HOST`. */
42
+ baseUrl?: string;
3
43
  host?: string;
4
44
  port?: number;
5
45
  timeoutMs?: number;
46
+ /** Minimum time between polled checks (default: none locally, 60s for a baseUrl). */
47
+ refreshIntervalMs?: number;
6
48
  }
7
49
  /**
8
- * Ollama adapter. Uses the HTTP API for a model count when the port is open;
9
- * falls back to a plain port probe if the API call fails.
50
+ * Ollama adapter, local or remote.
51
+ *
52
+ * Reachability is a TCP probe; when the port answers, `/api/tags` lists the
53
+ * models and `/api/ps` says which are loaded. Model names are never assumed.
10
54
  */
11
55
  export declare class OllamaService implements ServiceAdapter {
12
- readonly id = "ollama";
13
- readonly name = "Ollama";
56
+ readonly id: string;
57
+ readonly name: string;
14
58
  readonly category: "ai";
59
+ readonly refreshIntervalMs: number | undefined;
60
+ private readonly baseUrl;
15
61
  private readonly host;
16
62
  private readonly port;
17
63
  private readonly timeoutMs;
64
+ private readonly remote;
18
65
  constructor(options?: OllamaServiceOptions);
66
+ /** A configured endpoint is always shown, so "unreachable" is visible; the local one only when running. */
19
67
  detect(): Promise<boolean>;
20
68
  getStatus(): Promise<ServiceStatus>;
21
- private listModels;
69
+ /** Models with metadata, for the CLI and tests. Null when unreachable. */
70
+ listModels(): Promise<OllamaModel[] | null>;
71
+ private getJson;
22
72
  }
73
+ /** Combine `/api/tags` with `/api/ps`: loaded models first, then by name. */
74
+ export declare function mergeOllamaModels(tags: OllamaTagsResponse, ps: OllamaPsResponse | null): OllamaModel[];
75
+ /** A full base URL: a missing port means the scheme's default, exactly as `fetch` will treat it. */
76
+ export declare function parseBaseUrl(value: string): {
77
+ host: string;
78
+ port: number;
79
+ } | null;
80
+ /** `OLLAMA_HOST`-style `host[:port]`, where a missing port means Ollama's 11434. */
23
81
  export declare function parseHostPort(value: string | undefined): {
24
82
  host: string;
25
83
  port: number;
26
84
  } | null;
85
+ export {};
27
86
  //# sourceMappingURL=ollama.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/devcc/services/ollama.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAS/D,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,qBAAa,aAAc,YAAW,cAAc;IAClD,QAAQ,CAAC,EAAE,YAAW;IACtB,QAAQ,CAAC,IAAI,YAAW;IACxB,QAAQ,CAAC,QAAQ,EAAG,IAAI,CAAS;IAEjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;gBAEtB,OAAO,GAAE,oBAAyB;IAOxC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAI1B,SAAS,IAAI,OAAO,CAAC,aAAa,CAAC;YAgB3B,UAAU;CAYzB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAS9F"}
1
+ {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/devcc/services/ollama.ts"],"names":[],"mappings":"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"}
@@ -1,56 +1,157 @@
1
+ import { formatBytes } from "../utils/format.js";
1
2
  import { probeTcpPort } from "../utils/exec.js";
2
3
  const DEFAULT_HOST = "127.0.0.1";
3
4
  const DEFAULT_PORT = 11434;
5
+ /** Remote endpoints are checked at most this often while polling. */
6
+ const REMOTE_REFRESH_MS = 60_000;
7
+ const MAX_ITEMS = 12;
4
8
  /**
5
- * Ollama adapter. Uses the HTTP API for a model count when the port is open;
6
- * falls back to a plain port probe if the API call fails.
9
+ * Ollama adapter, local or remote.
10
+ *
11
+ * Reachability is a TCP probe; when the port answers, `/api/tags` lists the
12
+ * models and `/api/ps` says which are loaded. Model names are never assumed.
7
13
  */
8
14
  export class OllamaService {
9
- id = "ollama";
10
- name = "Ollama";
15
+ id;
16
+ name;
11
17
  category = "ai";
18
+ refreshIntervalMs;
19
+ baseUrl;
12
20
  host;
13
21
  port;
14
22
  timeoutMs;
23
+ remote;
15
24
  constructor(options = {}) {
25
+ const fromUrl = options.baseUrl ? parseBaseUrl(options.baseUrl) : null;
16
26
  const fromEnv = parseHostPort(process.env.OLLAMA_HOST);
17
- this.host = options.host ?? fromEnv?.host ?? DEFAULT_HOST;
18
- this.port = options.port ?? fromEnv?.port ?? DEFAULT_PORT;
27
+ this.remote = options.baseUrl !== undefined;
28
+ this.id = options.id ?? "ollama";
29
+ this.host = fromUrl?.host ?? options.host ?? fromEnv?.host ?? DEFAULT_HOST;
30
+ this.port = fromUrl?.port ?? options.port ?? fromEnv?.port ?? DEFAULT_PORT;
31
+ this.baseUrl = options.baseUrl?.replace(/\/+$/u, "") ?? `http://${this.host}:${this.port}`;
32
+ this.name = options.name ?? (this.remote ? `Ollama (${this.host})` : "Ollama");
19
33
  this.timeoutMs = options.timeoutMs ?? 1_500;
34
+ this.refreshIntervalMs = options.refreshIntervalMs ?? (this.remote ? REMOTE_REFRESH_MS : undefined);
20
35
  }
36
+ /** A configured endpoint is always shown, so "unreachable" is visible; the local one only when running. */
21
37
  async detect() {
38
+ if (this.remote)
39
+ return true;
22
40
  return probeTcpPort(this.port, this.host);
23
41
  }
24
42
  async getStatus() {
25
43
  const checkedAt = new Date();
26
44
  const endpoint = `${this.host}:${this.port}`;
27
- const listening = await probeTcpPort(this.port, this.host);
28
- if (!listening)
29
- return { state: "stopped", endpoint, detail: "not listening", checkedAt };
30
- const models = await this.listModels();
45
+ const listening = await probeTcpPort(this.port, this.host, this.remote ? 2_000 : 700);
46
+ if (!listening) {
47
+ return { state: "stopped", endpoint, detail: this.remote ? "unreachable" : "not listening", checkedAt };
48
+ }
49
+ const [tags, ps] = await Promise.all([
50
+ this.getJson("/api/tags"),
51
+ this.getJson("/api/ps"),
52
+ ]);
53
+ if (!tags)
54
+ return { state: "degraded", endpoint, detail: "listening, API not responding", checkedAt };
55
+ const models = mergeOllamaModels(tags, ps);
56
+ const loaded = models.filter((model) => model.loaded).length;
57
+ const detail = [
58
+ `${models.length} model${models.length === 1 ? "" : "s"}`,
59
+ ps ? `${loaded} loaded` : undefined,
60
+ ]
61
+ .filter(Boolean)
62
+ .join(" · ");
31
63
  return {
32
64
  state: "running",
33
65
  endpoint,
34
- detail: models === null ? "listening" : `${models.length} model${models.length === 1 ? "" : "s"}`,
35
- items: models?.slice(0, 6).map((name) => ({ name, state: "running" })),
66
+ detail,
67
+ items: models.slice(0, MAX_ITEMS).map(modelItem),
36
68
  checkedAt,
37
69
  };
38
70
  }
71
+ /** Models with metadata, for the CLI and tests. Null when unreachable. */
39
72
  async listModels() {
73
+ const [tags, ps] = await Promise.all([
74
+ this.getJson("/api/tags"),
75
+ this.getJson("/api/ps"),
76
+ ]);
77
+ return tags ? mergeOllamaModels(tags, ps) : null;
78
+ }
79
+ async getJson(path) {
40
80
  try {
41
- const response = await fetch(`http://${this.host}:${this.port}/api/tags`, {
42
- signal: AbortSignal.timeout(this.timeoutMs),
43
- });
81
+ const response = await fetch(`${this.baseUrl}${path}`, { signal: AbortSignal.timeout(this.timeoutMs) });
44
82
  if (!response.ok)
45
83
  return null;
46
- const body = (await response.json());
47
- return (body.models ?? []).map((model) => model.name ?? "unnamed");
84
+ return (await response.json());
48
85
  }
49
86
  catch {
50
87
  return null;
51
88
  }
52
89
  }
53
90
  }
91
+ /** Combine `/api/tags` with `/api/ps`: loaded models first, then by name. */
92
+ export function mergeOllamaModels(tags, ps) {
93
+ const running = new Map((ps?.models ?? []).filter((model) => model.name).map((model) => [model.name, model]));
94
+ const models = (tags.models ?? [])
95
+ .filter((model) => typeof model.name === "string")
96
+ .map((model) => {
97
+ const name = model.name;
98
+ const live = running.get(name);
99
+ running.delete(name);
100
+ return {
101
+ name,
102
+ size: model.size,
103
+ parameterSize: model.details?.parameter_size,
104
+ quantization: model.details?.quantization_level,
105
+ family: model.details?.family,
106
+ loaded: live !== undefined,
107
+ vram: live?.size_vram,
108
+ expiresAt: parseDate(live?.expires_at),
109
+ };
110
+ });
111
+ // A model can be loaded but missing from tags (e.g. pulled mid-refresh).
112
+ for (const [name, live] of running) {
113
+ models.push({
114
+ name,
115
+ size: live.size,
116
+ parameterSize: live.details?.parameter_size,
117
+ quantization: live.details?.quantization_level,
118
+ family: live.details?.family,
119
+ loaded: true,
120
+ vram: live.size_vram,
121
+ expiresAt: parseDate(live.expires_at),
122
+ });
123
+ }
124
+ return models.sort((a, b) => Number(b.loaded) - Number(a.loaded) || a.name.localeCompare(b.name));
125
+ }
126
+ function modelItem(model) {
127
+ const meta = [model.parameterSize, model.quantization, model.size ? formatBytes(model.size) : undefined];
128
+ if (model.loaded && model.vram)
129
+ meta.push(`${formatBytes(model.vram)} VRAM`);
130
+ return {
131
+ name: model.name,
132
+ state: model.loaded ? "running" : "stopped",
133
+ detail: [model.loaded ? "loaded" : undefined, ...meta].filter(Boolean).join(" · "),
134
+ };
135
+ }
136
+ function parseDate(value) {
137
+ if (!value)
138
+ return undefined;
139
+ const date = new Date(value);
140
+ return Number.isNaN(date.getTime()) ? undefined : date;
141
+ }
142
+ /** A full base URL: a missing port means the scheme's default, exactly as `fetch` will treat it. */
143
+ export function parseBaseUrl(value) {
144
+ try {
145
+ const parsed = new URL(value);
146
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:")
147
+ return null;
148
+ return { host: parsed.hostname, port: Number(parsed.port || (parsed.protocol === "https:" ? 443 : 80)) };
149
+ }
150
+ catch {
151
+ return null;
152
+ }
153
+ }
154
+ /** `OLLAMA_HOST`-style `host[:port]`, where a missing port means Ollama's 11434. */
54
155
  export function parseHostPort(value) {
55
156
  if (!value)
56
157
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../src/devcc/services/ollama.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../src/devcc/services/ollama.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ import type { RemoteMachineConfig } from "../core/config.js";
2
+ import { type Exec, type Which } from "../environment/tools.js";
3
+ import type { ScopedLogger } from "../utils/logger.js";
4
+ import type { ServiceAdapter, ServiceSnapshot, ServiceStatus } from "./types.js";
5
+ export interface SshTarget {
6
+ hostname: string;
7
+ port: number;
8
+ user?: string;
9
+ }
10
+ /** Arguments for `ssh -G`, which prints the effective config without connecting. */
11
+ export declare function sshConfigArgs(machine: Pick<RemoteMachineConfig, "host" | "port" | "user">): string[];
12
+ /** Parse the `key value` lines of `ssh -G`. */
13
+ export declare function parseSshConfig(output: string): Partial<SshTarget>;
14
+ /** The destination `ssh` should connect to: the alias, so the user's config applies in full. */
15
+ export declare function sshDestination(machine: Pick<RemoteMachineConfig, "host" | "user">): string;
16
+ export interface TailscaleNode {
17
+ hostName: string;
18
+ /** MagicDNS name without the trailing dot. */
19
+ dnsName: string;
20
+ ips: string[];
21
+ online: boolean;
22
+ os?: string;
23
+ }
24
+ export interface TailscaleStatus {
25
+ backendState: string;
26
+ connected: boolean;
27
+ self?: TailscaleNode;
28
+ peers: TailscaleNode[];
29
+ tailnet?: string;
30
+ }
31
+ /** Parse `tailscale status --json`. Returns null for output that is not a status object. */
32
+ export declare function parseTailscaleStatus(output: string): TailscaleStatus | null;
33
+ /** Find the tailnet peer a configured host refers to: MagicDNS name, short name, host name or IP. */
34
+ export declare function findTailscalePeer(status: TailscaleStatus, host: string): TailscaleNode | undefined;
35
+ export interface TailscaleServiceOptions {
36
+ /** Hosts of configured remote machines, shown when they are tailnet peers. */
37
+ machines?: readonly RemoteMachineConfig[];
38
+ run?: Exec;
39
+ which?: Which;
40
+ logger?: ScopedLogger;
41
+ }
42
+ export declare class TailscaleService implements ServiceAdapter {
43
+ private readonly options;
44
+ readonly id = "tailscale";
45
+ readonly name = "Tailscale";
46
+ readonly category: "remote";
47
+ readonly refreshIntervalMs = 30000;
48
+ private readonly run;
49
+ private readonly which;
50
+ private last;
51
+ constructor(options?: TailscaleServiceOptions);
52
+ /** The most recent parsed status, for remote machines to look up peers. */
53
+ getLastStatus(): TailscaleStatus | null;
54
+ private command;
55
+ detect(): Promise<boolean>;
56
+ getStatus(): Promise<ServiceStatus>;
57
+ }
58
+ export interface RemoteMachineServiceOptions {
59
+ machine: RemoteMachineConfig;
60
+ run?: Exec;
61
+ probe?: (port: number, host: string, timeoutMs: number) => Promise<boolean>;
62
+ /** Current Tailscale status, when the Tailscale adapter has one. */
63
+ tailscale?: () => TailscaleStatus | null;
64
+ /** Status of an associated service by id. */
65
+ service?: (id: string) => ServiceSnapshot | undefined;
66
+ logger?: ScopedLogger;
67
+ }
68
+ export declare function remoteServiceId(machineId: string): string;
69
+ /**
70
+ * A configured remote machine as a service: reachability of its SSH port, the
71
+ * effective target from `ssh -G`, Tailscale presence and associated services.
72
+ * It connects to nothing but the TCP port, and only once a minute while polling.
73
+ */
74
+ export declare class RemoteMachineService implements ServiceAdapter {
75
+ private readonly options;
76
+ readonly id: string;
77
+ readonly name: string;
78
+ readonly category: "remote";
79
+ readonly refreshIntervalMs = 60000;
80
+ private readonly run;
81
+ private readonly probe;
82
+ private target;
83
+ constructor(options: RemoteMachineServiceOptions);
84
+ get machine(): RemoteMachineConfig;
85
+ detect(): Promise<boolean>;
86
+ /** Effective host/port/user, resolved once through `ssh -G` and cached. */
87
+ resolveTarget(): Promise<SshTarget>;
88
+ getStatus(): Promise<ServiceStatus>;
89
+ }
90
+ //# sourceMappingURL=remote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../../../src/devcc/services/remote.ts"],"names":[],"mappings":"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"}