@schoolai/shipyard 1.0.0 → 1.1.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.
- package/README.md +75 -0
- package/dist/{chunk-FNYWUFGS.js → chunk-4IVLSSKL.js} +195 -5
- package/dist/chunk-4IVLSSKL.js.map +1 -0
- package/dist/{chunk-ERDY7OVK.js → chunk-FY3DRRGT.js} +1 -1
- package/dist/chunk-FY3DRRGT.js.map +1 -0
- package/dist/{chunk-EB3RPXYR.js → chunk-K3GFMEBF.js} +2 -2
- package/dist/index.js +1946 -348
- package/dist/index.js.map +1 -1
- package/dist/{login-5RRT37UW.js → login-BS6C2BRS.js} +4 -4
- package/dist/{logout-NWYPFICH.js → logout-XX5ULFHB.js} +3 -3
- package/package.json +3 -2
- package/dist/chunk-ERDY7OVK.js.map +0 -1
- package/dist/chunk-FNYWUFGS.js.map +0 -1
- /package/dist/{chunk-EB3RPXYR.js.map → chunk-K3GFMEBF.js.map} +0 -0
- /package/dist/{login-5RRT37UW.js.map → login-BS6C2BRS.js.map} +0 -0
- /package/dist/{logout-NWYPFICH.js.map → logout-XX5ULFHB.js.map} +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# @schoolai/shipyard
|
|
2
|
+
|
|
3
|
+
Ship responsibly. Agent management hub for human-agent collaboration.
|
|
4
|
+
|
|
5
|
+
Shipyard is the collaboration workspace for mixed human-agent teams. Agents create tasks with proof. Humans review in real-time. Feedback flows both ways.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @schoolai/shipyard@latest
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or run directly:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx @schoolai/shipyard --help
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Authentication
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
shipyard login # Device flow auth (opens browser)
|
|
23
|
+
shipyard login --check # Check current auth status
|
|
24
|
+
shipyard logout # Clear stored credentials
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Run a task with a prompt
|
|
31
|
+
shipyard --prompt "Fix the bug in auth.ts"
|
|
32
|
+
|
|
33
|
+
# Resume an existing session
|
|
34
|
+
shipyard --resume <session-id> --task-id <id>
|
|
35
|
+
|
|
36
|
+
# Run in serve mode (signaling + agent spawning)
|
|
37
|
+
shipyard --serve
|
|
38
|
+
|
|
39
|
+
# Check version
|
|
40
|
+
shipyard --version
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## CLI Options
|
|
44
|
+
|
|
45
|
+
| Option | Short | Description |
|
|
46
|
+
|--------|-------|-------------|
|
|
47
|
+
| `--prompt <text>` | `-p` | Prompt for the agent |
|
|
48
|
+
| `--task-id <id>` | `-t` | Task ID (auto-generated if omitted) |
|
|
49
|
+
| `--resume <id>` | `-r` | Resume session by session ID |
|
|
50
|
+
| `--data-dir <path>` | `-d` | Data directory (default: `~/.shipyard/data`) |
|
|
51
|
+
| `--cwd <path>` | | Working directory for agent |
|
|
52
|
+
| `--model <name>` | `-m` | Model to use |
|
|
53
|
+
| `--serve` | `-s` | Run in serve mode |
|
|
54
|
+
| `--version` | `-v` | Show version |
|
|
55
|
+
| `--help` | `-h` | Show help |
|
|
56
|
+
|
|
57
|
+
## Environment Variables
|
|
58
|
+
|
|
59
|
+
| Variable | Default | Description |
|
|
60
|
+
|----------|---------|-------------|
|
|
61
|
+
| `ANTHROPIC_API_KEY` | | API key for Claude (optional, overrides OAuth) |
|
|
62
|
+
| `SHIPYARD_DEV` | | Set to `1` for dev mode |
|
|
63
|
+
| `SHIPYARD_DATA_DIR` | `~/.shipyard/data` | Data directory |
|
|
64
|
+
| `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, `error` |
|
|
65
|
+
| `SHIPYARD_SIGNALING_URL` | (auto) | Signaling server WebSocket URL |
|
|
66
|
+
|
|
67
|
+
## Documentation
|
|
68
|
+
|
|
69
|
+
- [Installation Guide](https://github.com/SchoolAI/shipyard/blob/main/docs/installation.md)
|
|
70
|
+
- [Architecture](https://github.com/SchoolAI/shipyard/blob/main/docs/architecture.md)
|
|
71
|
+
- [Development](https://github.com/SchoolAI/shipyard/blob/main/docs/development.md)
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
[FSL-1.1-ALv2](https://github.com/SchoolAI/shipyard/blob/main/LICENSE.md) (Functional Source License) - Free for all non-competing use, converts to Apache 2.0 in 2 years.
|
|
@@ -4122,7 +4122,13 @@ var AuthVerifyResponseSchema = external_exports.discriminatedUnion("valid", [
|
|
|
4122
4122
|
reason: external_exports.enum(["invalid_token", "user_not_found"])
|
|
4123
4123
|
})
|
|
4124
4124
|
]);
|
|
4125
|
-
var
|
|
4125
|
+
var ParticipantRoleSchema = external_exports.enum([
|
|
4126
|
+
"owner",
|
|
4127
|
+
"collaborator-full",
|
|
4128
|
+
"collaborator-review",
|
|
4129
|
+
"viewer"
|
|
4130
|
+
]);
|
|
4131
|
+
var CollaboratorRoleSchema = ParticipantRoleSchema.extract([
|
|
4126
4132
|
"collaborator-full",
|
|
4127
4133
|
"collaborator-review",
|
|
4128
4134
|
"viewer"
|
|
@@ -4130,8 +4136,8 @@ var CollaboratorRoleSchema = external_exports.enum([
|
|
|
4130
4136
|
var CollabCreateRequestSchema = external_exports.object({
|
|
4131
4137
|
/** ID of the task to collaborate on */
|
|
4132
4138
|
taskId: external_exports.string().min(1, "taskId is required"),
|
|
4133
|
-
/** How long the collaboration link should be valid (1-
|
|
4134
|
-
expiresInMinutes: external_exports.number().min(1).max(
|
|
4139
|
+
/** How long the collaboration link should be valid (1-10080 minutes / 7 days max, default 60) */
|
|
4140
|
+
expiresInMinutes: external_exports.number().min(1).max(10080).default(60),
|
|
4135
4141
|
/** Permission level for the invitee (defaults to 'collaborator-full') */
|
|
4136
4142
|
role: CollaboratorRoleSchema.optional()
|
|
4137
4143
|
});
|
|
@@ -4274,6 +4280,15 @@ var NotifyTaskSchema = external_exports.object({
|
|
|
4274
4280
|
machineId: external_exports.string(),
|
|
4275
4281
|
taskId: external_exports.string()
|
|
4276
4282
|
});
|
|
4283
|
+
var NotifyCollabRoomSchema = external_exports.object({
|
|
4284
|
+
type: external_exports.literal("notify-collab-room"),
|
|
4285
|
+
requestId: external_exports.string(),
|
|
4286
|
+
machineId: external_exports.string(),
|
|
4287
|
+
taskId: external_exports.string(),
|
|
4288
|
+
roomId: external_exports.string(),
|
|
4289
|
+
token: external_exports.string().min(1),
|
|
4290
|
+
expiresAt: external_exports.number().positive()
|
|
4291
|
+
});
|
|
4277
4292
|
var TaskAckSchema = external_exports.object({
|
|
4278
4293
|
type: external_exports.literal("task-ack"),
|
|
4279
4294
|
requestId: external_exports.string(),
|
|
@@ -4362,6 +4377,7 @@ var PersonalRoomClientMessageSchema = external_exports.discriminatedUnion("type"
|
|
|
4362
4377
|
WebRTCAnswerSchema,
|
|
4363
4378
|
WebRTCIceSchema,
|
|
4364
4379
|
NotifyTaskSchema,
|
|
4380
|
+
NotifyCollabRoomSchema,
|
|
4365
4381
|
TaskAckSchema,
|
|
4366
4382
|
CancelTaskSchema,
|
|
4367
4383
|
ControlAckSchema,
|
|
@@ -4412,6 +4428,7 @@ var PersonalRoomServerMessageSchema = external_exports.discriminatedUnion("type"
|
|
|
4412
4428
|
AgentLeftSchema,
|
|
4413
4429
|
AgentStatusChangedSchema,
|
|
4414
4430
|
NotifyTaskSchema,
|
|
4431
|
+
NotifyCollabRoomSchema,
|
|
4415
4432
|
TaskAckSchema,
|
|
4416
4433
|
CancelTaskSchema,
|
|
4417
4434
|
ControlAckSchema,
|
|
@@ -4451,7 +4468,7 @@ var ParticipantSchema = external_exports.object({
|
|
|
4451
4468
|
userId: external_exports.string(),
|
|
4452
4469
|
username: external_exports.string(),
|
|
4453
4470
|
avatarUrl: external_exports.string().nullable().optional(),
|
|
4454
|
-
role:
|
|
4471
|
+
role: ParticipantRoleSchema
|
|
4455
4472
|
});
|
|
4456
4473
|
var CollabAuthenticatedSchema = external_exports.object({
|
|
4457
4474
|
type: external_exports.literal("authenticated"),
|
|
@@ -4499,6 +4516,164 @@ var DevicePollPendingSchema = external_exports.object({
|
|
|
4499
4516
|
error: external_exports.enum(["authorization_pending", "slow_down", "expired_token"])
|
|
4500
4517
|
});
|
|
4501
4518
|
|
|
4519
|
+
// ../../packages/session/src/collab-room-connection.ts
|
|
4520
|
+
var CollabRoomConnection = class {
|
|
4521
|
+
state = "disconnected";
|
|
4522
|
+
ws = null;
|
|
4523
|
+
messageHandlers = /* @__PURE__ */ new Set();
|
|
4524
|
+
stateChangeHandlers = /* @__PURE__ */ new Set();
|
|
4525
|
+
config;
|
|
4526
|
+
retryCount = 0;
|
|
4527
|
+
retryTimer = null;
|
|
4528
|
+
intentionalDisconnect = false;
|
|
4529
|
+
constructor(config) {
|
|
4530
|
+
this.config = config;
|
|
4531
|
+
}
|
|
4532
|
+
getState() {
|
|
4533
|
+
return this.state;
|
|
4534
|
+
}
|
|
4535
|
+
connect() {
|
|
4536
|
+
this.intentionalDisconnect = false;
|
|
4537
|
+
if (this.retryTimer !== null) {
|
|
4538
|
+
clearTimeout(this.retryTimer);
|
|
4539
|
+
this.retryTimer = null;
|
|
4540
|
+
}
|
|
4541
|
+
if (this.ws) {
|
|
4542
|
+
this.ws.onopen = null;
|
|
4543
|
+
this.ws.onclose = null;
|
|
4544
|
+
this.ws.onerror = null;
|
|
4545
|
+
this.ws.onmessage = null;
|
|
4546
|
+
this.ws.close();
|
|
4547
|
+
this.ws = null;
|
|
4548
|
+
}
|
|
4549
|
+
const Impl = this.config.WebSocketImpl ?? WebSocket;
|
|
4550
|
+
try {
|
|
4551
|
+
this.ws = new Impl(this.config.url);
|
|
4552
|
+
} catch {
|
|
4553
|
+
this.setState("error");
|
|
4554
|
+
this.reconnectWithBackoff();
|
|
4555
|
+
return;
|
|
4556
|
+
}
|
|
4557
|
+
this.setState("connecting");
|
|
4558
|
+
this.ws.onopen = () => {
|
|
4559
|
+
this.setState("connected");
|
|
4560
|
+
};
|
|
4561
|
+
this.ws.onclose = (ev) => {
|
|
4562
|
+
if (this.state !== "error" && this.state !== "reconnecting") {
|
|
4563
|
+
this.setState("disconnected");
|
|
4564
|
+
}
|
|
4565
|
+
if (!this.intentionalDisconnect && extractCloseCode(ev) !== 4001) {
|
|
4566
|
+
this.reconnectWithBackoff();
|
|
4567
|
+
}
|
|
4568
|
+
};
|
|
4569
|
+
this.ws.onerror = () => {
|
|
4570
|
+
this.setState("error");
|
|
4571
|
+
if (!this.intentionalDisconnect) {
|
|
4572
|
+
this.reconnectWithBackoff();
|
|
4573
|
+
}
|
|
4574
|
+
};
|
|
4575
|
+
this.ws.onmessage = (event) => {
|
|
4576
|
+
let raw;
|
|
4577
|
+
try {
|
|
4578
|
+
raw = JSON.parse(event.data);
|
|
4579
|
+
} catch {
|
|
4580
|
+
return;
|
|
4581
|
+
}
|
|
4582
|
+
const result = CollabRoomServerMessageSchema.safeParse(raw);
|
|
4583
|
+
if (!result.success) {
|
|
4584
|
+
console.warn(
|
|
4585
|
+
"[CollabRoom] Dropped unrecognized server message:",
|
|
4586
|
+
JSON.stringify(raw),
|
|
4587
|
+
result.error.issues
|
|
4588
|
+
);
|
|
4589
|
+
return;
|
|
4590
|
+
}
|
|
4591
|
+
for (const handler of [...this.messageHandlers]) {
|
|
4592
|
+
handler(result.data);
|
|
4593
|
+
}
|
|
4594
|
+
};
|
|
4595
|
+
}
|
|
4596
|
+
send(msg) {
|
|
4597
|
+
try {
|
|
4598
|
+
this.ws?.send(JSON.stringify(msg));
|
|
4599
|
+
} catch {
|
|
4600
|
+
}
|
|
4601
|
+
}
|
|
4602
|
+
onMessage(handler) {
|
|
4603
|
+
this.messageHandlers.add(handler);
|
|
4604
|
+
return () => {
|
|
4605
|
+
this.messageHandlers.delete(handler);
|
|
4606
|
+
};
|
|
4607
|
+
}
|
|
4608
|
+
onStateChange(handler) {
|
|
4609
|
+
this.stateChangeHandlers.add(handler);
|
|
4610
|
+
return () => {
|
|
4611
|
+
this.stateChangeHandlers.delete(handler);
|
|
4612
|
+
};
|
|
4613
|
+
}
|
|
4614
|
+
reconnect() {
|
|
4615
|
+
this.intentionalDisconnect = false;
|
|
4616
|
+
if (this.retryTimer !== null) {
|
|
4617
|
+
clearTimeout(this.retryTimer);
|
|
4618
|
+
this.retryTimer = null;
|
|
4619
|
+
}
|
|
4620
|
+
this.retryCount = 0;
|
|
4621
|
+
this.connect();
|
|
4622
|
+
}
|
|
4623
|
+
disconnect() {
|
|
4624
|
+
this.intentionalDisconnect = true;
|
|
4625
|
+
if (this.retryTimer !== null) {
|
|
4626
|
+
clearTimeout(this.retryTimer);
|
|
4627
|
+
this.retryTimer = null;
|
|
4628
|
+
}
|
|
4629
|
+
this.retryCount = 0;
|
|
4630
|
+
if (this.ws) {
|
|
4631
|
+
this.ws.onopen = null;
|
|
4632
|
+
this.ws.onclose = null;
|
|
4633
|
+
this.ws.onerror = null;
|
|
4634
|
+
this.ws.onmessage = null;
|
|
4635
|
+
this.ws.close();
|
|
4636
|
+
this.ws = null;
|
|
4637
|
+
}
|
|
4638
|
+
this.setState("disconnected");
|
|
4639
|
+
}
|
|
4640
|
+
reconnectWithBackoff() {
|
|
4641
|
+
if (this.retryTimer !== null) return;
|
|
4642
|
+
const maxRetries = this.config.maxRetries;
|
|
4643
|
+
if (maxRetries === void 0 || maxRetries === 0) {
|
|
4644
|
+
return;
|
|
4645
|
+
}
|
|
4646
|
+
if (maxRetries !== -1 && this.retryCount >= maxRetries) {
|
|
4647
|
+
return;
|
|
4648
|
+
}
|
|
4649
|
+
this.setState("reconnecting");
|
|
4650
|
+
if (this.intentionalDisconnect) return;
|
|
4651
|
+
const initialDelay = this.config.initialDelayMs ?? 1e3;
|
|
4652
|
+
const maxDelay = this.config.maxDelayMs ?? 3e4;
|
|
4653
|
+
const multiplier = this.config.backoffMultiplier ?? 2;
|
|
4654
|
+
const delay = Math.min(initialDelay * multiplier ** this.retryCount, maxDelay);
|
|
4655
|
+
this.retryCount++;
|
|
4656
|
+
this.retryTimer = setTimeout(() => {
|
|
4657
|
+
this.retryTimer = null;
|
|
4658
|
+
this.connect();
|
|
4659
|
+
}, delay);
|
|
4660
|
+
}
|
|
4661
|
+
setState(newState) {
|
|
4662
|
+
this.state = newState;
|
|
4663
|
+
if (newState === "connected") {
|
|
4664
|
+
this.retryCount = 0;
|
|
4665
|
+
}
|
|
4666
|
+
for (const handler of [...this.stateChangeHandlers]) {
|
|
4667
|
+
handler(newState);
|
|
4668
|
+
}
|
|
4669
|
+
}
|
|
4670
|
+
};
|
|
4671
|
+
function extractCloseCode(ev) {
|
|
4672
|
+
if (typeof ev !== "object" || ev === null || !("code" in ev)) return void 0;
|
|
4673
|
+
const code = ev.code;
|
|
4674
|
+
return typeof code === "number" ? code : void 0;
|
|
4675
|
+
}
|
|
4676
|
+
|
|
4502
4677
|
// ../../packages/session/src/personal-room-connection.ts
|
|
4503
4678
|
var PersonalRoomConnection = class {
|
|
4504
4679
|
state = "disconnected";
|
|
@@ -4564,6 +4739,11 @@ var PersonalRoomConnection = class {
|
|
|
4564
4739
|
}
|
|
4565
4740
|
const result = PersonalRoomServerMessageSchema.safeParse(raw);
|
|
4566
4741
|
if (!result.success) {
|
|
4742
|
+
console.warn(
|
|
4743
|
+
"[PersonalRoom] Dropped unrecognized server message:",
|
|
4744
|
+
JSON.stringify(raw),
|
|
4745
|
+
result.error.issues
|
|
4746
|
+
);
|
|
4567
4747
|
return;
|
|
4568
4748
|
}
|
|
4569
4749
|
for (const handler of [...this.messageHandlers]) {
|
|
@@ -4589,6 +4769,15 @@ var PersonalRoomConnection = class {
|
|
|
4589
4769
|
this.stateChangeHandlers.delete(handler);
|
|
4590
4770
|
};
|
|
4591
4771
|
}
|
|
4772
|
+
reconnect() {
|
|
4773
|
+
this.intentionalDisconnect = false;
|
|
4774
|
+
if (this.retryTimer !== null) {
|
|
4775
|
+
clearTimeout(this.retryTimer);
|
|
4776
|
+
this.retryTimer = null;
|
|
4777
|
+
}
|
|
4778
|
+
this.retryCount = 0;
|
|
4779
|
+
this.connect();
|
|
4780
|
+
}
|
|
4592
4781
|
disconnect() {
|
|
4593
4782
|
this.intentionalDisconnect = true;
|
|
4594
4783
|
if (this.retryTimer !== null) {
|
|
@@ -4650,6 +4839,7 @@ export {
|
|
|
4650
4839
|
CollabCreateRequestSchema,
|
|
4651
4840
|
CollabCreateResponseSchema,
|
|
4652
4841
|
PermissionModeSchema,
|
|
4842
|
+
CollabRoomConnection,
|
|
4653
4843
|
PersonalRoomConnection
|
|
4654
4844
|
};
|
|
4655
|
-
//# sourceMappingURL=chunk-
|
|
4845
|
+
//# sourceMappingURL=chunk-4IVLSSKL.js.map
|