@adhdev/mesh-shared 1.0.82-rc.16 → 1.0.82-rc.18
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/assistant-protocol.d.ts +4 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +63 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +57 -6
- package/dist/index.mjs.map +1 -1
- package/dist/launch-defaults.d.ts +194 -0
- package/dist/mesh-tool-names.d.ts +2 -2
- package/dist/quota-freshness.d.ts +4 -4
- package/package.json +2 -2
- package/src/assistant-protocol.ts +10 -1
- package/src/index.ts +1 -0
- package/src/launch-defaults.ts +168 -0
- package/src/mesh-tool-names.ts +1 -0
- package/src/quota-freshness.ts +15 -7
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/** Daemon-local launch intent and command wire contract. P2P/local only;
|
|
2
|
+
* never include this document or its history in cloud status_report.
|
|
3
|
+
* Publication through mesh-shared's barrel is a later integration step. */
|
|
4
|
+
export declare const LAUNCH_DEFAULT_ROLES: readonly ["assistant", "coordinator"];
|
|
5
|
+
export type LaunchDefaultRole = typeof LAUNCH_DEFAULT_ROLES[number];
|
|
6
|
+
export declare const LAUNCH_DEFAULT_SOURCES: readonly ["user", "stored_default", "project_default", "provider_default"];
|
|
7
|
+
export type LaunchDefaultSource = typeof LAUNCH_DEFAULT_SOURCES[number];
|
|
8
|
+
export declare const LAUNCH_DEFAULTS_NEXT_LAUNCH_NOTE = "Applies to the next launch; running sessions are unchanged.";
|
|
9
|
+
export declare function isLaunchDefaultRole(value: unknown): value is LaunchDefaultRole;
|
|
10
|
+
export declare function isLaunchDefaultSource(value: unknown): value is LaunchDefaultSource;
|
|
11
|
+
export interface LaunchDefaultSelection {
|
|
12
|
+
provider: string;
|
|
13
|
+
/** Omission means pass no model/thinking argument, not inherit another provider. */
|
|
14
|
+
model?: string;
|
|
15
|
+
thinkingLevel?: string;
|
|
16
|
+
}
|
|
17
|
+
export type LaunchDefaultToolRestriction = 'enforced' | 'prompt_only';
|
|
18
|
+
export type LaunchDefaultOrigin = 'owner' | 'human' | 'relay' | 'review' | 'review_tainted';
|
|
19
|
+
export interface LaunchDefaultEntry extends LaunchDefaultSelection {
|
|
20
|
+
revision: number;
|
|
21
|
+
setBy: 'owner' | 'assistant';
|
|
22
|
+
setAt: number;
|
|
23
|
+
}
|
|
24
|
+
export interface LaunchDefaultChange {
|
|
25
|
+
at: number;
|
|
26
|
+
role: LaunchDefaultRole;
|
|
27
|
+
by: 'owner' | 'assistant';
|
|
28
|
+
origin: LaunchDefaultOrigin;
|
|
29
|
+
from: LaunchDefaultEntry | null;
|
|
30
|
+
to: LaunchDefaultEntry | null;
|
|
31
|
+
}
|
|
32
|
+
export interface LaunchDefaultsDocument {
|
|
33
|
+
version: 1;
|
|
34
|
+
/** Global document token, including clears; distinct from entry revisions. */
|
|
35
|
+
revision: number;
|
|
36
|
+
assistant?: LaunchDefaultEntry;
|
|
37
|
+
coordinator?: LaunchDefaultEntry;
|
|
38
|
+
history: LaunchDefaultChange[];
|
|
39
|
+
}
|
|
40
|
+
export interface LaunchDefaultRef {
|
|
41
|
+
role: LaunchDefaultRole;
|
|
42
|
+
scope: 'global' | 'project';
|
|
43
|
+
/** Entry revision for global defaults; host project token for project defaults. */
|
|
44
|
+
revision: number;
|
|
45
|
+
projectId?: string;
|
|
46
|
+
}
|
|
47
|
+
export type LaunchDefaultField = keyof LaunchDefaultSelection;
|
|
48
|
+
export interface LaunchDefaultAxis {
|
|
49
|
+
value: string | null;
|
|
50
|
+
source: LaunchDefaultSource;
|
|
51
|
+
defaultRef?: LaunchDefaultRef;
|
|
52
|
+
}
|
|
53
|
+
export type LaunchDefaultWarning = 'catalog_unverified' | 'manual_mcp_setup_required';
|
|
54
|
+
export type LaunchDefaultValidationReason = 'invalid_schema' | 'provider_unknown' | 'provider_not_cli' | 'provider_disabled' | 'provider_not_detected' | 'provider_not_eligible' | 'model_unsupported' | 'model_provider_mismatch' | 'model_not_offered' | 'thinking_unsupported' | 'thinking_not_offered' | 'catalog_unavailable';
|
|
55
|
+
export type LaunchDefaultResolution = {
|
|
56
|
+
ok: true;
|
|
57
|
+
selection: LaunchDefaultSelection;
|
|
58
|
+
applied: Record<LaunchDefaultField, LaunchDefaultAxis>;
|
|
59
|
+
defaultRef?: LaunchDefaultRef;
|
|
60
|
+
documentRevision: number;
|
|
61
|
+
warnings: LaunchDefaultWarning[];
|
|
62
|
+
toolRestriction: LaunchDefaultToolRestriction;
|
|
63
|
+
} | {
|
|
64
|
+
ok: false;
|
|
65
|
+
code: 'launch_default_required' | 'launch_default_unavailable' | 'launch_selection_invalid';
|
|
66
|
+
role: LaunchDefaultRole;
|
|
67
|
+
field: LaunchDefaultField;
|
|
68
|
+
reason: string;
|
|
69
|
+
source?: LaunchDefaultSource;
|
|
70
|
+
value?: string | null;
|
|
71
|
+
defaultRef?: LaunchDefaultRef;
|
|
72
|
+
candidates?: readonly string[];
|
|
73
|
+
hint: string;
|
|
74
|
+
};
|
|
75
|
+
export interface LaunchDefaultsRoleView {
|
|
76
|
+
stored: LaunchDefaultEntry | null;
|
|
77
|
+
/** The existing daemon resolver's result, including loud failures. */
|
|
78
|
+
effective: LaunchDefaultResolution;
|
|
79
|
+
}
|
|
80
|
+
type Target = {
|
|
81
|
+
role: 'assistant';
|
|
82
|
+
project?: never;
|
|
83
|
+
} | {
|
|
84
|
+
role: 'coordinator';
|
|
85
|
+
project?: string;
|
|
86
|
+
};
|
|
87
|
+
export type LaunchDefaultsReadRequest = ({
|
|
88
|
+
action?: 'get';
|
|
89
|
+
} & (Target | {
|
|
90
|
+
role?: never;
|
|
91
|
+
project?: never;
|
|
92
|
+
})) | ({
|
|
93
|
+
action: 'check';
|
|
94
|
+
} & Target & LaunchDefaultSelection);
|
|
95
|
+
/** Mandatory CAS: global document token, or host project token for project writes.
|
|
96
|
+
* 0 is explicit first setup; clears advance the token and never restore fallback. */
|
|
97
|
+
export type LaunchDefaultsSetRequest = Target & {
|
|
98
|
+
expectedRevision: number;
|
|
99
|
+
} & (({
|
|
100
|
+
action: 'set';
|
|
101
|
+
} & LaunchDefaultSelection) | {
|
|
102
|
+
action: 'clear';
|
|
103
|
+
provider?: never;
|
|
104
|
+
model?: never;
|
|
105
|
+
thinkingLevel?: never;
|
|
106
|
+
});
|
|
107
|
+
/** Existing assistant routing envelope; session identity never supplies origin. */
|
|
108
|
+
export type AssistantLaunchDefaultsReadRequest = LaunchDefaultsReadRequest & {
|
|
109
|
+
assistantSessionId?: string;
|
|
110
|
+
};
|
|
111
|
+
export type AssistantLaunchDefaultsSetRequest = LaunchDefaultsSetRequest & {
|
|
112
|
+
assistantSessionId?: string;
|
|
113
|
+
};
|
|
114
|
+
export declare const LAUNCH_DEFAULT_ERROR_CODES: readonly ["invalid_args", "launch_default_required", "launch_default_unavailable", "launch_selection_invalid", "launch_default_invalid", "revision_conflict", "store_unavailable", "store_busy", "persistence_failed", "project_not_found", "project_ambiguous", "project_not_hosted", "project_storage_unavailable", "staging_unavailable", "staging_failed", "review_turn_tool_denied"];
|
|
115
|
+
export type LaunchDefaultsErrorCode = typeof LAUNCH_DEFAULT_ERROR_CODES[number];
|
|
116
|
+
export interface LaunchDefaultsError {
|
|
117
|
+
success: false;
|
|
118
|
+
code: LaunchDefaultsErrorCode;
|
|
119
|
+
error: string;
|
|
120
|
+
reason?: string;
|
|
121
|
+
role?: LaunchDefaultRole;
|
|
122
|
+
field?: LaunchDefaultField;
|
|
123
|
+
source?: LaunchDefaultSource;
|
|
124
|
+
value?: string | null;
|
|
125
|
+
defaultRef?: LaunchDefaultRef;
|
|
126
|
+
candidates?: readonly string[];
|
|
127
|
+
actualRevision?: number;
|
|
128
|
+
/** 0 for an absent global document; absent when it cannot be read. */
|
|
129
|
+
documentRevision?: number;
|
|
130
|
+
/** A persistence failure can replace intent without confirming durability.
|
|
131
|
+
* Re-read before retrying; never report applied on committed:true alone. */
|
|
132
|
+
committed?: boolean;
|
|
133
|
+
}
|
|
134
|
+
export interface LaunchDefaultsReadSuccess {
|
|
135
|
+
success: true;
|
|
136
|
+
result: 'get';
|
|
137
|
+
documentRevision: number;
|
|
138
|
+
roles: Partial<Record<LaunchDefaultRole, LaunchDefaultsRoleView>>;
|
|
139
|
+
project?: {
|
|
140
|
+
projectId: string;
|
|
141
|
+
revision: number;
|
|
142
|
+
entry: LaunchDefaultEntry | null;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export interface LaunchDefaultsCheckSuccess {
|
|
146
|
+
success: true;
|
|
147
|
+
result: 'check';
|
|
148
|
+
role: LaunchDefaultRole;
|
|
149
|
+
selection: LaunchDefaultSelection;
|
|
150
|
+
warnings: LaunchDefaultWarning[];
|
|
151
|
+
toolRestriction: LaunchDefaultToolRestriction;
|
|
152
|
+
lowersToolLock: boolean;
|
|
153
|
+
}
|
|
154
|
+
export interface LaunchDefaultsApplied {
|
|
155
|
+
success: true;
|
|
156
|
+
result: 'applied';
|
|
157
|
+
role: LaunchDefaultRole;
|
|
158
|
+
scope: 'global' | 'project';
|
|
159
|
+
projectId?: string;
|
|
160
|
+
entry: LaunchDefaultEntry | null;
|
|
161
|
+
previous: LaunchDefaultEntry | null;
|
|
162
|
+
/** CAS token returned by the authority that performed the write. */
|
|
163
|
+
revision: number;
|
|
164
|
+
warnings: LaunchDefaultWarning[];
|
|
165
|
+
durable: true;
|
|
166
|
+
note: string;
|
|
167
|
+
}
|
|
168
|
+
export interface LaunchDefaultsStaged {
|
|
169
|
+
success: true;
|
|
170
|
+
result: 'staged';
|
|
171
|
+
role: LaunchDefaultRole;
|
|
172
|
+
stagedId: string;
|
|
173
|
+
previous: LaunchDefaultEntry | null;
|
|
174
|
+
selection: LaunchDefaultSelection | null;
|
|
175
|
+
expectedRevision: number;
|
|
176
|
+
warnings: LaunchDefaultWarning[];
|
|
177
|
+
note: string;
|
|
178
|
+
}
|
|
179
|
+
/** Existing owner Inbox adapter stores this proposal; it is not another default.
|
|
180
|
+
* Applying it must revalidate on the host and CAS via the same set handler. */
|
|
181
|
+
export interface LaunchDefaultsProposal {
|
|
182
|
+
kind: 'launch_defaults';
|
|
183
|
+
role: LaunchDefaultRole;
|
|
184
|
+
project?: string;
|
|
185
|
+
selection: LaunchDefaultSelection | null;
|
|
186
|
+
previous: LaunchDefaultEntry | null;
|
|
187
|
+
expectedRevision: number;
|
|
188
|
+
origin: LaunchDefaultOrigin;
|
|
189
|
+
callerSessionId?: string;
|
|
190
|
+
}
|
|
191
|
+
export type LaunchDefaultsReadResponse = LaunchDefaultsReadSuccess | LaunchDefaultsCheckSuccess | LaunchDefaultsError;
|
|
192
|
+
export type LaunchDefaultsSetResponse = LaunchDefaultsApplied | LaunchDefaultsStaged | LaunchDefaultsError;
|
|
193
|
+
export type LaunchDefaultsResponse = LaunchDefaultsReadResponse | LaunchDefaultsSetResponse;
|
|
194
|
+
export {};
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
* Order mirrors mcp-server `ALL_MESH_TOOLS` for easy visual diffing, but the consistency
|
|
19
19
|
* checks are set-based (order-insensitive).
|
|
20
20
|
*/
|
|
21
|
-
export declare const CANONICAL_MESH_TOOL_NAMES: readonly ["mesh_status", "mesh_route_preview", "mesh_list_nodes", "mesh_enqueue_batch", "mesh_enqueue_task", "mesh_view_queue", "mesh_queue_cancel", "mesh_queue_requeue", "mesh_send_task", "mesh_read_chat", "mesh_read_debug", "mesh_read_terminal", "mesh_send_keys", "mesh_launch_session", "mesh_git_status", "mesh_read_node_logs", "mesh_fast_forward_node", "mesh_restart_daemon", "mesh_checkpoint", "mesh_approve", "mesh_answer_question", "mesh_list_pending_approvals", "mesh_create", "mesh_add_node", "mesh_clone_node", "mesh_remove_node", "mesh_cleanup_worktree_nodes", "mesh_refine_node", "mesh_refine_batch", "mesh_config", "mesh_init", "mesh_cleanup_sessions", "mesh_task_history", "mesh_ledger_query", "mesh_note", "mesh_reconcile_ledger", "mesh_mission_upsert", "mesh_mission_list", "mesh_review_inbox", "mesh_node_slots"];
|
|
21
|
+
export declare const CANONICAL_MESH_TOOL_NAMES: readonly ["mesh_status", "mesh_route_preview", "mesh_list_nodes", "mesh_enqueue_batch", "mesh_enqueue_task", "mesh_view_queue", "mesh_queue_cancel", "mesh_queue_requeue", "mesh_send_task", "mesh_read_chat", "mesh_read_debug", "mesh_read_terminal", "mesh_send_keys", "mesh_launch_session", "mesh_git_status", "mesh_read_node_logs", "mesh_fast_forward_node", "mesh_restart_daemon", "mesh_checkpoint", "mesh_approve", "mesh_answer_question", "mesh_list_pending_approvals", "mesh_create", "mesh_add_node", "mesh_attach_remote", "mesh_clone_node", "mesh_remove_node", "mesh_cleanup_worktree_nodes", "mesh_refine_node", "mesh_refine_batch", "mesh_config", "mesh_init", "mesh_cleanup_sessions", "mesh_task_history", "mesh_ledger_query", "mesh_note", "mesh_reconcile_ledger", "mesh_mission_upsert", "mesh_mission_list", "mesh_review_inbox", "mesh_node_slots"];
|
|
22
22
|
export type CanonicalMeshToolName = typeof CANONICAL_MESH_TOOL_NAMES[number];
|
|
23
23
|
/** The count the `NN tools` barrel doc comments and consistency test assert against. */
|
|
24
|
-
export declare const CANONICAL_MESH_TOOL_COUNT:
|
|
24
|
+
export declare const CANONICAL_MESH_TOOL_COUNT: 41;
|
|
25
25
|
/**
|
|
26
26
|
* Tool names retired by the 2026-09-26 tool-surface consolidation (60 → 48).
|
|
27
27
|
* Every capability behind them is still reachable: each retired name maps to the
|
|
@@ -17,7 +17,7 @@ export interface QuotaFreshness {
|
|
|
17
17
|
cue?: QuotaFreshnessCue;
|
|
18
18
|
/**
|
|
19
19
|
* Only the USER can produce a new reading (aged-out Claude statusline;
|
|
20
|
-
*
|
|
20
|
+
* expired CLI access token — the daemon never redeems it). The surface
|
|
21
21
|
* should say what to run, not promise a self-heal.
|
|
22
22
|
*/
|
|
23
23
|
userMustAct: boolean;
|
|
@@ -49,9 +49,9 @@ export declare const QUOTA_BACKFILL_HORIZON_MS: number;
|
|
|
49
49
|
* a session must run). Codex's `no-data` is the daemon re-reading the
|
|
50
50
|
* rollout files itself (≈60s while a CLI is active, ≤60 min idle), so it
|
|
51
51
|
* is `stale` WITHOUT userMustAct;
|
|
52
|
-
* ·
|
|
53
|
-
*
|
|
54
|
-
*
|
|
52
|
+
* · `expired-token` on Grok/Kimi/antigravity — only the owning CLI
|
|
53
|
+
* renews it on use. An idle CLI has no background renewal cadence.
|
|
54
|
+
* A scheduled quota retry does not itself renew credentials.
|
|
55
55
|
* - `refreshing` — retained numbers after a transient failure with a retry
|
|
56
56
|
* actually pending. ★Honest about the end of the retry budget: once the
|
|
57
57
|
* daemon has stopped retrying (`metadata.retryExhausted`, or `retryAtMs`
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/mesh-shared",
|
|
3
|
-
"version": "1.0.82-rc.
|
|
4
|
-
"description": "ADHDev mesh-shared
|
|
3
|
+
"version": "1.0.82-rc.18",
|
|
4
|
+
"description": "ADHDev mesh-shared — pure mesh/git status normalizers shared by daemon-core and web-core",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -25,11 +25,14 @@ export const ASSISTANT_TOOLS = [
|
|
|
25
25
|
'project_send',
|
|
26
26
|
'project_read',
|
|
27
27
|
'project_add',
|
|
28
|
+
'project_attach_remote',
|
|
28
29
|
'discover_repos',
|
|
29
30
|
'memory',
|
|
30
31
|
'skill_view',
|
|
31
32
|
'skill_manage',
|
|
32
33
|
'project_note',
|
|
34
|
+
'launch_defaults',
|
|
35
|
+
'launch_defaults_set',
|
|
33
36
|
] as const
|
|
34
37
|
|
|
35
38
|
export type AssistantTool = typeof ASSISTANT_TOOLS[number]
|
|
@@ -53,11 +56,14 @@ export const ASSISTANT_VERB = {
|
|
|
53
56
|
projectSend: 'assistant_project_send',
|
|
54
57
|
projectRead: 'assistant_project_read',
|
|
55
58
|
projectAdd: 'assistant_project_add',
|
|
59
|
+
projectAttachRemote: 'assistant_project_attach_remote',
|
|
56
60
|
discoverRepos: 'assistant_discover_repos',
|
|
57
61
|
memory: 'assistant_memory',
|
|
58
62
|
skillView: 'assistant_skill_view',
|
|
59
63
|
skillManage: 'assistant_skill_manage',
|
|
60
64
|
projectNote: 'assistant_project_note',
|
|
65
|
+
launchDefaults: 'assistant_launch_defaults',
|
|
66
|
+
launchDefaultsSet: 'assistant_launch_defaults_set',
|
|
61
67
|
// assistant-side daemon verbs without a tool of the same name
|
|
62
68
|
launch: 'launch_assistant',
|
|
63
69
|
pendingRelays: 'assistant_pending_relays',
|
|
@@ -79,11 +85,14 @@ export const ASSISTANT_TOOL_VERBS: Readonly<Record<AssistantTool, AssistantVerb>
|
|
|
79
85
|
project_send: ASSISTANT_VERB.projectSend,
|
|
80
86
|
project_read: ASSISTANT_VERB.projectRead,
|
|
81
87
|
project_add: ASSISTANT_VERB.projectAdd,
|
|
88
|
+
project_attach_remote: ASSISTANT_VERB.projectAttachRemote,
|
|
82
89
|
discover_repos: ASSISTANT_VERB.discoverRepos,
|
|
83
90
|
memory: ASSISTANT_VERB.memory,
|
|
84
91
|
skill_view: ASSISTANT_VERB.skillView,
|
|
85
92
|
skill_manage: ASSISTANT_VERB.skillManage,
|
|
86
93
|
project_note: ASSISTANT_VERB.projectNote,
|
|
94
|
+
launch_defaults: ASSISTANT_VERB.launchDefaults,
|
|
95
|
+
launch_defaults_set: ASSISTANT_VERB.launchDefaultsSet,
|
|
87
96
|
}
|
|
88
97
|
|
|
89
98
|
/**
|
|
@@ -92,7 +101,7 @@ export const ASSISTANT_TOOL_VERBS: Readonly<Record<AssistantTool, AssistantVerb>
|
|
|
92
101
|
* because they cause effects (a coordinator message or launch, a new
|
|
93
102
|
* project), and MCP clients use readOnlyHint to skip confirmation.
|
|
94
103
|
*/
|
|
95
|
-
export const ASSISTANT_WRITE_TOOLS: readonly AssistantTool[] = ['project_watch', 'assistant_action', 'memory', 'skill_manage', 'project_note', 'project_send', 'project_add']
|
|
104
|
+
export const ASSISTANT_WRITE_TOOLS: readonly AssistantTool[] = ['project_watch', 'assistant_action', 'memory', 'skill_manage', 'project_note', 'project_send', 'project_add', 'project_attach_remote', 'launch_defaults_set']
|
|
96
105
|
|
|
97
106
|
/** Owner-only verbs: never reachable from the assistant's MCP server (no `ipc`). */
|
|
98
107
|
export const ASSISTANT_OWNER_VERBS: readonly AssistantVerb[] = [
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/** Daemon-local launch intent and command wire contract. P2P/local only;
|
|
2
|
+
* never include this document or its history in cloud status_report.
|
|
3
|
+
* Publication through mesh-shared's barrel is a later integration step. */
|
|
4
|
+
export const LAUNCH_DEFAULT_ROLES = ['assistant', 'coordinator'] as const;
|
|
5
|
+
export type LaunchDefaultRole = typeof LAUNCH_DEFAULT_ROLES[number];
|
|
6
|
+
export const LAUNCH_DEFAULT_SOURCES = ['user', 'stored_default', 'project_default', 'provider_default'] as const;
|
|
7
|
+
export type LaunchDefaultSource = typeof LAUNCH_DEFAULT_SOURCES[number];
|
|
8
|
+
export const LAUNCH_DEFAULTS_NEXT_LAUNCH_NOTE = 'Applies to the next launch; running sessions are unchanged.';
|
|
9
|
+
export function isLaunchDefaultRole(value: unknown): value is LaunchDefaultRole {
|
|
10
|
+
return typeof value === 'string' && (LAUNCH_DEFAULT_ROLES as readonly string[]).includes(value);
|
|
11
|
+
}
|
|
12
|
+
export function isLaunchDefaultSource(value: unknown): value is LaunchDefaultSource {
|
|
13
|
+
return typeof value === 'string' && (LAUNCH_DEFAULT_SOURCES as readonly string[]).includes(value);
|
|
14
|
+
}
|
|
15
|
+
export interface LaunchDefaultSelection {
|
|
16
|
+
provider: string;
|
|
17
|
+
/** Omission means pass no model/thinking argument, not inherit another provider. */
|
|
18
|
+
model?: string;
|
|
19
|
+
thinkingLevel?: string;
|
|
20
|
+
}
|
|
21
|
+
export type LaunchDefaultToolRestriction = 'enforced' | 'prompt_only';
|
|
22
|
+
export type LaunchDefaultOrigin = 'owner' | 'human' | 'relay' | 'review' | 'review_tainted';
|
|
23
|
+
export interface LaunchDefaultEntry extends LaunchDefaultSelection {
|
|
24
|
+
revision: number;
|
|
25
|
+
setBy: 'owner' | 'assistant';
|
|
26
|
+
setAt: number;
|
|
27
|
+
}
|
|
28
|
+
export interface LaunchDefaultChange {
|
|
29
|
+
at: number;
|
|
30
|
+
role: LaunchDefaultRole;
|
|
31
|
+
by: 'owner' | 'assistant';
|
|
32
|
+
origin: LaunchDefaultOrigin;
|
|
33
|
+
from: LaunchDefaultEntry | null;
|
|
34
|
+
to: LaunchDefaultEntry | null;
|
|
35
|
+
}
|
|
36
|
+
export interface LaunchDefaultsDocument {
|
|
37
|
+
version: 1;
|
|
38
|
+
/** Global document token, including clears; distinct from entry revisions. */
|
|
39
|
+
revision: number;
|
|
40
|
+
assistant?: LaunchDefaultEntry;
|
|
41
|
+
coordinator?: LaunchDefaultEntry;
|
|
42
|
+
history: LaunchDefaultChange[];
|
|
43
|
+
}
|
|
44
|
+
export interface LaunchDefaultRef {
|
|
45
|
+
role: LaunchDefaultRole;
|
|
46
|
+
scope: 'global' | 'project';
|
|
47
|
+
/** Entry revision for global defaults; host project token for project defaults. */
|
|
48
|
+
revision: number;
|
|
49
|
+
projectId?: string;
|
|
50
|
+
}
|
|
51
|
+
export type LaunchDefaultField = keyof LaunchDefaultSelection;
|
|
52
|
+
export interface LaunchDefaultAxis {
|
|
53
|
+
value: string | null;
|
|
54
|
+
source: LaunchDefaultSource;
|
|
55
|
+
defaultRef?: LaunchDefaultRef;
|
|
56
|
+
}
|
|
57
|
+
export type LaunchDefaultWarning = 'catalog_unverified' | 'manual_mcp_setup_required';
|
|
58
|
+
export type LaunchDefaultValidationReason =
|
|
59
|
+
| 'invalid_schema' | 'provider_unknown' | 'provider_not_cli' | 'provider_disabled'
|
|
60
|
+
| 'provider_not_detected' | 'provider_not_eligible' | 'model_unsupported'
|
|
61
|
+
| 'model_provider_mismatch' | 'model_not_offered' | 'thinking_unsupported'
|
|
62
|
+
| 'thinking_not_offered' | 'catalog_unavailable';
|
|
63
|
+
export type LaunchDefaultResolution =
|
|
64
|
+
| { ok: true; selection: LaunchDefaultSelection; applied: Record<LaunchDefaultField, LaunchDefaultAxis>;
|
|
65
|
+
defaultRef?: LaunchDefaultRef; documentRevision: number; warnings: LaunchDefaultWarning[];
|
|
66
|
+
toolRestriction: LaunchDefaultToolRestriction }
|
|
67
|
+
| { ok: false; code: 'launch_default_required' | 'launch_default_unavailable' | 'launch_selection_invalid';
|
|
68
|
+
role: LaunchDefaultRole; field: LaunchDefaultField; reason: string; source?: LaunchDefaultSource;
|
|
69
|
+
value?: string | null; defaultRef?: LaunchDefaultRef; candidates?: readonly string[]; hint: string };
|
|
70
|
+
export interface LaunchDefaultsRoleView {
|
|
71
|
+
stored: LaunchDefaultEntry | null;
|
|
72
|
+
/** The existing daemon resolver's result, including loud failures. */
|
|
73
|
+
effective: LaunchDefaultResolution;
|
|
74
|
+
}
|
|
75
|
+
type Target = { role: 'assistant'; project?: never } | { role: 'coordinator'; project?: string };
|
|
76
|
+
export type LaunchDefaultsReadRequest =
|
|
77
|
+
| ({ action?: 'get' } & (Target | { role?: never; project?: never }))
|
|
78
|
+
| ({ action: 'check' } & Target & LaunchDefaultSelection);
|
|
79
|
+
/** Mandatory CAS: global document token, or host project token for project writes.
|
|
80
|
+
* 0 is explicit first setup; clears advance the token and never restore fallback. */
|
|
81
|
+
export type LaunchDefaultsSetRequest = Target & { expectedRevision: number } & (
|
|
82
|
+
| ({ action: 'set' } & LaunchDefaultSelection)
|
|
83
|
+
| { action: 'clear'; provider?: never; model?: never; thinkingLevel?: never }
|
|
84
|
+
);
|
|
85
|
+
/** Existing assistant routing envelope; session identity never supplies origin. */
|
|
86
|
+
export type AssistantLaunchDefaultsReadRequest = LaunchDefaultsReadRequest & { assistantSessionId?: string };
|
|
87
|
+
export type AssistantLaunchDefaultsSetRequest = LaunchDefaultsSetRequest & { assistantSessionId?: string };
|
|
88
|
+
export const LAUNCH_DEFAULT_ERROR_CODES = [
|
|
89
|
+
'invalid_args', 'launch_default_required', 'launch_default_unavailable', 'launch_selection_invalid',
|
|
90
|
+
'launch_default_invalid', 'revision_conflict', 'store_unavailable', 'store_busy', 'persistence_failed',
|
|
91
|
+
'project_not_found', 'project_ambiguous', 'project_not_hosted', 'project_storage_unavailable',
|
|
92
|
+
'staging_unavailable', 'staging_failed', 'review_turn_tool_denied',
|
|
93
|
+
] as const;
|
|
94
|
+
export type LaunchDefaultsErrorCode = typeof LAUNCH_DEFAULT_ERROR_CODES[number];
|
|
95
|
+
export interface LaunchDefaultsError {
|
|
96
|
+
success: false;
|
|
97
|
+
code: LaunchDefaultsErrorCode;
|
|
98
|
+
error: string;
|
|
99
|
+
reason?: string;
|
|
100
|
+
role?: LaunchDefaultRole;
|
|
101
|
+
field?: LaunchDefaultField;
|
|
102
|
+
source?: LaunchDefaultSource;
|
|
103
|
+
value?: string | null;
|
|
104
|
+
defaultRef?: LaunchDefaultRef;
|
|
105
|
+
candidates?: readonly string[];
|
|
106
|
+
actualRevision?: number;
|
|
107
|
+
/** 0 for an absent global document; absent when it cannot be read. */
|
|
108
|
+
documentRevision?: number;
|
|
109
|
+
/** A persistence failure can replace intent without confirming durability.
|
|
110
|
+
* Re-read before retrying; never report applied on committed:true alone. */
|
|
111
|
+
committed?: boolean;
|
|
112
|
+
}
|
|
113
|
+
export interface LaunchDefaultsReadSuccess {
|
|
114
|
+
success: true;
|
|
115
|
+
result: 'get';
|
|
116
|
+
documentRevision: number;
|
|
117
|
+
roles: Partial<Record<LaunchDefaultRole, LaunchDefaultsRoleView>>;
|
|
118
|
+
project?: { projectId: string; revision: number; entry: LaunchDefaultEntry | null };
|
|
119
|
+
}
|
|
120
|
+
export interface LaunchDefaultsCheckSuccess {
|
|
121
|
+
success: true;
|
|
122
|
+
result: 'check';
|
|
123
|
+
role: LaunchDefaultRole;
|
|
124
|
+
selection: LaunchDefaultSelection;
|
|
125
|
+
warnings: LaunchDefaultWarning[];
|
|
126
|
+
toolRestriction: LaunchDefaultToolRestriction;
|
|
127
|
+
lowersToolLock: boolean;
|
|
128
|
+
}
|
|
129
|
+
export interface LaunchDefaultsApplied {
|
|
130
|
+
success: true;
|
|
131
|
+
result: 'applied';
|
|
132
|
+
role: LaunchDefaultRole;
|
|
133
|
+
scope: 'global' | 'project';
|
|
134
|
+
projectId?: string;
|
|
135
|
+
entry: LaunchDefaultEntry | null;
|
|
136
|
+
previous: LaunchDefaultEntry | null;
|
|
137
|
+
/** CAS token returned by the authority that performed the write. */
|
|
138
|
+
revision: number;
|
|
139
|
+
warnings: LaunchDefaultWarning[];
|
|
140
|
+
durable: true;
|
|
141
|
+
note: string;
|
|
142
|
+
}
|
|
143
|
+
export interface LaunchDefaultsStaged {
|
|
144
|
+
success: true;
|
|
145
|
+
result: 'staged';
|
|
146
|
+
role: LaunchDefaultRole;
|
|
147
|
+
stagedId: string;
|
|
148
|
+
previous: LaunchDefaultEntry | null;
|
|
149
|
+
selection: LaunchDefaultSelection | null;
|
|
150
|
+
expectedRevision: number;
|
|
151
|
+
warnings: LaunchDefaultWarning[];
|
|
152
|
+
note: string;
|
|
153
|
+
}
|
|
154
|
+
/** Existing owner Inbox adapter stores this proposal; it is not another default.
|
|
155
|
+
* Applying it must revalidate on the host and CAS via the same set handler. */
|
|
156
|
+
export interface LaunchDefaultsProposal {
|
|
157
|
+
kind: 'launch_defaults';
|
|
158
|
+
role: LaunchDefaultRole;
|
|
159
|
+
project?: string;
|
|
160
|
+
selection: LaunchDefaultSelection | null;
|
|
161
|
+
previous: LaunchDefaultEntry | null;
|
|
162
|
+
expectedRevision: number;
|
|
163
|
+
origin: LaunchDefaultOrigin;
|
|
164
|
+
callerSessionId?: string;
|
|
165
|
+
}
|
|
166
|
+
export type LaunchDefaultsReadResponse = LaunchDefaultsReadSuccess | LaunchDefaultsCheckSuccess | LaunchDefaultsError;
|
|
167
|
+
export type LaunchDefaultsSetResponse = LaunchDefaultsApplied | LaunchDefaultsStaged | LaunchDefaultsError;
|
|
168
|
+
export type LaunchDefaultsResponse = LaunchDefaultsReadResponse | LaunchDefaultsSetResponse;
|
package/src/mesh-tool-names.ts
CHANGED
package/src/quota-freshness.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface QuotaFreshness {
|
|
|
19
19
|
cue?: QuotaFreshnessCue
|
|
20
20
|
/**
|
|
21
21
|
* Only the USER can produce a new reading (aged-out Claude statusline;
|
|
22
|
-
*
|
|
22
|
+
* expired CLI access token — the daemon never redeems it). The surface
|
|
23
23
|
* should say what to run, not promise a self-heal.
|
|
24
24
|
*/
|
|
25
25
|
userMustAct: boolean
|
|
@@ -88,9 +88,9 @@ function backfillCheckAt(quota: MeshNodeFactsProviderQuota, now: number): number
|
|
|
88
88
|
* a session must run). Codex's `no-data` is the daemon re-reading the
|
|
89
89
|
* rollout files itself (≈60s while a CLI is active, ≤60 min idle), so it
|
|
90
90
|
* is `stale` WITHOUT userMustAct;
|
|
91
|
-
* ·
|
|
92
|
-
*
|
|
93
|
-
*
|
|
91
|
+
* · `expired-token` on Grok/Kimi/antigravity — only the owning CLI
|
|
92
|
+
* renews it on use. An idle CLI has no background renewal cadence.
|
|
93
|
+
* A scheduled quota retry does not itself renew credentials.
|
|
94
94
|
* - `refreshing` — retained numbers after a transient failure with a retry
|
|
95
95
|
* actually pending. ★Honest about the end of the retry budget: once the
|
|
96
96
|
* daemon has stopped retrying (`metadata.retryExhausted`, or `retryAtMs`
|
|
@@ -103,12 +103,20 @@ export function assessQuotaFreshness(quota: MeshNodeFactsProviderQuota, now: num
|
|
|
103
103
|
const meta = quota.metadata
|
|
104
104
|
const kind = meta?.failureKind
|
|
105
105
|
const userMustAct = (kind === 'no-data' && quota.provider !== 'codex-cli')
|
|
106
|
-
|| (kind === 'expired-token' &&
|
|
106
|
+
|| (kind === 'expired-token' && ['grok-cli', 'kimi', 'antigravity-cli'].includes(quota.provider))
|
|
107
107
|
// Order matters: the aged-out Claude shape and the retained antigravity
|
|
108
108
|
// shape both ALSO mark lastGoodWindows (mesh routing trusts retained numbers
|
|
109
109
|
// until their reset), so they must be classified before the generic branch.
|
|
110
|
-
if (userMustAct
|
|
111
|
-
if (meta?.lastGoodWindows !== true)
|
|
110
|
+
if (userMustAct) return hasReading(quota) ? { cue: 'stale', userMustAct: true } : { userMustAct: true }
|
|
111
|
+
if (meta?.lastGoodWindows !== true) {
|
|
112
|
+
// A successful fetch is not a perpetual live reading. Use the DATA
|
|
113
|
+
// clock; a recent failed attempt must never rejuvenate old numbers.
|
|
114
|
+
const measuredAt = finiteMs(quota.updatedAt)
|
|
115
|
+
if (hasReading(quota) && (measuredAt === undefined || now - measuredAt >= QUOTA_BACKFILL_HORIZON_MS)) {
|
|
116
|
+
return { cue: 'stale', userMustAct }
|
|
117
|
+
}
|
|
118
|
+
return { userMustAct }
|
|
119
|
+
}
|
|
112
120
|
|
|
113
121
|
const retryAtMs = finiteMs(meta?.retryAtMs)
|
|
114
122
|
const retryStopped = meta?.retryExhausted === true
|