@love-moon/conductor-sdk 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,54 @@
1
+ # @love-moon/conductor-sdk
2
+
3
+ ## 0.3.2
4
+
5
+ ## 0.3.1
6
+
7
+ ### Patch Changes
8
+
9
+ - 4e8d4e5: Include `CHANGELOG.md` in published npm tarballs.
10
+
11
+ The `files` array in each package's `package.json` previously only
12
+ listed the build output (`bin`/`src` for the CLI, `dist` for the
13
+ modules). npm's `files` whitelist replaces the default include set,
14
+ and CHANGELOG is not one of the auto-included files (only
15
+ `package.json`, `README*`, `LICENSE*`, and `main` are unconditional).
16
+
17
+ As a result, every release through 0.3.0 published tarballs with no
18
+ CHANGELOG, so a consumer running `npm install` or unpacking the brew
19
+ artifact had no way to see what changed in the version they just
20
+ installed. The repo `cli/CHANGELOG.md` and the GitHub Release body
21
+ remain the canonical source until 0.3.1 ships with this fix.
22
+
23
+ ## 0.3.0
24
+
25
+ ### Minor Changes
26
+
27
+ - be3b3cb: Project list now merges same-name git projects that share a remote URL across daemons into a single card.
28
+
29
+ - `ProjectContext.snapshot()` (SDK) now captures the origin remote URL via `git config --get remote.origin.url` and exposes a `normalizeGitRemoteUrl` helper for callers that need their own equality comparison.
30
+ - The daemon's `validate_project_path` response carries a new `git_remote_url` field. Old daemons that don't send it stay forward-compatible — the web server treats missing values as "unmergeable" so projects from those daemons render standalone until they're refreshed.
31
+ - New web API surface:
32
+ - `PATCH /api/projects { mergeOptOut: true }` opts a project out of auto-grouping (manual split for accidental name collisions).
33
+ - `PATCH /api/projects { refresh: true }` re-runs the daemon validation handshake and back-fills `git_remote_url` for projects created before this feature.
34
+ - `GET /api/issues?project_ids=a,b` fetches issues from multiple projects in one call; responses include `daemonHost` + `projectName` for cross-daemon attribution.
35
+ - Schema: two new optional columns on `projects`: `git_remote_url` (nullable string) and `merge_opt_out` (boolean, default false). Run `pnpm -C web db:push` before upgrading.
36
+
37
+ ### Other Changes (retroactively documented)
38
+
39
+ The following changes shipped in `@love-moon/conductor-sdk@0.3.0` but
40
+ were merged without a `changeset` entry. See
41
+ `claw/lessons/arch_release-packages-pnpm-changesets-20260512.md` for
42
+ why this happened and the rule that every PR touching `modules/**`
43
+ must run `npm run changeset`.
44
+
45
+ - SDK helpers and types behind the new CLI `conductor project|issue|task`
46
+ entity commands (RFC 0025). Programs that already depended on SDK
47
+ project/issue/task surfaces gain a few stable convenience entry
48
+ points; callers using only the public client API see no change.
49
+ (`2e10756`)
50
+ - Reconnect: the SDK client survives the daemon-side websocket
51
+ late-send-after-disconnect crash path (companion fix to the daemon
52
+ change in `@love-moon/conductor-cli@0.3.0`). (`a3532cc`)
53
+ - Reconnect: stale `taskAttach` calls from a previously-bound fire
54
+ process no longer establish ghost bindings. (`dc73be9`)
@@ -13,6 +13,7 @@ export interface Project {
13
13
  repoRoot?: string | null;
14
14
  worktreeBranch?: string | null;
15
15
  lastCommit?: string | null;
16
+ lastCommitAt?: string | null;
16
17
  fileCount?: number | null;
17
18
  isDefault: boolean;
18
19
  hidden: boolean;
@@ -60,6 +60,7 @@ const normalizeProject = (payload) => {
60
60
  repoRoot: payload.repoRoot ?? payload.repo_root ?? null,
61
61
  worktreeBranch: payload.worktreeBranch ?? payload.worktree_branch ?? null,
62
62
  lastCommit: payload.lastCommit ?? payload.last_commit ?? null,
63
+ lastCommitAt: payload.lastCommitAt ?? payload.last_commit_at ?? null,
63
64
  fileCount: payload.fileCount ?? payload.file_count ?? null,
64
65
  isDefault: Boolean(payload.isDefault ?? payload.is_default ?? false),
65
66
  hidden: Boolean(payload.hidden ?? Boolean(hiddenAt)),
@@ -43,7 +43,8 @@ export declare class ProjectSummary {
43
43
  readonly lastCommit?: string | null | undefined;
44
44
  readonly fileCount?: number | null | undefined;
45
45
  readonly isDefault?: boolean | undefined;
46
- constructor(id: string, name?: string | undefined, daemonHost?: string | null | undefined, workspacePath?: string | null | undefined, repoRoot?: string | null | undefined, worktreeBranch?: string | null | undefined, lastCommit?: string | null | undefined, fileCount?: number | null | undefined, isDefault?: boolean | undefined);
46
+ readonly lastCommitAt?: string | null | undefined;
47
+ constructor(id: string, name?: string | undefined, daemonHost?: string | null | undefined, workspacePath?: string | null | undefined, repoRoot?: string | null | undefined, worktreeBranch?: string | null | undefined, lastCommit?: string | null | undefined, fileCount?: number | null | undefined, isDefault?: boolean | undefined, lastCommitAt?: string | null | undefined);
47
48
  static fromJSON(payload: Record<string, any>): ProjectSummary;
48
49
  asObject(): Record<string, unknown>;
49
50
  }
@@ -77,6 +78,7 @@ export declare class BackendApiClient {
77
78
  repoRoot?: string;
78
79
  worktreeBranch?: string;
79
80
  lastCommit?: string;
81
+ lastCommitAt?: string;
80
82
  fileCount?: number;
81
83
  }): Promise<ProjectSummary>;
82
84
  listTasks(params?: {
@@ -163,6 +165,7 @@ export declare class BackendApiClient {
163
165
  repoRoot?: string | null;
164
166
  worktreeBranch?: string | null;
165
167
  lastCommit?: string | null;
168
+ lastCommitAt?: string | null;
166
169
  fileCount?: number | null;
167
170
  isDefault?: boolean;
168
171
  }>;
@@ -175,6 +178,7 @@ export declare class BackendApiClient {
175
178
  repoRoot?: string;
176
179
  worktreeBranch?: string;
177
180
  lastCommit?: string;
181
+ lastCommitAt?: string;
178
182
  fileCount?: number;
179
183
  }): Promise<ProjectSummary>;
180
184
  /**
@@ -17,7 +17,8 @@ export class ProjectSummary {
17
17
  lastCommit;
18
18
  fileCount;
19
19
  isDefault;
20
- constructor(id, name, daemonHost, workspacePath, repoRoot, worktreeBranch, lastCommit, fileCount, isDefault) {
20
+ lastCommitAt;
21
+ constructor(id, name, daemonHost, workspacePath, repoRoot, worktreeBranch, lastCommit, fileCount, isDefault, lastCommitAt) {
21
22
  this.id = id;
22
23
  this.name = name;
23
24
  this.daemonHost = daemonHost;
@@ -27,13 +28,14 @@ export class ProjectSummary {
27
28
  this.lastCommit = lastCommit;
28
29
  this.fileCount = fileCount;
29
30
  this.isDefault = isDefault;
31
+ this.lastCommitAt = lastCommitAt;
30
32
  }
31
33
  static fromJSON(payload) {
32
34
  const id = payload.id ? String(payload.id) : '';
33
35
  if (!id) {
34
36
  throw new Error('Project payload missing id');
35
37
  }
36
- return new ProjectSummary(id, payload.name ?? undefined, payload.daemonHost ?? payload.daemon_host ?? null, payload.workspacePath ?? payload.workspace_path ?? null, payload.repoRoot ?? payload.repo_root ?? null, payload.worktreeBranch ?? payload.worktree_branch ?? null, payload.lastCommit ?? payload.last_commit ?? null, payload.fileCount ?? payload.file_count ?? null, payload.isDefault ?? payload.is_default ?? undefined);
38
+ return new ProjectSummary(id, payload.name ?? undefined, payload.daemonHost ?? payload.daemon_host ?? null, payload.workspacePath ?? payload.workspace_path ?? null, payload.repoRoot ?? payload.repo_root ?? null, payload.worktreeBranch ?? payload.worktree_branch ?? null, payload.lastCommit ?? payload.last_commit ?? null, payload.fileCount ?? payload.file_count ?? null, payload.isDefault ?? payload.is_default ?? undefined, payload.lastCommitAt ?? payload.last_commit_at ?? null);
37
39
  }
38
40
  asObject() {
39
41
  return {
@@ -44,6 +46,7 @@ export class ProjectSummary {
44
46
  repoRoot: this.repoRoot,
45
47
  worktreeBranch: this.worktreeBranch,
46
48
  lastCommit: this.lastCommit,
49
+ lastCommitAt: this.lastCommitAt,
47
50
  fileCount: this.fileCount,
48
51
  isDefault: this.isDefault,
49
52
  };
@@ -299,6 +302,7 @@ export class BackendApiClient {
299
302
  repoRoot: payload.repoRoot ?? payload.repo_root ?? undefined,
300
303
  worktreeBranch: payload.worktreeBranch ?? payload.worktree_branch ?? undefined,
301
304
  lastCommit: payload.lastCommit ?? payload.last_commit ?? undefined,
305
+ lastCommitAt: payload.lastCommitAt ?? payload.last_commit_at ?? undefined,
302
306
  fileCount: payload.fileCount ?? payload.file_count ?? undefined,
303
307
  isDefault: payload.isDefault ?? payload.is_default ?? undefined,
304
308
  };
package/dist/client.js CHANGED
@@ -541,6 +541,7 @@ export class ConductorClient {
541
541
  repoRoot: snapshot.repoRoot,
542
542
  worktreeBranch: snapshot.worktreeBranch,
543
543
  lastCommit: snapshot.lastCommit,
544
+ lastCommitAt: snapshot.lastCommitAt,
544
545
  fileCount: snapshot.fileCount,
545
546
  });
546
547
  return {
@@ -553,6 +554,7 @@ export class ConductorClient {
553
554
  repo_root: snapshot.repoRoot ?? null,
554
555
  worktree_branch: snapshot.worktreeBranch ?? null,
555
556
  last_commit: snapshot.lastCommit ?? null,
557
+ last_commit_at: snapshot.lastCommitAt ?? null,
556
558
  file_count: snapshot.fileCount ?? null,
557
559
  };
558
560
  }
@@ -7,6 +7,7 @@ export interface WorkspaceSnapshot {
7
7
  repoRoot?: string;
8
8
  worktreeBranch?: string;
9
9
  lastCommit?: string;
10
+ lastCommitAt?: string;
10
11
  /**
11
12
  * Normalized origin remote URL (lower-cased, trailing `.git` stripped).
12
13
  * Only populated when the workspace is a git repository AND has an
@@ -27,6 +28,7 @@ export declare class ProjectContext {
27
28
  private gitRoot;
28
29
  private gitBranch;
29
30
  private gitHead;
31
+ private gitHeadCommittedAt;
30
32
  private gitRemoteUrl;
31
33
  private gitFileCount;
32
34
  private gitListFiles;
@@ -26,6 +26,7 @@ export class ProjectContext {
26
26
  repoRoot: guess.repoRoot,
27
27
  worktreeBranch: this.gitBranch(guess.repoRoot) ?? undefined,
28
28
  lastCommit: this.gitHead(guess.repoRoot) ?? undefined,
29
+ lastCommitAt: this.gitHeadCommittedAt(guess.repoRoot) ?? undefined,
29
30
  gitRemoteUrl: this.gitRemoteUrl(guess.repoRoot) ?? undefined,
30
31
  fileCount: this.gitFileCount(guess.repoRoot) ?? undefined,
31
32
  };
@@ -92,6 +93,15 @@ export class ProjectContext {
92
93
  return null;
93
94
  }
94
95
  }
96
+ gitHeadCommittedAt(repoRoot) {
97
+ try {
98
+ const committedAt = runGit(['show', '-s', '--format=%cI', 'HEAD'], repoRoot).trim();
99
+ return committedAt || null;
100
+ }
101
+ catch {
102
+ return null;
103
+ }
104
+ }
95
105
  gitRemoteUrl(repoRoot) {
96
106
  try {
97
107
  const url = runGit(['config', '--get', 'remote.origin.url'], repoRoot).trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@love-moon/conductor-sdk",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/lovemoon-ai/conductor.git"
@@ -9,7 +9,8 @@
9
9
  "main": "dist/index.js",
10
10
  "types": "dist/index.d.ts",
11
11
  "files": [
12
- "dist"
12
+ "dist",
13
+ "CHANGELOG.md"
13
14
  ],
14
15
  "publishConfig": {
15
16
  "access": "public",
@@ -32,5 +33,5 @@
32
33
  "typescript": "^5.6.3",
33
34
  "vitest": "^2.1.4"
34
35
  },
35
- "gitCommitId": "b9f33cd"
36
+ "gitCommitId": "519f104"
36
37
  }