1741
});
1742
}
1744
>
if (sessionConfig.importConversation) {
1745
return this._importConversation(sessionConfig, sessionId, workingDirectory);
1746
}
1748
>
// Non-fork path: create a *provisional* session. The Copilot SDK
1749
>
// session, the worktree (if any), and the on-disk metadata are all
1750
>
// deferred until the first {@link sendMessage} via
1751
>
// {@link _materializeProvisional}. Until then this session occupies
1752
>
// only an in-memory slot plus a state-manager entry, so a workspace
1753
>
// switch (or quick close) costs nothing on disk.
1754
>
const sessionUri = AgentSession.uri(this.id, sessionId);
1755
>
1756
>
// Idempotency for already-materialized sessions: a duplicate
1757
>
// `createSession` for a URI that has already been promoted to a real
1758
>
// SDK session (or restored from disk) is a no-op; we return the
1759
>
// non-provisional result so the caller doesn't re-fire `SessionAdded`.
1760
>
// This guards against client retries that race a successful first
1761
>
// message.
1762
>
if (this._findAnySession(sessionId)) {
1763
this._logService.info(`[Copilot] createSession is a no-op: session already materialized: ${sessionUri.toString()}`);
1764
const project = await projectFromCopilotContext({ cwd: workingDirectory.fsPath }, this._gitService);
1765
return { session: sessionUri, workingDirectory, ...(project ? { project } : {}) };
1766
}
1768
>
// Idempotent: a duplicate `createSession` for a still-provisional URI
1769
>
// (e.g. a client retried on reconnect with the same URI) keeps the
1770
>
// existing record. We deliberately do NOT overwrite `model` or
1771
>
// `workingDirectory`: a re-create payload from a fresh connection sends
1772
>
// the eager-create defaults (model: undefined, the same workingDirectory),
1773
>
// which would clobber the user's selections accumulated since the
1774
>
// original create. The active-client / plugin sync below still runs so
1775
>
// the new connection's claim takes effect.
1776
>
const alreadyProvisional = this._provisionalSessions.has(sessionId);
1777
>
1778
>
// Seed active-client snapshot if the client claimed it eagerly. This
1779
>
// runs identically for provisional and real sessions; the SDK side
1780
>
// of activeClient state isn't engaged until materialization.
1781
>
if (sessionConfig.activeClient) {
1782
const ac = this._getOrCreateActiveClient(sessionUri, workingDirectory);
1783
const seeded = sessionConfig.activeClient;