Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qjclaw-dmg
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
AI-甘富林
qjclaw-dmg
Commits
f7047bcf
Commit
f7047bcf
authored
May 13, 2026
by
edy
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix(desktop): inject lobster key into workspace entries
parent
b178b48c
Pipeline
#18456
failed
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
139 additions
and
2 deletions
+139
-2
ipc.ts
apps/desktop/src/main/ipc.ts
+15
-2
workspace-entry-lobster-env.ts
.../desktop/src/main/services/workspace-entry-lobster-env.ts
+13
-0
workspace-entry-lobster-env-smoke.mjs
build/scripts/workspace-entry-lobster-env-smoke.mjs
+58
-0
workspace-entry-lobster-env-smoke.ts
build/scripts/workspace-entry-lobster-env-smoke.ts
+52
-0
package.json
package.json
+1
-0
No files found.
apps/desktop/src/main/ipc.ts
View file @
f7047bcf
...
...
@@ -60,6 +60,7 @@ import {
buildProjectModelRuntime
,
materializeProjectModelRuntime
}
from
"./services/project-model-runtime.js"
;
import
{
buildWorkspaceEntryLobsterEnv
}
from
"./services/workspace-entry-lobster-env.js"
;
import
{
refreshProjectContextAfterExecution
,
shouldRefreshProjectContextAfterExecution
...
...
@@ -732,6 +733,10 @@ export function registerDesktopIpc(services: MainServices): RegisteredDesktopIpc
return runtime.env;
};
const prepareWorkspaceEntryLobsterEnv = async (): Promise<Record<string, string>> => {
return buildWorkspaceEntryLobsterEnv(await secretManager.getApiKey());
};
const resolveConfiguredChatModel = async (config?: AppConfig) => {
const nextConfig = config ?? await getEffectiveConfig();
const baseUrl = nextConfig.expertModelConfig.copywriting.baseUrl.trim();
...
...
@@ -1769,6 +1774,7 @@ export function registerDesktopIpc(services: MainServices): RegisteredDesktopIpc
runtimeCloudSupervisor.noteMessageReceived(executionSessionId, prompt, executionSkillId);
try {
if (preparedExecution.decision.kind === "
workspace
-
entry
") {
const lobsterEnv = await prepareWorkspaceEntryLobsterEnv();
const projectModelEnv = await prepareProjectModelRuntime(
preparedExecution.sessionState.projectId,
preparedExecution.sessionState.projectRoot
...
...
@@ -1779,7 +1785,10 @@ export function registerDesktopIpc(services: MainServices): RegisteredDesktopIpc
prompt: preparedExecution.decision.preparedPrompt,
userPrompt: prompt,
attachments: preparedExecution.attachments,
extraEnv: projectModelEnv
extraEnv: {
...projectModelEnv,
...lobsterEnv
}
});
if ("
handoff
" in result) {
const fallbackExecutionPolicy = await resolveExecutionPolicy(
...
...
@@ -2067,6 +2076,7 @@ export function registerDesktopIpc(services: MainServices): RegisteredDesktopIpc
flushQueuedEvents();
void (async () => {
try {
const lobsterEnv = await prepareWorkspaceEntryLobsterEnv();
const projectModelEnv = await prepareProjectModelRuntime(
preparedExecution.sessionState.projectId,
preparedExecution.sessionState.projectRoot
...
...
@@ -2077,7 +2087,10 @@ export function registerDesktopIpc(services: MainServices): RegisteredDesktopIpc
prompt: preparedExecution.decision.preparedPrompt,
userPrompt: prompt,
attachments: preparedExecution.attachments,
extraEnv: projectModelEnv
extraEnv: {
...projectModelEnv,
...lobsterEnv
}
}, {
onStarted: (runId) => {
queueOrSend({
...
...
apps/desktop/src/main/services/workspace-entry-lobster-env.ts
0 → 100644
View file @
f7047bcf
const
LOBSTER_KEY_REQUIRED_MESSAGE
=
"请先绑定龙虾密钥"
;
export
function
buildWorkspaceEntryLobsterEnv
(
apiKey
:
string
|
undefined
):
Record
<
string
,
string
>
{
const
lobsterKey
=
apiKey
?.
trim
();
if
(
!
lobsterKey
)
{
throw
new
Error
(
LOBSTER_KEY_REQUIRED_MESSAGE
);
}
return
{
QJCLAW_LOBSTER_KEY
:
lobsterKey
,
OPENCLAW_EMPLOYEE_API_KEY
:
lobsterKey
};
}
build/scripts/workspace-entry-lobster-env-smoke.mjs
0 → 100644
View file @
f7047bcf
#!/usr/bin/env node
import
{
execFileSync
}
from
"node:child_process"
;
import
{
existsSync
,
mkdirSync
,
rmSync
,
writeFileSync
}
from
"node:fs"
;
import
path
from
"node:path"
;
import
{
fileURLToPath
}
from
"node:url"
;
const
__filename
=
fileURLToPath
(
import
.
meta
.
url
);
const
__dirname
=
path
.
dirname
(
__filename
);
const
repoRoot
=
path
.
resolve
(
__dirname
,
".."
,
".."
);
const
tempRoot
=
path
.
join
(
repoRoot
,
".tmp"
,
"workspace-entry-lobster-env-smoke"
);
const
compileRoot
=
path
.
join
(
tempRoot
,
"compiled"
);
const
sourcePath
=
path
.
join
(
repoRoot
,
"build"
,
"scripts"
,
"workspace-entry-lobster-env-smoke.ts"
);
const
entryPath
=
path
.
join
(
compileRoot
,
"build"
,
"scripts"
,
"workspace-entry-lobster-env-smoke.js"
);
const
resultPath
=
process
.
argv
[
2
]
?
path
.
resolve
(
process
.
argv
[
2
])
:
path
.
join
(
tempRoot
,
"result.json"
);
if
(
!
existsSync
(
sourcePath
))
{
throw
new
Error
(
`Workspace-entry lobster env smoke source was not found:
${
sourcePath
}
`
);
}
rmSync
(
compileRoot
,
{
recursive
:
true
,
force
:
true
});
mkdirSync
(
compileRoot
,
{
recursive
:
true
});
execFileSync
(
"corepack"
,
[
"pnpm"
,
"--dir"
,
path
.
join
(
repoRoot
,
"apps"
,
"desktop"
),
"exec"
,
"tsc"
,
"--module"
,
"ES2022"
,
"--moduleResolution"
,
"node"
,
"--target"
,
"ES2022"
,
"--lib"
,
"ES2022"
,
"--types"
,
"node"
,
"--esModuleInterop"
,
"--allowSyntheticDefaultImports"
,
"--skipLibCheck"
,
"--outDir"
,
compileRoot
,
sourcePath
],
{
stdio
:
"inherit"
});
if
(
!
existsSync
(
entryPath
))
{
throw
new
Error
(
`Workspace-entry lobster env smoke entry was not emitted:
${
entryPath
}
`
);
}
writeFileSync
(
path
.
join
(
compileRoot
,
"package.json"
),
"{
\"
type
\"
:
\"
module
\"
}"
,
"utf8"
);
execFileSync
(
"node"
,
[
entryPath
,
resultPath
],
{
stdio
:
"inherit"
});
if
(
!
existsSync
(
resultPath
))
{
throw
new
Error
(
`Workspace-entry lobster env smoke did not produce a result file:
${
resultPath
}
`
);
}
build/scripts/workspace-entry-lobster-env-smoke.ts
0 → 100644
View file @
f7047bcf
import
{
mkdir
,
rm
,
writeFile
}
from
"node:fs/promises"
;
import
path
from
"node:path"
;
import
{
fileURLToPath
}
from
"node:url"
;
import
{
buildWorkspaceEntryLobsterEnv
}
from
"../../apps/desktop/src/main/services/workspace-entry-lobster-env.js"
;
function
assert
(
condition
:
unknown
,
message
:
string
):
asserts
condition
{
if
(
!
condition
)
{
throw
new
Error
(
message
);
}
}
function
assertThrowsMissingKey
(
input
:
string
|
undefined
):
void
{
try
{
buildWorkspaceEntryLobsterEnv
(
input
);
}
catch
(
error
)
{
assert
(
error
instanceof
Error
,
"Missing-key path should throw an Error."
);
assert
(
error
.
message
===
"请先绑定龙虾密钥"
,
"Missing-key error message changed."
);
return
;
}
throw
new
Error
(
"Missing-key path did not throw."
);
}
async
function
main
():
Promise
<
void
>
{
const
__filename
=
fileURLToPath
(
import
.
meta
.
url
);
const
__dirname
=
path
.
dirname
(
__filename
);
const
repoRoot
=
path
.
resolve
(
__dirname
,
".."
,
".."
);
const
resultPath
=
path
.
resolve
(
process
.
argv
[
2
]
??
path
.
join
(
repoRoot
,
".tmp"
,
"workspace-entry-lobster-env-smoke"
,
"result.json"
));
const
tempRoot
=
path
.
dirname
(
resultPath
);
await
rm
(
tempRoot
,
{
recursive
:
true
,
force
:
true
});
await
mkdir
(
tempRoot
,
{
recursive
:
true
});
const
env
=
buildWorkspaceEntryLobsterEnv
(
" lobster-secret "
);
assert
(
env
.
QJCLAW_LOBSTER_KEY
===
"lobster-secret"
,
"Primary lobster env var should use the trimmed key."
);
assert
(
env
.
OPENCLAW_EMPLOYEE_API_KEY
===
"lobster-secret"
,
"Compatibility env var should use the trimmed key."
);
assert
(
Object
.
keys
(
env
).
length
===
2
,
"Workspace-entry lobster env should expose only the two expected variables."
);
assertThrowsMissingKey
(
undefined
);
assertThrowsMissingKey
(
""
);
assertThrowsMissingKey
(
" "
);
await
writeFile
(
resultPath
,
JSON
.
stringify
({
ok
:
true
,
envKeys
:
Object
.
keys
(
env
)
},
null
,
2
),
"utf8"
);
}
main
().
catch
((
error
)
=>
{
console
.
error
(
error
);
process
.
exit
(
1
);
});
package.json
View file @
f7047bcf
...
...
@@ -21,6 +21,7 @@
"smoke:mac:workspace-service"
:
"node build/scripts/mac-workspace-service-smoke.mjs"
,
"smoke:mac:workspace-startup"
:
"node build/scripts/mac-workspace-startup-smoke.mjs"
,
"smoke:workspace-agent-runner"
:
"node build/scripts/workspace-agent-runner-smoke.mjs"
,
"smoke:workspace-entry-lobster-env"
:
"node build/scripts/workspace-entry-lobster-env-smoke.mjs"
,
"smoke:bundled-runtime"
:
"powershell -ExecutionPolicy Bypass -File build/scripts/bundled-runtime-smoke.ps1"
,
"smoke:workspace-entry"
:
"powershell -ExecutionPolicy Bypass -File build/scripts/workspace-entry-smoke.ps1"
,
"smoke:cloud-bundle"
:
"powershell -ExecutionPolicy Bypass -File build/scripts/cloud-bundle-smoke.ps1"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment