@lightupai/polaris 0.0.1

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/docs/README.md ADDED
@@ -0,0 +1,377 @@
1
+ # Polaris
2
+
3
+ Multiplayer collaboration for AI agents and humans. Capture, share, and coordinate across agent sessions — with humans and AI agents working together on any kind of work. Model-agnostic: works with any AI agent (e.g., Claude Code, Cursor, custom agents).
4
+
5
+ ## What Polaris Does
6
+
7
+ Polaris connects AI agent sessions to a shared cloud service, enabling teams to collaborate in real time on any kind of work — software development, data analysis, event planning, and more.
8
+
9
+ - **Capture** every interaction in an agent session — user prompts, agent responses, tool calls — and broadcast it to your team
10
+ - **Inject** context from teammates or agents into a live agent session so the agent can incorporate it immediately
11
+ - **Pool context** across multiple concurrent workstreams so everyone benefits from the full picture
12
+ - **Hand off** work from one person to another with full context preserved
13
+
14
+ ## Getting Started
15
+
16
+ ### 1. Admin signs up the org (once)
17
+
18
+ Visit [polaris.dev](https://polaris.dev) and sign up with Google SSO. This creates your organization. From the dashboard:
19
+
20
+ - **Connect your Slack workspace** — one-click OAuth, enables the floor for all projects
21
+ - **Invite your team** — by email, or allow auto-join by email domain
22
+
23
+ ### 2. Each team member sets up their machine (once)
24
+
25
+ ```sh
26
+ npx @lightup/polaris login
27
+ ```
28
+
29
+ This opens your browser for Google SSO, then automatically installs everything:
30
+ - Local daemon for session routing
31
+ - AI agent integration (MCP server, hooks, status line)
32
+ - The `/polaris` command
33
+
34
+ One command. Done.
35
+
36
+ ### 3. Connect to a session (each time)
37
+
38
+ Inside any AI agent (Claude Code, Cursor, etc.):
39
+
40
+ ```
41
+ /polaris join my-project feature-1
42
+ ```
43
+
44
+ Your agent session is now connected. Everything you do is captured and broadcast to the project's floor. Advisors can inject context into your session in real time.
45
+
46
+ ## Core Concepts
47
+
48
+ ### Projects
49
+
50
+ A project is the top-level workspace for collaboration, scoped to your organization. It groups related sessions together and pools context across them. Each project has a **floor** — a shared space where all activity is broadcast and anyone can participate. The floor is backed by a messaging platform (Slack, WhatsApp, Discord, or any supported bridge).
51
+
52
+ Create a project for any coordinated effort — a feature build, a sprint, an incident response, a trip with friends.
53
+
54
+ ### Sessions
55
+
56
+ A session is a single workstream within a project — one person or agent working on one thing via an AI agent. A project can have many sessions running concurrently.
57
+
58
+ Examples: `auth-middleware`, `db-schema`, `tests`, `docs`.
59
+
60
+ ### Drivers
61
+
62
+ Each session has one **driver** — the person or agent actively working via an AI agent. The driver's interactions are captured and broadcast. Only one driver per session at a time, but a project can have multiple sessions with different drivers working in parallel.
63
+
64
+ ### Advisors
65
+
66
+ Advisors contribute context to a session without being the driver. They post on the project's floor, targeting a specific session. Their input is injected directly into that session — the agent sees it and can incorporate it immediately.
67
+
68
+ Anyone can advise any session at any time. Multiple advisors can contribute simultaneously.
69
+
70
+ ### The Floor
71
+
72
+ Each project has a floor — a shared space backed by a messaging platform (Slack, WhatsApp, Discord, or any platform with a Polaris bridge). The floor shows:
73
+
74
+ - An interleaved, attributed log of all sessions' activity
75
+ - Who said what, in which session (human and agent)
76
+ - Handoff transitions
77
+ - Advisory messages and their targets
78
+
79
+ Advisors participate directly on the floor. The floor is the complete, living record of the project.
80
+
81
+ ### Participants
82
+
83
+ Every participant has an identity, derived automatically from SSO:
84
+
85
+ | Type | Examples | Description |
86
+ |------|----------|-------------|
87
+ | `user:` | `user:manu`, `user:krishna` | Human participants (identity from Google SSO) |
88
+ | `agent:` | `agent:test-writer`, `agent:security-reviewer` | AI agent participants |
89
+ | `slack:` | `slack:someone` | Slack-only participants without a Polaris account |
90
+
91
+ Agents are first-class. They can be drivers or advisors, same as humans. The system treats them identically — the only difference is how they're labeled in the log.
92
+
93
+ **Slack identity mapping is automatic** — Polaris matches your Google SSO email to your Slack profile. When your work appears on the floor, it shows your Slack avatar and display name.
94
+
95
+ ### Handoff
96
+
97
+ The driver role on a session can transfer from one person to another:
98
+
99
+ 1. The current driver releases the session
100
+ 2. The new driver claims it and connects their agent
101
+ 3. The new driver's session is seeded with context from the project history
102
+ 4. The floor shows the transition
103
+
104
+ The log is continuous across handoffs — one unbroken narrative of how the work was done.
105
+
106
+ ### Cross-Session Context
107
+
108
+ Drivers can query what's happening in other sessions within the same project. This is pull-based (on demand), not push-based, so drivers aren't interrupted by sibling activity.
109
+
110
+ Use this to coordinate — check what a teammate has built before building something that depends on it.
111
+
112
+ ## The `/polaris` Command
113
+
114
+ Everything happens through one slash command inside your AI agent:
115
+
116
+ | Command | What it does |
117
+ |---------|-------------|
118
+ | `/polaris join <project> <session>` | Connect to a session (creates it if new) |
119
+ | `/polaris` | Show connection status |
120
+ | `/polaris disconnect` | Disconnect from current session |
121
+
122
+ The status line at the bottom of your agent always shows your connection state:
123
+
124
+ ```
125
+ polaris: my-project/feature-1 (user:manu) ● connected
126
+ ```
127
+
128
+ ## Features
129
+
130
+ ### Session Capture and Broadcast
131
+
132
+ Everything that happens in an agent session is captured and broadcast:
133
+
134
+ - User prompts
135
+ - Agent responses
136
+ - Tool calls and results (collapsed on the floor to reduce noise)
137
+
138
+ The broadcast goes to the project's floor and is persisted as the permanent record.
139
+
140
+ ### Context Injection
141
+
142
+ Advisors can inject context into any session by posting on the project's floor and targeting the session. The driver's agent sees the advisory message as it arrives.
143
+
144
+ Every injection must specify a target session — no untargeted broadcasts.
145
+
146
+ ### Context Pooling
147
+
148
+ All events across all sessions in a project are stored together. This shared context means:
149
+
150
+ - Advisors' messages reach the target driver in real time
151
+ - Any driver can pull context from sibling sessions on demand (e.g., "what has Krishna done on the database schema?")
152
+ - When someone takes over a session or starts a new one, they can be seeded with the full project history
153
+
154
+ Sibling session activity is available on-demand, not auto-injected, to avoid noise.
155
+
156
+ ## Examples
157
+
158
+ ### Software Development: Web App
159
+
160
+ A team building a web app, with two human developers and two AI agents:
161
+
162
+ ```
163
+ Project: webapp
164
+ ├── session auth driver: user:manu auth middleware
165
+ ├── session db-schema driver: user:krishna database schema
166
+ ├── session tests driver: agent:test-writer test suite
167
+
168
+ ├── advisor: agent:security-reviewer
169
+ └── advisor: user:priya (via Slack)
170
+ ```
171
+
172
+ The floor (Slack `#webapp`) shows:
173
+
174
+ ```
175
+ [user:manu/auth → agent] "Let's implement the auth middleware"
176
+ [agent → user:manu/auth] "I'll create src/middleware/auth.ts..."
177
+ [user:krishna/db-schema → agent] "Set up the database schema for users"
178
+ [agent → user:krishna/db-schema] "Creating migrations/001_users.sql..."
179
+ [user:priya → db-schema] "Remember we need GDPR compliance on the users table"
180
+ [agent → user:krishna/db-schema] "Good point from Priya. Adding data retention fields..."
181
+ [agent:security-reviewer → auth] "This auth endpoint needs rate limiting"
182
+ [agent → user:manu/auth] "Adding rate limiting middleware..."
183
+ [agent:test-writer/tests → agent] "Writing integration tests for auth middleware"
184
+ [agent → agent:test-writer/tests] "Created tests/auth.test.ts..."
185
+ ```
186
+
187
+ Manu finishes auth, hands off db-schema to himself to continue Krishna's work. The log continues seamlessly.
188
+
189
+ ### Data Engineering: Pipeline Migration
190
+
191
+ A data engineering team migrating a legacy Airflow pipeline to a new orchestrator, with a data quality agent watching for issues:
192
+
193
+ ```
194
+ Project: pipeline-migration
195
+ ├── session ingestion driver: user:sara rewrite ingestion DAGs
196
+ ├── session transforms driver: user:raj port dbt transforms
197
+ ├── session validation driver: agent:dq-checker data quality checks
198
+
199
+ ├── advisor: agent:schema-drift-monitor
200
+ ├── advisor: user:lee (data platform lead, via Slack)
201
+ ```
202
+
203
+ The floor (Slack `#pipeline-migration`) shows:
204
+
205
+ ```
206
+ [user:sara/ingestion → agent] "Rewrite the S3-to-Snowflake ingestion DAG for the new orchestrator"
207
+ [agent → user:sara/ingestion] "I'll create pipelines/ingest_s3_snowflake.py using the new SDK..."
208
+ [user:raj/transforms → agent] "Port the customer_ltv dbt model and its upstream dependencies"
209
+ [agent → user:raj/transforms] "Mapping the dependency graph: customer_ltv depends on orders, payments..."
210
+ [agent:schema-drift-monitor → transforms] "Column 'payment_method' was renamed to 'pay_type' in source system as of last night's sync"
211
+ [agent → user:raj/transforms] "Updating the dbt model to reference 'pay_type' instead..."
212
+ [user:lee → ingestion] "Use the v2 Snowflake connector — v1 doesn't support the new auth"
213
+ [agent → user:sara/ingestion] "Switching to v2 connector and updating credentials config..."
214
+ [agent:dq-checker/validation → agent] "Running row count and null checks on migrated tables"
215
+ [agent → agent:dq-checker/validation] "3 tables passed. orders_raw has 2.3% null rate on customer_id, up from 0.1%"
216
+ [agent:dq-checker → ingestion] "orders_raw customer_id null rate jumped to 2.3% — likely a source schema change"
217
+ [agent → user:sara/ingestion] "Investigating — adding null handling for customer_id in the ingestion pipeline..."
218
+ ```
219
+
220
+ Sara finishes ingestion, Raj finishes transforms. The dq-checker agent continues running validation against production data. Lee reviews the full log on the floor to verify the migration is complete.
221
+
222
+ ### Marketing: Email Campaign Launch
223
+
224
+ A marketing team building and launching a segmented email campaign, with AI agents handling personalization and compliance:
225
+
226
+ ```
227
+ Project: spring-campaign
228
+ ├── session segments driver: user:jess audience segmentation queries
229
+ ├── session templates driver: user:marco email HTML/copy
230
+ ├── session personalize driver: agent:content-writer variant generation
231
+
232
+ ├── advisor: agent:compliance-checker
233
+ ├── advisor: user:dana (brand director, via Slack)
234
+ ```
235
+
236
+ The floor (Slack `#spring-campaign`) shows:
237
+
238
+ ```
239
+ [user:jess/segments → agent] "Build segments for the spring campaign: churned-30d, active-high-ltv, new-trial"
240
+ [agent → user:jess/segments] "Creating SQL queries for each segment against the warehouse..."
241
+ [user:marco/templates → agent] "Create the base email template with our new brand guidelines"
242
+ [agent → user:marco/templates] "Building responsive HTML template with the updated color palette..."
243
+ [user:dana → templates] "Use the shorter subject line format we tested last quarter — under 40 chars"
244
+ [agent → user:marco/templates] "Constraining subject lines to under 40 characters..."
245
+ [agent:compliance-checker → templates] "CAN-SPAM: unsubscribe link must be in the first scroll. Also add physical mailing address."
246
+ [agent → user:marco/templates] "Moving unsubscribe link above the fold and adding mailing address to footer..."
247
+ [user:jess/segments → agent] "What does the template look like so far?"
248
+ [agent → user:jess/segments] "Marco's template has responsive layout, short subject lines, CAN-SPAM compliant footer..."
249
+ [agent:content-writer/personalize → agent] "Generate 3 subject line variants per segment based on the template and segment profiles"
250
+ [agent → agent:content-writer/personalize] "Churned-30d: 'We miss you — 20% off this week'... Active-high-ltv: 'Early access: spring collection'..."
251
+ [agent:compliance-checker → personalize] "Variant 2 for new-trial uses 'FREE' in all caps — likely to trigger spam filters"
252
+ [agent → agent:content-writer/personalize] "Revising variant 2 to avoid spam trigger words..."
253
+ [user:marco/templates → agent] "Pull in the final variants from the personalize session"
254
+ [agent → user:marco/templates] "Integrating 9 approved variants into the template with merge tags..."
255
+ ```
256
+
257
+ Jess hands off segments to the deployment team. Marco finalizes templates with the personalized variants. Dana reviews the full log in `#spring-campaign` to approve before send.
258
+
259
+ ### Data Analytics: Quarterly Business Review
260
+
261
+ A VP of Sales asks a question that kicks off an analysis workflow across a human analyst, a data agent, and domain experts — all collaborating on the floor:
262
+
263
+ ```
264
+ Project: q2-revenue-deep-dive
265
+ ├── session exploration driver: agent:data-analyst initial data pull and exploration
266
+ ├── session modeling driver: user:nina regression modeling and forecasting
267
+
268
+ ├── advisor: user:tom (VP Sales — the question-asker)
269
+ ├── advisor: user:finance-alex (FP&A, via Slack)
270
+ ├── advisor: agent:chart-builder
271
+ ```
272
+
273
+ The floor (Slack `#q2-revenue-deep-dive`) shows:
274
+
275
+ ```
276
+ [user:tom → exploration] "Why did APAC revenue drop 15% in Q2? Break it down by segment and product line"
277
+ [agent:data-analyst/exploration → agent] "Pulling Q2 APAC revenue by segment and product line from the warehouse..."
278
+ [agent → agent:data-analyst/exploration] "Query complete. Enterprise segment is flat. The drop is concentrated in mid-market, specifically the Pro tier — down 34%"
279
+ [agent:data-analyst/exploration → agent] "Drill into mid-market Pro: break down by new vs renewal, and pull churn timing"
280
+ [agent → agent:data-analyst/exploration] "Renewal revenue is stable. The drop is entirely new bookings — pipeline gen fell off in April"
281
+ [user:tom → exploration] "Was that the month we restructured the APAC SDR team?"
282
+ [agent → agent:data-analyst/exploration] "Checking timeline — yes, APAC SDR restructure was April 3rd. New opp creation dropped 40% in April, partially recovered in May"
283
+ [user:finance-alex → exploration] "Pull the SDR headcount and ramp data — we had 3 reps in ramp during April, that's probably the gap"
284
+ [agent → agent:data-analyst/exploration] "Confirmed: 3 of 8 APAC SDRs were in ramp (< 60 days). Fully ramped rep pipeline was actually up 5%"
285
+ [agent:data-analyst/exploration → agent] "Root cause identified. Summarize findings for the modeling session"
286
+ [agent → agent:data-analyst/exploration] "Summary ready: Q2 APAC revenue drop driven by new bookings shortfall in mid-market Pro, caused by SDR ramp gap from April restructure"
287
+ [user:nina/modeling → agent] "Pull the exploration findings and build a forecast — when does APAC recover if ramp completes on schedule?"
288
+ [agent → user:nina/modeling] "Fetching exploration context... Based on current ramp curves, full SDR productivity by late July. Modeling recovery..."
289
+ [agent:chart-builder → modeling] "Here's the revenue recovery projection chart with confidence intervals for Tom's deck"
290
+ [agent → user:nina/modeling] "Incorporating chart. Adding scenario analysis: on-track ramp vs accelerated hiring..."
291
+ [user:tom → modeling] "Add a scenario where we backfill one more rep in July"
292
+ [agent → user:nina/modeling] "Adding backfill scenario — projects recovery 3 weeks earlier, +$180K in Q3 net new"
293
+ [user:finance-alex → modeling] "That $180K assumes the same win rate. APAC mid-market win rate has been declining — use the trailing 3-month rate"
294
+ [agent → user:nina/modeling] "Adjusting win rate to trailing 3-month (18% vs 23%). Revised impact: +$140K in Q3"
295
+ ```
296
+
297
+ Tom gets his answer — and a data-backed recommendation — without writing a query or opening a notebook. Nina produces the final model. The entire analytical thread is preserved in `#q2-revenue-deep-dive` for the QBR deck, audit trail, and future reference.
298
+
299
+ ### Event Planning: Company Annual Kickoff
300
+
301
+ An event lead planning a 200-person, 3-day offsite — with AI agents handling research and drafting while stakeholders gate decisions from the floor:
302
+
303
+ ```
304
+ Project: annual-kickoff-2026
305
+ ├── session logistics driver: user:rachel venue, catering, travel
306
+ ├── session agenda driver: user:mike schedule, speakers, workshops
307
+ ├── session comms driver: agent:content-drafter invites, itinerary, speaker briefs
308
+
309
+ ├── advisor: user:diana (CFO — budget authority, via Slack)
310
+ ├── advisor: user:jay (IT — AV/tech setup, via Slack)
311
+ ├── advisor: agent:venue-scout
312
+ ```
313
+
314
+ The floor (Slack `#annual-kickoff-2026`) shows:
315
+
316
+ ```
317
+ [user:rachel/logistics → agent] "Find venues in Austin for 200 people, 3 days in September, budget $150K all-in"
318
+ [agent → user:rachel/logistics] "Searching... 4 options shortlisted with pricing and availability"
319
+ [agent:venue-scout → logistics] "Option 2 (Lakeway Resort) has a noise ordinance after 9pm — won't work for the evening events"
320
+ [agent → user:rachel/logistics] "Dropping option 2. Top pick is now Line Hotel — $128K, available Sep 15-17"
321
+ [user:diana → logistics] "That $128K — does it include AV? Last year we got hit with $20K in AV add-ons"
322
+ [agent → user:rachel/logistics] "Checking... AV is $8K extra at Line Hotel. Total $136K, under budget"
323
+ [user:mike/agenda → agent] "Draft a 3-day agenda: day 1 strategy, day 2 team workshops, day 3 hackathon + closing"
324
+ [agent → user:mike/agenda] "Here's the draft agenda with session blocks and break times..."
325
+ [user:jay → agenda] "Workshop rooms need breakout Zoom for remote attendees — max 6 concurrent streams"
326
+ [agent → user:mike/agenda] "Noted. Allocating workshops to 6 tracks max, adding Zoom setup requirements..."
327
+ [agent:content-drafter/comms → agent] "Draft the save-the-date email based on logistics and agenda progress"
328
+ [agent → agent:content-drafter/comms] "Fetching context from logistics and agenda... Draft ready: 'Annual Kickoff — Sep 15-17, Austin'"
329
+ [user:rachel/logistics → agent] "What has Mike finalized on the agenda?"
330
+ [agent → user:rachel/logistics] "Day 1: CEO keynote + strategy sessions. Day 2: 6 workshop tracks. Day 3: hackathon + awards dinner"
331
+ [user:diana → comms] "Don't send the save-the-date until I approve the venue contract"
332
+ [agent → agent:content-drafter/comms] "Holding send. Marking draft as pending finance approval..."
333
+ ```
334
+
335
+ Rachel handles logistics, Mike shapes the agenda, the content agent drafts communications pulling context from both. Diana gates spending from the floor without touching any tool. Jay flags technical requirements. The full planning trail lives on the floor — no code involved, just planning, decisions, and coordination.
336
+
337
+ ### Personal: Trip Planning with Friends
338
+
339
+ A group of friends planning a week-long trip to Japan, with the floor on WhatsApp:
340
+
341
+ ```
342
+ Project: japan-oct-2026
343
+ ├── session flights driver: user:alex finding and booking flights
344
+ ├── session stays driver: user:sam hotels, ryokans, Airbnbs
345
+ ├── session itinerary driver: agent:trip-planner day-by-day plan
346
+
347
+ ├── advisor: user:jordan (foodie — restaurant picks, via WhatsApp)
348
+ ├── advisor: user:riley (been to Japan twice, via WhatsApp)
349
+ ├── advisor: agent:budget-tracker
350
+ ```
351
+
352
+ The floor (WhatsApp group `Japan Oct 2026`) shows:
353
+
354
+ ```
355
+ [user:alex/flights → agent] "Find round-trip flights SFO→Tokyo for 4 people, Oct 10-18, under $900/person"
356
+ [agent → user:alex/flights] "Best options: ANA direct $870, JAL direct $920, United 1-stop $680"
357
+ [user:riley → flights] "Do ANA — the United 1-stop goes through Taipei and the layover is brutal"
358
+ [agent → user:alex/flights] "Noted. ANA direct, $870/person, $3,480 total. Arrives Haneda 3pm local"
359
+ [agent:budget-tracker → flights] "Running total: $3,480 of $8,000 group budget spent. $4,520 remaining for stays + activities"
360
+ [user:sam/stays → agent] "Find places for 4 in Tokyo (3 nights), Kyoto (2 nights), Osaka (2 nights)"
361
+ [agent → user:sam/stays] "Tokyo: Shinjuku apartment $180/night. Kyoto: traditional ryokan $220/night. Osaka: Dotonbori hotel $140/night"
362
+ [user:riley → stays] "Do the ryokan in Kyoto, 100%. Book one with a private onsen if you can"
363
+ [agent → user:sam/stays] "Found one with private onsen — $260/night. $40 more but it's the highlight of the trip"
364
+ [user:jordan → stays] "For Osaka, stay near Shinsekai not Dotonbori — way better street food and less touristy"
365
+ [agent → user:sam/stays] "Switching to Shinsekai area. Found a spot 5 min walk from Tsutenkaku — $130/night"
366
+ [agent:budget-tracker → stays] "Stays total: $1,640. Running total: $5,120. $2,880 left for activities and food"
367
+ [agent:trip-planner/itinerary → agent] "Build day-by-day itinerary pulling from flights and stays context"
368
+ [agent → agent:trip-planner/itinerary] "Fetching context... Day 1: Arrive Haneda 3pm, train to Shinjuku, dinner in Golden Gai..."
369
+ [user:jordan → itinerary] "Day 2 evening: book Tsuta for ramen (Michelin star, need reservation) and hit up Omoide Yokocho after"
370
+ [agent → agent:trip-planner/itinerary] "Adding Tsuta reservation to Day 2, Omoide Yokocho for late-night..."
371
+ [user:alex/flights → agent] "What's the itinerary looking like so far?"
372
+ [agent → user:alex/flights] "7 days planned: 3 Tokyo, 2 Kyoto, 2 Osaka. Highlights: ryokan with private onsen, Tsuta ramen, Fushimi Inari sunrise..."
373
+ [user:riley → itinerary] "Do Fushimi Inari at 5am, not during the day. Trust me, no crowds and it's magical"
374
+ [agent → agent:trip-planner/itinerary] "Moving Fushimi Inari to 5am slot on Day 4..."
375
+ ```
376
+
377
+ Everyone contributes what they know — Riley's been before, Jordan knows food, Alex handles logistics, Sam handles stays. The trip planner agent weaves it all together. The budget tracker keeps everyone honest. Nobody needs to be in a group chat arguing — they just drop their input when they have it, targeted to the right session. The floor becomes the trip bible.
@@ -0,0 +1,19 @@
1
+ #!/bin/sh
2
+ # hooks/capture.sh - Forward Claude Code hook events to polaris local client
3
+ # Reads hook JSON from stdin, POSTs to the local polaris client.
4
+ # Always exits 0 to avoid blocking the coding agent.
5
+
6
+ POLARIS_PORT="${POLARIS_PORT:-4321}"
7
+ POLARIS_URL="http://127.0.0.1:${POLARIS_PORT}/events"
8
+
9
+ # Read all of stdin
10
+ INPUT=$(cat)
11
+
12
+ # POST to polaris local client, fail silently
13
+ curl -s -X POST \
14
+ -H "Content-Type: application/json" \
15
+ -d "$INPUT" \
16
+ "$POLARIS_URL" \
17
+ >/dev/null 2>&1 || true
18
+
19
+ exit 0
@@ -0,0 +1,30 @@
1
+ #!/bin/sh
2
+ # hooks/statusline.sh — Polaris status line for coding agent CLI
3
+ # Reads session JSON from stdin, queries daemon for connection state.
4
+
5
+ POLARIS_DAEMON_PORT="${POLARIS_DAEMON_PORT:-4321}"
6
+
7
+ # Read stdin (session JSON from the coding agent)
8
+ INPUT=$(cat)
9
+
10
+ # Extract the CC session ID if available (jq optional, fallback to "unknown")
11
+ CC_SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // "unknown"' 2>/dev/null || echo "unknown")
12
+
13
+ # Query daemon for polaris connection status
14
+ STATUS=$(curl -s "http://127.0.0.1:${POLARIS_DAEMON_PORT}/status/${CC_SESSION_ID}" 2>/dev/null)
15
+
16
+ if [ -z "$STATUS" ]; then
17
+ echo "polaris: daemon offline"
18
+ exit 0
19
+ fi
20
+
21
+ CONNECTED=$(echo "$STATUS" | jq -r '.connected' 2>/dev/null || echo "false")
22
+
23
+ if [ "$CONNECTED" = "true" ]; then
24
+ PROJECT=$(echo "$STATUS" | jq -r '.project' 2>/dev/null)
25
+ SESSION=$(echo "$STATUS" | jq -r '.session' 2>/dev/null)
26
+ USER=$(echo "$STATUS" | jq -r '.user' 2>/dev/null)
27
+ echo "polaris: ${PROJECT}/${SESSION} (${USER})"
28
+ else
29
+ echo "polaris: not connected"
30
+ fi
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@lightupai/polaris",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "bin": {
6
+ "polaris": "src/cli/cli.ts"
7
+ },
8
+ "scripts": {
9
+ "test": "bun test"
10
+ },
11
+ "dependencies": {
12
+ "@modelcontextprotocol/sdk": "^1.12.0",
13
+ "arctic": "^3.5.0",
14
+ "hono": "^4.7.0",
15
+ "jose": "^6.0.0",
16
+ "postgres": "^3.4.0",
17
+ "zod": "^3.23.0"
18
+ },
19
+ "devDependencies": {
20
+ "@types/bun": "latest"
21
+ }
22
+ }
@@ -0,0 +1,111 @@
1
+ #!/bin/sh
2
+ # scripts/setup-google-oauth.sh
3
+ # Sets up a Google Cloud project with OAuth credentials for Polaris.
4
+ # Writes GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to .env
5
+ #
6
+ # Uses a local gcloud configuration so it doesn't touch your global settings.
7
+
8
+ set -e
9
+
10
+ GCLOUD_ACCOUNT="${GCLOUD_ACCOUNT:-manub@lightup.ai}"
11
+ GCLOUD_CONFIG_NAME="polaris-setup"
12
+ PROJECT_ID="polaris-dev-$(date +%s)"
13
+ PROJECT_NAME="Polaris Dev"
14
+ REDIRECT_URI="http://localhost:3000/auth/google/callback"
15
+ ENV_FILE=".env"
16
+
17
+ echo "=== Setting up Google OAuth for Polaris ==="
18
+ echo "Using gcloud account: ${GCLOUD_ACCOUNT}"
19
+ echo ""
20
+
21
+ # Create an isolated gcloud configuration (does not affect global config)
22
+ gcloud config configurations create "$GCLOUD_CONFIG_NAME" --quiet 2>/dev/null || \
23
+ gcloud config configurations activate "$GCLOUD_CONFIG_NAME" --quiet
24
+ gcloud config set account "$GCLOUD_ACCOUNT" --quiet
25
+ trap 'gcloud config configurations activate default --quiet 2>/dev/null; gcloud config configurations delete "$GCLOUD_CONFIG_NAME" --quiet 2>/dev/null' EXIT
26
+
27
+ # Create project
28
+ echo "Creating Google Cloud project: ${PROJECT_ID}"
29
+ gcloud projects create "$PROJECT_ID" --name="$PROJECT_NAME" --quiet 2>/dev/null || true
30
+ gcloud config set project "$PROJECT_ID" --quiet
31
+
32
+ # Enable OAuth APIs
33
+ echo "Enabling APIs..."
34
+ gcloud services enable iamcredentials.googleapis.com --quiet
35
+ gcloud services enable people.googleapis.com --quiet
36
+
37
+ # Configure OAuth consent screen
38
+ echo "Configuring OAuth consent screen..."
39
+ # Check if the current account has a billing account (needed for external)
40
+ # Use external type for dev, limited to test users
41
+ gcloud alpha iap oauth-brands create \
42
+ --application_title="Polaris" \
43
+ --support_email="$(gcloud config get account)" \
44
+ --quiet 2>/dev/null || true
45
+
46
+ # Create OAuth client
47
+ echo "Creating OAuth client..."
48
+ CLIENT_OUTPUT=$(gcloud alpha iap oauth-clients create \
49
+ "projects/${PROJECT_ID}/brands/$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')" \
50
+ --display_name="Polaris Web" \
51
+ 2>&1) || true
52
+
53
+ # If the above doesn't work (alpha commands can be flaky), fall back to REST API
54
+ if echo "$CLIENT_OUTPUT" | grep -q "ERROR"; then
55
+ echo ""
56
+ echo "Automated OAuth client creation failed."
57
+ echo "This is common — Google requires manual consent screen setup first."
58
+ echo ""
59
+ echo "Please complete these steps manually:"
60
+ echo ""
61
+ echo "1. Open: https://console.cloud.google.com/apis/credentials/consent?project=${PROJECT_ID}"
62
+ echo " - User type: External"
63
+ echo " - App name: Polaris"
64
+ echo " - Support email: your email"
65
+ echo " - Click Save"
66
+ echo ""
67
+ echo "2. Open: https://console.cloud.google.com/apis/credentials/oauthclient?project=${PROJECT_ID}"
68
+ echo " - Application type: Web application"
69
+ echo " - Name: Polaris Web"
70
+ echo " - Authorized redirect URIs: ${REDIRECT_URI}"
71
+ echo " - Click Create"
72
+ echo ""
73
+ echo "3. Copy the Client ID and Client Secret, then run:"
74
+ echo ""
75
+ echo " cat > .env << EOF"
76
+ echo " GOOGLE_CLIENT_ID=your-client-id"
77
+ echo " GOOGLE_CLIENT_SECRET=your-client-secret"
78
+ echo " GOOGLE_REDIRECT_URI=${REDIRECT_URI}"
79
+ echo " EOF"
80
+ echo ""
81
+ echo "Project created: ${PROJECT_ID}"
82
+ echo "Console: https://console.cloud.google.com/apis/credentials?project=${PROJECT_ID}"
83
+ exit 0
84
+ fi
85
+
86
+ # Extract client ID and secret
87
+ CLIENT_ID=$(echo "$CLIENT_OUTPUT" | grep -o '[0-9]*-[a-z0-9]*.apps.googleusercontent.com' | head -1)
88
+ CLIENT_SECRET=$(echo "$CLIENT_OUTPUT" | grep 'secret:' | awk '{print $2}')
89
+
90
+ if [ -z "$CLIENT_ID" ] || [ -z "$CLIENT_SECRET" ]; then
91
+ echo "Could not parse client credentials from output."
92
+ echo "Output was: $CLIENT_OUTPUT"
93
+ echo ""
94
+ echo "Create the OAuth client manually:"
95
+ echo "https://console.cloud.google.com/apis/credentials/oauthclient?project=${PROJECT_ID}"
96
+ exit 1
97
+ fi
98
+
99
+ # Write .env file
100
+ cat > "$ENV_FILE" << EOF
101
+ GOOGLE_CLIENT_ID=${CLIENT_ID}
102
+ GOOGLE_CLIENT_SECRET=${CLIENT_SECRET}
103
+ GOOGLE_REDIRECT_URI=${REDIRECT_URI}
104
+ EOF
105
+
106
+ echo ""
107
+ echo "=== Done! ==="
108
+ echo "Project: ${PROJECT_ID}"
109
+ echo "Credentials written to ${ENV_FILE}"
110
+ echo ""
111
+ echo "Start the dev server with: make clean && make dev"