gipity 1.0.410 → 1.0.411

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.
@@ -145,13 +145,17 @@ creditsCommand
145
145
  // commander binds to the parent - read merged opts so --json is seen here.
146
146
  .action((_opts, cmd) => run('Plans', async () => {
147
147
  const opts = cmd.optsWithGlobals();
148
- const [plansRes, productsRes, subRes] = await Promise.all([
148
+ // Plans + subscription are required; credit packs are best-effort - the plan
149
+ // comparison must still render if /credits/products is unavailable (e.g.
150
+ // credit packs aren't configured in this environment).
151
+ const [plansRes, subRes] = await Promise.all([
149
152
  get('/plans'),
150
- get('/credits/products'),
151
153
  get('/credits/subscription'),
152
154
  ]);
155
+ const products = await get('/credits/products')
156
+ .then(r => r.data).catch(() => []);
153
157
  if (opts.json) {
154
- console.log(JSON.stringify({ currentTier: subRes.data.tier, plans: plansRes.data, products: productsRes.data }));
158
+ console.log(JSON.stringify({ currentTier: subRes.data.tier, plans: plansRes.data, products }));
155
159
  return;
156
160
  }
157
161
  const currentTier = subRes.data.tier;
@@ -171,7 +175,7 @@ creditsCommand
171
175
  renderLimits(plan.limits, ' ');
172
176
  console.log('');
173
177
  }
174
- const packs = productsRes.data.filter(p => p.type === 'one_time');
178
+ const packs = products.filter(p => p.type === 'one_time');
175
179
  if (packs.length > 0) {
176
180
  console.log(bold('Credit packs') + muted(' (require an active Pro subscription)'));
177
181
  for (const pack of packs) {
@@ -195,11 +199,12 @@ creditsCommand
195
199
  // commander binds to the parent - read merged opts so --json/--open are seen here.
196
200
  .action((target, _opts, cmd) => run('Buy', async () => {
197
201
  const opts = cmd.optsWithGlobals();
198
- const [productsRes, subRes] = await Promise.all([
199
- get('/credits/products'),
200
- get('/credits/subscription'),
201
- ]);
202
- const products = productsRes.data;
202
+ const subRes = await get('/credits/subscription');
203
+ // Products are best-effort: if the catalog is unavailable we can't build a
204
+ // direct checkout link, so we fall back to the pricing page below rather
205
+ // than erroring out.
206
+ const products = await get('/credits/products')
207
+ .then(r => r.data).catch(() => []);
203
208
  const currentTier = subRes.data.tier;
204
209
  // Resolve the target product. With no arg, default to the first available
205
210
  // paid subscription (the upgrade path). With an arg, match a plan/pack by
@@ -7,14 +7,14 @@
7
7
  *
8
8
  * Not a user-facing `gipity` subcommand by design: users never invoke
9
9
  * this directly. The Gipity Claude Code plugin's capture hook script
10
- * (claude-plugin hooks/scripts/capture.cjs) resolves this file inside the
10
+ * (skills repo hooks/scripts/capture.cjs) resolves this file inside the
11
11
  * installed CLI at fire time and runs it - so the capture logic versions
12
12
  * with the CLI, not the plugin.
13
13
  *
14
14
  * Usage:
15
15
  * node capture-runner.js <source> <event>
16
16
  * source: 'claude-code' (today) | future: 'codex', …
17
- * event: 'session-start' | 'stop' | 'subagent-stop' | 'session-end' | 'post-tool-use'
17
+ * event: 'session-start' | 'stop' | 'subagent-stop' | 'session-end' | 'post-tool-use' | 'pre-compact'
18
18
  *
19
19
  * Graceful no-ops (exit 0 silently):
20
20
  * - GIPITY_CONVERSATION_GUID env var unset (hook fired from a bare
@@ -304,6 +304,19 @@ async function main() {
304
304
  case 'session-end':
305
305
  await handleSessionEnd(convGuid, hook, source);
306
306
  break;
307
+ case 'pre-compact': {
308
+ // Flush the transcript tail BEFORE compaction rewrites it (the
309
+ // watermark replay after a rewrite relies on server dedup, but
310
+ // flushing first keeps ordering clean), then record the boundary.
311
+ await handleStopFamily(convGuid, hook, false);
312
+ const trigger = typeof hook.trigger === 'string' ? hook.trigger : 'auto';
313
+ await postEntries(convGuid, [{
314
+ kind: 'compact',
315
+ trigger,
316
+ source_uuid: `${hook.session_id ?? 'unknown'}-compact-${Date.now()}`,
317
+ }]);
318
+ break;
319
+ }
307
320
  default:
308
321
  return; // unknown event - silent no-op
309
322
  }