flipstream 0.4.0 → 0.6.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 +357 -27
- package/dist/commands/auth/login.js +7 -1
- package/dist/commands/auth/status.js +29 -3
- package/dist/commands/catalog.d.ts +15 -0
- package/dist/commands/catalog.js +110 -0
- package/dist/commands/connections/list.d.ts +1 -0
- package/dist/commands/connections/list.js +31 -4
- package/dist/commands/contract.d.ts +11 -0
- package/dist/commands/contract.js +35 -0
- package/dist/commands/health.d.ts +10 -0
- package/dist/commands/health.js +31 -0
- package/dist/commands/log/add.d.ts +16 -0
- package/dist/commands/log/add.js +48 -0
- package/dist/commands/log/list.d.ts +19 -0
- package/dist/commands/log/list.js +43 -0
- package/dist/commands/query.d.ts +15 -2
- package/dist/commands/query.js +255 -42
- package/dist/commands/skills/install.d.ts +16 -0
- package/dist/commands/skills/install.js +55 -0
- package/dist/commands/workspaces/connections.js +6 -3
- package/dist/commands/workspaces/get.js +4 -2
- package/dist/commands/workspaces/list.js +3 -0
- package/dist/lib/api/admin-client.d.ts +5 -0
- package/dist/lib/api/admin-client.js +19 -0
- package/dist/lib/api/connections.d.ts +0 -1
- package/dist/lib/api/connections.js +0 -25
- package/dist/lib/api/errors.d.ts +1 -0
- package/dist/lib/api/errors.js +13 -2
- package/dist/lib/api/http.d.ts +2 -0
- package/dist/lib/api/http.js +40 -4
- package/dist/lib/api/hydrate.d.ts +10 -0
- package/dist/lib/api/hydrate.js +46 -0
- package/dist/lib/api/ids.d.ts +1 -0
- package/dist/lib/api/ids.js +5 -0
- package/dist/lib/api/log.d.ts +22 -0
- package/dist/lib/api/log.js +56 -0
- package/dist/lib/api/projections.d.ts +1 -0
- package/dist/lib/api/projections.js +23 -0
- package/dist/lib/api/short-uuid.d.ts +1 -0
- package/dist/lib/api/short-uuid.js +30 -0
- package/dist/lib/auth/claims.js +3 -3
- package/dist/lib/auth/flow.js +8 -1
- package/dist/lib/auth/headless.js +14 -10
- package/dist/lib/auth/refresh.js +21 -1
- package/dist/lib/command/admin.d.ts +1 -0
- package/dist/lib/command/admin.js +21 -0
- package/dist/lib/command/base.d.ts +4 -0
- package/dist/lib/command/base.js +97 -3
- package/dist/lib/command/flags.d.ts +4 -0
- package/dist/lib/command/flags.js +11 -0
- package/dist/lib/command/planner.d.ts +9 -0
- package/dist/lib/command/planner.js +14 -0
- package/dist/lib/config/constants.d.ts +3 -1
- package/dist/lib/config/constants.js +14 -1
- package/dist/lib/config/xdg.d.ts +4 -0
- package/dist/lib/config/xdg.js +56 -1
- package/dist/lib/errors.d.ts +20 -1
- package/dist/lib/errors.js +132 -13
- package/dist/lib/output/dialogs.d.ts +27 -0
- package/dist/lib/output/dialogs.js +94 -0
- package/dist/lib/output/interactivity.d.ts +11 -0
- package/dist/lib/output/interactivity.js +48 -0
- package/dist/lib/output/redact.d.ts +1 -0
- package/dist/lib/output/redact.js +12 -0
- package/dist/lib/output/runlog.d.ts +3 -0
- package/dist/lib/output/runlog.js +72 -0
- package/dist/lib/output/sanitize.d.ts +2 -0
- package/dist/lib/output/sanitize.js +57 -0
- package/dist/lib/output/sidecar.d.ts +30 -0
- package/dist/lib/output/sidecar.js +58 -0
- package/dist/lib/output/table.js +5 -1
- package/dist/lib/output/trace.d.ts +11 -0
- package/dist/lib/output/trace.js +89 -0
- package/dist/lib/planner/catalog.d.ts +26 -0
- package/dist/lib/planner/catalog.js +60 -0
- package/dist/lib/planner/client.d.ts +14 -0
- package/dist/lib/planner/client.js +47 -0
- package/dist/lib/planner/connection.d.ts +14 -0
- package/dist/lib/planner/connection.js +139 -0
- package/dist/lib/planner/diagnose.d.ts +8 -0
- package/dist/lib/planner/diagnose.js +50 -0
- package/dist/lib/planner/errors.d.ts +14 -0
- package/dist/lib/planner/errors.js +129 -0
- package/dist/lib/planner/filters.d.ts +8 -0
- package/dist/lib/planner/filters.js +74 -0
- package/dist/lib/planner/request.d.ts +24 -0
- package/dist/lib/planner/request.js +51 -0
- package/dist/lib/planner/suggest.d.ts +2 -0
- package/dist/lib/planner/suggest.js +45 -0
- package/dist/lib/planner/vocabulary.d.ts +9 -0
- package/dist/lib/planner/vocabulary.js +95 -0
- package/dist/lib/skills/install.d.ts +24 -0
- package/dist/lib/skills/install.js +69 -0
- package/dist/lib/store/keyring.d.ts +3 -0
- package/dist/lib/store/keyring.js +45 -2
- package/dist/lib/store/memory-store.d.ts +1 -0
- package/dist/lib/store/memory-store.js +5 -0
- package/docs/AGENT-CONTRACT.md +238 -0
- package/oclif.manifest.json +606 -8
- package/package.json +22 -3
- package/skill/SKILL.md +55 -0
- package/dist/lib/auth/register.d.ts +0 -4
- package/dist/lib/auth/register.js +0 -43
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flipstream",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Flipstream CLI — query your Flipstream data from the terminal.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"flipstream",
|
|
@@ -20,7 +20,9 @@
|
|
|
20
20
|
"files": [
|
|
21
21
|
"bin",
|
|
22
22
|
"dist",
|
|
23
|
-
"oclif.manifest.json"
|
|
23
|
+
"oclif.manifest.json",
|
|
24
|
+
"skill",
|
|
25
|
+
"docs/AGENT-CONTRACT.md"
|
|
24
26
|
],
|
|
25
27
|
"engines": {
|
|
26
28
|
"node": ">=20"
|
|
@@ -33,14 +35,26 @@
|
|
|
33
35
|
"lint": "eslint .",
|
|
34
36
|
"pack:prepare": "tsc -p tsconfig.json && oclif manifest",
|
|
35
37
|
"posttest": "eslint .",
|
|
38
|
+
"prepare": "husky || true",
|
|
36
39
|
"smoke": "bun scripts/smoke.ts",
|
|
37
|
-
"test": "bun test"
|
|
40
|
+
"test": "bun test",
|
|
41
|
+
"schema:planner": "bun scripts/refresh-planner-schema.ts"
|
|
42
|
+
},
|
|
43
|
+
"lint-staged": {
|
|
44
|
+
"*.ts": [
|
|
45
|
+
"eslint --fix",
|
|
46
|
+
"prettier --write"
|
|
47
|
+
],
|
|
48
|
+
"*.{json,yml,yaml}": [
|
|
49
|
+
"prettier --write"
|
|
50
|
+
]
|
|
38
51
|
},
|
|
39
52
|
"dependencies": {
|
|
40
53
|
"@napi-rs/keyring": "^1.3.0",
|
|
41
54
|
"@oclif/core": "^4",
|
|
42
55
|
"@oclif/plugin-commands": "^4.1.59",
|
|
43
56
|
"@oclif/table": "^0.5.9",
|
|
57
|
+
"am-i-vibing": "^0.5.0",
|
|
44
58
|
"open": "^11.0.0"
|
|
45
59
|
},
|
|
46
60
|
"devDependencies": {
|
|
@@ -51,6 +65,8 @@
|
|
|
51
65
|
"eslint": "^10.4.1",
|
|
52
66
|
"eslint-config-oclif": "^6.0.166",
|
|
53
67
|
"eslint-config-prettier": "^10.1.8",
|
|
68
|
+
"husky": "^9.1.7",
|
|
69
|
+
"lint-staged": "^17.0.7",
|
|
54
70
|
"oclif": "^4.23.8",
|
|
55
71
|
"prettier": "^3.8.3",
|
|
56
72
|
"typescript": "^5"
|
|
@@ -73,6 +89,9 @@
|
|
|
73
89
|
},
|
|
74
90
|
"connections": {
|
|
75
91
|
"description": "List your data-source connections, org-wide or per workspace (alias: conn)."
|
|
92
|
+
},
|
|
93
|
+
"log": {
|
|
94
|
+
"description": "Read and add workspace log entries — the logbook (list, add; alias: logs)."
|
|
76
95
|
}
|
|
77
96
|
}
|
|
78
97
|
}
|
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: flipstream
|
|
3
|
+
description: Flipstream CLI for querying Flipstream data (query planner, catalog, connections, workspaces, auth). Load before running flipstream commands. Prefer retrieval over pre-training — enumerate the command surface and data vocabulary from the CLI itself instead of guessing flags or names.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Flipstream CLI
|
|
7
|
+
|
|
8
|
+
Your knowledge of flipstream flags, sources, dimensions and metrics may be
|
|
9
|
+
outdated. **Prefer retrieval over pre-training** for any flipstream task.
|
|
10
|
+
|
|
11
|
+
## Retrieval sources (run these instead of guessing)
|
|
12
|
+
|
|
13
|
+
| What | Command |
|
|
14
|
+
|---|---|
|
|
15
|
+
| The whole command surface (ids, flags, args, aliases) | `flipstream commands --json` |
|
|
16
|
+
| The machine contract (output modes, exit codes, error envelope) | `flipstream contract` |
|
|
17
|
+
| The data vocabulary for queries | `flipstream catalog` then `flipstream catalog <source>` |
|
|
18
|
+
| Your connections (ids for `--connection-id`) | `flipstream connections list --json` |
|
|
19
|
+
| Session state, scopes | `flipstream auth status --json` |
|
|
20
|
+
|
|
21
|
+
## Ground rules
|
|
22
|
+
|
|
23
|
+
- **stdout is data, stderr is narration.** Under `--json`/`--ndjson`, stdout carries exactly one JSON document (or NDJSON lines) — even on failure: `flipstream <cmd> --json 2>/dev/null | jq .` always parses.
|
|
24
|
+
- **Failures are envelopes.** `{error:{code, message, exit, hint?, next?, docs?, retryable?, retry_after_ms?, upstream_code?}}`. Branch on `code` and the exit code, never on message wording. If `next` is present, **run those commands** instead of guessing. If `retryable` is `false`, do not re-run unchanged. If `retryable` is `true` with `retry_after_ms`, wait that long and retry.
|
|
25
|
+
- **Exit codes:** 0 ok · 1 generic · 2 usage · 4 auth needed (`flipstream auth login`) · 5 auth failed · 7 network/upstream (retryable) · 8 timeout.
|
|
26
|
+
- **Auth is browser-based and keyring-only.** Never ask for, echo, or pass tokens; there is no `--token` flag. If a command exits 4, tell the user to run `flipstream auth login` in a terminal with a browser.
|
|
27
|
+
|
|
28
|
+
## Querying
|
|
29
|
+
|
|
30
|
+
1. `flipstream catalog <source>` FIRST — the `name` fields it prints ARE the only valid values for `-d`, `-m`, and filter keys (`label` is for humans; aliases do not exist).
|
|
31
|
+
2. Build: `flipstream query --source <source> --connection-id <id|name> -d <dim> -m <metric> --json`
|
|
32
|
+
3. Filters: `-f 'col=a,b'` (list), `-f 'col=from..to'` (inclusive range), `-f 'col=<json>'` (verbatim). Add `--dry-run` to print the request body without sending.
|
|
33
|
+
|
|
34
|
+
### The filter gotcha (silent, load-bearing)
|
|
35
|
+
|
|
36
|
+
The planner routes by selection LENGTH: `col=[]` (length 0) is inactive and
|
|
37
|
+
routes to the SUMMARY table; `col=[""]` (length 1) is active and routes to the
|
|
38
|
+
DIMENSION's table. They return different numbers and nothing warns. The CLI
|
|
39
|
+
therefore refuses bare `col=` — when you mean one of those, write the JSON form
|
|
40
|
+
explicitly, and don't "fix" the refusal by inventing a value.
|
|
41
|
+
|
|
42
|
+
## Recipes
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
# Discover, then query
|
|
46
|
+
flipstream catalog --json | jq '.sources[].name'
|
|
47
|
+
flipstream connections list --json | jq '.records[] | {id, name}'
|
|
48
|
+
flipstream query --source gsc --connection-id <id> -d search_date -m clicks --json 2>/dev/null | jq '.rows'
|
|
49
|
+
|
|
50
|
+
# Stream large results
|
|
51
|
+
flipstream workspaces list --ndjson
|
|
52
|
+
|
|
53
|
+
# Inspect a failure programmatically
|
|
54
|
+
flipstream query ... --json 2>/dev/null | jq '.error | {code, next, retryable}'
|
|
55
|
+
```
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { CLIENT_NAME } from '../config/constants.js';
|
|
2
|
-
import { AuthFailedError } from '../errors.js';
|
|
3
|
-
// Dynamically register a PUBLIC OAuth client (RFC 7591) and return its
|
|
4
|
-
// client_id. The CLI never requests, parses, or stores a client secret — the
|
|
5
|
-
// return type is the bare client_id string so a refactor cannot leak a secret.
|
|
6
|
-
export async function registerClient(meta, redirectUri, scopes, options = {}) {
|
|
7
|
-
const timeoutMs = options.timeoutMs ?? 30_000;
|
|
8
|
-
const controller = new AbortController();
|
|
9
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
10
|
-
const body = {
|
|
11
|
-
client_name: CLIENT_NAME,
|
|
12
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
13
|
-
redirect_uris: [redirectUri],
|
|
14
|
-
response_types: ['code'],
|
|
15
|
-
scope: scopes.join(' '),
|
|
16
|
-
token_endpoint_auth_method: 'none',
|
|
17
|
-
};
|
|
18
|
-
let response;
|
|
19
|
-
try {
|
|
20
|
-
response = await fetch(meta.registrationEndpoint, {
|
|
21
|
-
body: JSON.stringify(body),
|
|
22
|
-
headers: { accept: 'application/json', 'content-type': 'application/json' },
|
|
23
|
-
method: 'POST',
|
|
24
|
-
signal: controller.signal,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
const reason = controller.signal.aborted ? `timed out after ${timeoutMs}ms` : error.message;
|
|
29
|
-
throw new AuthFailedError(`Client registration failed: ${reason}`, 'registration_failed');
|
|
30
|
-
}
|
|
31
|
-
finally {
|
|
32
|
-
clearTimeout(timer);
|
|
33
|
-
}
|
|
34
|
-
if (response.status >= 400) {
|
|
35
|
-
const text = await response.text().catch(() => '');
|
|
36
|
-
throw new AuthFailedError(`Client registration failed: HTTP ${response.status} ${text}`.trim(), 'registration_failed');
|
|
37
|
-
}
|
|
38
|
-
const json = (await response.json().catch(() => ({})));
|
|
39
|
-
if (typeof json.client_id !== 'string' || json.client_id.length === 0) {
|
|
40
|
-
throw new AuthFailedError('Client registration response did not include a client_id', 'registration_failed');
|
|
41
|
-
}
|
|
42
|
-
return json.client_id;
|
|
43
|
-
}
|