Align qualification wait with subscription preflight

This commit is contained in:
rcourtman
2026-07-16 10:01:40 +01:00
parent b84f650e77
commit cdae56df0f
3 changed files with 36 additions and 1 deletions
@@ -278,7 +278,10 @@ minimum request allowance for local subscription turns. Patrol tool-call
preflight owns one route-aware outer deadline: API providers retain the
30-second budget, while local subscription agents receive a bounded two-minute
budget for CLI startup and complete structured-output assembly. A caller's
earlier cancellation still wins. The native provider boundary accepts the
earlier cancellation still wins. Qualification waits through that complete
subscription-agent deadline plus bounded cache-publication grace before it may
classify missing fresh preflight evidence; its shorter API-provider wait must
not truncate a healthy local CLI turn. The native provider boundary accepts the
canonical qualified Pulse model identity from shared callers, strips only its
own subscription-provider prefix before CLI execution, and rejects foreign
provider prefixes rather than forwarding an invalid or cross-provider model
+15
View File
@@ -14,10 +14,13 @@ import (
"sync"
"time"
"github.com/rcourtman/pulse-go-rewrite/internal/ai/providers"
"github.com/rcourtman/pulse-go-rewrite/internal/unifiedresources"
"github.com/rcourtman/pulse-go-rewrite/pkg/aicontracts"
)
const subscriptionAgentPreflightEvidenceGrace = 15 * time.Second
type ClientConfig struct {
BaseURL string
Username string
@@ -122,6 +125,17 @@ func (s AISettings) EffectivePatrolModel() string {
return strings.TrimSpace(s.Model)
}
func patrolModelSuiteAcquisitionTimeout(provider string, requested time.Duration) time.Duration {
if provider != string(providers.SubscriptionAgentCodex) && provider != string(providers.SubscriptionAgentClaude) {
return requested
}
minimum := providers.SubscriptionAgentMinimumRequestTimeout + subscriptionAgentPreflightEvidenceGrace
if requested < minimum {
return minimum
}
return requested
}
type PatrolReadiness struct {
Status string `json:"status"`
Ready bool `json:"ready"`
@@ -368,6 +382,7 @@ func (c *PulseClient) AcquirePatrolModelSuite(ctx context.Context, model string,
if provider == "" || bareModel == "" {
return nil, fmt.Errorf("Patrol qualification requires a concrete provider:model route, got %q", target)
}
timeout = patrolModelSuiteAcquisitionTimeout(provider, timeout)
routeChanged := before.EffectivePatrolModel() != target ||
(provider == "codex-subscription" && !before.CodexSubscriptionEnabled) ||
+17
View File
@@ -234,6 +234,23 @@ func TestAcquirePatrolModelSuitePinsOneRouteAndUsesFreshAsyncPreflight(t *testin
}
}
func TestPatrolModelSuiteAcquisitionTimeoutIsRouteAware(t *testing.T) {
requested := 45 * time.Second
if got := patrolModelSuiteAcquisitionTimeout("openai", requested); got != requested {
t.Fatalf("API route acquisition timeout = %s, want %s", got, requested)
}
wantSubscription := 2*time.Minute + subscriptionAgentPreflightEvidenceGrace
for _, provider := range []string{"codex-subscription", "claude-subscription"} {
if got := patrolModelSuiteAcquisitionTimeout(provider, requested); got != wantSubscription {
t.Fatalf("%s acquisition timeout = %s, want %s", provider, got, wantSubscription)
}
}
longer := 4 * time.Minute
if got := patrolModelSuiteAcquisitionTimeout("claude-subscription", longer); got != longer {
t.Fatalf("long configured acquisition timeout = %s, want %s", got, longer)
}
}
func TestAcquirePatrolModelSuitePreflightsConfiguredRouteOnceWithoutSettingsWrite(t *testing.T) {
updates := 0
preflightPosts := 0