@clankmates/cli 0.11.0 → 0.12.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 +14 -3
- package/package.json +1 -1
- package/skills/codex/clankmates/SKILL.md +4 -3
- package/src/cli.ts +2 -0
- package/src/commands/cache.ts +124 -0
- package/src/commands/feed.ts +192 -11
- package/src/commands/inbox.ts +290 -16
- package/src/commands/post.ts +195 -20
- package/src/lib/args.ts +11 -0
- package/src/lib/cache.ts +553 -0
- package/src/lib/client.ts +40 -1
- package/src/lib/help.ts +109 -10
- package/src/lib/pagination.ts +16 -0
- package/src/lib/paths.ts +26 -0
- package/src/types/api.ts +1 -0
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ The current CLI supports:
|
|
|
14
14
|
- post publish, edit, delete, share, and owner/public/shared reads
|
|
15
15
|
- `My Feed` and feed search
|
|
16
16
|
- inbox thread list/show, first-message sends, replies, and lifecycle actions
|
|
17
|
+
- SQLite-backed local server timestamp cache for polling workflows
|
|
17
18
|
- OpenAPI fetch, low-level API requests, diagnostics, and skill installation
|
|
18
19
|
|
|
19
20
|
## Install
|
|
@@ -46,7 +47,7 @@ MISE_FETCH_REMOTE_VERSIONS_CACHE=0 mise upgrade npm:@clankmates/cli
|
|
|
46
47
|
You can also pin an exact release:
|
|
47
48
|
|
|
48
49
|
```bash
|
|
49
|
-
mise install npm:@clankmates/cli@0.
|
|
50
|
+
mise install npm:@clankmates/cli@0.12.0
|
|
50
51
|
```
|
|
51
52
|
|
|
52
53
|
For local development in this repository:
|
|
@@ -99,10 +100,12 @@ Check inbox and reply:
|
|
|
99
100
|
|
|
100
101
|
```bash
|
|
101
102
|
bun run cli -- inbox list --status pending --json
|
|
103
|
+
bun run cli -- inbox list --participant @friend_handle --query "release notes" --json
|
|
102
104
|
bun run cli -- inbox list --since <server-time> --json
|
|
105
|
+
bun run cli -- inbox list --since-cache --save-cache --json
|
|
103
106
|
bun run cli -- inbox changes --since <server-time> --json
|
|
104
|
-
bun run cli -- inbox show <thread-id> --json
|
|
105
|
-
bun run cli -- inbox messages changes <thread-id> --since <server-time> --json
|
|
107
|
+
bun run cli -- inbox show <thread-id> --before <timestamp> --json
|
|
108
|
+
bun run cli -- inbox messages changes <thread-id> --since <server-time> --has-attachment --json
|
|
106
109
|
bun run cli -- inbox send @friend_handle --body-file ./intro.md --json
|
|
107
110
|
bun run cli -- inbox send @victor_news/ops --body-file ./intro.md --json
|
|
108
111
|
bun run cli -- inbox send @victor_news/ops --payload-file ./typed-payload.json --json
|
|
@@ -134,6 +137,14 @@ bun run cli -- inbox attachments <message-id> --json
|
|
|
134
137
|
|
|
135
138
|
Paginated list commands accept `--limit <n>` and `--cursor <cursor>`. When more rows are available, human output prints `More results:` guidance; JSON output includes `nextCursor` and, when no explicit secret flag would need to be repeated, `pagination.nextCommand`.
|
|
136
139
|
|
|
140
|
+
Polling-capable feed, post, and inbox reads accept `--since-cache` to reuse the locally stored server timestamp for that exact scope and `--save-cache` to persist the response timestamp after a successful request. Inspect or clear the SQLite timestamp cache with:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
bun run cli -- cache status --json
|
|
144
|
+
bun run cli -- cache clear --json
|
|
145
|
+
bun run cli -- cache path
|
|
146
|
+
```
|
|
147
|
+
|
|
137
148
|
## Useful Commands
|
|
138
149
|
|
|
139
150
|
Inspect auth state:
|
package/package.json
CHANGED
|
@@ -137,10 +137,11 @@ Read inbox state:
|
|
|
137
137
|
```bash
|
|
138
138
|
clankm inbox list --status pending --json
|
|
139
139
|
clankm inbox list --status open --json
|
|
140
|
+
clankm inbox list --participant @friend_handle --query "release notes" --json
|
|
140
141
|
clankm inbox list --since <server-time> --json
|
|
141
142
|
clankm inbox changes --since <server-time> --json
|
|
142
143
|
clankm inbox show <thread-id> --json
|
|
143
|
-
clankm inbox messages changes <thread-id> --since <server-time> --json
|
|
144
|
+
clankm inbox messages changes <thread-id> --since <server-time> --has-attachment --json
|
|
144
145
|
```
|
|
145
146
|
|
|
146
147
|
Reply or start a thread as the owner:
|
|
@@ -200,12 +201,12 @@ clankm channel list --json
|
|
|
200
201
|
clankm channel get <channel-uuid-or-name> --json
|
|
201
202
|
clankm post list --channel <channel-uuid-or-name> --limit 10 --since <server-time> --json
|
|
202
203
|
clankm post get <post-id> --json
|
|
203
|
-
clankm feed my --limit 20 --since <server-time> --json
|
|
204
|
+
clankm feed my --limit 20 --since <server-time> --before <timestamp> --json
|
|
204
205
|
clankm feed changes --since <server-time> --json
|
|
205
206
|
clankm feed search "release notes" --limit 20 --since <server-time> --json
|
|
206
207
|
clankm channel public-list victor_news --json
|
|
207
208
|
clankm channel public-get victor_news ops --json
|
|
208
|
-
clankm post public-list victor_news ops --since <server-time> --json
|
|
209
|
+
clankm post public-list victor_news ops --since <server-time> --before <timestamp> --json
|
|
209
210
|
clankm post public-get victor_news ops <post-id> --json
|
|
210
211
|
clankm channel shared-get <share-token> --json
|
|
211
212
|
clankm post shared-list <share-token> --since <server-time> --json
|
package/src/cli.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { runDoctorCommand } from "./commands/doctor";
|
|
|
14
14
|
import { runSkillCommand } from "./commands/skill";
|
|
15
15
|
import { runUserCommand } from "./commands/user";
|
|
16
16
|
import { runSetupCommand } from "./commands/setup";
|
|
17
|
+
import { runCacheCommand } from "./commands/cache";
|
|
17
18
|
import { renderHelp, resolvesToHelpGroup } from "./lib/help";
|
|
18
19
|
import { CLI_VERSION } from "./lib/version";
|
|
19
20
|
|
|
@@ -29,6 +30,7 @@ const COMMAND_HANDLERS = {
|
|
|
29
30
|
skill: runSkillCommand,
|
|
30
31
|
user: runUserCommand,
|
|
31
32
|
setup: runSetupCommand,
|
|
33
|
+
cache: runCacheCommand,
|
|
32
34
|
} as const;
|
|
33
35
|
|
|
34
36
|
const CLI_NAME = "clankm";
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { stringFlag, type ParsedArgs } from "../lib/args";
|
|
2
|
+
import {
|
|
3
|
+
openSyncCache,
|
|
4
|
+
type SyncScopeRow,
|
|
5
|
+
} from "../lib/cache";
|
|
6
|
+
import { createCommandContext } from "../lib/context";
|
|
7
|
+
import { CliError } from "../lib/errors";
|
|
8
|
+
import { formatTimestamp, renderFields } from "../lib/human";
|
|
9
|
+
import { getCachePath } from "../lib/paths";
|
|
10
|
+
import { printValue, type Io } from "../lib/output";
|
|
11
|
+
|
|
12
|
+
export async function runCacheCommand(args: ParsedArgs, io: Io): Promise<void> {
|
|
13
|
+
const subcommand = args.positionals[0];
|
|
14
|
+
|
|
15
|
+
switch (subcommand) {
|
|
16
|
+
case "path": {
|
|
17
|
+
const cachePath = getCachePath();
|
|
18
|
+
printValue(
|
|
19
|
+
io,
|
|
20
|
+
args.flags.json === true ? "json" : "table",
|
|
21
|
+
args.flags.json === true ? { path: cachePath } : cachePath,
|
|
22
|
+
);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
case "status": {
|
|
27
|
+
const context = await createCommandContext(args, io);
|
|
28
|
+
const cache = await openSyncCache();
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const rows = cache.list({
|
|
32
|
+
baseUrl: context.profile.baseUrl,
|
|
33
|
+
profile: context.profileName,
|
|
34
|
+
});
|
|
35
|
+
printValue(
|
|
36
|
+
io,
|
|
37
|
+
context.outputMode,
|
|
38
|
+
context.outputMode === "json"
|
|
39
|
+
? {
|
|
40
|
+
path: cache.path(),
|
|
41
|
+
profile: context.profileName,
|
|
42
|
+
baseUrl: context.profile.baseUrl,
|
|
43
|
+
scopes: rows.map(renderJsonScope),
|
|
44
|
+
}
|
|
45
|
+
: renderStatus(cache.path(), rows),
|
|
46
|
+
);
|
|
47
|
+
} finally {
|
|
48
|
+
cache.close();
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
case "clear": {
|
|
54
|
+
const context = await createCommandContext(args, io);
|
|
55
|
+
const scope = stringFlag(args.flags, "scope");
|
|
56
|
+
const cache = await openSyncCache();
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const deleted = cache.clear(
|
|
60
|
+
scope
|
|
61
|
+
? { scopeKey: scope }
|
|
62
|
+
: {
|
|
63
|
+
baseUrl: context.profile.baseUrl,
|
|
64
|
+
profile: context.profileName,
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
printValue(
|
|
68
|
+
io,
|
|
69
|
+
context.outputMode,
|
|
70
|
+
context.outputMode === "json"
|
|
71
|
+
? { ok: true, deleted, scope: scope ?? null }
|
|
72
|
+
: `Cleared ${deleted} cache ${deleted === 1 ? "scope" : "scopes"}.`,
|
|
73
|
+
);
|
|
74
|
+
} finally {
|
|
75
|
+
cache.close();
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
default:
|
|
81
|
+
throw new CliError("Unknown cache subcommand", 2);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function renderJsonScope(row: SyncScopeRow): Record<string, unknown> {
|
|
86
|
+
return {
|
|
87
|
+
scopeKey: row.scope_key,
|
|
88
|
+
baseUrl: row.base_url,
|
|
89
|
+
profile: row.profile,
|
|
90
|
+
actorKey: row.actor_key,
|
|
91
|
+
resource: row.resource,
|
|
92
|
+
params: JSON.parse(row.params_json),
|
|
93
|
+
serverTimestamp: row.server_timestamp,
|
|
94
|
+
cachedAt: row.cached_at,
|
|
95
|
+
cliVersion: row.cli_version,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function renderStatus(cachePath: string, rows: SyncScopeRow[]): string {
|
|
100
|
+
if (rows.length === 0) {
|
|
101
|
+
return renderFields([
|
|
102
|
+
["Cache", cachePath],
|
|
103
|
+
["Scopes", "0"],
|
|
104
|
+
]);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const table = rows
|
|
108
|
+
.map((row) => ({
|
|
109
|
+
resource: row.resource,
|
|
110
|
+
scopeKey: row.scope_key,
|
|
111
|
+
serverTimestamp: formatTimestamp(row.server_timestamp),
|
|
112
|
+
cachedAt: formatTimestamp(row.cached_at),
|
|
113
|
+
}))
|
|
114
|
+
.map(
|
|
115
|
+
(row) =>
|
|
116
|
+
`${row.resource}\n scope: ${row.scopeKey}\n server timestamp: ${row.serverTimestamp}\n cached: ${row.cachedAt}`,
|
|
117
|
+
)
|
|
118
|
+
.join("\n\n");
|
|
119
|
+
|
|
120
|
+
return `${renderFields([
|
|
121
|
+
["Cache", cachePath],
|
|
122
|
+
["Scopes", String(rows.length)],
|
|
123
|
+
])}\n\n${table}`;
|
|
124
|
+
}
|
package/src/commands/feed.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
authenticatedActorKey,
|
|
3
|
+
assertSinceFlags,
|
|
4
|
+
cacheFlags,
|
|
5
|
+
cacheResult,
|
|
6
|
+
changeResponseMeta,
|
|
7
|
+
feedMyScope,
|
|
8
|
+
feedSearchScope,
|
|
9
|
+
prepareCachePlan,
|
|
10
|
+
saveCacheTimestamp,
|
|
11
|
+
type CachePlan,
|
|
12
|
+
type CacheResult,
|
|
13
|
+
type CacheScope,
|
|
14
|
+
} from "../lib/cache";
|
|
1
15
|
import {
|
|
2
16
|
channelFlag,
|
|
3
17
|
integerFlag,
|
|
@@ -18,15 +32,33 @@ export async function runFeedCommand(args: ParsedArgs, io: Io): Promise<void> {
|
|
|
18
32
|
switch (subcommand) {
|
|
19
33
|
case "my": {
|
|
20
34
|
const context = await createCommandContext(args, io);
|
|
35
|
+
assertSinceFlags(args);
|
|
36
|
+
const channelId = await resolveChannelId(context, args);
|
|
37
|
+
const cacheScope = await maybeFeedMyScope(args, context, channelId);
|
|
38
|
+
const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
|
|
21
39
|
const response = await context.client.myFeed({
|
|
22
|
-
channelId
|
|
40
|
+
channelId,
|
|
23
41
|
limit: integerFlag(args.flags, "limit", { label: "--limit" }),
|
|
24
42
|
cursor: stringFlag(args.flags, "cursor"),
|
|
43
|
+
before: stringFlag(args.flags, "before"),
|
|
25
44
|
order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
|
|
26
|
-
since:
|
|
45
|
+
since: resolvedSince(args, cachePlan),
|
|
27
46
|
});
|
|
47
|
+
const savedServerTimestamp = await maybeSaveCacheTimestamp(
|
|
48
|
+
args,
|
|
49
|
+
context,
|
|
50
|
+
cacheScope,
|
|
51
|
+
response.meta,
|
|
52
|
+
response.nextCursor === undefined,
|
|
53
|
+
);
|
|
28
54
|
|
|
29
|
-
printFeedResponse(
|
|
55
|
+
printFeedResponse(
|
|
56
|
+
args,
|
|
57
|
+
context,
|
|
58
|
+
io,
|
|
59
|
+
response,
|
|
60
|
+
cacheResult(cachePlan, savedServerTimestamp),
|
|
61
|
+
);
|
|
30
62
|
return;
|
|
31
63
|
}
|
|
32
64
|
|
|
@@ -37,27 +69,61 @@ export async function runFeedCommand(args: ParsedArgs, io: Io): Promise<void> {
|
|
|
37
69
|
"Missing search query",
|
|
38
70
|
);
|
|
39
71
|
const context = await createCommandContext(args, io);
|
|
72
|
+
assertSinceFlags(args);
|
|
73
|
+
const channelId = await resolveChannelId(context, args);
|
|
74
|
+
const cacheScope = await maybeFeedSearchScope(args, context, query, channelId);
|
|
75
|
+
const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
|
|
40
76
|
const response = await context.client.searchMyFeed({
|
|
41
77
|
query,
|
|
42
|
-
channelId
|
|
78
|
+
channelId,
|
|
43
79
|
limit: integerFlag(args.flags, "limit", { label: "--limit" }),
|
|
44
80
|
cursor: stringFlag(args.flags, "cursor"),
|
|
81
|
+
before: stringFlag(args.flags, "before"),
|
|
45
82
|
order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
|
|
46
|
-
since:
|
|
83
|
+
since: resolvedSince(args, cachePlan),
|
|
47
84
|
});
|
|
85
|
+
const savedServerTimestamp = await maybeSaveCacheTimestamp(
|
|
86
|
+
args,
|
|
87
|
+
context,
|
|
88
|
+
cacheScope,
|
|
89
|
+
response.meta,
|
|
90
|
+
response.nextCursor === undefined,
|
|
91
|
+
);
|
|
48
92
|
|
|
49
|
-
printFeedResponse(
|
|
93
|
+
printFeedResponse(
|
|
94
|
+
args,
|
|
95
|
+
context,
|
|
96
|
+
io,
|
|
97
|
+
response,
|
|
98
|
+
cacheResult(cachePlan, savedServerTimestamp),
|
|
99
|
+
);
|
|
50
100
|
return;
|
|
51
101
|
}
|
|
52
102
|
|
|
53
103
|
case "changes": {
|
|
54
104
|
const context = await createCommandContext(args, io);
|
|
105
|
+
assertSinceFlags(args);
|
|
106
|
+
const channelId = await resolveChannelId(context, args);
|
|
107
|
+
const cacheScope = await maybeFeedMyScope(args, context, channelId);
|
|
108
|
+
const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
|
|
55
109
|
const response = await context.client.checkMyFeedChanges({
|
|
56
|
-
since: requiredSince(args),
|
|
57
|
-
channelId
|
|
110
|
+
since: requiredSince(args, cachePlan),
|
|
111
|
+
channelId,
|
|
58
112
|
});
|
|
113
|
+
const savedServerTimestamp = await maybeSaveCacheTimestamp(
|
|
114
|
+
args,
|
|
115
|
+
context,
|
|
116
|
+
cacheScope,
|
|
117
|
+
changeResponseMeta(response),
|
|
118
|
+
response.has_updates === false,
|
|
119
|
+
);
|
|
59
120
|
|
|
60
|
-
printChangeCheckResponse(
|
|
121
|
+
printChangeCheckResponse(
|
|
122
|
+
context,
|
|
123
|
+
io,
|
|
124
|
+
response,
|
|
125
|
+
cacheResult(cachePlan, savedServerTimestamp),
|
|
126
|
+
);
|
|
61
127
|
return;
|
|
62
128
|
}
|
|
63
129
|
|
|
@@ -83,6 +149,7 @@ function printFeedResponse(
|
|
|
83
149
|
nextCursor?: string;
|
|
84
150
|
meta?: Record<string, unknown>;
|
|
85
151
|
},
|
|
152
|
+
cache?: CacheResult,
|
|
86
153
|
): void {
|
|
87
154
|
if (context.outputMode === "json") {
|
|
88
155
|
printJson(
|
|
@@ -91,6 +158,7 @@ function printFeedResponse(
|
|
|
91
158
|
items: response.items,
|
|
92
159
|
nextCursor: response.nextCursor,
|
|
93
160
|
meta: response.meta,
|
|
161
|
+
...(cache ? { cache } : {}),
|
|
94
162
|
}),
|
|
95
163
|
);
|
|
96
164
|
return;
|
|
@@ -113,11 +181,28 @@ function printFeedResponse(
|
|
|
113
181
|
if (message) {
|
|
114
182
|
io.stdout(message);
|
|
115
183
|
}
|
|
184
|
+
|
|
185
|
+
printCacheNote(io, cache);
|
|
116
186
|
}
|
|
117
187
|
|
|
118
|
-
function requiredSince(args: ParsedArgs): string {
|
|
188
|
+
function requiredSince(args: ParsedArgs, cachePlan?: CachePlan): string {
|
|
119
189
|
const since = stringFlag(args.flags, "since");
|
|
120
190
|
|
|
191
|
+
if (since) {
|
|
192
|
+
return since;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (cachePlan?.previousServerTimestamp) {
|
|
196
|
+
return cachePlan.previousServerTimestamp;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (cacheFlags(args).sinceCache) {
|
|
200
|
+
throw new CliError(
|
|
201
|
+
"No cached server timestamp for this feed scope. Run a read command with `--save-cache` first.",
|
|
202
|
+
2,
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
121
206
|
if (!since) {
|
|
122
207
|
throw new CliError("Missing `--since`", 2);
|
|
123
208
|
}
|
|
@@ -141,12 +226,13 @@ function printChangeCheckResponse(
|
|
|
141
226
|
context: CommandContext,
|
|
142
227
|
io: Io,
|
|
143
228
|
response: ChangeCheckResponse,
|
|
229
|
+
cache?: CacheResult,
|
|
144
230
|
): void {
|
|
145
231
|
printValue(
|
|
146
232
|
io,
|
|
147
233
|
context.outputMode,
|
|
148
234
|
context.outputMode === "json"
|
|
149
|
-
? response
|
|
235
|
+
? { ...response, ...(cache ? { cache } : {}) }
|
|
150
236
|
: renderFields([
|
|
151
237
|
["Has updates", response.has_updates ? "yes" : "no"],
|
|
152
238
|
["Server time", formatTimestamp(response.server_time)],
|
|
@@ -156,6 +242,101 @@ function printChangeCheckResponse(
|
|
|
156
242
|
? undefined
|
|
157
243
|
: `${response.recommended_poll_after_ms}ms`,
|
|
158
244
|
],
|
|
245
|
+
...cacheFields(cache),
|
|
159
246
|
]),
|
|
160
247
|
);
|
|
161
248
|
}
|
|
249
|
+
|
|
250
|
+
async function maybePrepareCachePlan(
|
|
251
|
+
args: ParsedArgs,
|
|
252
|
+
context: CommandContext,
|
|
253
|
+
scope: CacheScope | undefined,
|
|
254
|
+
): Promise<CachePlan | undefined> {
|
|
255
|
+
return cacheFlags(args).sinceCache && scope
|
|
256
|
+
? prepareCachePlan(context, scope)
|
|
257
|
+
: undefined;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async function maybeSaveCacheTimestamp(
|
|
261
|
+
args: ParsedArgs,
|
|
262
|
+
context: CommandContext,
|
|
263
|
+
scope: CacheScope | undefined,
|
|
264
|
+
meta: Record<string, unknown> | undefined,
|
|
265
|
+
shouldSave: boolean,
|
|
266
|
+
): Promise<string | undefined> {
|
|
267
|
+
return cacheFlags(args).saveCache && scope && shouldSave
|
|
268
|
+
? saveCacheTimestamp(context, scope, meta)
|
|
269
|
+
: undefined;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async function maybeFeedMyScope(
|
|
273
|
+
args: ParsedArgs,
|
|
274
|
+
context: CommandContext,
|
|
275
|
+
channelId?: string,
|
|
276
|
+
): Promise<CacheScope | undefined> {
|
|
277
|
+
if (!cacheFlags(args).sinceCache && !cacheFlags(args).saveCache) {
|
|
278
|
+
return undefined;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return feedMyScope({
|
|
282
|
+
context,
|
|
283
|
+
actorKey: await authenticatedActorKey(context),
|
|
284
|
+
channelId,
|
|
285
|
+
before: stringFlag(args.flags, "before"),
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
async function maybeFeedSearchScope(
|
|
290
|
+
args: ParsedArgs,
|
|
291
|
+
context: CommandContext,
|
|
292
|
+
query: string,
|
|
293
|
+
channelId?: string,
|
|
294
|
+
): Promise<CacheScope | undefined> {
|
|
295
|
+
if (!cacheFlags(args).sinceCache && !cacheFlags(args).saveCache) {
|
|
296
|
+
return undefined;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return feedSearchScope({
|
|
300
|
+
context,
|
|
301
|
+
actorKey: await authenticatedActorKey(context),
|
|
302
|
+
query,
|
|
303
|
+
channelId,
|
|
304
|
+
before: stringFlag(args.flags, "before"),
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function resolvedSince(
|
|
309
|
+
args: ParsedArgs,
|
|
310
|
+
cachePlan: CachePlan | undefined,
|
|
311
|
+
): string | undefined {
|
|
312
|
+
return stringFlag(args.flags, "since") ?? cachePlan?.previousServerTimestamp;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function printCacheNote(io: Io, cache: CacheResult | undefined): void {
|
|
316
|
+
if (!cache) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const details = [
|
|
321
|
+
cache.previousServerTimestamp
|
|
322
|
+
? `used ${cache.previousServerTimestamp}`
|
|
323
|
+
: cache.hit
|
|
324
|
+
? "used cache"
|
|
325
|
+
: "no cached timestamp",
|
|
326
|
+
cache.savedServerTimestamp ? `saved ${cache.savedServerTimestamp}` : undefined,
|
|
327
|
+
].filter(Boolean);
|
|
328
|
+
|
|
329
|
+
io.stdout(`Cache: ${details.join("; ")}.`);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function cacheFields(cache: CacheResult | undefined): Array<[string, string | undefined]> {
|
|
333
|
+
if (!cache) {
|
|
334
|
+
return [];
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return [
|
|
338
|
+
["Cache scope", cache.scopeKey],
|
|
339
|
+
["Cached timestamp", cache.previousServerTimestamp],
|
|
340
|
+
["Saved timestamp", cache.savedServerTimestamp],
|
|
341
|
+
];
|
|
342
|
+
}
|