Skip to content

Fix dinner chat NyxID workflow binding - #3584

Open
louis4li wants to merge 1 commit into
feature/integratefrom
fix/2026-09-04_dinner-chat-nyxid-binding
Open

Fix dinner chat NyxID workflow binding#3584
louis4li wants to merge 1 commit into
feature/integratefrom
fix/2026-09-04_dinner-chat-nyxid-binding

Conversation

@louis4li

@louis4li louis4li commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Allow endpoint-only read connected service selectors so custom NyxID OpenAPI reads like readDiningProfileContext can be exposed by committed agent profiles.
  • Align the dinner then-call workflow and local host config so /api/chat can read dining context, start dinner_date, and show the three-option choice gate before calls.
  • Add regression coverage for selector validation, profile bootstrap, workflow ensure behavior, invocation tool payloads, and then-call workflow fixture behavior.

Test plan

  • Verified local host direct /api/status on http://127.0.0.1:5107 returned overall=ok.
  • Verified NyxID proxy /api/status through aevatar-local-diag-catalog returned overall=ok.
  • Verified NyxID proxy authenticated context /api/workflow/observatory/me returned scope ee363bd4-33e1-4123-a789-17e9b8b8ca71.
  • Verified /api/chat through NyxID proxy for Plan a dinner date with Priya this week. called user-context-mock, started dinner_date, and reached waiting_for_signal with three restaurant options.
  • Full dotnet test aevatar.slnx --nologo not run in this session.

🤖 Generated with Claude Code

Allow endpoint-only read selectors and align the dinner workflow/runtime config so profiled /api/chat can read NyxID dining context and start the then-call workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@louis4li
louis4li requested a review from jason-aelf as a code owner September 4, 2026 12:13
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-04T12:20:48.843258Z 56484f9 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 56484f94bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +21 to +23
"AdditionalRequiredServiceSlugs": [
"user-context-mock"
],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep optional dining context out of required OAuth resources

Adding user-context-mock here makes it a global OAuth authorization floor, not an optional profile-context source: NyxIdRemoteCapabilityBroker includes every AdditionalRequiredServiceSlugs entry in RequiredResourceUris() and rejects token issuance when FindMissingRequiredResourcesAsync cannot find it. Consequently, existing users—or users making ordinary chat requests—who have not connected this mock service will hit required_service_access_missing, even though the profile instructions describe dining context as “any available” context. Leave this service optional and let the endpoint-only selector discover it when present.

Useful? React with 👍 / 👎.

"BackendConsole": {
"OidcAuthority": "https://nyx-api.chrono-ai.fun",
"OidcClientId": "a6ff2946-f02f-4c35-8203-1ec46132b660",
"OidcClientId": "8c76ced6-8f5a-4564-bea9-e3d98807f8ba",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep the provisioned console client invariant synchronized

This change deterministically breaks MainnetBootScriptTests.AppSettings_ShouldUseProvisionedConsoleOAuthClient, which reads this exact setting and asserts that it is a6ff2946-f02f-4c35-8203-1ec46132b660. If this is a newly provisioned client, update the pinned invariant and its provisioning evidence in the same change; otherwise restore the provisioned ID. As committed, the full test suite cannot pass.

AGENTS.md reference: AGENTS.md:L14-L14

Useful? React with 👍 / 👎.

"DefaultIntervalSeconds": 60,
"DefaultTimeoutMs": 5000,
"SelfBaseUrl": "http://localhost:5080",
"SelfBaseUrl": "http://127.0.0.1:5107",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep status and Studio defaults on the actual listen port

With the normal local startup path, the host still listens on 127.0.0.1:5080 (MainnetHostBuilderExtensions.LocalDevelopmentListenUrl and boot.sh both retain that default), so changing the built-in self probe to 5107 makes the status dashboard probe an unused port. The same commit also changes Studio.Storage.DefaultLocalRuntimeBaseUrl to 5107, causing newly initialized Studio settings to target the wrong server unless the developer supplies a matching override. The one-off 5107 command used in the test plan does not change these repository defaults.

AGENTS.md reference: AGENTS.md:L147-L147

Useful? React with 👍 / 👎.

parameters:
target: dinner_date_context
value: '{"task_id":"${json(steps.capture_user_choice.json.task_id)}","raw_user_request":"${json(steps.capture_user_choice.json.raw_user_request)}","participant":"${json(steps.capture_user_choice.json.participant)}","window":"${json(steps.capture_user_choice.json.window)}","party_size":${if(isBlank(steps.capture_user_choice.json.party_size), "null", steps.capture_user_choice.json.party_size)},"day":"${json(steps.capture_user_choice.json.day)}","time":"${json(steps.capture_user_choice.json.time)}","location":"${json(steps.capture_user_choice.json.location)}","cuisines":${if(isBlank(steps.capture_user_choice.json.cuisines), "null", steps.capture_user_choice.json.cuisines)},"restaurant_type":"${json(steps.capture_user_choice.json.restaurant_type)}","phone_number":"${json(steps.capture_user_choice.json.phone_number)}","budget_cap":${if(isBlank(steps.capture_user_choice.json.budget_cap), "null", steps.capture_user_choice.json.budget_cap)},"policy":${if(isBlank(steps.capture_user_choice.json.policy), "null", steps.capture_user_choice.json.policy)},"mode":"firecrawl-search-elevenlabs-call-selected","missing_fields":${if(isBlank(steps.capture_user_choice.json.missing_fields), "[]", steps.capture_user_choice.json.missing_fields)}}'
value: '{"task_id":"${json(steps.capture_user_choice.json.task_id)}","raw_user_request":"${json(if(isBlank(steps.capture_user_choice.json.raw_user_request), if(isBlank(steps.capture_user_choice.json.request), steps.capture_user_choice.output, steps.capture_user_choice.json.request), steps.capture_user_choice.json.raw_user_request))}","participant":"${json(if(isBlank(steps.capture_user_choice.json.participant), steps.capture_user_choice.json.companion_name, steps.capture_user_choice.json.participant))}","contact_name":"${json(if(isBlank(steps.capture_user_choice.json.contact_name), if(isBlank(steps.capture_user_choice.json.reservation_contact_name), if(isBlank(steps.capture_user_choice.json.booking_name), if(isBlank(steps.capture_user_choice.json.client_name), if(isBlank(steps.capture_user_choice.json.user_name), if(isBlank(steps.capture_user_choice.json.configured_name), "", steps.capture_user_choice.json.configured_name), steps.capture_user_choice.json.user_name), steps.capture_user_choice.json.client_name), steps.capture_user_choice.json.booking_name), steps.capture_user_choice.json.reservation_contact_name), steps.capture_user_choice.json.contact_name))}","window":"${json(if(isBlank(steps.capture_user_choice.json.window), steps.capture_user_choice.json.date_window, steps.capture_user_choice.json.window))}","party_size":${if(isBlank(steps.capture_user_choice.json.party_size), "null", steps.capture_user_choice.json.party_size)},"day":"${json(if(isBlank(steps.capture_user_choice.json.day), steps.capture_user_choice.json.date, steps.capture_user_choice.json.day))}","time":"${json(steps.capture_user_choice.json.time)}","location":"${json(if(isBlank(steps.capture_user_choice.json.location), steps.capture_user_choice.json.location_context, steps.capture_user_choice.json.location))}","cuisines":${if(isBlank(steps.capture_user_choice.json.cuisines), if(isBlank(steps.capture_user_choice.json.preferred_cuisines), "null", steps.capture_user_choice.json.preferred_cuisines), steps.capture_user_choice.json.cuisines)},"restaurant_type":"${json(steps.capture_user_choice.json.restaurant_type)}","phone_number":"${json(if(isBlank(steps.capture_user_choice.json.phone_number), steps.capture_user_choice.json.contact_phone_number, steps.capture_user_choice.json.phone_number))}","backup_times":"${json(steps.capture_user_choice.json.backup_times)}","special_requests":"${json(steps.capture_user_choice.json.special_requests)}","restaurant_phone_number":"${json(steps.capture_user_choice.json.restaurant_phone_number)}","budget_cap":${if(isBlank(steps.capture_user_choice.json.budget_cap), "null", steps.capture_user_choice.json.budget_cap)},"policy":${if(isBlank(steps.capture_user_choice.json.policy), "null", steps.capture_user_choice.json.policy)},"search_query":"${json(if(isBlank(steps.capture_user_choice.json.search_query), if(isBlank(steps.capture_user_choice.json.location), if(isBlank(steps.capture_user_choice.json.location_context), if(isBlank(steps.capture_user_choice.json.request), steps.capture_user_choice.output, steps.capture_user_choice.json.request), steps.capture_user_choice.json.location_context), steps.capture_user_choice.json.location), steps.capture_user_choice.json.search_query))}${if(isBlank(steps.capture_user_choice.json.search_query), " restaurant reservation", "")}","mode":"firecrawl-search-elevenlabs-call-selected","missing_fields":${if(isBlank(steps.capture_user_choice.json.missing_fields), "[]", steps.capture_user_choice.json.missing_fields)}}'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize home_location before building the search query

When readDiningProfileContext returns its advertised home_location field and the current request has no explicit location, the dispatcher copies that property into the workflow input verbatim, but this initializer only checks location and location_context for both the normalized location and fallback search query. A request such as “Plan a dinner date with Priya this week” therefore ignores the stored geography and sends a generic worldwide Firecrawl query. Include home_location in this normalization chain (the companion preferred_cuisines alias is already handled).

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant