@jive-sh/skill-sync 0.2.2-latest-linux-x64 → 0.2.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/README.md +56 -0
- package/bin/skill-sync +576 -0
- package/bin/skill-sync-daemon +576 -0
- package/dist/daemons/skill-sync-daemon.js +279 -0
- package/dist/daemons/skill-sync-daemon.js.map +1 -0
- package/dist/entrypoints/skill-sync.js +100 -0
- package/dist/entrypoints/skill-sync.js.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/config.js +150 -0
- package/dist/internal/config.js.map +1 -0
- package/dist/internal/folders.js +65 -0
- package/dist/internal/folders.js.map +1 -0
- package/dist/internal/notify.js +50 -0
- package/dist/internal/notify.js.map +1 -0
- package/dist/internal/path.js +36 -0
- package/dist/internal/path.js.map +1 -0
- package/dist/internal/reconcile.js +124 -0
- package/dist/internal/reconcile.js.map +1 -0
- package/dist/internal/sync.js +241 -0
- package/dist/internal/sync.js.map +1 -0
- package/dist/internal/wire.js +13 -0
- package/dist/internal/wire.js.map +1 -0
- package/install.js +576 -0
- package/package.json +39 -11
- package/src/daemons/skill-sync-daemon.ts +276 -0
- package/src/entrypoints/skill-sync.ts +109 -0
- package/src/index.ts +15 -0
- package/src/internal/config.ts +191 -0
- package/src/internal/folders.ts +69 -0
- package/src/internal/notify.ts +53 -0
- package/src/internal/path.ts +32 -0
- package/src/internal/reconcile.ts +166 -0
- package/src/internal/sync.ts +304 -0
- package/src/internal/wire.ts +162 -0
- package/multi-call-binary +0 -4
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shapes the daemon and the service exchange.
|
|
3
|
+
*
|
|
4
|
+
* Declared in the library and imported by the service so there is one definition rather than two that
|
|
5
|
+
* drift. The service depends on the library; nothing goes the other way.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface RemoteFile {
|
|
9
|
+
readonly path: string;
|
|
10
|
+
/** Null when the file is deleted; the row stays as a tombstone. */
|
|
11
|
+
readonly hash: string | null;
|
|
12
|
+
readonly deleted: boolean;
|
|
13
|
+
readonly updatedAt: number;
|
|
14
|
+
readonly updatedBy: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ListFilesResponse {
|
|
18
|
+
/** Highest sequence number in this page; the caller sends it back as `since`. */
|
|
19
|
+
readonly cursor: number;
|
|
20
|
+
readonly files: ReadonlyArray<RemoteFile>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface PutFileRequest {
|
|
24
|
+
readonly path: string;
|
|
25
|
+
/** What the client believes the server holds. The write is refused if that is no longer true. */
|
|
26
|
+
readonly baseHash: string | null;
|
|
27
|
+
/** Null to delete. */
|
|
28
|
+
readonly hash: string | null;
|
|
29
|
+
/** Base64, absent for a delete. */
|
|
30
|
+
readonly content: string | null;
|
|
31
|
+
readonly machine: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Where a folder's sync stands, as the dashboard shows it.
|
|
36
|
+
*
|
|
37
|
+
* `reconciling` means Claude is merging two versions of a file on that machine; `attention` means a cycle
|
|
38
|
+
* failed or a conflict could not be merged, and `detail` says which.
|
|
39
|
+
*/
|
|
40
|
+
export type FolderState = "idle" | "reconciling" | "attention";
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A skill is a top-level entry of a skills folder — usually a directory like `jive/` holding `SKILL.md`
|
|
44
|
+
* and its files — and it is the unit of opting in: all of its files sync, or none do, so a skill never
|
|
45
|
+
* arrives half-present on another machine.
|
|
46
|
+
*/
|
|
47
|
+
export const skillOf = (path: string): string => path.split("/")[0]!;
|
|
48
|
+
|
|
49
|
+
/** A file and the SHA-256 of its content — the same hash the server stores, so copies can be compared. */
|
|
50
|
+
export interface FileHash {
|
|
51
|
+
readonly path: string;
|
|
52
|
+
readonly hash: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** One skill as a folder holds it. */
|
|
56
|
+
export interface LocalSkill {
|
|
57
|
+
readonly name: string;
|
|
58
|
+
readonly files: ReadonlyArray<FileHash>;
|
|
59
|
+
/** True when this folder has synced it before, which makes it synced by default rather than local. */
|
|
60
|
+
readonly tracked: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* `POST /folders`: every folder this machine found, with the skills in each. Answered with the folders
|
|
65
|
+
* to sync and, for each, the skills that sync there. A skill left out stays local to its folder.
|
|
66
|
+
*/
|
|
67
|
+
export interface FoldersRequest {
|
|
68
|
+
readonly folders: ReadonlyArray<{ readonly path: string; readonly skills: ReadonlyArray<LocalSkill> }>;
|
|
69
|
+
}
|
|
70
|
+
export interface FolderPrefs {
|
|
71
|
+
readonly path: string;
|
|
72
|
+
readonly skills: ReadonlyArray<string>;
|
|
73
|
+
}
|
|
74
|
+
export interface FoldersResponse {
|
|
75
|
+
readonly folders: ReadonlyArray<FolderPrefs>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** `POST /reconciliations`: one merge Claude did, or failed to do, for the audit log. */
|
|
79
|
+
export interface ReconciliationRequest {
|
|
80
|
+
readonly folder: string;
|
|
81
|
+
readonly path: string;
|
|
82
|
+
readonly outcome: "merged" | "failed";
|
|
83
|
+
/** What differed between the two versions, in a sentence or two. */
|
|
84
|
+
readonly conflict: string;
|
|
85
|
+
/** What the merge kept, dropped or reworded — or why it failed. */
|
|
86
|
+
readonly resolution: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Daemon → hub, over the daemon's WebSocket. */
|
|
90
|
+
export type DaemonMessage = {
|
|
91
|
+
readonly type: "status";
|
|
92
|
+
readonly folder: string;
|
|
93
|
+
readonly state: FolderState;
|
|
94
|
+
readonly detail?: string;
|
|
95
|
+
/** A one-line summary of what the last cycle changed, when it changed anything. */
|
|
96
|
+
readonly activity?: string;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/** Hub → daemon. `prefs` replaces what syncs; `changed` means another write landed on the server. */
|
|
100
|
+
export type HubToDaemon =
|
|
101
|
+
| { readonly type: "prefs"; readonly folders: ReadonlyArray<FolderPrefs> }
|
|
102
|
+
| { readonly type: "changed" };
|
|
103
|
+
|
|
104
|
+
export interface SkillView {
|
|
105
|
+
readonly name: string;
|
|
106
|
+
/** Checked on the dashboard: this folder sends and receives the skill. */
|
|
107
|
+
readonly synced: boolean;
|
|
108
|
+
/** The folder has a copy on disk. */
|
|
109
|
+
readonly local: boolean;
|
|
110
|
+
readonly files: ReadonlyArray<FileHash>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface FolderView {
|
|
114
|
+
readonly path: string;
|
|
115
|
+
readonly enabled: boolean;
|
|
116
|
+
readonly state: FolderState;
|
|
117
|
+
readonly detail: string | null;
|
|
118
|
+
readonly lastActivityAt: number | null;
|
|
119
|
+
readonly lastActivity: string | null;
|
|
120
|
+
readonly skills: ReadonlyArray<SkillView>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface MachineView {
|
|
124
|
+
/** The name the machine's daemon uses; it identifies the machine and never changes. */
|
|
125
|
+
readonly machine: string;
|
|
126
|
+
/** What the dashboard calls it: renamed there, or the machine name until then. */
|
|
127
|
+
readonly name: string;
|
|
128
|
+
/** True while this machine's daemon holds a connection to the hub. */
|
|
129
|
+
readonly online: boolean;
|
|
130
|
+
readonly lastSeen: number | null;
|
|
131
|
+
readonly folders: ReadonlyArray<FolderView>;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** A skill as the server holds it: the synced version every opted-in folder converges on. */
|
|
135
|
+
export interface SyncedSkill {
|
|
136
|
+
readonly name: string;
|
|
137
|
+
readonly files: ReadonlyArray<FileHash & { readonly updatedBy: string; readonly updatedAt: number }>;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface ReconciliationView extends ReconciliationRequest {
|
|
141
|
+
readonly at: number;
|
|
142
|
+
readonly machine: string;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Hub → dashboard: the whole picture, resent on every change. It is small, and a diff protocol is not. */
|
|
146
|
+
export interface Snapshot {
|
|
147
|
+
readonly type: "snapshot";
|
|
148
|
+
/** The deployed service version. A dashboard built by another version reloads itself. */
|
|
149
|
+
readonly version: string;
|
|
150
|
+
/** Display name for every machine name that appears anywhere in the snapshot, including old log entries. */
|
|
151
|
+
readonly names: Readonly<Record<string, string>>;
|
|
152
|
+
readonly skills: ReadonlyArray<SyncedSkill>;
|
|
153
|
+
readonly reconciliations: ReadonlyArray<ReconciliationView>;
|
|
154
|
+
readonly machines: ReadonlyArray<MachineView>;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Dashboard → hub. */
|
|
158
|
+
export type DashboardMessage =
|
|
159
|
+
| { readonly type: "setFolder"; readonly machine: string; readonly path: string; readonly enabled: boolean }
|
|
160
|
+
| { readonly type: "setSkill"; readonly machine: string; readonly folder: string; readonly skill: string; readonly synced: boolean }
|
|
161
|
+
/** An empty name restores the machine name. */
|
|
162
|
+
| { readonly type: "renameMachine"; readonly machine: string; readonly name: string };
|
package/multi-call-binary
DELETED