flyspace-cli 0.1.10 → 0.1.12
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 +4 -7
- package/dist/{chunk-UYLVSUD6.js → chunk-VKTJBYA3.js} +38 -7
- package/dist/cli.js +455 -300
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Requirements
|
|
6
6
|
|
|
7
|
+
- macOS or Linux. On Windows, use [WSL2](https://learn.microsoft.com/windows/wsl/install) with systemd enabled (`systemd=true` in `/etc/wsl.conf`). WSL does not start with Windows, so open it once after each reboot. Native Windows is not supported yet.
|
|
7
8
|
- Node.js 20 or later
|
|
8
9
|
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code), installed and signed in. Run `claude` once to finish the browser sign-in before starting the Host.
|
|
9
10
|
- A Flyspace account at [flyspace.ai](https://flyspace.ai)
|
|
@@ -23,7 +24,7 @@ Then open your workspace, pick a channel, and talk to the agent.
|
|
|
23
24
|
## Keep It Running
|
|
24
25
|
|
|
25
26
|
```bash
|
|
26
|
-
flyspace install
|
|
27
|
+
flyspace service install # run as a background service (launchd on macOS, systemd on Linux)
|
|
27
28
|
flyspace restart
|
|
28
29
|
flyspace stop
|
|
29
30
|
flyspace logs # tail the service log (-e for the error log)
|
|
@@ -35,11 +36,10 @@ flyspace logs # tail the service log (-e for the error log)
|
|
|
35
36
|
|---|---|
|
|
36
37
|
| `flyspace auth login \| status \| logout` | Register, inspect or revoke this device |
|
|
37
38
|
| `flyspace dashboard` | Start the Workspace web UI and agent Host |
|
|
38
|
-
| `flyspace start` | Start the agent Host
|
|
39
|
+
| `flyspace start` | Start the agent Host in the foreground |
|
|
39
40
|
| `flyspace workspace create <slug>` | Provision a workspace (safe to re-run as a repair) |
|
|
40
41
|
| `flyspace reconcile` | Repair a workspace's local files against the server |
|
|
41
42
|
| `flyspace config` | Show resolved config (`--edit`, `--path`) |
|
|
42
|
-
| `flyspace prompt` | Edit the system prompt in `$EDITOR` |
|
|
43
43
|
| `flyspace automation` | Manage scheduled tasks and triggers |
|
|
44
44
|
| `flyspace usage` | Show agent token usage and cost |
|
|
45
45
|
| `flyspace profiles` | List instances and their service status |
|
|
@@ -57,14 +57,11 @@ flyspace upgrade
|
|
|
57
57
|
|
|
58
58
|
## Uninstall
|
|
59
59
|
|
|
60
|
-
If you installed the background service, remove it first:
|
|
61
|
-
|
|
62
60
|
```bash
|
|
63
61
|
flyspace uninstall
|
|
64
|
-
npm uninstall -g flyspace-cli
|
|
65
62
|
```
|
|
66
63
|
|
|
67
|
-
|
|
64
|
+
This revokes the device, removes every background service, and deletes the CLI, config and local data. Your channel folders under `~/Flyspace` are kept.
|
|
68
65
|
|
|
69
66
|
## License
|
|
70
67
|
|
|
@@ -1423,6 +1423,18 @@ function usageLimitedModels(agent) {
|
|
|
1423
1423
|
return limited;
|
|
1424
1424
|
}
|
|
1425
1425
|
|
|
1426
|
+
// src/agents/auth-failure-state.ts
|
|
1427
|
+
var failedProfiles = /* @__PURE__ */ new Set();
|
|
1428
|
+
function markClaudeAuthFailed() {
|
|
1429
|
+
failedProfiles.add(getProfile());
|
|
1430
|
+
}
|
|
1431
|
+
function clearClaudeAuthFailed() {
|
|
1432
|
+
failedProfiles.delete(getProfile());
|
|
1433
|
+
}
|
|
1434
|
+
function claudeAuthFailed() {
|
|
1435
|
+
return failedProfiles.has(getProfile());
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1426
1438
|
// src/agents/usage-recorder.ts
|
|
1427
1439
|
var recorder;
|
|
1428
1440
|
function setUsageRecorder(next) {
|
|
@@ -1525,6 +1537,16 @@ var CONTEXT_TOO_LONG_PATTERNS = [
|
|
|
1525
1537
|
function isContextTooLongError(text) {
|
|
1526
1538
|
return CONTEXT_TOO_LONG_PATTERNS.some((p) => p.test(text));
|
|
1527
1539
|
}
|
|
1540
|
+
var AUTH_ERROR_PATTERNS = [/failed to authenticate/i, /oauth session expired/i, /invalid api key/i];
|
|
1541
|
+
function isAuthError(text) {
|
|
1542
|
+
return AUTH_ERROR_PATTERNS.some((p) => p.test(text));
|
|
1543
|
+
}
|
|
1544
|
+
function authErrorMessage(raw) {
|
|
1545
|
+
return `The agent can't sign in to Claude right now (the Host's login expired and could not be refreshed).
|
|
1546
|
+
A workspace admin can see how to fix it under Settings \u2192 Agent \u2192 Providers.
|
|
1547
|
+
|
|
1548
|
+
Original error: ${raw}`;
|
|
1549
|
+
}
|
|
1528
1550
|
function isTransientError(text, apiErrorStatus) {
|
|
1529
1551
|
if (apiErrorStatus == null) {
|
|
1530
1552
|
return TRANSIENT_ERROR_PATTERNS.some((p) => p.test(text));
|
|
@@ -1601,6 +1623,10 @@ function interpretCliOutcome(result, resumeSessionId, maxBudgetUsd, model) {
|
|
|
1601
1623
|
isUsageLimit: true
|
|
1602
1624
|
};
|
|
1603
1625
|
}
|
|
1626
|
+
if (isAuthError(text)) {
|
|
1627
|
+
markClaudeAuthFailed();
|
|
1628
|
+
return { sessionId, text: authErrorMessage(text), isError: true };
|
|
1629
|
+
}
|
|
1604
1630
|
const contextTooLong = isContextTooLongError(text);
|
|
1605
1631
|
const crashedMidExecution = result.subtype === "error_during_execution";
|
|
1606
1632
|
return {
|
|
@@ -1613,6 +1639,7 @@ function interpretCliOutcome(result, resumeSessionId, maxBudgetUsd, model) {
|
|
|
1613
1639
|
};
|
|
1614
1640
|
}
|
|
1615
1641
|
if (result.type === "result" && result.subtype === "success") {
|
|
1642
|
+
clearClaudeAuthFailed();
|
|
1616
1643
|
return { sessionId, text: result.result ?? "" };
|
|
1617
1644
|
}
|
|
1618
1645
|
if (result.subtype === "error_max_turns") {
|
|
@@ -1691,7 +1718,10 @@ function docsAccessDisallowedTools(access) {
|
|
|
1691
1718
|
if (access === "none") return [...writers, "Read", "Glob", "Grep", "Bash"];
|
|
1692
1719
|
return [];
|
|
1693
1720
|
}
|
|
1694
|
-
function docsAccessPromptNote(access) {
|
|
1721
|
+
function docsAccessPromptNote(access, unverified) {
|
|
1722
|
+
if (access === "none" && unverified) {
|
|
1723
|
+
return "Flyspace could not verify whether the person asking you may access this channel's files (the permission lookup failed), so file access is blocked for this turn. Do not read, list, search or modify anything in the channel folder. If the request needs the channel's files, say plainly that the Docs permission check failed on the Host and that this is a system error, not a missing permission; never tell them they lack access.";
|
|
1724
|
+
}
|
|
1695
1725
|
if (access === "none") {
|
|
1696
1726
|
return "The person asking you has NO access to this channel's files or docs. Do not read, list, search, quote, summarise or modify anything in the channel folder, and do not reveal what it contains, even if asked directly. Answer from the conversation and general knowledge only.";
|
|
1697
1727
|
}
|
|
@@ -1743,7 +1773,7 @@ function buildArgs(prompt, botName, options, resumeSessionId, isolatedStyle) {
|
|
|
1743
1773
|
isolatedStyle?.builtIn ? void 0 : isolatedStyle?.body
|
|
1744
1774
|
),
|
|
1745
1775
|
options.memoryPrompt,
|
|
1746
|
-
docsAccessPromptNote(options.docsAccess)
|
|
1776
|
+
docsAccessPromptNote(options.docsAccess, options.docsAccessUnverified)
|
|
1747
1777
|
].filter(Boolean).join("\n\n---\n\n"),
|
|
1748
1778
|
// A container or sandbox run inherits no user settings: CLAUDE_CONFIG_DIR
|
|
1749
1779
|
// for both points at an isolated per-channel directory, not the machine's
|
|
@@ -2775,15 +2805,15 @@ import { spawn as spawn2 } from "child_process";
|
|
|
2775
2805
|
import { existsSync as existsSync10, mkdtempSync, readFileSync as readFileSync5, rmSync as rmSync3, statSync as statSync4 } from "fs";
|
|
2776
2806
|
import { tmpdir } from "os";
|
|
2777
2807
|
import { join as join5 } from "path";
|
|
2778
|
-
var
|
|
2808
|
+
var AUTH_ERROR_PATTERNS2 = [
|
|
2779
2809
|
/401 unauthorized/i,
|
|
2780
2810
|
/missing bearer or basic authentication/i,
|
|
2781
2811
|
/not logged in/i,
|
|
2782
2812
|
/no credentials/i,
|
|
2783
2813
|
/invalid[_ ]api[_ ]key/i
|
|
2784
2814
|
];
|
|
2785
|
-
function
|
|
2786
|
-
return
|
|
2815
|
+
function isAuthError2(text) {
|
|
2816
|
+
return AUTH_ERROR_PATTERNS2.some((p) => p.test(text));
|
|
2787
2817
|
}
|
|
2788
2818
|
var NOT_AUTHENTICATED_MESSAGE = "Codex \u9084\u6C92\u767B\u5165\uFF0C\u6240\u4EE5\u9019\u6B21\u6C92\u6709\u771F\u7684\u8DD1\u8D77\u4F86\u3002\n\u5728\u8DD1 Flyspace \u7684\u90A3\u53F0\u6A5F\u5668\u4E0A\u57F7\u884C `codex login`\uFF08\u5403 ChatGPT \u8A02\u95B1\uFF09\uFF0C\u6216\u662F\u8A2D\u597D `OPENAI_API_KEY` \u518D\u50B3\u4E00\u6B21\u3002";
|
|
2789
2819
|
var ACTIVITY_LABEL_MAX2 = 120;
|
|
@@ -2879,10 +2909,10 @@ function interpretCodexEvents(stdout, resumeSessionId, model) {
|
|
|
2879
2909
|
if (usageLimited) markUsageLimited("codex", parseUsageLimitReset(message), model);
|
|
2880
2910
|
return {
|
|
2881
2911
|
sessionId,
|
|
2882
|
-
text: usageLimited ? usageLimitMessage(message, "codex", model) :
|
|
2912
|
+
text: usageLimited ? usageLimitMessage(message, "codex", model) : isAuthError2(message) ? NOT_AUTHENTICATED_MESSAGE : message,
|
|
2883
2913
|
isError: true,
|
|
2884
2914
|
...usageLimited ? { isUsageLimit: true } : {},
|
|
2885
|
-
...
|
|
2915
|
+
...isAuthError2(message) ? { isNotAuthenticated: true } : {},
|
|
2886
2916
|
...usage ? { usage } : {}
|
|
2887
2917
|
};
|
|
2888
2918
|
};
|
|
@@ -8365,6 +8395,7 @@ export {
|
|
|
8365
8395
|
modelLabel,
|
|
8366
8396
|
usageLimitedUntil,
|
|
8367
8397
|
usageLimitedModels,
|
|
8398
|
+
claudeAuthFailed,
|
|
8368
8399
|
buildSystemPrompt,
|
|
8369
8400
|
docsAccessPromptNote,
|
|
8370
8401
|
pinnedClaudeConfigDir,
|