@threadbase-sh/streamer 1.37.0 → 1.38.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/dist/cli.cjs +1304 -368
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +1005 -128
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +131 -5
- package/dist/index.d.ts +131 -5
- package/dist/index.js +1003 -126
- package/dist/index.js.map +1 -1
- package/dist/launchd-entry.cjs +113 -30
- package/dist/launchd-entry.cjs.map +1 -1
- package/dist/migrations/013_add_push_token_kind.sql +63 -0
- package/dist/pg-migrations/007_create_push_tokens.sql +93 -0
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -102,6 +102,17 @@ interface FlagDefinition {
|
|
|
102
102
|
type ClaudeFlagValue = string | string[] | boolean;
|
|
103
103
|
type ClaudeFlagValues = Record<string, ClaudeFlagValue>;
|
|
104
104
|
|
|
105
|
+
interface FeatureFlagDefinition {
|
|
106
|
+
/** Stable config/wire key. Used in server.yaml, on the CLI, and over HTTP. */
|
|
107
|
+
id: string;
|
|
108
|
+
/** Shipped to clients alongside the values so a UI can render it. */
|
|
109
|
+
description: string;
|
|
110
|
+
default: boolean;
|
|
111
|
+
/** Full env var name. */
|
|
112
|
+
env: string;
|
|
113
|
+
}
|
|
114
|
+
type FeatureFlagValues = Record<string, boolean>;
|
|
115
|
+
|
|
105
116
|
declare const CLAUDE_CODE_PROVIDER: "claude-code";
|
|
106
117
|
declare const CODEX_CLI_PROVIDER: "codex-cli";
|
|
107
118
|
type ProviderName = typeof CLAUDE_CODE_PROVIDER | typeof CODEX_CLI_PROVIDER;
|
|
@@ -487,6 +498,8 @@ interface ServerConfig {
|
|
|
487
498
|
tailSize?: number;
|
|
488
499
|
directoryScanDebounceMs?: number;
|
|
489
500
|
defaultSystemPrompt?: string;
|
|
501
|
+
codexSystemPromptEnabled?: boolean;
|
|
502
|
+
featureFlags?: FeatureFlagValues;
|
|
490
503
|
defaultPermissionMode?: PermissionMode;
|
|
491
504
|
defaultModel?: string;
|
|
492
505
|
defaultEffort?: "low" | "medium" | "high" | "xhigh" | "max";
|
|
@@ -1045,6 +1058,18 @@ declare class ProjectsRepository {
|
|
|
1045
1058
|
upsertProjectByPath(rawPath: string, input?: UpsertProjectInput): Project;
|
|
1046
1059
|
}
|
|
1047
1060
|
|
|
1061
|
+
/**
|
|
1062
|
+
* Token kinds. A device supplies three non-interchangeable types, and
|
|
1063
|
+
* conflating them fails only at send time with no signal at registration:
|
|
1064
|
+
*
|
|
1065
|
+
* - `expo` — Expo relay token, for ordinary push notifications.
|
|
1066
|
+
* - `liveactivity_start` — ActivityKit push-to-start token. App-wide, one per
|
|
1067
|
+
* device, long-lived. Starts an activity when none exists.
|
|
1068
|
+
* - `liveactivity_update` — ActivityKit per-activity update token, issued by
|
|
1069
|
+
* iOS after an activity starts, scoped to that one activity, short-lived.
|
|
1070
|
+
*/
|
|
1071
|
+
declare const PUSH_TOKEN_KINDS: readonly ["expo", "liveactivity_start", "liveactivity_update"];
|
|
1072
|
+
type PushTokenKind = (typeof PUSH_TOKEN_KINDS)[number];
|
|
1048
1073
|
interface PushTokenRow {
|
|
1049
1074
|
token: string;
|
|
1050
1075
|
platform: string;
|
|
@@ -1055,6 +1080,13 @@ interface PushTokenRow {
|
|
|
1055
1080
|
last_failure_code: string | null;
|
|
1056
1081
|
failure_streak: number;
|
|
1057
1082
|
revoked_at: number | null;
|
|
1083
|
+
kind: PushTokenKind;
|
|
1084
|
+
activity_id: string | null;
|
|
1085
|
+
session_id: string | null;
|
|
1086
|
+
expires_at: number | null;
|
|
1087
|
+
stale_date: number | null;
|
|
1088
|
+
started_at: number | null;
|
|
1089
|
+
renewed_at: number | null;
|
|
1058
1090
|
}
|
|
1059
1091
|
/**
|
|
1060
1092
|
* Health as reported to a client. Deliberately omits the token itself — a push
|
|
@@ -1071,10 +1103,16 @@ interface PushTokenHealth {
|
|
|
1071
1103
|
failureStreak: number;
|
|
1072
1104
|
revokedAt: number | null;
|
|
1073
1105
|
/**
|
|
1074
|
-
* Never delivered vs delivering vs failing vs revoked. The
|
|
1075
|
-
* user actually needs: "not yet" and "broken" look identical
|
|
1106
|
+
* Never delivered vs delivering vs failing vs revoked vs expired. The
|
|
1107
|
+
* distinction the user actually needs: "not yet" and "broken" look identical
|
|
1108
|
+
* without it.
|
|
1076
1109
|
*/
|
|
1077
|
-
state: "never-delivered" | "healthy" | "failing" | "dead" | "revoked";
|
|
1110
|
+
state: "never-delivered" | "healthy" | "failing" | "dead" | "revoked" | "expired";
|
|
1111
|
+
kind: PushTokenKind;
|
|
1112
|
+
/** Present only for per-activity Live Activity tokens. */
|
|
1113
|
+
activityId: string | null;
|
|
1114
|
+
sessionId: string | null;
|
|
1115
|
+
expiresAt: number | null;
|
|
1078
1116
|
}
|
|
1079
1117
|
declare class PushRepository {
|
|
1080
1118
|
private upsertStmt;
|
|
@@ -1086,18 +1124,78 @@ declare class PushRepository {
|
|
|
1086
1124
|
private revokeStmt;
|
|
1087
1125
|
private claimEventStmt;
|
|
1088
1126
|
private markDeliveredStmt;
|
|
1127
|
+
private listByKindSessionStmt;
|
|
1128
|
+
private listByKindStmt;
|
|
1129
|
+
private listRenewableStmt;
|
|
1130
|
+
private claimRenewalStmt;
|
|
1131
|
+
private expireStmt;
|
|
1132
|
+
private expireSessionActivitiesStmt;
|
|
1089
1133
|
constructor(db: Database.Database);
|
|
1134
|
+
/**
|
|
1135
|
+
* Register or refresh a token.
|
|
1136
|
+
*
|
|
1137
|
+
* `kind` defaults to Expo so a released client posting `{ token, platform }`
|
|
1138
|
+
* keeps working — tb-mobile cannot be force-updated, and every client
|
|
1139
|
+
* predating Live Activities is registering an Expo relay token.
|
|
1140
|
+
*
|
|
1141
|
+
* Several rows per device is normal and intended: a device runs one activity
|
|
1142
|
+
* per live session, each with its own update token. The token itself is the
|
|
1143
|
+
* primary key, so distinct activities never collide.
|
|
1144
|
+
*/
|
|
1090
1145
|
register(args: {
|
|
1091
1146
|
token: string;
|
|
1092
1147
|
platform: string;
|
|
1093
1148
|
deviceId?: string | null;
|
|
1149
|
+
kind?: PushTokenKind;
|
|
1150
|
+
activityId?: string | null;
|
|
1151
|
+
sessionId?: string | null;
|
|
1152
|
+
expiresAt?: number | null;
|
|
1153
|
+
staleDate?: number | null;
|
|
1154
|
+
startedAt?: number | null;
|
|
1094
1155
|
now?: number;
|
|
1095
1156
|
}): void;
|
|
1096
1157
|
get(token: string): PushTokenRow | null;
|
|
1097
|
-
/**
|
|
1158
|
+
/**
|
|
1159
|
+
* Expo tokens eligible for delivery — not revoked, not past the failure limit.
|
|
1160
|
+
*
|
|
1161
|
+
* Deliberately Expo-only. ActivityKit tokens go over direct APNs with a
|
|
1162
|
+
* different topic and are rejected by Expo's relay, so the ordinary
|
|
1163
|
+
* notification fan-out must not see them.
|
|
1164
|
+
*/
|
|
1098
1165
|
listDeliverable(): PushTokenRow[];
|
|
1166
|
+
/** Live-activity tokens for one session, eligible for delivery. */
|
|
1167
|
+
listForSession(kind: PushTokenKind, sessionId: string, now?: number): PushTokenRow[];
|
|
1168
|
+
/**
|
|
1169
|
+
* Every deliverable token of one kind.
|
|
1170
|
+
*
|
|
1171
|
+
* Used for push-to-start, which is app-wide rather than session-scoped: the
|
|
1172
|
+
* activity does not exist yet, so there is no per-activity token to look up.
|
|
1173
|
+
*/
|
|
1174
|
+
listByKind(kind: PushTokenKind, now?: number): PushTokenRow[];
|
|
1175
|
+
/** Unrenewed activities with a renewal deadline, soonest first. */
|
|
1176
|
+
listRenewable(): PushTokenRow[];
|
|
1177
|
+
/**
|
|
1178
|
+
* Claim a row for renewal.
|
|
1179
|
+
*
|
|
1180
|
+
* Returns true exactly once per row. A restart re-arms timers from the
|
|
1181
|
+
* persisted deadline, so the same renewal can be attempted twice; the loser
|
|
1182
|
+
* gets false and must not send. Doing this as a conditional UPDATE rather
|
|
1183
|
+
* than read-then-write avoids the race where both attempts observe
|
|
1184
|
+
* "not yet renewed".
|
|
1185
|
+
*/
|
|
1186
|
+
claimRenewal(token: string, now?: number): boolean;
|
|
1187
|
+
/** Mark one token expired, so it stops being a delivery target. */
|
|
1188
|
+
expire(token: string, now?: number): void;
|
|
1189
|
+
/**
|
|
1190
|
+
* Expire every live activity for a session.
|
|
1191
|
+
*
|
|
1192
|
+
* Called when the session ends. Without this, a per-activity token outlives
|
|
1193
|
+
* its session and a later renewal sweep would resurrect an activity for a
|
|
1194
|
+
* session that is already gone.
|
|
1195
|
+
*/
|
|
1196
|
+
expireSessionActivities(sessionId: string, now?: number): void;
|
|
1099
1197
|
/** Every token, including dead and revoked ones, for the health report. */
|
|
1100
|
-
listHealth(): PushTokenHealth[];
|
|
1198
|
+
listHealth(now?: number): PushTokenHealth[];
|
|
1101
1199
|
recordSuccess(token: string, now?: number): void;
|
|
1102
1200
|
recordFailure(token: string, code: string, now?: number): void;
|
|
1103
1201
|
revoke(token: string, now?: number): boolean;
|
|
@@ -1288,6 +1386,10 @@ type ApiDeps = {
|
|
|
1288
1386
|
extraArgs: string | null;
|
|
1289
1387
|
persisted: boolean;
|
|
1290
1388
|
};
|
|
1389
|
+
featureFlagsConfig: () => {
|
|
1390
|
+
registry: readonly FeatureFlagDefinition[];
|
|
1391
|
+
values: FeatureFlagValues;
|
|
1392
|
+
};
|
|
1291
1393
|
publicUrl: string | null;
|
|
1292
1394
|
browseRoot: string | null;
|
|
1293
1395
|
browserCors: string | undefined;
|
|
@@ -1495,6 +1597,8 @@ declare class StreamerServer {
|
|
|
1495
1597
|
private sessionInputAttempts;
|
|
1496
1598
|
private ptyGracePeriodMs;
|
|
1497
1599
|
private defaultSystemPrompt;
|
|
1600
|
+
private featureFlags;
|
|
1601
|
+
private codexSystemPromptEnabled;
|
|
1498
1602
|
private defaultPermissionMode;
|
|
1499
1603
|
private defaultModel;
|
|
1500
1604
|
private defaultEffort;
|
|
@@ -1520,6 +1624,9 @@ declare class StreamerServer {
|
|
|
1520
1624
|
private cacheMetadataRepo;
|
|
1521
1625
|
private pushRepo;
|
|
1522
1626
|
private devicesRepo;
|
|
1627
|
+
private apnsClient;
|
|
1628
|
+
private liveActivityNotifier;
|
|
1629
|
+
private liveActivityRenewal;
|
|
1523
1630
|
private discoveryCache;
|
|
1524
1631
|
private cacheDir;
|
|
1525
1632
|
private tailSize;
|
|
@@ -1560,6 +1667,17 @@ declare class StreamerServer {
|
|
|
1560
1667
|
*/
|
|
1561
1668
|
private withReconciledLifecycle;
|
|
1562
1669
|
private addSessionSubscriber;
|
|
1670
|
+
/**
|
|
1671
|
+
* Bring up Live Activity push, if credentials are present (Feature 12).
|
|
1672
|
+
*
|
|
1673
|
+
* APNS_KEY absent is the ordinary case on a dev machine and in CI, so this
|
|
1674
|
+
* logs once at info and leaves the feature off rather than failing: the server
|
|
1675
|
+
* must not refuse to boot over a missing optional push credential.
|
|
1676
|
+
*
|
|
1677
|
+
* The key is read from the environment as PEM contents and never from a path
|
|
1678
|
+
* on disk; neither it nor any device token is ever logged.
|
|
1679
|
+
*/
|
|
1680
|
+
private initLiveActivityPush;
|
|
1563
1681
|
/**
|
|
1564
1682
|
* Classify sessions left behind by previous streamer runs (C1 Phase 3a).
|
|
1565
1683
|
*
|
|
@@ -1643,6 +1761,14 @@ declare class StreamerServer {
|
|
|
1643
1761
|
private handlePairStart;
|
|
1644
1762
|
private handlePairExchange;
|
|
1645
1763
|
private rotateApiKey;
|
|
1764
|
+
/**
|
|
1765
|
+
* The registry ships with the values so a client renders the list from one
|
|
1766
|
+
* round-trip, same as getClaudeFlagsConfig().
|
|
1767
|
+
*
|
|
1768
|
+
* Deliberately no `persisted` field: unlike claude-flags there is no PUT, and
|
|
1769
|
+
* the absence of that field is the signal that this endpoint is read-only.
|
|
1770
|
+
*/
|
|
1771
|
+
private getFeatureFlagsConfig;
|
|
1646
1772
|
private getClaudeFlagsConfig;
|
|
1647
1773
|
/**
|
|
1648
1774
|
* Replace the per-server flag set. Applies to the NEXT spawn — a live PTY
|
package/dist/index.d.ts
CHANGED
|
@@ -102,6 +102,17 @@ interface FlagDefinition {
|
|
|
102
102
|
type ClaudeFlagValue = string | string[] | boolean;
|
|
103
103
|
type ClaudeFlagValues = Record<string, ClaudeFlagValue>;
|
|
104
104
|
|
|
105
|
+
interface FeatureFlagDefinition {
|
|
106
|
+
/** Stable config/wire key. Used in server.yaml, on the CLI, and over HTTP. */
|
|
107
|
+
id: string;
|
|
108
|
+
/** Shipped to clients alongside the values so a UI can render it. */
|
|
109
|
+
description: string;
|
|
110
|
+
default: boolean;
|
|
111
|
+
/** Full env var name. */
|
|
112
|
+
env: string;
|
|
113
|
+
}
|
|
114
|
+
type FeatureFlagValues = Record<string, boolean>;
|
|
115
|
+
|
|
105
116
|
declare const CLAUDE_CODE_PROVIDER: "claude-code";
|
|
106
117
|
declare const CODEX_CLI_PROVIDER: "codex-cli";
|
|
107
118
|
type ProviderName = typeof CLAUDE_CODE_PROVIDER | typeof CODEX_CLI_PROVIDER;
|
|
@@ -487,6 +498,8 @@ interface ServerConfig {
|
|
|
487
498
|
tailSize?: number;
|
|
488
499
|
directoryScanDebounceMs?: number;
|
|
489
500
|
defaultSystemPrompt?: string;
|
|
501
|
+
codexSystemPromptEnabled?: boolean;
|
|
502
|
+
featureFlags?: FeatureFlagValues;
|
|
490
503
|
defaultPermissionMode?: PermissionMode;
|
|
491
504
|
defaultModel?: string;
|
|
492
505
|
defaultEffort?: "low" | "medium" | "high" | "xhigh" | "max";
|
|
@@ -1045,6 +1058,18 @@ declare class ProjectsRepository {
|
|
|
1045
1058
|
upsertProjectByPath(rawPath: string, input?: UpsertProjectInput): Project;
|
|
1046
1059
|
}
|
|
1047
1060
|
|
|
1061
|
+
/**
|
|
1062
|
+
* Token kinds. A device supplies three non-interchangeable types, and
|
|
1063
|
+
* conflating them fails only at send time with no signal at registration:
|
|
1064
|
+
*
|
|
1065
|
+
* - `expo` — Expo relay token, for ordinary push notifications.
|
|
1066
|
+
* - `liveactivity_start` — ActivityKit push-to-start token. App-wide, one per
|
|
1067
|
+
* device, long-lived. Starts an activity when none exists.
|
|
1068
|
+
* - `liveactivity_update` — ActivityKit per-activity update token, issued by
|
|
1069
|
+
* iOS after an activity starts, scoped to that one activity, short-lived.
|
|
1070
|
+
*/
|
|
1071
|
+
declare const PUSH_TOKEN_KINDS: readonly ["expo", "liveactivity_start", "liveactivity_update"];
|
|
1072
|
+
type PushTokenKind = (typeof PUSH_TOKEN_KINDS)[number];
|
|
1048
1073
|
interface PushTokenRow {
|
|
1049
1074
|
token: string;
|
|
1050
1075
|
platform: string;
|
|
@@ -1055,6 +1080,13 @@ interface PushTokenRow {
|
|
|
1055
1080
|
last_failure_code: string | null;
|
|
1056
1081
|
failure_streak: number;
|
|
1057
1082
|
revoked_at: number | null;
|
|
1083
|
+
kind: PushTokenKind;
|
|
1084
|
+
activity_id: string | null;
|
|
1085
|
+
session_id: string | null;
|
|
1086
|
+
expires_at: number | null;
|
|
1087
|
+
stale_date: number | null;
|
|
1088
|
+
started_at: number | null;
|
|
1089
|
+
renewed_at: number | null;
|
|
1058
1090
|
}
|
|
1059
1091
|
/**
|
|
1060
1092
|
* Health as reported to a client. Deliberately omits the token itself — a push
|
|
@@ -1071,10 +1103,16 @@ interface PushTokenHealth {
|
|
|
1071
1103
|
failureStreak: number;
|
|
1072
1104
|
revokedAt: number | null;
|
|
1073
1105
|
/**
|
|
1074
|
-
* Never delivered vs delivering vs failing vs revoked. The
|
|
1075
|
-
* user actually needs: "not yet" and "broken" look identical
|
|
1106
|
+
* Never delivered vs delivering vs failing vs revoked vs expired. The
|
|
1107
|
+
* distinction the user actually needs: "not yet" and "broken" look identical
|
|
1108
|
+
* without it.
|
|
1076
1109
|
*/
|
|
1077
|
-
state: "never-delivered" | "healthy" | "failing" | "dead" | "revoked";
|
|
1110
|
+
state: "never-delivered" | "healthy" | "failing" | "dead" | "revoked" | "expired";
|
|
1111
|
+
kind: PushTokenKind;
|
|
1112
|
+
/** Present only for per-activity Live Activity tokens. */
|
|
1113
|
+
activityId: string | null;
|
|
1114
|
+
sessionId: string | null;
|
|
1115
|
+
expiresAt: number | null;
|
|
1078
1116
|
}
|
|
1079
1117
|
declare class PushRepository {
|
|
1080
1118
|
private upsertStmt;
|
|
@@ -1086,18 +1124,78 @@ declare class PushRepository {
|
|
|
1086
1124
|
private revokeStmt;
|
|
1087
1125
|
private claimEventStmt;
|
|
1088
1126
|
private markDeliveredStmt;
|
|
1127
|
+
private listByKindSessionStmt;
|
|
1128
|
+
private listByKindStmt;
|
|
1129
|
+
private listRenewableStmt;
|
|
1130
|
+
private claimRenewalStmt;
|
|
1131
|
+
private expireStmt;
|
|
1132
|
+
private expireSessionActivitiesStmt;
|
|
1089
1133
|
constructor(db: Database.Database);
|
|
1134
|
+
/**
|
|
1135
|
+
* Register or refresh a token.
|
|
1136
|
+
*
|
|
1137
|
+
* `kind` defaults to Expo so a released client posting `{ token, platform }`
|
|
1138
|
+
* keeps working — tb-mobile cannot be force-updated, and every client
|
|
1139
|
+
* predating Live Activities is registering an Expo relay token.
|
|
1140
|
+
*
|
|
1141
|
+
* Several rows per device is normal and intended: a device runs one activity
|
|
1142
|
+
* per live session, each with its own update token. The token itself is the
|
|
1143
|
+
* primary key, so distinct activities never collide.
|
|
1144
|
+
*/
|
|
1090
1145
|
register(args: {
|
|
1091
1146
|
token: string;
|
|
1092
1147
|
platform: string;
|
|
1093
1148
|
deviceId?: string | null;
|
|
1149
|
+
kind?: PushTokenKind;
|
|
1150
|
+
activityId?: string | null;
|
|
1151
|
+
sessionId?: string | null;
|
|
1152
|
+
expiresAt?: number | null;
|
|
1153
|
+
staleDate?: number | null;
|
|
1154
|
+
startedAt?: number | null;
|
|
1094
1155
|
now?: number;
|
|
1095
1156
|
}): void;
|
|
1096
1157
|
get(token: string): PushTokenRow | null;
|
|
1097
|
-
/**
|
|
1158
|
+
/**
|
|
1159
|
+
* Expo tokens eligible for delivery — not revoked, not past the failure limit.
|
|
1160
|
+
*
|
|
1161
|
+
* Deliberately Expo-only. ActivityKit tokens go over direct APNs with a
|
|
1162
|
+
* different topic and are rejected by Expo's relay, so the ordinary
|
|
1163
|
+
* notification fan-out must not see them.
|
|
1164
|
+
*/
|
|
1098
1165
|
listDeliverable(): PushTokenRow[];
|
|
1166
|
+
/** Live-activity tokens for one session, eligible for delivery. */
|
|
1167
|
+
listForSession(kind: PushTokenKind, sessionId: string, now?: number): PushTokenRow[];
|
|
1168
|
+
/**
|
|
1169
|
+
* Every deliverable token of one kind.
|
|
1170
|
+
*
|
|
1171
|
+
* Used for push-to-start, which is app-wide rather than session-scoped: the
|
|
1172
|
+
* activity does not exist yet, so there is no per-activity token to look up.
|
|
1173
|
+
*/
|
|
1174
|
+
listByKind(kind: PushTokenKind, now?: number): PushTokenRow[];
|
|
1175
|
+
/** Unrenewed activities with a renewal deadline, soonest first. */
|
|
1176
|
+
listRenewable(): PushTokenRow[];
|
|
1177
|
+
/**
|
|
1178
|
+
* Claim a row for renewal.
|
|
1179
|
+
*
|
|
1180
|
+
* Returns true exactly once per row. A restart re-arms timers from the
|
|
1181
|
+
* persisted deadline, so the same renewal can be attempted twice; the loser
|
|
1182
|
+
* gets false and must not send. Doing this as a conditional UPDATE rather
|
|
1183
|
+
* than read-then-write avoids the race where both attempts observe
|
|
1184
|
+
* "not yet renewed".
|
|
1185
|
+
*/
|
|
1186
|
+
claimRenewal(token: string, now?: number): boolean;
|
|
1187
|
+
/** Mark one token expired, so it stops being a delivery target. */
|
|
1188
|
+
expire(token: string, now?: number): void;
|
|
1189
|
+
/**
|
|
1190
|
+
* Expire every live activity for a session.
|
|
1191
|
+
*
|
|
1192
|
+
* Called when the session ends. Without this, a per-activity token outlives
|
|
1193
|
+
* its session and a later renewal sweep would resurrect an activity for a
|
|
1194
|
+
* session that is already gone.
|
|
1195
|
+
*/
|
|
1196
|
+
expireSessionActivities(sessionId: string, now?: number): void;
|
|
1099
1197
|
/** Every token, including dead and revoked ones, for the health report. */
|
|
1100
|
-
listHealth(): PushTokenHealth[];
|
|
1198
|
+
listHealth(now?: number): PushTokenHealth[];
|
|
1101
1199
|
recordSuccess(token: string, now?: number): void;
|
|
1102
1200
|
recordFailure(token: string, code: string, now?: number): void;
|
|
1103
1201
|
revoke(token: string, now?: number): boolean;
|
|
@@ -1288,6 +1386,10 @@ type ApiDeps = {
|
|
|
1288
1386
|
extraArgs: string | null;
|
|
1289
1387
|
persisted: boolean;
|
|
1290
1388
|
};
|
|
1389
|
+
featureFlagsConfig: () => {
|
|
1390
|
+
registry: readonly FeatureFlagDefinition[];
|
|
1391
|
+
values: FeatureFlagValues;
|
|
1392
|
+
};
|
|
1291
1393
|
publicUrl: string | null;
|
|
1292
1394
|
browseRoot: string | null;
|
|
1293
1395
|
browserCors: string | undefined;
|
|
@@ -1495,6 +1597,8 @@ declare class StreamerServer {
|
|
|
1495
1597
|
private sessionInputAttempts;
|
|
1496
1598
|
private ptyGracePeriodMs;
|
|
1497
1599
|
private defaultSystemPrompt;
|
|
1600
|
+
private featureFlags;
|
|
1601
|
+
private codexSystemPromptEnabled;
|
|
1498
1602
|
private defaultPermissionMode;
|
|
1499
1603
|
private defaultModel;
|
|
1500
1604
|
private defaultEffort;
|
|
@@ -1520,6 +1624,9 @@ declare class StreamerServer {
|
|
|
1520
1624
|
private cacheMetadataRepo;
|
|
1521
1625
|
private pushRepo;
|
|
1522
1626
|
private devicesRepo;
|
|
1627
|
+
private apnsClient;
|
|
1628
|
+
private liveActivityNotifier;
|
|
1629
|
+
private liveActivityRenewal;
|
|
1523
1630
|
private discoveryCache;
|
|
1524
1631
|
private cacheDir;
|
|
1525
1632
|
private tailSize;
|
|
@@ -1560,6 +1667,17 @@ declare class StreamerServer {
|
|
|
1560
1667
|
*/
|
|
1561
1668
|
private withReconciledLifecycle;
|
|
1562
1669
|
private addSessionSubscriber;
|
|
1670
|
+
/**
|
|
1671
|
+
* Bring up Live Activity push, if credentials are present (Feature 12).
|
|
1672
|
+
*
|
|
1673
|
+
* APNS_KEY absent is the ordinary case on a dev machine and in CI, so this
|
|
1674
|
+
* logs once at info and leaves the feature off rather than failing: the server
|
|
1675
|
+
* must not refuse to boot over a missing optional push credential.
|
|
1676
|
+
*
|
|
1677
|
+
* The key is read from the environment as PEM contents and never from a path
|
|
1678
|
+
* on disk; neither it nor any device token is ever logged.
|
|
1679
|
+
*/
|
|
1680
|
+
private initLiveActivityPush;
|
|
1563
1681
|
/**
|
|
1564
1682
|
* Classify sessions left behind by previous streamer runs (C1 Phase 3a).
|
|
1565
1683
|
*
|
|
@@ -1643,6 +1761,14 @@ declare class StreamerServer {
|
|
|
1643
1761
|
private handlePairStart;
|
|
1644
1762
|
private handlePairExchange;
|
|
1645
1763
|
private rotateApiKey;
|
|
1764
|
+
/**
|
|
1765
|
+
* The registry ships with the values so a client renders the list from one
|
|
1766
|
+
* round-trip, same as getClaudeFlagsConfig().
|
|
1767
|
+
*
|
|
1768
|
+
* Deliberately no `persisted` field: unlike claude-flags there is no PUT, and
|
|
1769
|
+
* the absence of that field is the signal that this endpoint is read-only.
|
|
1770
|
+
*/
|
|
1771
|
+
private getFeatureFlagsConfig;
|
|
1646
1772
|
private getClaudeFlagsConfig;
|
|
1647
1773
|
/**
|
|
1648
1774
|
* Replace the per-server flag set. Applies to the NEXT spawn — a live PTY
|